summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock4
-rw-r--r--RELEASES.md7
-rw-r--r--compiler/rustc_ast/src/mut_visit.rs8
-rw-r--r--compiler/rustc_ast/src/visit.rs34
-rw-r--r--compiler/rustc_ast_lowering/src/lib.rs108
-rw-r--r--compiler/rustc_ast_passes/src/lib.rs1
-rw-r--r--compiler/rustc_ast_passes/src/node_count.rs129
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs2
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs44
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/mod.rs8
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/move_errors.rs2
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs4
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/region_errors.rs6
-rw-r--r--compiler/rustc_borrowck/src/lib.rs21
-rw-r--r--compiler/rustc_borrowck/src/nll.rs46
-rw-r--r--compiler/rustc_borrowck/src/polonius/mod.rs15
-rw-r--r--compiler/rustc_borrowck/src/region_infer/dump_mir.rs3
-rw-r--r--compiler/rustc_borrowck/src/region_infer/mod.rs82
-rw-r--r--compiler/rustc_borrowck/src/region_infer/opaque_types.rs6
-rw-r--r--compiler/rustc_borrowck/src/region_infer/reverse_sccs.rs2
-rw-r--r--compiler/rustc_borrowck/src/region_infer/values.rs5
-rw-r--r--compiler/rustc_borrowck/src/type_check/canonical.rs12
-rw-r--r--compiler/rustc_borrowck/src/type_check/constraint_conversion.rs4
-rw-r--r--compiler/rustc_borrowck/src/type_check/free_region_relations.rs39
-rw-r--r--compiler/rustc_borrowck/src/type_check/input_output.rs9
-rw-r--r--compiler/rustc_borrowck/src/type_check/liveness/mod.rs6
-rw-r--r--compiler/rustc_borrowck/src/type_check/liveness/trace.rs7
-rw-r--r--compiler/rustc_borrowck/src/type_check/mod.rs56
-rw-r--r--compiler/rustc_borrowck/src/type_check/relate_tys.rs2
-rw-r--r--compiler/rustc_borrowck/src/universal_regions.rs15
-rw-r--r--compiler/rustc_codegen_cranelift/scripts/setup_rust_fork.sh5
-rw-r--r--compiler/rustc_codegen_cranelift/src/abi/mod.rs2
-rw-r--r--compiler/rustc_codegen_cranelift/src/base.rs10
-rw-r--r--compiler/rustc_codegen_cranelift/src/common.rs18
-rw-r--r--compiler/rustc_codegen_cranelift/src/constant.rs11
-rw-r--r--compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs8
-rw-r--r--compiler/rustc_codegen_cranelift/src/inline_asm.rs10
-rw-r--r--compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs9
-rw-r--r--compiler/rustc_codegen_cranelift/src/lib.rs2
-rw-r--r--compiler/rustc_codegen_cranelift/src/main_shim.rs6
-rw-r--r--compiler/rustc_codegen_cranelift/src/unsize.rs3
-rw-r--r--compiler/rustc_codegen_cranelift/src/value_and_place.rs18
-rw-r--r--compiler/rustc_codegen_gcc/src/builder.rs10
-rw-r--r--compiler/rustc_codegen_gcc/src/consts.rs2
-rw-r--r--compiler/rustc_codegen_gcc/src/context.rs16
-rw-r--r--compiler/rustc_codegen_gcc/src/debuginfo.rs18
-rw-r--r--compiler/rustc_codegen_gcc/src/int.rs7
-rw-r--r--compiler/rustc_codegen_gcc/src/intrinsic/mod.rs6
-rw-r--r--compiler/rustc_codegen_gcc/src/intrinsic/simd.rs10
-rw-r--r--compiler/rustc_codegen_gcc/src/mono_item.rs9
-rw-r--r--compiler/rustc_codegen_llvm/src/builder.rs10
-rw-r--r--compiler/rustc_codegen_llvm/src/callee.rs9
-rw-r--r--compiler/rustc_codegen_llvm/src/consts.rs6
-rw-r--r--compiler/rustc_codegen_llvm/src/context.rs10
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs65
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs19
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs26
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/mod.rs15
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/utils.rs4
-rw-r--r--compiler/rustc_codegen_llvm/src/intrinsic.rs13
-rw-r--r--compiler/rustc_codegen_llvm/src/mono_item.rs9
-rw-r--r--compiler/rustc_codegen_ssa/src/back/symbol_export.rs6
-rw-r--r--compiler/rustc_codegen_ssa/src/base.rs13
-rw-r--r--compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs31
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/block.rs14
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/constant.rs6
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/debuginfo.rs6
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/intrinsic.rs4
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/mod.rs4
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/rvalue.rs6
-rw-r--r--compiler/rustc_codegen_ssa/src/traits/type_.rs16
-rw-r--r--compiler/rustc_const_eval/src/check_consts/check.rs11
-rw-r--r--compiler/rustc_const_eval/src/check_consts/mod.rs8
-rw-r--r--compiler/rustc_const_eval/src/check_consts/ops.rs8
-rw-r--r--compiler/rustc_const_eval/src/check_consts/post_drop_elaboration.rs8
-rw-r--r--compiler/rustc_const_eval/src/check_consts/qualifs.rs24
-rw-r--r--compiler/rustc_const_eval/src/check_consts/resolver.rs5
-rw-r--r--compiler/rustc_const_eval/src/const_eval/error.rs9
-rw-r--r--compiler/rustc_const_eval/src/const_eval/eval_queries.rs6
-rw-r--r--compiler/rustc_const_eval/src/const_eval/machine.rs3
-rw-r--r--compiler/rustc_const_eval/src/const_eval/valtrees.rs11
-rw-r--r--compiler/rustc_const_eval/src/interpret/call.rs58
-rw-r--r--compiler/rustc_const_eval/src/interpret/cast.rs4
-rw-r--r--compiler/rustc_const_eval/src/interpret/eval_context.rs55
-rw-r--r--compiler/rustc_const_eval/src/interpret/intrinsics.rs9
-rw-r--r--compiler/rustc_const_eval/src/interpret/memory.rs2
-rw-r--r--compiler/rustc_const_eval/src/interpret/operand.rs21
-rw-r--r--compiler/rustc_const_eval/src/interpret/operator.rs2
-rw-r--r--compiler/rustc_const_eval/src/interpret/place.rs12
-rw-r--r--compiler/rustc_const_eval/src/interpret/stack.rs15
-rw-r--r--compiler/rustc_const_eval/src/interpret/step.rs3
-rw-r--r--compiler/rustc_const_eval/src/interpret/validity.rs6
-rw-r--r--compiler/rustc_const_eval/src/lib.rs2
-rw-r--r--compiler/rustc_const_eval/src/util/alignment.rs6
-rw-r--r--compiler/rustc_const_eval/src/util/check_validity_requirement.rs10
-rw-r--r--compiler/rustc_const_eval/src/util/compare_types.rs13
-rw-r--r--compiler/rustc_data_structures/src/lib.rs2
-rw-r--r--compiler/rustc_data_structures/src/vec_cache.rs324
-rw-r--r--compiler/rustc_data_structures/src/vec_cache/tests.rs95
-rw-r--r--compiler/rustc_feature/src/builtin_attrs.rs5
-rw-r--r--compiler/rustc_feature/src/unstable.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/check/check.rs22
-rw-r--r--compiler/rustc_hir_analysis/src/check/wfcheck.rs5
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/builtin.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/collect.rs23
-rw-r--r--compiler/rustc_hir_analysis/src/collect/predicates_of.rs5
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs8
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs10
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs19
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs167
-rw-r--r--compiler/rustc_hir_analysis/src/lib.rs15
-rw-r--r--compiler/rustc_hir_typeck/src/expr.rs6
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs9
-rw-r--r--compiler/rustc_hir_typeck/src/intrinsicck.rs4
-rw-r--r--compiler/rustc_hir_typeck/src/upvar.rs15
-rw-r--r--compiler/rustc_hir_typeck/src/writeback.rs4
-rw-r--r--compiler/rustc_infer/src/infer/mod.rs46
-rw-r--r--compiler/rustc_interface/src/passes.rs29
-rw-r--r--compiler/rustc_interface/src/tests.rs1
-rw-r--r--compiler/rustc_lexer/src/lib.rs106
-rw-r--r--compiler/rustc_lint/src/builtin.rs6
-rw-r--r--compiler/rustc_lint/src/context.rs14
-rw-r--r--compiler/rustc_lint/src/dangling.rs27
-rw-r--r--compiler/rustc_lint/src/for_loops_over_fallibles.rs4
-rw-r--r--compiler/rustc_lint/src/foreign_modules.rs30
-rw-r--r--compiler/rustc_lint/src/if_let_rescope.rs2
-rw-r--r--compiler/rustc_lint/src/internal.rs5
-rw-r--r--compiler/rustc_lint/src/let_underscore.rs2
-rw-r--r--compiler/rustc_lint/src/levels.rs22
-rw-r--r--compiler/rustc_lint/src/non_fmt_panic.rs16
-rw-r--r--compiler/rustc_lint/src/noop_method_call.rs4
-rw-r--r--compiler/rustc_lint/src/tail_expr_drop_order.rs11
-rw-r--r--compiler/rustc_lint/src/types.rs45
-rw-r--r--compiler/rustc_lint/src/unused.rs4
-rw-r--r--compiler/rustc_lint_defs/src/builtin.rs1
-rw-r--r--compiler/rustc_lint_defs/src/lib.rs14
-rw-r--r--compiler/rustc_metadata/src/native_libs.rs4
-rw-r--r--compiler/rustc_middle/src/lint.rs7
-rw-r--r--compiler/rustc_middle/src/mir/consts.rs61
-rw-r--r--compiler/rustc_middle/src/mir/interpret/error.rs15
-rw-r--r--compiler/rustc_middle/src/mir/interpret/mod.rs8
-rw-r--r--compiler/rustc_middle/src/mir/interpret/queries.rs17
-rw-r--r--compiler/rustc_middle/src/mir/mod.rs27
-rw-r--r--compiler/rustc_middle/src/mir/statement.rs4
-rw-r--r--compiler/rustc_middle/src/mir/syntax.rs9
-rw-r--r--compiler/rustc_middle/src/query/keys.rs21
-rw-r--r--compiler/rustc_middle/src/query/mod.rs26
-rw-r--r--compiler/rustc_middle/src/thir.rs29
-rw-r--r--compiler/rustc_middle/src/ty/adt.rs5
-rw-r--r--compiler/rustc_middle/src/ty/consts.rs131
-rw-r--r--compiler/rustc_middle/src/ty/context.rs18
-rw-r--r--compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs37
-rw-r--r--compiler/rustc_middle/src/ty/inhabitedness/mod.rs8
-rw-r--r--compiler/rustc_middle/src/ty/instance.rs41
-rw-r--r--compiler/rustc_middle/src/ty/layout.rs115
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs104
-rw-r--r--compiler/rustc_middle/src/ty/normalize_erasing_regions.rs49
-rw-r--r--compiler/rustc_middle/src/ty/util.rs58
-rw-r--r--compiler/rustc_middle/src/ty/vtable.rs4
-rw-r--r--compiler/rustc_middle/src/util/call_kind.rs8
-rw-r--r--compiler/rustc_mir_build/src/build/custom/mod.rs6
-rw-r--r--compiler/rustc_mir_build/src/build/custom/parse/instruction.rs4
-rw-r--r--compiler/rustc_mir_build/src/build/expr/as_constant.rs3
-rw-r--r--compiler/rustc_mir_build/src/build/expr/as_operand.rs2
-rw-r--r--compiler/rustc_mir_build/src/build/expr/as_rvalue.rs20
-rw-r--r--compiler/rustc_mir_build/src/build/expr/into.rs6
-rw-r--r--compiler/rustc_mir_build/src/build/expr/stmt.rs2
-rw-r--r--compiler/rustc_mir_build/src/build/matches/match_pair.rs2
-rw-r--r--compiler/rustc_mir_build/src/build/matches/test.rs17
-rw-r--r--compiler/rustc_mir_build/src/build/misc.rs2
-rw-r--r--compiler/rustc_mir_build/src/build/mod.rs4
-rw-r--r--compiler/rustc_mir_build/src/build/scope.rs2
-rw-r--r--compiler/rustc_mir_build/src/check_unsafety.rs4
-rw-r--r--compiler/rustc_mir_build/src/errors.rs2
-rw-r--r--compiler/rustc_mir_build/src/lints.rs13
-rw-r--r--compiler/rustc_mir_build/src/thir/constant.rs5
-rw-r--r--compiler/rustc_mir_build/src/thir/cx/expr.rs7
-rw-r--r--compiler/rustc_mir_build/src/thir/cx/mod.rs12
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/check_match.rs6
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs15
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/mod.rs2
-rw-r--r--compiler/rustc_mir_dataflow/src/elaborate_drops.rs13
-rw-r--r--compiler/rustc_mir_dataflow/src/value_analysis.rs16
-rw-r--r--compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs10
-rw-r--r--compiler/rustc_mir_transform/src/check_packed_ref.rs9
-rw-r--r--compiler/rustc_mir_transform/src/coroutine.rs12
-rw-r--r--compiler/rustc_mir_transform/src/cost_checker.rs10
-rw-r--r--compiler/rustc_mir_transform/src/dataflow_const_prop.rs43
-rw-r--r--compiler/rustc_mir_transform/src/deduce_param_attrs.rs6
-rw-r--r--compiler/rustc_mir_transform/src/elaborate_drops.rs22
-rw-r--r--compiler/rustc_mir_transform/src/gvn.rs13
-rw-r--r--compiler/rustc_mir_transform/src/inline.rs55
-rw-r--r--compiler/rustc_mir_transform/src/inline/cycle.rs15
-rw-r--r--compiler/rustc_mir_transform/src/instsimplify.rs12
-rw-r--r--compiler/rustc_mir_transform/src/jump_threading.rs14
-rw-r--r--compiler/rustc_mir_transform/src/known_panics_lint.rs31
-rw-r--r--compiler/rustc_mir_transform/src/large_enums.rs11
-rw-r--r--compiler/rustc_mir_transform/src/lib.rs18
-rw-r--r--compiler/rustc_mir_transform/src/match_branches.rs56
-rw-r--r--compiler/rustc_mir_transform/src/promote_consts.rs6
-rw-r--r--compiler/rustc_mir_transform/src/remove_uninit_drops.rs22
-rw-r--r--compiler/rustc_mir_transform/src/remove_unneeded_drops.rs10
-rw-r--r--compiler/rustc_mir_transform/src/remove_zsts.rs8
-rw-r--r--compiler/rustc_mir_transform/src/reveal_all.rs12
-rw-r--r--compiler/rustc_mir_transform/src/shim.rs14
-rw-r--r--compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs8
-rw-r--r--compiler/rustc_mir_transform/src/simplify_branches.rs8
-rw-r--r--compiler/rustc_mir_transform/src/simplify_comparison_integral.rs4
-rw-r--r--compiler/rustc_mir_transform/src/sroa.rs14
-rw-r--r--compiler/rustc_mir_transform/src/unreachable_enum_branching.rs4
-rw-r--r--compiler/rustc_mir_transform/src/validate.rs54
-rw-r--r--compiler/rustc_monomorphize/src/collector.rs49
-rw-r--r--compiler/rustc_monomorphize/src/lib.rs4
-rw-r--r--compiler/rustc_monomorphize/src/mono_checks/abi_check.rs17
-rw-r--r--compiler/rustc_monomorphize/src/mono_checks/move_check.rs6
-rw-r--r--compiler/rustc_monomorphize/src/partitioning.rs2
-rw-r--r--compiler/rustc_monomorphize/src/util.rs10
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/trait_goals.rs6
-rw-r--r--compiler/rustc_parse/src/lexer/mod.rs5
-rw-r--r--compiler/rustc_parse/src/parser/mod.rs3
-rw-r--r--compiler/rustc_passes/src/abi_test.rs36
-rw-r--r--compiler/rustc_passes/src/check_attr.rs3
-rw-r--r--compiler/rustc_passes/src/dead.rs11
-rw-r--r--compiler/rustc_passes/src/input_stats.rs (renamed from compiler/rustc_passes/src/hir_stats.rs)9
-rw-r--r--compiler/rustc_passes/src/layout_test.rs37
-rw-r--r--compiler/rustc_passes/src/lib.rs2
-rw-r--r--compiler/rustc_passes/src/liveness.rs2
-rw-r--r--compiler/rustc_pattern_analysis/src/rustc.rs36
-rw-r--r--compiler/rustc_query_system/src/lib.rs1
-rw-r--r--compiler/rustc_query_system/src/query/caches.rs94
-rw-r--r--compiler/rustc_resolve/src/diagnostics.rs12
-rw-r--r--compiler/rustc_resolve/src/ident.rs112
-rw-r--r--compiler/rustc_resolve/src/late.rs2
-rw-r--r--compiler/rustc_resolve/src/lib.rs17
-rw-r--r--compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs4
-rw-r--r--compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/mod.rs4
-rw-r--r--compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs18
-rw-r--r--compiler/rustc_session/src/options.rs4
-rw-r--r--compiler/rustc_smir/src/rustc_smir/alloc.rs8
-rw-r--r--compiler/rustc_smir/src/rustc_smir/builder.rs4
-rw-r--r--compiler/rustc_smir/src/rustc_smir/context.rs48
-rw-r--r--compiler/rustc_span/src/symbol.rs4
-rw-r--r--compiler/rustc_symbol_mangling/src/v0.rs9
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs2
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs6
-rw-r--r--compiler/rustc_trait_selection/src/traits/mod.rs5
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs23
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs14
-rw-r--r--compiler/rustc_trait_selection/src/traits/vtable.rs8
-rw-r--r--compiler/rustc_traits/src/codegen.rs9
-rw-r--r--compiler/rustc_traits/src/dropck_outlives.rs6
-rw-r--r--compiler/rustc_traits/src/normalize_erasing_regions.rs8
-rw-r--r--compiler/rustc_transmute/src/maybe_transmutable/mod.rs4
-rw-r--r--compiler/rustc_ty_utils/src/abi.rs38
-rw-r--r--compiler/rustc_ty_utils/src/instance.rs30
-rw-r--r--compiler/rustc_ty_utils/src/layout.rs44
-rw-r--r--compiler/rustc_ty_utils/src/layout/invariant.rs2
-rw-r--r--compiler/rustc_ty_utils/src/needs_drop.rs46
-rw-r--r--compiler/rustc_type_ir/src/infer_ctxt.rs2
-rw-r--r--compiler/rustc_type_ir/src/interner.rs9
-rw-r--r--library/alloc/src/boxed.rs2
-rw-r--r--library/alloc/src/collections/btree/map.rs46
-rw-r--r--library/alloc/src/collections/vec_deque/iter.rs34
-rw-r--r--library/alloc/src/collections/vec_deque/iter_mut.rs107
-rw-r--r--library/alloc/src/lib.rs1
-rw-r--r--library/alloc/src/vec/mod.rs2
-rw-r--r--library/core/src/cell.rs5
-rw-r--r--library/core/src/ffi/c_str.rs1
-rw-r--r--library/core/src/mem/maybe_uninit.rs2
-rw-r--r--library/core/src/panic.rs2
-rw-r--r--library/core/src/slice/mod.rs2
-rw-r--r--library/core/src/str/mod.rs2
-rw-r--r--library/std/src/collections/hash/map.rs40
-rw-r--r--library/std/src/fs.rs4
-rw-r--r--library/std/src/sync/rwlock/tests.rs3
-rw-r--r--library/std/src/thread/mod.rs34
-rw-r--r--library/std/src/thread/spawnhook.rs148
m---------library/stdarch0
-rw-r--r--library/test/src/lib.rs11
-rw-r--r--src/bootstrap/src/core/config/config.rs4
-rw-r--r--src/bootstrap/src/utils/change_tracker.rs5
-rw-r--r--src/ci/github-actions/jobs.yml2
m---------src/doc/edition-guide0
m---------src/doc/nomicon0
m---------src/doc/reference0
m---------src/doc/rustc-dev-guide0
-rw-r--r--src/doc/rustc/src/SUMMARY.md2
-rw-r--r--src/doc/rustc/src/platform-support.md4
-rw-r--r--src/doc/rustc/src/platform-support/s390x-unknown-linux-gnu.md113
-rw-r--r--src/doc/rustc/src/platform-support/s390x-unknown-linux-musl.md83
-rw-r--r--src/doc/rustc/src/platform-support/wasm32-wasip2.md2
-rw-r--r--src/doc/rustdoc/src/command-line-arguments.md29
-rw-r--r--src/doc/rustdoc/src/unstable-features.md33
-rw-r--r--src/librustdoc/clean/mod.rs21
-rw-r--r--src/librustdoc/clean/types.rs6
-rw-r--r--src/librustdoc/clean/utils.rs5
-rw-r--r--src/librustdoc/core.rs9
-rw-r--r--src/librustdoc/html/highlight.rs7
-rw-r--r--src/librustdoc/html/render/span_map.rs23
-rw-r--r--src/librustdoc/html/render/type_layout.rs6
-rw-r--r--src/librustdoc/html/static/js/search.js65
-rw-r--r--src/tools/clippy/clippy_lints/src/assigning_clones.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/bool_assert_comparison.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/dereference.rs9
-rw-r--r--src/tools/clippy/clippy_lints/src/drop_forget_ref.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/iter_not_returning_iterator.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/iter_without_into_iter.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/large_const_arrays.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/large_futures.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/large_stack_frames.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs12
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/needless_collect.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/unnecessary_min_or_max.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/zst_offset.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/non_copy_const.rs18
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/const_comparisons.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/erasing_op.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/float_cmp.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/redundant_slicing.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/returns.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/significant_drop_tightening.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/trailing_empty_array.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/eager_transmute.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/utils.rs9
-rw-r--r--src/tools/clippy/clippy_lints/src/uninhabited_references.rs4
-rw-r--r--src/tools/clippy/clippy_utils/src/consts.rs12
-rw-r--r--src/tools/clippy/clippy_utils/src/eager_or_lazy.rs2
-rw-r--r--src/tools/clippy/clippy_utils/src/hir_utils.rs6
-rw-r--r--src/tools/clippy/clippy_utils/src/lib.rs2
-rw-r--r--src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs10
-rw-r--r--src/tools/clippy/clippy_utils/src/ty.rs17
-rw-r--r--src/tools/miri/miri-script/Cargo.lock10
-rw-r--r--src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs2
-rw-r--r--src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs2
-rw-r--r--src/tools/miri/src/eval.rs14
-rw-r--r--src/tools/miri/src/helpers.rs4
-rw-r--r--src/tools/miri/src/machine.rs4
-rw-r--r--src/tools/rust-analyzer/crates/parser/src/lexed_str.rs2
-rw-r--r--tests/crashes/130687.rs4
-rw-r--r--tests/crashes/132985.rs17
-rw-r--r--tests/crashes/auxiliary/aux132985.rs6
-rw-r--r--tests/rustdoc/link-on-path-with-generics.rs14
-rw-r--r--tests/ui/check-cfg/auxiliary/cfg_macro.rs11
-rw-r--r--tests/ui/check-cfg/report-in-external-macros.rs12
-rw-r--r--tests/ui/check-cfg/report-in-external-macros.stderr14
-rw-r--r--tests/ui/const-generics/auxiliary/xcrate-const-ctor-a.rs6
-rw-r--r--tests/ui/const-generics/using-static-as-const-arg.rs7
-rw-r--r--tests/ui/const-generics/xcrate-const-ctor-b.rs15
-rw-r--r--tests/ui/consts/promoted_running_out_of_memory_issue-130687.rs12
-rw-r--r--tests/ui/consts/promoted_running_out_of_memory_issue-130687.stderr15
-rw-r--r--tests/ui/debuginfo/debuginfo-inline-callsite-location-macro-1.rs4124
-rw-r--r--tests/ui/debuginfo/debuginfo-inline-callsite-location-macro-2.rs4122
-rw-r--r--tests/ui/diagnostic_namespace/deny_malformed_attribute.rs2
-rw-r--r--tests/ui/diagnostic_namespace/deny_malformed_attribute.stderr4
-rw-r--r--tests/ui/diagnostic_namespace/malformed_foreign_on_unimplemented.rs1
-rw-r--r--tests/ui/diagnostic_namespace/malformed_foreign_on_unimplemented.stderr36
-rw-r--r--tests/ui/diagnostic_namespace/non_existing_attributes_accepted.rs1
-rw-r--r--tests/ui/diagnostic_namespace/non_existing_attributes_accepted.stderr4
-rw-r--r--tests/ui/diagnostic_namespace/on_unimplemented/broken_format.rs1
-rw-r--r--tests/ui/diagnostic_namespace/on_unimplemented/broken_format.stderr54
-rw-r--r--tests/ui/diagnostic_namespace/on_unimplemented/custom-on-unimplemented-diagnostic.rs (renamed from tests/ui/traits/custom-on-unimplemented-diagnostic.rs)2
-rw-r--r--tests/ui/diagnostic_namespace/on_unimplemented/custom-on-unimplemented-diagnostic.stderr (renamed from tests/ui/traits/custom-on-unimplemented-diagnostic.stderr)8
-rw-r--r--tests/ui/diagnostic_namespace/on_unimplemented/do_not_accept_options_of_the_internal_rustc_attribute.rs4
-rw-r--r--tests/ui/diagnostic_namespace/on_unimplemented/do_not_accept_options_of_the_internal_rustc_attribute.stderr74
-rw-r--r--tests/ui/diagnostic_namespace/on_unimplemented/do_not_fail_parsing_on_invalid_options_1.rs2
-rw-r--r--tests/ui/diagnostic_namespace/on_unimplemented/do_not_fail_parsing_on_invalid_options_1.stderr54
-rw-r--r--tests/ui/diagnostic_namespace/on_unimplemented/error_is_shown_in_downstream_crates.rs1
-rw-r--r--tests/ui/diagnostic_namespace/on_unimplemented/error_is_shown_in_downstream_crates.stderr4
-rw-r--r--tests/ui/diagnostic_namespace/on_unimplemented/ignore_unsupported_options_and_continue_to_use_fallback.rs2
-rw-r--r--tests/ui/diagnostic_namespace/on_unimplemented/ignore_unsupported_options_and_continue_to_use_fallback.stderr14
-rw-r--r--tests/ui/diagnostic_namespace/on_unimplemented/multiple_notes.rs1
-rw-r--r--tests/ui/diagnostic_namespace/on_unimplemented/multiple_notes.stderr12
-rw-r--r--tests/ui/diagnostic_namespace/on_unimplemented/on_unimplemented_simple.rs2
-rw-r--r--tests/ui/diagnostic_namespace/on_unimplemented/on_unimplemented_simple.stderr6
-rw-r--r--tests/ui/diagnostic_namespace/on_unimplemented/report_warning_on_duplicated_options.rs1
-rw-r--r--tests/ui/diagnostic_namespace/on_unimplemented/report_warning_on_duplicated_options.stderr14
-rw-r--r--tests/ui/diagnostic_namespace/suggest_typos.rs1
-rw-r--r--tests/ui/diagnostic_namespace/suggest_typos.stderr8
-rw-r--r--tests/ui/feature-gates/feature-gate-min-generic-const-args.rs11
-rw-r--r--tests/ui/feature-gates/feature-gate-min-generic-const-args.stderr11
-rw-r--r--tests/ui/lint/dangling-pointers-from-temporaries/types.rs7
-rw-r--r--tests/ui/lint/dangling-pointers-from-temporaries/types.stderr54
-rw-r--r--tests/ui/stats/input-stats.rs (renamed from tests/ui/stats/hir-stats.rs)6
-rw-r--r--tests/ui/stats/input-stats.stderr (renamed from tests/ui/stats/hir-stats.stderr)6
-rw-r--r--tests/ui/traits/negative-bounds/on-unimplemented.rs2
-rw-r--r--tests/ui/traits/negative-bounds/on-unimplemented.stderr2
-rw-r--r--triagebot.toml2
391 files changed, 12306 insertions, 2464 deletions
diff --git a/Cargo.lock b/Cargo.lock
index e5025a1ba4f..c8d26559728 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -111,9 +111,9 @@ dependencies = [
 
 [[package]]
 name = "anstream"
-version = "0.6.17"
+version = "0.6.18"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "23a1e53f0f5d86382dafe1cf314783b2044280f406e7e1506368220ad11b1338"
+checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b"
 dependencies = [
  "anstyle",
  "anstyle-parse",
diff --git a/RELEASES.md b/RELEASES.md
index 40ddba6dbc5..54465621b73 100644
--- a/RELEASES.md
+++ b/RELEASES.md
@@ -670,13 +670,6 @@ Cargo
 - [Support `target.<triple>.rustdocflags` officially](https://github.com/rust-lang/cargo/pull/13197/)
 - [Stabilize global cache data tracking](https://github.com/rust-lang/cargo/pull/13492/)
 
-<a id="1.78.0-Misc"></a>
-
-Misc
-----
-
-- [rustdoc: add `--test-builder-wrapper` arg to support wrappers such as RUSTC_WRAPPER when building doctests](https://github.com/rust-lang/rust/pull/114651/)
-
 <a id="1.78.0-Compatibility-Notes"></a>
 
 Compatibility Notes
diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs
index a09aa9ee665..811cb0be9f9 100644
--- a/compiler/rustc_ast/src/mut_visit.rs
+++ b/compiler/rustc_ast/src/mut_visit.rs
@@ -330,6 +330,10 @@ pub trait MutVisitor: Sized {
     fn visit_capture_by(&mut self, capture_by: &mut CaptureBy) {
         walk_capture_by(self, capture_by)
     }
+
+    fn visit_fn_ret_ty(&mut self, fn_ret_ty: &mut FnRetTy) {
+        walk_fn_ret_ty(self, fn_ret_ty)
+    }
 }
 
 /// Use a map-style function (`FnOnce(T) -> T`) to overwrite a `&mut T`. Useful
@@ -609,7 +613,7 @@ fn walk_angle_bracketed_parameter_data<T: MutVisitor>(vis: &mut T, data: &mut An
 fn walk_parenthesized_parameter_data<T: MutVisitor>(vis: &mut T, args: &mut ParenthesizedArgs) {
     let ParenthesizedArgs { inputs, output, span, inputs_span } = args;
     visit_thin_vec(inputs, |input| vis.visit_ty(input));
-    walk_fn_ret_ty(vis, output);
+    vis.visit_fn_ret_ty(output);
     vis.visit_span(span);
     vis.visit_span(inputs_span);
 }
@@ -911,7 +915,7 @@ fn walk_fn<T: MutVisitor>(vis: &mut T, kind: FnKind<'_>) {
 fn walk_fn_decl<T: MutVisitor>(vis: &mut T, decl: &mut P<FnDecl>) {
     let FnDecl { inputs, output } = decl.deref_mut();
     inputs.flat_map_in_place(|param| vis.flat_map_param(param));
-    walk_fn_ret_ty(vis, output);
+    vis.visit_fn_ret_ty(output);
 }
 
 fn walk_fn_ret_ty<T: MutVisitor>(vis: &mut T, fn_ret_ty: &mut FnRetTy) {
diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs
index 3500c215376..c121e7711ee 100644
--- a/compiler/rustc_ast/src/visit.rs
+++ b/compiler/rustc_ast/src/visit.rs
@@ -299,6 +299,12 @@ pub trait Visitor<'ast>: Sized {
     fn visit_coroutine_kind(&mut self, _coroutine_kind: &'ast CoroutineKind) -> Self::Result {
         Self::Result::output()
     }
+    fn visit_fn_decl(&mut self, fn_decl: &'ast FnDecl) -> Self::Result {
+        walk_fn_decl(self, fn_decl)
+    }
+    fn visit_qself(&mut self, qs: &'ast Option<P<QSelf>>) -> Self::Result {
+        walk_qself(self, qs)
+    }
 }
 
 pub fn walk_crate<'a, V: Visitor<'a>>(visitor: &mut V, krate: &'a Crate) -> V::Result {
@@ -434,13 +440,13 @@ impl WalkItemKind for ItemKind {
                 body,
                 from_glob: _,
             }) => {
-                try_visit!(walk_qself(visitor, qself));
+                try_visit!(visitor.visit_qself(qself));
                 try_visit!(visitor.visit_path(path, *id));
                 visit_opt!(visitor, visit_ident, rename);
                 visit_opt!(visitor, visit_block, body);
             }
             ItemKind::DelegationMac(box DelegationMac { qself, prefix, suffixes, body }) => {
-                try_visit!(walk_qself(visitor, qself));
+                try_visit!(visitor.visit_qself(qself));
                 try_visit!(visitor.visit_path(prefix, id));
                 if let Some(suffixes) = suffixes {
                     for (ident, rename) in suffixes {
@@ -518,10 +524,10 @@ pub fn walk_ty<'a, V: Visitor<'a>>(visitor: &mut V, typ: &'a Ty) -> V::Result {
             let BareFnTy { safety: _, ext: _, generic_params, decl, decl_span: _ } =
                 &**function_declaration;
             walk_list!(visitor, visit_generic_param, generic_params);
-            try_visit!(walk_fn_decl(visitor, decl));
+            try_visit!(visitor.visit_fn_decl(decl));
         }
         TyKind::Path(maybe_qself, path) => {
-            try_visit!(walk_qself(visitor, maybe_qself));
+            try_visit!(visitor.visit_qself(maybe_qself));
             try_visit!(visitor.visit_path(path, *id));
         }
         TyKind::Pat(ty, pat) => {
@@ -652,16 +658,16 @@ pub fn walk_pat<'a, V: Visitor<'a>>(visitor: &mut V, pattern: &'a Pat) -> V::Res
     let Pat { id, kind, span: _, tokens: _ } = pattern;
     match kind {
         PatKind::TupleStruct(opt_qself, path, elems) => {
-            try_visit!(walk_qself(visitor, opt_qself));
+            try_visit!(visitor.visit_qself(opt_qself));
             try_visit!(visitor.visit_path(path, *id));
             walk_list!(visitor, visit_pat, elems);
         }
         PatKind::Path(opt_qself, path) => {
-            try_visit!(walk_qself(visitor, opt_qself));
+            try_visit!(visitor.visit_qself(opt_qself));
             try_visit!(visitor.visit_path(path, *id))
         }
         PatKind::Struct(opt_qself, path, fields, _rest) => {
-            try_visit!(walk_qself(visitor, opt_qself));
+            try_visit!(visitor.visit_qself(opt_qself));
             try_visit!(visitor.visit_path(path, *id));
             walk_list!(visitor, visit_pat_field, fields);
         }
@@ -846,13 +852,13 @@ pub fn walk_fn<'a, V: Visitor<'a>>(visitor: &mut V, kind: FnKind<'a>) -> V::Resu
             // Identifier and visibility are visited as a part of the item.
             try_visit!(visitor.visit_fn_header(header));
             try_visit!(visitor.visit_generics(generics));
-            try_visit!(walk_fn_decl(visitor, decl));
+            try_visit!(visitor.visit_fn_decl(decl));
             visit_opt!(visitor, visit_block, body);
         }
         FnKind::Closure(binder, coroutine_kind, decl, body) => {
             try_visit!(visitor.visit_closure_binder(binder));
             visit_opt!(visitor, visit_coroutine_kind, coroutine_kind.as_ref());
-            try_visit!(walk_fn_decl(visitor, decl));
+            try_visit!(visitor.visit_fn_decl(decl));
             try_visit!(visitor.visit_expr(body));
         }
     }
@@ -902,13 +908,13 @@ impl WalkItemKind for AssocItemKind {
                 body,
                 from_glob: _,
             }) => {
-                try_visit!(walk_qself(visitor, qself));
+                try_visit!(visitor.visit_qself(qself));
                 try_visit!(visitor.visit_path(path, *id));
                 visit_opt!(visitor, visit_ident, rename);
                 visit_opt!(visitor, visit_block, body);
             }
             AssocItemKind::DelegationMac(box DelegationMac { qself, prefix, suffixes, body }) => {
-                try_visit!(walk_qself(visitor, qself));
+                try_visit!(visitor.visit_qself(qself));
                 try_visit!(visitor.visit_path(prefix, id));
                 if let Some(suffixes) = suffixes {
                     for (ident, rename) in suffixes {
@@ -1023,7 +1029,7 @@ pub fn walk_inline_asm_sym<'a, V: Visitor<'a>>(
     visitor: &mut V,
     InlineAsmSym { id, qself, path }: &'a InlineAsmSym,
 ) -> V::Result {
-    try_visit!(walk_qself(visitor, qself));
+    try_visit!(visitor.visit_qself(qself));
     visitor.visit_path(path, *id)
 }
 
@@ -1055,7 +1061,7 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) -> V
         }
         ExprKind::Struct(se) => {
             let StructExpr { qself, path, fields, rest } = &**se;
-            try_visit!(walk_qself(visitor, qself));
+            try_visit!(visitor.visit_qself(qself));
             try_visit!(visitor.visit_path(path, *id));
             walk_list!(visitor, visit_expr_field, fields);
             match rest {
@@ -1164,7 +1170,7 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) -> V
         }
         ExprKind::Underscore => {}
         ExprKind::Path(maybe_qself, path) => {
-            try_visit!(walk_qself(visitor, maybe_qself));
+            try_visit!(visitor.visit_qself(maybe_qself));
             try_visit!(visitor.visit_path(path, *id));
         }
         ExprKind::Break(opt_label, opt_expr) => {
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index d53280751fc..0b2969a49ba 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -2052,6 +2052,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         }
     }
 
+    /// Used when lowering a type argument that turned out to actually be a const argument.
+    ///
+    /// Only use for that purpose since otherwise it will create a duplicate def.
     #[instrument(level = "debug", skip(self))]
     fn lower_const_path_to_const_arg(
         &mut self,
@@ -2060,51 +2063,58 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         ty_id: NodeId,
         span: Span,
     ) -> &'hir hir::ConstArg<'hir> {
-        let ct_kind = match res {
-            Res::Def(DefKind::ConstParam, _) => {
-                let qpath = self.lower_qpath(
-                    ty_id,
-                    &None,
-                    path,
-                    ParamMode::Optional,
-                    AllowReturnTypeNotation::No,
-                    ImplTraitContext::Disallowed(ImplTraitPosition::Path),
-                    None,
-                );
-                hir::ConstArgKind::Path(qpath)
-            }
-            _ => {
-                // Construct an AnonConst where the expr is the "ty"'s path.
+        let tcx = self.tcx;
 
-                let parent_def_id = self.current_def_id_parent;
-                let node_id = self.next_node_id();
-                let span = self.lower_span(span);
-
-                // Add a definition for the in-band const def.
-                let def_id =
-                    self.create_def(parent_def_id, node_id, kw::Empty, DefKind::AnonConst, span);
-                let hir_id = self.lower_node_id(node_id);
+        // FIXME(min_generic_const_args): we only allow one-segment const paths for now
+        let ct_kind = if path.is_potential_trivial_const_arg()
+            && (tcx.features().min_generic_const_args()
+                || matches!(res, Res::Def(DefKind::ConstParam, _)))
+        {
+            let qpath = self.lower_qpath(
+                ty_id,
+                &None,
+                path,
+                ParamMode::Optional,
+                AllowReturnTypeNotation::No,
+                // FIXME(min_generic_const_args): update for `fn foo() -> Bar<FOO<impl Trait>>` support
+                ImplTraitContext::Disallowed(ImplTraitPosition::Path),
+                None,
+            );
+            hir::ConstArgKind::Path(qpath)
+        } else {
+            // Construct an AnonConst where the expr is the "ty"'s path.
+
+            let parent_def_id = self.current_def_id_parent;
+            let node_id = self.next_node_id();
+            let span = self.lower_span(span);
+
+            // Add a definition for the in-band const def.
+            // We're lowering a const argument that was originally thought to be a type argument,
+            // so the def collector didn't create the def ahead of time. That's why we have to do
+            // it here.
+            let def_id =
+                self.create_def(parent_def_id, node_id, kw::Empty, DefKind::AnonConst, span);
+            let hir_id = self.lower_node_id(node_id);
+
+            let path_expr = Expr {
+                id: ty_id,
+                kind: ExprKind::Path(None, path.clone()),
+                span,
+                attrs: AttrVec::new(),
+                tokens: None,
+            };
 
-                let path_expr = Expr {
-                    id: ty_id,
-                    kind: ExprKind::Path(None, path.clone()),
+            let ct = self.with_new_scopes(span, |this| {
+                self.arena.alloc(hir::AnonConst {
+                    def_id,
+                    hir_id,
+                    body: this.with_def_id_parent(def_id, |this| {
+                        this.lower_const_body(path_expr.span, Some(&path_expr))
+                    }),
                     span,
-                    attrs: AttrVec::new(),
-                    tokens: None,
-                };
-
-                let ct = self.with_new_scopes(span, |this| {
-                    self.arena.alloc(hir::AnonConst {
-                        def_id,
-                        hir_id,
-                        body: this.with_def_id_parent(def_id, |this| {
-                            this.lower_const_body(path_expr.span, Some(&path_expr))
-                        }),
-                        span,
-                    })
-                });
-                hir::ConstArgKind::Anon(ct)
-            }
+                })
+            });
+            hir::ConstArgKind::Anon(ct)
         };
 
         self.arena.alloc(hir::ConstArg {
@@ -2122,6 +2132,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
 
     #[instrument(level = "debug", skip(self))]
     fn lower_anon_const_to_const_arg_direct(&mut self, anon: &AnonConst) -> hir::ConstArg<'hir> {
+        let tcx = self.tcx;
         // Unwrap a block, so that e.g. `{ P }` is recognised as a parameter. Const arguments
         // currently have to be wrapped in curly brackets, so it's necessary to special-case.
         let expr = if let ExprKind::Block(block, _) = &anon.value.kind
@@ -2135,18 +2146,19 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         };
         let maybe_res =
             self.resolver.get_partial_res(expr.id).and_then(|partial_res| partial_res.full_res());
-        debug!("res={:?}", maybe_res);
-        // FIXME(min_generic_const_args): for now we only lower params to ConstArgKind::Path
-        if let Some(res) = maybe_res
-            && let Res::Def(DefKind::ConstParam, _) = res
-            && let ExprKind::Path(qself, path) = &expr.kind
+        // FIXME(min_generic_const_args): we only allow one-segment const paths for now
+        if let ExprKind::Path(None, path) = &expr.kind
+            && path.is_potential_trivial_const_arg()
+            && (tcx.features().min_generic_const_args()
+                || matches!(maybe_res, Some(Res::Def(DefKind::ConstParam, _))))
         {
             let qpath = self.lower_qpath(
                 expr.id,
-                qself,
+                &None,
                 path,
                 ParamMode::Optional,
                 AllowReturnTypeNotation::No,
+                // FIXME(min_generic_const_args): update for `fn foo() -> Bar<FOO<impl Trait>>` support
                 ImplTraitContext::Disallowed(ImplTraitPosition::Path),
                 None,
             );
diff --git a/compiler/rustc_ast_passes/src/lib.rs b/compiler/rustc_ast_passes/src/lib.rs
index 88c6bde3106..86752da79ae 100644
--- a/compiler/rustc_ast_passes/src/lib.rs
+++ b/compiler/rustc_ast_passes/src/lib.rs
@@ -18,7 +18,6 @@
 pub mod ast_validation;
 mod errors;
 pub mod feature_gate;
-pub mod node_count;
 pub mod show_span;
 
 rustc_fluent_macro::fluent_messages! { "../messages.ftl" }
diff --git a/compiler/rustc_ast_passes/src/node_count.rs b/compiler/rustc_ast_passes/src/node_count.rs
deleted file mode 100644
index 9e7204df8ad..00000000000
--- a/compiler/rustc_ast_passes/src/node_count.rs
+++ /dev/null
@@ -1,129 +0,0 @@
-// Simply gives a rough count of the number of nodes in an AST.
-
-use rustc_ast::visit::*;
-use rustc_ast::*;
-use rustc_span::Span;
-use rustc_span::symbol::Ident;
-
-pub struct NodeCounter {
-    pub count: usize,
-}
-
-impl NodeCounter {
-    pub fn new() -> NodeCounter {
-        NodeCounter { count: 0 }
-    }
-}
-
-impl<'ast> Visitor<'ast> for NodeCounter {
-    fn visit_ident(&mut self, _ident: &Ident) {
-        self.count += 1;
-    }
-    fn visit_foreign_item(&mut self, i: &ForeignItem) {
-        self.count += 1;
-        walk_item(self, i)
-    }
-    fn visit_item(&mut self, i: &Item) {
-        self.count += 1;
-        walk_item(self, i)
-    }
-    fn visit_local(&mut self, l: &Local) {
-        self.count += 1;
-        walk_local(self, l)
-    }
-    fn visit_block(&mut self, b: &Block) {
-        self.count += 1;
-        walk_block(self, b)
-    }
-    fn visit_stmt(&mut self, s: &Stmt) {
-        self.count += 1;
-        walk_stmt(self, s)
-    }
-    fn visit_arm(&mut self, a: &Arm) {
-        self.count += 1;
-        walk_arm(self, a)
-    }
-    fn visit_pat(&mut self, p: &Pat) {
-        self.count += 1;
-        walk_pat(self, p)
-    }
-    fn visit_expr(&mut self, ex: &Expr) {
-        self.count += 1;
-        walk_expr(self, ex)
-    }
-    fn visit_ty(&mut self, t: &Ty) {
-        self.count += 1;
-        walk_ty(self, t)
-    }
-    fn visit_generic_param(&mut self, param: &GenericParam) {
-        self.count += 1;
-        walk_generic_param(self, param)
-    }
-    fn visit_generics(&mut self, g: &Generics) {
-        self.count += 1;
-        walk_generics(self, g)
-    }
-    fn visit_fn(&mut self, fk: visit::FnKind<'_>, _: Span, _: NodeId) {
-        self.count += 1;
-        walk_fn(self, fk)
-    }
-    fn visit_assoc_item(&mut self, ti: &AssocItem, ctxt: AssocCtxt) {
-        self.count += 1;
-        walk_assoc_item(self, ti, ctxt);
-    }
-    fn visit_trait_ref(&mut self, t: &TraitRef) {
-        self.count += 1;
-        walk_trait_ref(self, t)
-    }
-    fn visit_param_bound(&mut self, bounds: &GenericBound, _ctxt: BoundKind) {
-        self.count += 1;
-        walk_param_bound(self, bounds)
-    }
-    fn visit_poly_trait_ref(&mut self, t: &PolyTraitRef) {
-        self.count += 1;
-        walk_poly_trait_ref(self, t)
-    }
-    fn visit_variant_data(&mut self, s: &VariantData) {
-        self.count += 1;
-        walk_struct_def(self, s)
-    }
-    fn visit_field_def(&mut self, s: &FieldDef) {
-        self.count += 1;
-        walk_field_def(self, s)
-    }
-    fn visit_enum_def(&mut self, enum_definition: &EnumDef) {
-        self.count += 1;
-        walk_enum_def(self, enum_definition)
-    }
-    fn visit_variant(&mut self, v: &Variant) {
-        self.count += 1;
-        walk_variant(self, v)
-    }
-    fn visit_lifetime(&mut self, lifetime: &Lifetime, _: visit::LifetimeCtxt) {
-        self.count += 1;
-        walk_lifetime(self, lifetime)
-    }
-    fn visit_mac_call(&mut self, mac: &MacCall) {
-        self.count += 1;
-        walk_mac(self, mac)
-    }
-    fn visit_path(&mut self, path: &Path, _id: NodeId) {
-        self.count += 1;
-        walk_path(self, path)
-    }
-    fn visit_use_tree(&mut self, use_tree: &UseTree, id: NodeId, _nested: bool) {
-        self.count += 1;
-        walk_use_tree(self, use_tree, id)
-    }
-    fn visit_generic_args(&mut self, generic_args: &GenericArgs) {
-        self.count += 1;
-        walk_generic_args(self, generic_args)
-    }
-    fn visit_assoc_item_constraint(&mut self, constraint: &AssocItemConstraint) {
-        self.count += 1;
-        walk_assoc_item_constraint(self, constraint)
-    }
-    fn visit_attribute(&mut self, _attr: &Attribute) {
-        self.count += 1;
-    }
-}
diff --git a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs
index 0897d140d60..90d12ea8328 100644
--- a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs
@@ -60,7 +60,7 @@ impl<'tcx> UniverseInfo<'tcx> {
             UniverseInfo::RelateTys { expected, found } => {
                 let err = mbcx.infcx.err_ctxt().report_mismatched_types(
                     &cause,
-                    mbcx.param_env,
+                    mbcx.infcx.param_env,
                     expected,
                     found,
                     TypeError::RegionsPlaceholderMismatch,
diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index 51c2282422e..c11103af476 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -266,7 +266,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
                 }
             }
 
-            if self.param_env.caller_bounds().iter().any(|c| {
+            if self.infcx.param_env.caller_bounds().iter().any(|c| {
                 c.as_trait_clause().is_some_and(|pred| {
                     pred.skip_binder().self_ty() == ty && self.infcx.tcx.is_fn_trait(pred.def_id())
                 })
@@ -682,9 +682,13 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
                 // Normalize before comparing to see through type aliases and projections.
                 let old_ty = ty::EarlyBinder::bind(ty).instantiate(tcx, generic_args);
                 let new_ty = ty::EarlyBinder::bind(ty).instantiate(tcx, new_args);
-                if let Ok(old_ty) = tcx.try_normalize_erasing_regions(self.param_env, old_ty)
-                    && let Ok(new_ty) = tcx.try_normalize_erasing_regions(self.param_env, new_ty)
-                {
+                if let Ok(old_ty) = tcx.try_normalize_erasing_regions(
+                    self.infcx.typing_env(self.infcx.param_env),
+                    old_ty,
+                ) && let Ok(new_ty) = tcx.try_normalize_erasing_regions(
+                    self.infcx.typing_env(self.infcx.param_env),
+                    new_ty,
+                ) {
                     old_ty == new_ty
                 } else {
                     false
@@ -703,13 +707,16 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
             // Test the callee's predicates, substituting in `ref_ty` for the moved argument type.
             clauses.instantiate(tcx, new_args).predicates.iter().all(|&(mut clause)| {
                 // Normalize before testing to see through type aliases and projections.
-                if let Ok(normalized) = tcx.try_normalize_erasing_regions(self.param_env, clause) {
+                if let Ok(normalized) = tcx.try_normalize_erasing_regions(
+                    self.infcx.typing_env(self.infcx.param_env),
+                    clause,
+                ) {
                     clause = normalized;
                 }
                 self.infcx.predicate_must_hold_modulo_regions(&Obligation::new(
                     tcx,
                     ObligationCause::dummy(),
-                    self.param_env,
+                    self.infcx.param_env,
                     clause,
                 ))
             })
@@ -898,7 +905,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
         let ty = moved_place.ty(self.body, self.infcx.tcx).ty;
         debug!("ty: {:?}, kind: {:?}", ty, ty.kind());
 
-        let Some(assign_value) = self.infcx.err_ctxt().ty_kind_suggestion(self.param_env, ty)
+        let Some(assign_value) = self.infcx.err_ctxt().ty_kind_suggestion(self.infcx.param_env, ty)
         else {
             return;
         };
@@ -1298,7 +1305,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
     pub(crate) fn implements_clone(&self, ty: Ty<'tcx>) -> bool {
         let Some(clone_trait_def) = self.infcx.tcx.lang_items().clone_trait() else { return false };
         self.infcx
-            .type_implements_trait(clone_trait_def, [ty], self.param_env)
+            .type_implements_trait(clone_trait_def, [ty], self.infcx.param_env)
             .must_apply_modulo_regions()
     }
 
@@ -1431,7 +1438,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
         let ocx = ObligationCtxt::new_with_diagnostics(self.infcx);
         let cause = ObligationCause::misc(span, self.mir_def_id());
 
-        ocx.register_bound(cause, self.param_env, ty, def_id);
+        ocx.register_bound(cause, self.infcx.param_env, ty, def_id);
         let errors = ocx.select_all_or_error();
 
         // Only emit suggestion if all required predicates are on generic
@@ -1951,7 +1958,8 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
                 && let ty::Ref(_, inner, _) = rcvr_ty.kind()
                 && let inner = inner.peel_refs()
                 && (Holds { ty: inner }).visit_ty(local_ty).is_break()
-                && let None = self.infcx.type_implements_trait_shallow(clone, inner, self.param_env)
+                && let None =
+                    self.infcx.type_implements_trait_shallow(clone, inner, self.infcx.param_env)
             {
                 err.span_label(
                     span,
@@ -1983,7 +1991,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
             let obligation = Obligation::new(
                 self.infcx.tcx,
                 ObligationCause::dummy(),
-                self.param_env,
+                self.infcx.param_env,
                 trait_ref,
             );
             self.infcx.err_ctxt().suggest_derive(
@@ -3392,7 +3400,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
             if let Some(iter_trait) = tcx.get_diagnostic_item(sym::Iterator)
                 && self
                     .infcx
-                    .type_implements_trait(iter_trait, [return_ty], self.param_env)
+                    .type_implements_trait(iter_trait, [return_ty], self.infcx.param_env)
                     .must_apply_modulo_regions()
             {
                 err.span_suggestion_hidden(
@@ -3831,11 +3839,17 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
             if tcx.is_diagnostic_item(sym::deref_method, method_did) {
                 let deref_target =
                     tcx.get_diagnostic_item(sym::deref_target).and_then(|deref_target| {
-                        Instance::try_resolve(tcx, self.param_env, deref_target, method_args)
-                            .transpose()
+                        Instance::try_resolve(
+                            tcx,
+                            self.infcx.typing_env(self.infcx.param_env),
+                            deref_target,
+                            method_args,
+                        )
+                        .transpose()
                     });
                 if let Some(Ok(instance)) = deref_target {
-                    let deref_target_ty = instance.ty(tcx, self.param_env);
+                    let deref_target_ty =
+                        instance.ty(tcx, self.infcx.typing_env(self.infcx.param_env));
                     err.note(format!("borrow occurs due to deref coercion to `{deref_target_ty}`"));
                     err.span_note(tcx.def_span(instance.def_id()), "deref defined here");
                 }
diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs
index 0797bb49bf9..bda96726738 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mod.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs
@@ -864,7 +864,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
 
             let kind = call_kind(
                 self.infcx.tcx,
-                self.param_env,
+                self.infcx.typing_env(self.infcx.param_env),
                 method_did,
                 method_args,
                 *fn_span,
@@ -1160,7 +1160,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
                         let suggest = match tcx.get_diagnostic_item(sym::IntoIterator) {
                             Some(def_id) => type_known_to_meet_bound_modulo_regions(
                                 self.infcx,
-                                self.param_env,
+                                self.infcx.param_env,
                                 Ty::new_imm_ref(tcx, tcx.lifetimes.re_erased, ty),
                                 def_id,
                             ),
@@ -1224,7 +1224,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
                                 BoundRegionConversionTime::FnCall,
                                 tcx.fn_sig(method_did).instantiate(tcx, method_args).input(0),
                             )
-                            && self.infcx.can_eq(self.param_env, ty, self_ty)
+                            && self.infcx.can_eq(self.infcx.param_env, ty, self_ty)
                         {
                             err.subdiagnostic(CaptureReasonSuggest::FreshReborrow {
                                 span: move_span.shrink_to_hi(),
@@ -1258,7 +1258,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
                             if let Some(errors) = self.infcx.type_implements_trait_shallow(
                                 clone_trait,
                                 ty,
-                                self.param_env,
+                                self.infcx.param_env,
                             ) && !has_sugg
                             {
                                 let msg = match &errors[..] {
diff --git a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs
index 15cc9c20ab7..4ba6b2e94ec 100644
--- a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs
@@ -305,7 +305,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
         let Some(copy_trait_def) = self.infcx.tcx.lang_items().copy_trait() else { return false };
         // This is only going to be ambiguous if there are incoherent impls, because otherwise
         // ambiguity should never happen in MIR.
-        self.infcx.type_implements_trait(copy_trait_def, [ty], self.param_env).may_apply()
+        self.infcx.type_implements_trait(copy_trait_def, [ty], self.infcx.param_env).may_apply()
     }
 
     fn report_cannot_move_from_static(&mut self, place: Place<'tcx>, span: Span) -> Diag<'infcx> {
diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
index d064bf098e4..c5ebf3c547e 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
@@ -1242,7 +1242,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
                             .type_implements_trait_shallow(
                                 clone_trait,
                                 ty.peel_refs(),
-                                self.param_env,
+                                self.infcx.param_env,
                             )
                             .as_deref()
                         {
@@ -1279,7 +1279,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
                                 let obligation = traits::Obligation::new(
                                     self.infcx.tcx,
                                     traits::ObligationCause::dummy(),
-                                    self.param_env,
+                                    self.infcx.param_env,
                                     trait_ref,
                                 );
                                 self.infcx.err_ctxt().suggest_derive(
diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
index 807b5576976..c38747f6675 100644
--- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
@@ -952,7 +952,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
 
             if let Ok(Some(instance)) = ty::Instance::try_resolve(
                 tcx,
-                self.param_env,
+                self.infcx.typing_env(self.infcx.param_env),
                 *fn_did,
                 self.infcx.resolve_vars_if_possible(args),
             ) {
@@ -1091,7 +1091,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
             peeled_ty = ref_ty;
             count += 1;
         }
-        if !self.infcx.type_is_copy_modulo_regions(self.param_env, peeled_ty) {
+        if !self.infcx.type_is_copy_modulo_regions(self.infcx.param_env, peeled_ty) {
             return;
         }
 
@@ -1160,7 +1160,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
         let ocx = ObligationCtxt::new(&self.infcx);
         ocx.register_obligations(preds.iter().map(|(pred, span)| {
             trace!(?pred);
-            Obligation::misc(tcx, span, self.mir_def_id(), self.param_env, pred)
+            Obligation::misc(tcx, span, self.mir_def_id(), self.infcx.param_env, pred)
         }));
 
         if ocx.select_all_or_error().is_empty() && count > 0 {
diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs
index 7eaf265d410..03f7b05d1e3 100644
--- a/compiler/rustc_borrowck/src/lib.rs
+++ b/compiler/rustc_borrowck/src/lib.rs
@@ -140,7 +140,6 @@ fn do_mir_borrowck<'tcx>(
 ) -> (BorrowCheckResult<'tcx>, Option<Box<BodyWithBorrowckFacts<'tcx>>>) {
     let def = input_body.source.def_id().expect_local();
     let infcx = BorrowckInferCtxt::new(tcx, def);
-    let param_env = tcx.param_env(def);
 
     let mut local_names = IndexVec::from_elem(None, &input_body.local_decls);
     for var_debug_info in &input_body.var_debug_info {
@@ -175,8 +174,7 @@ fn do_mir_borrowck<'tcx>(
     // will have a lifetime tied to the inference context.
     let mut body_owned = input_body.clone();
     let mut promoted = input_promoted.to_owned();
-    let free_regions =
-        nll::replace_regions_in_mir(&infcx, param_env, &mut body_owned, &mut promoted);
+    let free_regions = nll::replace_regions_in_mir(&infcx, &mut body_owned, &mut promoted);
     let body = &body_owned; // no further changes
 
     // FIXME(-Znext-solver): A bit dubious that we're only registering
@@ -192,7 +190,7 @@ fn do_mir_borrowck<'tcx>(
         .iter_enumerated()
         .map(|(idx, body)| (idx, MoveData::gather_moves(body, tcx, |_| true)));
 
-    let mut flow_inits = MaybeInitializedPlaces::new(tcx, body, &move_data)
+    let flow_inits = MaybeInitializedPlaces::new(tcx, body, &move_data)
         .iterate_to_fixpoint(tcx, body, Some("borrowck"))
         .into_results_cursor(body);
 
@@ -213,18 +211,12 @@ fn do_mir_borrowck<'tcx>(
         body,
         &promoted,
         &location_table,
-        param_env,
-        &mut flow_inits,
+        flow_inits,
         &move_data,
         &borrow_set,
-        tcx.closure_captures(def),
         consumer_options,
     );
 
-    // `flow_inits` is large, so we drop it as soon as possible. This reduces
-    // peak memory usage significantly on some benchmarks.
-    drop(flow_inits);
-
     // Dump MIR results into a file, if that is enabled. This let us
     // write unit-tests, as well as helping with debugging.
     nll::dump_nll_mir(&infcx, body, &regioncx, &opt_closure_req, &borrow_set);
@@ -251,7 +243,6 @@ fn do_mir_borrowck<'tcx>(
         let promoted_body = &promoted[idx];
         let mut promoted_mbcx = MirBorrowckCtxt {
             infcx: &infcx,
-            param_env,
             body: promoted_body,
             move_data: &move_data,
             location_table: &location_table, // no need to create a real one for the promoted, it is not used
@@ -291,7 +282,6 @@ fn do_mir_borrowck<'tcx>(
 
     let mut mbcx = MirBorrowckCtxt {
         infcx: &infcx,
-        param_env,
         body,
         move_data: &move_data,
         location_table: &location_table,
@@ -448,12 +438,14 @@ fn get_flow_results<'a, 'tcx>(
 pub(crate) struct BorrowckInferCtxt<'tcx> {
     pub(crate) infcx: InferCtxt<'tcx>,
     pub(crate) reg_var_to_origin: RefCell<FxIndexMap<ty::RegionVid, RegionCtxt>>,
+    pub(crate) param_env: ParamEnv<'tcx>,
 }
 
 impl<'tcx> BorrowckInferCtxt<'tcx> {
     pub(crate) fn new(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Self {
         let infcx = tcx.infer_ctxt().build(TypingMode::analysis_in_body(tcx, def_id));
-        BorrowckInferCtxt { infcx, reg_var_to_origin: RefCell::new(Default::default()) }
+        let param_env = tcx.param_env(def_id);
+        BorrowckInferCtxt { infcx, reg_var_to_origin: RefCell::new(Default::default()), param_env }
     }
 
     pub(crate) fn next_region_var<F>(
@@ -532,7 +524,6 @@ impl<'tcx> Deref for BorrowckInferCtxt<'tcx> {
 
 struct MirBorrowckCtxt<'a, 'infcx, 'tcx> {
     infcx: &'infcx BorrowckInferCtxt<'tcx>,
-    param_env: ParamEnv<'tcx>,
     body: &'a Body<'tcx>,
     move_data: &'a MoveData<'tcx>,
 
diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs
index f76603d5679..be02e2f48df 100644
--- a/compiler/rustc_borrowck/src/nll.rs
+++ b/compiler/rustc_borrowck/src/nll.rs
@@ -30,7 +30,7 @@ use crate::diagnostics::RegionErrors;
 use crate::facts::{AllFacts, AllFactsExt, RustcFacts};
 use crate::location::LocationTable;
 use crate::region_infer::RegionInferenceContext;
-use crate::type_check::{self, MirTypeckRegionConstraints, MirTypeckResults};
+use crate::type_check::{self, MirTypeckResults};
 use crate::universal_regions::UniversalRegions;
 use crate::{BorrowckInferCtxt, polonius, renumber};
 
@@ -50,10 +50,9 @@ pub(crate) struct NllOutput<'tcx> {
 /// Rewrites the regions in the MIR to use NLL variables, also scraping out the set of universal
 /// regions (e.g., region parameters) declared on the function. That set will need to be given to
 /// `compute_regions`.
-#[instrument(skip(infcx, param_env, body, promoted), level = "debug")]
+#[instrument(skip(infcx, body, promoted), level = "debug")]
 pub(crate) fn replace_regions_in_mir<'tcx>(
     infcx: &BorrowckInferCtxt<'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
     body: &mut Body<'tcx>,
     promoted: &mut IndexSlice<Promoted, Body<'tcx>>,
 ) -> UniversalRegions<'tcx> {
@@ -62,7 +61,7 @@ pub(crate) fn replace_regions_in_mir<'tcx>(
     debug!(?def);
 
     // Compute named region information. This also renumbers the inputs/outputs.
-    let universal_regions = UniversalRegions::new(infcx, def, param_env);
+    let universal_regions = UniversalRegions::new(infcx, def);
 
     // Replace all remaining regions with fresh inference variables.
     renumber::renumber_mir(infcx, body, promoted);
@@ -81,11 +80,9 @@ pub(crate) fn compute_regions<'a, 'tcx>(
     body: &Body<'tcx>,
     promoted: &IndexSlice<Promoted, Body<'tcx>>,
     location_table: &LocationTable,
-    param_env: ty::ParamEnv<'tcx>,
-    flow_inits: &mut ResultsCursor<'a, 'tcx, MaybeInitializedPlaces<'a, 'tcx>>,
+    flow_inits: ResultsCursor<'a, 'tcx, MaybeInitializedPlaces<'a, 'tcx>>,
     move_data: &MoveData<'tcx>,
     borrow_set: &BorrowSet<'tcx>,
-    upvars: &[&ty::CapturedPlace<'tcx>],
     consumer_options: Option<ConsumerOptions>,
 ) -> NllOutput<'tcx> {
     let is_polonius_legacy_enabled = infcx.tcx.sess.opts.unstable_opts.polonius.is_legacy_enabled();
@@ -96,41 +93,27 @@ pub(crate) fn compute_regions<'a, 'tcx>(
     let mut all_facts =
         (polonius_input || AllFacts::enabled(infcx.tcx)).then_some(AllFacts::default());
 
-    let universal_regions = Rc::new(universal_regions);
-
     let elements = Rc::new(DenseLocationMap::new(body));
 
     // Run the MIR type-checker.
     let MirTypeckResults { constraints, universal_region_relations, opaque_type_values } =
         type_check::type_check(
             infcx,
-            param_env,
             body,
             promoted,
-            Rc::clone(&universal_regions),
+            universal_regions,
             location_table,
             borrow_set,
             &mut all_facts,
             flow_inits,
             move_data,
             Rc::clone(&elements),
-            upvars,
         );
 
     // Create the region inference context, taking ownership of the
     // region inference data that was contained in `infcx`, and the
     // base constraints generated by the type-check.
     let var_origins = infcx.get_region_var_origins();
-    let MirTypeckRegionConstraints {
-        placeholder_indices,
-        placeholder_index_to_region: _,
-        liveness_constraints,
-        mut outlives_constraints,
-        mut member_constraints,
-        universe_causes,
-        type_tests,
-    } = constraints;
-    let placeholder_indices = Rc::new(placeholder_indices);
 
     // If requested, emit legacy polonius facts.
     polonius::emit_facts(
@@ -140,31 +123,14 @@ pub(crate) fn compute_regions<'a, 'tcx>(
         body,
         borrow_set,
         move_data,
-        &universal_regions,
         &universal_region_relations,
     );
 
-    if let Some(guar) = universal_regions.tainted_by_errors() {
-        // Suppress unhelpful extra errors in `infer_opaque_types` by clearing out all
-        // outlives bounds that we may end up checking.
-        outlives_constraints = Default::default();
-        member_constraints = Default::default();
-
-        // Also taint the entire scope.
-        infcx.set_tainted_by_errors(guar);
-    }
-
     let mut regioncx = RegionInferenceContext::new(
         infcx,
         var_origins,
-        universal_regions,
-        placeholder_indices,
+        constraints,
         universal_region_relations,
-        outlives_constraints,
-        member_constraints,
-        universe_causes,
-        type_tests,
-        liveness_constraints,
         elements,
     );
 
diff --git a/compiler/rustc_borrowck/src/polonius/mod.rs b/compiler/rustc_borrowck/src/polonius/mod.rs
index 6862eb13427..9fccc00bdaf 100644
--- a/compiler/rustc_borrowck/src/polonius/mod.rs
+++ b/compiler/rustc_borrowck/src/polonius/mod.rs
@@ -12,7 +12,6 @@ use crate::borrow_set::BorrowSet;
 use crate::facts::{AllFacts, PoloniusRegionVid};
 use crate::location::LocationTable;
 use crate::type_check::free_region_relations::UniversalRegionRelations;
-use crate::universal_regions::UniversalRegions;
 
 mod loan_invalidations;
 mod loan_kills;
@@ -32,7 +31,6 @@ pub(crate) fn emit_facts<'tcx>(
     body: &Body<'tcx>,
     borrow_set: &BorrowSet<'tcx>,
     move_data: &MoveData<'_>,
-    universal_regions: &UniversalRegions<'_>,
     universal_region_relations: &UniversalRegionRelations<'_>,
 ) {
     let Some(all_facts) = all_facts else {
@@ -41,12 +39,7 @@ pub(crate) fn emit_facts<'tcx>(
     };
     let _prof_timer = tcx.prof.generic_activity("polonius_fact_generation");
     emit_move_facts(all_facts, move_data, location_table, body);
-    emit_universal_region_facts(
-        all_facts,
-        borrow_set,
-        universal_regions,
-        universal_region_relations,
-    );
+    emit_universal_region_facts(all_facts, borrow_set, universal_region_relations);
     emit_cfg_and_loan_kills_facts(all_facts, tcx, location_table, body, borrow_set);
     emit_loan_invalidations_facts(all_facts, tcx, location_table, body, borrow_set);
 }
@@ -129,7 +122,6 @@ fn emit_move_facts(
 fn emit_universal_region_facts(
     all_facts: &mut AllFacts,
     borrow_set: &BorrowSet<'_>,
-    universal_regions: &UniversalRegions<'_>,
     universal_region_relations: &UniversalRegionRelations<'_>,
 ) {
     // 1: universal regions are modeled in Polonius as a pair:
@@ -138,9 +130,10 @@ fn emit_universal_region_facts(
     //   the `borrow_set`, their `BorrowIndex` are synthesized as the universal region index
     //   added to the existing number of loans, as if they succeeded them in the set.
     //
+    let universal_regions = &universal_region_relations.universal_regions;
     all_facts
         .universal_region
-        .extend(universal_regions.universal_regions().map(PoloniusRegionVid::from));
+        .extend(universal_regions.universal_regions_iter().map(PoloniusRegionVid::from));
     let borrow_count = borrow_set.len();
     debug!(
         "emit_universal_region_facts: polonius placeholders, num_universals={}, borrow_count={}",
@@ -148,7 +141,7 @@ fn emit_universal_region_facts(
         borrow_count
     );
 
-    for universal_region in universal_regions.universal_regions() {
+    for universal_region in universal_regions.universal_regions_iter() {
         let universal_region_idx = universal_region.index();
         let placeholder_loan_idx = borrow_count + universal_region_idx;
         all_facts.placeholder.push((universal_region.into(), placeholder_loan_idx.into()));
diff --git a/compiler/rustc_borrowck/src/region_infer/dump_mir.rs b/compiler/rustc_borrowck/src/region_infer/dump_mir.rs
index 6b8dd1a49e7..ef3d6309c19 100644
--- a/compiler/rustc_borrowck/src/region_infer/dump_mir.rs
+++ b/compiler/rustc_borrowck/src/region_infer/dump_mir.rs
@@ -23,7 +23,8 @@ impl<'tcx> RegionInferenceContext<'tcx> {
 
         for region in self.regions() {
             if let NllRegionVariableOrigin::FreeRegion = self.definitions[region].origin {
-                let classification = self.universal_regions.region_classification(region).unwrap();
+                let classification =
+                    self.universal_regions().region_classification(region).unwrap();
                 let outlived_by = self.universal_region_relations.regions_outlived_by(region);
                 writeln!(
                     out,
diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs
index 7e317ea6554..0ddb4e110e3 100644
--- a/compiler/rustc_borrowck/src/region_infer/mod.rs
+++ b/compiler/rustc_borrowck/src/region_infer/mod.rs
@@ -31,11 +31,9 @@ use crate::diagnostics::{RegionErrorKind, RegionErrors, UniverseInfo};
 use crate::member_constraints::{MemberConstraintSet, NllMemberConstraintIndex};
 use crate::nll::PoloniusOutput;
 use crate::region_infer::reverse_sccs::ReverseSccGraph;
-use crate::region_infer::values::{
-    LivenessValues, PlaceholderIndices, RegionElement, RegionValues, ToElementIndex,
-};
-use crate::type_check::Locations;
+use crate::region_infer::values::{LivenessValues, RegionElement, RegionValues, ToElementIndex};
 use crate::type_check::free_region_relations::UniversalRegionRelations;
+use crate::type_check::{Locations, MirTypeckRegionConstraints};
 use crate::universal_regions::UniversalRegions;
 
 mod dump_mir;
@@ -191,10 +189,6 @@ pub struct RegionInferenceContext<'tcx> {
     /// Type constraints that we check after solving.
     type_tests: Vec<TypeTest<'tcx>>,
 
-    /// Information about the universally quantified regions in scope
-    /// on this function.
-    universal_regions: Rc<UniversalRegions<'tcx>>,
-
     /// Information about how the universally quantified regions in
     /// scope on this function relate to one another.
     universal_region_relations: Frozen<UniversalRegionRelations<'tcx>>,
@@ -399,21 +393,36 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     pub(crate) fn new(
         infcx: &BorrowckInferCtxt<'tcx>,
         var_infos: VarInfos,
-        universal_regions: Rc<UniversalRegions<'tcx>>,
-        placeholder_indices: Rc<PlaceholderIndices>,
+        constraints: MirTypeckRegionConstraints<'tcx>,
         universal_region_relations: Frozen<UniversalRegionRelations<'tcx>>,
-        mut outlives_constraints: OutlivesConstraintSet<'tcx>,
-        member_constraints_in: MemberConstraintSet<'tcx, RegionVid>,
-        universe_causes: FxIndexMap<ty::UniverseIndex, UniverseInfo<'tcx>>,
-        type_tests: Vec<TypeTest<'tcx>>,
-        liveness_constraints: LivenessValues,
         elements: Rc<DenseLocationMap>,
     ) -> Self {
-        debug!("universal_regions: {:#?}", universal_regions);
+        let universal_regions = &universal_region_relations.universal_regions;
+        let MirTypeckRegionConstraints {
+            placeholder_indices,
+            placeholder_index_to_region: _,
+            liveness_constraints,
+            mut outlives_constraints,
+            mut member_constraints,
+            universe_causes,
+            type_tests,
+        } = constraints;
+
+        debug!("universal_regions: {:#?}", universal_region_relations.universal_regions);
         debug!("outlives constraints: {:#?}", outlives_constraints);
         debug!("placeholder_indices: {:#?}", placeholder_indices);
         debug!("type tests: {:#?}", type_tests);
 
+        if let Some(guar) = universal_region_relations.universal_regions.tainted_by_errors() {
+            // Suppress unhelpful extra errors in `infer_opaque_types` by clearing out all
+            // outlives bounds that we may end up checking.
+            outlives_constraints = Default::default();
+            member_constraints = Default::default();
+
+            // Also taint the entire scope.
+            infcx.set_tainted_by_errors(guar);
+        }
+
         // Create a RegionDefinition for each inference variable.
         let definitions: IndexVec<_, _> = var_infos
             .iter()
@@ -438,7 +447,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         }
 
         let member_constraints =
-            Rc::new(member_constraints_in.into_mapped(|r| constraint_sccs.scc(r)));
+            Rc::new(member_constraints.into_mapped(|r| constraint_sccs.scc(r)));
 
         let mut result = Self {
             var_infos,
@@ -453,7 +462,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
             universe_causes,
             scc_values,
             type_tests,
-            universal_regions,
             universal_region_relations,
         };
 
@@ -518,7 +526,9 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     fn init_free_and_bound_regions(&mut self) {
         // Update the names (if any)
         // This iterator has unstable order but we collect it all into an IndexVec
-        for (external_name, variable) in self.universal_regions.named_universal_regions() {
+        for (external_name, variable) in
+            self.universal_region_relations.universal_regions.named_universal_regions_iter()
+        {
             debug!(
                 "init_free_and_bound_regions: region {:?} has external name {:?}",
                 variable, external_name
@@ -562,7 +572,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     ///
     /// (Panics if `r` is not a registered universal region.)
     pub(crate) fn to_region_vid(&self, r: ty::Region<'tcx>) -> RegionVid {
-        self.universal_regions.to_region_vid(r)
+        self.universal_regions().to_region_vid(r)
     }
 
     /// Returns an iterator over all the outlives constraints.
@@ -574,7 +584,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
 
     /// Adds annotations for `#[rustc_regions]`; see `UniversalRegions::annotate`.
     pub(crate) fn annotate(&self, tcx: TyCtxt<'tcx>, err: &mut Diag<'_, ()>) {
-        self.universal_regions.annotate(tcx, err)
+        self.universal_regions().annotate(tcx, err)
     }
 
     /// Returns `true` if the region `r` contains the point `p`.
@@ -686,7 +696,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         if outlives_requirements.is_empty() {
             (None, errors_buffer)
         } else {
-            let num_external_vids = self.universal_regions.num_global_and_external_regions();
+            let num_external_vids = self.universal_regions().num_global_and_external_regions();
             (
                 Some(ClosureRegionRequirements { num_external_vids, outlives_requirements }),
                 errors_buffer,
@@ -989,7 +999,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         // always be in the root universe.
         if let Some(p) = self.scc_values.placeholders_contained_in(r_scc).next() {
             debug!("encountered placeholder in higher universe: {:?}, requiring 'static", p);
-            let static_r = self.universal_regions.fr_static;
+            let static_r = self.universal_regions().fr_static;
             propagated_outlives_requirements.push(ClosureOutlivesRequirement {
                 subject,
                 outlived_free_region: static_r,
@@ -1032,8 +1042,8 @@ impl<'tcx> RegionInferenceContext<'tcx> {
             // avoid potential non-determinism we approximate this by requiring
             // T: '1 and T: '2.
             for upper_bound in non_local_ub {
-                debug_assert!(self.universal_regions.is_universal_region(upper_bound));
-                debug_assert!(!self.universal_regions.is_local_free_region(upper_bound));
+                debug_assert!(self.universal_regions().is_universal_region(upper_bound));
+                debug_assert!(!self.universal_regions().is_local_free_region(upper_bound));
 
                 let requirement = ClosureOutlivesRequirement {
                     subject,
@@ -1101,7 +1111,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
             // To do so, we simply check every candidate `u_r` for equality.
             self.scc_values
                 .universal_regions_outlived_by(r_scc)
-                .filter(|&u_r| !self.universal_regions.is_local_free_region(u_r))
+                .filter(|&u_r| !self.universal_regions().is_local_free_region(u_r))
                 .find(|&u_r| self.eval_equal(u_r, r_vid))
                 .map(|u_r| ty::Region::new_var(tcx, u_r))
                 // In case we could not find a named region to map to,
@@ -1139,9 +1149,9 @@ impl<'tcx> RegionInferenceContext<'tcx> {
 
         // Find the smallest universal region that contains all other
         // universal regions within `region`.
-        let mut lub = self.universal_regions.fr_fn_body;
+        let mut lub = self.universal_regions().fr_fn_body;
         let r_scc = self.constraint_sccs.scc(r);
-        let static_r = self.universal_regions.fr_static;
+        let static_r = self.universal_regions().fr_static;
         for ur in self.scc_values.universal_regions_outlived_by(r_scc) {
             let new_lub = self.universal_region_relations.postdom_upper_bound(lub, ur);
             debug!(?ur, ?lub, ?new_lub);
@@ -1288,12 +1298,12 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         debug!(
             "sup_region's value = {:?} universal={:?}",
             self.region_value_str(sup_region),
-            self.universal_regions.is_universal_region(sup_region),
+            self.universal_regions().is_universal_region(sup_region),
         );
         debug!(
             "sub_region's value = {:?} universal={:?}",
             self.region_value_str(sub_region),
-            self.universal_regions.is_universal_region(sub_region),
+            self.universal_regions().is_universal_region(sub_region),
         );
 
         let sub_region_scc = self.constraint_sccs.scc(sub_region);
@@ -1308,7 +1318,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
                 by super `{sup_region_scc:?}`, promoting to static",
             );
 
-            return self.eval_outlives(sup_region, self.universal_regions.fr_static);
+            return self.eval_outlives(sup_region, self.universal_regions().fr_static);
         }
 
         // Both the `sub_region` and `sup_region` consist of the union
@@ -1332,7 +1342,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         // Now we have to compare all the points in the sub region and make
         // sure they exist in the sup region.
 
-        if self.universal_regions.is_universal_region(sup_region) {
+        if self.universal_regions().is_universal_region(sup_region) {
             // Micro-opt: universal regions contain all points.
             debug!("super is universal and hence contains all points");
             return true;
@@ -1736,7 +1746,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         debug!("provides_universal_region(r={:?}, fr1={:?}, fr2={:?})", r, fr1, fr2);
         let result = {
             r == fr2 || {
-                fr2 == self.universal_regions.fr_static && self.cannot_name_placeholder(fr1, r)
+                fr2 == self.universal_regions().fr_static && self.cannot_name_placeholder(fr1, r)
             }
         };
         debug!("provides_universal_region: result = {:?}", result);
@@ -1837,7 +1847,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
 
             // A constraint like `'r: 'x` can come from our constraint
             // graph.
-            let fr_static = self.universal_regions.fr_static;
+            let fr_static = self.universal_regions().fr_static;
             let outgoing_edges_from_graph =
                 self.constraint_graph.outgoing_edges(r, &self.constraints, fr_static);
 
@@ -1952,7 +1962,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     }
 
     pub(crate) fn universal_regions(&self) -> &UniversalRegions<'tcx> {
-        self.universal_regions.as_ref()
+        &self.universal_region_relations.universal_regions
     }
 
     /// Tries to find the best constraint to blame for the fact that
@@ -2212,7 +2222,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
 
     /// Access to the region graph, built from the outlives constraints.
     pub(crate) fn region_graph(&self) -> RegionGraph<'_, 'tcx, graph::Normal> {
-        self.constraint_graph.region_graph(&self.constraints, self.universal_regions.fr_static)
+        self.constraint_graph.region_graph(&self.constraints, self.universal_regions().fr_static)
     }
 
     /// Returns whether the given region is considered live at all points: whether it is a
diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
index d676ce59cfe..993d5d86333 100644
--- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
+++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
@@ -74,7 +74,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
             debug!(?opaque_type_key, ?concrete_type);
 
             let mut arg_regions: Vec<(ty::RegionVid, ty::Region<'_>)> =
-                vec![(self.universal_regions.fr_static, infcx.tcx.lifetimes.re_static)];
+                vec![(self.universal_regions().fr_static, infcx.tcx.lifetimes.re_static)];
 
             let opaque_type_key =
                 opaque_type_key.fold_captured_lifetime_args(infcx.tcx, |region| {
@@ -88,12 +88,12 @@ impl<'tcx> RegionInferenceContext<'tcx> {
                         // the same name and simplifies subsequent handling.
                         // See [rustc-dev-guide chapter] § "Semantic lifetime equality".
                         NllRegionVariableOrigin::FreeRegion => self
-                            .universal_regions
                             .universal_regions()
+                            .universal_regions_iter()
                             .filter(|&ur| {
                                 // See [rustc-dev-guide chapter] § "Closure restrictions".
                                 !matches!(
-                                    self.universal_regions.region_classification(ur),
+                                    self.universal_regions().region_classification(ur),
                                     Some(RegionClassification::External)
                                 )
                             })
diff --git a/compiler/rustc_borrowck/src/region_infer/reverse_sccs.rs b/compiler/rustc_borrowck/src/region_infer/reverse_sccs.rs
index cfd5a92787e..d0cfe572d08 100644
--- a/compiler/rustc_borrowck/src/region_infer/reverse_sccs.rs
+++ b/compiler/rustc_borrowck/src/region_infer/reverse_sccs.rs
@@ -45,8 +45,8 @@ impl RegionInferenceContext<'_> {
 
         let graph = self.constraint_sccs.reverse();
         let mut paired_scc_regions = self
-            .universal_regions
             .universal_regions()
+            .universal_regions_iter()
             .map(|region| (self.constraint_sccs.scc(region), region))
             .collect::<Vec<_>>();
         paired_scc_regions.sort();
diff --git a/compiler/rustc_borrowck/src/region_infer/values.rs b/compiler/rustc_borrowck/src/region_infer/values.rs
index 519edfafda5..a16bce63839 100644
--- a/compiler/rustc_borrowck/src/region_infer/values.rs
+++ b/compiler/rustc_borrowck/src/region_infer/values.rs
@@ -258,10 +258,9 @@ impl PlaceholderIndices {
 /// Here, the variable `'0` would contain the free region `'a`,
 /// because (since it is returned) it must live for at least `'a`. But
 /// it would also contain various points from within the function.
-#[derive(Clone)]
 pub(crate) struct RegionValues<N: Idx> {
     elements: Rc<DenseLocationMap>,
-    placeholder_indices: Rc<PlaceholderIndices>,
+    placeholder_indices: PlaceholderIndices,
     points: SparseIntervalMatrix<N, PointIndex>,
     free_regions: SparseBitMatrix<N, RegionVid>,
 
@@ -277,7 +276,7 @@ impl<N: Idx> RegionValues<N> {
     pub(crate) fn new(
         elements: Rc<DenseLocationMap>,
         num_universal_regions: usize,
-        placeholder_indices: Rc<PlaceholderIndices>,
+        placeholder_indices: PlaceholderIndices,
     ) -> Self {
         let num_points = elements.num_points();
         let num_placeholders = placeholder_indices.len();
diff --git a/compiler/rustc_borrowck/src/type_check/canonical.rs b/compiler/rustc_borrowck/src/type_check/canonical.rs
index aee13ca8cd7..68b843d4d0d 100644
--- a/compiler/rustc_borrowck/src/type_check/canonical.rs
+++ b/compiler/rustc_borrowck/src/type_check/canonical.rs
@@ -132,7 +132,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         locations: Locations,
         category: ConstraintCategory<'tcx>,
     ) {
-        let param_env = self.param_env;
+        let param_env = self.infcx.param_env;
         let predicate = predicate.upcast(self.tcx());
         let _: Result<_, ErrorGuaranteed> = self.fully_perform_op(
             locations,
@@ -158,7 +158,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
     where
         T: type_op::normalize::Normalizable<'tcx> + fmt::Display + Copy + 'tcx,
     {
-        let param_env = self.param_env;
+        let param_env = self.infcx.param_env;
         let result: Result<_, ErrorGuaranteed> = self.fully_perform_op(
             location.to_locations(),
             category,
@@ -176,7 +176,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         let tcx = self.tcx();
         if self.infcx.next_trait_solver() {
             let body = self.body;
-            let param_env = self.param_env;
+            let param_env = self.infcx.param_env;
             self.fully_perform_op(
                 location.to_locations(),
                 ConstraintCategory::Boring,
@@ -223,7 +223,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         let _: Result<_, ErrorGuaranteed> = self.fully_perform_op(
             Locations::All(span),
             ConstraintCategory::Boring,
-            self.param_env.and(type_op::ascribe_user_type::AscribeUserType { mir_ty, user_ty }),
+            self.infcx
+                .param_env
+                .and(type_op::ascribe_user_type::AscribeUserType { mir_ty, user_ty }),
         );
     }
 
@@ -250,7 +252,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         let mir_ty = self.normalize(mir_ty, Locations::All(span));
 
         let cause = ObligationCause::dummy_with_span(span);
-        let param_env = self.param_env;
+        let param_env = self.infcx.param_env;
         let _: Result<_, ErrorGuaranteed> = self.fully_perform_op(
             Locations::All(span),
             ConstraintCategory::Boring,
diff --git a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs
index 6c86968389a..67915371b1f 100644
--- a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs
+++ b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs
@@ -37,7 +37,7 @@ pub(crate) struct ConstraintConversion<'a, 'tcx> {
     region_bound_pairs: &'a RegionBoundPairs<'tcx>,
     implicit_region_bound: ty::Region<'tcx>,
     param_env: ty::ParamEnv<'tcx>,
-    known_type_outlives_obligations: &'tcx [ty::PolyTypeOutlivesPredicate<'tcx>],
+    known_type_outlives_obligations: &'a [ty::PolyTypeOutlivesPredicate<'tcx>],
     locations: Locations,
     span: Span,
     category: ConstraintCategory<'tcx>,
@@ -52,7 +52,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
         region_bound_pairs: &'a RegionBoundPairs<'tcx>,
         implicit_region_bound: ty::Region<'tcx>,
         param_env: ty::ParamEnv<'tcx>,
-        known_type_outlives_obligations: &'tcx [ty::PolyTypeOutlivesPredicate<'tcx>],
+        known_type_outlives_obligations: &'a [ty::PolyTypeOutlivesPredicate<'tcx>],
         locations: Locations,
         span: Span,
         category: ConstraintCategory<'tcx>,
diff --git a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs
index 8e1faf025e2..ea965eb6545 100644
--- a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs
+++ b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs
@@ -1,5 +1,3 @@
-use std::rc::Rc;
-
 use rustc_data_structures::frozen::Frozen;
 use rustc_data_structures::transitive_relation::{TransitiveRelation, TransitiveRelationBuilder};
 use rustc_hir::def::DefKind;
@@ -23,7 +21,7 @@ use crate::universal_regions::UniversalRegions;
 
 #[derive(Debug)]
 pub(crate) struct UniversalRegionRelations<'tcx> {
-    universal_regions: Rc<UniversalRegions<'tcx>>,
+    pub(crate) universal_regions: UniversalRegions<'tcx>,
 
     /// Stores the outlives relations that are known to hold from the
     /// implied bounds, in-scope where-clauses, and that sort of
@@ -46,7 +44,7 @@ type NormalizedInputsAndOutput<'tcx> = Vec<Ty<'tcx>>;
 pub(crate) struct CreateResult<'tcx> {
     pub(crate) universal_region_relations: Frozen<UniversalRegionRelations<'tcx>>,
     pub(crate) region_bound_pairs: RegionBoundPairs<'tcx>,
-    pub(crate) known_type_outlives_obligations: &'tcx [ty::PolyTypeOutlivesPredicate<'tcx>],
+    pub(crate) known_type_outlives_obligations: Vec<ty::PolyTypeOutlivesPredicate<'tcx>>,
     pub(crate) normalized_inputs_and_output: NormalizedInputsAndOutput<'tcx>,
 }
 
@@ -54,7 +52,7 @@ pub(crate) fn create<'tcx>(
     infcx: &InferCtxt<'tcx>,
     param_env: ty::ParamEnv<'tcx>,
     implicit_region_bound: ty::Region<'tcx>,
-    universal_regions: Rc<UniversalRegions<'tcx>>,
+    universal_regions: UniversalRegions<'tcx>,
     constraints: &mut MirTypeckRegionConstraints<'tcx>,
 ) -> CreateResult<'tcx> {
     UniversalRegionRelationsBuilder {
@@ -184,7 +182,7 @@ impl UniversalRegionRelations<'_> {
 struct UniversalRegionRelationsBuilder<'a, 'tcx> {
     infcx: &'a InferCtxt<'tcx>,
     param_env: ty::ParamEnv<'tcx>,
-    universal_regions: Rc<UniversalRegions<'tcx>>,
+    universal_regions: UniversalRegions<'tcx>,
     implicit_region_bound: ty::Region<'tcx>,
     constraints: &'a mut MirTypeckRegionConstraints<'tcx>,
 
@@ -220,7 +218,7 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
         //   region `'r`, all of which are provided by our caller
         let fr_static = self.universal_regions.fr_static;
         let fr_fn_body = self.universal_regions.fr_fn_body;
-        for fr in self.universal_regions.universal_regions() {
+        for fr in self.universal_regions.universal_regions_iter() {
             debug!("build: relating free region {:?} to itself and to 'static", fr);
             self.relate_universal_regions(fr, fr);
             self.relate_universal_regions(fr_static, fr);
@@ -236,7 +234,7 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
             // In the new solver, normalize the type-outlives obligation assumptions.
             if self.infcx.next_trait_solver() {
                 match deeply_normalize(
-                    self.infcx.at(&ObligationCause::misc(span, defining_ty_def_id), self.param_env),
+                    self.infcx.at(&ObligationCause::misc(span, defining_ty_def_id), param_env),
                     outlives,
                 ) {
                     Ok(normalized_outlives) => {
@@ -250,8 +248,6 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
 
             known_type_outlives_obligations.push(outlives);
         }
-        let known_type_outlives_obligations =
-            self.infcx.tcx.arena.alloc_slice(&known_type_outlives_obligations);
 
         let unnormalized_input_output_tys = self
             .universal_regions
@@ -278,15 +274,15 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
             if let Some(c) = constraints_unnorm {
                 constraints.push(c)
             }
-            let TypeOpOutput { output: norm_ty, constraints: constraints_normalize, .. } = self
-                .param_env
-                .and(type_op::normalize::Normalize { value: ty })
-                .fully_perform(self.infcx, span)
-                .unwrap_or_else(|guar| TypeOpOutput {
-                    output: Ty::new_error(self.infcx.tcx, guar),
-                    constraints: None,
-                    error_info: None,
-                });
+            let TypeOpOutput { output: norm_ty, constraints: constraints_normalize, .. } =
+                param_env
+                    .and(type_op::normalize::Normalize { value: ty })
+                    .fully_perform(self.infcx, span)
+                    .unwrap_or_else(|guar| TypeOpOutput {
+                        output: Ty::new_error(self.infcx.tcx, guar),
+                        constraints: None,
+                        error_info: None,
+                    });
             if let Some(c) = constraints_normalize {
                 constraints.push(c)
             }
@@ -316,8 +312,7 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
         // Add implied bounds from impl header.
         if matches!(tcx.def_kind(defining_ty_def_id), DefKind::AssocFn | DefKind::AssocConst) {
             for &(ty, _) in tcx.assumed_wf_types(tcx.local_parent(defining_ty_def_id)) {
-                let result: Result<_, ErrorGuaranteed> = self
-                    .param_env
+                let result: Result<_, ErrorGuaranteed> = param_env
                     .and(type_op::normalize::Normalize { value: ty })
                     .fully_perform(self.infcx, span);
                 let Ok(TypeOpOutput { output: norm_ty, constraints: c, .. }) = result else {
@@ -340,7 +335,7 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
                 &self.region_bound_pairs,
                 self.implicit_region_bound,
                 param_env,
-                known_type_outlives_obligations,
+                &known_type_outlives_obligations,
                 Locations::All(span),
                 span,
                 ConstraintCategory::Internal,
diff --git a/compiler/rustc_borrowck/src/type_check/input_output.rs b/compiler/rustc_borrowck/src/type_check/input_output.rs
index 7effd5c5a68..bbe2b55d8c4 100644
--- a/compiler/rustc_borrowck/src/type_check/input_output.rs
+++ b/compiler/rustc_borrowck/src/type_check/input_output.rs
@@ -19,7 +19,7 @@ use tracing::{debug, instrument};
 
 use super::{Locations, TypeChecker};
 use crate::renumber::RegionCtxt;
-use crate::universal_regions::{DefiningTy, UniversalRegions};
+use crate::universal_regions::DefiningTy;
 
 impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
     /// Check explicit closure signature annotation,
@@ -124,11 +124,10 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         );
     }
 
-    #[instrument(skip(self, body, universal_regions), level = "debug")]
+    #[instrument(skip(self, body), level = "debug")]
     pub(super) fn equate_inputs_and_outputs(
         &mut self,
         body: &Body<'tcx>,
-        universal_regions: &UniversalRegions<'tcx>,
         normalized_inputs_and_output: &[Ty<'tcx>],
     ) {
         let (&normalized_output_ty, normalized_input_tys) =
@@ -161,7 +160,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         if let Some(mir_yield_ty) = body.yield_ty() {
             let yield_span = body.local_decls[RETURN_PLACE].source_info.span;
             self.equate_normalized_input_or_output(
-                universal_regions.yield_ty.unwrap(),
+                self.universal_regions.yield_ty.unwrap(),
                 mir_yield_ty,
                 yield_span,
             );
@@ -170,7 +169,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         if let Some(mir_resume_ty) = body.resume_ty() {
             let yield_span = body.local_decls[RETURN_PLACE].source_info.span;
             self.equate_normalized_input_or_output(
-                universal_regions.resume_ty.unwrap(),
+                self.universal_regions.resume_ty.unwrap(),
                 mir_resume_ty,
                 yield_span,
             );
diff --git a/compiler/rustc_borrowck/src/type_check/liveness/mod.rs b/compiler/rustc_borrowck/src/type_check/liveness/mod.rs
index 84fb36dd32a..20d19a53752 100644
--- a/compiler/rustc_borrowck/src/type_check/liveness/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/liveness/mod.rs
@@ -32,14 +32,14 @@ pub(super) fn generate<'a, 'tcx>(
     typeck: &mut TypeChecker<'_, 'tcx>,
     body: &Body<'tcx>,
     elements: &DenseLocationMap,
-    flow_inits: &mut ResultsCursor<'a, 'tcx, MaybeInitializedPlaces<'a, 'tcx>>,
+    flow_inits: ResultsCursor<'a, 'tcx, MaybeInitializedPlaces<'a, 'tcx>>,
     move_data: &MoveData<'tcx>,
 ) {
     debug!("liveness::generate");
 
     let free_regions = regions_that_outlive_free_regions(
         typeck.infcx.num_region_vars(),
-        typeck.universal_regions,
+        &typeck.universal_regions,
         &typeck.constraints.outlives_constraints,
     );
     let (relevant_live_locals, boring_locals) =
@@ -107,7 +107,7 @@ fn regions_that_outlive_free_regions<'tcx>(
     let rev_region_graph = rev_constraint_graph.region_graph(constraint_set, fr_static);
 
     // Stack for the depth-first search. Start out with all the free regions.
-    let mut stack: Vec<_> = universal_regions.universal_regions().collect();
+    let mut stack: Vec<_> = universal_regions.universal_regions_iter().collect();
 
     // Set of all free regions, plus anything that outlives them. Initially
     // just contains the free regions.
diff --git a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs
index 72f6a605279..3ec36c16cbf 100644
--- a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs
+++ b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs
@@ -38,7 +38,7 @@ pub(super) fn trace<'a, 'tcx>(
     typeck: &mut TypeChecker<'_, 'tcx>,
     body: &Body<'tcx>,
     elements: &DenseLocationMap,
-    flow_inits: &mut ResultsCursor<'a, 'tcx, MaybeInitializedPlaces<'a, 'tcx>>,
+    flow_inits: ResultsCursor<'a, 'tcx, MaybeInitializedPlaces<'a, 'tcx>>,
     move_data: &MoveData<'tcx>,
     relevant_live_locals: Vec<Local>,
     boring_locals: Vec<Local>,
@@ -113,7 +113,7 @@ struct LivenessContext<'a, 'typeck, 'b, 'tcx> {
 
     /// Results of dataflow tracking which variables (and paths) have been
     /// initialized.
-    flow_inits: &'a mut ResultsCursor<'b, 'tcx, MaybeInitializedPlaces<'b, 'tcx>>,
+    flow_inits: ResultsCursor<'b, 'tcx, MaybeInitializedPlaces<'b, 'tcx>>,
 
     /// Index indicating where each variable is assigned, used, or
     /// dropped.
@@ -608,7 +608,7 @@ impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> {
 
         value.visit_with(&mut for_liveness::FreeRegionsVisitor {
             tcx: typeck.tcx(),
-            param_env: typeck.param_env,
+            param_env: typeck.infcx.param_env,
             op: |r| {
                 let live_region_vid = typeck.universal_regions.to_region_vid(r);
 
@@ -621,6 +621,7 @@ impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> {
         debug!("compute_drop_data(dropped_ty={:?})", dropped_ty,);
 
         match typeck
+            .infcx
             .param_env
             .and(DropckOutlives { dropped_ty })
             .fully_perform(typeck.infcx, DUMMY_SP)
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index 0fe6a4b5fce..58a23b9e558 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -118,17 +118,15 @@ mod relate_tys;
 /// - `elements` -- MIR region map
 pub(crate) fn type_check<'a, 'tcx>(
     infcx: &BorrowckInferCtxt<'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
     body: &Body<'tcx>,
     promoted: &IndexSlice<Promoted, Body<'tcx>>,
-    universal_regions: Rc<UniversalRegions<'tcx>>,
+    universal_regions: UniversalRegions<'tcx>,
     location_table: &LocationTable,
     borrow_set: &BorrowSet<'tcx>,
     all_facts: &mut Option<AllFacts>,
-    flow_inits: &mut ResultsCursor<'a, 'tcx, MaybeInitializedPlaces<'a, 'tcx>>,
+    flow_inits: ResultsCursor<'a, 'tcx, MaybeInitializedPlaces<'a, 'tcx>>,
     move_data: &MoveData<'tcx>,
     elements: Rc<DenseLocationMap>,
-    upvars: &[&ty::CapturedPlace<'tcx>],
 ) -> MirTypeckResults<'tcx> {
     let implicit_region_bound = ty::Region::new_var(infcx.tcx, universal_regions.fr_fn_body);
     let mut constraints = MirTypeckRegionConstraints {
@@ -148,9 +146,9 @@ pub(crate) fn type_check<'a, 'tcx>(
         known_type_outlives_obligations,
     } = free_region_relations::create(
         infcx,
-        param_env,
+        infcx.param_env,
         implicit_region_bound,
-        Rc::clone(&universal_regions),
+        universal_regions,
         &mut constraints,
     );
 
@@ -158,29 +156,27 @@ pub(crate) fn type_check<'a, 'tcx>(
 
     let mut checker = TypeChecker {
         infcx,
-        param_env,
         last_span: body.span,
         body,
         user_type_annotations: &body.user_type_annotations,
-        region_bound_pairs: &region_bound_pairs,
+        region_bound_pairs,
         known_type_outlives_obligations,
         implicit_region_bound,
         reported_errors: Default::default(),
-        universal_regions: &universal_regions,
+        universal_regions: &universal_region_relations.universal_regions,
         location_table,
         all_facts,
         borrow_set,
         constraints: &mut constraints,
-        upvars,
     };
 
     checker.check_user_type_annotations();
 
-    let mut verifier = TypeVerifier::new(&mut checker, promoted);
+    let mut verifier = TypeVerifier { cx: &mut checker, promoted, last_span: body.span };
     verifier.visit_body(body);
 
     checker.typeck_mir(body);
-    checker.equate_inputs_and_outputs(body, &universal_regions, &normalized_inputs_and_output);
+    checker.equate_inputs_and_outputs(body, &normalized_inputs_and_output);
     checker.check_signature_annotation(body);
 
     liveness::generate(&mut checker, body, &elements, flow_inits, move_data);
@@ -467,13 +463,6 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
 }
 
 impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
-    fn new(
-        cx: &'a mut TypeChecker<'b, 'tcx>,
-        promoted: &'b IndexSlice<Promoted, Body<'tcx>>,
-    ) -> Self {
-        TypeVerifier { promoted, last_span: cx.body.span, cx }
-    }
-
     fn body(&self) -> &Body<'tcx> {
         self.cx.body
     }
@@ -837,14 +826,13 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
 /// NLL region checking.
 struct TypeChecker<'a, 'tcx> {
     infcx: &'a BorrowckInferCtxt<'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
     last_span: Span,
     body: &'a 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>,
-    region_bound_pairs: &'a RegionBoundPairs<'tcx>,
-    known_type_outlives_obligations: &'tcx [ty::PolyTypeOutlivesPredicate<'tcx>],
+    region_bound_pairs: RegionBoundPairs<'tcx>,
+    known_type_outlives_obligations: Vec<ty::PolyTypeOutlivesPredicate<'tcx>>,
     implicit_region_bound: ty::Region<'tcx>,
     reported_errors: FxIndexSet<(Ty<'tcx>, Span)>,
     universal_regions: &'a UniversalRegions<'tcx>,
@@ -852,7 +840,6 @@ struct TypeChecker<'a, 'tcx> {
     all_facts: &'a mut Option<AllFacts>,
     borrow_set: &'a BorrowSet<'tcx>,
     constraints: &'a mut MirTypeckRegionConstraints<'tcx>,
-    upvars: &'a [&'a ty::CapturedPlace<'tcx>],
 }
 
 /// Holder struct for passing results from MIR typeck to the rest of the non-lexical regions
@@ -1025,10 +1012,10 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         constraint_conversion::ConstraintConversion::new(
             self.infcx,
             self.universal_regions,
-            self.region_bound_pairs,
+            &self.region_bound_pairs,
             self.implicit_region_bound,
-            self.param_env,
-            self.known_type_outlives_obligations,
+            self.infcx.param_env,
+            &self.known_type_outlives_obligations,
             locations,
             locations.span(self.body),
             category,
@@ -1527,7 +1514,10 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                 // 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.param_env) {
+                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);
                 }
             }
@@ -1737,7 +1727,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         // `Sized` bound in no way depends on precise regions, so this
         // shouldn't affect `is_sized`.
         let erased_ty = tcx.erase_regions(ty);
-        if !erased_ty.is_sized(tcx, self.param_env) {
+        if !erased_ty.is_sized(tcx, 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
@@ -2629,8 +2619,10 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         );
 
         let tcx = self.infcx.tcx;
+        let def = self.body.source.def_id().expect_local();
+        let upvars = tcx.closure_captures(def);
         let field =
-            path_utils::is_upvar_field_projection(tcx, self.upvars, borrowed_place.as_ref(), body);
+            path_utils::is_upvar_field_projection(tcx, upvars, borrowed_place.as_ref(), body);
         let category = if let Some(field) = field {
             ConstraintCategory::ClosureUpvar(field)
         } else {
@@ -2785,10 +2777,10 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
             constraint_conversion::ConstraintConversion::new(
                 self.infcx,
                 self.universal_regions,
-                self.region_bound_pairs,
+                &self.region_bound_pairs,
                 self.implicit_region_bound,
-                self.param_env,
-                self.known_type_outlives_obligations,
+                self.infcx.param_env,
+                &self.known_type_outlives_obligations,
                 locations,
                 self.body.span,             // irrelevant; will be overridden.
                 ConstraintCategory::Boring, // same as above.
diff --git a/compiler/rustc_borrowck/src/type_check/relate_tys.rs b/compiler/rustc_borrowck/src/type_check/relate_tys.rs
index e2f3e065bc0..752b2bf1a24 100644
--- a/compiler/rustc_borrowck/src/type_check/relate_tys.rs
+++ b/compiler/rustc_borrowck/src/type_check/relate_tys.rs
@@ -522,7 +522,7 @@ impl<'b, 'tcx> PredicateEmittingRelation<InferCtxt<'tcx>> for NllTypeRelating<'_
     }
 
     fn param_env(&self) -> ty::ParamEnv<'tcx> {
-        self.type_checker.param_env
+        self.type_checker.infcx.param_env
     }
 
     fn register_predicates(
diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs
index b63144f560f..f1c23aa26a9 100644
--- a/compiler/rustc_borrowck/src/universal_regions.rs
+++ b/compiler/rustc_borrowck/src/universal_regions.rs
@@ -248,12 +248,8 @@ impl<'tcx> UniversalRegions<'tcx> {
     /// MIR -- that is, all the regions that appear in the function's
     /// signature. This will also compute the relationships that are
     /// known between those regions.
-    pub(crate) fn new(
-        infcx: &BorrowckInferCtxt<'tcx>,
-        mir_def: LocalDefId,
-        param_env: ty::ParamEnv<'tcx>,
-    ) -> Self {
-        UniversalRegionsBuilder { infcx, mir_def, param_env }.build()
+    pub(crate) fn new(infcx: &BorrowckInferCtxt<'tcx>, mir_def: LocalDefId) -> Self {
+        UniversalRegionsBuilder { infcx, mir_def }.build()
     }
 
     /// Given a reference to a closure type, extracts all the values
@@ -312,7 +308,7 @@ impl<'tcx> UniversalRegions<'tcx> {
 
     /// Returns an iterator over all the RegionVids corresponding to
     /// universally quantified free regions.
-    pub(crate) fn universal_regions(&self) -> impl Iterator<Item = RegionVid> {
+    pub(crate) fn universal_regions_iter(&self) -> impl Iterator<Item = RegionVid> {
         (FIRST_GLOBAL_INDEX..self.num_universals).map(RegionVid::from_usize)
     }
 
@@ -336,7 +332,7 @@ impl<'tcx> UniversalRegions<'tcx> {
     }
 
     /// Gets an iterator over all the early-bound regions that have names.
-    pub(crate) fn named_universal_regions<'s>(
+    pub(crate) fn named_universal_regions_iter<'s>(
         &'s self,
     ) -> impl Iterator<Item = (ty::Region<'tcx>, ty::RegionVid)> + 's {
         self.indices.indices.iter().map(|(&r, &v)| (r, v))
@@ -426,7 +422,6 @@ impl<'tcx> UniversalRegions<'tcx> {
 struct UniversalRegionsBuilder<'infcx, 'tcx> {
     infcx: &'infcx BorrowckInferCtxt<'tcx>,
     mir_def: LocalDefId,
-    param_env: ty::ParamEnv<'tcx>,
 }
 
 const FR: NllRegionVariableOrigin = NllRegionVariableOrigin::FreeRegion;
@@ -435,7 +430,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
     fn build(self) -> UniversalRegions<'tcx> {
         debug!("build(mir_def={:?})", self.mir_def);
 
-        let param_env = self.param_env;
+        let param_env = self.infcx.param_env;
         debug!("build: param_env={:?}", param_env);
 
         assert_eq!(FIRST_GLOBAL_INDEX, self.infcx.num_region_vars());
diff --git a/compiler/rustc_codegen_cranelift/scripts/setup_rust_fork.sh b/compiler/rustc_codegen_cranelift/scripts/setup_rust_fork.sh
index 2f13b0b9cb8..5b3f2a91207 100644
--- a/compiler/rustc_codegen_cranelift/scripts/setup_rust_fork.sh
+++ b/compiler/rustc_codegen_cranelift/scripts/setup_rust_fork.sh
@@ -38,6 +38,11 @@ local-rebuild = true
 codegen-backends = ["cranelift"]
 deny-warnings = false
 verbose-tests = false
+# The cg_clif sysroot doesn't contain llvm tools and unless llvm_tools is
+# disabled bootstrap will crash trying to copy llvm tools for the bootstrap
+# compiler.
+llvm_tools = false
+
 EOF
 popd
 
diff --git a/compiler/rustc_codegen_cranelift/src/abi/mod.rs b/compiler/rustc_codegen_cranelift/src/abi/mod.rs
index f647ee36c48..7dd2139cf90 100644
--- a/compiler/rustc_codegen_cranelift/src/abi/mod.rs
+++ b/compiler/rustc_codegen_cranelift/src/abi/mod.rs
@@ -376,7 +376,7 @@ pub(crate) fn codegen_terminator_call<'tcx>(
     let instance = if let ty::FnDef(def_id, fn_args) = *func.layout().ty.kind() {
         let instance = ty::Instance::expect_resolve(
             fx.tcx,
-            ty::ParamEnv::reveal_all(),
+            ty::TypingEnv::fully_monomorphized(),
             def_id,
             fn_args,
             source_info.span,
diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs
index da3818ca25e..1b91d251bfd 100644
--- a/compiler/rustc_codegen_cranelift/src/base.rs
+++ b/compiler/rustc_codegen_cranelift/src/base.rs
@@ -666,7 +666,7 @@ fn codegen_stmt<'tcx>(
                             let func_ref = fx.get_function_ref(
                                 Instance::resolve_for_fn_ptr(
                                     fx.tcx,
-                                    ParamEnv::reveal_all(),
+                                    ty::TypingEnv::fully_monomorphized(),
                                     def_id,
                                     args,
                                 )
@@ -841,14 +841,18 @@ fn codegen_stmt<'tcx>(
                     lval.write_cvalue(fx, CValue::by_val(operand, box_layout));
                 }
                 Rvalue::NullaryOp(ref null_op, ty) => {
-                    assert!(lval.layout().ty.is_sized(fx.tcx, ParamEnv::reveal_all()));
+                    assert!(lval.layout().ty.is_sized(fx.tcx, ty::ParamEnv::reveal_all()));
                     let layout = fx.layout_of(fx.monomorphize(ty));
                     let val = match null_op {
                         NullOp::SizeOf => layout.size.bytes(),
                         NullOp::AlignOf => layout.align.abi.bytes(),
                         NullOp::OffsetOf(fields) => fx
                             .tcx
-                            .offset_of_subfield(ParamEnv::reveal_all(), layout, fields.iter())
+                            .offset_of_subfield(
+                                ty::TypingEnv::fully_monomorphized(),
+                                layout,
+                                fields.iter(),
+                            )
                             .bytes(),
                         NullOp::UbChecks => {
                             let val = fx.tcx.sess.ub_checks();
diff --git a/compiler/rustc_codegen_cranelift/src/common.rs b/compiler/rustc_codegen_cranelift/src/common.rs
index 27e71b92561..add081bc795 100644
--- a/compiler/rustc_codegen_cranelift/src/common.rs
+++ b/compiler/rustc_codegen_cranelift/src/common.rs
@@ -103,11 +103,11 @@ fn clif_pair_type_from_ty<'tcx>(
 
 /// Is a pointer to this type a wide ptr?
 pub(crate) fn has_ptr_meta<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool {
-    if ty.is_sized(tcx, ParamEnv::reveal_all()) {
+    if ty.is_sized(tcx, ty::ParamEnv::reveal_all()) {
         return false;
     }
 
-    let tail = tcx.struct_tail_for_codegen(ty, ParamEnv::reveal_all());
+    let tail = tcx.struct_tail_for_codegen(ty, ty::TypingEnv::fully_monomorphized());
     match tail.kind() {
         ty::Foreign(..) => false,
         ty::Str | ty::Slice(..) | ty::Dynamic(..) => true,
@@ -339,9 +339,9 @@ impl<'tcx> rustc_abi::HasDataLayout for FunctionCx<'_, '_, 'tcx> {
     }
 }
 
-impl<'tcx> layout::HasParamEnv<'tcx> for FunctionCx<'_, '_, 'tcx> {
-    fn param_env(&self) -> ParamEnv<'tcx> {
-        ParamEnv::reveal_all()
+impl<'tcx> layout::HasTypingEnv<'tcx> for FunctionCx<'_, '_, 'tcx> {
+    fn typing_env(&self) -> ty::TypingEnv<'tcx> {
+        ty::TypingEnv::fully_monomorphized()
     }
 }
 
@@ -358,7 +358,7 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> {
     {
         self.instance.instantiate_mir_and_normalize_erasing_regions(
             self.tcx,
-            ty::ParamEnv::reveal_all(),
+            ty::TypingEnv::fully_monomorphized(),
             ty::EarlyBinder::bind(value),
         )
     }
@@ -497,9 +497,9 @@ impl<'tcx> rustc_abi::HasDataLayout for RevealAllLayoutCx<'tcx> {
     }
 }
 
-impl<'tcx> layout::HasParamEnv<'tcx> for RevealAllLayoutCx<'tcx> {
-    fn param_env(&self) -> ParamEnv<'tcx> {
-        ParamEnv::reveal_all()
+impl<'tcx> layout::HasTypingEnv<'tcx> for RevealAllLayoutCx<'tcx> {
+    fn typing_env(&self) -> ty::TypingEnv<'tcx> {
+        ty::TypingEnv::fully_monomorphized()
     }
 }
 
diff --git a/compiler/rustc_codegen_cranelift/src/constant.rs b/compiler/rustc_codegen_cranelift/src/constant.rs
index ab78584332a..5311547309c 100644
--- a/compiler/rustc_codegen_cranelift/src/constant.rs
+++ b/compiler/rustc_codegen_cranelift/src/constant.rs
@@ -78,7 +78,7 @@ pub(crate) fn eval_mir_constant<'tcx>(
     let cv = fx.monomorphize(constant.const_);
     // This cannot fail because we checked all required_consts in advance.
     let val = cv
-        .eval(fx.tcx, ty::ParamEnv::reveal_all(), constant.span)
+        .eval(fx.tcx, ty::TypingEnv::fully_monomorphized(), constant.span)
         .expect("erroneous constant missed by mono item collection");
     (val, cv.ty())
 }
@@ -265,8 +265,13 @@ fn data_id_for_static(
         assert!(!definition);
         assert!(!tcx.is_mutable_static(def_id));
 
-        let ty = instance.ty(tcx, ParamEnv::reveal_all());
-        let align = tcx.layout_of(ParamEnv::reveal_all().and(ty)).unwrap().align.pref.bytes();
+        let ty = instance.ty(tcx, ty::TypingEnv::fully_monomorphized());
+        let align = tcx
+            .layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(ty))
+            .unwrap()
+            .align
+            .pref
+            .bytes();
 
         let linkage = if import_linkage == rustc_middle::mir::mono::Linkage::ExternalWeak
             || import_linkage == rustc_middle::mir::mono::Linkage::WeakAny
diff --git a/compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs b/compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs
index 9025ea97b81..f3a8623e216 100644
--- a/compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs
+++ b/compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs
@@ -210,7 +210,7 @@ impl DebugContext {
 
         type_names::push_generic_params(
             tcx,
-            tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), args),
+            tcx.normalize_erasing_regions(ty::TypingEnv::fully_monomorphized(), args),
             &mut name,
         );
 
@@ -275,8 +275,10 @@ impl DebugContext {
         let span = tcx.def_span(def_id);
         let (file_id, line, _column) = self.get_span_loc(tcx, span, span);
 
-        let static_type = Instance::mono(tcx, def_id).ty(tcx, ty::ParamEnv::reveal_all());
-        let static_layout = tcx.layout_of(ty::ParamEnv::reveal_all().and(static_type)).unwrap();
+        let static_type = Instance::mono(tcx, def_id).ty(tcx, ty::TypingEnv::fully_monomorphized());
+        let static_layout = tcx
+            .layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(static_type))
+            .unwrap();
         // FIXME use the actual type layout
         let type_id = self.debug_type(tcx, type_dbg, static_type);
 
diff --git a/compiler/rustc_codegen_cranelift/src/inline_asm.rs b/compiler/rustc_codegen_cranelift/src/inline_asm.rs
index a3f816f70a9..0df1a30fc0a 100644
--- a/compiler/rustc_codegen_cranelift/src/inline_asm.rs
+++ b/compiler/rustc_codegen_cranelift/src/inline_asm.rs
@@ -92,7 +92,7 @@ pub(crate) fn codegen_inline_asm_terminator<'tcx>(
                 if let ty::FnDef(def_id, args) = *const_.ty().kind() {
                     let instance = ty::Instance::resolve_for_fn_ptr(
                         fx.tcx,
-                        ty::ParamEnv::reveal_all(),
+                        ty::TypingEnv::fully_monomorphized(),
                         def_id,
                         args,
                     )
@@ -227,11 +227,11 @@ pub(crate) fn codegen_naked_asm<'tcx>(
             InlineAsmOperand::Const { ref value } => {
                 let cv = instance.instantiate_mir_and_normalize_erasing_regions(
                     tcx,
-                    ty::ParamEnv::reveal_all(),
+                    ty::TypingEnv::fully_monomorphized(),
                     ty::EarlyBinder::bind(value.const_),
                 );
                 let const_value = cv
-                    .eval(tcx, ty::ParamEnv::reveal_all(), value.span)
+                    .eval(tcx, ty::TypingEnv::fully_monomorphized(), value.span)
                     .expect("erroneous constant missed by mono item collection");
 
                 let value = rustc_codegen_ssa::common::asm_const_to_str(
@@ -250,13 +250,13 @@ pub(crate) fn codegen_naked_asm<'tcx>(
 
                 let const_ = instance.instantiate_mir_and_normalize_erasing_regions(
                     tcx,
-                    ty::ParamEnv::reveal_all(),
+                    ty::TypingEnv::fully_monomorphized(),
                     ty::EarlyBinder::bind(value.const_),
                 );
                 if let ty::FnDef(def_id, args) = *const_.ty().kind() {
                     let instance = ty::Instance::resolve_for_fn_ptr(
                         tcx,
-                        ty::ParamEnv::reveal_all(),
+                        ty::TypingEnv::fully_monomorphized(),
                         def_id,
                         args,
                     )
diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
index 6cf1cff183d..c663f6fc2d3 100644
--- a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
+++ b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
@@ -20,7 +20,7 @@ mod simd;
 use cranelift_codegen::ir::AtomicRmwOp;
 use rustc_middle::ty;
 use rustc_middle::ty::GenericArgsRef;
-use rustc_middle::ty::layout::{HasParamEnv, ValidityRequirement};
+use rustc_middle::ty::layout::ValidityRequirement;
 use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths};
 use rustc_span::source_map::Spanned;
 use rustc_span::symbol::{Symbol, sym};
@@ -682,7 +682,10 @@ fn codegen_regular_intrinsic_call<'tcx>(
             if let Some(requirement) = requirement {
                 let do_panic = !fx
                     .tcx
-                    .check_validity_requirement((requirement, fx.param_env().and(ty)))
+                    .check_validity_requirement((
+                        requirement,
+                        ty::TypingEnv::fully_monomorphized().as_query_input(ty),
+                    ))
                     .expect("expect to have layout during codegen");
 
                 if do_panic {
@@ -741,7 +744,7 @@ fn codegen_regular_intrinsic_call<'tcx>(
 
             let const_val = fx
                 .tcx
-                .const_eval_instance(ParamEnv::reveal_all(), instance, source_info.span)
+                .const_eval_instance(ty::ParamEnv::reveal_all(), instance, source_info.span)
                 .unwrap();
             let val = crate::constant::codegen_const_value(fx, const_val, ret.layout().ty);
             ret.write_cvalue(fx, val);
diff --git a/compiler/rustc_codegen_cranelift/src/lib.rs b/compiler/rustc_codegen_cranelift/src/lib.rs
index b506b1f5731..e6f6ae30581 100644
--- a/compiler/rustc_codegen_cranelift/src/lib.rs
+++ b/compiler/rustc_codegen_cranelift/src/lib.rs
@@ -98,7 +98,7 @@ mod prelude {
     pub(crate) use rustc_middle::mir::{self, *};
     pub(crate) use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
     pub(crate) use rustc_middle::ty::{
-        self, FloatTy, Instance, InstanceKind, IntTy, ParamEnv, Ty, TyCtxt, UintTy,
+        self, FloatTy, Instance, InstanceKind, IntTy, Ty, TyCtxt, UintTy,
     };
     pub(crate) use rustc_span::Span;
 
diff --git a/compiler/rustc_codegen_cranelift/src/main_shim.rs b/compiler/rustc_codegen_cranelift/src/main_shim.rs
index df92bc58bf5..2ee4ff5cec7 100644
--- a/compiler/rustc_codegen_cranelift/src/main_shim.rs
+++ b/compiler/rustc_codegen_cranelift/src/main_shim.rs
@@ -49,7 +49,7 @@ pub(crate) fn maybe_create_entry_wrapper(
         // regions must appear in the argument
         // listing.
         let main_ret_ty = tcx.normalize_erasing_regions(
-            ty::ParamEnv::reveal_all(),
+            ty::TypingEnv::fully_monomorphized(),
             main_ret_ty.no_bound_vars().unwrap(),
         );
 
@@ -113,7 +113,7 @@ pub(crate) fn maybe_create_entry_wrapper(
                     .unwrap();
                 let report = Instance::expect_resolve(
                     tcx,
-                    ParamEnv::reveal_all(),
+                    ty::TypingEnv::fully_monomorphized(),
                     report.def_id,
                     tcx.mk_args(&[GenericArg::from(main_ret_ty)]),
                     DUMMY_SP,
@@ -139,7 +139,7 @@ pub(crate) fn maybe_create_entry_wrapper(
                 let start_def_id = tcx.require_lang_item(LangItem::Start, None);
                 let start_instance = Instance::expect_resolve(
                     tcx,
-                    ParamEnv::reveal_all(),
+                    ty::TypingEnv::fully_monomorphized(),
                     start_def_id,
                     tcx.mk_args(&[main_ret_ty.into()]),
                     DUMMY_SP,
diff --git a/compiler/rustc_codegen_cranelift/src/unsize.rs b/compiler/rustc_codegen_cranelift/src/unsize.rs
index 336934354e1..2843e5bbdfb 100644
--- a/compiler/rustc_codegen_cranelift/src/unsize.rs
+++ b/compiler/rustc_codegen_cranelift/src/unsize.rs
@@ -3,6 +3,7 @@
 //! [`PointerCoercion::Unsize`]: `rustc_middle::ty::adjustment::PointerCoercion::Unsize`
 
 use rustc_codegen_ssa::base::validate_trivial_unsize;
+use rustc_middle::ty::layout::HasTypingEnv;
 use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths};
 
 use crate::base::codegen_panic_nounwind;
@@ -23,7 +24,7 @@ pub(crate) fn unsized_info<'tcx>(
     old_info: Option<Value>,
 ) -> Value {
     let (source, target) =
-        fx.tcx.struct_lockstep_tails_for_codegen(source, target, ParamEnv::reveal_all());
+        fx.tcx.struct_lockstep_tails_for_codegen(source, target, fx.typing_env());
     match (&source.kind(), &target.kind()) {
         (&ty::Array(_, len), &ty::Slice(_)) => fx.bcx.ins().iconst(
             fx.pointer_type,
diff --git a/compiler/rustc_codegen_cranelift/src/value_and_place.rs b/compiler/rustc_codegen_cranelift/src/value_and_place.rs
index 900d7e69714..6676e684ca0 100644
--- a/compiler/rustc_codegen_cranelift/src/value_and_place.rs
+++ b/compiler/rustc_codegen_cranelift/src/value_and_place.rs
@@ -4,6 +4,7 @@ use cranelift_codegen::entity::EntityRef;
 use cranelift_codegen::ir::immediates::Offset32;
 use cranelift_frontend::Variable;
 use rustc_middle::ty::FnSig;
+use rustc_middle::ty::layout::HasTypingEnv;
 
 use crate::prelude::*;
 
@@ -884,19 +885,17 @@ pub(crate) fn assert_assignable<'tcx>(
             assert_assignable(fx, *a, *b, limit - 1);
         }
         (ty::FnPtr(..), ty::FnPtr(..)) => {
-            let from_sig = fx.tcx.normalize_erasing_late_bound_regions(
-                ParamEnv::reveal_all(),
-                from_ty.fn_sig(fx.tcx),
-            );
+            let from_sig = fx
+                .tcx
+                .normalize_erasing_late_bound_regions(fx.typing_env(), from_ty.fn_sig(fx.tcx));
             let FnSig {
                 inputs_and_output: types_from,
                 c_variadic: c_variadic_from,
                 safety: unsafety_from,
                 abi: abi_from,
             } = from_sig;
-            let to_sig = fx
-                .tcx
-                .normalize_erasing_late_bound_regions(ParamEnv::reveal_all(), to_ty.fn_sig(fx.tcx));
+            let to_sig =
+                fx.tcx.normalize_erasing_late_bound_regions(fx.typing_env(), to_ty.fn_sig(fx.tcx));
             let FnSig {
                 inputs_and_output: types_to,
                 c_variadic: c_variadic_to,
@@ -932,9 +931,8 @@ pub(crate) fn assert_assignable<'tcx>(
         (&ty::Dynamic(from_traits, _, _from_kind), &ty::Dynamic(to_traits, _, _to_kind)) => {
             // FIXME(dyn-star): Do the right thing with DynKinds
             for (from, to) in from_traits.iter().zip(to_traits) {
-                let from =
-                    fx.tcx.normalize_erasing_late_bound_regions(ParamEnv::reveal_all(), from);
-                let to = fx.tcx.normalize_erasing_late_bound_regions(ParamEnv::reveal_all(), to);
+                let from = fx.tcx.normalize_erasing_late_bound_regions(fx.typing_env(), from);
+                let to = fx.tcx.normalize_erasing_late_bound_regions(fx.typing_env(), to);
                 assert_eq!(
                     from, to,
                     "Can't write trait object of incompatible traits {:?} to place with traits {:?}\n\n{:#?}",
diff --git a/compiler/rustc_codegen_gcc/src/builder.rs b/compiler/rustc_codegen_gcc/src/builder.rs
index e6ae7cf174d..9a142326ad1 100644
--- a/compiler/rustc_codegen_gcc/src/builder.rs
+++ b/compiler/rustc_codegen_gcc/src/builder.rs
@@ -24,9 +24,9 @@ use rustc_data_structures::fx::FxHashSet;
 use rustc_middle::bug;
 use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;
 use rustc_middle::ty::layout::{
-    FnAbiError, FnAbiOfHelpers, FnAbiRequest, HasParamEnv, HasTyCtxt, LayoutError, LayoutOfHelpers,
+    FnAbiError, FnAbiOfHelpers, FnAbiRequest, HasTyCtxt, HasTypingEnv, LayoutError, LayoutOfHelpers,
 };
-use rustc_middle::ty::{Instance, ParamEnv, Ty, TyCtxt};
+use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
 use rustc_span::Span;
 use rustc_span::def_id::DefId;
 use rustc_target::abi::call::FnAbi;
@@ -2319,9 +2319,9 @@ impl<'a, 'gcc, 'tcx> StaticBuilderMethods for Builder<'a, 'gcc, 'tcx> {
     }
 }
 
-impl<'tcx> HasParamEnv<'tcx> for Builder<'_, '_, 'tcx> {
-    fn param_env(&self) -> ParamEnv<'tcx> {
-        self.cx.param_env()
+impl<'tcx> HasTypingEnv<'tcx> for Builder<'_, '_, 'tcx> {
+    fn typing_env(&self) -> ty::TypingEnv<'tcx> {
+        self.cx.typing_env()
     }
 }
 
diff --git a/compiler/rustc_codegen_gcc/src/consts.rs b/compiler/rustc_codegen_gcc/src/consts.rs
index 07c7a54de1c..6dc2f4ed668 100644
--- a/compiler/rustc_codegen_gcc/src/consts.rs
+++ b/compiler/rustc_codegen_gcc/src/consts.rs
@@ -215,7 +215,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
         let gcc_type = if nested {
             self.type_i8()
         } else {
-            let ty = instance.ty(self.tcx, ty::ParamEnv::reveal_all());
+            let ty = instance.ty(self.tcx, ty::TypingEnv::fully_monomorphized());
             self.layout_of(ty).gcc_type(self)
         };
 
diff --git a/compiler/rustc_codegen_gcc/src/context.rs b/compiler/rustc_codegen_gcc/src/context.rs
index 707b35967a6..3846d025537 100644
--- a/compiler/rustc_codegen_gcc/src/context.rs
+++ b/compiler/rustc_codegen_gcc/src/context.rs
@@ -11,10 +11,10 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_middle::mir::mono::CodegenUnit;
 use rustc_middle::span_bug;
 use rustc_middle::ty::layout::{
-    FnAbiError, FnAbiOf, FnAbiOfHelpers, FnAbiRequest, HasParamEnv, HasTyCtxt, LayoutError,
+    FnAbiError, FnAbiOf, FnAbiOfHelpers, FnAbiRequest, HasTyCtxt, HasTypingEnv, LayoutError,
     LayoutOfHelpers,
 };
-use rustc_middle::ty::{self, Instance, ParamEnv, PolyExistentialTraitRef, Ty, TyCtxt};
+use rustc_middle::ty::{self, Instance, PolyExistentialTraitRef, Ty, TyCtxt};
 use rustc_session::Session;
 use rustc_span::source_map::respan;
 use rustc_span::{DUMMY_SP, Span};
@@ -144,7 +144,9 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
         supports_f128_type: bool,
     ) -> Self {
         let create_type = |ctype, rust_type| {
-            let layout = tcx.layout_of(ParamEnv::reveal_all().and(rust_type)).unwrap();
+            let layout = tcx
+                .layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(rust_type))
+                .unwrap();
             let align = layout.align.abi.bytes();
             #[cfg(feature = "master")]
             {
@@ -459,7 +461,7 @@ impl<'gcc, 'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
             Some(def_id) if !wants_msvc_seh(self.sess()) => {
                 let instance = ty::Instance::expect_resolve(
                     tcx,
-                    ty::ParamEnv::reveal_all(),
+                    self.typing_env(),
                     def_id,
                     ty::List::empty(),
                     DUMMY_SP,
@@ -583,9 +585,9 @@ impl<'gcc, 'tcx> FnAbiOfHelpers<'tcx> for CodegenCx<'gcc, 'tcx> {
     }
 }
 
-impl<'tcx, 'gcc> HasParamEnv<'tcx> for CodegenCx<'gcc, 'tcx> {
-    fn param_env(&self) -> ParamEnv<'tcx> {
-        ParamEnv::reveal_all()
+impl<'tcx, 'gcc> HasTypingEnv<'tcx> for CodegenCx<'gcc, 'tcx> {
+    fn typing_env(&self) -> ty::TypingEnv<'tcx> {
+        ty::TypingEnv::fully_monomorphized()
     }
 }
 
diff --git a/compiler/rustc_codegen_gcc/src/debuginfo.rs b/compiler/rustc_codegen_gcc/src/debuginfo.rs
index 5d8c5c199b1..6aeb656c1ab 100644
--- a/compiler/rustc_codegen_gcc/src/debuginfo.rs
+++ b/compiler/rustc_codegen_gcc/src/debuginfo.rs
@@ -113,15 +113,15 @@ fn make_mir_scope<'gcc, 'tcx>(
     let scope_data = &mir.source_scopes[scope];
     let parent_scope = if let Some(parent) = scope_data.parent_scope {
         make_mir_scope(cx, _instance, mir, variables, debug_context, instantiated, parent);
-        debug_context.scopes[parent]
+        debug_context.scopes[parent].unwrap()
     } else {
         // The root is the function itself.
         let file = cx.sess().source_map().lookup_source_file(mir.span.lo());
-        debug_context.scopes[scope] = DebugScope {
+        debug_context.scopes[scope] = Some(DebugScope {
             file_start_pos: file.start_pos,
             file_end_pos: file.end_position(),
-            ..debug_context.scopes[scope]
-        };
+            ..debug_context.scopes[scope].unwrap()
+        });
         instantiated.insert(scope);
         return;
     };
@@ -130,7 +130,7 @@ fn make_mir_scope<'gcc, 'tcx>(
         if !vars.contains(scope) && scope_data.inlined.is_none() {
             // Do not create a DIScope if there are no variables defined in this
             // MIR `SourceScope`, and it's not `inlined`, to avoid debuginfo bloat.
-            debug_context.scopes[scope] = parent_scope;
+            debug_context.scopes[scope] = Some(parent_scope);
             instantiated.insert(scope);
             return;
         }
@@ -157,12 +157,12 @@ fn make_mir_scope<'gcc, 'tcx>(
     // TODO(tempdragon): dbg_scope: Add support for scope extension here.
     inlined_at.or(p_inlined_at);
 
-    debug_context.scopes[scope] = DebugScope {
+    debug_context.scopes[scope] = Some(DebugScope {
         dbg_scope,
         inlined_at,
         file_start_pos: loc.file.start_pos,
         file_end_pos: loc.file.end_position(),
-    };
+    });
     instantiated.insert(scope);
 }
 
@@ -232,12 +232,12 @@ impl<'gcc, 'tcx> DebugInfoCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
         }
 
         // Initialize fn debug context (including scopes).
-        let empty_scope = DebugScope {
+        let empty_scope = Some(DebugScope {
             dbg_scope: self.dbg_scope_fn(instance, fn_abi, Some(llfn)),
             inlined_at: None,
             file_start_pos: BytePos(0),
             file_end_pos: BytePos(0),
-        };
+        });
         let mut fn_debug_context = FunctionDebugContext {
             scopes: IndexVec::from_elem(empty_scope, mir.source_scopes.as_slice()),
             inlined_function_scopes: Default::default(),
diff --git a/compiler/rustc_codegen_gcc/src/int.rs b/compiler/rustc_codegen_gcc/src/int.rs
index 5ca440f4c9b..02b760dc733 100644
--- a/compiler/rustc_codegen_gcc/src/int.rs
+++ b/compiler/rustc_codegen_gcc/src/int.rs
@@ -5,7 +5,7 @@
 use gccjit::{BinaryOp, ComparisonOp, FunctionType, Location, RValue, ToRValue, Type, UnaryOp};
 use rustc_codegen_ssa::common::{IntPredicate, TypeKind};
 use rustc_codegen_ssa::traits::{BackendTypes, BaseTypeCodegenMethods, BuilderMethods, OverflowOp};
-use rustc_middle::ty::{ParamEnv, Ty};
+use rustc_middle::ty::{self, Ty};
 use rustc_target::abi::Endian;
 use rustc_target::abi::call::{ArgAbi, ArgAttributes, Conv, FnAbi, PassMode};
 use rustc_target::spec;
@@ -380,7 +380,10 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
         let overflow_field = self.context.new_field(self.location, self.bool_type, "overflow");
 
         let ret_ty = Ty::new_tup(self.tcx, &[self.tcx.types.i128, self.tcx.types.bool]);
-        let layout = self.tcx.layout_of(ParamEnv::reveal_all().and(ret_ty)).unwrap();
+        let layout = self
+            .tcx
+            .layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(ret_ty))
+            .unwrap();
 
         let arg_abi = ArgAbi { layout, mode: PassMode::Direct(ArgAttributes::new()) };
         let mut fn_abi = FnAbi {
diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs
index 225f294e1e4..69326f409bb 100644
--- a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs
+++ b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs
@@ -21,7 +21,7 @@ use rustc_codegen_ssa::traits::{BaseTypeCodegenMethods, MiscCodegenMethods};
 use rustc_middle::bug;
 use rustc_middle::ty::layout::LayoutOf;
 #[cfg(feature = "master")]
-use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt};
+use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, HasTypingEnv};
 use rustc_middle::ty::{self, Instance, Ty};
 use rustc_span::{Span, Symbol, sym};
 use rustc_target::abi::HasDataLayout;
@@ -107,7 +107,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc
         span: Span,
     ) -> Result<(), Instance<'tcx>> {
         let tcx = self.tcx;
-        let callee_ty = instance.ty(tcx, ty::ParamEnv::reveal_all());
+        let callee_ty = instance.ty(tcx, self.typing_env());
 
         let (def_id, fn_args) = match *callee_ty.kind() {
             ty::FnDef(def_id, fn_args) => (def_id, fn_args),
@@ -115,7 +115,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc
         };
 
         let sig = callee_ty.fn_sig(tcx);
-        let sig = tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), sig);
+        let sig = tcx.normalize_erasing_late_bound_regions(self.typing_env(), sig);
         let arg_tys = sig.inputs();
         let ret_ty = sig.output();
         let name = tcx.item_name(def_id);
diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs b/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs
index 43dbfafa871..604678a9af4 100644
--- a/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs
+++ b/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs
@@ -55,8 +55,10 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
     }
 
     let tcx = bx.tcx();
-    let sig =
-        tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), callee_ty.fn_sig(tcx));
+    let sig = tcx.normalize_erasing_late_bound_regions(
+        ty::TypingEnv::fully_monomorphized(),
+        callee_ty.fn_sig(tcx),
+    );
     let arg_tys = sig.inputs();
 
     if name == sym::simd_select_bitmask {
@@ -478,7 +480,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
         match *in_elem.kind() {
             ty::RawPtr(p_ty, _) => {
                 let metadata = p_ty.ptr_metadata_ty(bx.tcx, |ty| {
-                    bx.tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), ty)
+                    bx.tcx.normalize_erasing_regions(ty::TypingEnv::fully_monomorphized(), ty)
                 });
                 require!(metadata.is_unit(), InvalidMonomorphization::CastWidePointer {
                     span,
@@ -493,7 +495,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
         match *out_elem.kind() {
             ty::RawPtr(p_ty, _) => {
                 let metadata = p_ty.ptr_metadata_ty(bx.tcx, |ty| {
-                    bx.tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), ty)
+                    bx.tcx.normalize_erasing_regions(ty::TypingEnv::fully_monomorphized(), ty)
                 });
                 require!(metadata.is_unit(), InvalidMonomorphization::CastWidePointer {
                     span,
diff --git a/compiler/rustc_codegen_gcc/src/mono_item.rs b/compiler/rustc_codegen_gcc/src/mono_item.rs
index b7b282bf2a6..239902df7f0 100644
--- a/compiler/rustc_codegen_gcc/src/mono_item.rs
+++ b/compiler/rustc_codegen_gcc/src/mono_item.rs
@@ -6,7 +6,7 @@ use rustc_hir::def_id::{DefId, LOCAL_CRATE};
 use rustc_middle::bug;
 use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use rustc_middle::mir::mono::{Linkage, Visibility};
-use rustc_middle::ty::layout::{FnAbiOf, LayoutOf};
+use rustc_middle::ty::layout::{FnAbiOf, HasTypingEnv, LayoutOf};
 use rustc_middle::ty::{self, Instance, TypeVisitableExt};
 
 use crate::context::CodegenCx;
@@ -27,11 +27,8 @@ impl<'gcc, 'tcx> PreDefineCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
         let DefKind::Static { nested, .. } = self.tcx.def_kind(def_id) else { bug!() };
         // Nested statics do not have a type, so pick a dummy type and let `codegen_static` figure out
         // the gcc type from the actual evaluated initializer.
-        let ty = if nested {
-            self.tcx.types.unit
-        } else {
-            instance.ty(self.tcx, ty::ParamEnv::reveal_all())
-        };
+        let ty =
+            if nested { self.tcx.types.unit } else { instance.ty(self.tcx, self.typing_env()) };
         let gcc_type = self.layout_of(ty).gcc_type(self);
 
         let is_tls = attrs.flags.contains(CodegenFnAttrFlags::THREAD_LOCAL);
diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs
index ac76b781218..b5bb7630ca6 100644
--- a/compiler/rustc_codegen_llvm/src/builder.rs
+++ b/compiler/rustc_codegen_llvm/src/builder.rs
@@ -14,7 +14,7 @@ use rustc_data_structures::small_c_str::SmallCStr;
 use rustc_hir::def_id::DefId;
 use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;
 use rustc_middle::ty::layout::{
-    FnAbiError, FnAbiOfHelpers, FnAbiRequest, HasParamEnv, LayoutError, LayoutOfHelpers,
+    FnAbiError, FnAbiOfHelpers, FnAbiRequest, HasTypingEnv, LayoutError, LayoutOfHelpers,
     TyAndLayout,
 };
 use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
@@ -81,9 +81,9 @@ impl<'tcx> ty::layout::HasTyCtxt<'tcx> for Builder<'_, '_, 'tcx> {
     }
 }
 
-impl<'tcx> ty::layout::HasParamEnv<'tcx> for Builder<'_, '_, 'tcx> {
-    fn param_env(&self) -> ty::ParamEnv<'tcx> {
-        self.cx.param_env()
+impl<'tcx> ty::layout::HasTypingEnv<'tcx> for Builder<'_, '_, 'tcx> {
+    fn typing_env(&self) -> ty::TypingEnv<'tcx> {
+        self.cx.typing_env()
     }
 }
 
@@ -472,7 +472,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
     #[instrument(level = "trace", skip(self))]
     fn load_operand(&mut self, place: PlaceRef<'tcx, &'ll Value>) -> OperandRef<'tcx, &'ll Value> {
         if place.layout.is_unsized() {
-            let tail = self.tcx.struct_tail_for_codegen(place.layout.ty, self.param_env());
+            let tail = self.tcx.struct_tail_for_codegen(place.layout.ty, self.typing_env());
             if matches!(tail.kind(), ty::Foreign(..)) {
                 // Unsized locals and, at least conceptually, even unsized arguments must be copied
                 // around, which requires dynamically determining their size. Therefore, we cannot
diff --git a/compiler/rustc_codegen_llvm/src/callee.rs b/compiler/rustc_codegen_llvm/src/callee.rs
index dcea9d3b391..e0a2de3366c 100644
--- a/compiler/rustc_codegen_llvm/src/callee.rs
+++ b/compiler/rustc_codegen_llvm/src/callee.rs
@@ -5,7 +5,7 @@
 //! closure.
 
 use rustc_codegen_ssa::common;
-use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt};
+use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, HasTypingEnv};
 use rustc_middle::ty::{self, Instance, TypeVisitableExt};
 use tracing::debug;
 
@@ -28,12 +28,7 @@ pub(crate) fn get_fn<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'t
     }
 
     let sym = tcx.symbol_name(instance).name;
-    debug!(
-        "get_fn({:?}: {:?}) => {}",
-        instance,
-        instance.ty(cx.tcx(), ty::ParamEnv::reveal_all()),
-        sym
-    );
+    debug!("get_fn({:?}: {:?}) => {}", instance, instance.ty(cx.tcx(), cx.typing_env()), sym);
 
     let fn_abi = cx.fn_abi_of_instance(instance, ty::List::empty());
 
diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs
index 7ab4f45cd73..6f5ffbb4b34 100644
--- a/compiler/rustc_codegen_llvm/src/consts.rs
+++ b/compiler/rustc_codegen_llvm/src/consts.rs
@@ -13,8 +13,8 @@ use rustc_middle::mir::interpret::{
     read_target_uint,
 };
 use rustc_middle::mir::mono::MonoItem;
-use rustc_middle::ty::layout::LayoutOf;
-use rustc_middle::ty::{self, Instance};
+use rustc_middle::ty::Instance;
+use rustc_middle::ty::layout::{HasTypingEnv, LayoutOf};
 use rustc_middle::{bug, span_bug};
 use rustc_session::config::Lto;
 use tracing::{debug, instrument, trace};
@@ -244,7 +244,7 @@ impl<'ll> CodegenCx<'ll, '_> {
         let llty = if nested {
             self.type_i8()
         } else {
-            let ty = instance.ty(self.tcx, ty::ParamEnv::reveal_all());
+            let ty = instance.ty(self.tcx, self.typing_env());
             trace!(?ty);
             self.layout_of(ty).llvm_type(self)
         };
diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs
index 3a7c7efe03b..841c110b3c8 100644
--- a/compiler/rustc_codegen_llvm/src/context.rs
+++ b/compiler/rustc_codegen_llvm/src/context.rs
@@ -15,7 +15,7 @@ use rustc_hir::def_id::DefId;
 use rustc_middle::middle::codegen_fn_attrs::PatchableFunctionEntry;
 use rustc_middle::mir::mono::CodegenUnit;
 use rustc_middle::ty::layout::{
-    FnAbiError, FnAbiOfHelpers, FnAbiRequest, HasParamEnv, LayoutError, LayoutOfHelpers,
+    FnAbiError, FnAbiOfHelpers, FnAbiRequest, HasTypingEnv, LayoutError, LayoutOfHelpers,
 };
 use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
 use rustc_middle::{bug, span_bug};
@@ -658,7 +658,7 @@ impl<'ll, 'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> {
         let llfn = match tcx.lang_items().eh_personality() {
             Some(def_id) if name.is_none() => self.get_fn_addr(ty::Instance::expect_resolve(
                 tcx,
-                ty::ParamEnv::reveal_all(),
+                self.typing_env(),
                 def_id,
                 ty::List::empty(),
                 DUMMY_SP,
@@ -1162,9 +1162,9 @@ impl<'tcx> ty::layout::HasTyCtxt<'tcx> for CodegenCx<'_, 'tcx> {
     }
 }
 
-impl<'tcx, 'll> HasParamEnv<'tcx> for CodegenCx<'ll, 'tcx> {
-    fn param_env(&self) -> ty::ParamEnv<'tcx> {
-        ty::ParamEnv::reveal_all()
+impl<'tcx, 'll> HasTypingEnv<'tcx> for CodegenCx<'ll, 'tcx> {
+    fn typing_env(&self) -> ty::TypingEnv<'tcx> {
+        ty::TypingEnv::fully_monomorphized()
     }
 }
 
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs b/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs
index 0f1909486ec..07bd0f4d1c1 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs
@@ -6,10 +6,10 @@ use rustc_data_structures::fx::FxHashMap;
 use rustc_index::Idx;
 use rustc_index::bit_set::BitSet;
 use rustc_middle::mir::{Body, SourceScope};
-use rustc_middle::ty::layout::FnAbiOf;
+use rustc_middle::ty::layout::{FnAbiOf, HasTypingEnv};
 use rustc_middle::ty::{self, Instance};
 use rustc_session::config::DebugInfo;
-use rustc_span::BytePos;
+use rustc_span::{BytePos, hygiene};
 
 use super::metadata::file_metadata;
 use super::utils::DIB;
@@ -85,15 +85,23 @@ fn make_mir_scope<'ll, 'tcx>(
             discriminators,
             parent,
         );
-        debug_context.scopes[parent]
+        if let Some(parent_scope) = debug_context.scopes[parent] {
+            parent_scope
+        } else {
+            // If the parent scope could not be represented then no children
+            // can be either.
+            debug_context.scopes[scope] = None;
+            instantiated.insert(scope);
+            return;
+        }
     } else {
         // The root is the function itself.
         let file = cx.sess().source_map().lookup_source_file(mir.span.lo());
-        debug_context.scopes[scope] = DebugScope {
+        debug_context.scopes[scope] = Some(DebugScope {
             file_start_pos: file.start_pos,
             file_end_pos: file.end_position(),
-            ..debug_context.scopes[scope]
-        };
+            ..debug_context.scopes[scope].unwrap()
+        });
         instantiated.insert(scope);
         return;
     };
@@ -104,7 +112,7 @@ fn make_mir_scope<'ll, 'tcx>(
     {
         // Do not create a DIScope if there are no variables defined in this
         // MIR `SourceScope`, and it's not `inlined`, to avoid debuginfo bloat.
-        debug_context.scopes[scope] = parent_scope;
+        debug_context.scopes[scope] = Some(parent_scope);
         instantiated.insert(scope);
         return;
     }
@@ -118,7 +126,7 @@ fn make_mir_scope<'ll, 'tcx>(
             // if this is moved to `rustc_codegen_ssa::mir::debuginfo`.
             let callee = cx.tcx.instantiate_and_normalize_erasing_regions(
                 instance.args,
-                ty::ParamEnv::reveal_all(),
+                cx.typing_env(),
                 ty::EarlyBinder::bind(callee),
             );
             debug_context.inlined_function_scopes.entry(callee).or_insert_with(|| {
@@ -137,14 +145,20 @@ fn make_mir_scope<'ll, 'tcx>(
         },
     };
 
-    let inlined_at = scope_data.inlined.map(|(_, callsite_span)| {
-        // FIXME(eddyb) this doesn't account for the macro-related
-        // `Span` fixups that `rustc_codegen_ssa::mir::debuginfo` does.
+    let mut debug_scope = Some(DebugScope {
+        dbg_scope,
+        inlined_at: parent_scope.inlined_at,
+        file_start_pos: loc.file.start_pos,
+        file_end_pos: loc.file.end_position(),
+    });
+
+    if let Some((_, callsite_span)) = scope_data.inlined {
+        let callsite_span = hygiene::walk_chain_collapsed(callsite_span, mir.span);
         let callsite_scope = parent_scope.adjust_dbg_scope_for_span(cx, callsite_span);
         let loc = cx.dbg_loc(callsite_scope, parent_scope.inlined_at, callsite_span);
 
         // NB: In order to produce proper debug info for variables (particularly
-        // arguments) in multiply-inline functions, LLVM expects to see a single
+        // arguments) in multiply-inlined functions, LLVM expects to see a single
         // DILocalVariable with multiple different DILocations in the IR. While
         // the source information for each DILocation would be identical, their
         // inlinedAt attributes will be unique to the particular callsite.
@@ -152,7 +166,7 @@ fn make_mir_scope<'ll, 'tcx>(
         // We generate DILocations here based on the callsite's location in the
         // source code. A single location in the source code usually can't
         // produce multiple distinct calls so this mostly works, until
-        // proc-macros get involved. A proc-macro can generate multiple calls
+        // macros get involved. A macro can generate multiple calls
         // at the same span, which breaks the assumption that we're going to
         // produce a unique DILocation for every scope we process here. We
         // have to explicitly add discriminators if we see inlines into the
@@ -161,24 +175,29 @@ fn make_mir_scope<'ll, 'tcx>(
         // Note further that we can't key this hashtable on the span itself,
         // because these spans could have distinct SyntaxContexts. We have
         // to key on exactly what we're giving to LLVM.
-        match discriminators.entry(callsite_span.lo()) {
+        let inlined_at = match discriminators.entry(callsite_span.lo()) {
             Entry::Occupied(mut o) => {
                 *o.get_mut() += 1;
                 unsafe { llvm::LLVMRustDILocationCloneWithBaseDiscriminator(loc, *o.get()) }
-                    .expect("Failed to encode discriminator in DILocation")
             }
             Entry::Vacant(v) => {
                 v.insert(0);
-                loc
+                Some(loc)
+            }
+        };
+        match inlined_at {
+            Some(inlined_at) => {
+                debug_scope.as_mut().unwrap().inlined_at = Some(inlined_at);
+            }
+            None => {
+                // LLVM has a maximum discriminator that it can encode (currently
+                // it uses 12 bits for 4096 possible values). If we exceed that
+                // there is little we can do but drop the debug info.
+                debug_scope = None;
             }
         }
-    });
+    }
 
-    debug_context.scopes[scope] = DebugScope {
-        dbg_scope,
-        inlined_at: inlined_at.or(parent_scope.inlined_at),
-        file_start_pos: loc.file.start_pos,
-        file_end_pos: loc.file.end_position(),
-    };
+    debug_context.scopes[scope] = debug_scope;
     instantiated.insert(scope);
 }
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
index 151923a3bd2..ef16e5bb459 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
@@ -11,10 +11,9 @@ use rustc_codegen_ssa::traits::*;
 use rustc_hir::def::{CtorKind, DefKind};
 use rustc_hir::def_id::{DefId, LOCAL_CRATE};
 use rustc_middle::bug;
-use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
+use rustc_middle::ty::layout::{HasTypingEnv, LayoutOf, TyAndLayout};
 use rustc_middle::ty::{
-    self, AdtKind, CoroutineArgsExt, Instance, ParamEnv, PolyExistentialTraitRef, Ty, TyCtxt,
-    Visibility,
+    self, AdtKind, CoroutineArgsExt, Instance, PolyExistentialTraitRef, Ty, TyCtxt, Visibility,
 };
 use rustc_session::config::{self, DebugInfo, Lto};
 use rustc_span::symbol::Symbol;
@@ -301,9 +300,8 @@ fn build_subroutine_type_di_node<'ll, 'tcx>(
         .insert(unique_type_id, recursion_marker_type_di_node(cx));
 
     let fn_ty = unique_type_id.expect_ty();
-    let signature = cx
-        .tcx
-        .normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), fn_ty.fn_sig(cx.tcx));
+    let signature =
+        cx.tcx.normalize_erasing_late_bound_regions(cx.typing_env(), fn_ty.fn_sig(cx.tcx));
 
     let signature_di_nodes: SmallVec<_> = iter::once(
         // return type
@@ -1109,9 +1107,7 @@ fn build_upvar_field_di_nodes<'ll, 'tcx>(
         }
     };
 
-    assert!(
-        up_var_tys.iter().all(|t| t == cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), t))
-    );
+    assert!(up_var_tys.iter().all(|t| t == cx.tcx.normalize_erasing_regions(cx.typing_env(), t)));
 
     let capture_names = cx.tcx.closure_saved_names_of_captured_variables(def_id);
     let layout = cx.layout_of(closure_or_coroutine_ty);
@@ -1272,8 +1268,7 @@ fn build_generic_type_param_di_nodes<'ll, 'tcx>(
             let template_params: SmallVec<_> = iter::zip(args, names)
                 .filter_map(|(kind, name)| {
                     kind.as_type().map(|ty| {
-                        let actual_type =
-                            cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), ty);
+                        let actual_type = cx.tcx.normalize_erasing_regions(cx.typing_env(), ty);
                         let actual_type_di_node = type_di_node(cx, actual_type);
                         let name = name.as_str();
                         unsafe {
@@ -1341,7 +1336,7 @@ pub(crate) fn build_global_var_di_node<'ll>(
     if nested {
         return;
     }
-    let variable_type = Instance::mono(cx.tcx, def_id).ty(cx.tcx, ty::ParamEnv::reveal_all());
+    let variable_type = Instance::mono(cx.tcx, def_id).ty(cx.tcx, cx.typing_env());
     let type_di_node = type_di_node(cx, variable_type);
     let var_name = tcx.item_name(def_id);
     let var_name = var_name.as_str();
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs
index 5120b63d173..4e461476040 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs
@@ -6,7 +6,7 @@ use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_macros::HashStable;
 use rustc_middle::bug;
-use rustc_middle::ty::{ParamEnv, PolyExistentialTraitRef, Ty, TyCtxt};
+use rustc_middle::ty::{self, PolyExistentialTraitRef, Ty, TyCtxt};
 
 use super::{SmallVec, UNKNOWN_LINE_NUMBER, unknown_file_metadata};
 use crate::common::{AsCCharPtr, CodegenCx};
@@ -49,12 +49,15 @@ pub(super) enum UniqueTypeId<'tcx> {
 
 impl<'tcx> UniqueTypeId<'tcx> {
     pub(crate) fn for_ty(tcx: TyCtxt<'tcx>, t: Ty<'tcx>) -> Self {
-        assert_eq!(t, tcx.normalize_erasing_regions(ParamEnv::reveal_all(), t));
+        assert_eq!(t, tcx.normalize_erasing_regions(ty::TypingEnv::fully_monomorphized(), t));
         UniqueTypeId::Ty(t, private::HiddenZst)
     }
 
     pub(crate) fn for_enum_variant_part(tcx: TyCtxt<'tcx>, enum_ty: Ty<'tcx>) -> Self {
-        assert_eq!(enum_ty, tcx.normalize_erasing_regions(ParamEnv::reveal_all(), enum_ty));
+        assert_eq!(
+            enum_ty,
+            tcx.normalize_erasing_regions(ty::TypingEnv::fully_monomorphized(), enum_ty)
+        );
         UniqueTypeId::VariantPart(enum_ty, private::HiddenZst)
     }
 
@@ -63,7 +66,10 @@ impl<'tcx> UniqueTypeId<'tcx> {
         enum_ty: Ty<'tcx>,
         variant_idx: VariantIdx,
     ) -> Self {
-        assert_eq!(enum_ty, tcx.normalize_erasing_regions(ParamEnv::reveal_all(), enum_ty));
+        assert_eq!(
+            enum_ty,
+            tcx.normalize_erasing_regions(ty::TypingEnv::fully_monomorphized(), enum_ty)
+        );
         UniqueTypeId::VariantStructType(enum_ty, variant_idx, private::HiddenZst)
     }
 
@@ -72,7 +78,10 @@ impl<'tcx> UniqueTypeId<'tcx> {
         enum_ty: Ty<'tcx>,
         variant_idx: VariantIdx,
     ) -> Self {
-        assert_eq!(enum_ty, tcx.normalize_erasing_regions(ParamEnv::reveal_all(), enum_ty));
+        assert_eq!(
+            enum_ty,
+            tcx.normalize_erasing_regions(ty::TypingEnv::fully_monomorphized(), enum_ty)
+        );
         UniqueTypeId::VariantStructTypeCppLikeWrapper(enum_ty, variant_idx, private::HiddenZst)
     }
 
@@ -81,10 +90,13 @@ impl<'tcx> UniqueTypeId<'tcx> {
         self_type: Ty<'tcx>,
         implemented_trait: Option<PolyExistentialTraitRef<'tcx>>,
     ) -> Self {
-        assert_eq!(self_type, tcx.normalize_erasing_regions(ParamEnv::reveal_all(), self_type));
+        assert_eq!(
+            self_type,
+            tcx.normalize_erasing_regions(ty::TypingEnv::fully_monomorphized(), self_type)
+        );
         assert_eq!(
             implemented_trait,
-            tcx.normalize_erasing_regions(ParamEnv::reveal_all(), implemented_trait)
+            tcx.normalize_erasing_regions(ty::TypingEnv::fully_monomorphized(), implemented_trait)
         );
         UniqueTypeId::VTableTy(self_type, implemented_trait, private::HiddenZst)
     }
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
index 89492e4b9fe..a8fdfbed592 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
@@ -15,8 +15,8 @@ use rustc_data_structures::unord::UnordMap;
 use rustc_hir::def_id::{DefId, DefIdMap};
 use rustc_index::IndexVec;
 use rustc_middle::mir;
-use rustc_middle::ty::layout::LayoutOf;
-use rustc_middle::ty::{self, GenericArgsRef, Instance, ParamEnv, Ty, TypeVisitableExt};
+use rustc_middle::ty::layout::{HasTypingEnv, LayoutOf};
+use rustc_middle::ty::{self, GenericArgsRef, Instance, Ty, TypeVisitableExt};
 use rustc_session::Session;
 use rustc_session::config::{self, DebugInfo};
 use rustc_span::symbol::Symbol;
@@ -294,12 +294,12 @@ impl<'ll, 'tcx> DebugInfoCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> {
         }
 
         // Initialize fn debug context (including scopes).
-        let empty_scope = DebugScope {
+        let empty_scope = Some(DebugScope {
             dbg_scope: self.dbg_scope_fn(instance, fn_abi, Some(llfn)),
             inlined_at: None,
             file_start_pos: BytePos(0),
             file_end_pos: BytePos(0),
-        };
+        });
         let mut fn_debug_context = FunctionDebugContext {
             scopes: IndexVec::from_elem(empty_scope, &mir.source_scopes),
             inlined_function_scopes: Default::default(),
@@ -344,7 +344,7 @@ impl<'ll, 'tcx> DebugInfoCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> {
 
         type_names::push_generic_params(
             tcx,
-            tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), args),
+            tcx.normalize_erasing_regions(self.typing_env(), args),
             &mut name,
         );
 
@@ -481,8 +481,7 @@ impl<'ll, 'tcx> DebugInfoCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> {
                 iter::zip(args, names)
                     .filter_map(|(kind, name)| {
                         kind.as_type().map(|ty| {
-                            let actual_type =
-                                cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), ty);
+                            let actual_type = cx.tcx.normalize_erasing_regions(cx.typing_env(), ty);
                             let actual_type_metadata = type_di_node(cx, actual_type);
                             let name = name.as_str();
                             unsafe {
@@ -526,7 +525,7 @@ impl<'ll, 'tcx> DebugInfoCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> {
                 if cx.tcx.trait_id_of_impl(impl_def_id).is_none() {
                     let impl_self_ty = cx.tcx.instantiate_and_normalize_erasing_regions(
                         instance.args,
-                        ty::ParamEnv::reveal_all(),
+                        cx.typing_env(),
                         cx.tcx.type_of(impl_def_id),
                     );
 
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/utils.rs b/compiler/rustc_codegen_llvm/src/debuginfo/utils.rs
index 960487ada16..6e841293477 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/utils.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/utils.rs
@@ -1,7 +1,7 @@
 // Utility Functions.
 
 use rustc_hir::def_id::DefId;
-use rustc_middle::ty::layout::{HasParamEnv, LayoutOf};
+use rustc_middle::ty::layout::{HasTypingEnv, LayoutOf};
 use rustc_middle::ty::{self, Ty};
 use tracing::trace;
 
@@ -62,7 +62,7 @@ pub(crate) fn wide_pointer_kind<'ll, 'tcx>(
     cx: &CodegenCx<'ll, 'tcx>,
     pointee_ty: Ty<'tcx>,
 ) -> Option<WidePtrKind> {
-    let pointee_tail_ty = cx.tcx.struct_tail_for_codegen(pointee_ty, cx.param_env());
+    let pointee_tail_ty = cx.tcx.struct_tail_for_codegen(pointee_ty, cx.typing_env());
     let layout = cx.layout_of(pointee_tail_ty);
     trace!(
         "wide_pointer_kind: {:?} has layout {:?} (is_unsized? {})",
diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs
index b56f464975d..da7f94e8cf7 100644
--- a/compiler/rustc_codegen_llvm/src/intrinsic.rs
+++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs
@@ -10,7 +10,7 @@ use rustc_codegen_ssa::mir::place::{PlaceRef, PlaceValue};
 use rustc_codegen_ssa::traits::*;
 use rustc_hir as hir;
 use rustc_middle::mir::BinOp;
-use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, LayoutOf};
+use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, HasTypingEnv, LayoutOf};
 use rustc_middle::ty::{self, GenericArgsRef, Ty};
 use rustc_middle::{bug, span_bug};
 use rustc_span::{Span, Symbol, sym};
@@ -163,14 +163,14 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
         span: Span,
     ) -> Result<(), ty::Instance<'tcx>> {
         let tcx = self.tcx;
-        let callee_ty = instance.ty(tcx, ty::ParamEnv::reveal_all());
+        let callee_ty = instance.ty(tcx, self.typing_env());
 
         let ty::FnDef(def_id, fn_args) = *callee_ty.kind() else {
             bug!("expected fn item type, found {}", callee_ty);
         };
 
         let sig = callee_ty.fn_sig(tcx);
-        let sig = tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), sig);
+        let sig = tcx.normalize_erasing_late_bound_regions(self.typing_env(), sig);
         let arg_tys = sig.inputs();
         let ret_ty = sig.output();
         let name = tcx.item_name(def_id);
@@ -1152,8 +1152,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
     }
 
     let tcx = bx.tcx();
-    let sig =
-        tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), callee_ty.fn_sig(tcx));
+    let sig = tcx.normalize_erasing_late_bound_regions(bx.typing_env(), callee_ty.fn_sig(tcx));
     let arg_tys = sig.inputs();
 
     // Sanity-check: all vector arguments must be immediates.
@@ -2187,7 +2186,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
         match in_elem.kind() {
             ty::RawPtr(p_ty, _) => {
                 let metadata = p_ty.ptr_metadata_ty(bx.tcx, |ty| {
-                    bx.tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), ty)
+                    bx.tcx.normalize_erasing_regions(bx.typing_env(), ty)
                 });
                 require!(metadata.is_unit(), InvalidMonomorphization::CastWidePointer {
                     span,
@@ -2202,7 +2201,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
         match out_elem.kind() {
             ty::RawPtr(p_ty, _) => {
                 let metadata = p_ty.ptr_metadata_ty(bx.tcx, |ty| {
-                    bx.tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), ty)
+                    bx.tcx.normalize_erasing_regions(bx.typing_env(), ty)
                 });
                 require!(metadata.is_unit(), InvalidMonomorphization::CastWidePointer {
                     span,
diff --git a/compiler/rustc_codegen_llvm/src/mono_item.rs b/compiler/rustc_codegen_llvm/src/mono_item.rs
index ea8857b4739..33789c6261f 100644
--- a/compiler/rustc_codegen_llvm/src/mono_item.rs
+++ b/compiler/rustc_codegen_llvm/src/mono_item.rs
@@ -3,7 +3,7 @@ use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{DefId, LOCAL_CRATE};
 use rustc_middle::bug;
 use rustc_middle::mir::mono::{Linkage, Visibility};
-use rustc_middle::ty::layout::{FnAbiOf, LayoutOf};
+use rustc_middle::ty::layout::{FnAbiOf, HasTypingEnv, LayoutOf};
 use rustc_middle::ty::{self, Instance, TypeVisitableExt};
 use rustc_session::config::CrateType;
 use rustc_target::spec::RelocModel;
@@ -26,11 +26,8 @@ impl<'tcx> PreDefineCodegenMethods<'tcx> for CodegenCx<'_, 'tcx> {
         let DefKind::Static { nested, .. } = self.tcx.def_kind(def_id) else { bug!() };
         // Nested statics do not have a type, so pick a dummy type and let `codegen_static` figure
         // out the llvm type from the actual evaluated initializer.
-        let ty = if nested {
-            self.tcx.types.unit
-        } else {
-            instance.ty(self.tcx, ty::ParamEnv::reveal_all())
-        };
+        let ty =
+            if nested { self.tcx.types.unit } else { instance.ty(self.tcx, self.typing_env()) };
         let llty = self.layout_of(ty).llvm_type(self);
 
         let g = self.define_global(symbol_name, llty).unwrap_or_else(|| {
diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
index 850d36872dd..d9152c5d080 100644
--- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
+++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
@@ -595,8 +595,10 @@ pub(crate) fn linking_symbol_name_for_instance_in_crate<'tcx>(
 
     let (conv, args) = instance
         .map(|i| {
-            tcx.fn_abi_of_instance(ty::ParamEnv::reveal_all().and((i, ty::List::empty())))
-                .unwrap_or_else(|_| bug!("fn_abi_of_instance({i:?}) failed"))
+            tcx.fn_abi_of_instance(
+                ty::TypingEnv::fully_monomorphized().as_query_input((i, ty::List::empty())),
+            )
+            .unwrap_or_else(|_| bug!("fn_abi_of_instance({i:?}) failed"))
         })
         .map(|fnabi| (fnabi.conv, &fnabi.args[..]))
         .unwrap_or((Conv::Rust, &[]));
diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs
index ef95ab94062..c8b3b30218a 100644
--- a/compiler/rustc_codegen_ssa/src/base.rs
+++ b/compiler/rustc_codegen_ssa/src/base.rs
@@ -21,7 +21,7 @@ use rustc_middle::middle::{exported_symbols, lang_items};
 use rustc_middle::mir::BinOp;
 use rustc_middle::mir::mono::{CodegenUnit, CodegenUnitNameBuilder, MonoItem};
 use rustc_middle::query::Providers;
-use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, TyAndLayout};
+use rustc_middle::ty::layout::{HasTyCtxt, HasTypingEnv, LayoutOf, TyAndLayout};
 use rustc_middle::ty::{self, Instance, Ty, TyCtxt, TypingMode};
 use rustc_session::Session;
 use rustc_session::config::{self, CrateType, EntryFnType, OptLevel, OutputType};
@@ -165,7 +165,7 @@ fn unsized_info<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
 ) -> Bx::Value {
     let cx = bx.cx();
     let (source, target) =
-        cx.tcx().struct_lockstep_tails_for_codegen(source, target, bx.param_env());
+        cx.tcx().struct_lockstep_tails_for_codegen(source, target, bx.typing_env());
     match (source.kind(), target.kind()) {
         (&ty::Array(_, len), &ty::Slice(_)) => cx.const_usize(
             len.try_to_target_usize(cx.tcx()).expect("expected monomorphic const in codegen"),
@@ -466,10 +466,9 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
         // late-bound regions, since late-bound
         // regions must appear in the argument
         // listing.
-        let main_ret_ty = cx.tcx().normalize_erasing_regions(
-            ty::ParamEnv::reveal_all(),
-            main_ret_ty.no_bound_vars().unwrap(),
-        );
+        let main_ret_ty = cx
+            .tcx()
+            .normalize_erasing_regions(cx.typing_env(), main_ret_ty.no_bound_vars().unwrap());
 
         let Some(llfn) = cx.declare_c_main(llfty) else {
             // FIXME: We should be smart and show a better diagnostic here.
@@ -495,7 +494,7 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
             let start_def_id = cx.tcx().require_lang_item(LangItem::Start, None);
             let start_instance = ty::Instance::expect_resolve(
                 cx.tcx(),
-                ty::ParamEnv::reveal_all(),
+                cx.typing_env(),
                 start_def_id,
                 cx.tcx().mk_args(&[main_ret_ty.into()]),
                 DUMMY_SP,
diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
index 27bc58516c0..6c4f6d37972 100644
--- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
+++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
@@ -21,9 +21,7 @@ use rustc_hir::definitions::{DefPathData, DefPathDataName, DisambiguatedDefPathD
 use rustc_hir::{CoroutineDesugaring, CoroutineKind, CoroutineSource, Mutability};
 use rustc_middle::bug;
 use rustc_middle::ty::layout::{IntegerExt, TyAndLayout};
-use rustc_middle::ty::{
-    self, ExistentialProjection, GenericArgKind, GenericArgsRef, ParamEnv, Ty, TyCtxt,
-};
+use rustc_middle::ty::{self, ExistentialProjection, GenericArgKind, GenericArgsRef, Ty, TyCtxt};
 use smallvec::SmallVec;
 
 use crate::debuginfo::wants_c_like_enum_debuginfo;
@@ -82,7 +80,7 @@ fn push_debuginfo_type_name<'tcx>(
         ty::Adt(def, args) => {
             // `layout_for_cpp_like_fallback` will be `Some` if we want to use the fallback encoding.
             let layout_for_cpp_like_fallback = if cpp_like_debuginfo && def.is_enum() {
-                match tcx.layout_of(ParamEnv::reveal_all().and(t)) {
+                match tcx.layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(t)) {
                     Ok(layout) => {
                         if !wants_c_like_enum_debuginfo(tcx, layout) {
                             Some(layout)
@@ -248,8 +246,10 @@ fn push_debuginfo_type_name<'tcx>(
             };
 
             if let Some(principal) = trait_data.principal() {
-                let principal =
-                    tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), principal);
+                let principal = tcx.normalize_erasing_late_bound_regions(
+                    ty::TypingEnv::fully_monomorphized(),
+                    principal,
+                );
                 push_item_name(tcx, principal.def_id, qualified, output);
                 let principal_has_generic_params =
                     push_generic_params_internal(tcx, principal.args, output, visited);
@@ -350,8 +350,10 @@ fn push_debuginfo_type_name<'tcx>(
                 return;
             }
 
-            let sig =
-                tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), t.fn_sig(tcx));
+            let sig = tcx.normalize_erasing_late_bound_regions(
+                ty::TypingEnv::fully_monomorphized(),
+                t.fn_sig(tcx),
+            );
 
             if cpp_like_debuginfo {
                 // Format as a C++ function pointer: return_type (*)(params...)
@@ -415,7 +417,8 @@ fn push_debuginfo_type_name<'tcx>(
             // In the case of cpp-like debuginfo, the name additionally gets wrapped inside of
             // an artificial `enum2$<>` type, as defined in msvc_enum_fallback().
             if cpp_like_debuginfo && t.is_coroutine() {
-                let ty_and_layout = tcx.layout_of(ParamEnv::reveal_all().and(t)).unwrap();
+                let ty_and_layout =
+                    tcx.layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(t)).unwrap();
                 msvc_enum_fallback(
                     tcx,
                     ty_and_layout,
@@ -529,8 +532,8 @@ pub fn compute_debuginfo_vtable_name<'tcx>(
     }
 
     if let Some(trait_ref) = trait_ref {
-        let trait_ref =
-            tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), trait_ref);
+        let trait_ref = tcx
+            .normalize_erasing_late_bound_regions(ty::TypingEnv::fully_monomorphized(), trait_ref);
         push_item_name(tcx, trait_ref.def_id, true, &mut vtable_name);
         visited.clear();
         push_generic_params_internal(tcx, trait_ref.args, &mut vtable_name, &mut visited);
@@ -639,7 +642,7 @@ fn push_generic_params_internal<'tcx>(
     output: &mut String,
     visited: &mut FxHashSet<Ty<'tcx>>,
 ) -> bool {
-    assert_eq!(args, tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), args));
+    assert_eq!(args, tcx.normalize_erasing_regions(ty::TypingEnv::fully_monomorphized(), args));
     let mut args = args.non_erasable_generics().peekable();
     if args.peek().is_none() {
         return false;
@@ -678,14 +681,14 @@ fn push_const_param<'tcx>(tcx: TyCtxt<'tcx>, ct: ty::Const<'tcx>, output: &mut S
                     // FIXME: directly extract the bits from a valtree instead of evaluating an
                     // already evaluated `Const` in order to get the bits.
                     let bits = ct
-                        .try_to_bits(tcx, ty::ParamEnv::reveal_all())
+                        .try_to_bits(tcx, ty::TypingEnv::fully_monomorphized())
                         .expect("expected monomorphic const in codegen");
                     let val = Integer::from_int_ty(&tcx, *ity).size().sign_extend(bits) as i128;
                     write!(output, "{val}")
                 }
                 ty::Uint(_) => {
                     let val = ct
-                        .try_to_bits(tcx, ty::ParamEnv::reveal_all())
+                        .try_to_bits(tcx, ty::TypingEnv::fully_monomorphized())
                         .expect("expected monomorphic const in codegen");
                     write!(output, "{val}")
                 }
diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs
index 097d37bb70c..e3ed12b5ce6 100644
--- a/compiler/rustc_codegen_ssa/src/mir/block.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/block.rs
@@ -777,7 +777,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
 
             let do_panic = !bx
                 .tcx()
-                .check_validity_requirement((requirement, bx.param_env().and(ty)))
+                .check_validity_requirement((requirement, bx.typing_env().as_query_input(ty)))
                 .expect("expect to have layout during codegen");
 
             let layout = bx.layout_of(ty);
@@ -848,14 +848,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         let (instance, mut llfn) = match *callee.layout.ty.kind() {
             ty::FnDef(def_id, args) => (
                 Some(
-                    ty::Instance::expect_resolve(
-                        bx.tcx(),
-                        ty::ParamEnv::reveal_all(),
-                        def_id,
-                        args,
-                        fn_span,
-                    )
-                    .polymorphize(bx.tcx()),
+                    ty::Instance::expect_resolve(bx.tcx(), bx.typing_env(), def_id, args, fn_span)
+                        .polymorphize(bx.tcx()),
                 ),
                 None,
             ),
@@ -1191,7 +1185,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                     if let ty::FnDef(def_id, args) = *const_.ty().kind() {
                         let instance = ty::Instance::resolve_for_fn_ptr(
                             bx.tcx(),
-                            ty::ParamEnv::reveal_all(),
+                            bx.typing_env(),
                             def_id,
                             args,
                         )
diff --git a/compiler/rustc_codegen_ssa/src/mir/constant.rs b/compiler/rustc_codegen_ssa/src/mir/constant.rs
index 54b9c9cc89f..7676e1e171a 100644
--- a/compiler/rustc_codegen_ssa/src/mir/constant.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/constant.rs
@@ -1,6 +1,6 @@
 use rustc_abi::BackendRepr;
 use rustc_middle::mir::interpret::ErrorHandled;
-use rustc_middle::ty::layout::HasTyCtxt;
+use rustc_middle::ty::layout::{HasTyCtxt, HasTypingEnv};
 use rustc_middle::ty::{self, Ty};
 use rustc_middle::{bug, mir, span_bug};
 
@@ -24,7 +24,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         // `MirUsedCollector` visited all required_consts before codegen began, so if we got here
         // there can be no more constants that fail to evaluate.
         self.monomorphize(constant.const_)
-            .eval(self.cx.tcx(), ty::ParamEnv::reveal_all(), constant.span)
+            .eval(self.cx.tcx(), self.cx.typing_env(), constant.span)
             .expect("erroneous constant missed by mono item collection")
     }
 
@@ -57,7 +57,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
             other => span_bug!(constant.span, "{other:#?}"),
         };
         let uv = self.monomorphize(uv);
-        self.cx.tcx().const_eval_resolve_for_typeck(ty::ParamEnv::reveal_all(), uv, constant.span)
+        self.cx.tcx().const_eval_resolve_for_typeck(self.cx.typing_env(), uv, constant.span)
     }
 
     /// process constant containing SIMD shuffle indices & constant vectors
diff --git a/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs b/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs
index 21d20475408..d4d7f16db55 100644
--- a/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs
@@ -20,7 +20,9 @@ use crate::traits::*;
 
 pub struct FunctionDebugContext<'tcx, S, L> {
     /// Maps from source code to the corresponding debug info scope.
-    pub scopes: IndexVec<mir::SourceScope, DebugScope<S, L>>,
+    /// May be None if the backend is not capable of representing the scope for
+    /// some reason.
+    pub scopes: IndexVec<mir::SourceScope, Option<DebugScope<S, L>>>,
 
     /// Maps from an inlined function to its debug info declaration.
     pub inlined_function_scopes: FxHashMap<Instance<'tcx>, S>,
@@ -231,7 +233,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         &self,
         source_info: mir::SourceInfo,
     ) -> Option<(Bx::DIScope, Option<Bx::DILocation>, Span)> {
-        let scope = &self.debug_context.as_ref()?.scopes[source_info.scope];
+        let scope = &self.debug_context.as_ref()?.scopes[source_info.scope]?;
         let span = hygiene::walk_chain_collapsed(source_info.span, self.mir.span);
         Some((scope.adjust_dbg_scope_for_span(self.cx, span), scope.inlined_at, span))
     }
diff --git a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs
index 2a1b9e28c1e..c35d0b90706 100644
--- a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs
@@ -59,14 +59,14 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         llresult: Bx::Value,
         span: Span,
     ) -> Result<(), ty::Instance<'tcx>> {
-        let callee_ty = instance.ty(bx.tcx(), ty::ParamEnv::reveal_all());
+        let callee_ty = instance.ty(bx.tcx(), bx.typing_env());
 
         let ty::FnDef(def_id, fn_args) = *callee_ty.kind() else {
             bug!("expected fn item type, found {}", callee_ty);
         };
 
         let sig = callee_ty.fn_sig(bx.tcx());
-        let sig = bx.tcx().normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), sig);
+        let sig = bx.tcx().normalize_erasing_late_bound_regions(bx.typing_env(), sig);
         let arg_tys = sig.inputs();
         let ret_ty = sig.output();
         let name = bx.tcx().item_name(def_id);
diff --git a/compiler/rustc_codegen_ssa/src/mir/mod.rs b/compiler/rustc_codegen_ssa/src/mir/mod.rs
index f19e3b72141..0cbc5c45736 100644
--- a/compiler/rustc_codegen_ssa/src/mir/mod.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/mod.rs
@@ -4,7 +4,7 @@ use rustc_index::IndexVec;
 use rustc_index::bit_set::BitSet;
 use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use rustc_middle::mir::{UnwindTerminateReason, traversal};
-use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, TyAndLayout};
+use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, HasTypingEnv, TyAndLayout};
 use rustc_middle::ty::{self, Instance, Ty, TyCtxt, TypeFoldable, TypeVisitableExt};
 use rustc_middle::{bug, mir, span_bug};
 use rustc_target::callconv::{FnAbi, PassMode};
@@ -128,7 +128,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         debug!("monomorphize: self.instance={:?}", self.instance);
         self.instance.instantiate_mir_and_normalize_erasing_regions(
             self.cx.tcx(),
-            ty::ParamEnv::reveal_all(),
+            self.cx.typing_env(),
             ty::EarlyBinder::bind(value),
         )
     }
diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
index 0e1cd662f91..f63b2d139c5 100644
--- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
@@ -474,7 +474,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                             ty::FnDef(def_id, args) => {
                                 let instance = ty::Instance::resolve_for_fn_ptr(
                                     bx.tcx(),
-                                    ty::ParamEnv::reveal_all(),
+                                    bx.typing_env(),
                                     def_id,
                                     args,
                                 )
@@ -709,7 +709,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                     mir::NullOp::OffsetOf(fields) => {
                         let val = bx
                             .tcx()
-                            .offset_of_subfield(bx.param_env(), layout, fields.iter())
+                            .offset_of_subfield(bx.typing_env(), layout, fields.iter())
                             .bytes();
                         bx.cx().const_usize(val)
                     }
@@ -727,7 +727,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
 
             mir::Rvalue::ThreadLocalRef(def_id) => {
                 assert!(bx.cx().tcx().is_static(def_id));
-                let layout = bx.layout_of(bx.cx().tcx().static_ptr_ty(def_id));
+                let layout = bx.layout_of(bx.cx().tcx().static_ptr_ty(def_id, bx.typing_env()));
                 let static_ = if !def_id.is_local() && bx.cx().tcx().needs_thread_local_shim(def_id)
                 {
                     let instance = ty::Instance {
diff --git a/compiler/rustc_codegen_ssa/src/traits/type_.rs b/compiler/rustc_codegen_ssa/src/traits/type_.rs
index 44ba2262149..3810c609fd4 100644
--- a/compiler/rustc_codegen_ssa/src/traits/type_.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/type_.rs
@@ -1,6 +1,6 @@
 use rustc_abi::{AddressSpace, Float, Integer};
 use rustc_middle::bug;
-use rustc_middle::ty::layout::{HasTyCtxt, TyAndLayout};
+use rustc_middle::ty::layout::{HasTyCtxt, HasTypingEnv, TyAndLayout};
 use rustc_middle::ty::{self, Ty};
 use rustc_target::callconv::{ArgAbi, CastTarget, FnAbi, Reg};
 
@@ -41,7 +41,7 @@ pub trait BaseTypeCodegenMethods<'tcx>: BackendTypes {
 }
 
 pub trait DerivedTypeCodegenMethods<'tcx>:
-    BaseTypeCodegenMethods<'tcx> + MiscCodegenMethods<'tcx> + HasTyCtxt<'tcx>
+    BaseTypeCodegenMethods<'tcx> + MiscCodegenMethods<'tcx> + HasTyCtxt<'tcx> + HasTypingEnv<'tcx>
 {
     fn type_int(&self) -> Self::Type {
         match &self.sess().target.c_int_width[..] {
@@ -74,7 +74,7 @@ pub trait DerivedTypeCodegenMethods<'tcx>:
     }
 
     fn type_needs_drop(&self, ty: Ty<'tcx>) -> bool {
-        ty.needs_drop(self.tcx(), ty::ParamEnv::reveal_all())
+        ty.needs_drop(self.tcx(), self.typing_env())
     }
 
     fn type_is_sized(&self, ty: Ty<'tcx>) -> bool {
@@ -86,12 +86,11 @@ pub trait DerivedTypeCodegenMethods<'tcx>:
     }
 
     fn type_has_metadata(&self, ty: Ty<'tcx>) -> bool {
-        let param_env = ty::ParamEnv::reveal_all();
-        if ty.is_sized(self.tcx(), param_env) {
+        if ty.is_sized(self.tcx(), self.param_env()) {
             return false;
         }
 
-        let tail = self.tcx().struct_tail_for_codegen(ty, param_env);
+        let tail = self.tcx().struct_tail_for_codegen(ty, self.typing_env());
         match tail.kind() {
             ty::Foreign(..) => false,
             ty::Str | ty::Slice(..) | ty::Dynamic(..) => true,
@@ -101,7 +100,10 @@ pub trait DerivedTypeCodegenMethods<'tcx>:
 }
 
 impl<'tcx, T> DerivedTypeCodegenMethods<'tcx> for T where
-    Self: BaseTypeCodegenMethods<'tcx> + MiscCodegenMethods<'tcx> + HasTyCtxt<'tcx>
+    Self: BaseTypeCodegenMethods<'tcx>
+        + MiscCodegenMethods<'tcx>
+        + HasTyCtxt<'tcx>
+        + HasTypingEnv<'tcx>
 {
 }
 
diff --git a/compiler/rustc_const_eval/src/check_consts/check.rs b/compiler/rustc_const_eval/src/check_consts/check.rs
index b6664606ef9..8e96d365beb 100644
--- a/compiler/rustc_const_eval/src/check_consts/check.rs
+++ b/compiler/rustc_const_eval/src/check_consts/check.rs
@@ -388,7 +388,7 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> {
             return false;
         }
 
-        let infcx = tcx.infer_ctxt().build(self.body.typing_mode(tcx));
+        let (infcx, param_env) = tcx.infer_ctxt().build_with_typing_env(self.body.typing_env(tcx));
         let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
 
         let body_id = self.body.source.def_id().expect_local();
@@ -398,11 +398,8 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> {
                 ty::BoundConstness::Const
             }
         };
-        let const_conditions = ocx.normalize(
-            &ObligationCause::misc(call_span, body_id),
-            self.param_env,
-            const_conditions,
-        );
+        let const_conditions =
+            ocx.normalize(&ObligationCause::misc(call_span, body_id), param_env, const_conditions);
         ocx.register_obligations(const_conditions.into_iter().map(|(trait_ref, span)| {
             Obligation::new(
                 tcx,
@@ -411,7 +408,7 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> {
                     body_id,
                     ObligationCauseCode::WhereClause(callee, span),
                 ),
-                self.param_env,
+                param_env,
                 trait_ref.to_host_effect_clause(tcx, host_polarity),
             )
         }));
diff --git a/compiler/rustc_const_eval/src/check_consts/mod.rs b/compiler/rustc_const_eval/src/check_consts/mod.rs
index ebdd55a4f70..80d3c6448aa 100644
--- a/compiler/rustc_const_eval/src/check_consts/mod.rs
+++ b/compiler/rustc_const_eval/src/check_consts/mod.rs
@@ -24,17 +24,15 @@ mod resolver;
 pub struct ConstCx<'mir, 'tcx> {
     pub body: &'mir mir::Body<'tcx>,
     pub tcx: TyCtxt<'tcx>,
-    pub param_env: ty::ParamEnv<'tcx>,
+    pub typing_env: ty::TypingEnv<'tcx>,
     pub const_kind: Option<hir::ConstContext>,
 }
 
 impl<'mir, 'tcx> ConstCx<'mir, 'tcx> {
     pub fn new(tcx: TyCtxt<'tcx>, body: &'mir mir::Body<'tcx>) -> Self {
-        let def_id = body.source.def_id().expect_local();
-        let param_env = tcx.param_env(def_id);
-
+        let typing_env = body.typing_env(tcx);
         let const_kind = tcx.hir().body_const_context(body.source.def_id().expect_local());
-        ConstCx { body, tcx, param_env, const_kind }
+        ConstCx { body, tcx, typing_env, const_kind }
     }
 
     pub(crate) fn dcx(&self) -> DiagCtxtHandle<'tcx> {
diff --git a/compiler/rustc_const_eval/src/check_consts/ops.rs b/compiler/rustc_const_eval/src/check_consts/ops.rs
index ca95e42dd2b..8ba6b89aad4 100644
--- a/compiler/rustc_const_eval/src/check_consts/ops.rs
+++ b/compiler/rustc_const_eval/src/check_consts/ops.rs
@@ -120,7 +120,7 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> {
     #[allow(rustc::untranslatable_diagnostic)]
     fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, _: Span) -> Diag<'tcx> {
         let FnCallNonConst { callee, args, span, call_source } = *self;
-        let ConstCx { tcx, param_env, .. } = *ccx;
+        let ConstCx { tcx, typing_env, .. } = *ccx;
         let caller = ccx.def_id();
 
         let diag_trait = |err, self_ty: Ty<'_>, trait_id| {
@@ -146,13 +146,11 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> {
                     }
                 }
                 ty::Adt(..) => {
+                    let (infcx, param_env) = tcx.infer_ctxt().build_with_typing_env(typing_env);
                     let obligation =
                         Obligation::new(tcx, ObligationCause::dummy(), param_env, trait_ref);
-
-                    let infcx = tcx.infer_ctxt().build(ccx.body.typing_mode(tcx));
                     let mut selcx = SelectionContext::new(&infcx);
                     let implsrc = selcx.select(&obligation);
-
                     if let Ok(Some(ImplSource::UserDefined(data))) = implsrc {
                         // FIXME(const_trait_impl) revisit this
                         if !tcx.is_const_trait_impl(data.impl_def_id) {
@@ -166,7 +164,7 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> {
         };
 
         let call_kind =
-            call_kind(tcx, ccx.param_env, callee, args, span, call_source.from_hir_call(), None);
+            call_kind(tcx, ccx.typing_env, callee, args, span, call_source.from_hir_call(), None);
 
         debug!(?call_kind);
 
diff --git a/compiler/rustc_const_eval/src/check_consts/post_drop_elaboration.rs b/compiler/rustc_const_eval/src/check_consts/post_drop_elaboration.rs
index 0173a528c22..f6eb130fbd3 100644
--- a/compiler/rustc_const_eval/src/check_consts/post_drop_elaboration.rs
+++ b/compiler/rustc_const_eval/src/check_consts/post_drop_elaboration.rs
@@ -32,17 +32,15 @@ pub fn checking_enabled(ccx: &ConstCx<'_, '_>) -> bool {
 /// This is separate from the rest of the const checking logic because it must run after drop
 /// elaboration.
 pub fn check_live_drops<'tcx>(tcx: TyCtxt<'tcx>, body: &mir::Body<'tcx>) {
-    let def_id = body.source.def_id().expect_local();
-    let const_kind = tcx.hir().body_const_context(def_id);
-    if const_kind.is_none() {
+    let ccx = ConstCx::new(tcx, body);
+    if ccx.const_kind.is_none() {
         return;
     }
 
-    if tcx.has_attr(def_id, sym::rustc_do_not_const_check) {
+    if tcx.has_attr(body.source.def_id(), sym::rustc_do_not_const_check) {
         return;
     }
 
-    let ccx = ConstCx { body, tcx, const_kind, param_env: tcx.param_env(def_id) };
     if !checking_enabled(&ccx) {
         return;
     }
diff --git a/compiler/rustc_const_eval/src/check_consts/qualifs.rs b/compiler/rustc_const_eval/src/check_consts/qualifs.rs
index 29a08579175..bc416acc58d 100644
--- a/compiler/rustc_const_eval/src/check_consts/qualifs.rs
+++ b/compiler/rustc_const_eval/src/check_consts/qualifs.rs
@@ -106,20 +106,24 @@ impl Qualif for HasMutInterior {
         // Instead we invoke an obligation context manually, and provide the opaque type inference settings
         // that allow the trait solver to just error out instead of cycling.
         let freeze_def_id = cx.tcx.require_lang_item(LangItem::Freeze, Some(cx.body.span));
-
+        // FIXME(#132279): Once we've got a typing mode which reveals opaque types using the HIR
+        // typeck results without causing query cycles, we should use this here instead of defining
+        // opaque types.
+        let typing_env = ty::TypingEnv {
+            typing_mode: ty::TypingMode::analysis_in_body(
+                cx.tcx,
+                cx.body.source.def_id().expect_local(),
+            ),
+            param_env: cx.typing_env.param_env,
+        };
+        let (infcx, param_env) = cx.tcx.infer_ctxt().build_with_typing_env(typing_env);
+        let ocx = ObligationCtxt::new(&infcx);
         let obligation = Obligation::new(
             cx.tcx,
             ObligationCause::dummy_with_span(cx.body.span),
-            cx.param_env,
+            param_env,
             ty::TraitRef::new(cx.tcx, freeze_def_id, [ty::GenericArg::from(ty)]),
         );
-
-        // FIXME(#132279): This should eventually use the already defined hidden types.
-        let infcx = cx.tcx.infer_ctxt().build(ty::TypingMode::analysis_in_body(
-            cx.tcx,
-            cx.body.source.def_id().expect_local(),
-        ));
-        let ocx = ObligationCtxt::new(&infcx);
         ocx.register_obligation(obligation);
         let errors = ocx.select_all_or_error();
         !errors.is_empty()
@@ -156,7 +160,7 @@ impl Qualif for NeedsDrop {
     }
 
     fn in_any_value_of_ty<'tcx>(cx: &ConstCx<'_, 'tcx>, ty: Ty<'tcx>) -> bool {
-        ty.needs_drop(cx.tcx, cx.param_env)
+        ty.needs_drop(cx.tcx, cx.typing_env)
     }
 
     fn in_adt_inherently<'tcx>(
diff --git a/compiler/rustc_const_eval/src/check_consts/resolver.rs b/compiler/rustc_const_eval/src/check_consts/resolver.rs
index 74eb6b37fbb..03624a2ce50 100644
--- a/compiler/rustc_const_eval/src/check_consts/resolver.rs
+++ b/compiler/rustc_const_eval/src/check_consts/resolver.rs
@@ -120,7 +120,10 @@ where
     ///
     /// [rust-lang/unsafe-code-guidelines#134]: https://github.com/rust-lang/unsafe-code-guidelines/issues/134
     fn shared_borrow_allows_mutation(&self, place: mir::Place<'tcx>) -> bool {
-        !place.ty(self.ccx.body, self.ccx.tcx).ty.is_freeze(self.ccx.tcx, self.ccx.param_env)
+        !place
+            .ty(self.ccx.body, self.ccx.tcx)
+            .ty
+            .is_freeze(self.ccx.tcx, self.ccx.typing_env.param_env)
     }
 }
 
diff --git a/compiler/rustc_const_eval/src/const_eval/error.rs b/compiler/rustc_const_eval/src/const_eval/error.rs
index 6686413bf02..1271d9d2d0d 100644
--- a/compiler/rustc_const_eval/src/const_eval/error.rs
+++ b/compiler/rustc_const_eval/src/const_eval/error.rs
@@ -152,13 +152,20 @@ where
             let span = span.substitute_dummy(our_span);
             let err = mk(span, frames);
             let mut err = tcx.dcx().create_err(err);
+            let can_be_spurious = matches!(error, InterpErrorKind::ResourceExhaustion(_));
 
             let msg = error.diagnostic_message();
             error.add_args(&mut err);
 
             // Use *our* span to label the interp error
             err.span_label(our_span, msg);
-            ErrorHandled::Reported(err.emit().into(), span)
+            let g = err.emit();
+            let reported = if can_be_spurious {
+                ReportedErrorInfo::spurious(g)
+            } else {
+                ReportedErrorInfo::from(g)
+            };
+            ErrorHandled::Reported(reported, span)
         }
     }
 }
diff --git a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs
index a430d9dc797..ca3ee6773a0 100644
--- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs
+++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs
@@ -221,7 +221,7 @@ pub(super) fn op_to_const<'tcx>(
                 let pointee_ty = imm.layout.ty.builtin_deref(false).unwrap(); // `false` = no raw ptrs
                 debug_assert!(
                     matches!(
-                        ecx.tcx.struct_tail_for_codegen(pointee_ty, ecx.param_env).kind(),
+                        ecx.tcx.struct_tail_for_codegen(pointee_ty, ecx.typing_env()).kind(),
                         ty::Str | ty::Slice(..),
                     ),
                     "`ConstValue::Slice` is for slice-tailed types only, but got {}",
@@ -280,11 +280,13 @@ pub fn eval_to_const_value_raw_provider<'tcx>(
     // opaque types. This is needed for trivial things like `size_of`, but also for using associated
     // types that are not specified in the opaque type.
     assert_eq!(key.param_env.reveal(), Reveal::All);
+    let typing_env =
+        ty::TypingEnv { typing_mode: ty::TypingMode::PostAnalysis, param_env: key.param_env };
 
     // We call `const_eval` for zero arg intrinsics, too, in order to cache their value.
     // Catch such calls and evaluate them instead of trying to load a constant's MIR.
     if let ty::InstanceKind::Intrinsic(def_id) = key.value.instance.def {
-        let ty = key.value.instance.ty(tcx, key.param_env);
+        let ty = key.value.instance.ty(tcx, typing_env);
         let ty::FnDef(_, args) = ty.kind() else {
             bug!("intrinsic with type {:?}", ty);
         };
diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs
index f12320cb851..19c3195aaa4 100644
--- a/compiler/rustc_const_eval/src/const_eval/machine.rs
+++ b/compiler/rustc_const_eval/src/const_eval/machine.rs
@@ -249,9 +249,10 @@ impl<'tcx> CompileTimeInterpCx<'tcx> {
         } else if self.tcx.is_lang_item(def_id, LangItem::PanicFmt) {
             // For panic_fmt, call const_panic_fmt instead.
             let const_def_id = self.tcx.require_lang_item(LangItem::ConstPanicFmt, None);
+            // FIXME(@lcnr): why does this use an empty env if we've got a `param_env` right here.
             let new_instance = ty::Instance::expect_resolve(
                 *self.tcx,
-                ty::ParamEnv::reveal_all(),
+                ty::TypingEnv::fully_monomorphized(),
                 const_def_id,
                 instance.args,
                 self.cur_span(),
diff --git a/compiler/rustc_const_eval/src/const_eval/valtrees.rs b/compiler/rustc_const_eval/src/const_eval/valtrees.rs
index ea88b2ed22e..64bedea3b3f 100644
--- a/compiler/rustc_const_eval/src/const_eval/valtrees.rs
+++ b/compiler/rustc_const_eval/src/const_eval/valtrees.rs
@@ -2,6 +2,7 @@ use rustc_abi::{BackendRepr, VariantIdx};
 use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_middle::mir::interpret::{EvalToValTreeResult, GlobalId};
 use rustc_middle::ty::layout::{LayoutCx, LayoutOf, TyAndLayout};
+use rustc_middle::ty::solve::Reveal;
 use rustc_middle::ty::{self, ScalarInt, Ty, TyCtxt};
 use rustc_middle::{bug, mir};
 use rustc_span::DUMMY_SP;
@@ -281,8 +282,9 @@ pub fn valtree_to_const_value<'tcx>(
     // the `ValTree` and using `place_projection` and `place_field` to
     // create inner `MPlace`s which are filled recursively.
     // FIXME Does this need an example?
-
     let (param_env, ty) = param_env_ty.into_parts();
+    debug_assert_eq!(param_env.reveal(), Reveal::All);
+    let typing_env = ty::TypingEnv { typing_mode: ty::TypingMode::PostAnalysis, param_env };
 
     match *ty.kind() {
         ty::FnDef(..) => {
@@ -302,11 +304,12 @@ pub fn valtree_to_const_value<'tcx>(
             let mut ecx =
                 mk_eval_cx_to_read_const_val(tcx, DUMMY_SP, param_env, CanAccessMutGlobal::No);
             let imm = valtree_to_ref(&mut ecx, valtree, inner_ty);
-            let imm = ImmTy::from_immediate(imm, tcx.layout_of(param_env_ty).unwrap());
+            let imm =
+                ImmTy::from_immediate(imm, tcx.layout_of(typing_env.as_query_input(ty)).unwrap());
             op_to_const(&ecx, &imm.into(), /* for diagnostics */ false)
         }
         ty::Tuple(_) | ty::Array(_, _) | ty::Adt(..) => {
-            let layout = tcx.layout_of(param_env_ty).unwrap();
+            let layout = tcx.layout_of(typing_env.as_query_input(ty)).unwrap();
             if layout.is_zst() {
                 // Fast path to avoid some allocations.
                 return mir::ConstValue::ZeroSized;
@@ -319,7 +322,7 @@ pub fn valtree_to_const_value<'tcx>(
                 let branches = valtree.unwrap_branch();
                 // Find the non-ZST field. (There can be aligned ZST!)
                 for (i, &inner_valtree) in branches.iter().enumerate() {
-                    let field = layout.field(&LayoutCx::new(tcx, param_env), i);
+                    let field = layout.field(&LayoutCx::new(tcx, typing_env), i);
                     if !field.is_zst() {
                         return valtree_to_const_value(tcx, param_env.and(field.ty), inner_valtree);
                     }
diff --git a/compiler/rustc_const_eval/src/interpret/call.rs b/compiler/rustc_const_eval/src/interpret/call.rs
index ef0902e4226..6cfe4b21907 100644
--- a/compiler/rustc_const_eval/src/interpret/call.rs
+++ b/compiler/rustc_const_eval/src/interpret/call.rs
@@ -215,7 +215,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
                 // Even if `ty` is normalized, the search for the unsized tail will project
                 // to fields, which can yield non-normalized types. So we need to provide a
                 // normalization function.
-                let normalize = |ty| self.tcx.normalize_erasing_regions(self.param_env, ty);
+                let normalize = |ty| self.tcx.normalize_erasing_regions(self.typing_env(), ty);
                 ty.ptr_metadata_ty(*self.tcx, normalize)
             };
             return interp_ok(meta_ty(caller) == meta_ty(callee));
@@ -652,35 +652,35 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
                 };
 
                 // Obtain the underlying trait we are working on, and the adjusted receiver argument.
-                let (trait_, dyn_ty, adjusted_recv) = if let ty::Dynamic(data, _, ty::DynStar) =
-                    receiver_place.layout.ty.kind()
-                {
-                    let recv = self.unpack_dyn_star(&receiver_place, data)?;
+                let (trait_, dyn_ty, adjusted_recv) =
+                    if let ty::Dynamic(data, _, ty::DynStar) = receiver_place.layout.ty.kind() {
+                        let recv = self.unpack_dyn_star(&receiver_place, data)?;
 
-                    (data.principal(), recv.layout.ty, recv.ptr())
-                } else {
-                    // Doesn't have to be a `dyn Trait`, but the unsized tail must be `dyn Trait`.
-                    // (For that reason we also cannot use `unpack_dyn_trait`.)
-                    let receiver_tail =
-                        self.tcx.struct_tail_for_codegen(receiver_place.layout.ty, self.param_env);
-                    let ty::Dynamic(receiver_trait, _, ty::Dyn) = receiver_tail.kind() else {
-                        span_bug!(
-                            self.cur_span(),
-                            "dynamic call on non-`dyn` type {}",
-                            receiver_tail
-                        )
+                        (data.principal(), recv.layout.ty, recv.ptr())
+                    } else {
+                        // Doesn't have to be a `dyn Trait`, but the unsized tail must be `dyn Trait`.
+                        // (For that reason we also cannot use `unpack_dyn_trait`.)
+                        let receiver_tail = self
+                            .tcx
+                            .struct_tail_for_codegen(receiver_place.layout.ty, self.typing_env());
+                        let ty::Dynamic(receiver_trait, _, ty::Dyn) = receiver_tail.kind() else {
+                            span_bug!(
+                                self.cur_span(),
+                                "dynamic call on non-`dyn` type {}",
+                                receiver_tail
+                            )
+                        };
+                        assert!(receiver_place.layout.is_unsized());
+
+                        // Get the required information from the vtable.
+                        let vptr = receiver_place.meta().unwrap_meta().to_pointer(self)?;
+                        let dyn_ty = self.get_ptr_vtable_ty(vptr, Some(receiver_trait))?;
+
+                        // It might be surprising that we use a pointer as the receiver even if this
+                        // is a by-val case; this works because by-val passing of an unsized `dyn
+                        // Trait` to a function is actually desugared to a pointer.
+                        (receiver_trait.principal(), dyn_ty, receiver_place.ptr())
                     };
-                    assert!(receiver_place.layout.is_unsized());
-
-                    // Get the required information from the vtable.
-                    let vptr = receiver_place.meta().unwrap_meta().to_pointer(self)?;
-                    let dyn_ty = self.get_ptr_vtable_ty(vptr, Some(receiver_trait))?;
-
-                    // It might be surprising that we use a pointer as the receiver even if this
-                    // is a by-val case; this works because by-val passing of an unsized `dyn
-                    // Trait` to a function is actually desugared to a pointer.
-                    (receiver_trait.principal(), dyn_ty, receiver_place.ptr())
-                };
 
                 // Now determine the actual method to call. Usually we use the easy way of just
                 // looking up the method at index `idx`.
@@ -704,7 +704,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
 
                     let concrete_method = Instance::expect_resolve_for_vtable(
                         tcx,
-                        self.param_env,
+                        self.typing_env(),
                         def_id,
                         instance.args.rebase_onto(tcx, trait_def_id, concrete_trait_ref.args),
                         self.cur_span(),
diff --git a/compiler/rustc_const_eval/src/interpret/cast.rs b/compiler/rustc_const_eval/src/interpret/cast.rs
index 49559059265..2d1bb5c9551 100644
--- a/compiler/rustc_const_eval/src/interpret/cast.rs
+++ b/compiler/rustc_const_eval/src/interpret/cast.rs
@@ -83,7 +83,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
                     ty::FnDef(def_id, args) => {
                         let instance = ty::Instance::resolve_for_fn_ptr(
                             *self.tcx,
-                            self.param_env,
+                            self.typing_env(),
                             def_id,
                             args,
                         )
@@ -384,7 +384,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
     ) -> InterpResult<'tcx> {
         // A<Struct> -> A<Trait> conversion
         let (src_pointee_ty, dest_pointee_ty) =
-            self.tcx.struct_lockstep_tails_for_codegen(source_ty, cast_ty, self.param_env);
+            self.tcx.struct_lockstep_tails_for_codegen(source_ty, cast_ty, self.typing_env());
 
         match (src_pointee_ty.kind(), dest_pointee_ty.kind()) {
             (&ty::Array(_, length), &ty::Slice(_)) => {
diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs
index ff6d5b28b3b..4f413c84615 100644
--- a/compiler/rustc_const_eval/src/interpret/eval_context.rs
+++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs
@@ -10,9 +10,7 @@ use rustc_middle::query::TyCtxtAt;
 use rustc_middle::ty::layout::{
     self, FnAbiError, FnAbiOfHelpers, FnAbiRequest, LayoutError, LayoutOfHelpers, TyAndLayout,
 };
-use rustc_middle::ty::{
-    self, GenericArgsRef, ParamEnv, Ty, TyCtxt, TypeFoldable, TypingMode, Variance,
-};
+use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt, TypeFoldable, TypingEnv, Variance};
 use rustc_middle::{mir, span_bug};
 use rustc_session::Limit;
 use rustc_span::Span;
@@ -65,12 +63,12 @@ where
     }
 }
 
-impl<'tcx, M> layout::HasParamEnv<'tcx> for InterpCx<'tcx, M>
+impl<'tcx, M> layout::HasTypingEnv<'tcx> for InterpCx<'tcx, M>
 where
     M: Machine<'tcx>,
 {
-    fn param_env(&self) -> ty::ParamEnv<'tcx> {
-        self.param_env
+    fn typing_env(&self) -> ty::TypingEnv<'tcx> {
+        self.typing_env()
     }
 }
 
@@ -116,8 +114,7 @@ impl<'tcx, M: Machine<'tcx>> FnAbiOfHelpers<'tcx> for InterpCx<'tcx, M> {
 /// This test should be symmetric, as it is primarily about layout compatibility.
 pub(super) fn mir_assign_valid_types<'tcx>(
     tcx: TyCtxt<'tcx>,
-    typing_mode: TypingMode<'tcx>,
-    param_env: ParamEnv<'tcx>,
+    typing_env: TypingEnv<'tcx>,
     src: TyAndLayout<'tcx>,
     dest: TyAndLayout<'tcx>,
 ) -> bool {
@@ -125,7 +122,7 @@ pub(super) fn mir_assign_valid_types<'tcx>(
     // all normal lifetimes are erased, higher-ranked types with their
     // late-bound lifetimes are still around and can lead to type
     // differences.
-    if util::relate_types(tcx, typing_mode, param_env, Variance::Covariant, src.ty, dest.ty) {
+    if util::relate_types(tcx, typing_env, Variance::Covariant, src.ty, dest.ty) {
         // Make sure the layout is equal, too -- just to be safe. Miri really
         // needs layout equality. For performance reason we skip this check when
         // the types are equal. Equal types *can* have different layouts when
@@ -145,8 +142,7 @@ pub(super) fn mir_assign_valid_types<'tcx>(
 #[cfg_attr(not(debug_assertions), inline(always))]
 pub(super) fn from_known_layout<'tcx>(
     tcx: TyCtxtAt<'tcx>,
-    typing_mode: TypingMode<'tcx>,
-    param_env: ParamEnv<'tcx>,
+    typing_env: TypingEnv<'tcx>,
     known_layout: Option<TyAndLayout<'tcx>>,
     compute: impl FnOnce() -> InterpResult<'tcx, TyAndLayout<'tcx>>,
 ) -> InterpResult<'tcx, TyAndLayout<'tcx>> {
@@ -155,13 +151,7 @@ pub(super) fn from_known_layout<'tcx>(
         Some(known_layout) => {
             if cfg!(debug_assertions) {
                 let check_layout = compute()?;
-                if !mir_assign_valid_types(
-                    tcx.tcx,
-                    typing_mode,
-                    param_env,
-                    check_layout,
-                    known_layout,
-                ) {
+                if !mir_assign_valid_types(tcx.tcx, typing_env, check_layout, known_layout) {
                     span_bug!(
                         tcx.span,
                         "expected type differs from actual type.\nexpected: {}\nactual: {}",
@@ -211,9 +201,11 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
         }
     }
 
-    pub fn typing_mode(&self) -> TypingMode<'tcx> {
+    /// During CTFE we're always in `PostAnalysis` mode.
+    #[inline(always)]
+    pub fn typing_env(&self) -> ty::TypingEnv<'tcx> {
         debug_assert_eq!(self.param_env.reveal(), Reveal::All);
-        TypingMode::PostAnalysis
+        ty::TypingEnv { typing_mode: ty::TypingMode::PostAnalysis, param_env: self.param_env }
     }
 
     /// Returns the span of the currently executed statement/terminator.
@@ -304,13 +296,13 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
             .instance
             .try_instantiate_mir_and_normalize_erasing_regions(
                 *self.tcx,
-                self.param_env,
+                self.typing_env(),
                 ty::EarlyBinder::bind(value),
             )
             .map_err(|_| ErrorHandled::TooGeneric(self.cur_span()))
     }
 
-    /// The `args` are assumed to already be in our interpreter "universe" (param_env).
+    /// The `args` are assumed to already be in our interpreter "universe".
     pub(super) fn resolve(
         &self,
         def: DefId,
@@ -319,7 +311,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
         trace!("resolve: {:?}, {:#?}", def, args);
         trace!("param_env: {:#?}", self.param_env);
         trace!("args: {:#?}", args);
-        match ty::Instance::try_resolve(*self.tcx, self.param_env, def, args) {
+        match ty::Instance::try_resolve(*self.tcx, self.typing_env(), def, args) {
             Ok(Some(instance)) => interp_ok(instance),
             Ok(None) => throw_inval!(TooGeneric),
 
@@ -328,7 +320,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
         }
     }
 
-    /// Check if the two things are equal in the current param_env, using an infctx to get proper
+    /// Check if the two things are equal in the current param_env, using an infcx to get proper
     /// equality checks.
     #[instrument(level = "trace", skip(self), ret)]
     pub(super) fn eq_in_param_env<T>(&self, a: T, b: T) -> bool
@@ -340,14 +332,14 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
             return true;
         }
         // Slow path: spin up an inference context to check if these traits are sufficiently equal.
-        let infcx = self.tcx.infer_ctxt().build(self.typing_mode());
+        let (infcx, param_env) = self.tcx.infer_ctxt().build_with_typing_env(self.typing_env());
         let ocx = ObligationCtxt::new(&infcx);
         let cause = ObligationCause::dummy_with_span(self.cur_span());
         // equate the two trait refs after normalization
-        let a = ocx.normalize(&cause, self.param_env, a);
-        let b = ocx.normalize(&cause, self.param_env, b);
+        let a = ocx.normalize(&cause, param_env, a);
+        let b = ocx.normalize(&cause, param_env, b);
 
-        if let Err(terr) = ocx.eq(&cause, self.param_env, a, b) {
+        if let Err(terr) = ocx.eq(&cause, param_env, a, b) {
             trace!(?terr);
             return false;
         }
@@ -572,7 +564,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
         let val = if self.tcx.is_static(gid.instance.def_id()) {
             let alloc_id = self.tcx.reserve_and_set_static_alloc(gid.instance.def_id());
 
-            let ty = instance.ty(self.tcx.tcx, self.param_env);
+            let ty = instance.ty(self.tcx.tcx, self.typing_env());
             mir::ConstAlloc { alloc_id, ty }
         } else {
             self.ctfe_query(|tcx| tcx.eval_to_allocation_raw(self.param_env.and(gid)))?
@@ -587,7 +579,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
         layout: Option<TyAndLayout<'tcx>>,
     ) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> {
         M::eval_mir_constant(self, *val, span, layout, |ecx, val, span, layout| {
-            let const_val = val.eval(*ecx.tcx, ecx.param_env, span).map_err(|err| {
+            let const_val = val.eval(*ecx.tcx, ecx.typing_env(), span).map_err(|err| {
                 if M::ALL_CONSTS_ARE_PRECHECKED {
                     match err {
                         ErrorHandled::TooGeneric(..) => {},
@@ -596,6 +588,9 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
                                 // const-eval will return "tainted" errors if e.g. the layout cannot
                                 // be computed as the type references non-existing names.
                                 // See <https://github.com/rust-lang/rust/issues/124348>.
+                            } else if reported.can_be_spurious() {
+                                // These errors can just sometimes happen, even when the expression
+                                // is nominally "infallible", e.g. when running out of memory.
                             } else {
                                 // Looks like the const is not captured by `required_consts`, that's bad.
                                 span_bug!(span, "interpret const eval failure of {val:?} which is not in required_consts");
diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs
index c7a56a80e81..c8859ab3e88 100644
--- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs
+++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs
@@ -40,6 +40,7 @@ pub(crate) fn eval_nullary_intrinsic<'tcx>(
 ) -> InterpResult<'tcx, ConstValue<'tcx>> {
     let tp_ty = args.type_at(0);
     let name = tcx.item_name(def_id);
+    let typing_env = ty::TypingEnv { typing_mode: ty::TypingMode::PostAnalysis, param_env };
     interp_ok(match name {
         sym::type_name => {
             ensure_monomorphic_enough(tcx, tp_ty)?;
@@ -48,11 +49,13 @@ pub(crate) fn eval_nullary_intrinsic<'tcx>(
         }
         sym::needs_drop => {
             ensure_monomorphic_enough(tcx, tp_ty)?;
-            ConstValue::from_bool(tp_ty.needs_drop(tcx, param_env))
+            ConstValue::from_bool(tp_ty.needs_drop(tcx, typing_env))
         }
         sym::pref_align_of => {
             // Correctly handles non-monomorphic calls, so there is no need for ensure_monomorphic_enough.
-            let layout = tcx.layout_of(param_env.and(tp_ty)).map_err(|e| err_inval!(Layout(*e)))?;
+            let layout = tcx
+                .layout_of(typing_env.as_query_input(tp_ty))
+                .map_err(|e| err_inval!(Layout(*e)))?;
             ConstValue::from_target_usize(layout.align.pref.bytes(), &tcx)
         }
         sym::type_id => {
@@ -355,7 +358,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
 
                 let should_panic = !self
                     .tcx
-                    .check_validity_requirement((requirement, self.param_env.and(ty)))
+                    .check_validity_requirement((requirement, self.typing_env().as_query_input(ty)))
                     .map_err(|_| err_inval!(TooGeneric))?;
 
                 if should_panic {
diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs
index 09635c96e57..07566e9fda2 100644
--- a/compiler/rustc_const_eval/src/interpret/memory.rs
+++ b/compiler/rustc_const_eval/src/interpret/memory.rs
@@ -859,7 +859,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
 
         // # Global allocations
         if let Some(global_alloc) = self.tcx.try_get_global_alloc(id) {
-            let (size, align) = global_alloc.size_and_align(*self.tcx, self.param_env);
+            let (size, align) = global_alloc.size_and_align(*self.tcx, self.typing_env());
             let mutbl = global_alloc.mutability(*self.tcx, self.param_env);
             let kind = match global_alloc {
                 GlobalAlloc::Static { .. } | GlobalAlloc::Memory { .. } => AllocKind::LiveData,
diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs
index a130ae89bcb..0157e6c2125 100644
--- a/compiler/rustc_const_eval/src/interpret/operand.rs
+++ b/compiler/rustc_const_eval/src/interpret/operand.rs
@@ -8,7 +8,7 @@ use rustc_abi as abi;
 use rustc_abi::{BackendRepr, HasDataLayout, Size};
 use rustc_hir::def::Namespace;
 use rustc_middle::mir::interpret::ScalarSizeMismatch;
-use rustc_middle::ty::layout::{HasParamEnv, HasTyCtxt, LayoutOf, TyAndLayout};
+use rustc_middle::ty::layout::{HasTyCtxt, HasTypingEnv, LayoutOf, TyAndLayout};
 use rustc_middle::ty::print::{FmtPrinter, PrettyPrinter};
 use rustc_middle::ty::{ConstInt, ScalarInt, Ty, TyCtxt};
 use rustc_middle::{bug, mir, span_bug, ty};
@@ -297,21 +297,25 @@ impl<'tcx, Prov: Provenance> ImmTy<'tcx, Prov> {
 
     #[inline]
     pub fn from_bool(b: bool, tcx: TyCtxt<'tcx>) -> Self {
-        let layout = tcx.layout_of(ty::ParamEnv::reveal_all().and(tcx.types.bool)).unwrap();
+        let layout = tcx
+            .layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(tcx.types.bool))
+            .unwrap();
         Self::from_scalar(Scalar::from_bool(b), layout)
     }
 
     #[inline]
     pub fn from_ordering(c: std::cmp::Ordering, tcx: TyCtxt<'tcx>) -> Self {
         let ty = tcx.ty_ordering_enum(None);
-        let layout = tcx.layout_of(ty::ParamEnv::reveal_all().and(ty)).unwrap();
+        let layout =
+            tcx.layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(ty)).unwrap();
         Self::from_scalar(Scalar::from_i8(c as i8), layout)
     }
 
     pub fn from_pair(a: Self, b: Self, tcx: TyCtxt<'tcx>) -> Self {
         let layout = tcx
             .layout_of(
-                ty::ParamEnv::reveal_all().and(Ty::new_tup(tcx, &[a.layout.ty, b.layout.ty])),
+                ty::TypingEnv::fully_monomorphized()
+                    .as_query_input(Ty::new_tup(tcx, &[a.layout.ty, b.layout.ty])),
             )
             .unwrap();
         Self::from_scalar_pair(a.to_scalar(), b.to_scalar(), layout)
@@ -341,7 +345,7 @@ impl<'tcx, Prov: Provenance> ImmTy<'tcx, Prov> {
 
     #[inline]
     #[cfg_attr(debug_assertions, track_caller)] // only in debug builds due to perf (see #98980)
-    pub fn to_pair(self, cx: &(impl HasTyCtxt<'tcx> + HasParamEnv<'tcx>)) -> (Self, Self) {
+    pub fn to_pair(self, cx: &(impl HasTyCtxt<'tcx> + HasTypingEnv<'tcx>)) -> (Self, Self) {
         let layout = self.layout;
         let (val0, val1) = self.to_scalar_pair();
         (
@@ -773,8 +777,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
                 )?;
             if !mir_assign_valid_types(
                 *self.tcx,
-                self.typing_mode(),
-                self.param_env,
+                self.typing_env(),
                 self.layout_of(normalized_place_ty)?,
                 op.layout,
             ) {
@@ -833,9 +836,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
             })
         };
         let layout =
-            from_known_layout(self.tcx, self.typing_mode(), self.param_env, layout, || {
-                self.layout_of(ty).into()
-            })?;
+            from_known_layout(self.tcx, self.typing_env(), layout, || self.layout_of(ty).into())?;
         let imm = match val_val {
             mir::ConstValue::Indirect { alloc_id, offset } => {
                 // This is const data, no mutation allowed.
diff --git a/compiler/rustc_const_eval/src/interpret/operator.rs b/compiler/rustc_const_eval/src/interpret/operator.rs
index fbc85d37953..201f1b5dc62 100644
--- a/compiler/rustc_const_eval/src/interpret/operator.rs
+++ b/compiler/rustc_const_eval/src/interpret/operator.rs
@@ -533,7 +533,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
             }
             OffsetOf(fields) => {
                 let val =
-                    self.tcx.offset_of_subfield(self.param_env, layout, fields.iter()).bytes();
+                    self.tcx.offset_of_subfield(self.typing_env(), layout, fields.iter()).bytes();
                 ImmTy::from_uint(val, usize_layout())
             }
             UbChecks => ImmTy::from_bool(M::ub_checks(self)?, *self.tcx),
diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs
index cc8d1db6cfb..13fcccca76b 100644
--- a/compiler/rustc_const_eval/src/interpret/place.rs
+++ b/compiler/rustc_const_eval/src/interpret/place.rs
@@ -540,8 +540,7 @@ where
                 )?;
             if !mir_assign_valid_types(
                 *self.tcx,
-                self.typing_mode(),
-                self.param_env,
+                self.typing_env(),
                 self.layout_of(normalized_place_ty)?,
                 place.layout,
             ) {
@@ -871,13 +870,8 @@ where
     ) -> InterpResult<'tcx> {
         // We do NOT compare the types for equality, because well-typed code can
         // actually "transmute" `&mut T` to `&T` in an assignment without a cast.
-        let layout_compat = mir_assign_valid_types(
-            *self.tcx,
-            self.typing_mode(),
-            self.param_env,
-            src.layout(),
-            dest.layout(),
-        );
+        let layout_compat =
+            mir_assign_valid_types(*self.tcx, self.typing_env(), src.layout(), dest.layout());
         if !allow_transmute && !layout_compat {
             span_bug!(
                 self.cur_span(),
diff --git a/compiler/rustc_const_eval/src/interpret/stack.rs b/compiler/rustc_const_eval/src/interpret/stack.rs
index 50c0446b3cd..037c1a233ee 100644
--- a/compiler/rustc_const_eval/src/interpret/stack.rs
+++ b/compiler/rustc_const_eval/src/interpret/stack.rs
@@ -379,7 +379,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
         for &const_ in body.required_consts() {
             let c =
                 self.instantiate_from_current_frame_and_normalize_erasing_regions(const_.const_)?;
-            c.eval(*self.tcx, self.param_env, const_.span).map_err(|err| {
+            c.eval(*self.tcx, self.typing_env(), const_.span).map_err(|err| {
                 err.emit_note(*self.tcx);
                 err
             })?;
@@ -596,13 +596,12 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
             return interp_ok(layout);
         }
 
-        let layout =
-            from_known_layout(self.tcx, self.typing_mode(), self.param_env, layout, || {
-                let local_ty = frame.body.local_decls[local].ty;
-                let local_ty =
-                    self.instantiate_from_frame_and_normalize_erasing_regions(frame, local_ty)?;
-                self.layout_of(local_ty).into()
-            })?;
+        let layout = from_known_layout(self.tcx, self.typing_env(), layout, || {
+            let local_ty = frame.body.local_decls[local].ty;
+            let local_ty =
+                self.instantiate_from_frame_and_normalize_erasing_regions(frame, local_ty)?;
+            self.layout_of(local_ty).into()
+        })?;
 
         // Layouts of locals are requested a lot, so we cache them.
         state.layout.set(Some(layout));
diff --git a/compiler/rustc_const_eval/src/interpret/step.rs b/compiler/rustc_const_eval/src/interpret/step.rs
index 18cff2c5e0f..d4525243642 100644
--- a/compiler/rustc_const_eval/src/interpret/step.rs
+++ b/compiler/rustc_const_eval/src/interpret/step.rs
@@ -418,7 +418,8 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
             .collect::<InterpResult<'tcx, Vec<_>>>()?;
 
         let fn_sig_binder = func.layout.ty.fn_sig(*self.tcx);
-        let fn_sig = self.tcx.normalize_erasing_late_bound_regions(self.param_env, fn_sig_binder);
+        let fn_sig =
+            self.tcx.normalize_erasing_late_bound_regions(self.typing_env(), fn_sig_binder);
         let extra_args = &args[fn_sig.inputs().len()..];
         let extra_args =
             self.tcx.mk_type_list_from_iter(extra_args.iter().map(|arg| arg.layout().ty));
diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs
index 3a68db9f7f7..005b430bc8a 100644
--- a/compiler/rustc_const_eval/src/interpret/validity.rs
+++ b/compiler/rustc_const_eval/src/interpret/validity.rs
@@ -448,7 +448,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> {
         meta: MemPlaceMeta<M::Provenance>,
         pointee: TyAndLayout<'tcx>,
     ) -> InterpResult<'tcx> {
-        let tail = self.ecx.tcx.struct_tail_for_codegen(pointee.ty, self.ecx.param_env);
+        let tail = self.ecx.tcx.struct_tail_for_codegen(pointee.ty, self.ecx.typing_env());
         match tail.kind() {
             ty::Dynamic(data, _, ty::Dyn) => {
                 let vtable = meta.unwrap_meta().to_pointer(self.ecx)?;
@@ -568,7 +568,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> {
                         throw_validation_failure!(self.path, DanglingPtrUseAfterFree { ptr_kind });
                     };
                     let (size, _align) =
-                        global_alloc.size_and_align(*self.ecx.tcx, self.ecx.param_env);
+                        global_alloc.size_and_align(*self.ecx.tcx, self.ecx.typing_env());
 
                     if let GlobalAlloc::Static(did) = global_alloc {
                         let DefKind::Static { nested, .. } = self.ecx.tcx.def_kind(did) else {
@@ -955,7 +955,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> {
     ) -> Cow<'e, RangeSet> {
         assert!(layout.ty.is_union());
         assert!(layout.is_sized(), "there are no unsized unions");
-        let layout_cx = LayoutCx::new(*ecx.tcx, ecx.param_env);
+        let layout_cx = LayoutCx::new(*ecx.tcx, ecx.typing_env());
         return M::cached_union_data_range(ecx, layout.ty, || {
             let mut out = RangeSet(Vec::new());
             union_data_range_uncached(&layout_cx, layout, Size::ZERO, &mut out);
diff --git a/compiler/rustc_const_eval/src/lib.rs b/compiler/rustc_const_eval/src/lib.rs
index 0490195caf4..527236b2c22 100644
--- a/compiler/rustc_const_eval/src/lib.rs
+++ b/compiler/rustc_const_eval/src/lib.rs
@@ -47,7 +47,7 @@ pub fn provide(providers: &mut Providers) {
     providers.hooks.try_destructure_mir_constant_for_user_output =
         const_eval::try_destructure_mir_constant_for_user_output;
     providers.valtree_to_const_val = |tcx, (ty, valtree)| {
-        const_eval::valtree_to_const_value(tcx, ty::ParamEnv::empty().and(ty), valtree)
+        const_eval::valtree_to_const_value(tcx, ty::ParamEnv::reveal_all().and(ty), valtree)
     };
     providers.check_validity_requirement = |tcx, (init_kind, param_env_and_ty)| {
         util::check_validity_requirement(tcx, init_kind, param_env_and_ty)
diff --git a/compiler/rustc_const_eval/src/util/alignment.rs b/compiler/rustc_const_eval/src/util/alignment.rs
index 6fa7d369229..9507b24f603 100644
--- a/compiler/rustc_const_eval/src/util/alignment.rs
+++ b/compiler/rustc_const_eval/src/util/alignment.rs
@@ -9,7 +9,7 @@ use tracing::debug;
 pub fn is_disaligned<'tcx, L>(
     tcx: TyCtxt<'tcx>,
     local_decls: &L,
-    param_env: ty::ParamEnv<'tcx>,
+    typing_env: ty::TypingEnv<'tcx>,
     place: Place<'tcx>,
 ) -> bool
 where
@@ -22,8 +22,8 @@ where
     };
 
     let ty = place.ty(local_decls, tcx).ty;
-    let unsized_tail = || tcx.struct_tail_for_codegen(ty, param_env);
-    match tcx.layout_of(param_env.and(ty)) {
+    let unsized_tail = || tcx.struct_tail_for_codegen(ty, typing_env);
+    match tcx.layout_of(typing_env.as_query_input(ty)) {
         Ok(layout)
             if layout.align.abi <= pack
                 && (layout.is_sized()
diff --git a/compiler/rustc_const_eval/src/util/check_validity_requirement.rs b/compiler/rustc_const_eval/src/util/check_validity_requirement.rs
index f743525f359..1afc910ce8f 100644
--- a/compiler/rustc_const_eval/src/util/check_validity_requirement.rs
+++ b/compiler/rustc_const_eval/src/util/check_validity_requirement.rs
@@ -3,7 +3,7 @@ use rustc_middle::bug;
 use rustc_middle::ty::layout::{
     HasTyCtxt, LayoutCx, LayoutError, LayoutOf, TyAndLayout, ValidityRequirement,
 };
-use rustc_middle::ty::{ParamEnvAnd, Ty, TyCtxt};
+use rustc_middle::ty::{PseudoCanonicalInput, Ty, TyCtxt};
 
 use crate::const_eval::{CanAccessMutGlobal, CheckAlignment, CompileTimeMachine};
 use crate::interpret::{InterpCx, MemoryKind};
@@ -23,16 +23,16 @@ use crate::interpret::{InterpCx, MemoryKind};
 pub fn check_validity_requirement<'tcx>(
     tcx: TyCtxt<'tcx>,
     kind: ValidityRequirement,
-    param_env_and_ty: ParamEnvAnd<'tcx, Ty<'tcx>>,
+    input: PseudoCanonicalInput<'tcx, Ty<'tcx>>,
 ) -> Result<bool, &'tcx LayoutError<'tcx>> {
-    let layout = tcx.layout_of(param_env_and_ty)?;
+    let layout = tcx.layout_of(input)?;
 
     // There is nothing strict or lax about inhabitedness.
     if kind == ValidityRequirement::Inhabited {
         return Ok(!layout.is_uninhabited());
     }
 
-    let layout_cx = LayoutCx::new(tcx, param_env_and_ty.param_env);
+    let layout_cx = LayoutCx::new(tcx, input.typing_env);
     if kind == ValidityRequirement::Uninit || tcx.sess.opts.unstable_opts.strict_init_checks {
         check_validity_requirement_strict(layout, &layout_cx, kind)
     } else {
@@ -49,7 +49,7 @@ fn check_validity_requirement_strict<'tcx>(
 ) -> Result<bool, &'tcx LayoutError<'tcx>> {
     let machine = CompileTimeMachine::new(CanAccessMutGlobal::No, CheckAlignment::Error);
 
-    let mut cx = InterpCx::new(cx.tcx(), rustc_span::DUMMY_SP, cx.param_env, machine);
+    let mut cx = InterpCx::new(cx.tcx(), rustc_span::DUMMY_SP, cx.typing_env.param_env, machine);
 
     let allocated = cx
         .allocate(ty, MemoryKind::Machine(crate::const_eval::MemoryKind::Heap))
diff --git a/compiler/rustc_const_eval/src/util/compare_types.rs b/compiler/rustc_const_eval/src/util/compare_types.rs
index 0cf27d30c36..9eed1a20f15 100644
--- a/compiler/rustc_const_eval/src/util/compare_types.rs
+++ b/compiler/rustc_const_eval/src/util/compare_types.rs
@@ -5,18 +5,17 @@
 
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_middle::traits::ObligationCause;
-use rustc_middle::ty::{ParamEnv, Ty, TyCtxt, TypingMode, Variance};
+use rustc_middle::ty::{Ty, TyCtxt, TypingEnv, Variance};
 use rustc_trait_selection::traits::ObligationCtxt;
 
 /// Returns whether `src` is a subtype of `dest`, i.e. `src <: dest`.
 pub fn sub_types<'tcx>(
     tcx: TyCtxt<'tcx>,
-    typing_mode: TypingMode<'tcx>,
-    param_env: ParamEnv<'tcx>,
+    typing_env: TypingEnv<'tcx>,
     src: Ty<'tcx>,
     dest: Ty<'tcx>,
 ) -> bool {
-    relate_types(tcx, typing_mode, param_env, Variance::Covariant, src, dest)
+    relate_types(tcx, typing_env, Variance::Covariant, src, dest)
 }
 
 /// Returns whether `src` is a subtype of `dest`, i.e. `src <: dest`.
@@ -26,8 +25,7 @@ pub fn sub_types<'tcx>(
 /// because we want to check for type equality.
 pub fn relate_types<'tcx>(
     tcx: TyCtxt<'tcx>,
-    typing_mode: TypingMode<'tcx>,
-    param_env: ParamEnv<'tcx>,
+    typing_env: TypingEnv<'tcx>,
     variance: Variance,
     src: Ty<'tcx>,
     dest: Ty<'tcx>,
@@ -36,8 +34,7 @@ pub fn relate_types<'tcx>(
         return true;
     }
 
-    let mut builder = tcx.infer_ctxt().ignoring_regions();
-    let infcx = builder.build(typing_mode);
+    let (infcx, param_env) = tcx.infer_ctxt().ignoring_regions().build_with_typing_env(typing_env);
     let ocx = ObligationCtxt::new(&infcx);
     let cause = ObligationCause::dummy();
     let src = ocx.normalize(&cause, param_env, src);
diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs
index bede4c49703..65d586124b3 100644
--- a/compiler/rustc_data_structures/src/lib.rs
+++ b/compiler/rustc_data_structures/src/lib.rs
@@ -21,6 +21,7 @@
 #![feature(auto_traits)]
 #![feature(cfg_match)]
 #![feature(core_intrinsics)]
+#![feature(dropck_eyepatch)]
 #![feature(extend_one)]
 #![feature(file_buffered)]
 #![feature(hash_raw_entry)]
@@ -78,6 +79,7 @@ pub mod thinvec;
 pub mod transitive_relation;
 pub mod unhash;
 pub mod unord;
+pub mod vec_cache;
 pub mod work_queue;
 
 mod atomic_ref;
diff --git a/compiler/rustc_data_structures/src/vec_cache.rs b/compiler/rustc_data_structures/src/vec_cache.rs
new file mode 100644
index 00000000000..eb251b587c8
--- /dev/null
+++ b/compiler/rustc_data_structures/src/vec_cache.rs
@@ -0,0 +1,324 @@
+//! VecCache maintains a mapping from K -> (V, I) pairing. K and I must be roughly u32-sized, and V
+//! must be Copy.
+//!
+//! VecCache supports efficient concurrent put/get across the key space, with write-once semantics
+//! (i.e., a given key can only be put once). Subsequent puts will panic.
+//!
+//! This is currently used for query caching.
+
+use std::fmt::Debug;
+use std::marker::PhantomData;
+use std::sync::atomic::{AtomicPtr, AtomicU32, AtomicUsize, Ordering};
+
+use rustc_index::Idx;
+
+struct Slot<V> {
+    // We never construct &Slot<V> so it's fine for this to not be in an UnsafeCell.
+    value: V,
+    // This is both an index and a once-lock.
+    //
+    // 0: not yet initialized.
+    // 1: lock held, initializing.
+    // 2..u32::MAX - 2: initialized.
+    index_and_lock: AtomicU32,
+}
+
+/// This uniquely identifies a single `Slot<V>` entry in the buckets map, and provides accessors for
+/// either getting the value or putting a value.
+#[derive(Copy, Clone, Debug)]
+struct SlotIndex {
+    // the index of the bucket in VecCache (0 to 20)
+    bucket_idx: usize,
+    // number of entries in that bucket
+    entries: usize,
+    // the index of the slot within the bucket
+    index_in_bucket: usize,
+}
+
+// This makes sure the counts are consistent with what we allocate, precomputing each bucket a
+// compile-time. Visiting all powers of two is enough to hit all the buckets.
+//
+// We confirm counts are accurate in the slot_index_exhaustive test.
+const ENTRIES_BY_BUCKET: [usize; 21] = {
+    let mut entries = [0; 21];
+    let mut key = 0;
+    loop {
+        let si = SlotIndex::from_index(key);
+        entries[si.bucket_idx] = si.entries;
+        if key == 0 {
+            key = 1;
+        } else if key == (1 << 31) {
+            break;
+        } else {
+            key <<= 1;
+        }
+    }
+    entries
+};
+
+impl SlotIndex {
+    // This unpacks a flat u32 index into identifying which bucket it belongs to and the offset
+    // within that bucket. As noted in the VecCache docs, buckets double in size with each index.
+    // Typically that would mean 31 buckets (2^0 + 2^1 ... + 2^31 = u32::MAX - 1), but to reduce
+    // the size of the VecCache struct and avoid uselessly small allocations, we instead have the
+    // first bucket have 2**12 entries. To simplify the math, the second bucket also 2**12 entries,
+    // and buckets double from there.
+    //
+    // We assert that [0, 2**32 - 1] uniquely map through this function to individual, consecutive
+    // slots (see `slot_index_exhaustive` in tests).
+    #[inline]
+    const fn from_index(idx: u32) -> Self {
+        let mut bucket = match idx.checked_ilog2() {
+            Some(x) => x as usize,
+            None => 0,
+        };
+        let entries;
+        let running_sum;
+        if bucket <= 11 {
+            entries = 1 << 12;
+            running_sum = 0;
+            bucket = 0;
+        } else {
+            entries = 1 << bucket;
+            running_sum = entries;
+            bucket = bucket - 11;
+        }
+        SlotIndex { bucket_idx: bucket, entries, index_in_bucket: idx as usize - running_sum }
+    }
+
+    // SAFETY: Buckets must be managed solely by functions here (i.e., get/put on SlotIndex) and
+    // `self` comes from SlotIndex::from_index
+    #[inline]
+    unsafe fn get<V: Copy>(&self, buckets: &[AtomicPtr<Slot<V>>; 21]) -> Option<(V, u32)> {
+        // SAFETY: `bucket_idx` is ilog2(u32).saturating_sub(11), which is at most 21, i.e.,
+        // in-bounds of buckets. See `from_index` for computation.
+        let bucket = unsafe { buckets.get_unchecked(self.bucket_idx) };
+        let ptr = bucket.load(Ordering::Acquire);
+        // Bucket is not yet initialized: then we obviously won't find this entry in that bucket.
+        if ptr.is_null() {
+            return None;
+        }
+        assert!(self.index_in_bucket < self.entries);
+        // SAFETY: `bucket` was allocated (so <= isize in total bytes) to hold `entries`, so this
+        // must be inbounds.
+        let slot = unsafe { ptr.add(self.index_in_bucket) };
+
+        // SAFETY: initialized bucket has zeroed all memory within the bucket, so we are valid for
+        // AtomicU32 access.
+        let index_and_lock = unsafe { &(*slot).index_and_lock };
+        let current = index_and_lock.load(Ordering::Acquire);
+        let index = match current {
+            0 => return None,
+            // Treat "initializing" as actually just not initialized at all.
+            // The only reason this is a separate state is that `complete` calls could race and
+            // we can't allow that, but from load perspective there's no difference.
+            1 => return None,
+            _ => current - 2,
+        };
+
+        // SAFETY:
+        // * slot is a valid pointer (buckets are always valid for the index we get).
+        // * value is initialized since we saw a >= 2 index above.
+        // * `V: Copy`, so safe to read.
+        let value = unsafe { (*slot).value };
+        Some((value, index))
+    }
+
+    fn bucket_ptr<V>(&self, bucket: &AtomicPtr<Slot<V>>) -> *mut Slot<V> {
+        let ptr = bucket.load(Ordering::Acquire);
+        if ptr.is_null() { self.initialize_bucket(bucket) } else { ptr }
+    }
+
+    #[cold]
+    fn initialize_bucket<V>(&self, bucket: &AtomicPtr<Slot<V>>) -> *mut Slot<V> {
+        static LOCK: std::sync::Mutex<()> = std::sync::Mutex::new(());
+
+        // If we are initializing the bucket, then acquire a global lock.
+        //
+        // This path is quite cold, so it's cheap to use a global lock. This ensures that we never
+        // have multiple allocations for the same bucket.
+        let _allocator_guard = LOCK.lock().unwrap_or_else(|e| e.into_inner());
+
+        let ptr = bucket.load(Ordering::Acquire);
+
+        // OK, now under the allocator lock, if we're still null then it's definitely us that will
+        // initialize this bucket.
+        if ptr.is_null() {
+            let bucket_layout =
+                std::alloc::Layout::array::<Slot<V>>(self.entries as usize).unwrap();
+            // This is more of a sanity check -- this code is very cold, so it's safe to pay a
+            // little extra cost here.
+            assert!(bucket_layout.size() > 0);
+            // SAFETY: Just checked that size is non-zero.
+            let allocated = unsafe { std::alloc::alloc_zeroed(bucket_layout).cast::<Slot<V>>() };
+            if allocated.is_null() {
+                std::alloc::handle_alloc_error(bucket_layout);
+            }
+            bucket.store(allocated, Ordering::Release);
+            allocated
+        } else {
+            // Otherwise some other thread initialized this bucket after we took the lock. In that
+            // case, just return early.
+            ptr
+        }
+    }
+
+    /// Returns true if this successfully put into the map.
+    #[inline]
+    fn put<V>(&self, buckets: &[AtomicPtr<Slot<V>>; 21], value: V, extra: u32) -> bool {
+        // SAFETY: `bucket_idx` is ilog2(u32).saturating_sub(11), which is at most 21, i.e.,
+        // in-bounds of buckets.
+        let bucket = unsafe { buckets.get_unchecked(self.bucket_idx) };
+        let ptr = self.bucket_ptr(bucket);
+
+        assert!(self.index_in_bucket < self.entries);
+        // SAFETY: `bucket` was allocated (so <= isize in total bytes) to hold `entries`, so this
+        // must be inbounds.
+        let slot = unsafe { ptr.add(self.index_in_bucket) };
+
+        // SAFETY: initialized bucket has zeroed all memory within the bucket, so we are valid for
+        // AtomicU32 access.
+        let index_and_lock = unsafe { &(*slot).index_and_lock };
+        match index_and_lock.compare_exchange(0, 1, Ordering::AcqRel, Ordering::Acquire) {
+            Ok(_) => {
+                // We have acquired the initialization lock. It is our job to write `value` and
+                // then set the lock to the real index.
+
+                unsafe {
+                    (&raw mut (*slot).value).write(value);
+                }
+
+                index_and_lock.store(extra.checked_add(2).unwrap(), Ordering::Release);
+
+                true
+            }
+
+            // Treat "initializing" as the caller's fault. Callers are responsible for ensuring that
+            // there are no races on initialization. In the compiler's current usage for query
+            // caches, that's the "active query map" which ensures each query actually runs once
+            // (even if concurrently started).
+            Err(1) => panic!("caller raced calls to put()"),
+
+            // This slot was already populated. Also ignore, currently this is the same as
+            // "initializing".
+            Err(_) => false,
+        }
+    }
+}
+
+pub struct VecCache<K: Idx, V, I> {
+    // Entries per bucket:
+    // Bucket  0:       4096 2^12
+    // Bucket  1:       4096 2^12
+    // Bucket  2:       8192
+    // Bucket  3:      16384
+    // ...
+    // Bucket 19: 1073741824
+    // Bucket 20: 2147483648
+    // The total number of entries if all buckets are initialized is u32::MAX-1.
+    buckets: [AtomicPtr<Slot<V>>; 21],
+
+    // In the compiler's current usage these are only *read* during incremental and self-profiling.
+    // They are an optimization over iterating the full buckets array.
+    present: [AtomicPtr<Slot<()>>; 21],
+    len: AtomicUsize,
+
+    key: PhantomData<(K, I)>,
+}
+
+impl<K: Idx, V, I> Default for VecCache<K, V, I> {
+    fn default() -> Self {
+        VecCache {
+            buckets: Default::default(),
+            key: PhantomData,
+            len: Default::default(),
+            present: Default::default(),
+        }
+    }
+}
+
+// SAFETY: No access to `V` is made.
+unsafe impl<K: Idx, #[may_dangle] V, I> Drop for VecCache<K, V, I> {
+    fn drop(&mut self) {
+        // We have unique ownership, so no locks etc. are needed. Since `K` and `V` are both `Copy`,
+        // we are also guaranteed to just need to deallocate any large arrays (not iterate over
+        // contents).
+        //
+        // Confirm no need to deallocate invidual entries. Note that `V: Copy` is asserted on
+        // insert/lookup but not necessarily construction, primarily to avoid annoyingly propagating
+        // the bounds into struct definitions everywhere.
+        assert!(!std::mem::needs_drop::<K>());
+        assert!(!std::mem::needs_drop::<V>());
+
+        for (idx, bucket) in self.buckets.iter().enumerate() {
+            let bucket = bucket.load(Ordering::Acquire);
+            if !bucket.is_null() {
+                let layout = std::alloc::Layout::array::<Slot<V>>(ENTRIES_BY_BUCKET[idx]).unwrap();
+                unsafe {
+                    std::alloc::dealloc(bucket.cast(), layout);
+                }
+            }
+        }
+
+        for (idx, bucket) in self.present.iter().enumerate() {
+            let bucket = bucket.load(Ordering::Acquire);
+            if !bucket.is_null() {
+                let layout = std::alloc::Layout::array::<Slot<()>>(ENTRIES_BY_BUCKET[idx]).unwrap();
+                unsafe {
+                    std::alloc::dealloc(bucket.cast(), layout);
+                }
+            }
+        }
+    }
+}
+
+impl<K, V, I> VecCache<K, V, I>
+where
+    K: Eq + Idx + Copy + Debug,
+    V: Copy,
+    I: Idx + Copy,
+{
+    #[inline(always)]
+    pub fn lookup(&self, key: &K) -> Option<(V, I)> {
+        let key = u32::try_from(key.index()).unwrap();
+        let slot_idx = SlotIndex::from_index(key);
+        match unsafe { slot_idx.get(&self.buckets) } {
+            Some((value, idx)) => Some((value, I::new(idx as usize))),
+            None => None,
+        }
+    }
+
+    #[inline]
+    pub fn complete(&self, key: K, value: V, index: I) {
+        let key = u32::try_from(key.index()).unwrap();
+        let slot_idx = SlotIndex::from_index(key);
+        if slot_idx.put(&self.buckets, value, index.index() as u32) {
+            let present_idx = self.len.fetch_add(1, Ordering::Relaxed);
+            let slot = SlotIndex::from_index(present_idx as u32);
+            // We should always be uniquely putting due to `len` fetch_add returning unique values.
+            assert!(slot.put(&self.present, (), key));
+        }
+    }
+
+    pub fn iter(&self, f: &mut dyn FnMut(&K, &V, I)) {
+        for idx in 0..self.len.load(Ordering::Acquire) {
+            let key = SlotIndex::from_index(idx as u32);
+            match unsafe { key.get(&self.present) } {
+                // This shouldn't happen in our current usage (iter is really only
+                // used long after queries are done running), but if we hit this in practice it's
+                // probably fine to just break early.
+                None => unreachable!(),
+                Some(((), key)) => {
+                    let key = K::new(key as usize);
+                    // unwrap() is OK: present entries are always written only after we put the real
+                    // entry.
+                    let value = self.lookup(&key).unwrap();
+                    f(&key, &value.0, value.1);
+                }
+            }
+        }
+    }
+}
+
+#[cfg(test)]
+mod tests;
diff --git a/compiler/rustc_data_structures/src/vec_cache/tests.rs b/compiler/rustc_data_structures/src/vec_cache/tests.rs
new file mode 100644
index 00000000000..a05f2741362
--- /dev/null
+++ b/compiler/rustc_data_structures/src/vec_cache/tests.rs
@@ -0,0 +1,95 @@
+use super::*;
+
+#[test]
+#[cfg(not(miri))]
+fn vec_cache_empty() {
+    let cache: VecCache<u32, u32, u32> = VecCache::default();
+    for key in 0..u32::MAX {
+        assert!(cache.lookup(&key).is_none());
+    }
+}
+
+#[test]
+fn vec_cache_insert_and_check() {
+    let cache: VecCache<u32, u32, u32> = VecCache::default();
+    cache.complete(0, 1, 2);
+    assert_eq!(cache.lookup(&0), Some((1, 2)));
+}
+
+#[test]
+fn sparse_inserts() {
+    let cache: VecCache<u32, u8, u32> = VecCache::default();
+    let end = if cfg!(target_pointer_width = "64") && cfg!(target_os = "linux") {
+        // For paged memory, 64-bit systems we should be able to sparsely allocate all of the pages
+        // needed for these inserts cheaply (without needing to actually have gigabytes of resident
+        // memory).
+        31
+    } else {
+        // Otherwise, still run the test but scaled back:
+        //
+        // Each slot is 5 bytes, so 2^25 entries (on non-virtual memory systems, like e.g. Windows) will
+        // mean 160 megabytes of allocated memory. Going beyond that is probably not reasonable for
+        // tests.
+        25
+    };
+    for shift in 0..end {
+        let key = 1u32 << shift;
+        cache.complete(key, shift, key);
+        assert_eq!(cache.lookup(&key), Some((shift, key)));
+    }
+}
+
+#[test]
+fn concurrent_stress_check() {
+    let cache: VecCache<u32, u32, u32> = VecCache::default();
+    std::thread::scope(|s| {
+        for idx in 0..100 {
+            let cache = &cache;
+            s.spawn(move || {
+                cache.complete(idx, idx, idx);
+            });
+        }
+    });
+
+    for idx in 0..100 {
+        assert_eq!(cache.lookup(&idx), Some((idx, idx)));
+    }
+}
+
+#[test]
+fn slot_entries_table() {
+    assert_eq!(ENTRIES_BY_BUCKET, [
+        4096, 4096, 8192, 16384, 32768, 65536, 131072, 262144, 524288, 1048576, 2097152, 4194304,
+        8388608, 16777216, 33554432, 67108864, 134217728, 268435456, 536870912, 1073741824,
+        2147483648
+    ]);
+}
+
+#[test]
+#[cfg(not(miri))]
+fn slot_index_exhaustive() {
+    let mut buckets = [0u32; 21];
+    for idx in 0..=u32::MAX {
+        buckets[SlotIndex::from_index(idx).bucket_idx] += 1;
+    }
+    let mut prev = None::<SlotIndex>;
+    for idx in 0..=u32::MAX {
+        let slot_idx = SlotIndex::from_index(idx);
+        if let Some(p) = prev {
+            if p.bucket_idx == slot_idx.bucket_idx {
+                assert_eq!(p.index_in_bucket + 1, slot_idx.index_in_bucket);
+            } else {
+                assert_eq!(slot_idx.index_in_bucket, 0);
+            }
+        } else {
+            assert_eq!(idx, 0);
+            assert_eq!(slot_idx.index_in_bucket, 0);
+            assert_eq!(slot_idx.bucket_idx, 0);
+        }
+
+        assert_eq!(buckets[slot_idx.bucket_idx], slot_idx.entries as u32);
+        assert_eq!(ENTRIES_BY_BUCKET[slot_idx.bucket_idx], slot_idx.entries, "{}", idx);
+
+        prev = Some(slot_idx);
+    }
+}
diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs
index ce2b47ed1ea..fd08b35d242 100644
--- a/compiler/rustc_feature/src/builtin_attrs.rs
+++ b/compiler/rustc_feature/src/builtin_attrs.rs
@@ -880,6 +880,11 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
         "lang items are subject to change",
     ),
     rustc_attr!(
+        rustc_as_ptr, Normal, template!(Word), ErrorFollowing,
+        EncodeCrossCrate::Yes,
+        "#[rustc_as_ptr] is used to mark functions returning pointers to their inner allocations."
+    ),
+    rustc_attr!(
         rustc_pass_by_value, Normal, template!(Word), ErrorFollowing,
         EncodeCrossCrate::Yes,
         "#[rustc_pass_by_value] is used to mark types that must be passed by value instead of reference."
diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs
index a67a5776449..2acebebb419 100644
--- a/compiler/rustc_feature/src/unstable.rs
+++ b/compiler/rustc_feature/src/unstable.rs
@@ -529,6 +529,8 @@ declare_features! (
     (unstable, macro_metavar_expr_concat, "1.81.0", Some(124225)),
     /// Allows `#[marker]` on certain traits allowing overlapping implementations.
     (unstable, marker_trait_attr, "1.30.0", Some(29864)),
+    /// Enables the generic const args MVP (only bare paths, not arbitrary computation).
+    (incomplete, min_generic_const_args, "CURRENT_RUSTC_VERSION", Some(132980)),
     /// A minimal, sound subset of specialization intended to be used by the
     /// standard library until the soundness issues with specialization
     /// are fixed.
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index 3080d8b3510..cf8c81c0b08 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -21,8 +21,7 @@ use rustc_middle::ty::fold::BottomUpFolder;
 use rustc_middle::ty::layout::{LayoutError, MAX_SIMD_LANES};
 use rustc_middle::ty::util::{Discr, InspectCoroutineFields, IntTypeExt};
 use rustc_middle::ty::{
-    AdtDef, GenericArgKind, ParamEnv, RegionKind, TypeSuperVisitable, TypeVisitable,
-    TypeVisitableExt,
+    AdtDef, GenericArgKind, RegionKind, TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
 };
 use rustc_session::lint::builtin::UNINHABITED_STATIC;
 use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
@@ -114,15 +113,15 @@ fn check_union_fields(tcx: TyCtxt<'_>, span: Span, item_def_id: LocalDefId) -> b
             }
         }
 
-        let param_env = tcx.param_env(item_def_id);
+        let typing_env = ty::TypingEnv::non_body_analysis(tcx, item_def_id);
         for field in &def.non_enum_variant().fields {
-            let Ok(field_ty) = tcx.try_normalize_erasing_regions(param_env, field.ty(tcx, args))
+            let Ok(field_ty) = tcx.try_normalize_erasing_regions(typing_env, field.ty(tcx, args))
             else {
                 tcx.dcx().span_delayed_bug(span, "could not normalize field type");
                 continue;
             };
 
-            if !allowed_union_field(field_ty, tcx, param_env) {
+            if !allowed_union_field(field_ty, tcx, typing_env.param_env) {
                 let (field_span, ty_span) = match tcx.hir().get_if_local(field.did) {
                     // We are currently checking the type this field came from, so it must be local.
                     Some(Node::Field(field)) => (field.span, field.ty.span),
@@ -137,7 +136,7 @@ fn check_union_fields(tcx: TyCtxt<'_>, span: Span, item_def_id: LocalDefId) -> b
                     note: (),
                 });
                 return false;
-            } else if field_ty.needs_drop(tcx, param_env) {
+            } else if field_ty.needs_drop(tcx, typing_env) {
                 // This should never happen. But we can get here e.g. in case of name resolution errors.
                 tcx.dcx()
                     .span_delayed_bug(span, "we should never accept maybe-dropping union fields");
@@ -158,7 +157,7 @@ fn check_static_inhabited(tcx: TyCtxt<'_>, def_id: LocalDefId) {
     // reason to allow any statics to be uninhabited.
     let ty = tcx.type_of(def_id).instantiate_identity();
     let span = tcx.def_span(def_id);
-    let layout = match tcx.layout_of(ParamEnv::reveal_all().and(ty)) {
+    let layout = match tcx.layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(ty)) {
         Ok(l) => l,
         // Foreign statics that overflow their allowed size should emit an error
         Err(LayoutError::SizeOverflow(_))
@@ -237,7 +236,10 @@ pub(super) fn check_opaque_for_cycles<'tcx>(
 
         // And also look for cycle errors in the layout of coroutines.
         if let Err(&LayoutError::Cycle(guar)) =
-            tcx.layout_of(tcx.param_env(def_id).and(Ty::new_opaque(tcx, def_id.to_def_id(), args)))
+            tcx.layout_of(
+                ty::TypingEnv::post_analysis(tcx, def_id.to_def_id())
+                    .as_query_input(Ty::new_opaque(tcx, def_id.to_def_id(), args)),
+            )
         {
             return Err(guar);
         }
@@ -1307,8 +1309,8 @@ pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>)
     // "known" respecting #[non_exhaustive] attributes.
     let field_infos = adt.all_fields().map(|field| {
         let ty = field.ty(tcx, GenericArgs::identity_for_item(tcx, field.did));
-        let param_env = tcx.param_env(field.did);
-        let layout = tcx.layout_of(param_env.and(ty));
+        let typing_env = ty::TypingEnv::non_body_analysis(tcx, field.did);
+        let layout = tcx.layout_of(typing_env.as_query_input(ty));
         // We are currently checking the type this field came from, so it must be local
         let span = tcx.hir().span_if_local(field.did).unwrap();
         let trivial = layout.is_ok_and(|layout| layout.is_1zst());
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index 1802f00bc1f..20bc34b8c79 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -1126,7 +1126,7 @@ fn check_type_defn<'tcx>(
                     let ty = tcx.type_of(variant.tail().did).instantiate_identity();
                     let ty = tcx.erase_regions(ty);
                     assert!(!ty.has_infer());
-                    ty.needs_drop(tcx, tcx.param_env(item.owner_id))
+                    ty.needs_drop(tcx, wfcx.infcx.typing_env(wfcx.param_env))
                 }
             };
             // All fields (except for possibly the last) should be sized.
@@ -1281,7 +1281,8 @@ fn check_item_type(
             UnsizedHandling::Forbid => true,
             UnsizedHandling::Allow => false,
             UnsizedHandling::AllowIfForeignTail => {
-                let tail = tcx.struct_tail_for_codegen(item_ty, wfcx.param_env);
+                let tail =
+                    tcx.struct_tail_for_codegen(item_ty, wfcx.infcx.typing_env(wfcx.param_env));
                 !matches!(tail.kind(), ty::Foreign(_))
             }
         };
diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs
index 5ff52376837..c2ad61820a7 100644
--- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs
@@ -259,7 +259,9 @@ fn visit_implementation_of_dispatch_from_dyn(checker: &Checker<'_>) -> Result<()
                     let ty_a = field.ty(tcx, args_a);
                     let ty_b = field.ty(tcx, args_b);
 
-                    if let Ok(layout) = tcx.layout_of(param_env.and(ty_a)) {
+                    if let Ok(layout) =
+                        tcx.layout_of(infcx.typing_env(param_env).as_query_input(ty_a))
+                    {
                         if layout.is_1zst() {
                             // ignore 1-ZST fields
                             return false;
diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs
index 63a0e7d31c3..1a925597c6c 100644
--- a/compiler/rustc_hir_analysis/src/collect.rs
+++ b/compiler/rustc_hir_analysis/src/collect.rs
@@ -46,7 +46,7 @@ use tracing::{debug, instrument};
 
 use crate::check::intrinsic::intrinsic_operation_unsafety;
 use crate::errors;
-use crate::hir_ty_lowering::{HirTyLowerer, RegionInferReason};
+use crate::hir_ty_lowering::{FeedConstTy, HirTyLowerer, RegionInferReason};
 
 pub(crate) mod dump;
 mod generics_of;
@@ -88,6 +88,7 @@ pub fn provide(providers: &mut Providers) {
         coroutine_for_closure,
         opaque_ty_origin,
         rendered_precise_capturing_args,
+        const_param_default,
         ..*providers
     };
 }
@@ -1790,3 +1791,23 @@ fn rendered_precise_capturing_args<'tcx>(
         _ => None,
     })
 }
+
+fn const_param_default<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    def_id: LocalDefId,
+) -> ty::EarlyBinder<'tcx, Const<'tcx>> {
+    let default_ct = match tcx.hir_node_by_def_id(def_id) {
+        hir::Node::GenericParam(hir::GenericParam {
+            kind: hir::GenericParamKind::Const { default: Some(ct), .. },
+            ..
+        }) => ct,
+        _ => span_bug!(
+            tcx.def_span(def_id),
+            "`const_param_default` expected a generic parameter with a constant"
+        ),
+    };
+    let icx = ItemCtxt::new(tcx, def_id);
+    // FIXME(const_generics): investigate which places do and don't need const ty feeding
+    let ct = icx.lowerer().lower_const_arg(default_ct, FeedConstTy::No);
+    ty::EarlyBinder::bind(ct)
+}
diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
index 7ce12d48160..0f37d61beb0 100644
--- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
@@ -223,11 +223,12 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
                 trace!(?predicates);
             }
             hir::GenericParamKind::Const { .. } => {
+                let param_def_id = param.def_id.to_def_id();
                 let ct_ty = tcx
-                    .type_of(param.def_id.to_def_id())
+                    .type_of(param_def_id)
                     .no_bound_vars()
                     .expect("const parameters cannot be generic");
-                let ct = icx.lowerer().lower_const_param(param.hir_id);
+                let ct = icx.lowerer().lower_const_param(param_def_id, param.hir_id);
                 predicates
                     .insert((ty::ClauseKind::ConstArgHasType(ct, ct_ty).upcast(tcx), param.span));
             }
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs
index 1cade402c54..6ebe1cedcaf 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs
@@ -19,7 +19,9 @@ use tracing::{debug, instrument};
 use super::errors::GenericsArgsErrExtend;
 use crate::bounds::Bounds;
 use crate::errors;
-use crate::hir_ty_lowering::{AssocItemQSelf, HirTyLowerer, PredicateFilter, RegionInferReason};
+use crate::hir_ty_lowering::{
+    AssocItemQSelf, FeedConstTy, HirTyLowerer, PredicateFilter, RegionInferReason,
+};
 
 impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
     /// Add a `Sized` bound to the `bounds` if appropriate.
@@ -346,9 +348,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
             hir::AssocItemConstraintKind::Equality { term } => {
                 let term = match term {
                     hir::Term::Ty(ty) => self.lower_ty(ty).into(),
-                    hir::Term::Const(ct) => {
-                        ty::Const::from_const_arg(tcx, ct, ty::FeedConstTy::No).into()
-                    }
+                    hir::Term::Const(ct) => self.lower_const_arg(ct, FeedConstTy::No).into(),
                 };
 
                 // Find any late-bound regions declared in `ty` that are not
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs
index 92f38a7dde0..39471931461 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs
@@ -3,7 +3,7 @@ use rustc_errors::{DiagCtxtHandle, E0781, struct_span_code_err};
 use rustc_hir::{self as hir, HirId};
 use rustc_middle::bug;
 use rustc_middle::ty::layout::LayoutError;
-use rustc_middle::ty::{self, ParamEnv, TyCtxt};
+use rustc_middle::ty::{self, TyCtxt};
 
 use crate::errors;
 
@@ -130,7 +130,7 @@ fn is_valid_cmse_inputs<'tcx>(
     let fn_sig = tcx.instantiate_bound_regions_with_erased(fn_sig);
 
     for (index, ty) in fn_sig.inputs().iter().enumerate() {
-        let layout = tcx.layout_of(ParamEnv::reveal_all().and(*ty))?;
+        let layout = tcx.layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(*ty))?;
 
         let align = layout.layout.align().abi.bytes();
         let size = layout.layout.size().bytes();
@@ -158,8 +158,10 @@ fn is_valid_cmse_output<'tcx>(
     // this type is only used for layout computation, which does not rely on regions
     let fn_sig = tcx.instantiate_bound_regions_with_erased(fn_sig);
 
+    let typing_env = ty::TypingEnv::fully_monomorphized();
+
     let mut ret_ty = fn_sig.output();
-    let layout = tcx.layout_of(ParamEnv::reveal_all().and(ret_ty))?;
+    let layout = tcx.layout_of(typing_env.as_query_input(ret_ty))?;
     let size = layout.layout.size().bytes();
 
     if size <= 4 {
@@ -182,7 +184,7 @@ fn is_valid_cmse_output<'tcx>(
         for variant_def in adt_def.variants() {
             for field_def in variant_def.fields.iter() {
                 let ty = field_def.ty(tcx, args);
-                let layout = tcx.layout_of(ParamEnv::reveal_all().and(ty))?;
+                let layout = tcx.layout_of(typing_env.as_query_input(ty))?;
 
                 if !layout.layout.is_1zst() {
                     ret_ty = ty;
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs
index 6e8a9ded4f3..ae1279d428c 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs
@@ -115,17 +115,22 @@ fn generic_arg_mismatch_err(
             }
         }
         (GenericArg::Const(cnst), GenericParamDefKind::Type { .. }) => {
-            // FIXME(min_generic_const_args): once ConstArgKind::Path is used for non-params too,
-            // this should match against that instead of ::Anon
-            if let hir::ConstArgKind::Anon(anon) = cnst.kind
+            if let hir::ConstArgKind::Path(qpath) = cnst.kind
+                && let rustc_hir::QPath::Resolved(_, path) = qpath
+                && let Res::Def(DefKind::Fn { .. }, id) = path.res
+            {
+                err.help(format!("`{}` is a function item, not a type", tcx.item_name(id)));
+                err.help("function item types cannot be named directly");
+            } else if let hir::ConstArgKind::Anon(anon) = cnst.kind
                 && let body = tcx.hir().body(anon.body)
                 && let rustc_hir::ExprKind::Path(rustc_hir::QPath::Resolved(_, path)) =
                     body.value.kind
+                && let Res::Def(DefKind::Fn { .. }, id) = path.res
             {
-                if let Res::Def(DefKind::Fn { .. }, id) = path.res {
-                    err.help(format!("`{}` is a function item, not a type", tcx.item_name(id)));
-                    err.help("function item types cannot be named directly");
-                }
+                // FIXME(min_generic_const_args): this branch is dead once new const path lowering
+                // (for single-segment paths) is no longer gated
+                err.help(format!("`{}` is a function item, not a type", tcx.item_name(id)));
+                err.help("function item types cannot be named directly");
             }
         }
         _ => {}
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 ed39708981b..01276abec22 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
@@ -30,7 +30,7 @@ use rustc_errors::{
     Applicability, Diag, DiagCtxtHandle, ErrorGuaranteed, FatalError, struct_span_code_err,
 };
 use rustc_hir as hir;
-use rustc_hir::def::{CtorOf, DefKind, Namespace, Res};
+use rustc_hir::def::{CtorKind, CtorOf, DefKind, Namespace, Res};
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::{GenericArg, GenericArgs, HirId};
 use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
@@ -217,6 +217,23 @@ impl AssocItemQSelf {
     }
 }
 
+/// In some cases, [`hir::ConstArg`]s that are being used in the type system
+/// through const generics need to have their type "fed" to them
+/// using the query system.
+///
+/// Use this enum with `<dyn HirTyLowerer>::lower_const_arg` to instruct it with the
+/// desired behavior.
+#[derive(Debug, Clone, Copy)]
+pub enum FeedConstTy {
+    /// Feed the type.
+    ///
+    /// The `DefId` belongs to the const param that we are supplying
+    /// this (anon) const arg to.
+    Param(DefId),
+    /// Don't feed the type.
+    No,
+}
+
 /// New-typed boolean indicating whether explicit late-bound lifetimes
 /// are present in a set of generic arguments.
 ///
@@ -500,8 +517,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                         handle_ty_args(has_default, &inf.to_ty())
                     }
                     (GenericParamDefKind::Const { .. }, GenericArg::Const(ct)) => {
-                        ty::Const::from_const_arg(tcx, ct, ty::FeedConstTy::Param(param.def_id))
-                            .into()
+                        self.lowerer.lower_const_arg(ct, FeedConstTy::Param(param.def_id)).into()
                     }
                     (&GenericParamDefKind::Const { .. }, GenericArg::Infer(inf)) => {
                         self.lowerer.ct_infer(Some(param), inf.span).into()
@@ -979,8 +995,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                                 let term: ty::Term<'_> = match term {
                                     hir::Term::Ty(ty) => self.lower_ty(ty).into(),
                                     hir::Term::Const(ct) => {
-                                        ty::Const::from_const_arg(tcx, ct, ty::FeedConstTy::No)
-                                            .into()
+                                        self.lower_const_arg(ct, FeedConstTy::No).into()
                                     }
                                 };
                                 // FIXME(#97583): This isn't syntactically well-formed!
@@ -2025,23 +2040,138 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
     ///
     /// Early-bound const parameters get lowered to [`ty::ConstKind::Param`]
     /// and late-bound ones to [`ty::ConstKind::Bound`].
-    pub(crate) fn lower_const_param(&self, hir_id: HirId) -> Const<'tcx> {
+    pub(crate) fn lower_const_param(&self, param_def_id: DefId, path_hir_id: HirId) -> Const<'tcx> {
         let tcx = self.tcx();
-        match tcx.named_bound_var(hir_id) {
-            Some(rbv::ResolvedArg::EarlyBound(def_id)) => {
+
+        match tcx.named_bound_var(path_hir_id) {
+            Some(rbv::ResolvedArg::EarlyBound(_)) => {
                 // Find the name and index of the const parameter by indexing the generics of
                 // the parent item and construct a `ParamConst`.
-                let item_def_id = tcx.local_parent(def_id);
+                let item_def_id = tcx.parent(param_def_id);
                 let generics = tcx.generics_of(item_def_id);
-                let index = generics.param_def_id_to_index[&def_id.to_def_id()];
-                let name = tcx.item_name(def_id.to_def_id());
+                let index = generics.param_def_id_to_index[&param_def_id];
+                let name = tcx.item_name(param_def_id);
                 ty::Const::new_param(tcx, ty::ParamConst::new(index, name))
             }
             Some(rbv::ResolvedArg::LateBound(debruijn, index, _)) => {
                 ty::Const::new_bound(tcx, debruijn, ty::BoundVar::from_u32(index))
             }
             Some(rbv::ResolvedArg::Error(guar)) => ty::Const::new_error(tcx, guar),
-            arg => bug!("unexpected bound var resolution for {:?}: {arg:?}", hir_id),
+            arg => bug!("unexpected bound var resolution for {:?}: {arg:?}", path_hir_id),
+        }
+    }
+
+    /// Convert a [`hir::ConstArg`] to a [`ty::Const`](Const).
+    #[instrument(skip(self), level = "debug")]
+    pub fn lower_const_arg(
+        &self,
+        const_arg: &hir::ConstArg<'tcx>,
+        feed: FeedConstTy,
+    ) -> Const<'tcx> {
+        let tcx = self.tcx();
+
+        if let FeedConstTy::Param(param_def_id) = feed
+            && let hir::ConstArgKind::Anon(anon) = &const_arg.kind
+        {
+            tcx.feed_anon_const_type(anon.def_id, tcx.type_of(param_def_id));
+        }
+
+        let hir_id = const_arg.hir_id;
+        match const_arg.kind {
+            hir::ConstArgKind::Path(hir::QPath::Resolved(maybe_qself, path)) => {
+                debug!(?maybe_qself, ?path);
+                let opt_self_ty = maybe_qself.as_ref().map(|qself| self.lower_ty(qself));
+                self.lower_const_path_resolved(opt_self_ty, path, hir_id)
+            }
+            hir::ConstArgKind::Path(qpath) => ty::Const::new_error_with_message(
+                tcx,
+                qpath.span(),
+                format!("Const::lower_const_arg: invalid qpath {qpath:?}"),
+            ),
+            hir::ConstArgKind::Anon(anon) => Const::from_anon_const(tcx, anon.def_id),
+        }
+    }
+
+    fn lower_const_path_resolved(
+        &self,
+        opt_self_ty: Option<Ty<'tcx>>,
+        path: &hir::Path<'tcx>,
+        hir_id: HirId,
+    ) -> Const<'tcx> {
+        let tcx = self.tcx();
+        let span = path.span;
+        match path.res {
+            Res::Def(DefKind::ConstParam, def_id) => {
+                assert_eq!(opt_self_ty, None);
+                let _ = self.prohibit_generic_args(
+                    path.segments.iter(),
+                    GenericsArgsErrExtend::Param(def_id),
+                );
+                self.lower_const_param(def_id, hir_id)
+            }
+            Res::Def(DefKind::Const | DefKind::Ctor(_, CtorKind::Const), did) => {
+                assert_eq!(opt_self_ty, None);
+                let _ = self.prohibit_generic_args(
+                    path.segments.split_last().unwrap().1.iter(),
+                    GenericsArgsErrExtend::None,
+                );
+                let args = self.lower_generic_args_of_path_segment(
+                    span,
+                    did,
+                    path.segments.last().unwrap(),
+                );
+                ty::Const::new_unevaluated(tcx, ty::UnevaluatedConst::new(did, args))
+            }
+            Res::Def(DefKind::Static { .. }, _) => {
+                span_bug!(span, "use of bare `static` ConstArgKind::Path's not yet supported")
+            }
+            // FIXME(const_generics): create real const to allow fn items as const paths
+            Res::Def(DefKind::Fn | DefKind::AssocFn, _) => ty::Const::new_error_with_message(
+                tcx,
+                span,
+                "fn items cannot be used as const args",
+            ),
+
+            // Exhaustive match to be clear about what exactly we're considering to be
+            // an invalid Res for a const path.
+            Res::Def(
+                DefKind::Mod
+                | DefKind::Enum
+                | DefKind::Variant
+                | DefKind::Ctor(CtorOf::Variant, CtorKind::Fn)
+                | DefKind::Struct
+                | DefKind::Ctor(CtorOf::Struct, CtorKind::Fn)
+                | DefKind::OpaqueTy
+                | DefKind::TyAlias
+                | DefKind::TraitAlias
+                | DefKind::AssocTy
+                | DefKind::Union
+                | DefKind::Trait
+                | DefKind::ForeignTy
+                | DefKind::AssocConst
+                | DefKind::TyParam
+                | DefKind::Macro(_)
+                | DefKind::LifetimeParam
+                | DefKind::Use
+                | DefKind::ForeignMod
+                | DefKind::AnonConst
+                | DefKind::InlineConst
+                | DefKind::Field
+                | DefKind::Impl { .. }
+                | DefKind::Closure
+                | DefKind::ExternCrate
+                | DefKind::GlobalAsm
+                | DefKind::SyntheticCoroutineBody,
+                _,
+            )
+            | Res::PrimTy(_)
+            | Res::SelfTyParam { .. }
+            | Res::SelfTyAlias { .. }
+            | Res::SelfCtor(_)
+            | Res::Local(_)
+            | Res::ToolMod
+            | Res::NonMacroAttr(_)
+            | Res::Err => Const::new_error_with_message(tcx, span, "invalid Res for const path"),
         }
     }
 
@@ -2053,14 +2183,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
         }
     }
 
-    /// Lower a type from the HIR to our internal notion of a type given some extra data for diagnostics.
-    ///
-    /// Extra diagnostic data:
-    ///
-    /// 1. `borrowed`: Whether trait object types are borrowed like in `&dyn Trait`.
-    ///    Used to avoid emitting redundant errors.
-    /// 2. `in_path`: Whether the type appears inside of a path.
-    ///    Used to provide correct diagnostics for bare trait object types.
+    /// Lower a type from the HIR to our internal notion of a type.
     #[instrument(level = "debug", skip(self), ret)]
     pub fn lower_ty(&self, hir_ty: &hir::Ty<'tcx>) -> Ty<'tcx> {
         let tcx = self.tcx();
@@ -2189,7 +2312,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                 let length = match length {
                     hir::ArrayLen::Infer(inf) => self.ct_infer(None, inf.span),
                     hir::ArrayLen::Body(constant) => {
-                        ty::Const::from_const_arg(tcx, constant, ty::FeedConstTy::No)
+                        self.lower_const_arg(constant, FeedConstTy::No)
                     }
                 };
 
@@ -2247,7 +2370,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                                         .type_of(def_id)
                                         .no_bound_vars()
                                         .expect("const parameter types cannot be generic");
-                                    let ct = self.lower_const_param(expr.hir_id);
+                                    let ct = self.lower_const_param(def_id, expr.hir_id);
                                     (ct, ty)
                                 }
 
diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs
index 5830636c6e8..564e45c677d 100644
--- a/compiler/rustc_hir_analysis/src/lib.rs
+++ b/compiler/rustc_hir_analysis/src/lib.rs
@@ -97,12 +97,14 @@ use rustc_hir::def::DefKind;
 use rustc_middle::middle;
 use rustc_middle::mir::interpret::GlobalId;
 use rustc_middle::query::Providers;
-use rustc_middle::ty::{self, Ty, TyCtxt};
+use rustc_middle::ty::{self, Const, Ty, TyCtxt};
 use rustc_session::parse::feature_err;
 use rustc_span::Span;
 use rustc_span::symbol::sym;
 use rustc_trait_selection::traits;
 
+use self::hir_ty_lowering::{FeedConstTy, HirTyLowerer};
+
 rustc_fluent_macro::fluent_messages! { "../messages.ftl" }
 
 fn require_c_abi_if_c_variadic(
@@ -226,3 +228,14 @@ pub fn lower_ty<'tcx>(tcx: TyCtxt<'tcx>, hir_ty: &hir::Ty<'tcx>) -> Ty<'tcx> {
     let env_def_id = tcx.hir().get_parent_item(hir_ty.hir_id);
     collect::ItemCtxt::new(tcx, env_def_id.def_id).lower_ty(hir_ty)
 }
+
+/// This is for rustdoc.
+// FIXME(const_generics): having special methods for rustdoc in `rustc_hir_analysis` is cursed
+pub fn lower_const_arg_for_rustdoc<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    hir_ct: &hir::ConstArg<'tcx>,
+    feed: FeedConstTy,
+) -> Const<'tcx> {
+    let env_def_id = tcx.hir().get_parent_item(hir_ct.hir_id);
+    collect::ItemCtxt::new(tcx, env_def_id.def_id).lowerer().lower_const_arg(hir_ct, feed)
+}
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index 354993513da..1610848958e 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -2357,8 +2357,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     // Only assoc fns that return `Self`
                     let fn_sig = self.tcx.fn_sig(item.def_id).skip_binder();
                     let ret_ty = fn_sig.output();
-                    let ret_ty =
-                        self.tcx.normalize_erasing_late_bound_regions(self.param_env, ret_ty);
+                    let ret_ty = self.tcx.normalize_erasing_late_bound_regions(
+                        self.typing_env(self.param_env),
+                        ret_ty,
+                    );
                     if !self.can_eq(self.param_env, ret_ty, adt_ty) {
                         return None;
                     }
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
index f0738491609..ce6ce0381a9 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
@@ -14,8 +14,8 @@ use rustc_hir_analysis::hir_ty_lowering::generics::{
     check_generic_arg_count_for_call, lower_generic_args,
 };
 use rustc_hir_analysis::hir_ty_lowering::{
-    ExplicitLateBound, GenericArgCountMismatch, GenericArgCountResult, GenericArgsLowerer,
-    GenericPathSegment, HirTyLowerer, IsMethodCall, RegionInferReason,
+    ExplicitLateBound, FeedConstTy, GenericArgCountMismatch, GenericArgCountResult,
+    GenericArgsLowerer, GenericPathSegment, HirTyLowerer, IsMethodCall, RegionInferReason,
 };
 use rustc_infer::infer::canonical::{Canonical, OriginalQueryValues, QueryResponse};
 use rustc_infer::infer::{DefineOpaqueTypes, InferResult};
@@ -491,7 +491,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             hir::ArrayLen::Infer(inf) => self.ct_infer(None, inf.span),
             hir::ArrayLen::Body(const_arg) => {
                 let span = const_arg.span();
-                let c = ty::Const::from_const_arg(self.tcx, const_arg, ty::FeedConstTy::No);
+                let c = self.lowerer().lower_const_arg(const_arg, FeedConstTy::No);
                 self.register_wf_obligation(c.into(), span, ObligationCauseCode::WellFormed(None));
                 self.normalize(span, c)
             }
@@ -503,8 +503,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         const_arg: &'tcx hir::ConstArg<'tcx>,
         param_def_id: DefId,
     ) -> ty::Const<'tcx> {
-        let ct =
-            ty::Const::from_const_arg(self.tcx, const_arg, ty::FeedConstTy::Param(param_def_id));
+        let ct = self.lowerer().lower_const_arg(const_arg, FeedConstTy::Param(param_def_id));
         self.register_wf_obligation(
             ct.into(),
             self.tcx.hir().span(const_arg.hir_id),
diff --git a/compiler/rustc_hir_typeck/src/intrinsicck.rs b/compiler/rustc_hir_typeck/src/intrinsicck.rs
index a754f7fddc9..789530d35dd 100644
--- a/compiler/rustc_hir_typeck/src/intrinsicck.rs
+++ b/compiler/rustc_hir_typeck/src/intrinsicck.rs
@@ -46,7 +46,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let span = tcx.hir().span(hir_id);
         let normalize = |ty| {
             let ty = self.resolve_vars_if_possible(ty);
-            self.tcx.normalize_erasing_regions(self.param_env, ty)
+            self.tcx.normalize_erasing_regions(self.typing_env(self.param_env), ty)
         };
         let from = normalize(from);
         let to = normalize(to);
@@ -62,7 +62,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             return;
         }
 
-        let skel = |ty| SizeSkeleton::compute(ty, tcx, self.param_env);
+        let skel = |ty| SizeSkeleton::compute(ty, tcx, self.typing_env(self.param_env));
         let sk_from = skel(from);
         let sk_to = skel(to);
         trace!(?sk_from, ?sk_to);
diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs
index 175fca327f3..d50eff0deb0 100644
--- a/compiler/rustc_hir_typeck/src/upvar.rs
+++ b/compiler/rustc_hir_typeck/src/upvar.rs
@@ -1257,7 +1257,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     ) -> Option<FxIndexSet<UpvarMigrationInfo>> {
         let ty = self.resolve_vars_if_possible(self.node_ty(var_hir_id));
 
-        if !ty.has_significant_drop(self.tcx, self.tcx.param_env(closure_def_id)) {
+        // FIXME(#132279): Using `non_body_analysis` here feels wrong.
+        if !ty.has_significant_drop(
+            self.tcx,
+            ty::TypingEnv::non_body_analysis(self.tcx, closure_def_id),
+        ) {
             debug!("does not have significant drop");
             return None;
         }
@@ -1535,8 +1539,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         base_path_ty: Ty<'tcx>,
         captured_by_move_projs: Vec<&[Projection<'tcx>]>,
     ) -> bool {
-        let needs_drop =
-            |ty: Ty<'tcx>| ty.has_significant_drop(self.tcx, self.tcx.param_env(closure_def_id));
+        // FIXME(#132279): Using `non_body_analysis` here feels wrong.
+        let needs_drop = |ty: Ty<'tcx>| {
+            ty.has_significant_drop(
+                self.tcx,
+                ty::TypingEnv::non_body_analysis(self.tcx, closure_def_id),
+            )
+        };
 
         let is_drop_defined_for_ty = |ty: Ty<'tcx>| {
             let drop_trait = self.tcx.require_lang_item(hir::LangItem::Drop, Some(closure_span));
diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs
index 391e640f8bc..8694800ac43 100644
--- a/compiler/rustc_hir_typeck/src/writeback.rs
+++ b/compiler/rustc_hir_typeck/src/writeback.rs
@@ -881,6 +881,8 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for EagerlyNormalizeConsts<'tcx> {
     }
 
     fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
-        self.tcx.try_normalize_erasing_regions(self.param_env, ct).unwrap_or(ct)
+        self.tcx
+            .try_normalize_erasing_regions(ty::TypingEnv::from_param_env(self.param_env), ct)
+            .unwrap_or(ct)
     }
 }
diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs
index 12df4a10e63..b29dc7f909d 100644
--- a/compiler/rustc_infer/src/infer/mod.rs
+++ b/compiler/rustc_infer/src/infer/mod.rs
@@ -38,7 +38,8 @@ use rustc_middle::ty::fold::{
 use rustc_middle::ty::visit::TypeVisitableExt;
 use rustc_middle::ty::{
     self, ConstVid, FloatVid, GenericArg, GenericArgKind, GenericArgs, GenericArgsRef,
-    GenericParamDefKind, InferConst, IntVid, Ty, TyCtxt, TyVid, TypingMode,
+    GenericParamDefKind, InferConst, IntVid, PseudoCanonicalInput, Ty, TyCtxt, TyVid,
+    TypeVisitable, TypingEnv, TypingMode,
 };
 use rustc_span::Span;
 use rustc_span::symbol::Symbol;
@@ -565,6 +566,13 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
         (infcx, value, args)
     }
 
+    pub fn build_with_typing_env(
+        mut self,
+        TypingEnv { typing_mode, param_env }: TypingEnv<'tcx>,
+    ) -> (InferCtxt<'tcx>, ty::ParamEnv<'tcx>) {
+        (self.build(typing_mode), param_env)
+    }
+
     pub fn build(&mut self, typing_mode: TypingMode<'tcx>) -> InferCtxt<'tcx> {
         let InferCtxtBuilder { tcx, considering_regions, skip_leak_check, next_trait_solver } =
             *self;
@@ -1278,6 +1286,42 @@ impl<'tcx> InferCtxt<'tcx> {
         u
     }
 
+    /// Extract [`ty::TypingMode`] of this inference context to get a `TypingEnv`
+    /// which contains the necessary information to use the trait system without
+    /// using canonicalization or carrying this inference context around.
+    pub fn typing_env(&self, param_env: ty::ParamEnv<'tcx>) -> ty::TypingEnv<'tcx> {
+        let typing_mode = match self.typing_mode(param_env) {
+            ty::TypingMode::Coherence => ty::TypingMode::Coherence,
+            // FIXME(#132279): This erases the `defining_opaque_types` as it isn't possible
+            // to handle them without proper canonicalization. This means we may cause cycle
+            // errors and fail to reveal opaques while inside of bodies. We should rename this
+            // function and require explicit comments on all use-sites in the future.
+            ty::TypingMode::Analysis { defining_opaque_types: _ } => {
+                TypingMode::non_body_analysis()
+            }
+            ty::TypingMode::PostAnalysis => ty::TypingMode::PostAnalysis,
+        };
+        ty::TypingEnv { typing_mode, param_env }
+    }
+
+    /// Similar to [`Self::canonicalize_query`], except that it returns
+    /// a [`PseudoCanonicalInput`] and requires both the `value` and the
+    /// `param_env` to not contain any inference variables or placeholders.
+    pub fn pseudo_canonicalize_query<V>(
+        &self,
+        param_env: ty::ParamEnv<'tcx>,
+        value: V,
+    ) -> PseudoCanonicalInput<'tcx, V>
+    where
+        V: TypeVisitable<TyCtxt<'tcx>>,
+    {
+        debug_assert!(!value.has_infer());
+        debug_assert!(!value.has_placeholders());
+        debug_assert!(!param_env.has_infer());
+        debug_assert!(!param_env.has_placeholders());
+        self.typing_env(param_env).as_query_input(value)
+    }
+
     /// The returned function is used in a fast path. If it returns `true` the variable is
     /// unchanged, `false` indicates that the status is unknown.
     #[inline]
diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs
index 7e629c1d18f..43a98782016 100644
--- a/compiler/rustc_interface/src/passes.rs
+++ b/compiler/rustc_interface/src/passes.rs
@@ -5,7 +5,7 @@ use std::path::{Path, PathBuf};
 use std::sync::{Arc, LazyLock};
 use std::{env, fs, iter};
 
-use rustc_ast::{self as ast, visit};
+use rustc_ast as ast;
 use rustc_codegen_ssa::traits::CodegenBackend;
 use rustc_data_structures::parallel;
 use rustc_data_structures::steal::Steal;
@@ -24,7 +24,7 @@ use rustc_middle::util::Providers;
 use rustc_parse::{
     new_parser_from_file, new_parser_from_source_str, unwrap_or_emit_fatal, validate_attr,
 };
-use rustc_passes::{abi_test, hir_stats, layout_test};
+use rustc_passes::{abi_test, input_stats, layout_test};
 use rustc_resolve::Resolver;
 use rustc_session::code_stats::VTableSizeInfo;
 use rustc_session::config::{CrateType, Input, OutFileName, OutputFilenames, OutputType};
@@ -54,28 +54,17 @@ pub(crate) fn parse<'a>(sess: &'a Session) -> Result<ast::Crate> {
         })
         .map_err(|parse_error| parse_error.emit())?;
 
-    if sess.opts.unstable_opts.input_stats {
-        eprintln!("Lines of code:             {}", sess.source_map().count_lines());
-        eprintln!("Pre-expansion node count:  {}", count_nodes(&krate));
-    }
-
     if let Some(ref s) = sess.opts.unstable_opts.show_span {
         rustc_ast_passes::show_span::run(sess.dcx(), s, &krate);
     }
 
-    if sess.opts.unstable_opts.hir_stats {
-        hir_stats::print_ast_stats(&krate, "PRE EXPANSION AST STATS", "ast-stats-1");
+    if sess.opts.unstable_opts.input_stats {
+        input_stats::print_ast_stats(&krate, "PRE EXPANSION AST STATS", "ast-stats-1");
     }
 
     Ok(krate)
 }
 
-fn count_nodes(krate: &ast::Crate) -> usize {
-    let mut counter = rustc_ast_passes::node_count::NodeCounter::new();
-    visit::walk_crate(&mut counter, krate);
-    counter.count
-}
-
 fn pre_expansion_lint<'a>(
     sess: &Session,
     features: &Features,
@@ -290,11 +279,7 @@ fn early_lint_checks(tcx: TyCtxt<'_>, (): ()) {
     let mut lint_buffer = resolver.lint_buffer.steal();
 
     if sess.opts.unstable_opts.input_stats {
-        eprintln!("Post-expansion node count: {}", count_nodes(krate));
-    }
-
-    if sess.opts.unstable_opts.hir_stats {
-        hir_stats::print_ast_stats(krate, "POST EXPANSION AST STATS", "ast-stats-2");
+        input_stats::print_ast_stats(krate, "POST EXPANSION AST STATS", "ast-stats-2");
     }
 
     // Needs to go *after* expansion to be able to check the results of macro expansion.
@@ -820,8 +805,8 @@ pub(crate) fn create_global_ctxt<'tcx>(
 /// Runs all analyses that we guarantee to run, even if errors were reported in earlier analyses.
 /// This function never fails.
 fn run_required_analyses(tcx: TyCtxt<'_>) {
-    if tcx.sess.opts.unstable_opts.hir_stats {
-        rustc_passes::hir_stats::print_hir_stats(tcx);
+    if tcx.sess.opts.unstable_opts.input_stats {
+        rustc_passes::input_stats::print_hir_stats(tcx);
     }
     #[cfg(debug_assertions)]
     rustc_passes::hir_id_validator::check_crate(tcx);
diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs
index 2361231b3fb..e48c4d46b59 100644
--- a/compiler/rustc_interface/src/tests.rs
+++ b/compiler/rustc_interface/src/tests.rs
@@ -698,7 +698,6 @@ fn test_unstable_options_tracking_hash() {
     untracked!(dylib_lto, true);
     untracked!(emit_stack_sizes, true);
     untracked!(future_incompat_test, true);
-    untracked!(hir_stats, true);
     untracked!(identify_regions, true);
     untracked!(incremental_info, true);
     untracked!(incremental_verify_ich, true);
diff --git a/compiler/rustc_lexer/src/lib.rs b/compiler/rustc_lexer/src/lib.rs
index f9f2a14dbd2..bcb103957ba 100644
--- a/compiler/rustc_lexer/src/lib.rs
+++ b/compiler/rustc_lexer/src/lib.rs
@@ -57,11 +57,10 @@ impl Token {
 /// Enum representing common lexeme types.
 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
 pub enum TokenKind {
-    // Multi-char tokens:
-    /// "// comment"
+    /// A line comment, e.g. `// comment`.
     LineComment { doc_style: Option<DocStyle> },
 
-    /// `/* block comment */`
+    /// A block comment, e.g. `/* block comment */`.
     ///
     /// Block comments can be recursive, so a sequence like `/* /* */`
     /// will not be considered terminated and will result in a parsing error.
@@ -70,18 +69,17 @@ pub enum TokenKind {
     /// Any whitespace character sequence.
     Whitespace,
 
-    /// "ident" or "continue"
-    ///
-    /// At this step, keywords are also considered identifiers.
+    /// An identifier or keyword, e.g. `ident` or `continue`.
     Ident,
 
-    /// Like the above, but containing invalid unicode codepoints.
+    /// An identifier that is invalid because it contains emoji.
     InvalidIdent,
 
-    /// "r#ident"
+    /// A raw identifier, e.g. "r#ident".
     RawIdent,
 
-    /// An unknown prefix, like `foo#`, `foo'`, `foo"`.
+    /// An unknown literal prefix, like `foo#`, `foo'`, `foo"`. Excludes
+    /// literal prefixes that contain emoji, which are considered "invalid".
     ///
     /// Note that only the
     /// prefix (`foo`) is included in the token, not the separator (which is
@@ -93,87 +91,83 @@ pub enum TokenKind {
 
     /// An unknown prefix in a lifetime, like `'foo#`.
     ///
-    /// Note that like above, only the `'` and prefix are included in the token
+    /// Like `UnknownPrefix`, only the `'` and prefix are included in the token
     /// and not the separator.
     UnknownPrefixLifetime,
 
-    /// `'r#lt`, which in edition < 2021 is split into several tokens: `'r # lt`.
+    /// A raw lifetime, e.g. `'r#foo`. In edition < 2021 it will be split into
+    /// several tokens: `'r` and `#` and `foo`.
     RawLifetime,
 
-    /// Similar to the above, but *always* an error on every edition. This is used
-    /// for emoji identifier recovery, as those are not meant to be ever accepted.
-    InvalidPrefix,
-
     /// Guarded string literal prefix: `#"` or `##`.
     ///
     /// Used for reserving "guarded strings" (RFC 3598) in edition 2024.
     /// Split into the component tokens on older editions.
     GuardedStrPrefix,
 
-    /// Examples: `12u8`, `1.0e-40`, `b"123"`. Note that `_` is an invalid
+    /// Literals, e.g. `12u8`, `1.0e-40`, `b"123"`. Note that `_` is an invalid
     /// suffix, but may be present here on string and float literals. Users of
     /// this type will need to check for and reject that case.
     ///
     /// See [LiteralKind] for more details.
     Literal { kind: LiteralKind, suffix_start: u32 },
 
-    /// "'a"
+    /// A lifetime, e.g. `'a`.
     Lifetime { starts_with_number: bool },
 
-    // One-char tokens:
-    /// ";"
+    /// `;`
     Semi,
-    /// ","
+    /// `,`
     Comma,
-    /// "."
+    /// `.`
     Dot,
-    /// "("
+    /// `(`
     OpenParen,
-    /// ")"
+    /// `)`
     CloseParen,
-    /// "{"
+    /// `{`
     OpenBrace,
-    /// "}"
+    /// `}`
     CloseBrace,
-    /// "["
+    /// `[`
     OpenBracket,
-    /// "]"
+    /// `]`
     CloseBracket,
-    /// "@"
+    /// `@`
     At,
-    /// "#"
+    /// `#`
     Pound,
-    /// "~"
+    /// `~`
     Tilde,
-    /// "?"
+    /// `?`
     Question,
-    /// ":"
+    /// `:`
     Colon,
-    /// "$"
+    /// `$`
     Dollar,
-    /// "="
+    /// `=`
     Eq,
-    /// "!"
+    /// `!`
     Bang,
-    /// "<"
+    /// `<`
     Lt,
-    /// ">"
+    /// `>`
     Gt,
-    /// "-"
+    /// `-`
     Minus,
-    /// "&"
+    /// `&`
     And,
-    /// "|"
+    /// `|`
     Or,
-    /// "+"
+    /// `+`
     Plus,
-    /// "*"
+    /// `*`
     Star,
-    /// "/"
+    /// `/`
     Slash,
-    /// "^"
+    /// `^`
     Caret,
-    /// "%"
+    /// `%`
     Percent,
 
     /// Unknown token, not expected by the lexer, e.g. "â„–"
@@ -468,7 +462,7 @@ impl Cursor<'_> {
                 Literal { kind, suffix_start }
             }
             // Identifier starting with an emoji. Only lexed for graceful error recovery.
-            c if !c.is_ascii() && c.is_emoji_char() => self.fake_ident_or_unknown_prefix(),
+            c if !c.is_ascii() && c.is_emoji_char() => self.invalid_ident(),
             _ => Unknown,
         };
         let res = Token::new(token_kind, self.pos_within_token());
@@ -552,24 +546,22 @@ impl Cursor<'_> {
         // we see a prefix here, it is definitely an unknown prefix.
         match self.first() {
             '#' | '"' | '\'' => UnknownPrefix,
-            c if !c.is_ascii() && c.is_emoji_char() => self.fake_ident_or_unknown_prefix(),
+            c if !c.is_ascii() && c.is_emoji_char() => self.invalid_ident(),
             _ => Ident,
         }
     }
 
-    fn fake_ident_or_unknown_prefix(&mut self) -> TokenKind {
+    fn invalid_ident(&mut self) -> TokenKind {
         // Start is already eaten, eat the rest of identifier.
         self.eat_while(|c| {
-            unicode_xid::UnicodeXID::is_xid_continue(c)
-                || (!c.is_ascii() && c.is_emoji_char())
-                || c == '\u{200d}'
+            const ZERO_WIDTH_JOINER: char = '\u{200d}';
+            is_id_continue(c) || (!c.is_ascii() && c.is_emoji_char()) || c == ZERO_WIDTH_JOINER
         });
-        // Known prefixes must have been handled earlier. So if
-        // we see a prefix here, it is definitely an unknown prefix.
-        match self.first() {
-            '#' | '"' | '\'' => InvalidPrefix,
-            _ => InvalidIdent,
-        }
+        // An invalid identifier followed by '#' or '"' or '\'' could be
+        // interpreted as an invalid literal prefix. We don't bother doing that
+        // because the treatment of invalid identifiers and invalid prefixes
+        // would be the same.
+        InvalidIdent
     }
 
     fn c_or_byte_string(
diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index 130f3cb7c2a..f6366ec3b80 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -2485,7 +2485,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue {
             });
 
             // Check if this ADT has a constrained layout (like `NonNull` and friends).
-            if let Ok(layout) = cx.tcx.layout_of(cx.param_env.and(ty)) {
+            if let Ok(layout) = cx.tcx.layout_of(cx.typing_env().as_query_input(ty)) {
                 if let BackendRepr::Scalar(scalar) | BackendRepr::ScalarPair(scalar, _) =
                     &layout.backend_repr
                 {
@@ -2521,7 +2521,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue {
             ty: Ty<'tcx>,
             init: InitKind,
         ) -> Option<InitError> {
-            let ty = cx.tcx.try_normalize_erasing_regions(cx.param_env, ty).unwrap_or(ty);
+            let ty = cx.tcx.try_normalize_erasing_regions(cx.typing_env(), ty).unwrap_or(ty);
 
             use rustc_type_ir::TyKind::*;
             match ty.kind() {
@@ -2568,7 +2568,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue {
                         let definitely_inhabited = match variant
                             .inhabited_predicate(cx.tcx, *adt_def)
                             .instantiate(cx.tcx, args)
-                            .apply_any_module(cx.tcx, cx.param_env)
+                            .apply_any_module(cx.tcx, cx.typing_env())
                         {
                             // Entirely skip uninhabited variants.
                             Some(false) => return None,
diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs
index aa7ec2659d0..6eec32beab0 100644
--- a/compiler/rustc_lint/src/context.rs
+++ b/compiler/rustc_lint/src/context.rs
@@ -19,7 +19,7 @@ use rustc_middle::bug;
 use rustc_middle::middle::privacy::EffectiveVisibilities;
 use rustc_middle::ty::layout::{LayoutError, LayoutOfHelpers, TyAndLayout};
 use rustc_middle::ty::print::{PrintError, PrintTraitRefExt as _, Printer, with_no_trimmed_paths};
-use rustc_middle::ty::{self, GenericArg, RegisteredTools, Ty, TyCtxt, TypingMode};
+use rustc_middle::ty::{self, GenericArg, RegisteredTools, Ty, TyCtxt, TypingEnv, TypingMode};
 use rustc_session::lint::{
     BuiltinLintDiag, FutureIncompatibleInfo, Level, Lint, LintBuffer, LintExpectationId, LintId,
 };
@@ -708,6 +708,10 @@ impl<'tcx> LateContext<'tcx> {
         TypingMode::non_body_analysis()
     }
 
+    pub fn typing_env(&self) -> TypingEnv<'tcx> {
+        TypingEnv { typing_mode: self.typing_mode(), param_env: self.param_env }
+    }
+
     /// Gets the type-checking results for the current body,
     /// or `None` if outside a body.
     pub fn maybe_typeck_results(&self) -> Option<&'tcx ty::TypeckResults<'tcx>> {
@@ -906,7 +910,7 @@ impl<'tcx> LateContext<'tcx> {
             .find_by_name_and_kind(tcx, Ident::from_str(name), ty::AssocKind::Type, trait_id)
             .and_then(|assoc| {
                 let proj = Ty::new_projection(tcx, assoc.def_id, [self_ty]);
-                tcx.try_normalize_erasing_regions(self.param_env, proj).ok()
+                tcx.try_normalize_erasing_regions(self.typing_env(), proj).ok()
             })
     }
 
@@ -1010,10 +1014,10 @@ impl<'tcx> ty::layout::HasTyCtxt<'tcx> for LateContext<'tcx> {
     }
 }
 
-impl<'tcx> ty::layout::HasParamEnv<'tcx> for LateContext<'tcx> {
+impl<'tcx> ty::layout::HasTypingEnv<'tcx> for LateContext<'tcx> {
     #[inline]
-    fn param_env(&self) -> ty::ParamEnv<'tcx> {
-        self.param_env
+    fn typing_env(&self) -> ty::TypingEnv<'tcx> {
+        self.typing_env()
     }
 }
 
diff --git a/compiler/rustc_lint/src/dangling.rs b/compiler/rustc_lint/src/dangling.rs
index a34c3e26778..e3e51ba263d 100644
--- a/compiler/rustc_lint/src/dangling.rs
+++ b/compiler/rustc_lint/src/dangling.rs
@@ -43,13 +43,10 @@ declare_lint! {
 }
 
 /// FIXME: false negatives (i.e. the lint is not emitted when it should be)
-/// 1. Method calls that are not checked for:
-///    - [`temporary_unsafe_cell.get()`][`core::cell::UnsafeCell::get()`]
-///    - [`temporary_sync_unsafe_cell.get()`][`core::cell::SyncUnsafeCell::get()`]
-/// 2. Ways to get a temporary that are not recognized:
+/// 1. Ways to get a temporary that are not recognized:
 ///    - `owning_temporary.field`
 ///    - `owning_temporary[index]`
-/// 3. No checks for ref-to-ptr conversions:
+/// 2. No checks for ref-to-ptr conversions:
 ///    - `&raw [mut] temporary`
 ///    - `&temporary as *(const|mut) _`
 ///    - `ptr::from_ref(&temporary)` and friends
@@ -133,10 +130,11 @@ impl DanglingPointerSearcher<'_, '_> {
 
 fn lint_expr(cx: &LateContext<'_>, expr: &Expr<'_>) {
     if let ExprKind::MethodCall(method, receiver, _args, _span) = expr.kind
-        && matches!(method.ident.name, sym::as_ptr | sym::as_mut_ptr)
+        && let Some(fn_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id)
+        && cx.tcx.has_attr(fn_id, sym::rustc_as_ptr)
         && is_temporary_rvalue(receiver)
         && let ty = cx.typeck_results().expr_ty(receiver)
-        && is_interesting(cx.tcx, ty)
+        && owns_allocation(cx.tcx, ty)
     {
         // FIXME: use `emit_node_lint` when `#[primary_span]` is added.
         cx.tcx.emit_node_span_lint(
@@ -199,24 +197,25 @@ fn is_temporary_rvalue(expr: &Expr<'_>) -> bool {
     }
 }
 
-// Array, Vec, String, CString, MaybeUninit, Cell, Box<[_]>, Box<str>, Box<CStr>,
-// or any of the above in arbitrary many nested Box'es.
-fn is_interesting(tcx: TyCtxt<'_>, ty: Ty<'_>) -> bool {
+// Array, Vec, String, CString, MaybeUninit, Cell, Box<[_]>, Box<str>, Box<CStr>, UnsafeCell,
+// SyncUnsafeCell, or any of the above in arbitrary many nested Box'es.
+fn owns_allocation(tcx: TyCtxt<'_>, ty: Ty<'_>) -> bool {
     if ty.is_array() {
         true
     } else if let Some(inner) = ty.boxed_ty() {
         inner.is_slice()
             || inner.is_str()
             || inner.ty_adt_def().is_some_and(|def| tcx.is_lang_item(def.did(), LangItem::CStr))
-            || is_interesting(tcx, inner)
+            || owns_allocation(tcx, inner)
     } else if let Some(def) = ty.ty_adt_def() {
-        for lang_item in [LangItem::String, LangItem::MaybeUninit] {
+        for lang_item in [LangItem::String, LangItem::MaybeUninit, LangItem::UnsafeCell] {
             if tcx.is_lang_item(def.did(), lang_item) {
                 return true;
             }
         }
-        tcx.get_diagnostic_name(def.did())
-            .is_some_and(|name| matches!(name, sym::cstring_type | sym::Vec | sym::Cell))
+        tcx.get_diagnostic_name(def.did()).is_some_and(|name| {
+            matches!(name, sym::cstring_type | sym::Vec | sym::Cell | sym::SyncUnsafeCell)
+        })
     } else {
         false
     }
diff --git a/compiler/rustc_lint/src/for_loops_over_fallibles.rs b/compiler/rustc_lint/src/for_loops_over_fallibles.rs
index cf68e41243f..dbc920ea5ae 100644
--- a/compiler/rustc_lint/src/for_loops_over_fallibles.rs
+++ b/compiler/rustc_lint/src/for_loops_over_fallibles.rs
@@ -166,7 +166,7 @@ fn suggest_question_mark<'tcx>(
     }
 
     let ty = args.type_at(0);
-    let infcx = cx.tcx.infer_ctxt().build(cx.typing_mode());
+    let (infcx, param_env) = cx.tcx.infer_ctxt().build_with_typing_env(cx.typing_env());
     let ocx = ObligationCtxt::new(&infcx);
 
     let body_def_id = cx.tcx.hir().body_owner_def_id(body_id);
@@ -175,7 +175,7 @@ fn suggest_question_mark<'tcx>(
 
     ocx.register_bound(
         cause,
-        cx.param_env,
+        param_env,
         // Erase any region vids from the type, which may not be resolved
         infcx.tcx.erase_regions(ty),
         into_iterator_did,
diff --git a/compiler/rustc_lint/src/foreign_modules.rs b/compiler/rustc_lint/src/foreign_modules.rs
index 394ea798d3e..45b188205d2 100644
--- a/compiler/rustc_lint/src/foreign_modules.rs
+++ b/compiler/rustc_lint/src/foreign_modules.rs
@@ -131,7 +131,7 @@ impl ClashingExternDeclarations {
         // Check that the declarations match.
         if !structurally_same_type(
             tcx,
-            tcx.param_env(this_fi.owner_id),
+            ty::TypingEnv::non_body_analysis(tcx, this_fi.owner_id),
             existing_decl_ty,
             this_decl_ty,
             types::CItemKind::Declaration,
@@ -205,18 +205,18 @@ fn get_relevant_span(tcx: TyCtxt<'_>, fi: hir::OwnerId) -> Span {
 /// with the same members (as the declarations shouldn't clash).
 fn structurally_same_type<'tcx>(
     tcx: TyCtxt<'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
+    typing_env: ty::TypingEnv<'tcx>,
     a: Ty<'tcx>,
     b: Ty<'tcx>,
     ckind: types::CItemKind,
 ) -> bool {
     let mut seen_types = UnordSet::default();
-    let result = structurally_same_type_impl(&mut seen_types, tcx, param_env, a, b, ckind);
+    let result = structurally_same_type_impl(&mut seen_types, tcx, typing_env, a, b, ckind);
     if cfg!(debug_assertions) && result {
         // Sanity-check: must have same ABI, size and alignment.
         // `extern` blocks cannot be generic, so we'll always get a layout here.
-        let a_layout = tcx.layout_of(param_env.and(a)).unwrap();
-        let b_layout = tcx.layout_of(param_env.and(b)).unwrap();
+        let a_layout = tcx.layout_of(typing_env.as_query_input(a)).unwrap();
+        let b_layout = tcx.layout_of(typing_env.as_query_input(b)).unwrap();
         assert_eq!(a_layout.backend_repr, b_layout.backend_repr);
         assert_eq!(a_layout.size, b_layout.size);
         assert_eq!(a_layout.align, b_layout.align);
@@ -227,7 +227,7 @@ fn structurally_same_type<'tcx>(
 fn structurally_same_type_impl<'tcx>(
     seen_types: &mut UnordSet<(Ty<'tcx>, Ty<'tcx>)>,
     tcx: TyCtxt<'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
+    typing_env: ty::TypingEnv<'tcx>,
     a: Ty<'tcx>,
     b: Ty<'tcx>,
     ckind: types::CItemKind,
@@ -303,7 +303,7 @@ fn structurally_same_type_impl<'tcx>(
                             structurally_same_type_impl(
                                 seen_types,
                                 tcx,
-                                param_env,
+                                typing_env,
                                 tcx.type_of(a_did).instantiate(tcx, a_gen_args),
                                 tcx.type_of(b_did).instantiate(tcx, b_gen_args),
                                 ckind,
@@ -315,23 +315,23 @@ fn structurally_same_type_impl<'tcx>(
                     // For arrays, we also check the length.
                     a_len == b_len
                         && structurally_same_type_impl(
-                            seen_types, tcx, param_env, *a_ty, *b_ty, ckind,
+                            seen_types, tcx, typing_env, *a_ty, *b_ty, ckind,
                         )
                 }
                 (Slice(a_ty), Slice(b_ty)) => {
-                    structurally_same_type_impl(seen_types, tcx, param_env, *a_ty, *b_ty, ckind)
+                    structurally_same_type_impl(seen_types, tcx, typing_env, *a_ty, *b_ty, ckind)
                 }
                 (RawPtr(a_ty, a_mutbl), RawPtr(b_ty, b_mutbl)) => {
                     a_mutbl == b_mutbl
                         && structurally_same_type_impl(
-                            seen_types, tcx, param_env, *a_ty, *b_ty, ckind,
+                            seen_types, tcx, typing_env, *a_ty, *b_ty, ckind,
                         )
                 }
                 (Ref(_a_region, a_ty, a_mut), Ref(_b_region, b_ty, b_mut)) => {
                     // For structural sameness, we don't need the region to be same.
                     a_mut == b_mut
                         && structurally_same_type_impl(
-                            seen_types, tcx, param_env, *a_ty, *b_ty, ckind,
+                            seen_types, tcx, typing_env, *a_ty, *b_ty, ckind,
                         )
                 }
                 (FnDef(..), FnDef(..)) => {
@@ -346,12 +346,12 @@ fn structurally_same_type_impl<'tcx>(
                     (a_sig.abi, a_sig.safety, a_sig.c_variadic)
                         == (b_sig.abi, b_sig.safety, b_sig.c_variadic)
                         && a_sig.inputs().iter().eq_by(b_sig.inputs().iter(), |a, b| {
-                            structurally_same_type_impl(seen_types, tcx, param_env, *a, *b, ckind)
+                            structurally_same_type_impl(seen_types, tcx, typing_env, *a, *b, ckind)
                         })
                         && structurally_same_type_impl(
                             seen_types,
                             tcx,
-                            param_env,
+                            typing_env,
                             a_sig.output(),
                             b_sig.output(),
                             ckind,
@@ -379,14 +379,14 @@ fn structurally_same_type_impl<'tcx>(
                 // An Adt and a primitive or pointer type. This can be FFI-safe if non-null
                 // enum layout optimisation is being applied.
                 (Adt(..), _) if is_primitive_or_pointer(b) => {
-                    if let Some(a_inner) = types::repr_nullable_ptr(tcx, param_env, a, ckind) {
+                    if let Some(a_inner) = types::repr_nullable_ptr(tcx, typing_env, a, ckind) {
                         a_inner == b
                     } else {
                         false
                     }
                 }
                 (_, Adt(..)) if is_primitive_or_pointer(a) => {
-                    if let Some(b_inner) = types::repr_nullable_ptr(tcx, param_env, b, ckind) {
+                    if let Some(b_inner) = types::repr_nullable_ptr(tcx, typing_env, b, ckind) {
                         b_inner == a
                     } else {
                         false
diff --git a/compiler/rustc_lint/src/if_let_rescope.rs b/compiler/rustc_lint/src/if_let_rescope.rs
index afcfbebc14b..0e874669043 100644
--- a/compiler/rustc_lint/src/if_let_rescope.rs
+++ b/compiler/rustc_lint/src/if_let_rescope.rs
@@ -368,7 +368,7 @@ impl<'tcx, 'a> Visitor<'tcx> for FindSignificantDropper<'tcx, 'a> {
             .cx
             .typeck_results()
             .expr_ty(expr)
-            .has_significant_drop(self.cx.tcx, self.cx.param_env)
+            .has_significant_drop(self.cx.tcx, self.cx.typing_env())
         {
             return ControlFlow::Break(expr.span);
         }
diff --git a/compiler/rustc_lint/src/internal.rs b/compiler/rustc_lint/src/internal.rs
index 2f338f42f19..38c38b59bc5 100644
--- a/compiler/rustc_lint/src/internal.rs
+++ b/compiler/rustc_lint/src/internal.rs
@@ -103,7 +103,8 @@ declare_lint_pass!(QueryStability => [POTENTIAL_QUERY_INSTABILITY, UNTRACKED_QUE
 impl LateLintPass<'_> for QueryStability {
     fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
         let Some((span, def_id, args)) = typeck_results_of_method_fn(cx, expr) else { return };
-        if let Ok(Some(instance)) = ty::Instance::try_resolve(cx.tcx, cx.param_env, def_id, args) {
+        if let Ok(Some(instance)) = ty::Instance::try_resolve(cx.tcx, cx.typing_env(), def_id, args)
+        {
             let def_id = instance.def_id();
             if cx.tcx.has_attr(def_id, sym::rustc_lint_query_instability) {
                 cx.emit_span_lint(POTENTIAL_QUERY_INSTABILITY, span, QueryInstability {
@@ -544,7 +545,7 @@ impl Diagnostics {
     ) {
         // Is the callee marked with `#[rustc_lint_diagnostics]`?
         let Some(inst) =
-            ty::Instance::try_resolve(cx.tcx, cx.param_env, def_id, fn_gen_args).ok().flatten()
+            ty::Instance::try_resolve(cx.tcx, cx.typing_env(), def_id, fn_gen_args).ok().flatten()
         else {
             return;
         };
diff --git a/compiler/rustc_lint/src/let_underscore.rs b/compiler/rustc_lint/src/let_underscore.rs
index abee9ee7869..9e4e8333164 100644
--- a/compiler/rustc_lint/src/let_underscore.rs
+++ b/compiler/rustc_lint/src/let_underscore.rs
@@ -128,7 +128,7 @@ impl<'tcx> LateLintPass<'tcx> for LetUnderscore {
 
             // If the type has a trivial Drop implementation, then it doesn't
             // matter that we drop the value immediately.
-            if !ty.needs_drop(cx.tcx, cx.param_env) {
+            if !ty.needs_drop(cx.tcx, cx.typing_env()) {
                 return;
             }
             // Lint for patterns like `mutex.lock()`, which returns `Result<MutexGuard, _>` as well.
diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs
index 97a95787422..4b1dafbdbee 100644
--- a/compiler/rustc_lint/src/levels.rs
+++ b/compiler/rustc_lint/src/levels.rs
@@ -123,17 +123,19 @@ fn lints_that_dont_need_to_run(tcx: TyCtxt<'_>, (): ()) -> FxIndexSet<LintId> {
     let dont_need_to_run: FxIndexSet<LintId> = store
         .get_lints()
         .into_iter()
+        .filter(|lint| {
+            // Lints that show up in future-compat reports must always be run.
+            let has_future_breakage =
+                lint.future_incompatible.is_some_and(|fut| fut.reason.has_future_breakage());
+            !has_future_breakage && !lint.eval_always
+        })
         .filter_map(|lint| {
-            if !lint.eval_always {
-                let lint_level = map.lint_level_id_at_node(tcx, LintId::of(lint), CRATE_HIR_ID);
-                if matches!(lint_level, (Level::Allow, ..))
-                    || (matches!(lint_level, (.., LintLevelSource::Default)))
-                        && lint.default_level(tcx.sess.edition()) == Level::Allow
-                {
-                    Some(LintId::of(lint))
-                } else {
-                    None
-                }
+            let lint_level = map.lint_level_id_at_node(tcx, LintId::of(lint), CRATE_HIR_ID);
+            if matches!(lint_level, (Level::Allow, ..))
+                || (matches!(lint_level, (.., LintLevelSource::Default)))
+                    && lint.default_level(tcx.sess.edition()) == Level::Allow
+            {
+                Some(LintId::of(lint))
             } else {
                 None
             }
diff --git a/compiler/rustc_lint/src/non_fmt_panic.rs b/compiler/rustc_lint/src/non_fmt_panic.rs
index cf25ec99e67..36b1ff59c67 100644
--- a/compiler/rustc_lint/src/non_fmt_panic.rs
+++ b/compiler/rustc_lint/src/non_fmt_panic.rs
@@ -157,15 +157,17 @@ fn check_panic<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>, arg: &'tc
                 Some(ty_def) if cx.tcx.is_lang_item(ty_def.did(), LangItem::String),
             );
 
-            let infcx = cx.tcx.infer_ctxt().build(cx.typing_mode());
+            let (infcx, param_env) = cx.tcx.infer_ctxt().build_with_typing_env(cx.typing_env());
             let suggest_display = is_str
-                || cx.tcx.get_diagnostic_item(sym::Display).is_some_and(|t| {
-                    infcx.type_implements_trait(t, [ty], cx.param_env).may_apply()
-                });
+                || cx
+                    .tcx
+                    .get_diagnostic_item(sym::Display)
+                    .is_some_and(|t| infcx.type_implements_trait(t, [ty], param_env).may_apply());
             let suggest_debug = !suggest_display
-                && cx.tcx.get_diagnostic_item(sym::Debug).is_some_and(|t| {
-                    infcx.type_implements_trait(t, [ty], cx.param_env).may_apply()
-                });
+                && cx
+                    .tcx
+                    .get_diagnostic_item(sym::Debug)
+                    .is_some_and(|t| infcx.type_implements_trait(t, [ty], param_env).may_apply());
 
             let suggest_panic_any = !is_str && panic == sym::std_panic_macro;
 
diff --git a/compiler/rustc_lint/src/noop_method_call.rs b/compiler/rustc_lint/src/noop_method_call.rs
index 4890a93fa76..76dc96ae00f 100644
--- a/compiler/rustc_lint/src/noop_method_call.rs
+++ b/compiler/rustc_lint/src/noop_method_call.rs
@@ -94,9 +94,9 @@ impl<'tcx> LateLintPass<'tcx> for NoopMethodCall {
 
         let args = cx
             .tcx
-            .normalize_erasing_regions(cx.param_env, cx.typeck_results().node_args(expr.hir_id));
+            .normalize_erasing_regions(cx.typing_env(), cx.typeck_results().node_args(expr.hir_id));
         // Resolve the trait method instance.
-        let Ok(Some(i)) = ty::Instance::try_resolve(cx.tcx, cx.param_env, did, args) else {
+        let Ok(Some(i)) = ty::Instance::try_resolve(cx.tcx, cx.typing_env(), did, args) else {
             return;
         };
         // (Re)check that it implements the noop diagnostic.
diff --git a/compiler/rustc_lint/src/tail_expr_drop_order.rs b/compiler/rustc_lint/src/tail_expr_drop_order.rs
index 89763059877..19763ce1ec5 100644
--- a/compiler/rustc_lint/src/tail_expr_drop_order.rs
+++ b/compiler/rustc_lint/src/tail_expr_drop_order.rs
@@ -103,7 +103,7 @@ impl TailExprDropOrder {
         if matches!(fn_kind, hir::intravisit::FnKind::Closure) {
             for &capture in cx.tcx.closure_captures(def_id) {
                 if matches!(capture.info.capture_kind, ty::UpvarCapture::ByValue)
-                    && capture.place.ty().has_significant_drop(cx.tcx, cx.param_env)
+                    && capture.place.ty().has_significant_drop(cx.tcx, cx.typing_env())
                 {
                     locals.push(capture.var_ident.span);
                 }
@@ -113,7 +113,7 @@ impl TailExprDropOrder {
             if cx
                 .typeck_results()
                 .node_type(param.hir_id)
-                .has_significant_drop(cx.tcx, cx.param_env)
+                .has_significant_drop(cx.tcx, cx.typing_env())
             {
                 locals.push(param.span);
             }
@@ -158,7 +158,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LocalCollector<'a, 'tcx> {
     fn visit_pat(&mut self, pat: &'tcx Pat<'tcx>) {
         if let PatKind::Binding(_binding_mode, id, ident, pat) = pat.kind {
             let ty = self.cx.typeck_results().node_type(id);
-            if ty.has_significant_drop(self.cx.tcx, self.cx.param_env) {
+            if ty.has_significant_drop(self.cx.tcx, self.cx.typing_env()) {
                 self.locals.push(ident.span);
             }
             if let Some(pat) = pat {
@@ -234,7 +234,10 @@ impl<'a, 'tcx> LintTailExpr<'a, 'tcx> {
         if Self::expr_eventually_point_into_local(expr) {
             return false;
         }
-        self.cx.typeck_results().expr_ty(expr).has_significant_drop(self.cx.tcx, self.cx.param_env)
+        self.cx
+            .typeck_results()
+            .expr_ty(expr)
+            .has_significant_drop(self.cx.tcx, self.cx.typing_env())
     }
 }
 
diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs
index be70149b664..2e6cb993842 100644
--- a/compiler/rustc_lint/src/types.rs
+++ b/compiler/rustc_lint/src/types.rs
@@ -613,10 +613,11 @@ pub(crate) fn transparent_newtype_field<'a, 'tcx>(
     tcx: TyCtxt<'tcx>,
     variant: &'a ty::VariantDef,
 ) -> Option<&'a ty::FieldDef> {
-    let param_env = tcx.param_env(variant.def_id);
+    let typing_env = ty::TypingEnv::non_body_analysis(tcx, variant.def_id);
     variant.fields.iter().find(|field| {
         let field_ty = tcx.type_of(field.did).instantiate_identity();
-        let is_1zst = tcx.layout_of(param_env.and(field_ty)).is_ok_and(|layout| layout.is_1zst());
+        let is_1zst =
+            tcx.layout_of(typing_env.as_query_input(field_ty)).is_ok_and(|layout| layout.is_1zst());
         !is_1zst
     })
 }
@@ -624,11 +625,11 @@ pub(crate) fn transparent_newtype_field<'a, 'tcx>(
 /// Is type known to be non-null?
 fn ty_is_known_nonnull<'tcx>(
     tcx: TyCtxt<'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
+    typing_env: ty::TypingEnv<'tcx>,
     ty: Ty<'tcx>,
     mode: CItemKind,
 ) -> bool {
-    let ty = tcx.try_normalize_erasing_regions(param_env, ty).unwrap_or(ty);
+    let ty = tcx.try_normalize_erasing_regions(typing_env, ty).unwrap_or(ty);
 
     match ty.kind() {
         ty::FnPtr(..) => true,
@@ -649,7 +650,7 @@ fn ty_is_known_nonnull<'tcx>(
             def.variants()
                 .iter()
                 .filter_map(|variant| transparent_newtype_field(tcx, variant))
-                .any(|field| ty_is_known_nonnull(tcx, param_env, field.ty(tcx, args), mode))
+                .any(|field| ty_is_known_nonnull(tcx, typing_env, field.ty(tcx, args), mode))
         }
         _ => false,
     }
@@ -659,10 +660,10 @@ fn ty_is_known_nonnull<'tcx>(
 /// If the type passed in was not scalar, returns None.
 fn get_nullable_type<'tcx>(
     tcx: TyCtxt<'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
+    typing_env: ty::TypingEnv<'tcx>,
     ty: Ty<'tcx>,
 ) -> Option<Ty<'tcx>> {
-    let ty = tcx.try_normalize_erasing_regions(param_env, ty).unwrap_or(ty);
+    let ty = tcx.try_normalize_erasing_regions(typing_env, ty).unwrap_or(ty);
 
     Some(match *ty.kind() {
         ty::Adt(field_def, field_args) => {
@@ -679,7 +680,7 @@ fn get_nullable_type<'tcx>(
                     .expect("No non-zst fields in transparent type.")
                     .ty(tcx, field_args)
             };
-            return get_nullable_type(tcx, param_env, inner_field_ty);
+            return get_nullable_type(tcx, typing_env, inner_field_ty);
         }
         ty::Int(ty) => Ty::new_int(tcx, ty),
         ty::Uint(ty) => Ty::new_uint(tcx, ty),
@@ -708,10 +709,10 @@ fn get_nullable_type<'tcx>(
 /// - Does not have the `#[non_exhaustive]` attribute.
 fn is_niche_optimization_candidate<'tcx>(
     tcx: TyCtxt<'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
+    typing_env: ty::TypingEnv<'tcx>,
     ty: Ty<'tcx>,
 ) -> bool {
-    if tcx.layout_of(param_env.and(ty)).is_ok_and(|layout| !layout.is_1zst()) {
+    if tcx.layout_of(typing_env.as_query_input(ty)).is_ok_and(|layout| !layout.is_1zst()) {
         return false;
     }
 
@@ -734,7 +735,7 @@ fn is_niche_optimization_candidate<'tcx>(
 /// `core::ptr::NonNull`, and `#[repr(transparent)]` newtypes.
 pub(crate) fn repr_nullable_ptr<'tcx>(
     tcx: TyCtxt<'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
+    typing_env: ty::TypingEnv<'tcx>,
     ty: Ty<'tcx>,
     ckind: CItemKind,
 ) -> Option<Ty<'tcx>> {
@@ -747,9 +748,9 @@ pub(crate) fn repr_nullable_ptr<'tcx>(
                     let ty1 = field1.ty(tcx, args);
                     let ty2 = field2.ty(tcx, args);
 
-                    if is_niche_optimization_candidate(tcx, param_env, ty1) {
+                    if is_niche_optimization_candidate(tcx, typing_env, ty1) {
                         ty2
-                    } else if is_niche_optimization_candidate(tcx, param_env, ty2) {
+                    } else if is_niche_optimization_candidate(tcx, typing_env, ty2) {
                         ty1
                     } else {
                         return None;
@@ -760,20 +761,20 @@ pub(crate) fn repr_nullable_ptr<'tcx>(
             _ => return None,
         };
 
-        if !ty_is_known_nonnull(tcx, param_env, field_ty, ckind) {
+        if !ty_is_known_nonnull(tcx, typing_env, field_ty, ckind) {
             return None;
         }
 
         // At this point, the field's type is known to be nonnull and the parent enum is Option-like.
         // If the computed size for the field and the enum are different, the nonnull optimization isn't
         // being applied (and we've got a problem somewhere).
-        let compute_size_skeleton = |t| SizeSkeleton::compute(t, tcx, param_env).ok();
+        let compute_size_skeleton = |t| SizeSkeleton::compute(t, tcx, typing_env).ok();
         if !compute_size_skeleton(ty)?.same_size(compute_size_skeleton(field_ty)?) {
             bug!("improper_ctypes: Option nonnull optimization not applied?");
         }
 
         // Return the nullable type this Option-like enum can be safely represented with.
-        let field_ty_layout = tcx.layout_of(param_env.and(field_ty));
+        let field_ty_layout = tcx.layout_of(typing_env.as_query_input(field_ty));
         if field_ty_layout.is_err() && !field_ty.has_non_region_param() {
             bug!("should be able to compute the layout of non-polymorphic type");
         }
@@ -784,10 +785,10 @@ pub(crate) fn repr_nullable_ptr<'tcx>(
                 WrappingRange { start: 0, end }
                     if end == field_ty_scalar.size(&tcx).unsigned_int_max() - 1 =>
                 {
-                    return Some(get_nullable_type(tcx, param_env, field_ty).unwrap());
+                    return Some(get_nullable_type(tcx, typing_env, field_ty).unwrap());
                 }
                 WrappingRange { start: 1, .. } => {
-                    return Some(get_nullable_type(tcx, param_env, field_ty).unwrap());
+                    return Some(get_nullable_type(tcx, typing_env, field_ty).unwrap());
                 }
                 WrappingRange { start, end } => {
                     unreachable!("Unhandled start and end range: ({}, {})", start, end)
@@ -825,7 +826,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
         let field_ty = self
             .cx
             .tcx
-            .try_normalize_erasing_regions(self.cx.param_env, field_ty)
+            .try_normalize_erasing_regions(self.cx.typing_env(), field_ty)
             .unwrap_or(field_ty);
         self.check_type_for_ffi(acc, field_ty)
     }
@@ -988,7 +989,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
                         {
                             // Special-case types like `Option<extern fn()>` and `Result<extern fn(), ()>`
                             if let Some(ty) =
-                                repr_nullable_ptr(self.cx.tcx, self.cx.param_env, ty, self.mode)
+                                repr_nullable_ptr(self.cx.tcx, self.cx.typing_env(), ty, self.mode)
                             {
                                 return self.check_type_for_ffi(acc, ty);
                             }
@@ -1196,7 +1197,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
         if let Some(ty) = self
             .cx
             .tcx
-            .try_normalize_erasing_regions(self.cx.param_env, ty)
+            .try_normalize_erasing_regions(self.cx.typing_env(), ty)
             .unwrap_or(ty)
             .visit_with(&mut ProhibitOpaqueTypes)
             .break_value()
@@ -1220,7 +1221,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
             return;
         }
 
-        let ty = self.cx.tcx.try_normalize_erasing_regions(self.cx.param_env, ty).unwrap_or(ty);
+        let ty = self.cx.tcx.try_normalize_erasing_regions(self.cx.typing_env(), ty).unwrap_or(ty);
 
         // C doesn't really support passing arrays by value - the only way to pass an array by value
         // is through a struct. So, first test that the top level isn't an array, and then
diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs
index 6c13127b04e..5ec920d39f4 100644
--- a/compiler/rustc_lint/src/unused.rs
+++ b/compiler/rustc_lint/src/unused.rs
@@ -272,7 +272,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
                 || !ty.is_inhabited_from(
                     cx.tcx,
                     cx.tcx.parent_module(expr.hir_id).to_def_id(),
-                    cx.param_env,
+                    cx.typing_env(),
                 )
             {
                 return Some(MustUsePath::Suppressed);
@@ -556,7 +556,7 @@ impl<'tcx> LateLintPass<'tcx> for PathStatements {
         if let hir::StmtKind::Semi(expr) = s.kind {
             if let hir::ExprKind::Path(_) = expr.kind {
                 let ty = cx.typeck_results().expr_ty(expr);
-                if ty.needs_drop(cx.tcx, cx.param_env) {
+                if ty.needs_drop(cx.tcx, cx.typing_env()) {
                     let sub = if let Ok(snippet) = cx.sess().source_map().span_to_snippet(expr.span)
                     {
                         PathStatementDropSub::Suggestion { span: s.span, snippet }
diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs
index efdb4b077e9..313a7badf19 100644
--- a/compiler/rustc_lint_defs/src/builtin.rs
+++ b/compiler/rustc_lint_defs/src/builtin.rs
@@ -3185,6 +3185,7 @@ declare_lint! {
     pub UNEXPECTED_CFGS,
     Warn,
     "detects unexpected names and values in `#[cfg]` conditions",
+    report_in_external_macro
 }
 
 declare_lint! {
diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs
index eac4afee050..c74fceeedba 100644
--- a/compiler/rustc_lint_defs/src/lib.rs
+++ b/compiler/rustc_lint_defs/src/lib.rs
@@ -466,6 +466,20 @@ impl FutureIncompatibilityReason {
             | FutureIncompatibilityReason::Custom(_) => None,
         }
     }
+
+    pub fn has_future_breakage(self) -> bool {
+        match self {
+            FutureIncompatibilityReason::FutureReleaseErrorReportInDeps => true,
+
+            FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps
+            | FutureIncompatibilityReason::FutureReleaseSemanticsChange
+            | FutureIncompatibilityReason::EditionError(_)
+            | FutureIncompatibilityReason::EditionSemanticsChange(_)
+            | FutureIncompatibilityReason::EditionAndFutureReleaseError(_)
+            | FutureIncompatibilityReason::EditionAndFutureReleaseSemanticsChange(_)
+            | FutureIncompatibilityReason::Custom(_) => false,
+        }
+    }
 }
 
 impl FutureIncompatibleInfo {
diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs
index 493db498b7c..ace46891f83 100644
--- a/compiler/rustc_metadata/src/native_libs.rs
+++ b/compiler/rustc_metadata/src/native_libs.rs
@@ -6,7 +6,7 @@ use rustc_ast::CRATE_NODE_ID;
 use rustc_attr as attr;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_middle::query::LocalCrate;
-use rustc_middle::ty::{List, ParamEnv, ParamEnvAnd, Ty, TyCtxt};
+use rustc_middle::ty::{self, List, Ty, TyCtxt};
 use rustc_session::Session;
 use rustc_session::config::CrateType;
 use rustc_session::cstore::{
@@ -613,7 +613,7 @@ impl<'tcx> Collector<'tcx> {
             .map(|ty| {
                 let layout = self
                     .tcx
-                    .layout_of(ParamEnvAnd { param_env: ParamEnv::empty(), value: ty })
+                    .layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(ty))
                     .expect("layout")
                     .layout;
                 // In both stdcall and fastcall, we always round up the argument size to the
diff --git a/compiler/rustc_middle/src/lint.rs b/compiler/rustc_middle/src/lint.rs
index 92ba6ceee93..971d036fa69 100644
--- a/compiler/rustc_middle/src/lint.rs
+++ b/compiler/rustc_middle/src/lint.rs
@@ -290,12 +290,7 @@ pub fn lint_level(
         let has_future_breakage = future_incompatible.map_or(
             // Default allow lints trigger too often for testing.
             sess.opts.unstable_opts.future_incompat_test && lint.default_level != Level::Allow,
-            |incompat| {
-                matches!(
-                    incompat.reason,
-                    FutureIncompatibilityReason::FutureReleaseErrorReportInDeps
-                )
-            },
+            |incompat| incompat.reason.has_future_breakage(),
         );
 
         // Convert lint level to error level.
diff --git a/compiler/rustc_middle/src/mir/consts.rs b/compiler/rustc_middle/src/mir/consts.rs
index f95635370dc..a51370369b8 100644
--- a/compiler/rustc_middle/src/mir/consts.rs
+++ b/compiler/rustc_middle/src/mir/consts.rs
@@ -102,10 +102,11 @@ impl<'tcx> ConstValue<'tcx> {
     pub fn try_to_bits_for_ty(
         &self,
         tcx: TyCtxt<'tcx>,
-        param_env: ty::ParamEnv<'tcx>,
+        typing_env: ty::TypingEnv<'tcx>,
         ty: Ty<'tcx>,
     ) -> Option<u128> {
-        let size = tcx.layout_of(param_env.with_reveal_all_normalized(tcx).and(ty)).ok()?.size;
+        let size =
+            tcx.layout_of(typing_env.with_reveal_all_normalized(tcx).as_query_input(ty)).ok()?.size;
         self.try_to_bits(size)
     }
 
@@ -314,7 +315,7 @@ impl<'tcx> Const<'tcx> {
     pub fn eval(
         self,
         tcx: TyCtxt<'tcx>,
-        param_env: ty::ParamEnv<'tcx>,
+        typing_env: ty::TypingEnv<'tcx>,
         span: Span,
     ) -> Result<ConstValue<'tcx>, ErrorHandled> {
         match self {
@@ -333,7 +334,7 @@ impl<'tcx> Const<'tcx> {
             }
             Const::Unevaluated(uneval, _) => {
                 // FIXME: We might want to have a `try_eval`-like function on `Unevaluated`
-                tcx.const_eval_resolve(param_env, uneval, span)
+                tcx.const_eval_resolve(typing_env, uneval, span)
             }
             Const::Val(val, _) => Ok(val),
         }
@@ -343,7 +344,7 @@ impl<'tcx> Const<'tcx> {
     pub fn try_eval_scalar(
         self,
         tcx: TyCtxt<'tcx>,
-        param_env: ty::ParamEnv<'tcx>,
+        typing_env: ty::TypingEnv<'tcx>,
     ) -> Option<Scalar> {
         if let Const::Ty(_, c) = self
             && let ty::ConstKind::Value(ty, val) = c.kind()
@@ -354,7 +355,7 @@ impl<'tcx> Const<'tcx> {
             // pointer here, which valtrees don't represent.)
             Some(val.unwrap_leaf().into())
         } else {
-            self.eval(tcx, param_env, DUMMY_SP).ok()?.try_to_scalar()
+            self.eval(tcx, typing_env, DUMMY_SP).ok()?.try_to_scalar()
         }
     }
 
@@ -362,23 +363,29 @@ impl<'tcx> Const<'tcx> {
     pub fn try_eval_scalar_int(
         self,
         tcx: TyCtxt<'tcx>,
-        param_env: ty::ParamEnv<'tcx>,
+        typing_env: ty::TypingEnv<'tcx>,
     ) -> Option<ScalarInt> {
-        self.try_eval_scalar(tcx, param_env)?.try_to_scalar_int().ok()
+        self.try_eval_scalar(tcx, typing_env)?.try_to_scalar_int().ok()
     }
 
     #[inline]
-    pub fn try_eval_bits(&self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Option<u128> {
-        let int = self.try_eval_scalar_int(tcx, param_env)?;
-        let size =
-            tcx.layout_of(param_env.with_reveal_all_normalized(tcx).and(self.ty())).ok()?.size;
+    pub fn try_eval_bits(
+        &self,
+        tcx: TyCtxt<'tcx>,
+        typing_env: ty::TypingEnv<'tcx>,
+    ) -> Option<u128> {
+        let int = self.try_eval_scalar_int(tcx, typing_env)?;
+        let size = tcx
+            .layout_of(typing_env.with_reveal_all_normalized(tcx).as_query_input(self.ty()))
+            .ok()?
+            .size;
         Some(int.to_bits(size))
     }
 
     /// Panics if the value cannot be evaluated or doesn't contain a valid integer of the given type.
     #[inline]
-    pub fn eval_bits(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> u128 {
-        self.try_eval_bits(tcx, param_env)
+    pub fn eval_bits(self, tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>) -> u128 {
+        self.try_eval_bits(tcx, typing_env)
             .unwrap_or_else(|| bug!("expected bits of {:#?}, got {:#?}", self.ty(), self))
     }
 
@@ -386,21 +393,21 @@ impl<'tcx> Const<'tcx> {
     pub fn try_eval_target_usize(
         self,
         tcx: TyCtxt<'tcx>,
-        param_env: ty::ParamEnv<'tcx>,
+        typing_env: ty::TypingEnv<'tcx>,
     ) -> Option<u64> {
-        Some(self.try_eval_scalar_int(tcx, param_env)?.to_target_usize(tcx))
+        Some(self.try_eval_scalar_int(tcx, typing_env)?.to_target_usize(tcx))
     }
 
     #[inline]
     /// Panics if the value cannot be evaluated or doesn't contain a valid `usize`.
-    pub fn eval_target_usize(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> u64 {
-        self.try_eval_target_usize(tcx, param_env)
+    pub fn eval_target_usize(self, tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>) -> u64 {
+        self.try_eval_target_usize(tcx, typing_env)
             .unwrap_or_else(|| bug!("expected usize, got {:#?}", self))
     }
 
     #[inline]
-    pub fn try_eval_bool(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Option<bool> {
-        self.try_eval_scalar_int(tcx, param_env)?.try_into().ok()
+    pub fn try_eval_bool(self, tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>) -> Option<bool> {
+        self.try_eval_scalar_int(tcx, typing_env)?.try_into().ok()
     }
 
     #[inline]
@@ -411,17 +418,16 @@ impl<'tcx> Const<'tcx> {
     pub fn from_bits(
         tcx: TyCtxt<'tcx>,
         bits: u128,
-        param_env_ty: ty::ParamEnvAnd<'tcx, Ty<'tcx>>,
+        typing_env: ty::TypingEnv<'tcx>,
+        ty: Ty<'tcx>,
     ) -> Self {
         let size = tcx
-            .layout_of(param_env_ty)
-            .unwrap_or_else(|e| {
-                bug!("could not compute layout for {:?}: {:?}", param_env_ty.value, e)
-            })
+            .layout_of(typing_env.as_query_input(ty))
+            .unwrap_or_else(|e| bug!("could not compute layout for {ty:?}: {e:?}"))
             .size;
         let cv = ConstValue::Scalar(Scalar::from_uint(bits, size));
 
-        Self::Val(cv, param_env_ty.value)
+        Self::Val(cv, ty)
     }
 
     #[inline]
@@ -438,7 +444,8 @@ impl<'tcx> Const<'tcx> {
 
     pub fn from_usize(tcx: TyCtxt<'tcx>, n: u64) -> Self {
         let ty = tcx.types.usize;
-        Self::from_bits(tcx, n as u128, ty::ParamEnv::empty().and(ty))
+        let typing_env = ty::TypingEnv::fully_monomorphized();
+        Self::from_bits(tcx, n as u128, typing_env, ty)
     }
 
     #[inline]
diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs
index 8ec7e1851a5..08afa33c6b4 100644
--- a/compiler/rustc_middle/src/mir/interpret/error.rs
+++ b/compiler/rustc_middle/src/mir/interpret/error.rs
@@ -59,22 +59,33 @@ impl ErrorHandled {
 pub struct ReportedErrorInfo {
     error: ErrorGuaranteed,
     is_tainted_by_errors: bool,
+    /// Whether this is the kind of error that can sometimes occur, and sometimes not.
+    /// Used for resource exhaustion errors.
+    can_be_spurious: bool,
 }
 
 impl ReportedErrorInfo {
     #[inline]
     pub fn tainted_by_errors(error: ErrorGuaranteed) -> ReportedErrorInfo {
-        ReportedErrorInfo { is_tainted_by_errors: true, error }
+        ReportedErrorInfo { is_tainted_by_errors: true, can_be_spurious: false, error }
     }
+    #[inline]
+    pub fn spurious(error: ErrorGuaranteed) -> ReportedErrorInfo {
+        ReportedErrorInfo { can_be_spurious: true, is_tainted_by_errors: false, error }
+    }
+
     pub fn is_tainted_by_errors(&self) -> bool {
         self.is_tainted_by_errors
     }
+    pub fn can_be_spurious(&self) -> bool {
+        self.can_be_spurious
+    }
 }
 
 impl From<ErrorGuaranteed> for ReportedErrorInfo {
     #[inline]
     fn from(error: ErrorGuaranteed) -> ReportedErrorInfo {
-        ReportedErrorInfo { is_tainted_by_errors: false, error }
+        ReportedErrorInfo { is_tainted_by_errors: false, can_be_spurious: false, error }
     }
 }
 
diff --git a/compiler/rustc_middle/src/mir/interpret/mod.rs b/compiler/rustc_middle/src/mir/interpret/mod.rs
index f225ad94aa7..c4b0e6e39cc 100644
--- a/compiler/rustc_middle/src/mir/interpret/mod.rs
+++ b/compiler/rustc_middle/src/mir/interpret/mod.rs
@@ -351,7 +351,11 @@ impl<'tcx> GlobalAlloc<'tcx> {
         }
     }
 
-    pub fn size_and_align(&self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> (Size, Align) {
+    pub fn size_and_align(
+        &self,
+        tcx: TyCtxt<'tcx>,
+        typing_env: ty::TypingEnv<'tcx>,
+    ) -> (Size, Align) {
         match self {
             GlobalAlloc::Static(def_id) => {
                 let DefKind::Static { nested, .. } = tcx.def_kind(def_id) else {
@@ -374,7 +378,7 @@ impl<'tcx> GlobalAlloc<'tcx> {
                         .type_of(def_id)
                         .no_bound_vars()
                         .expect("statics should not have generic parameters");
-                    let layout = tcx.layout_of(param_env.and(ty)).unwrap();
+                    let layout = tcx.layout_of(typing_env.as_query_input(ty)).unwrap();
                     assert!(layout.is_sized());
                     (layout.size, layout.align.abi)
                 }
diff --git a/compiler/rustc_middle/src/mir/interpret/queries.rs b/compiler/rustc_middle/src/mir/interpret/queries.rs
index 2ecf1d0bcf8..7092f87a7d1 100644
--- a/compiler/rustc_middle/src/mir/interpret/queries.rs
+++ b/compiler/rustc_middle/src/mir/interpret/queries.rs
@@ -58,7 +58,7 @@ impl<'tcx> TyCtxt<'tcx> {
     #[instrument(level = "debug", skip(self))]
     pub fn const_eval_resolve(
         self,
-        param_env: ty::ParamEnv<'tcx>,
+        typing_env: ty::TypingEnv<'tcx>,
         ct: mir::UnevaluatedConst<'tcx>,
         span: Span,
     ) -> EvalToConstValueResult<'tcx> {
@@ -72,14 +72,11 @@ impl<'tcx> TyCtxt<'tcx> {
             bug!("did not expect inference variables here");
         }
 
-        match ty::Instance::try_resolve(
-            self, param_env,
-            // FIXME: maybe have a separate version for resolving mir::UnevaluatedConst?
-            ct.def, ct.args,
-        ) {
+        // FIXME: maybe have a separate version for resolving mir::UnevaluatedConst?
+        match ty::Instance::try_resolve(self, typing_env, ct.def, ct.args) {
             Ok(Some(instance)) => {
                 let cid = GlobalId { instance, promoted: ct.promoted };
-                self.const_eval_global_id(param_env, cid, span)
+                self.const_eval_global_id(typing_env.param_env, cid, span)
             }
             // For errors during resolution, we deliberately do not point at the usage site of the constant,
             // since for these errors the place the constant is used shouldn't matter.
@@ -91,7 +88,7 @@ impl<'tcx> TyCtxt<'tcx> {
     #[instrument(level = "debug", skip(self))]
     pub fn const_eval_resolve_for_typeck(
         self,
-        param_env: ty::ParamEnv<'tcx>,
+        typing_env: ty::TypingEnv<'tcx>,
         ct: ty::UnevaluatedConst<'tcx>,
         span: Span,
     ) -> EvalToValTreeResult<'tcx> {
@@ -105,10 +102,10 @@ impl<'tcx> TyCtxt<'tcx> {
             bug!("did not expect inference variables here");
         }
 
-        match ty::Instance::try_resolve(self, param_env, ct.def, ct.args) {
+        match ty::Instance::try_resolve(self, typing_env, ct.def, ct.args) {
             Ok(Some(instance)) => {
                 let cid = GlobalId { instance, promoted: None };
-                self.const_eval_global_id_for_typeck(param_env, cid, span).inspect(|_| {
+                self.const_eval_global_id_for_typeck(typing_env.param_env, cid, span).inspect(|_| {
                     // We are emitting the lint here instead of in `is_const_evaluatable`
                     // as we normalize obligations before checking them, and normalization
                     // uses this function to evaluate this constant.
diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs
index 260c6543f98..425cb059e57 100644
--- a/compiler/rustc_middle/src/mir/mod.rs
+++ b/compiler/rustc_middle/src/mir/mod.rs
@@ -39,7 +39,7 @@ use crate::ty::fold::{FallibleTypeFolder, TypeFoldable};
 use crate::ty::print::{FmtPrinter, Printer, pretty_print_const, with_no_trimmed_paths};
 use crate::ty::visit::TypeVisitableExt;
 use crate::ty::{
-    self, AdtDef, GenericArg, GenericArgsRef, Instance, InstanceKind, List, Ty, TyCtxt, TypingMode,
+    self, AdtDef, GenericArg, GenericArgsRef, Instance, InstanceKind, List, Ty, TyCtxt, TypingEnv,
     UserTypeAnnotationIndex,
 };
 
@@ -452,12 +452,17 @@ impl<'tcx> Body<'tcx> {
         self.basic_blocks.as_mut()
     }
 
-    pub fn typing_mode(&self, _tcx: TyCtxt<'tcx>) -> TypingMode<'tcx> {
+    pub fn typing_env(&self, tcx: TyCtxt<'tcx>) -> TypingEnv<'tcx> {
         match self.phase {
-            // FIXME(#132279): the MIR is quite clearly inside of a body, so we
-            // should instead reveal opaques defined by that body here.
-            MirPhase::Built | MirPhase::Analysis(_) => TypingMode::non_body_analysis(),
-            MirPhase::Runtime(_) => TypingMode::PostAnalysis,
+            // FIXME(#132279): we should reveal the opaques defined in the body during analysis.
+            MirPhase::Built | MirPhase::Analysis(_) => TypingEnv {
+                typing_mode: ty::TypingMode::non_body_analysis(),
+                param_env: tcx.param_env(self.source.def_id()),
+            },
+            MirPhase::Runtime(_) => TypingEnv {
+                typing_mode: ty::TypingMode::PostAnalysis,
+                param_env: tcx.param_env_reveal_all_normalized(self.source.def_id()),
+            },
         }
     }
 
@@ -618,7 +623,7 @@ impl<'tcx> Body<'tcx> {
     }
 
     /// If this basic block ends with a [`TerminatorKind::SwitchInt`] for which we can evaluate the
-    /// dimscriminant in monomorphization, we return the discriminant bits and the
+    /// discriminant in monomorphization, we return the discriminant bits and the
     /// [`SwitchTargets`], just so the caller doesn't also have to match on the terminator.
     fn try_const_mono_switchint<'a>(
         tcx: TyCtxt<'tcx>,
@@ -627,13 +632,15 @@ impl<'tcx> Body<'tcx> {
     ) -> Option<(u128, &'a SwitchTargets)> {
         // There are two places here we need to evaluate a constant.
         let eval_mono_const = |constant: &ConstOperand<'tcx>| {
-            let env = ty::ParamEnv::reveal_all();
+            // FIXME(#132279): what is this, why are we using an empty environment with
+            // `RevealAll` here.
+            let typing_env = ty::TypingEnv::fully_monomorphized();
             let mono_literal = instance.instantiate_mir_and_normalize_erasing_regions(
                 tcx,
-                env,
+                typing_env,
                 crate::ty::EarlyBinder::bind(constant.const_),
             );
-            mono_literal.try_eval_bits(tcx, env)
+            mono_literal.try_eval_bits(tcx, typing_env)
         };
 
         let TerminatorKind::SwitchInt { discr, targets } = &block.terminator().kind else {
diff --git a/compiler/rustc_middle/src/mir/statement.rs b/compiler/rustc_middle/src/mir/statement.rs
index 88ed90c3114..1ce735cec63 100644
--- a/compiler/rustc_middle/src/mir/statement.rs
+++ b/compiler/rustc_middle/src/mir/statement.rs
@@ -332,9 +332,9 @@ impl<'tcx> Operand<'tcx> {
         span: Span,
     ) -> Operand<'tcx> {
         debug_assert!({
-            let param_env_and_ty = ty::ParamEnv::empty().and(ty);
+            let typing_env = ty::TypingEnv::fully_monomorphized();
             let type_size = tcx
-                .layout_of(param_env_and_ty)
+                .layout_of(typing_env.as_query_input(ty))
                 .unwrap_or_else(|e| panic!("could not compute layout for {ty:?}: {e:?}"))
                 .size;
             let scalar_size = match val {
diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs
index f01ac305d3f..2083279e128 100644
--- a/compiler/rustc_middle/src/mir/syntax.rs
+++ b/compiler/rustc_middle/src/mir/syntax.rs
@@ -20,7 +20,7 @@ use smallvec::SmallVec;
 use super::{BasicBlock, Const, Local, UserTypeProjection};
 use crate::mir::coverage::CoverageKind;
 use crate::ty::adjustment::PointerCoercion;
-use crate::ty::{self, GenericArgsRef, List, Region, Ty, TyCtxt, UserTypeAnnotationIndex};
+use crate::ty::{self, GenericArgsRef, List, Region, Ty, UserTypeAnnotationIndex};
 
 /// Represents the "flavors" of MIR.
 ///
@@ -100,13 +100,6 @@ impl MirPhase {
             MirPhase::Runtime(RuntimePhase::Optimized) => "runtime-optimized",
         }
     }
-
-    pub fn param_env<'tcx>(&self, tcx: TyCtxt<'tcx>, body_def_id: DefId) -> ty::ParamEnv<'tcx> {
-        match self {
-            MirPhase::Built | MirPhase::Analysis(_) => tcx.param_env(body_def_id),
-            MirPhase::Runtime(_) => tcx.param_env_reveal_all_normalized(body_def_id),
-        }
-    }
 }
 
 /// See [`MirPhase::Analysis`].
diff --git a/compiler/rustc_middle/src/query/keys.rs b/compiler/rustc_middle/src/query/keys.rs
index c5def5fc65b..d2fab8e78d5 100644
--- a/compiler/rustc_middle/src/query/keys.rs
+++ b/compiler/rustc_middle/src/query/keys.rs
@@ -2,6 +2,7 @@
 
 use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE, LocalDefId, LocalModDefId, ModDefId};
 use rustc_hir::hir_id::{HirId, OwnerId};
+use rustc_query_system::dep_graph::DepNodeIndex;
 use rustc_query_system::query::{DefIdCache, DefaultCache, SingleCache, VecCache};
 use rustc_span::symbol::{Ident, Symbol};
 use rustc_span::{DUMMY_SP, Span};
@@ -111,7 +112,7 @@ impl<'tcx> Key for mir::interpret::LitToConstInput<'tcx> {
 }
 
 impl Key for CrateNum {
-    type Cache<V> = VecCache<Self, V>;
+    type Cache<V> = VecCache<Self, V, DepNodeIndex>;
 
     fn default_span(&self, _: TyCtxt<'_>) -> Span {
         DUMMY_SP
@@ -128,7 +129,7 @@ impl AsLocalKey for CrateNum {
 }
 
 impl Key for OwnerId {
-    type Cache<V> = VecCache<Self, V>;
+    type Cache<V> = VecCache<Self, V, DepNodeIndex>;
 
     fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
         self.to_def_id().default_span(tcx)
@@ -140,7 +141,7 @@ impl Key for OwnerId {
 }
 
 impl Key for LocalDefId {
-    type Cache<V> = VecCache<Self, V>;
+    type Cache<V> = VecCache<Self, V, DepNodeIndex>;
 
     fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
         self.to_def_id().default_span(tcx)
@@ -467,6 +468,18 @@ impl<'tcx, T: Key> Key for ty::ParamEnvAnd<'tcx, T> {
     }
 }
 
+impl<'tcx, T: Key> Key for ty::PseudoCanonicalInput<'tcx, T> {
+    type Cache<V> = DefaultCache<Self, V>;
+
+    fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
+        self.value.default_span(tcx)
+    }
+
+    fn ty_def_id(&self) -> Option<DefId> {
+        self.value.ty_def_id()
+    }
+}
+
 impl Key for Symbol {
     type Cache<V> = DefaultCache<Self, V>;
 
@@ -575,7 +588,7 @@ impl Key for (LocalDefId, HirId) {
     }
 }
 
-impl<'tcx> Key for (ValidityRequirement, ty::ParamEnvAnd<'tcx, Ty<'tcx>>) {
+impl<'tcx> Key for (ValidityRequirement, ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>) {
     type Cache<V> = DefaultCache<Self, V>;
 
     // Just forward to `Ty<'tcx>`
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index 4068d06f6df..684d5b6c2a7 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -81,8 +81,8 @@ use crate::ty::layout::ValidityRequirement;
 use crate::ty::print::{PrintTraitRefExt, describe_as_module};
 use crate::ty::util::AlwaysRequiresDrop;
 use crate::ty::{
-    self, CrateInherentImpls, GenericArg, GenericArgsRef, ParamEnvAnd, Ty, TyCtxt, TyCtxtFeed,
-    UnusedGenericParams,
+    self, CrateInherentImpls, GenericArg, GenericArgsRef, PseudoCanonicalInput, Ty, TyCtxt,
+    TyCtxtFeed, UnusedGenericParams,
 };
 use crate::{dep_graph, mir, thir};
 
@@ -1341,10 +1341,10 @@ rustc_queries! {
     }
 
     query codegen_select_candidate(
-        key: (ty::ParamEnv<'tcx>, ty::TraitRef<'tcx>)
+        key: PseudoCanonicalInput<'tcx, ty::TraitRef<'tcx>>
     ) -> Result<&'tcx ImplSource<'tcx, ()>, CodegenObligationError> {
         cache_on_disk_if { true }
-        desc { |tcx| "computing candidate for `{}`", key.1 }
+        desc { |tcx| "computing candidate for `{}`", key.value }
     }
 
     /// Return all `impl` blocks in the current crate.
@@ -1406,15 +1406,15 @@ rustc_queries! {
         desc { "computing whether `{}` is `Unpin`", env.value }
     }
     /// Query backing `Ty::needs_drop`.
-    query needs_drop_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
+    query needs_drop_raw(env: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>) -> bool {
         desc { "computing whether `{}` needs drop", env.value }
     }
     /// Query backing `Ty::needs_async_drop`.
-    query needs_async_drop_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
+    query needs_async_drop_raw(env: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>) -> bool {
         desc { "computing whether `{}` needs async drop", env.value }
     }
     /// Query backing `Ty::has_significant_drop_raw`.
-    query has_significant_drop_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
+    query has_significant_drop_raw(env: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>) -> bool {
         desc { "computing whether `{}` has a significant drop", env.value }
     }
 
@@ -1451,7 +1451,7 @@ rustc_queries! {
     /// Computes the layout of a type. Note that this implicitly
     /// executes in "reveal all" mode, and will normalize the input type.
     query layout_of(
-        key: ty::ParamEnvAnd<'tcx, Ty<'tcx>>
+        key: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>
     ) -> Result<ty::layout::TyAndLayout<'tcx>, &'tcx ty::layout::LayoutError<'tcx>> {
         depth_limit
         desc { "computing layout of `{}`", key.value }
@@ -1464,7 +1464,7 @@ rustc_queries! {
     /// NB: this doesn't handle virtual calls - those should use `fn_abi_of_instance`
     /// instead, where the instance is an `InstanceKind::Virtual`.
     query fn_abi_of_fn_ptr(
-        key: ty::ParamEnvAnd<'tcx, (ty::PolyFnSig<'tcx>, &'tcx ty::List<Ty<'tcx>>)>
+        key: ty::PseudoCanonicalInput<'tcx, (ty::PolyFnSig<'tcx>, &'tcx ty::List<Ty<'tcx>>)>
     ) -> Result<&'tcx rustc_target::callconv::FnAbi<'tcx, Ty<'tcx>>, &'tcx ty::layout::FnAbiError<'tcx>> {
         desc { "computing call ABI of `{}` function pointers", key.value.0 }
     }
@@ -1475,7 +1475,7 @@ rustc_queries! {
     /// NB: that includes virtual calls, which are represented by "direct calls"
     /// to an `InstanceKind::Virtual` instance (of `<dyn Trait as Trait>::fn`).
     query fn_abi_of_instance(
-        key: ty::ParamEnvAnd<'tcx, (ty::Instance<'tcx>, &'tcx ty::List<Ty<'tcx>>)>
+        key: ty::PseudoCanonicalInput<'tcx, (ty::Instance<'tcx>, &'tcx ty::List<Ty<'tcx>>)>
     ) -> Result<&'tcx rustc_target::callconv::FnAbi<'tcx, Ty<'tcx>>, &'tcx ty::layout::FnAbiError<'tcx>> {
         desc { "computing call ABI of `{}`", key.value.0 }
     }
@@ -2088,7 +2088,7 @@ rustc_queries! {
 
     /// Do not call this query directly: invoke `try_normalize_erasing_regions` instead.
     query try_normalize_generic_arg_after_erasing_regions(
-        goal: ParamEnvAnd<'tcx, GenericArg<'tcx>>
+        goal: PseudoCanonicalInput<'tcx, GenericArg<'tcx>>
     ) -> Result<GenericArg<'tcx>, NoSolution> {
         desc { "normalizing `{}`", goal.value }
     }
@@ -2245,7 +2245,7 @@ rustc_queries! {
     ///    from `Ok(None)` to avoid misleading diagnostics when an error
     ///    has already been/will be emitted, for the original cause.
     query resolve_instance_raw(
-        key: ty::ParamEnvAnd<'tcx, (DefId, GenericArgsRef<'tcx>)>
+        key: ty::PseudoCanonicalInput<'tcx, (DefId, GenericArgsRef<'tcx>)>
     ) -> Result<Option<ty::Instance<'tcx>>, ErrorGuaranteed> {
         desc { "resolving instance `{}`", ty::Instance::new(key.value.0, key.value.1) }
     }
@@ -2283,7 +2283,7 @@ rustc_queries! {
         desc { "computing the backend features for CLI flags" }
     }
 
-    query check_validity_requirement(key: (ValidityRequirement, ty::ParamEnvAnd<'tcx, Ty<'tcx>>)) -> Result<bool, &'tcx ty::layout::LayoutError<'tcx>> {
+    query check_validity_requirement(key: (ValidityRequirement, ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>)) -> Result<bool, &'tcx ty::layout::LayoutError<'tcx>> {
         desc { "checking validity requirement for `{}`: {}", key.1.value, key.0 }
     }
 
diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs
index 45ceb0a555d..8f26e05cb72 100644
--- a/compiler/rustc_middle/src/thir.rs
+++ b/compiler/rustc_middle/src/thir.rs
@@ -905,7 +905,7 @@ impl<'tcx> PatRange<'tcx> {
         &self,
         value: mir::Const<'tcx>,
         tcx: TyCtxt<'tcx>,
-        param_env: ty::ParamEnv<'tcx>,
+        typing_env: ty::TypingEnv<'tcx>,
     ) -> Option<bool> {
         use Ordering::*;
         debug_assert_eq!(self.ty, value.ty());
@@ -913,10 +913,10 @@ impl<'tcx> PatRange<'tcx> {
         let value = PatRangeBoundary::Finite(value);
         // For performance, it's important to only do the second comparison if necessary.
         Some(
-            match self.lo.compare_with(value, ty, tcx, param_env)? {
+            match self.lo.compare_with(value, ty, tcx, typing_env)? {
                 Less | Equal => true,
                 Greater => false,
-            } && match value.compare_with(self.hi, ty, tcx, param_env)? {
+            } && match value.compare_with(self.hi, ty, tcx, typing_env)? {
                 Less => true,
                 Equal => self.end == RangeEnd::Included,
                 Greater => false,
@@ -929,17 +929,17 @@ impl<'tcx> PatRange<'tcx> {
         &self,
         other: &Self,
         tcx: TyCtxt<'tcx>,
-        param_env: ty::ParamEnv<'tcx>,
+        typing_env: ty::TypingEnv<'tcx>,
     ) -> Option<bool> {
         use Ordering::*;
         debug_assert_eq!(self.ty, other.ty);
         // For performance, it's important to only do the second comparison if necessary.
         Some(
-            match other.lo.compare_with(self.hi, self.ty, tcx, param_env)? {
+            match other.lo.compare_with(self.hi, self.ty, tcx, typing_env)? {
                 Less => true,
                 Equal => self.end == RangeEnd::Included,
                 Greater => false,
-            } && match self.lo.compare_with(other.hi, self.ty, tcx, param_env)? {
+            } && match self.lo.compare_with(other.hi, self.ty, tcx, typing_env)? {
                 Less => true,
                 Equal => other.end == RangeEnd::Included,
                 Greater => false,
@@ -985,9 +985,14 @@ impl<'tcx> PatRangeBoundary<'tcx> {
             Self::NegInfinity | Self::PosInfinity => None,
         }
     }
-    pub fn eval_bits(self, ty: Ty<'tcx>, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> u128 {
+    pub fn eval_bits(
+        self,
+        ty: Ty<'tcx>,
+        tcx: TyCtxt<'tcx>,
+        typing_env: ty::TypingEnv<'tcx>,
+    ) -> u128 {
         match self {
-            Self::Finite(value) => value.eval_bits(tcx, param_env),
+            Self::Finite(value) => value.eval_bits(tcx, typing_env),
             Self::NegInfinity => {
                 // Unwrap is ok because the type is known to be numeric.
                 ty.numeric_min_and_max_as_bits(tcx).unwrap().0
@@ -999,13 +1004,13 @@ impl<'tcx> PatRangeBoundary<'tcx> {
         }
     }
 
-    #[instrument(skip(tcx, param_env), level = "debug", ret)]
+    #[instrument(skip(tcx, typing_env), level = "debug", ret)]
     pub fn compare_with(
         self,
         other: Self,
         ty: Ty<'tcx>,
         tcx: TyCtxt<'tcx>,
-        param_env: ty::ParamEnv<'tcx>,
+        typing_env: ty::TypingEnv<'tcx>,
     ) -> Option<Ordering> {
         use PatRangeBoundary::*;
         match (self, other) {
@@ -1034,8 +1039,8 @@ impl<'tcx> PatRangeBoundary<'tcx> {
             _ => {}
         }
 
-        let a = self.eval_bits(ty, tcx, param_env);
-        let b = other.eval_bits(ty, tcx, param_env);
+        let a = self.eval_bits(ty, tcx, typing_env);
+        let b = other.eval_bits(ty, tcx, typing_env);
 
         match ty.kind() {
             ty::Float(ty::FloatTy::F16) => {
diff --git a/compiler/rustc_middle/src/ty/adt.rs b/compiler/rustc_middle/src/ty/adt.rs
index 0773eb7a3be..79d56702be2 100644
--- a/compiler/rustc_middle/src/ty/adt.rs
+++ b/compiler/rustc_middle/src/ty/adt.rs
@@ -498,12 +498,13 @@ impl<'tcx> AdtDef<'tcx> {
         expr_did: DefId,
     ) -> Result<Discr<'tcx>, ErrorGuaranteed> {
         assert!(self.is_enum());
-        let param_env = tcx.param_env(expr_did);
+
         let repr_type = self.repr().discr_type();
         match tcx.const_eval_poly(expr_did) {
             Ok(val) => {
+                let typing_env = ty::TypingEnv::post_analysis(tcx, expr_did);
                 let ty = repr_type.to_ty(tcx);
-                if let Some(b) = val.try_to_bits_for_ty(tcx, param_env, ty) {
+                if let Some(b) = val.try_to_bits_for_ty(tcx, typing_env, ty) {
                     trace!("discriminants: {} ({:?})", b, repr_type);
                     Ok(Discr { val: b, ty })
                 } else {
diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs
index 5689f3d4265..d853edb34c9 100644
--- a/compiler/rustc_middle/src/ty/consts.rs
+++ b/compiler/rustc_middle/src/ty/consts.rs
@@ -1,15 +1,16 @@
+use std::borrow::Cow;
+
 use rustc_data_structures::intern::Interned;
 use rustc_error_messages::MultiSpan;
 use rustc_hir::def::{DefKind, Res};
-use rustc_hir::def_id::{DefId, LocalDefId};
-use rustc_hir::{self as hir, HirId};
+use rustc_hir::def_id::LocalDefId;
+use rustc_hir::{self as hir};
 use rustc_macros::HashStable;
 use rustc_type_ir::{self as ir, TypeFlags, WithCachedTypeInfo};
 use tracing::{debug, instrument};
 
-use crate::middle::resolve_bound_vars as rbv;
 use crate::mir::interpret::{LitToConstInput, Scalar};
-use crate::ty::{self, GenericArgs, ParamEnv, ParamEnvAnd, Ty, TyCtxt, TypeVisitableExt};
+use crate::ty::{self, GenericArgs, Ty, TyCtxt, TypeVisitableExt};
 
 mod int;
 mod kind;
@@ -142,7 +143,7 @@ impl<'tcx> Const<'tcx> {
     pub fn new_error_with_message<S: Into<MultiSpan>>(
         tcx: TyCtxt<'tcx>,
         span: S,
-        msg: &'static str,
+        msg: impl Into<Cow<'static, str>>,
     ) -> Const<'tcx> {
         let reported = tcx.dcx().span_delayed_bug(span, msg);
         Const::new_error(tcx, reported)
@@ -183,46 +184,8 @@ impl<'tcx> rustc_type_ir::inherent::Const<TyCtxt<'tcx>> for Const<'tcx> {
     }
 }
 
-/// In some cases, [`hir::ConstArg`]s that are being used in the type system
-/// through const generics need to have their type "fed" to them
-/// using the query system.
-///
-/// Use this enum with [`Const::from_const_arg`] to instruct it with the
-/// desired behavior.
-#[derive(Debug, Clone, Copy)]
-pub enum FeedConstTy {
-    /// Feed the type.
-    ///
-    /// The `DefId` belongs to the const param that we are supplying
-    /// this (anon) const arg to.
-    Param(DefId),
-    /// Don't feed the type.
-    No,
-}
-
 impl<'tcx> Const<'tcx> {
-    /// Convert a [`hir::ConstArg`] to a [`ty::Const`](Self).
-    #[instrument(skip(tcx), level = "debug")]
-    pub fn from_const_arg(
-        tcx: TyCtxt<'tcx>,
-        const_arg: &'tcx hir::ConstArg<'tcx>,
-        feed: FeedConstTy,
-    ) -> Self {
-        if let FeedConstTy::Param(param_def_id) = feed
-            && let hir::ConstArgKind::Anon(anon) = &const_arg.kind
-        {
-            tcx.feed_anon_const_type(anon.def_id, tcx.type_of(param_def_id));
-        }
-
-        match const_arg.kind {
-            hir::ConstArgKind::Path(qpath) => {
-                // FIXME(min_generic_const_args): for now only params are lowered to ConstArgKind::Path
-                Self::from_param(tcx, qpath, const_arg.hir_id)
-            }
-            hir::ConstArgKind::Anon(anon) => Self::from_anon_const(tcx, anon.def_id),
-        }
-    }
-
+    // FIXME: move this and try_from_lit to hir_ty_lowering like lower_const_arg/from_const_arg
     /// Literals and const generic parameters are eagerly converted to a constant, everything else
     /// becomes `Unevaluated`.
     #[instrument(skip(tcx), level = "debug")]
@@ -240,7 +203,7 @@ impl<'tcx> Const<'tcx> {
 
         let ty = tcx.type_of(def).no_bound_vars().expect("const parameter types cannot be generic");
 
-        match Self::try_from_lit_or_param(tcx, ty, expr) {
+        match Self::try_from_lit(tcx, ty, expr) {
             Some(v) => v,
             None => ty::Const::new_unevaluated(tcx, ty::UnevaluatedConst {
                 def: def.to_def_id(),
@@ -249,40 +212,8 @@ impl<'tcx> Const<'tcx> {
         }
     }
 
-    /// Lower a const param to a [`Const`].
-    ///
-    /// IMPORTANT: `qpath` must be a const param, otherwise this will panic
-    fn from_param(tcx: TyCtxt<'tcx>, qpath: hir::QPath<'tcx>, hir_id: HirId) -> Self {
-        let hir::QPath::Resolved(_, &hir::Path { res: Res::Def(DefKind::ConstParam, def_id), .. }) =
-            qpath
-        else {
-            span_bug!(qpath.span(), "non-param {qpath:?} passed to Const::from_param")
-        };
-
-        match tcx.named_bound_var(hir_id) {
-            Some(rbv::ResolvedArg::EarlyBound(_)) => {
-                // Find the name and index of the const parameter by indexing the generics of
-                // the parent item and construct a `ParamConst`.
-                let item_def_id = tcx.parent(def_id);
-                let generics = tcx.generics_of(item_def_id);
-                let index = generics.param_def_id_to_index[&def_id];
-                let name = tcx.item_name(def_id);
-                ty::Const::new_param(tcx, ty::ParamConst::new(index, name))
-            }
-            Some(rbv::ResolvedArg::LateBound(debruijn, index, _)) => {
-                ty::Const::new_bound(tcx, debruijn, ty::BoundVar::from_u32(index))
-            }
-            Some(rbv::ResolvedArg::Error(guar)) => ty::Const::new_error(tcx, guar),
-            arg => bug!("unexpected bound var resolution for {:?}: {arg:?}", hir_id),
-        }
-    }
-
     #[instrument(skip(tcx), level = "debug")]
-    fn try_from_lit_or_param(
-        tcx: TyCtxt<'tcx>,
-        ty: Ty<'tcx>,
-        expr: &'tcx hir::Expr<'tcx>,
-    ) -> Option<Self> {
+    fn try_from_lit(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, expr: &'tcx hir::Expr<'tcx>) -> Option<Self> {
         // Unwrap a block, so that e.g. `{ P }` is recognised as a parameter. Const arguments
         // currently have to be wrapped in curly brackets, so it's necessary to special-case.
         let expr = match &expr.kind {
@@ -321,7 +252,7 @@ impl<'tcx> Const<'tcx> {
                 Err(e) => {
                     tcx.dcx().span_delayed_bug(
                         expr.span,
-                        format!("Const::from_anon_const: couldn't lit_to_const {e:?}"),
+                        format!("Const::try_from_lit: couldn't lit_to_const {e:?}"),
                     );
                 }
             }
@@ -330,17 +261,22 @@ impl<'tcx> Const<'tcx> {
         None
     }
 
-    #[inline]
     /// Creates a constant with the given integer value and interns it.
-    pub fn from_bits(tcx: TyCtxt<'tcx>, bits: u128, ty: ParamEnvAnd<'tcx, Ty<'tcx>>) -> Self {
+    #[inline]
+    pub fn from_bits(
+        tcx: TyCtxt<'tcx>,
+        bits: u128,
+        typing_env: ty::TypingEnv<'tcx>,
+        ty: Ty<'tcx>,
+    ) -> Self {
         let size = tcx
-            .layout_of(ty)
+            .layout_of(typing_env.as_query_input(ty))
             .unwrap_or_else(|e| panic!("could not compute layout for {ty:?}: {e:?}"))
             .size;
         ty::Const::new_value(
             tcx,
             ty::ValTree::from_scalar_int(ScalarInt::try_from_uint(bits, size).unwrap()),
-            ty.value,
+            ty,
         )
     }
 
@@ -353,13 +289,13 @@ impl<'tcx> Const<'tcx> {
     #[inline]
     /// Creates an interned bool constant.
     pub fn from_bool(tcx: TyCtxt<'tcx>, v: bool) -> Self {
-        Self::from_bits(tcx, v as u128, ParamEnv::empty().and(tcx.types.bool))
+        Self::from_bits(tcx, v as u128, ty::TypingEnv::fully_monomorphized(), tcx.types.bool)
     }
 
     #[inline]
     /// Creates an interned usize constant.
     pub fn from_target_usize(tcx: TyCtxt<'tcx>, n: u64) -> Self {
-        Self::from_bits(tcx, n as u128, ParamEnv::empty().and(tcx.types.usize))
+        Self::from_bits(tcx, n as u128, ty::TypingEnv::fully_monomorphized(), tcx.types.usize)
     }
 
     /// Panics if self.kind != ty::ConstKind::Value
@@ -393,15 +329,15 @@ impl<'tcx> Const<'tcx> {
         self.try_to_valtree()?.0.try_to_target_usize(tcx)
     }
 
-    #[inline]
     /// Attempts to evaluate the given constant to bits. Can fail to evaluate in the presence of
     /// generics (or erroneous code) or if the value can't be represented as bits (e.g. because it
     /// contains const generic parameters or pointers).
-    pub fn try_to_bits(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Option<u128> {
+    #[inline]
+    pub fn try_to_bits(self, tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>) -> Option<u128> {
         let (scalar, ty) = self.try_to_scalar()?;
         let scalar = scalar.try_to_scalar_int().ok()?;
-        let size = tcx.layout_of(param_env.with_reveal_all_normalized(tcx).and(ty)).ok()?.size;
-        // if `ty` does not depend on generic parameters, use an empty param_env
+        let input = typing_env.with_reveal_all_normalized(tcx).as_query_input(ty);
+        let size = tcx.layout_of(input).ok()?.size;
         Some(scalar.to_bits(size))
     }
 
@@ -409,20 +345,3 @@ impl<'tcx> Const<'tcx> {
         matches!(self.kind(), ty::ConstKind::Infer(_))
     }
 }
-
-pub fn const_param_default<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    def_id: LocalDefId,
-) -> ty::EarlyBinder<'tcx, Const<'tcx>> {
-    let default_ct = match tcx.hir_node_by_def_id(def_id) {
-        hir::Node::GenericParam(hir::GenericParam {
-            kind: hir::GenericParamKind::Const { default: Some(ct), .. },
-            ..
-        }) => ct,
-        _ => span_bug!(
-            tcx.def_span(def_id),
-            "`const_param_default` expected a generic parameter with a constant"
-        ),
-    };
-    ty::EarlyBinder::bind(Const::from_const_arg(tcx, default_ct, FeedConstTy::No))
-}
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 84ac281c258..68c3b064eee 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -30,7 +30,7 @@ use rustc_errors::{
     Applicability, Diag, DiagCtxtHandle, ErrorGuaranteed, LintDiagnostic, MultiSpan,
 };
 use rustc_hir as hir;
-use rustc_hir::def::DefKind;
+use rustc_hir::def::{CtorKind, DefKind};
 use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE, LocalDefId};
 use rustc_hir::definitions::Definitions;
 use rustc_hir::intravisit::Visitor;
@@ -230,7 +230,9 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
             DefKind::OpaqueTy => ty::AliasTermKind::OpaqueTy,
             DefKind::TyAlias => ty::AliasTermKind::WeakTy,
             DefKind::AssocConst => ty::AliasTermKind::ProjectionConst,
-            DefKind::AnonConst => ty::AliasTermKind::UnevaluatedConst,
+            DefKind::AnonConst | DefKind::Const | DefKind::Ctor(_, CtorKind::Const) => {
+                ty::AliasTermKind::UnevaluatedConst
+            }
             kind => bug!("unexpected DefKind in AliasTy: {kind:?}"),
         }
     }
@@ -596,8 +598,16 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
         self.coroutine_is_async_gen(coroutine_def_id)
     }
 
-    fn layout_is_pointer_like(self, param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>) -> bool {
-        self.layout_of(self.erase_regions(param_env.and(ty)))
+    // We don't use `TypingEnv` here as it's only defined in `rustc_middle` and
+    // `rustc_next_trait_solver` shouldn't have to know about it.
+    fn layout_is_pointer_like(
+        self,
+        typing_mode: ty::TypingMode<'tcx>,
+        param_env: ty::ParamEnv<'tcx>,
+        ty: Ty<'tcx>,
+    ) -> bool {
+        let typing_env = ty::TypingEnv { typing_mode, param_env };
+        self.layout_of(self.erase_regions(typing_env).as_query_input(self.erase_regions(ty)))
             .is_ok_and(|layout| layout.layout.is_pointer_like(&self.data_layout))
     }
 
diff --git a/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs b/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs
index bf741f63a3d..505c7278176 100644
--- a/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs
+++ b/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs
@@ -3,7 +3,7 @@ use smallvec::SmallVec;
 use tracing::instrument;
 
 use crate::ty::context::TyCtxt;
-use crate::ty::{self, DefId, OpaqueTypeKey, ParamEnv, Ty};
+use crate::ty::{self, DefId, OpaqueTypeKey, Ty, TypingEnv};
 
 /// Represents whether some type is inhabited in a given context.
 /// Examples of uninhabited types are `!`, `enum Void {}`, or a struct
@@ -35,8 +35,13 @@ pub enum InhabitedPredicate<'tcx> {
 
 impl<'tcx> InhabitedPredicate<'tcx> {
     /// Returns true if the corresponding type is inhabited in the given `ParamEnv` and module.
-    pub fn apply(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, module_def_id: DefId) -> bool {
-        self.apply_revealing_opaque(tcx, param_env, module_def_id, &|_| None)
+    pub fn apply(
+        self,
+        tcx: TyCtxt<'tcx>,
+        typing_env: TypingEnv<'tcx>,
+        module_def_id: DefId,
+    ) -> bool {
+        self.apply_revealing_opaque(tcx, typing_env, module_def_id, &|_| None)
     }
 
     /// Returns true if the corresponding type is inhabited in the given `ParamEnv` and module,
@@ -44,13 +49,13 @@ impl<'tcx> InhabitedPredicate<'tcx> {
     pub fn apply_revealing_opaque(
         self,
         tcx: TyCtxt<'tcx>,
-        param_env: ParamEnv<'tcx>,
+        typing_env: TypingEnv<'tcx>,
         module_def_id: DefId,
         reveal_opaque: &impl Fn(OpaqueTypeKey<'tcx>) -> Option<Ty<'tcx>>,
     ) -> bool {
         let Ok(result) = self.apply_inner::<!>(
             tcx,
-            param_env,
+            typing_env,
             &mut Default::default(),
             &|id| Ok(tcx.is_descendant_of(module_def_id, id)),
             reveal_opaque,
@@ -59,25 +64,25 @@ impl<'tcx> InhabitedPredicate<'tcx> {
     }
 
     /// Same as `apply`, but returns `None` if self contains a module predicate
-    pub fn apply_any_module(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Option<bool> {
-        self.apply_inner(tcx, param_env, &mut Default::default(), &|_| Err(()), &|_| None).ok()
+    pub fn apply_any_module(self, tcx: TyCtxt<'tcx>, typing_env: TypingEnv<'tcx>) -> Option<bool> {
+        self.apply_inner(tcx, typing_env, &mut Default::default(), &|_| Err(()), &|_| None).ok()
     }
 
     /// Same as `apply`, but `NotInModule(_)` predicates yield `false`. That is,
     /// privately uninhabited types are considered always uninhabited.
-    pub fn apply_ignore_module(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> bool {
+    pub fn apply_ignore_module(self, tcx: TyCtxt<'tcx>, typing_env: TypingEnv<'tcx>) -> bool {
         let Ok(result) =
-            self.apply_inner::<!>(tcx, param_env, &mut Default::default(), &|_| Ok(true), &|_| {
+            self.apply_inner::<!>(tcx, typing_env, &mut Default::default(), &|_| Ok(true), &|_| {
                 None
             });
         result
     }
 
-    #[instrument(level = "debug", skip(tcx, param_env, in_module, reveal_opaque), ret)]
+    #[instrument(level = "debug", skip(tcx, typing_env, in_module, reveal_opaque), ret)]
     fn apply_inner<E: std::fmt::Debug>(
         self,
         tcx: TyCtxt<'tcx>,
-        param_env: ParamEnv<'tcx>,
+        typing_env: TypingEnv<'tcx>,
         eval_stack: &mut SmallVec<[Ty<'tcx>; 1]>, // for cycle detection
         in_module: &impl Fn(DefId) -> Result<bool, E>,
         reveal_opaque: &impl Fn(OpaqueTypeKey<'tcx>) -> Option<Ty<'tcx>>,
@@ -94,7 +99,7 @@ impl<'tcx> InhabitedPredicate<'tcx> {
             // we have a param_env available, we can do better.
             Self::GenericType(t) => {
                 let normalized_pred = tcx
-                    .try_normalize_erasing_regions(param_env, t)
+                    .try_normalize_erasing_regions(typing_env, t)
                     .map_or(self, |t| t.inhabited_predicate(tcx));
                 match normalized_pred {
                     // We don't have more information than we started with, so consider inhabited.
@@ -107,7 +112,7 @@ impl<'tcx> InhabitedPredicate<'tcx> {
                         }
                         eval_stack.push(t);
                         let ret =
-                            pred.apply_inner(tcx, param_env, eval_stack, in_module, reveal_opaque);
+                            pred.apply_inner(tcx, typing_env, eval_stack, in_module, reveal_opaque);
                         eval_stack.pop();
                         ret
                     }
@@ -126,7 +131,7 @@ impl<'tcx> InhabitedPredicate<'tcx> {
                     eval_stack.push(t);
                     let ret = t.inhabited_predicate(tcx).apply_inner(
                         tcx,
-                        param_env,
+                        typing_env,
                         eval_stack,
                         in_module,
                         reveal_opaque,
@@ -136,10 +141,10 @@ impl<'tcx> InhabitedPredicate<'tcx> {
                 }
             },
             Self::And([a, b]) => try_and(a, b, |x| {
-                x.apply_inner(tcx, param_env, eval_stack, in_module, reveal_opaque)
+                x.apply_inner(tcx, typing_env, eval_stack, in_module, reveal_opaque)
             }),
             Self::Or([a, b]) => try_or(a, b, |x| {
-                x.apply_inner(tcx, param_env, eval_stack, in_module, reveal_opaque)
+                x.apply_inner(tcx, typing_env, eval_stack, in_module, reveal_opaque)
             }),
         }
     }
diff --git a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs
index dd00db8635f..4a5f6d80f24 100644
--- a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs
+++ b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs
@@ -181,18 +181,18 @@ impl<'tcx> Ty<'tcx> {
         self,
         tcx: TyCtxt<'tcx>,
         module: DefId,
-        param_env: ty::ParamEnv<'tcx>,
+        typing_env: ty::TypingEnv<'tcx>,
     ) -> bool {
-        self.inhabited_predicate(tcx).apply(tcx, param_env, module)
+        self.inhabited_predicate(tcx).apply(tcx, typing_env, module)
     }
 
     /// Returns true if the type is uninhabited without regard to visibility
     pub fn is_privately_uninhabited(
         self,
         tcx: TyCtxt<'tcx>,
-        param_env: ty::ParamEnv<'tcx>,
+        typing_env: ty::TypingEnv<'tcx>,
     ) -> bool {
-        !self.inhabited_predicate(tcx).apply_ignore_module(tcx, param_env)
+        !self.inhabited_predicate(tcx).apply_ignore_module(tcx, typing_env)
     }
 }
 
diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs
index 0d1c56f0d38..d42b6be4787 100644
--- a/compiler/rustc_middle/src/ty/instance.rs
+++ b/compiler/rustc_middle/src/ty/instance.rs
@@ -178,9 +178,9 @@ pub enum InstanceKind<'tcx> {
 impl<'tcx> Instance<'tcx> {
     /// Returns the `Ty` corresponding to this `Instance`, with generic instantiations applied and
     /// lifetimes erased, allowing a `ParamEnv` to be specified for use during normalization.
-    pub fn ty(&self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Ty<'tcx> {
+    pub fn ty(&self, tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>) -> Ty<'tcx> {
         let ty = tcx.type_of(self.def.def_id());
-        tcx.instantiate_and_normalize_erasing_regions(self.args, param_env, ty)
+        tcx.instantiate_and_normalize_erasing_regions(self.args, typing_env, ty)
     }
 
     /// Finds a crate that contains a monomorphization of this instance that
@@ -519,7 +519,7 @@ impl<'tcx> Instance<'tcx> {
     #[instrument(level = "debug", skip(tcx), ret)]
     pub fn try_resolve(
         tcx: TyCtxt<'tcx>,
-        param_env: ty::ParamEnv<'tcx>,
+        typing_env: ty::TypingEnv<'tcx>,
         def_id: DefId,
         args: GenericArgsRef<'tcx>,
     ) -> Result<Option<Instance<'tcx>>, ErrorGuaranteed> {
@@ -537,17 +537,14 @@ impl<'tcx> Instance<'tcx> {
 
         // All regions in the result of this query are erased, so it's
         // fine to erase all of the input regions.
-
-        // HACK(eddyb) erase regions in `args` first, so that `param_env.and(...)`
-        // below is more likely to ignore the bounds in scope (e.g. if the only
-        // generic parameters mentioned by `args` were lifetime ones).
+        let typing_env = tcx.erase_regions(typing_env);
         let args = tcx.erase_regions(args);
-        tcx.resolve_instance_raw(tcx.erase_regions(param_env.and((def_id, args))))
+        tcx.resolve_instance_raw(typing_env.as_query_input((def_id, args)))
     }
 
     pub fn expect_resolve(
         tcx: TyCtxt<'tcx>,
-        param_env: ty::ParamEnv<'tcx>,
+        typing_env: ty::TypingEnv<'tcx>,
         def_id: DefId,
         args: GenericArgsRef<'tcx>,
         span: Span,
@@ -558,7 +555,7 @@ impl<'tcx> Instance<'tcx> {
         let span_or_local_def_span =
             || if span.is_dummy() && def_id.is_local() { tcx.def_span(def_id) } else { span };
 
-        match ty::Instance::try_resolve(tcx, param_env, def_id, args) {
+        match ty::Instance::try_resolve(tcx, typing_env, def_id, args) {
             Ok(Some(instance)) => instance,
             Ok(None) => {
                 let type_length = type_length(args);
@@ -600,7 +597,7 @@ impl<'tcx> Instance<'tcx> {
 
     pub fn resolve_for_fn_ptr(
         tcx: TyCtxt<'tcx>,
-        param_env: ty::ParamEnv<'tcx>,
+        typing_env: ty::TypingEnv<'tcx>,
         def_id: DefId,
         args: GenericArgsRef<'tcx>,
     ) -> Option<Instance<'tcx>> {
@@ -608,7 +605,7 @@ impl<'tcx> Instance<'tcx> {
         // Use either `resolve_closure` or `resolve_for_vtable`
         assert!(!tcx.is_closure_like(def_id), "Called `resolve_for_fn_ptr` on closure: {def_id:?}");
         let reason = tcx.sess.is_sanitizer_kcfi_enabled().then_some(ReifyReason::FnPtr);
-        Instance::try_resolve(tcx, param_env, def_id, args).ok().flatten().map(|mut resolved| {
+        Instance::try_resolve(tcx, typing_env, def_id, args).ok().flatten().map(|mut resolved| {
             match resolved.def {
                 InstanceKind::Item(def) if resolved.def.requires_caller_location(tcx) => {
                     debug!(" => fn pointer created for function with #[track_caller]");
@@ -648,7 +645,7 @@ impl<'tcx> Instance<'tcx> {
 
     pub fn expect_resolve_for_vtable(
         tcx: TyCtxt<'tcx>,
-        param_env: ty::ParamEnv<'tcx>,
+        typing_env: ty::TypingEnv<'tcx>,
         def_id: DefId,
         args: GenericArgsRef<'tcx>,
         span: Span,
@@ -664,7 +661,7 @@ impl<'tcx> Instance<'tcx> {
             return Instance { def: InstanceKind::VTableShim(def_id), args };
         }
 
-        let mut resolved = Instance::expect_resolve(tcx, param_env, def_id, args, span);
+        let mut resolved = Instance::expect_resolve(tcx, typing_env, def_id, args, span);
 
         let reason = tcx.sess.is_sanitizer_kcfi_enabled().then_some(ReifyReason::Vtable);
         match resolved.def {
@@ -743,7 +740,7 @@ impl<'tcx> Instance<'tcx> {
         let args = tcx.mk_args(&[ty.into()]);
         Instance::expect_resolve(
             tcx,
-            ty::ParamEnv::reveal_all(),
+            ty::TypingEnv::fully_monomorphized(),
             def_id,
             args,
             ty.ty_adt_def().and_then(|adt| tcx.hir().span_if_local(adt.did())).unwrap_or(DUMMY_SP),
@@ -755,7 +752,7 @@ impl<'tcx> Instance<'tcx> {
         let args = tcx.mk_args(&[ty.into()]);
         Instance::expect_resolve(
             tcx,
-            ty::ParamEnv::reveal_all(),
+            ty::TypingEnv::fully_monomorphized(),
             def_id,
             args,
             ty.ty_adt_def().and_then(|adt| tcx.hir().span_if_local(adt.did())).unwrap_or(DUMMY_SP),
@@ -883,16 +880,16 @@ impl<'tcx> Instance<'tcx> {
     pub fn instantiate_mir_and_normalize_erasing_regions<T>(
         &self,
         tcx: TyCtxt<'tcx>,
-        param_env: ty::ParamEnv<'tcx>,
+        typing_env: ty::TypingEnv<'tcx>,
         v: EarlyBinder<'tcx, T>,
     ) -> T
     where
         T: TypeFoldable<TyCtxt<'tcx>>,
     {
         if let Some(args) = self.args_for_mir_body() {
-            tcx.instantiate_and_normalize_erasing_regions(args, param_env, v)
+            tcx.instantiate_and_normalize_erasing_regions(args, typing_env, v)
         } else {
-            tcx.normalize_erasing_regions(param_env, v.instantiate_identity())
+            tcx.normalize_erasing_regions(typing_env, v.instantiate_identity())
         }
     }
 
@@ -901,21 +898,21 @@ impl<'tcx> Instance<'tcx> {
     pub fn try_instantiate_mir_and_normalize_erasing_regions<T>(
         &self,
         tcx: TyCtxt<'tcx>,
-        param_env: ty::ParamEnv<'tcx>,
+        typing_env: ty::TypingEnv<'tcx>,
         v: EarlyBinder<'tcx, T>,
     ) -> Result<T, NormalizationError<'tcx>>
     where
         T: TypeFoldable<TyCtxt<'tcx>>,
     {
         if let Some(args) = self.args_for_mir_body() {
-            tcx.try_instantiate_and_normalize_erasing_regions(args, param_env, v)
+            tcx.try_instantiate_and_normalize_erasing_regions(args, typing_env, v)
         } else {
             // We're using `instantiate_identity` as e.g.
             // `FnPtrShim` is separately generated for every
             // instantiation of the `FnDef`, so the MIR body
             // is already instantiated. Any generic parameters it
             // contains are generic parameters from the caller.
-            tcx.try_normalize_erasing_regions(param_env, v.instantiate_identity())
+            tcx.try_normalize_erasing_regions(typing_env, v.instantiate_identity())
         }
     }
 
diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs
index a0eb9029319..8625a8dcb2a 100644
--- a/compiler/rustc_middle/src/ty/layout.rs
+++ b/compiler/rustc_middle/src/ty/layout.rs
@@ -297,12 +297,12 @@ impl<'tcx> IntoDiagArg for LayoutError<'tcx> {
 #[derive(Clone, Copy)]
 pub struct LayoutCx<'tcx> {
     pub calc: abi::LayoutCalculator<TyCtxt<'tcx>>,
-    pub param_env: ty::ParamEnv<'tcx>,
+    pub typing_env: ty::TypingEnv<'tcx>,
 }
 
 impl<'tcx> LayoutCx<'tcx> {
-    pub fn new(tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Self {
-        Self { calc: abi::LayoutCalculator::new(tcx), param_env }
+    pub fn new(tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>) -> Self {
+        Self { calc: abi::LayoutCalculator::new(tcx), typing_env }
     }
 }
 
@@ -337,12 +337,12 @@ impl<'tcx> SizeSkeleton<'tcx> {
     pub fn compute(
         ty: Ty<'tcx>,
         tcx: TyCtxt<'tcx>,
-        param_env: ty::ParamEnv<'tcx>,
+        typing_env: ty::TypingEnv<'tcx>,
     ) -> Result<SizeSkeleton<'tcx>, &'tcx LayoutError<'tcx>> {
         debug_assert!(!ty.has_non_region_infer());
 
         // First try computing a static layout.
-        let err = match tcx.layout_of(param_env.and(ty)) {
+        let err = match tcx.layout_of(typing_env.as_query_input(ty)) {
             Ok(layout) => {
                 if layout.is_sized() {
                     return Ok(SizeSkeleton::Known(layout.size, Some(layout.align.abi)));
@@ -367,7 +367,7 @@ impl<'tcx> SizeSkeleton<'tcx> {
 
                 let tail = tcx.struct_tail_raw(
                     pointee,
-                    |ty| match tcx.try_normalize_erasing_regions(param_env, ty) {
+                    |ty| match tcx.try_normalize_erasing_regions(typing_env, ty) {
                         Ok(ty) => ty,
                         Err(e) => Ty::new_error_with_message(
                             tcx,
@@ -402,7 +402,7 @@ impl<'tcx> SizeSkeleton<'tcx> {
                     return Ok(SizeSkeleton::Known(Size::from_bytes(0), None));
                 }
 
-                match SizeSkeleton::compute(inner, tcx, param_env)? {
+                match SizeSkeleton::compute(inner, tcx, typing_env)? {
                     // This may succeed because the multiplication of two types may overflow
                     // but a single size of a nested array will not.
                     SizeSkeleton::Known(s, a) => {
@@ -432,7 +432,7 @@ impl<'tcx> SizeSkeleton<'tcx> {
                     let i = VariantIdx::from_usize(i);
                     let fields =
                         def.variant(i).fields.iter().map(|field| {
-                            SizeSkeleton::compute(field.ty(tcx, args), tcx, param_env)
+                            SizeSkeleton::compute(field.ty(tcx, args), tcx, typing_env)
                         });
                     let mut ptr = None;
                     for field in fields {
@@ -491,11 +491,11 @@ impl<'tcx> SizeSkeleton<'tcx> {
             }
 
             ty::Alias(..) => {
-                let normalized = tcx.normalize_erasing_regions(param_env, ty);
+                let normalized = tcx.normalize_erasing_regions(typing_env, ty);
                 if ty == normalized {
                     Err(err)
                 } else {
-                    SizeSkeleton::compute(normalized, tcx, param_env)
+                    SizeSkeleton::compute(normalized, tcx, typing_env)
                 }
             }
 
@@ -521,8 +521,14 @@ pub trait HasTyCtxt<'tcx>: HasDataLayout {
     fn tcx(&self) -> TyCtxt<'tcx>;
 }
 
-pub trait HasParamEnv<'tcx> {
-    fn param_env(&self) -> ty::ParamEnv<'tcx>;
+pub trait HasTypingEnv<'tcx> {
+    fn typing_env(&self) -> ty::TypingEnv<'tcx>;
+
+    /// FIXME(#132279): This method should not be used as in the future
+    /// everything should take a `TypingEnv` instead. Remove it as that point.
+    fn param_env(&self) -> ty::ParamEnv<'tcx> {
+        self.typing_env().param_env
+    }
 }
 
 impl<'tcx> HasDataLayout for TyCtxt<'tcx> {
@@ -577,9 +583,9 @@ impl<'tcx> HasTyCtxt<'tcx> for TyCtxtAt<'tcx> {
     }
 }
 
-impl<'tcx> HasParamEnv<'tcx> for LayoutCx<'tcx> {
-    fn param_env(&self) -> ty::ParamEnv<'tcx> {
-        self.param_env
+impl<'tcx> HasTypingEnv<'tcx> for LayoutCx<'tcx> {
+    fn typing_env(&self) -> ty::TypingEnv<'tcx> {
+        self.typing_env
     }
 }
 
@@ -646,7 +652,7 @@ pub type TyAndLayout<'tcx> = rustc_abi::TyAndLayout<'tcx, Ty<'tcx>>;
 
 /// Trait for contexts that want to be able to compute layouts of types.
 /// This automatically gives access to `LayoutOf`, through a blanket `impl`.
-pub trait LayoutOfHelpers<'tcx>: HasDataLayout + HasTyCtxt<'tcx> + HasParamEnv<'tcx> {
+pub trait LayoutOfHelpers<'tcx>: HasDataLayout + HasTyCtxt<'tcx> + HasTypingEnv<'tcx> {
     /// The `TyAndLayout`-wrapping type (or `TyAndLayout` itself), which will be
     /// returned from `layout_of` (see also `handle_layout_err`).
     type LayoutOfResult: MaybeResult<TyAndLayout<'tcx>> = TyAndLayout<'tcx>;
@@ -692,7 +698,7 @@ pub trait LayoutOf<'tcx>: LayoutOfHelpers<'tcx> {
         let tcx = self.tcx().at(span);
 
         MaybeResult::from(
-            tcx.layout_of(self.param_env().and(ty))
+            tcx.layout_of(self.typing_env().as_query_input(ty))
                 .map_err(|err| self.handle_layout_err(*err, span, ty)),
         )
     }
@@ -716,7 +722,7 @@ impl<'tcx> LayoutOfHelpers<'tcx> for LayoutCx<'tcx> {
 
 impl<'tcx, C> TyAbiInterface<'tcx, C> for Ty<'tcx>
 where
-    C: HasTyCtxt<'tcx> + HasParamEnv<'tcx>,
+    C: HasTyCtxt<'tcx> + HasTypingEnv<'tcx>,
 {
     fn ty_and_layout_for_variant(
         this: TyAndLayout<'tcx>,
@@ -736,10 +742,10 @@ where
 
             Variants::Single { index } => {
                 let tcx = cx.tcx();
-                let param_env = cx.param_env();
+                let typing_env = cx.typing_env();
 
                 // Deny calling for_variant more than once for non-Single enums.
-                if let Ok(original_layout) = tcx.layout_of(param_env.and(this.ty)) {
+                if let Ok(original_layout) = tcx.layout_of(typing_env.as_query_input(this.ty)) {
                     assert_eq!(original_layout.variants, Variants::Single { index });
                 }
 
@@ -780,7 +786,7 @@ where
 
         fn field_ty_or_layout<'tcx>(
             this: TyAndLayout<'tcx>,
-            cx: &(impl HasTyCtxt<'tcx> + HasParamEnv<'tcx>),
+            cx: &(impl HasTyCtxt<'tcx> + HasTypingEnv<'tcx>),
             i: usize,
         ) -> TyMaybeWithLayout<'tcx> {
             let tcx = cx.tcx();
@@ -823,12 +829,13 @@ where
                             Ty::new_mut_ref(tcx, tcx.lifetimes.re_static, nil)
                         };
 
-                        // NOTE(eddyb) using an empty `ParamEnv`, and `unwrap`-ing
-                        // the `Result` should always work because the type is
-                        // always either `*mut ()` or `&'static mut ()`.
+                        // NOTE: using an fully monomorphized typing env and `unwrap`-ing
+                        // the `Result` should always work because the type is always either
+                        // `*mut ()` or `&'static mut ()`.
+                        let typing_env = ty::TypingEnv::fully_monomorphized();
                         return TyMaybeWithLayout::TyAndLayout(TyAndLayout {
                             ty: this.ty,
-                            ..tcx.layout_of(ty::ParamEnv::reveal_all().and(unit_ptr_ty)).unwrap()
+                            ..tcx.layout_of(typing_env.as_query_input(unit_ptr_ty)).unwrap()
                         });
                     }
 
@@ -848,7 +855,7 @@ where
                         && !pointee.references_error()
                     {
                         let metadata = tcx.normalize_erasing_regions(
-                            cx.param_env(),
+                            cx.typing_env(),
                             Ty::new_projection(tcx, metadata_def_id, [pointee]),
                         );
 
@@ -865,7 +872,7 @@ where
                             metadata
                         }
                     } else {
-                        match tcx.struct_tail_for_codegen(pointee, cx.param_env()).kind() {
+                        match tcx.struct_tail_for_codegen(pointee, cx.typing_env()).kind() {
                             ty::Slice(_) | ty::Str => tcx.types.usize,
                             ty::Dynamic(data, _, ty::Dyn) => mk_dyn_vtable(data.principal()),
                             _ => bug!("TyAndLayout::field({:?}): not applicable", this),
@@ -953,7 +960,7 @@ where
 
         match field_ty_or_layout(this, cx, i) {
             TyMaybeWithLayout::Ty(field_ty) => {
-                cx.tcx().layout_of(cx.param_env().and(field_ty)).unwrap_or_else(|e| {
+                cx.tcx().layout_of(cx.typing_env().as_query_input(field_ty)).unwrap_or_else(|e| {
                     bug!(
                         "failed to get layout for `{field_ty}`: {e:?},\n\
                          despite it being a field (#{i}) of an existing layout: {this:#?}",
@@ -972,18 +979,18 @@ where
         offset: Size,
     ) -> Option<PointeeInfo> {
         let tcx = cx.tcx();
-        let param_env = cx.param_env();
+        let typing_env = cx.typing_env();
 
         let pointee_info = match *this.ty.kind() {
             ty::RawPtr(p_ty, _) if offset.bytes() == 0 => {
-                tcx.layout_of(param_env.and(p_ty)).ok().map(|layout| PointeeInfo {
+                tcx.layout_of(typing_env.as_query_input(p_ty)).ok().map(|layout| PointeeInfo {
                     size: layout.size,
                     align: layout.align.abi,
                     safe: None,
                 })
             }
             ty::FnPtr(..) if offset.bytes() == 0 => {
-                tcx.layout_of(param_env.and(this.ty)).ok().map(|layout| PointeeInfo {
+                tcx.layout_of(typing_env.as_query_input(this.ty)).ok().map(|layout| PointeeInfo {
                     size: layout.size,
                     align: layout.align.abi,
                     safe: None,
@@ -996,14 +1003,14 @@ where
                 let optimize = tcx.sess.opts.optimize != OptLevel::No;
                 let kind = match mt {
                     hir::Mutability::Not => PointerKind::SharedRef {
-                        frozen: optimize && ty.is_freeze(tcx, cx.param_env()),
+                        frozen: optimize && ty.is_freeze(tcx, typing_env.param_env),
                     },
                     hir::Mutability::Mut => PointerKind::MutableRef {
-                        unpin: optimize && ty.is_unpin(tcx, cx.param_env()),
+                        unpin: optimize && ty.is_unpin(tcx, typing_env.param_env),
                     },
                 };
 
-                tcx.layout_of(param_env.and(ty)).ok().map(|layout| PointeeInfo {
+                tcx.layout_of(typing_env.as_query_input(ty)).ok().map(|layout| PointeeInfo {
                     size: layout.size,
                     align: layout.align.abi,
                     safe: Some(kind),
@@ -1093,7 +1100,7 @@ where
                         debug_assert!(pointee.safe.is_none());
                         let optimize = tcx.sess.opts.optimize != OptLevel::No;
                         pointee.safe = Some(PointerKind::Box {
-                            unpin: optimize && boxed_ty.is_unpin(tcx, cx.param_env()),
+                            unpin: optimize && boxed_ty.is_unpin(tcx, typing_env.param_env),
                             global: this.ty.is_box_global(tcx),
                         });
                     }
@@ -1304,9 +1311,11 @@ pub trait FnAbiOf<'tcx>: FnAbiOfHelpers<'tcx> {
         let span = self.layout_tcx_at_span();
         let tcx = self.tcx().at(span);
 
-        MaybeResult::from(tcx.fn_abi_of_fn_ptr(self.param_env().and((sig, extra_args))).map_err(
-            |err| self.handle_fn_abi_err(*err, span, FnAbiRequest::OfFnPtr { sig, extra_args }),
-        ))
+        MaybeResult::from(
+            tcx.fn_abi_of_fn_ptr(self.typing_env().as_query_input((sig, extra_args))).map_err(
+                |err| self.handle_fn_abi_err(*err, span, FnAbiRequest::OfFnPtr { sig, extra_args }),
+            ),
+        )
     }
 
     /// Compute a `FnAbi` suitable for declaring/defining an `fn` instance, and for
@@ -1326,17 +1335,19 @@ pub trait FnAbiOf<'tcx>: FnAbiOfHelpers<'tcx> {
         let tcx = self.tcx().at(span);
 
         MaybeResult::from(
-            tcx.fn_abi_of_instance(self.param_env().and((instance, extra_args))).map_err(|err| {
-                // HACK(eddyb) at least for definitions of/calls to `Instance`s,
-                // we can get some kind of span even if one wasn't provided.
-                // However, we don't do this early in order to avoid calling
-                // `def_span` unconditionally (which may have a perf penalty).
-                let span = if !span.is_dummy() { span } else { tcx.def_span(instance.def_id()) };
-                self.handle_fn_abi_err(*err, span, FnAbiRequest::OfInstance {
-                    instance,
-                    extra_args,
-                })
-            }),
+            tcx.fn_abi_of_instance(self.typing_env().as_query_input((instance, extra_args)))
+                .map_err(|err| {
+                    // HACK(eddyb) at least for definitions of/calls to `Instance`s,
+                    // we can get some kind of span even if one wasn't provided.
+                    // However, we don't do this early in order to avoid calling
+                    // `def_span` unconditionally (which may have a perf penalty).
+                    let span =
+                        if !span.is_dummy() { span } else { tcx.def_span(instance.def_id()) };
+                    self.handle_fn_abi_err(*err, span, FnAbiRequest::OfInstance {
+                        instance,
+                        extra_args,
+                    })
+                }),
         )
     }
 }
@@ -1346,14 +1357,14 @@ impl<'tcx, C: FnAbiOfHelpers<'tcx>> FnAbiOf<'tcx> for C {}
 impl<'tcx> TyCtxt<'tcx> {
     pub fn offset_of_subfield<I>(
         self,
-        param_env: ty::ParamEnv<'tcx>,
+        typing_env: ty::TypingEnv<'tcx>,
         mut layout: TyAndLayout<'tcx>,
         indices: I,
     ) -> Size
     where
         I: Iterator<Item = (VariantIdx, FieldIdx)>,
     {
-        let cx = LayoutCx::new(self, param_env);
+        let cx = LayoutCx::new(self, typing_env);
         let mut offset = Size::ZERO;
 
         for (variant, field) in indices {
@@ -1363,7 +1374,7 @@ impl<'tcx> TyCtxt<'tcx> {
             layout = layout.field(&cx, index);
             if !layout.is_sized() {
                 // If it is not sized, then the tail must still have at least a known static alignment.
-                let tail = self.struct_tail_for_codegen(layout.ty, param_env);
+                let tail = self.struct_tail_for_codegen(layout.ty, typing_env);
                 if !matches!(tail.kind(), ty::Slice(..)) {
                     bug!(
                         "offset of not-statically-aligned field (type {:?}) cannot be computed statically",
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 7fda0662a34..965a8c8c95e 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -62,7 +62,7 @@ pub use self::closure::{
     place_to_string_for_capture,
 };
 pub use self::consts::{
-    Const, ConstInt, ConstKind, Expr, ExprKind, FeedConstTy, ScalarInt, UnevaluatedConst, ValTree,
+    Const, ConstInt, ConstKind, Expr, ExprKind, ScalarInt, UnevaluatedConst, ValTree,
 };
 pub use self::context::{
     CtxtInterners, CurrentGcx, DeducedParamAttrs, Feed, FreeRegionInfo, GlobalCtxt, Lift, TyCtxt,
@@ -103,7 +103,7 @@ use crate::error::{OpaqueHiddenTypeMismatch, TypeMismatchReason};
 use crate::metadata::ModChild;
 use crate::middle::privacy::EffectiveVisibilities;
 use crate::mir::{Body, CoroutineLayout};
-use crate::query::Providers;
+use crate::query::{IntoQueryParam, Providers};
 use crate::traits::{self, Reveal};
 use crate::ty;
 pub use crate::ty::diagnostics::*;
@@ -1122,6 +1122,105 @@ impl<'tcx, T> ParamEnvAnd<'tcx, T> {
     }
 }
 
+/// The environment in which to do trait solving.
+///
+/// Most of the time you only need to care about the `ParamEnv`
+/// as the `TypingMode` is simply stored in the `InferCtxt`.
+///
+/// However, there are some places which rely on trait solving
+/// without using an `InferCtxt` themselves. For these to be
+/// able to use the trait system they have to be able to initialize
+/// such an `InferCtxt` with the right `typing_mode`, so they need
+/// to track both.
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable)]
+#[derive(TypeVisitable, TypeFoldable)]
+pub struct TypingEnv<'tcx> {
+    pub typing_mode: TypingMode<'tcx>,
+    pub param_env: ParamEnv<'tcx>,
+}
+
+impl<'tcx> TypingEnv<'tcx> {
+    // FIXME(#132279): This method should be removed but simplifies the
+    // transition.
+    pub fn from_param_env(param_env: ParamEnv<'tcx>) -> TypingEnv<'tcx> {
+        TypingEnv { typing_mode: TypingMode::from_param_env(param_env), param_env }
+    }
+
+    /// Create a typing environment with no where-clauses in scope
+    /// where all opaque types and default associated items are revealed.
+    ///
+    /// This is only suitable for monomorphized, post-typeck environments.
+    /// Do not use this for MIR optimizations, as even though they also
+    /// use `TypingMode::PostAnalysis`, they may still have where-clauses
+    /// in scope.
+    pub fn fully_monomorphized() -> TypingEnv<'tcx> {
+        TypingEnv { typing_mode: TypingMode::PostAnalysis, param_env: ParamEnv::reveal_all() }
+    }
+
+    /// Create a typing environment for use during analysis outside of a body.
+    ///
+    /// Using a typing environment inside of bodies is not supported as the body
+    /// may define opaque types. In this case the used functions have to be
+    /// converted to use proper canonical inputs instead.
+    pub fn non_body_analysis(
+        tcx: TyCtxt<'tcx>,
+        def_id: impl IntoQueryParam<DefId>,
+    ) -> TypingEnv<'tcx> {
+        TypingEnv { typing_mode: TypingMode::non_body_analysis(), param_env: tcx.param_env(def_id) }
+    }
+
+    pub fn post_analysis(tcx: TyCtxt<'tcx>, def_id: impl IntoQueryParam<DefId>) -> TypingEnv<'tcx> {
+        TypingEnv {
+            typing_mode: TypingMode::PostAnalysis,
+            param_env: tcx.param_env_reveal_all_normalized(def_id),
+        }
+    }
+
+    /// Modify the `typing_mode` to `PostAnalysis` and eagerly reveal all
+    /// opaque types in the `param_env`.
+    pub fn with_reveal_all_normalized(self, tcx: TyCtxt<'tcx>) -> TypingEnv<'tcx> {
+        let TypingEnv { typing_mode: _, param_env } = self;
+        let param_env = param_env.with_reveal_all_normalized(tcx);
+        TypingEnv { typing_mode: TypingMode::PostAnalysis, param_env }
+    }
+
+    /// Combine this typing environment with the given `value` to be used by
+    /// not (yet) canonicalized queries. This only works if the value does not
+    /// contain anything local to some `InferCtxt`, i.e. inference variables or
+    /// placeholders.
+    pub fn as_query_input<T>(self, value: T) -> PseudoCanonicalInput<'tcx, T>
+    where
+        T: TypeVisitable<TyCtxt<'tcx>>,
+    {
+        debug_assert!(!value.has_infer());
+        // FIXME(#132279): We should assert that the value does not contain any placeholders
+        // as these placeholders are also local to the current inference context. However, we
+        // currently use pseudo-canonical queries in the trait solver which replaces params with
+        // placeholders. We should also simply not use pseudo-canonical queries in the trait
+        // solver, at which point we can readd this assert. As of writing this comment, this is
+        // only used by `fn layout_is_pointer_like` when calling `layout_of`.
+        //
+        // debug_assert!(!value.has_placeholders());
+        PseudoCanonicalInput { typing_env: self, value }
+    }
+}
+
+/// Similar to `CanonicalInput`, this carries the `typing_mode` and the environment
+/// necessary to do any kind of trait solving inside of nested queries.
+///
+/// Unlike proper canonicalization, this requires the `param_env` and the `value` to not
+/// contain anything local to the `infcx` of the caller, so we don't actually canonicalize
+/// anything.
+///
+/// This should be created by using `infcx.pseudo_canonicalize_query(param_env, value)`
+/// or by using `typing_env.as_query_input(value)`.
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
+#[derive(HashStable)]
+pub struct PseudoCanonicalInput<'tcx, T> {
+    pub typing_env: TypingEnv<'tcx>,
+    pub value: T,
+}
+
 #[derive(Copy, Clone, Debug, HashStable, Encodable, Decodable)]
 pub struct Destructor {
     /// The `DefId` of the destructor method
@@ -2150,7 +2249,6 @@ pub fn provide(providers: &mut Providers) {
         incoherent_impls: trait_def::incoherent_impls_provider,
         trait_impls_in_crate: trait_def::trait_impls_in_crate_provider,
         traits: trait_def::traits_provider,
-        const_param_default: consts::const_param_default,
         vtable_allocation: vtable::vtable_allocation_provider,
         ..*providers
     };
diff --git a/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs b/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs
index e51d2201922..f611b69905c 100644
--- a/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs
+++ b/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs
@@ -35,16 +35,16 @@ impl<'tcx> TyCtxt<'tcx> {
     ///
     /// This should only be used outside of type inference. For example,
     /// it assumes that normalization will succeed.
-    #[tracing::instrument(level = "debug", skip(self, param_env), ret)]
-    pub fn normalize_erasing_regions<T>(self, param_env: ty::ParamEnv<'tcx>, value: T) -> T
+    #[tracing::instrument(level = "debug", skip(self, typing_env), ret)]
+    pub fn normalize_erasing_regions<T>(self, typing_env: ty::TypingEnv<'tcx>, value: T) -> T
     where
         T: TypeFoldable<TyCtxt<'tcx>>,
     {
         debug!(
-            "normalize_erasing_regions::<{}>(value={:?}, param_env={:?})",
+            "normalize_erasing_regions::<{}>(value={:?}, typing_env={:?})",
             std::any::type_name::<T>(),
             value,
-            param_env,
+            typing_env,
         );
 
         // Erase first before we do the real query -- this keeps the
@@ -55,7 +55,7 @@ impl<'tcx> TyCtxt<'tcx> {
         if !value.has_aliases() {
             value
         } else {
-            value.fold_with(&mut NormalizeAfterErasingRegionsFolder { tcx: self, param_env })
+            value.fold_with(&mut NormalizeAfterErasingRegionsFolder { tcx: self, typing_env })
         }
     }
 
@@ -66,17 +66,17 @@ impl<'tcx> TyCtxt<'tcx> {
     /// succeeds.
     pub fn try_normalize_erasing_regions<T>(
         self,
-        param_env: ty::ParamEnv<'tcx>,
+        typing_env: ty::TypingEnv<'tcx>,
         value: T,
     ) -> Result<T, NormalizationError<'tcx>>
     where
         T: TypeFoldable<TyCtxt<'tcx>>,
     {
         debug!(
-            "try_normalize_erasing_regions::<{}>(value={:?}, param_env={:?})",
+            "try_normalize_erasing_regions::<{}>(value={:?}, typing_env={:?})",
             std::any::type_name::<T>(),
             value,
-            param_env,
+            typing_env,
         );
 
         // Erase first before we do the real query -- this keeps the
@@ -87,7 +87,7 @@ impl<'tcx> TyCtxt<'tcx> {
         if !value.has_aliases() {
             Ok(value)
         } else {
-            let mut folder = TryNormalizeAfterErasingRegionsFolder::new(self, param_env);
+            let mut folder = TryNormalizeAfterErasingRegionsFolder::new(self, typing_env);
             value.try_fold_with(&mut folder)
         }
     }
@@ -103,17 +103,17 @@ impl<'tcx> TyCtxt<'tcx> {
     // FIXME(@lcnr): This method should not be necessary, we now normalize
     // inside of binders. We should be able to only use
     // `tcx.instantiate_bound_regions_with_erased`.
-    #[tracing::instrument(level = "debug", skip(self, param_env))]
+    #[tracing::instrument(level = "debug", skip(self, typing_env))]
     pub fn normalize_erasing_late_bound_regions<T>(
         self,
-        param_env: ty::ParamEnv<'tcx>,
+        typing_env: ty::TypingEnv<'tcx>,
         value: ty::Binder<'tcx, T>,
     ) -> T
     where
         T: TypeFoldable<TyCtxt<'tcx>>,
     {
         let value = self.instantiate_bound_regions_with_erased(value);
-        self.normalize_erasing_regions(param_env, value)
+        self.normalize_erasing_regions(typing_env, value)
     }
 
     /// Monomorphizes a type from the AST by first applying the
@@ -125,14 +125,14 @@ impl<'tcx> TyCtxt<'tcx> {
     pub fn instantiate_and_normalize_erasing_regions<T>(
         self,
         param_args: GenericArgsRef<'tcx>,
-        param_env: ty::ParamEnv<'tcx>,
+        typing_env: ty::TypingEnv<'tcx>,
         value: EarlyBinder<'tcx, T>,
     ) -> T
     where
         T: TypeFoldable<TyCtxt<'tcx>>,
     {
         let instantiated = value.instantiate(self, param_args);
-        self.normalize_erasing_regions(param_env, instantiated)
+        self.normalize_erasing_regions(typing_env, instantiated)
     }
 
     /// Monomorphizes a type from the AST by first applying the
@@ -143,20 +143,20 @@ impl<'tcx> TyCtxt<'tcx> {
     pub fn try_instantiate_and_normalize_erasing_regions<T>(
         self,
         param_args: GenericArgsRef<'tcx>,
-        param_env: ty::ParamEnv<'tcx>,
+        typing_env: ty::TypingEnv<'tcx>,
         value: EarlyBinder<'tcx, T>,
     ) -> Result<T, NormalizationError<'tcx>>
     where
         T: TypeFoldable<TyCtxt<'tcx>>,
     {
         let instantiated = value.instantiate(self, param_args);
-        self.try_normalize_erasing_regions(param_env, instantiated)
+        self.try_normalize_erasing_regions(typing_env, instantiated)
     }
 }
 
 struct NormalizeAfterErasingRegionsFolder<'tcx> {
     tcx: TyCtxt<'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
+    typing_env: ty::TypingEnv<'tcx>,
 }
 
 impl<'tcx> NormalizeAfterErasingRegionsFolder<'tcx> {
@@ -164,8 +164,7 @@ impl<'tcx> NormalizeAfterErasingRegionsFolder<'tcx> {
         &self,
         arg: ty::GenericArg<'tcx>,
     ) -> ty::GenericArg<'tcx> {
-        let arg = self.param_env.and(arg);
-
+        let arg = self.typing_env.as_query_input(arg);
         self.tcx.try_normalize_generic_arg_after_erasing_regions(arg).unwrap_or_else(|_| bug!(
             "Failed to normalize {:?}, maybe try to call `try_normalize_erasing_regions` instead",
             arg.value
@@ -189,12 +188,12 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for NormalizeAfterErasingRegionsFolder<'tcx>
 
 struct TryNormalizeAfterErasingRegionsFolder<'tcx> {
     tcx: TyCtxt<'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
+    typing_env: ty::TypingEnv<'tcx>,
 }
 
 impl<'tcx> TryNormalizeAfterErasingRegionsFolder<'tcx> {
-    fn new(tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Self {
-        TryNormalizeAfterErasingRegionsFolder { tcx, param_env }
+    fn new(tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>) -> Self {
+        TryNormalizeAfterErasingRegionsFolder { tcx, typing_env }
     }
 
     #[instrument(skip(self), level = "debug")]
@@ -202,10 +201,8 @@ impl<'tcx> TryNormalizeAfterErasingRegionsFolder<'tcx> {
         &self,
         arg: ty::GenericArg<'tcx>,
     ) -> Result<ty::GenericArg<'tcx>, NoSolution> {
-        let arg = self.param_env.and(arg);
-        debug!(?arg);
-
-        self.tcx.try_normalize_generic_arg_after_erasing_regions(arg)
+        let input = self.typing_env.as_query_input(arg);
+        self.tcx.try_normalize_generic_arg_after_erasing_regions(input)
     }
 }
 
diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs
index 4093812b472..703a7826b7a 100644
--- a/compiler/rustc_middle/src/ty/util.rs
+++ b/compiler/rustc_middle/src/ty/util.rs
@@ -18,6 +18,7 @@ use rustc_span::sym;
 use smallvec::{SmallVec, smallvec};
 use tracing::{debug, instrument};
 
+use super::TypingEnv;
 use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use crate::query::Providers;
 use crate::ty::layout::{FloatExt, IntegerExt};
@@ -177,9 +178,13 @@ impl<'tcx> TyCtxt<'tcx> {
     /// Should only be called if `ty` has no inference variables and does not
     /// need its lifetimes preserved (e.g. as part of codegen); otherwise
     /// normalization attempt may cause compiler bugs.
-    pub fn struct_tail_for_codegen(self, ty: Ty<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Ty<'tcx> {
+    pub fn struct_tail_for_codegen(
+        self,
+        ty: Ty<'tcx>,
+        typing_env: ty::TypingEnv<'tcx>,
+    ) -> Ty<'tcx> {
         let tcx = self;
-        tcx.struct_tail_raw(ty, |ty| tcx.normalize_erasing_regions(param_env, ty), || {})
+        tcx.struct_tail_raw(ty, |ty| tcx.normalize_erasing_regions(typing_env, ty), || {})
     }
 
     /// Returns the deeply last field of nested structures, or the same type if
@@ -271,11 +276,11 @@ impl<'tcx> TyCtxt<'tcx> {
         self,
         source: Ty<'tcx>,
         target: Ty<'tcx>,
-        param_env: ty::ParamEnv<'tcx>,
+        typing_env: ty::TypingEnv<'tcx>,
     ) -> (Ty<'tcx>, Ty<'tcx>) {
         let tcx = self;
         tcx.struct_lockstep_tails_raw(source, target, |ty| {
-            tcx.normalize_erasing_regions(param_env, ty)
+            tcx.normalize_erasing_regions(typing_env, ty)
         })
     }
 
@@ -420,10 +425,10 @@ impl<'tcx> TyCtxt<'tcx> {
 
         // Async drop glue morphology is an internal detail, so reveal_all probably
         // should be fine
-        let param_env = ty::ParamEnv::reveal_all();
-        if ty.needs_async_drop(self, param_env) {
+        let typing_env = ty::TypingEnv::fully_monomorphized();
+        if ty.needs_async_drop(self, typing_env) {
             AsyncDropGlueMorphology::Custom
-        } else if ty.needs_drop(self, param_env) {
+        } else if ty.needs_drop(self, typing_env) {
             AsyncDropGlueMorphology::DeferredDropInPlace
         } else {
             AsyncDropGlueMorphology::Noop
@@ -683,12 +688,10 @@ impl<'tcx> TyCtxt<'tcx> {
     }
 
     /// Get the type of the pointer to the static that we use in MIR.
-    pub fn static_ptr_ty(self, def_id: DefId) -> Ty<'tcx> {
+    pub fn static_ptr_ty(self, def_id: DefId, typing_env: ty::TypingEnv<'tcx>) -> Ty<'tcx> {
         // Make sure that any constants in the static's type are evaluated.
-        let static_ty = self.normalize_erasing_regions(
-            ty::ParamEnv::empty(),
-            self.type_of(def_id).instantiate_identity(),
-        );
+        let static_ty =
+            self.normalize_erasing_regions(typing_env, self.type_of(def_id).instantiate_identity());
 
         // Make sure that accesses to unsafe statics end up using raw pointers.
         // For thread-locals, this needs to be kept in sync with `Rvalue::ty`.
@@ -1157,15 +1160,17 @@ impl<'tcx> Ty<'tcx> {
     /// Returns the maximum value for the given numeric type (including `char`s)
     /// or returns `None` if the type is not numeric.
     pub fn numeric_max_val(self, tcx: TyCtxt<'tcx>) -> Option<ty::Const<'tcx>> {
+        let typing_env = TypingEnv::fully_monomorphized();
         self.numeric_min_and_max_as_bits(tcx)
-            .map(|(_, max)| ty::Const::from_bits(tcx, max, ty::ParamEnv::empty().and(self)))
+            .map(|(_, max)| ty::Const::from_bits(tcx, max, typing_env, self))
     }
 
     /// Returns the minimum value for the given numeric type (including `char`s)
     /// or returns `None` if the type is not numeric.
     pub fn numeric_min_val(self, tcx: TyCtxt<'tcx>) -> Option<ty::Const<'tcx>> {
+        let typing_env = TypingEnv::fully_monomorphized();
         self.numeric_min_and_max_as_bits(tcx)
-            .map(|(min, _)| ty::Const::from_bits(tcx, min, ty::ParamEnv::empty().and(self)))
+            .map(|(min, _)| ty::Const::from_bits(tcx, min, typing_env, self))
     }
 
     /// Checks whether values of this type `T` are *moved* or *copied*
@@ -1345,7 +1350,7 @@ impl<'tcx> Ty<'tcx> {
     ///
     /// Note that this method is used to check eligible types in unions.
     #[inline]
-    pub fn needs_drop(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool {
+    pub fn needs_drop(self, tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>) -> bool {
         // Avoid querying in simple cases.
         match needs_drop_components(tcx, self) {
             Err(AlwaysRequiresDrop) => true,
@@ -1359,14 +1364,13 @@ impl<'tcx> Ty<'tcx> {
                 };
 
                 // This doesn't depend on regions, so try to minimize distinct
-                // query keys used.
-                // If normalization fails, we just use `query_ty`.
-                debug_assert!(!param_env.has_infer());
+                // query keys used. If normalization fails, we just use `query_ty`.
+                debug_assert!(!typing_env.param_env.has_infer());
                 let query_ty = tcx
-                    .try_normalize_erasing_regions(param_env, query_ty)
+                    .try_normalize_erasing_regions(typing_env, query_ty)
                     .unwrap_or_else(|_| tcx.erase_regions(query_ty));
 
-                tcx.needs_drop_raw(param_env.and(query_ty))
+                tcx.needs_drop_raw(typing_env.as_query_input(query_ty))
             }
         }
     }
@@ -1385,7 +1389,7 @@ impl<'tcx> Ty<'tcx> {
     // FIXME(zetanumbers): Note that this method is used to check eligible types
     // in unions.
     #[inline]
-    pub fn needs_async_drop(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool {
+    pub fn needs_async_drop(self, tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>) -> bool {
         // Avoid querying in simple cases.
         match needs_drop_components(tcx, self) {
             Err(AlwaysRequiresDrop) => true,
@@ -1401,12 +1405,12 @@ impl<'tcx> Ty<'tcx> {
                 // This doesn't depend on regions, so try to minimize distinct
                 // query keys used.
                 // If normalization fails, we just use `query_ty`.
-                debug_assert!(!param_env.has_infer());
+                debug_assert!(!typing_env.has_infer());
                 let query_ty = tcx
-                    .try_normalize_erasing_regions(param_env, query_ty)
+                    .try_normalize_erasing_regions(typing_env, query_ty)
                     .unwrap_or_else(|_| tcx.erase_regions(query_ty));
 
-                tcx.needs_async_drop_raw(param_env.and(query_ty))
+                tcx.needs_async_drop_raw(typing_env.as_query_input(query_ty))
             }
         }
     }
@@ -1420,7 +1424,7 @@ impl<'tcx> Ty<'tcx> {
     /// Note that this method is used to check for change in drop order for
     /// 2229 drop reorder migration analysis.
     #[inline]
-    pub fn has_significant_drop(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool {
+    pub fn has_significant_drop(self, tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>) -> bool {
         // Avoid querying in simple cases.
         match needs_drop_components(tcx, self) {
             Err(AlwaysRequiresDrop) => true,
@@ -1443,8 +1447,8 @@ impl<'tcx> Ty<'tcx> {
 
                 // This doesn't depend on regions, so try to minimize distinct
                 // query keys used.
-                let erased = tcx.normalize_erasing_regions(param_env, query_ty);
-                tcx.has_significant_drop_raw(param_env.and(erased))
+                let erased = tcx.normalize_erasing_regions(typing_env, query_ty);
+                tcx.has_significant_drop_raw(typing_env.as_query_input(erased))
             }
         }
     }
diff --git a/compiler/rustc_middle/src/ty/vtable.rs b/compiler/rustc_middle/src/ty/vtable.rs
index 963fa12a8c7..e5eeb23be25 100644
--- a/compiler/rustc_middle/src/ty/vtable.rs
+++ b/compiler/rustc_middle/src/ty/vtable.rs
@@ -97,7 +97,7 @@ pub(super) fn vtable_allocation_provider<'tcx>(
     assert!(vtable_entries.len() >= vtable_min_entries(tcx, poly_trait_ref));
 
     let layout = tcx
-        .layout_of(ty::ParamEnv::reveal_all().and(ty))
+        .layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(ty))
         .expect("failed to build vtable representation");
     assert!(layout.is_sized(), "can't create a vtable for an unsized type");
     let size = layout.size.bytes();
@@ -117,7 +117,7 @@ pub(super) fn vtable_allocation_provider<'tcx>(
         let idx: u64 = u64::try_from(idx).unwrap();
         let scalar = match entry {
             VtblEntry::MetadataDropInPlace => {
-                if ty.needs_drop(tcx, ty::ParamEnv::reveal_all()) {
+                if ty.needs_drop(tcx, ty::TypingEnv::fully_monomorphized()) {
                     let instance = ty::Instance::resolve_drop_in_place(tcx, ty);
                     let fn_alloc_id = tcx.reserve_and_set_fn_alloc(instance, CTFE_ALLOC_SALT);
                     let fn_ptr = Pointer::from(fn_alloc_id);
diff --git a/compiler/rustc_middle/src/util/call_kind.rs b/compiler/rustc_middle/src/util/call_kind.rs
index ed27a880562..acfb78b3f6e 100644
--- a/compiler/rustc_middle/src/util/call_kind.rs
+++ b/compiler/rustc_middle/src/util/call_kind.rs
@@ -8,7 +8,7 @@ use rustc_span::symbol::Ident;
 use rustc_span::{DesugaringKind, Span, sym};
 use tracing::debug;
 
-use crate::ty::{AssocItemContainer, GenericArgsRef, Instance, ParamEnv, Ty, TyCtxt};
+use crate::ty::{AssocItemContainer, GenericArgsRef, Instance, Ty, TyCtxt, TypingEnv};
 
 #[derive(Clone, Copy, PartialEq, Eq, Debug)]
 pub enum CallDesugaringKind {
@@ -62,7 +62,7 @@ pub enum CallKind<'tcx> {
 
 pub fn call_kind<'tcx>(
     tcx: TyCtxt<'tcx>,
-    param_env: ParamEnv<'tcx>,
+    typing_env: TypingEnv<'tcx>,
     method_did: DefId,
     method_args: GenericArgsRef<'tcx>,
     fn_call_span: Span,
@@ -98,10 +98,10 @@ pub fn call_kind<'tcx>(
         Some(CallKind::Operator { self_arg, trait_id, self_ty: method_args.type_at(0) })
     } else if is_deref {
         let deref_target = tcx.get_diagnostic_item(sym::deref_target).and_then(|deref_target| {
-            Instance::try_resolve(tcx, param_env, deref_target, method_args).transpose()
+            Instance::try_resolve(tcx, typing_env, deref_target, method_args).transpose()
         });
         if let Some(Ok(instance)) = deref_target {
-            let deref_target_ty = instance.ty(tcx, param_env);
+            let deref_target_ty = instance.ty(tcx, typing_env);
             Some(CallKind::DerefCoercion {
                 deref_target: tcx.def_span(instance.def_id()),
                 deref_target_ty,
diff --git a/compiler/rustc_mir_build/src/build/custom/mod.rs b/compiler/rustc_mir_build/src/build/custom/mod.rs
index 4815db47b16..e809c9a23f3 100644
--- a/compiler/rustc_mir_build/src/build/custom/mod.rs
+++ b/compiler/rustc_mir_build/src/build/custom/mod.rs
@@ -25,7 +25,7 @@ use rustc_index::{IndexSlice, IndexVec};
 use rustc_middle::mir::*;
 use rustc_middle::span_bug;
 use rustc_middle::thir::*;
-use rustc_middle::ty::{ParamEnv, Ty, TyCtxt};
+use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_span::Span;
 
 mod parse;
@@ -77,7 +77,7 @@ pub(super) fn build_custom_mir<'tcx>(
 
     let mut pctxt = ParseCtxt {
         tcx,
-        param_env: tcx.param_env(did),
+        typing_env: body.typing_env(tcx),
         thir,
         source_scope: OUTERMOST_SOURCE_SCOPE,
         body: &mut body,
@@ -136,7 +136,7 @@ fn parse_attribute(attr: &Attribute) -> MirPhase {
 
 struct ParseCtxt<'a, 'tcx> {
     tcx: TyCtxt<'tcx>,
-    param_env: ParamEnv<'tcx>,
+    typing_env: ty::TypingEnv<'tcx>,
     thir: &'a Thir<'tcx>,
     source_scope: SourceScope,
     body: &'a mut Body<'tcx>,
diff --git a/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs b/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs
index 07964e304b9..d08809ef67b 100644
--- a/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs
+++ b/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs
@@ -151,7 +151,7 @@ impl<'a, 'tcx> ParseCtxt<'a, 'tcx> {
                     expected: "constant pattern".to_string(),
                 });
             };
-            values.push(value.eval_bits(self.tcx, self.param_env));
+            values.push(value.eval_bits(self.tcx, self.typing_env));
             targets.push(self.parse_block(arm.body)?);
         }
 
@@ -385,7 +385,7 @@ impl<'a, 'tcx> ParseCtxt<'a, 'tcx> {
             | ExprKind::NonHirLiteral { .. }
             | ExprKind::ConstBlock { .. } => Ok({
                 let value = as_constant_inner(expr, |_| None, self.tcx);
-                value.const_.eval_bits(self.tcx, self.param_env)
+                value.const_.eval_bits(self.tcx, self.typing_env)
             }),
         )
     }
diff --git a/compiler/rustc_mir_build/src/build/expr/as_constant.rs b/compiler/rustc_mir_build/src/build/expr/as_constant.rs
index 3f2e3b956fc..640408cb9c8 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_constant.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_constant.rs
@@ -114,8 +114,7 @@ fn lit_to_mir_constant<'tcx>(
 ) -> Result<Const<'tcx>, LitToConstError> {
     let LitToConstInput { lit, ty, neg } = lit_input;
     let trunc = |n| {
-        let param_ty = ty::ParamEnv::reveal_all().and(ty);
-        let width = match tcx.layout_of(param_ty) {
+        let width = match tcx.layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(ty)) {
             Ok(layout) => layout.size,
             Err(_) => {
                 tcx.dcx().bug(format!("couldn't compute width of literal: {:?}", lit_input.lit))
diff --git a/compiler/rustc_mir_build/src/build/expr/as_operand.rs b/compiler/rustc_mir_build/src/build/expr/as_operand.rs
index 112eac32264..aad7d54833b 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_operand.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_operand.rs
@@ -123,7 +123,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         match category {
             Category::Constant
                 if matches!(needs_temporary, NeedsTemporary::No)
-                    || !expr.ty.needs_drop(this.tcx, this.param_env) =>
+                    || !expr.ty.needs_drop(this.tcx, this.typing_env()) =>
             {
                 let constant = this.as_constant(expr);
                 block.and(Operand::Constant(Box::new(constant)))
diff --git a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
index 1985dd3fca0..a3fee38908b 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
@@ -197,7 +197,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 {
                     let discr_ty = adt_def.repr().discr_type().to_ty(this.tcx);
                     let temp = unpack!(block = this.as_temp(block, scope, source, Mutability::Not));
-                    let layout = this.tcx.layout_of(this.param_env.and(source_expr.ty));
+                    let layout =
+                        this.tcx.layout_of(this.typing_env().as_query_input(source_expr.ty));
                     let discr = this.temp(discr_ty, source_expr.span);
                     this.cfg.push_assign(
                         block,
@@ -226,10 +227,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                             if range.start <= range.end { BinOp::BitAnd } else { BinOp::BitOr };
 
                         let mut comparer = |range: u128, bin_op: BinOp| -> Place<'tcx> {
+                            // We can use `ty::TypingEnv::fully_monomorphized()`` here
+                            // as we only need it to compute the layout of a primitive.
                             let range_val = Const::from_bits(
                                 this.tcx,
                                 range,
-                                ty::ParamEnv::empty().and(unsigned_ty),
+                                ty::TypingEnv::fully_monomorphized(),
+                                unsigned_ty,
                             );
                             let lit_op = this.literal_operand(expr.span, range_val);
                             let is_bin_op = this.temp(bool_ty, expr_span);
@@ -812,9 +816,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
 
     // Helper to get a `-1` value of the appropriate type
     fn neg_1_literal(&mut self, span: Span, ty: Ty<'tcx>) -> Operand<'tcx> {
-        let param_ty = ty::ParamEnv::empty().and(ty);
-        let size = self.tcx.layout_of(param_ty).unwrap().size;
-        let literal = Const::from_bits(self.tcx, size.unsigned_int_max(), param_ty);
+        let typing_env = ty::TypingEnv::fully_monomorphized();
+        let size = self.tcx.layout_of(typing_env.as_query_input(ty)).unwrap().size;
+        let literal = Const::from_bits(self.tcx, size.unsigned_int_max(), typing_env, ty);
 
         self.literal_operand(span, literal)
     }
@@ -822,10 +826,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     // Helper to get the minimum value of the appropriate type
     fn minval_literal(&mut self, span: Span, ty: Ty<'tcx>) -> Operand<'tcx> {
         assert!(ty.is_signed());
-        let param_ty = ty::ParamEnv::empty().and(ty);
-        let bits = self.tcx.layout_of(param_ty).unwrap().size.bits();
+        let typing_env = ty::TypingEnv::fully_monomorphized();
+        let bits = self.tcx.layout_of(typing_env.as_query_input(ty)).unwrap().size.bits();
         let n = 1 << (bits - 1);
-        let literal = Const::from_bits(self.tcx, n, param_ty);
+        let literal = Const::from_bits(self.tcx, n, typing_env, ty);
 
         self.literal_operand(span, literal)
     }
diff --git a/compiler/rustc_mir_build/src/build/expr/into.rs b/compiler/rustc_mir_build/src/build/expr/into.rs
index dc317feb20c..0dec56d21ae 100644
--- a/compiler/rustc_mir_build/src/build/expr/into.rs
+++ b/compiler/rustc_mir_build/src/build/expr/into.rs
@@ -266,7 +266,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     // that makes the call.
                     target: expr
                         .ty
-                        .is_inhabited_from(this.tcx, this.parent_module, this.param_env)
+                        .is_inhabited_from(
+                            this.tcx,
+                            this.parent_module,
+                            this.infcx.typing_env(this.param_env),
+                        )
                         .then_some(success),
                     call_source: if from_hir_call {
                         CallSource::Normal
diff --git a/compiler/rustc_mir_build/src/build/expr/stmt.rs b/compiler/rustc_mir_build/src/build/expr/stmt.rs
index 76034c03b4b..02ca12028d3 100644
--- a/compiler/rustc_mir_build/src/build/expr/stmt.rs
+++ b/compiler/rustc_mir_build/src/build/expr/stmt.rs
@@ -42,7 +42,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
 
                 // Generate better code for things that don't need to be
                 // dropped.
-                if lhs_expr.ty.needs_drop(this.tcx, this.param_env) {
+                if lhs_expr.ty.needs_drop(this.tcx, this.typing_env()) {
                     let rhs = unpack!(block = this.as_local_rvalue(block, rhs));
                     let lhs = unpack!(block = this.as_place(block, lhs));
                     block =
diff --git a/compiler/rustc_mir_build/src/build/matches/match_pair.rs b/compiler/rustc_mir_build/src/build/matches/match_pair.rs
index 6df50057ee8..fcbf84a41d9 100644
--- a/compiler/rustc_mir_build/src/build/matches/match_pair.rs
+++ b/compiler/rustc_mir_build/src/build/matches/match_pair.rs
@@ -214,7 +214,7 @@ impl<'pat, 'tcx> MatchPairTree<'pat, 'tcx> {
                         || !v
                             .inhabited_predicate(cx.tcx, adt_def)
                             .instantiate(cx.tcx, args)
-                            .apply_ignore_module(cx.tcx, cx.param_env)
+                            .apply_ignore_module(cx.tcx, cx.infcx.typing_env(cx.param_env))
                 }) && (adt_def.did().is_local()
                     || !adt_def.is_variant_list_non_exhaustive());
                 if irrefutable {
diff --git a/compiler/rustc_mir_build/src/build/matches/test.rs b/compiler/rustc_mir_build/src/build/matches/test.rs
index 37cedd8cf5c..4f7bbc4ce3e 100644
--- a/compiler/rustc_mir_build/src/build/matches/test.rs
+++ b/compiler/rustc_mir_build/src/build/matches/test.rs
@@ -567,7 +567,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 // not to add such values here.
                 let is_covering_range = |test_case: &TestCase<'_, 'tcx>| {
                     test_case.as_range().is_some_and(|range| {
-                        matches!(range.contains(value, self.tcx, self.param_env), None | Some(true))
+                        matches!(
+                            range.contains(value, self.tcx, self.typing_env()),
+                            None | Some(true)
+                        )
                     })
                 };
                 let is_conflicting_candidate = |candidate: &&mut Candidate<'_, 'tcx>| {
@@ -584,7 +587,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     None
                 } else {
                     fully_matched = true;
-                    let bits = value.eval_bits(self.tcx, self.param_env);
+                    let bits = value.eval_bits(self.tcx, self.typing_env());
                     Some(TestBranch::Constant(value, bits))
                 }
             }
@@ -596,7 +599,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 fully_matched = false;
                 let not_contained =
                     sorted_candidates.keys().filter_map(|br| br.as_constant()).copied().all(
-                        |val| matches!(range.contains(val, self.tcx, self.param_env), Some(false)),
+                        |val| {
+                            matches!(range.contains(val, self.tcx, self.typing_env()), Some(false))
+                        },
                     );
 
                 not_contained.then(|| {
@@ -608,7 +613,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
 
             (TestKind::If, TestCase::Constant { value }) => {
                 fully_matched = true;
-                let value = value.try_eval_bool(self.tcx, self.param_env).unwrap_or_else(|| {
+                let value = value.try_eval_bool(self.tcx, self.typing_env()).unwrap_or_else(|| {
                     span_bug!(test.span, "expected boolean value but got {value:?}")
                 });
                 Some(if value { TestBranch::Success } else { TestBranch::Failure })
@@ -688,7 +693,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     fully_matched = false;
                     // If the testing range does not overlap with pattern range,
                     // the pattern can be matched only if this test fails.
-                    if !test.overlaps(pat, self.tcx, self.param_env)? {
+                    if !test.overlaps(pat, self.tcx, self.typing_env())? {
                         Some(TestBranch::Failure)
                     } else {
                         None
@@ -697,7 +702,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             }
             (TestKind::Range(range), &TestCase::Constant { value }) => {
                 fully_matched = false;
-                if !range.contains(value, self.tcx, self.param_env)? {
+                if !range.contains(value, self.tcx, self.typing_env())? {
                     // `value` is not contained in the testing range,
                     // so `value` can be matched only if this test fails.
                     Some(TestBranch::Failure)
diff --git a/compiler/rustc_mir_build/src/build/misc.rs b/compiler/rustc_mir_build/src/build/misc.rs
index 53cb99d44e8..a14dcad6573 100644
--- a/compiler/rustc_mir_build/src/build/misc.rs
+++ b/compiler/rustc_mir_build/src/build/misc.rs
@@ -32,7 +32,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     /// Returns a zero literal operand for the appropriate type, works for
     /// bool, char and integers.
     pub(crate) fn zero_literal(&mut self, span: Span, ty: Ty<'tcx>) -> Operand<'tcx> {
-        let literal = Const::from_bits(self.tcx, 0, ty::ParamEnv::empty().and(ty));
+        let literal = Const::from_bits(self.tcx, 0, ty::TypingEnv::fully_monomorphized(), ty);
 
         self.literal_operand(span, literal)
     }
diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs
index 46be2aee637..cf8dc597b7b 100644
--- a/compiler/rustc_mir_build/src/build/mod.rs
+++ b/compiler/rustc_mir_build/src/build/mod.rs
@@ -230,6 +230,10 @@ struct Capture<'tcx> {
 }
 
 impl<'a, 'tcx> Builder<'a, 'tcx> {
+    fn typing_env(&self) -> ty::TypingEnv<'tcx> {
+        self.infcx.typing_env(self.param_env)
+    }
+
     fn is_bound_var_in_guard(&self, id: LocalVarId) -> bool {
         self.guard_context.iter().any(|frame| frame.locals.iter().any(|local| local.id == id))
     }
diff --git a/compiler/rustc_mir_build/src/build/scope.rs b/compiler/rustc_mir_build/src/build/scope.rs
index a7e56b8f589..e63fbeeac66 100644
--- a/compiler/rustc_mir_build/src/build/scope.rs
+++ b/compiler/rustc_mir_build/src/build/scope.rs
@@ -1010,7 +1010,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     ) {
         let needs_drop = match drop_kind {
             DropKind::Value => {
-                if !self.local_decls[local].ty.needs_drop(self.tcx, self.param_env) {
+                if !self.local_decls[local].ty.needs_drop(self.tcx, self.typing_env()) {
                     return;
                 }
                 true
diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs
index 33e194fa246..da6b52ce0b8 100644
--- a/compiler/rustc_mir_build/src/check_unsafety.rs
+++ b/compiler/rustc_mir_build/src/check_unsafety.rs
@@ -566,7 +566,9 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
                     && adt_def.is_union()
                 {
                     if let Some(assigned_ty) = self.assignment_info {
-                        if assigned_ty.needs_drop(self.tcx, self.param_env) {
+                        if assigned_ty
+                            .needs_drop(self.tcx, ty::TypingEnv::from_param_env(self.param_env))
+                        {
                             // This would be unsafe, but should be outright impossible since we
                             // reject such unions.
                             assert!(
diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs
index 00f65e0c7d0..62c6d85b73f 100644
--- a/compiler/rustc_mir_build/src/errors.rs
+++ b/compiler/rustc_mir_build/src/errors.rs
@@ -528,7 +528,7 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for NonExhaustivePatternsTypeNo
         }
 
         if let ty::Ref(_, sub_ty, _) = self.ty.kind() {
-            if !sub_ty.is_inhabited_from(self.cx.tcx, self.cx.module, self.cx.param_env) {
+            if !sub_ty.is_inhabited_from(self.cx.tcx, self.cx.module, self.cx.typing_env()) {
                 diag.note(fluent::mir_build_reference_note);
             }
         }
diff --git a/compiler/rustc_mir_build/src/lints.rs b/compiler/rustc_mir_build/src/lints.rs
index cb9a4e2604e..a1b75c22c4d 100644
--- a/compiler/rustc_mir_build/src/lints.rs
+++ b/compiler/rustc_mir_build/src/lints.rs
@@ -136,12 +136,17 @@ impl<'tcx> TerminatorClassifier<'tcx> for CallRecursion<'tcx> {
 
         let func_ty = func.ty(body, tcx);
         if let ty::FnDef(callee, args) = *func_ty.kind() {
-            let Ok(normalized_args) = tcx.try_normalize_erasing_regions(param_env, args) else {
+            let Ok(normalized_args) =
+                tcx.try_normalize_erasing_regions(ty::TypingEnv::from_param_env(param_env), args)
+            else {
                 return false;
             };
-            let (callee, call_args) = if let Ok(Some(instance)) =
-                Instance::try_resolve(tcx, param_env, callee, normalized_args)
-            {
+            let (callee, call_args) = if let Ok(Some(instance)) = Instance::try_resolve(
+                tcx,
+                ty::TypingEnv::from_param_env(param_env),
+                callee,
+                normalized_args,
+            ) {
                 (instance.def_id(), instance.args)
             } else {
                 (callee, normalized_args)
diff --git a/compiler/rustc_mir_build/src/thir/constant.rs b/compiler/rustc_mir_build/src/thir/constant.rs
index b8877a64e47..3fa0e4def82 100644
--- a/compiler/rustc_mir_build/src/thir/constant.rs
+++ b/compiler/rustc_mir_build/src/thir/constant.rs
@@ -2,7 +2,7 @@ use rustc_ast as ast;
 use rustc_hir::LangItem;
 use rustc_middle::bug;
 use rustc_middle::mir::interpret::{LitToConstError, LitToConstInput};
-use rustc_middle::ty::{self, ParamEnv, ScalarInt, TyCtxt};
+use rustc_middle::ty::{self, ScalarInt, TyCtxt};
 use tracing::trace;
 
 use crate::build::parse_float_into_scalar;
@@ -14,8 +14,7 @@ pub(crate) fn lit_to_const<'tcx>(
     let LitToConstInput { lit, ty, neg } = lit_input;
 
     let trunc = |n| {
-        let param_ty = ParamEnv::reveal_all().and(ty);
-        let width = match tcx.layout_of(param_ty) {
+        let width = match tcx.layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(ty)) {
             Ok(layout) => layout.size,
             Err(_) => {
                 tcx.dcx().bug(format!("couldn't compute width of literal: {:?}", lit_input.lit))
diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs
index 64457031997..198fa4ffb7a 100644
--- a/compiler/rustc_mir_build/src/thir/cx/expr.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs
@@ -284,10 +284,9 @@ impl<'tcx> Cx<'tcx> {
             let ty = adt_def.repr().discr_type();
             let discr_ty = ty.to_ty(tcx);
 
-            let param_env_ty = self.param_env.and(discr_ty);
             let size = tcx
-                .layout_of(param_env_ty)
-                .unwrap_or_else(|e| panic!("could not compute layout for {param_env_ty:?}: {e:?}"))
+                .layout_of(self.typing_env().as_query_input(discr_ty))
+                .unwrap_or_else(|e| panic!("could not compute layout for {discr_ty:?}: {e:?}"))
                 .size;
 
             let (lit, overflowing) = ScalarInt::truncate_from_uint(discr_offset as u128, size);
@@ -1025,7 +1024,7 @@ impl<'tcx> Cx<'tcx> {
             // but distinguish between &STATIC and &THREAD_LOCAL as they have different semantics
             Res::Def(DefKind::Static { .. }, id) => {
                 // this is &raw for extern static or static mut, and & for other statics
-                let ty = self.tcx.static_ptr_ty(id);
+                let ty = self.tcx.static_ptr_ty(id, self.typing_env());
                 let temp_lifetime = self
                     .rvalue_scopes
                     .temporary_scope(self.region_scope_tree, expr.hir_id.local_id);
diff --git a/compiler/rustc_mir_build/src/thir/cx/mod.rs b/compiler/rustc_mir_build/src/thir/cx/mod.rs
index 377931e3be7..dfc180f5261 100644
--- a/compiler/rustc_mir_build/src/thir/cx/mod.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/mod.rs
@@ -12,6 +12,7 @@ use rustc_hir::lang_items::LangItem;
 use rustc_middle::bug;
 use rustc_middle::middle::region;
 use rustc_middle::thir::*;
+use rustc_middle::ty::solve::Reveal;
 use rustc_middle::ty::{self, RvalueScopes, TyCtxt};
 use tracing::instrument;
 
@@ -109,6 +110,17 @@ impl<'tcx> Cx<'tcx> {
         }
     }
 
+    fn typing_mode(&self) -> ty::TypingMode<'tcx> {
+        debug_assert_eq!(self.param_env.reveal(), Reveal::UserFacing);
+        // FIXME(#132279): In case we're in a body, we should use a typing
+        // mode which reveals the opaque types defined by that body.
+        ty::TypingMode::non_body_analysis()
+    }
+
+    fn typing_env(&self) -> ty::TypingEnv<'tcx> {
+        ty::TypingEnv { typing_mode: self.typing_mode(), param_env: self.param_env }
+    }
+
     #[instrument(level = "debug", skip(self))]
     fn pattern_from_hir(&mut self, p: &'tcx hir::Pat<'tcx>) -> Box<Pat<'tcx>> {
         pat_from_hir(self.tcx, self.param_env, self.typeck_results(), p)
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 f222a869c03..73fcbeaef82 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
@@ -721,8 +721,8 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> {
                 .variant(*variant_index)
                 .inhabited_predicate(self.tcx, *adt)
                 .instantiate(self.tcx, args);
-            variant_inhabited.apply(self.tcx, cx.param_env, cx.module)
-                && !variant_inhabited.apply_ignore_module(self.tcx, cx.param_env)
+            variant_inhabited.apply(self.tcx, cx.typing_env(), cx.module)
+                && !variant_inhabited.apply_ignore_module(self.tcx, cx.typing_env())
         } else {
             false
         };
@@ -1124,7 +1124,7 @@ fn report_non_exhaustive_match<'p, 'tcx>(
     }
 
     if let ty::Ref(_, sub_ty, _) = scrut_ty.kind() {
-        if !sub_ty.is_inhabited_from(cx.tcx, cx.module, cx.param_env) {
+        if !sub_ty.is_inhabited_from(cx.tcx, cx.module, cx.typing_env()) {
             err.note("references are always considered inhabited");
         }
     }
diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
index 82632350af5..6b462198db6 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
@@ -50,10 +50,10 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
 
 struct ConstToPat<'tcx> {
     span: Span,
-    param_env: ty::ParamEnv<'tcx>,
 
     // inference context used for checking `T: Structural` bounds.
     infcx: InferCtxt<'tcx>,
+    param_env: ty::ParamEnv<'tcx>,
 
     treat_byte_string_as_slice: bool,
 }
@@ -81,6 +81,10 @@ impl<'tcx> ConstToPat<'tcx> {
         self.infcx.tcx
     }
 
+    fn typing_env(&self) -> ty::TypingEnv<'tcx> {
+        self.infcx.typing_env(self.param_env)
+    }
+
     fn type_marked_structural(&self, ty: Ty<'tcx>) -> bool {
         ty.is_structural_eq_shallow(self.infcx.tcx)
     }
@@ -100,13 +104,14 @@ impl<'tcx> ConstToPat<'tcx> {
         //
         // FIXME: `const_eval_resolve_for_typeck` should probably just set the env to `Reveal::All`
         // instead of having this logic here
-        let param_env =
-            self.tcx().erase_regions(self.param_env).with_reveal_all_normalized(self.tcx());
+        let typing_env =
+            self.tcx().erase_regions(self.typing_env()).with_reveal_all_normalized(self.tcx());
         let uv = self.tcx().erase_regions(uv);
 
         // try to resolve e.g. associated constants to their definition on an impl, and then
         // evaluate the const.
-        let valtree = match self.infcx.tcx.const_eval_resolve_for_typeck(param_env, uv, self.span) {
+        let valtree = match self.infcx.tcx.const_eval_resolve_for_typeck(typing_env, uv, self.span)
+        {
             Ok(Ok(c)) => c,
             Err(ErrorHandled::Reported(_, _)) => {
                 // Let's tell the use where this failing const occurs.
@@ -187,7 +192,7 @@ impl<'tcx> ConstToPat<'tcx> {
             .map(|(idx, (val, ty))| {
                 let field = FieldIdx::new(idx);
                 // Patterns can only use monomorphic types.
-                let ty = self.tcx().normalize_erasing_regions(self.param_env, ty);
+                let ty = self.tcx().normalize_erasing_regions(self.typing_env(), ty);
                 FieldPat { field, pattern: self.valtree_to_pat(val, ty) }
             })
             .collect()
diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
index ec852add94d..d17bc8566cc 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
@@ -242,7 +242,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
         let lo = lo.unwrap_or(PatRangeBoundary::NegInfinity);
         let hi = hi.unwrap_or(PatRangeBoundary::PosInfinity);
 
-        let cmp = lo.compare_with(hi, ty, self.tcx, self.param_env);
+        let cmp = lo.compare_with(hi, ty, self.tcx, ty::TypingEnv::from_param_env(self.param_env));
         let mut kind = PatKind::Range(Box::new(PatRange { lo, hi, end, ty }));
         match (end, cmp) {
             // `x..y` where `x < y`.
diff --git a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs
index 9a1f000d39d..494b7d54d8a 100644
--- a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs
+++ b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs
@@ -6,7 +6,6 @@ use rustc_index::Idx;
 use rustc_middle::mir::patch::MirPatch;
 use rustc_middle::mir::*;
 use rustc_middle::span_bug;
-use rustc_middle::traits::Reveal;
 use rustc_middle::ty::util::IntTypeExt;
 use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt};
 use rustc_span::DUMMY_SP;
@@ -111,7 +110,7 @@ pub trait DropElaborator<'a, 'tcx>: fmt::Debug {
     fn patch(&mut self) -> &mut MirPatch<'tcx>;
     fn body(&self) -> &'a Body<'tcx>;
     fn tcx(&self) -> TyCtxt<'tcx>;
-    fn param_env(&self) -> ty::ParamEnv<'tcx>;
+    fn typing_env(&self) -> ty::TypingEnv<'tcx>;
 
     // Drop logic
 
@@ -273,9 +272,9 @@ where
                 let subpath = self.elaborator.field_subpath(variant_path, field);
                 let tcx = self.tcx();
 
-                assert_eq!(self.elaborator.param_env().reveal(), Reveal::All);
+                assert_eq!(self.elaborator.typing_env().typing_mode, ty::TypingMode::PostAnalysis);
                 let field_ty =
-                    tcx.normalize_erasing_regions(self.elaborator.param_env(), f.ty(tcx, args));
+                    tcx.normalize_erasing_regions(self.elaborator.typing_env(), f.ty(tcx, args));
 
                 (tcx.mk_place_field(base_place, field, field_ty), subpath)
             })
@@ -372,7 +371,7 @@ where
 
         let mut fields = fields;
         fields.retain(|&(place, _)| {
-            self.place_ty(place).needs_drop(self.tcx(), self.elaborator.param_env())
+            self.place_ty(place).needs_drop(self.tcx(), self.elaborator.typing_env())
         });
 
         debug!("drop_ladder - fields needing drop: {:?}", fields);
@@ -544,11 +543,11 @@ where
             } else {
                 have_otherwise = true;
 
-                let param_env = self.elaborator.param_env();
+                let typing_env = self.elaborator.typing_env();
                 let have_field_with_drop_glue = variant
                     .fields
                     .iter()
-                    .any(|field| field.ty(tcx, args).needs_drop(tcx, param_env));
+                    .any(|field| field.ty(tcx, args).needs_drop(tcx, typing_env));
                 if have_field_with_drop_glue {
                     have_otherwise_with_drop_glue = true;
                 }
diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs
index af2d514fc76..ed8678de1eb 100644
--- a/compiler/rustc_mir_dataflow/src/value_analysis.rs
+++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs
@@ -462,7 +462,7 @@ impl<'tcx> Map<'tcx> {
         drop(assignments);
 
         // Create values for places whose type have scalar layout.
-        let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id());
+        let typing_env = body.typing_env(tcx);
         for place_info in self.places.iter_mut() {
             // The user requires a bound on the number of created values.
             if let Some(value_limit) = value_limit
@@ -471,13 +471,13 @@ impl<'tcx> Map<'tcx> {
                 break;
             }
 
-            if let Ok(ty) = tcx.try_normalize_erasing_regions(param_env, place_info.ty) {
+            if let Ok(ty) = tcx.try_normalize_erasing_regions(typing_env, place_info.ty) {
                 place_info.ty = ty;
             }
 
             // Allocate a value slot if it doesn't have one, and the user requested one.
             assert!(place_info.value_index.is_none());
-            if let Ok(layout) = tcx.layout_of(param_env.and(place_info.ty))
+            if let Ok(layout) = tcx.layout_of(typing_env.as_query_input(place_info.ty))
                 && layout.backend_repr.is_scalar()
             {
                 place_info.value_index = Some(self.value_count.into());
@@ -874,7 +874,7 @@ impl<V, T> TryFrom<ProjectionElem<V, T>> for TrackElem {
 pub fn iter_fields<'tcx>(
     ty: Ty<'tcx>,
     tcx: TyCtxt<'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
+    typing_env: ty::TypingEnv<'tcx>,
     mut f: impl FnMut(Option<VariantIdx>, FieldIdx, Ty<'tcx>),
 ) {
     match ty.kind() {
@@ -892,20 +892,20 @@ pub fn iter_fields<'tcx>(
                 for (f_index, f_def) in v_def.fields.iter().enumerate() {
                     let field_ty = f_def.ty(tcx, args);
                     let field_ty = tcx
-                        .try_normalize_erasing_regions(param_env, field_ty)
+                        .try_normalize_erasing_regions(typing_env, field_ty)
                         .unwrap_or_else(|_| tcx.erase_regions(field_ty));
                     f(variant, f_index.into(), field_ty);
                 }
             }
         }
         ty::Closure(_, args) => {
-            iter_fields(args.as_closure().tupled_upvars_ty(), tcx, param_env, f);
+            iter_fields(args.as_closure().tupled_upvars_ty(), tcx, typing_env, f);
         }
         ty::Coroutine(_, args) => {
-            iter_fields(args.as_coroutine().tupled_upvars_ty(), tcx, param_env, f);
+            iter_fields(args.as_coroutine().tupled_upvars_ty(), tcx, typing_env, f);
         }
         ty::CoroutineClosure(_, args) => {
-            iter_fields(args.as_coroutine_closure().tupled_upvars_ty(), tcx, param_env, f);
+            iter_fields(args.as_coroutine_closure().tupled_upvars_ty(), tcx, typing_env, f);
         }
         _ => (),
     }
diff --git a/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs b/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs
index 559df222a50..12a2fe23b14 100644
--- a/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs
+++ b/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs
@@ -1,6 +1,6 @@
 use rustc_middle::mir::patch::MirPatch;
 use rustc_middle::mir::*;
-use rustc_middle::ty::TyCtxt;
+use rustc_middle::ty::{self, TyCtxt};
 use tracing::debug;
 
 use crate::util;
@@ -40,10 +40,10 @@ pub(super) struct AddMovesForPackedDrops;
 impl<'tcx> crate::MirPass<'tcx> for AddMovesForPackedDrops {
     fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
         debug!("add_moves_for_packed_drops({:?} @ {:?})", body.source, body.span);
-
-        let def_id = body.source.def_id();
         let mut patch = MirPatch::new(body);
-        let param_env = tcx.param_env(def_id);
+        // FIXME(#132279): This is used during the phase transition from analysis
+        // to runtime, so we have to manually specify the correct typing mode.
+        let typing_env = ty::TypingEnv::post_analysis(tcx, body.source.def_id());
 
         for (bb, data) in body.basic_blocks.iter_enumerated() {
             let loc = Location { block: bb, statement_index: data.statements.len() };
@@ -51,7 +51,7 @@ impl<'tcx> crate::MirPass<'tcx> for AddMovesForPackedDrops {
 
             match terminator.kind {
                 TerminatorKind::Drop { place, .. }
-                    if util::is_disaligned(tcx, body, param_env, place) =>
+                    if util::is_disaligned(tcx, body, typing_env, place) =>
                 {
                     add_move_for_packed_drop(
                         tcx,
diff --git a/compiler/rustc_mir_transform/src/check_packed_ref.rs b/compiler/rustc_mir_transform/src/check_packed_ref.rs
index 1922d4fef25..e9b85ba6e9d 100644
--- a/compiler/rustc_mir_transform/src/check_packed_ref.rs
+++ b/compiler/rustc_mir_transform/src/check_packed_ref.rs
@@ -9,9 +9,9 @@ pub(super) struct CheckPackedRef;
 
 impl<'tcx> crate::MirLint<'tcx> for CheckPackedRef {
     fn run_lint(&self, tcx: TyCtxt<'tcx>, body: &Body<'tcx>) {
-        let param_env = tcx.param_env(body.source.def_id());
+        let typing_env = body.typing_env(tcx);
         let source_info = SourceInfo::outermost(body.span);
-        let mut checker = PackedRefChecker { body, tcx, param_env, source_info };
+        let mut checker = PackedRefChecker { body, tcx, typing_env, source_info };
         checker.visit_body(body);
     }
 }
@@ -19,7 +19,7 @@ impl<'tcx> crate::MirLint<'tcx> for CheckPackedRef {
 struct PackedRefChecker<'a, 'tcx> {
     body: &'a Body<'tcx>,
     tcx: TyCtxt<'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
+    typing_env: ty::TypingEnv<'tcx>,
     source_info: SourceInfo,
 }
 
@@ -37,7 +37,8 @@ impl<'tcx> Visitor<'tcx> for PackedRefChecker<'_, 'tcx> {
     }
 
     fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, _location: Location) {
-        if context.is_borrow() && util::is_disaligned(self.tcx, self.body, self.param_env, *place) {
+        if context.is_borrow() && util::is_disaligned(self.tcx, self.body, self.typing_env, *place)
+        {
             let def_id = self.body.source.instance.def_id();
             if let Some(impl_def_id) = self.tcx.impl_of_method(def_id)
                 && self.tcx.is_builtin_derived(impl_def_id)
diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs
index c2666caa1e8..d38a1dd11dc 100644
--- a/compiler/rustc_mir_transform/src/coroutine.rs
+++ b/compiler/rustc_mir_transform/src/coroutine.rs
@@ -1069,11 +1069,9 @@ fn elaborate_coroutine_drops<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
     // Note that `elaborate_drops` only drops the upvars of a coroutine, and
     // this is ok because `open_drop` can only be reached within that own
     // coroutine's resume function.
+    let typing_env = body.typing_env(tcx);
 
-    let def_id = body.source.def_id();
-    let param_env = tcx.param_env(def_id);
-
-    let mut elaborator = DropShimElaborator { body, patch: MirPatch::new(body), tcx, param_env };
+    let mut elaborator = DropShimElaborator { body, patch: MirPatch::new(body), tcx, typing_env };
 
     for (block, block_data) in body.basic_blocks.iter_enumerated() {
         let (target, unwind, source_info) = match block_data.terminator() {
@@ -1204,9 +1202,9 @@ fn insert_panic_block<'tcx>(
     insert_term_block(body, kind)
 }
 
-fn can_return<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool {
+fn can_return<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, typing_env: ty::TypingEnv<'tcx>) -> bool {
     // Returning from a function with an uninhabited return type is undefined behavior.
-    if body.return_ty().is_privately_uninhabited(tcx, param_env) {
+    if body.return_ty().is_privately_uninhabited(tcx, typing_env) {
         return false;
     }
 
@@ -1627,7 +1625,7 @@ impl<'tcx> crate::MirPass<'tcx> for StateTransform {
         // `storage_liveness` tells us which locals have live storage at suspension points
         let (remap, layout, storage_liveness) = compute_layout(liveness_info, body);
 
-        let can_return = can_return(tcx, body, tcx.param_env(body.source.def_id()));
+        let can_return = can_return(tcx, body, body.typing_env(tcx));
 
         // Run the transformation which converts Places from Local to coroutine struct
         // accesses for locals in `remap`.
diff --git a/compiler/rustc_mir_transform/src/cost_checker.rs b/compiler/rustc_mir_transform/src/cost_checker.rs
index 59b403538a3..b23d8b9e737 100644
--- a/compiler/rustc_mir_transform/src/cost_checker.rs
+++ b/compiler/rustc_mir_transform/src/cost_checker.rs
@@ -1,7 +1,7 @@
 use rustc_middle::bug;
 use rustc_middle::mir::visit::*;
 use rustc_middle::mir::*;
-use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt};
+use rustc_middle::ty::{self, Ty, TyCtxt};
 
 const INSTR_COST: usize = 5;
 const CALL_PENALTY: usize = 25;
@@ -14,7 +14,7 @@ const CONST_SWITCH_BONUS: usize = 10;
 #[derive(Clone)]
 pub(super) struct CostChecker<'b, 'tcx> {
     tcx: TyCtxt<'tcx>,
-    param_env: ParamEnv<'tcx>,
+    typing_env: ty::TypingEnv<'tcx>,
     penalty: usize,
     bonus: usize,
     callee_body: &'b Body<'tcx>,
@@ -24,11 +24,11 @@ pub(super) struct CostChecker<'b, 'tcx> {
 impl<'b, 'tcx> CostChecker<'b, 'tcx> {
     pub(super) fn new(
         tcx: TyCtxt<'tcx>,
-        param_env: ParamEnv<'tcx>,
+        typing_env: ty::TypingEnv<'tcx>,
         instance: Option<ty::Instance<'tcx>>,
         callee_body: &'b Body<'tcx>,
     ) -> CostChecker<'b, 'tcx> {
-        CostChecker { tcx, param_env, callee_body, instance, penalty: 0, bonus: 0 }
+        CostChecker { tcx, typing_env, callee_body, instance, penalty: 0, bonus: 0 }
     }
 
     /// Add function-level costs not well-represented by the block-level costs.
@@ -119,7 +119,7 @@ impl<'tcx> Visitor<'tcx> for CostChecker<'_, 'tcx> {
             TerminatorKind::Drop { place, unwind, .. } => {
                 // If the place doesn't actually need dropping, treat it like a regular goto.
                 let ty = self.instantiate_ty(place.ty(self.callee_body, self.tcx).ty);
-                if ty.needs_drop(self.tcx, self.param_env) {
+                if ty.needs_drop(self.tcx, self.typing_env) {
                     self.penalty += CALL_PENALTY;
                     if let UnwindAction::Cleanup(_) = unwind {
                         self.penalty += LANDINGPAD_PENALTY;
diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs
index ab6460c490b..500515bc3cc 100644
--- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs
+++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs
@@ -16,7 +16,7 @@ use rustc_middle::bug;
 use rustc_middle::mir::interpret::{InterpResult, Scalar};
 use rustc_middle::mir::visit::{MutVisitor, PlaceContext, Visitor};
 use rustc_middle::mir::*;
-use rustc_middle::ty::layout::{HasParamEnv, LayoutOf};
+use rustc_middle::ty::layout::LayoutOf;
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_mir_dataflow::fmt::DebugWithContext;
 use rustc_mir_dataflow::lattice::{FlatSet, HasBottom};
@@ -82,7 +82,7 @@ struct ConstAnalysis<'a, 'tcx> {
     tcx: TyCtxt<'tcx>,
     local_decls: &'a LocalDecls<'tcx>,
     ecx: InterpCx<'tcx, DummyMachine>,
-    param_env: ty::ParamEnv<'tcx>,
+    typing_env: ty::TypingEnv<'tcx>,
 }
 
 impl<'tcx> Analysis<'tcx> for ConstAnalysis<'_, 'tcx> {
@@ -144,13 +144,13 @@ impl<'tcx> Analysis<'tcx> for ConstAnalysis<'_, 'tcx> {
 
 impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> {
     fn new(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, map: Map<'tcx>) -> Self {
-        let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id());
+        let typing_env = body.typing_env(tcx);
         Self {
             map,
             tcx,
             local_decls: &body.local_decls,
-            ecx: InterpCx::new(tcx, DUMMY_SP, param_env, DummyMachine),
-            param_env,
+            ecx: InterpCx::new(tcx, DUMMY_SP, typing_env.param_env, DummyMachine),
+            typing_env,
         }
     }
 
@@ -389,7 +389,7 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> {
                     && let Some(operand_ty) = operand_ty.builtin_deref(true)
                     && let ty::Array(_, len) = operand_ty.kind()
                     && let Some(len) = Const::Ty(self.tcx.types.usize, *len)
-                        .try_eval_scalar_int(self.tcx, self.param_env)
+                        .try_eval_scalar_int(self.tcx, self.typing_env)
                 {
                     state.insert_value_idx(target_len, FlatSet::Elem(len.into()), &self.map);
                 }
@@ -411,7 +411,7 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> {
                 let place_ty = place.ty(self.local_decls, self.tcx);
                 if let ty::Array(_, len) = place_ty.ty.kind() {
                     Const::Ty(self.tcx.types.usize, *len)
-                        .try_eval_scalar(self.tcx, self.param_env)
+                        .try_eval_scalar(self.tcx, self.typing_env)
                         .map_or(FlatSet::Top, FlatSet::Elem)
                 } else if let [ProjectionElem::Deref] = place.projection[..] {
                     state.get_len(place.local.into(), &self.map)
@@ -420,7 +420,7 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> {
                 }
             }
             Rvalue::Cast(CastKind::IntToInt | CastKind::IntToFloat, operand, ty) => {
-                let Ok(layout) = self.tcx.layout_of(self.param_env.and(*ty)) else {
+                let Ok(layout) = self.tcx.layout_of(self.typing_env.as_query_input(*ty)) else {
                     return ValueOrPlace::Value(FlatSet::Top);
                 };
                 match self.eval_operand(operand, state) {
@@ -434,7 +434,7 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> {
                 }
             }
             Rvalue::Cast(CastKind::FloatToInt | CastKind::FloatToFloat, operand, ty) => {
-                let Ok(layout) = self.tcx.layout_of(self.param_env.and(*ty)) else {
+                let Ok(layout) = self.tcx.layout_of(self.typing_env.as_query_input(*ty)) else {
                     return ValueOrPlace::Value(FlatSet::Top);
                 };
                 match self.eval_operand(operand, state) {
@@ -470,7 +470,7 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> {
                 FlatSet::Top => FlatSet::Top,
             },
             Rvalue::NullaryOp(null_op, ty) => {
-                let Ok(layout) = self.tcx.layout_of(self.param_env.and(*ty)) else {
+                let Ok(layout) = self.tcx.layout_of(self.typing_env.as_query_input(*ty)) else {
                     return ValueOrPlace::Value(FlatSet::Top);
                 };
                 let val = match null_op {
@@ -479,7 +479,7 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> {
                     NullOp::OffsetOf(fields) => self
                         .ecx
                         .tcx
-                        .offset_of_subfield(self.ecx.param_env(), layout, fields.iter())
+                        .offset_of_subfield(self.typing_env, layout, fields.iter())
                         .bytes(),
                     _ => return ValueOrPlace::Value(FlatSet::Top),
                 };
@@ -514,7 +514,7 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> {
     ) -> FlatSet<Scalar> {
         constant
             .const_
-            .try_eval_scalar(self.tcx, self.param_env)
+            .try_eval_scalar(self.tcx, self.typing_env)
             .map_or(FlatSet::Top, FlatSet::Elem)
     }
 
@@ -554,7 +554,8 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> {
                 } else if rhs.projection.first() == Some(&PlaceElem::Deref)
                     && let FlatSet::Elem(pointer) = state.get(rhs.local.into(), &self.map)
                     && let rhs_ty = self.local_decls[rhs.local].ty
-                    && let Ok(rhs_layout) = self.tcx.layout_of(self.param_env.and(rhs_ty))
+                    && let Ok(rhs_layout) =
+                        self.tcx.layout_of(self.typing_env.as_query_input(rhs_ty))
                 {
                     let op = ImmTy::from_scalar(pointer, rhs_layout).into();
                     self.assign_constant(state, place, op, rhs.projection);
@@ -614,8 +615,10 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> {
                 TrackElem::DerefLen => {
                     let op: OpTy<'_> = self.ecx.deref_pointer(op).discard_err()?.into();
                     let len_usize = op.len(&self.ecx).discard_err()?;
-                    let layout =
-                        self.tcx.layout_of(self.param_env.and(self.tcx.types.usize)).unwrap();
+                    let layout = self
+                        .tcx
+                        .layout_of(self.typing_env.as_query_input(self.tcx.types.usize))
+                        .unwrap();
                     Some(ImmTy::from_uint(len_usize, layout).into())
                 }
             },
@@ -702,9 +705,11 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> {
             FlatSet::Top => FlatSet::Top,
             FlatSet::Elem(scalar) => {
                 let ty = op.ty(self.local_decls, self.tcx);
-                self.tcx.layout_of(self.param_env.and(ty)).map_or(FlatSet::Top, |layout| {
-                    FlatSet::Elem(ImmTy::from_scalar(scalar, layout))
-                })
+                self.tcx
+                    .layout_of(self.typing_env.as_query_input(ty))
+                    .map_or(FlatSet::Top, |layout| {
+                        FlatSet::Elem(ImmTy::from_scalar(scalar, layout))
+                    })
             }
             FlatSet::Bottom => FlatSet::Bottom,
         }
@@ -714,7 +719,7 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> {
         if !enum_ty.is_enum() {
             return None;
         }
-        let enum_ty_layout = self.tcx.layout_of(self.param_env.and(enum_ty)).ok()?;
+        let enum_ty_layout = self.tcx.layout_of(self.typing_env.as_query_input(enum_ty)).ok()?;
         let discr_value =
             self.ecx.discriminant_for_variant(enum_ty_layout.ty, variant_index).discard_err()?;
         Some(discr_value.to_scalar())
diff --git a/compiler/rustc_mir_transform/src/deduce_param_attrs.rs b/compiler/rustc_mir_transform/src/deduce_param_attrs.rs
index 753bae8e156..db72ec522a2 100644
--- a/compiler/rustc_mir_transform/src/deduce_param_attrs.rs
+++ b/compiler/rustc_mir_transform/src/deduce_param_attrs.rs
@@ -198,7 +198,7 @@ pub(super) fn deduced_param_attrs<'tcx>(
     // see [1].
     //
     // [1]: https://github.com/rust-lang/rust/pull/103172#discussion_r999139997
-    let param_env = tcx.param_env_reveal_all_normalized(def_id);
+    let typing_env = body.typing_env(tcx);
     let mut deduced_param_attrs = tcx.arena.alloc_from_iter(
         body.local_decls.iter().skip(1).take(body.arg_count).enumerate().map(
             |(arg_index, local_decl)| DeducedParamAttrs {
@@ -207,8 +207,8 @@ pub(super) fn deduced_param_attrs<'tcx>(
                     // their generic parameters, otherwise we'll see exponential
                     // blow-up in compile times: #113372
                     && tcx
-                        .normalize_erasing_regions(param_env, local_decl.ty)
-                        .is_freeze(tcx, param_env),
+                        .normalize_erasing_regions(typing_env, local_decl.ty)
+                        .is_freeze(tcx, typing_env.param_env),
             },
         ),
     );
diff --git a/compiler/rustc_mir_transform/src/elaborate_drops.rs b/compiler/rustc_mir_transform/src/elaborate_drops.rs
index 74572100db3..b0f041d8722 100644
--- a/compiler/rustc_mir_transform/src/elaborate_drops.rs
+++ b/compiler/rustc_mir_transform/src/elaborate_drops.rs
@@ -3,6 +3,7 @@ use std::fmt;
 use rustc_abi::{FieldIdx, VariantIdx};
 use rustc_index::IndexVec;
 use rustc_index::bit_set::BitSet;
+use rustc_infer::traits::Reveal;
 use rustc_middle::mir::patch::MirPatch;
 use rustc_middle::mir::*;
 use rustc_middle::ty::{self, TyCtxt};
@@ -53,14 +54,14 @@ impl<'tcx> crate::MirPass<'tcx> for ElaborateDrops {
     #[instrument(level = "trace", skip(self, tcx, body))]
     fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
         debug!("elaborate_drops({:?} @ {:?})", body.source, body.span);
-
-        let def_id = body.source.def_id();
-        let param_env = tcx.param_env_reveal_all_normalized(def_id);
+        // FIXME(#132279): This is used during the phase transition from analysis
+        // to runtime, so we have to manually specify the correct typing mode.
+        let typing_env = ty::TypingEnv::post_analysis(tcx, body.source.def_id());
         // For types that do not need dropping, the behaviour is trivial. So we only need to track
         // init/uninit for types that do need dropping.
-        let move_data = MoveData::gather_moves(body, tcx, |ty| ty.needs_drop(tcx, param_env));
+        let move_data = MoveData::gather_moves(body, tcx, |ty| ty.needs_drop(tcx, typing_env));
         let elaborate_patch = {
-            let env = MoveDataParamEnv { move_data, param_env };
+            let env = MoveDataParamEnv { move_data, param_env: typing_env.param_env };
 
             let mut inits = MaybeInitializedPlaces::new(tcx, body, &env.move_data)
                 .skipping_unreachable_unwind()
@@ -147,8 +148,8 @@ impl<'a, 'tcx> DropElaborator<'a, 'tcx> for ElaborateDropsCtxt<'a, 'tcx> {
         self.tcx
     }
 
-    fn param_env(&self) -> ty::ParamEnv<'tcx> {
-        self.param_env()
+    fn typing_env(&self) -> ty::TypingEnv<'tcx> {
+        self.typing_env()
     }
 
     #[instrument(level = "debug", skip(self), ret)]
@@ -250,6 +251,11 @@ impl<'a, 'tcx> ElaborateDropsCtxt<'a, 'tcx> {
         self.env.param_env
     }
 
+    fn typing_env(&self) -> ty::TypingEnv<'tcx> {
+        debug_assert_eq!(self.param_env().reveal(), Reveal::All);
+        ty::TypingEnv { typing_mode: ty::TypingMode::PostAnalysis, param_env: self.param_env() }
+    }
+
     fn create_drop_flag(&mut self, index: MovePathIndex, span: Span) {
         let patch = &mut self.patch;
         debug!("create_drop_flag({:?})", self.body.span);
@@ -335,7 +341,7 @@ impl<'a, 'tcx> ElaborateDropsCtxt<'a, 'tcx> {
             if !place
                 .ty(&self.body.local_decls, self.tcx)
                 .ty
-                .needs_drop(self.tcx, self.env.param_env)
+                .needs_drop(self.tcx, self.typing_env())
             {
                 self.patch.patch_terminator(bb, TerminatorKind::Goto { target });
                 continue;
diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs
index 274eea9563f..27fe0ad72e7 100644
--- a/compiler/rustc_mir_transform/src/gvn.rs
+++ b/compiler/rustc_mir_transform/src/gvn.rs
@@ -100,7 +100,7 @@ use rustc_middle::bug;
 use rustc_middle::mir::interpret::GlobalAlloc;
 use rustc_middle::mir::visit::*;
 use rustc_middle::mir::*;
-use rustc_middle::ty::layout::{HasParamEnv, LayoutOf};
+use rustc_middle::ty::layout::LayoutOf;
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_span::DUMMY_SP;
 use rustc_span::def_id::DefId;
@@ -295,6 +295,10 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
         }
     }
 
+    fn typing_env(&self) -> ty::TypingEnv<'tcx> {
+        ty::TypingEnv { typing_mode: ty::TypingMode::PostAnalysis, param_env: self.param_env }
+    }
+
     #[instrument(level = "trace", skip(self), ret)]
     fn insert(&mut self, value: Value<'tcx>) -> VnIndex {
         let (index, new) = self.values.insert_full(value);
@@ -531,7 +535,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
                     NullOp::OffsetOf(fields) => self
                         .ecx
                         .tcx
-                        .offset_of_subfield(self.ecx.param_env(), layout, fields.iter())
+                        .offset_of_subfield(self.typing_env(), layout, fields.iter())
                         .bytes(),
                     NullOp::UbChecks => return None,
                 };
@@ -1476,8 +1480,9 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
         if left_meta_ty == right_meta_ty {
             true
         } else if let Ok(left) =
-            self.tcx.try_normalize_erasing_regions(self.param_env, left_meta_ty)
-            && let Ok(right) = self.tcx.try_normalize_erasing_regions(self.param_env, right_meta_ty)
+            self.tcx.try_normalize_erasing_regions(self.typing_env(), left_meta_ty)
+            && let Ok(right) =
+                self.tcx.try_normalize_erasing_regions(self.typing_env(), right_meta_ty)
         {
             left == right
         } else {
diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs
index e95ab4ffe16..fcb51fbddd9 100644
--- a/compiler/rustc_mir_transform/src/inline.rs
+++ b/compiler/rustc_mir_transform/src/inline.rs
@@ -13,9 +13,7 @@ use rustc_middle::bug;
 use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
 use rustc_middle::mir::visit::*;
 use rustc_middle::mir::*;
-use rustc_middle::ty::{
-    self, Instance, InstanceKind, ParamEnv, Ty, TyCtxt, TypeFlags, TypeVisitableExt,
-};
+use rustc_middle::ty::{self, Instance, InstanceKind, Ty, TyCtxt, TypeFlags, TypeVisitableExt};
 use rustc_session::config::{DebugInfo, OptLevel};
 use rustc_span::source_map::Spanned;
 use rustc_span::sym;
@@ -94,12 +92,12 @@ fn inline<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) -> bool {
         return false;
     }
 
-    let param_env = tcx.param_env_reveal_all_normalized(def_id);
+    let typing_env = body.typing_env(tcx);
     let codegen_fn_attrs = tcx.codegen_fn_attrs(def_id);
 
     let mut this = Inliner {
         tcx,
-        param_env,
+        typing_env,
         codegen_fn_attrs,
         history: Vec::new(),
         changed: false,
@@ -115,7 +113,7 @@ fn inline<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) -> bool {
 
 struct Inliner<'tcx> {
     tcx: TyCtxt<'tcx>,
-    param_env: ParamEnv<'tcx>,
+    typing_env: ty::TypingEnv<'tcx>,
     /// Caller codegen attributes.
     codegen_fn_attrs: &'tcx CodegenFnAttrs,
     /// Stack of inlined instances.
@@ -201,7 +199,11 @@ impl<'tcx> Inliner<'tcx> {
         let TerminatorKind::Call { args, destination, .. } = &terminator.kind else { bug!() };
         let destination_ty = destination.ty(&caller_body.local_decls, self.tcx).ty;
         for arg in args {
-            if !arg.node.ty(&caller_body.local_decls, self.tcx).is_sized(self.tcx, self.param_env) {
+            if !arg
+                .node
+                .ty(&caller_body.local_decls, self.tcx)
+                .is_sized(self.tcx, self.typing_env.param_env)
+            {
                 // We do not allow inlining functions with unsized params. Inlining these functions
                 // could create unsized locals, which are unsound and being phased out.
                 return Err("Call has unsized argument");
@@ -219,7 +221,7 @@ impl<'tcx> Inliner<'tcx> {
 
         let Ok(callee_body) = callsite.callee.try_instantiate_mir_and_normalize_erasing_regions(
             self.tcx,
-            self.param_env,
+            self.typing_env,
             ty::EarlyBinder::bind(callee_body.clone()),
         ) else {
             return Err("failed to normalize callee body");
@@ -230,7 +232,7 @@ impl<'tcx> Inliner<'tcx> {
         if !validate_types(
             self.tcx,
             MirPhase::Runtime(RuntimePhase::Optimized),
-            self.param_env,
+            self.typing_env,
             &callee_body,
             &caller_body,
         )
@@ -243,13 +245,7 @@ impl<'tcx> Inliner<'tcx> {
         // Normally, this shouldn't be required, but trait normalization failure can create a
         // validation ICE.
         let output_type = callee_body.return_ty();
-        if !util::sub_types(
-            self.tcx,
-            caller_body.typing_mode(self.tcx),
-            self.param_env,
-            output_type,
-            destination_ty,
-        ) {
+        if !util::sub_types(self.tcx, self.typing_env, output_type, destination_ty) {
             trace!(?output_type, ?destination_ty);
             return Err("failed to normalize return type");
         }
@@ -279,13 +275,7 @@ impl<'tcx> Inliner<'tcx> {
                 self_arg_ty.into_iter().chain(arg_tuple_tys).zip(callee_body.args_iter())
             {
                 let input_type = callee_body.local_decls[input].ty;
-                if !util::sub_types(
-                    self.tcx,
-                    caller_body.typing_mode(self.tcx),
-                    self.param_env,
-                    input_type,
-                    arg_ty,
-                ) {
+                if !util::sub_types(self.tcx, self.typing_env, input_type, arg_ty) {
                     trace!(?arg_ty, ?input_type);
                     return Err("failed to normalize tuple argument type");
                 }
@@ -294,13 +284,7 @@ impl<'tcx> Inliner<'tcx> {
             for (arg, input) in args.iter().zip(callee_body.args_iter()) {
                 let input_type = callee_body.local_decls[input].ty;
                 let arg_ty = arg.node.ty(&caller_body.local_decls, self.tcx);
-                if !util::sub_types(
-                    self.tcx,
-                    caller_body.typing_mode(self.tcx),
-                    self.param_env,
-                    input_type,
-                    arg_ty,
-                ) {
+                if !util::sub_types(self.tcx, self.typing_env, input_type, arg_ty) {
                     trace!(?arg_ty, ?input_type);
                     return Err("failed to normalize argument type");
                 }
@@ -402,9 +386,10 @@ impl<'tcx> Inliner<'tcx> {
             let func_ty = func.ty(caller_body, self.tcx);
             if let ty::FnDef(def_id, args) = *func_ty.kind() {
                 // To resolve an instance its args have to be fully normalized.
-                let args = self.tcx.try_normalize_erasing_regions(self.param_env, args).ok()?;
-                let callee =
-                    Instance::try_resolve(self.tcx, self.param_env, def_id, args).ok().flatten()?;
+                let args = self.tcx.try_normalize_erasing_regions(self.typing_env, args).ok()?;
+                let callee = Instance::try_resolve(self.tcx, self.typing_env, def_id, args)
+                    .ok()
+                    .flatten()?;
 
                 if let InstanceKind::Virtual(..) | InstanceKind::Intrinsic(_) = callee.def {
                     return None;
@@ -528,7 +513,7 @@ impl<'tcx> Inliner<'tcx> {
         // FIXME: Give a bonus to functions with only a single caller
 
         let mut checker =
-            CostChecker::new(self.tcx, self.param_env, Some(callsite.callee), callee_body);
+            CostChecker::new(self.tcx, self.typing_env, Some(callsite.callee), callee_body);
 
         checker.add_function_level_costs();
 
@@ -552,7 +537,7 @@ impl<'tcx> Inliner<'tcx> {
                     self.tcx,
                     ty::EarlyBinder::bind(&place.ty(callee_body, tcx).ty),
                 );
-                if ty.needs_drop(tcx, self.param_env)
+                if ty.needs_drop(tcx, self.typing_env)
                     && let UnwindAction::Cleanup(unwind) = unwind
                 {
                     work_list.push(unwind);
diff --git a/compiler/rustc_mir_transform/src/inline/cycle.rs b/compiler/rustc_mir_transform/src/inline/cycle.rs
index 9828e90de88..a40768300f5 100644
--- a/compiler/rustc_mir_transform/src/inline/cycle.rs
+++ b/compiler/rustc_mir_transform/src/inline/cycle.rs
@@ -15,7 +15,6 @@ pub(crate) fn mir_callgraph_reachable<'tcx>(
     (root, target): (ty::Instance<'tcx>, LocalDefId),
 ) -> bool {
     trace!(%root, target = %tcx.def_path_str(target));
-    let param_env = tcx.param_env_reveal_all_normalized(target);
     assert_ne!(
         root.def_id().expect_local(),
         target,
@@ -31,11 +30,11 @@ pub(crate) fn mir_callgraph_reachable<'tcx>(
     );
     #[instrument(
         level = "debug",
-        skip(tcx, param_env, target, stack, seen, recursion_limiter, caller, recursion_limit)
+        skip(tcx, typing_env, target, stack, seen, recursion_limiter, caller, recursion_limit)
     )]
     fn process<'tcx>(
         tcx: TyCtxt<'tcx>,
-        param_env: ty::ParamEnv<'tcx>,
+        typing_env: ty::TypingEnv<'tcx>,
         caller: ty::Instance<'tcx>,
         target: LocalDefId,
         stack: &mut Vec<ty::Instance<'tcx>>,
@@ -47,13 +46,13 @@ pub(crate) fn mir_callgraph_reachable<'tcx>(
         for &(callee, args) in tcx.mir_inliner_callees(caller.def) {
             let Ok(args) = caller.try_instantiate_mir_and_normalize_erasing_regions(
                 tcx,
-                param_env,
+                typing_env,
                 ty::EarlyBinder::bind(args),
             ) else {
-                trace!(?caller, ?param_env, ?args, "cannot normalize, skipping");
+                trace!(?caller, ?typing_env, ?args, "cannot normalize, skipping");
                 continue;
             };
-            let Ok(Some(callee)) = ty::Instance::try_resolve(tcx, param_env, callee, args) else {
+            let Ok(Some(callee)) = ty::Instance::try_resolve(tcx, typing_env, callee, args) else {
                 trace!(?callee, "cannot resolve, skipping");
                 continue;
             };
@@ -115,7 +114,7 @@ pub(crate) fn mir_callgraph_reachable<'tcx>(
                     let found_recursion = ensure_sufficient_stack(|| {
                         process(
                             tcx,
-                            param_env,
+                            typing_env,
                             callee,
                             target,
                             stack,
@@ -146,7 +145,7 @@ pub(crate) fn mir_callgraph_reachable<'tcx>(
     let recursion_limit = tcx.recursion_limit() / 2;
     process(
         tcx,
-        param_env,
+        ty::TypingEnv::post_analysis(tcx, target),
         root,
         target,
         &mut Vec::new(),
diff --git a/compiler/rustc_mir_transform/src/instsimplify.rs b/compiler/rustc_mir_transform/src/instsimplify.rs
index 9471c1b2a9a..b80abcca969 100644
--- a/compiler/rustc_mir_transform/src/instsimplify.rs
+++ b/compiler/rustc_mir_transform/src/instsimplify.rs
@@ -70,6 +70,12 @@ struct InstSimplifyContext<'a, 'tcx> {
 }
 
 impl<'tcx> InstSimplifyContext<'_, 'tcx> {
+    fn typing_env(&self) -> ty::TypingEnv<'tcx> {
+        ty::TypingEnv { typing_mode: ty::TypingMode::PostAnalysis, param_env: self.param_env }
+    }
+}
+
+impl<'tcx> InstSimplifyContext<'_, 'tcx> {
     fn should_simplify(&self, source_info: &SourceInfo, rvalue: &Rvalue<'tcx>) -> bool {
         self.should_simplify_custom(source_info, "Rvalue", rvalue)
     }
@@ -348,7 +354,7 @@ impl<'tcx> InstSimplifyContext<'_, 'tcx> {
         }
 
         let known_is_valid =
-            intrinsic_assert_panics(self.tcx, self.param_env, args[0], intrinsic_name);
+            intrinsic_assert_panics(self.tcx, self.typing_env(), args[0], intrinsic_name);
         match known_is_valid {
             // We don't know the layout or it's not validity assertion at all, don't touch it
             None => {}
@@ -366,13 +372,13 @@ impl<'tcx> InstSimplifyContext<'_, 'tcx> {
 
 fn intrinsic_assert_panics<'tcx>(
     tcx: TyCtxt<'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
+    typing_env: ty::TypingEnv<'tcx>,
     arg: ty::GenericArg<'tcx>,
     intrinsic_name: Symbol,
 ) -> Option<bool> {
     let requirement = ValidityRequirement::from_intrinsic(intrinsic_name)?;
     let ty = arg.expect_ty();
-    Some(!tcx.check_validity_requirement((requirement, param_env.and(ty))).ok()?)
+    Some(!tcx.check_validity_requirement((requirement, typing_env.as_query_input(ty))).ok()?)
 }
 
 fn resolve_rust_intrinsic<'tcx>(
diff --git a/compiler/rustc_mir_transform/src/jump_threading.rs b/compiler/rustc_mir_transform/src/jump_threading.rs
index 3772589ac4e..71a843a785c 100644
--- a/compiler/rustc_mir_transform/src/jump_threading.rs
+++ b/compiler/rustc_mir_transform/src/jump_threading.rs
@@ -77,13 +77,12 @@ impl<'tcx> crate::MirPass<'tcx> for JumpThreading {
             return;
         }
 
-        let param_env = tcx.param_env_reveal_all_normalized(def_id);
-
+        let typing_env = body.typing_env(tcx);
         let arena = &DroplessArena::default();
         let mut finder = TOFinder {
             tcx,
-            param_env,
-            ecx: InterpCx::new(tcx, DUMMY_SP, param_env, DummyMachine),
+            typing_env,
+            ecx: InterpCx::new(tcx, DUMMY_SP, typing_env.param_env, DummyMachine),
             body,
             arena,
             map: Map::new(tcx, body, Some(MAX_PLACES)),
@@ -119,7 +118,7 @@ struct ThreadingOpportunity {
 
 struct TOFinder<'a, 'tcx> {
     tcx: TyCtxt<'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
+    typing_env: ty::TypingEnv<'tcx>,
     ecx: InterpCx<'tcx, DummyMachine>,
     body: &'a Body<'tcx>,
     map: Map<'tcx>,
@@ -207,7 +206,7 @@ impl<'a, 'tcx> TOFinder<'a, 'tcx> {
         let Some(discr) = self.map.find(discr.as_ref()) else { return };
         debug!(?discr);
 
-        let cost = CostChecker::new(self.tcx, self.param_env, None, self.body);
+        let cost = CostChecker::new(self.tcx, self.typing_env, None, self.body);
         let mut state = State::new_reachable();
 
         let conds = if let Some((value, then, else_)) = targets.as_static_if() {
@@ -528,7 +527,8 @@ impl<'a, 'tcx> TOFinder<'a, 'tcx> {
                     // Avoid handling them, though this could be extended in the future.
                     return;
                 }
-                let Some(value) = value.const_.try_eval_scalar_int(self.tcx, self.param_env) else {
+                let Some(value) = value.const_.try_eval_scalar_int(self.tcx, self.typing_env)
+                else {
                     return;
                 };
                 let conds = conditions.map(self.arena, |c| Condition {
diff --git a/compiler/rustc_mir_transform/src/known_panics_lint.rs b/compiler/rustc_mir_transform/src/known_panics_lint.rs
index 0604665642a..3911b0a2db6 100644
--- a/compiler/rustc_mir_transform/src/known_panics_lint.rs
+++ b/compiler/rustc_mir_transform/src/known_panics_lint.rs
@@ -18,7 +18,7 @@ use rustc_middle::bug;
 use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor};
 use rustc_middle::mir::*;
 use rustc_middle::ty::layout::{LayoutError, LayoutOf, LayoutOfHelpers, TyAndLayout};
-use rustc_middle::ty::{self, ConstInt, ParamEnv, ScalarInt, Ty, TyCtxt, TypeVisitableExt};
+use rustc_middle::ty::{self, ConstInt, ScalarInt, Ty, TyCtxt, TypeVisitableExt};
 use rustc_span::Span;
 use tracing::{debug, instrument, trace};
 
@@ -65,7 +65,7 @@ impl<'tcx> crate::MirLint<'tcx> for KnownPanicsLint {
 struct ConstPropagator<'mir, 'tcx> {
     ecx: InterpCx<'tcx, DummyMachine>,
     tcx: TyCtxt<'tcx>,
-    param_env: ParamEnv<'tcx>,
+    typing_env: ty::TypingEnv<'tcx>,
     worklist: Vec<BasicBlock>,
     visited_blocks: BitSet<BasicBlock>,
     locals: IndexVec<Local, Value<'tcx>>,
@@ -169,25 +169,26 @@ impl<'tcx> ty::layout::HasTyCtxt<'tcx> for ConstPropagator<'_, 'tcx> {
     }
 }
 
-impl<'tcx> ty::layout::HasParamEnv<'tcx> for ConstPropagator<'_, 'tcx> {
+impl<'tcx> ty::layout::HasTypingEnv<'tcx> for ConstPropagator<'_, 'tcx> {
     #[inline]
-    fn param_env(&self) -> ty::ParamEnv<'tcx> {
-        self.param_env
+    fn typing_env(&self) -> ty::TypingEnv<'tcx> {
+        self.typing_env
     }
 }
 
 impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
     fn new(body: &'mir Body<'tcx>, tcx: TyCtxt<'tcx>) -> ConstPropagator<'mir, 'tcx> {
         let def_id = body.source.def_id();
-        let param_env = tcx.param_env_reveal_all_normalized(def_id);
-
-        let can_const_prop = CanConstProp::check(tcx, param_env, body);
-        let ecx = InterpCx::new(tcx, tcx.def_span(def_id), param_env, DummyMachine);
+        // FIXME(#132279): This is used during the phase transition from analysis
+        // to runtime, so we have to manually specify the correct typing mode.
+        let typing_env = ty::TypingEnv::post_analysis(tcx, body.source.def_id());
+        let can_const_prop = CanConstProp::check(tcx, typing_env, body);
+        let ecx = InterpCx::new(tcx, tcx.def_span(def_id), typing_env.param_env, DummyMachine);
 
         ConstPropagator {
             ecx,
             tcx,
-            param_env,
+            typing_env,
             worklist: vec![START_BLOCK],
             visited_blocks: BitSet::new_empty(body.basic_blocks.len()),
             locals: IndexVec::from_elem_n(Value::Uninit, body.local_decls.len()),
@@ -260,7 +261,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
         // that the `RevealAll` pass has happened and that the body's consts
         // are normalized, so any call to resolve before that needs to be
         // manually normalized.
-        let val = self.tcx.try_normalize_erasing_regions(self.param_env, c.const_).ok()?;
+        let val = self.tcx.try_normalize_erasing_regions(self.typing_env, c.const_).ok()?;
 
         self.use_ecx(|this| this.ecx.eval_mir_constant(&val, c.span, None))?
             .as_mplace_or_imm()
@@ -450,7 +451,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
         if rvalue.has_param() {
             return None;
         }
-        if !rvalue.ty(self.local_decls(), self.tcx).is_sized(self.tcx, self.param_env) {
+        if !rvalue.ty(self.local_decls(), self.tcx).is_sized(self.tcx, self.typing_env.param_env) {
             // the interpreter doesn't support unsized locals (only unsized arguments),
             // but rustc does (in a kinda broken way), so we have to skip them here
             return None;
@@ -622,7 +623,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
                     NullOp::AlignOf => op_layout.align.abi.bytes(),
                     NullOp::OffsetOf(fields) => self
                         .tcx
-                        .offset_of_subfield(self.param_env, op_layout, fields.iter())
+                        .offset_of_subfield(self.typing_env, op_layout, fields.iter())
                         .bytes(),
                     NullOp::UbChecks => return None,
                 };
@@ -873,7 +874,7 @@ impl CanConstProp {
     /// Returns true if `local` can be propagated
     fn check<'tcx>(
         tcx: TyCtxt<'tcx>,
-        param_env: ParamEnv<'tcx>,
+        typing_env: ty::TypingEnv<'tcx>,
         body: &Body<'tcx>,
     ) -> IndexVec<Local, ConstPropMode> {
         let mut cpv = CanConstProp {
@@ -888,7 +889,7 @@ impl CanConstProp {
                 // variant of a union
                 *val = ConstPropMode::NoPropagation;
             } else {
-                match tcx.layout_of(param_env.and(ty)) {
+                match tcx.layout_of(typing_env.as_query_input(ty)) {
                     Ok(layout) if layout.size < Size::from_bytes(MAX_ALLOC_LIMIT) => {}
                     // Either the layout fails to compute, then we can't use this local anyway
                     // or the local is too large, then we don't want to.
diff --git a/compiler/rustc_mir_transform/src/large_enums.rs b/compiler/rustc_mir_transform/src/large_enums.rs
index fa659a56a27..8be5a63d008 100644
--- a/compiler/rustc_mir_transform/src/large_enums.rs
+++ b/compiler/rustc_mir_transform/src/large_enums.rs
@@ -3,7 +3,7 @@ use rustc_data_structures::fx::FxHashMap;
 use rustc_middle::mir::interpret::AllocId;
 use rustc_middle::mir::*;
 use rustc_middle::ty::util::IntTypeExt;
-use rustc_middle::ty::{self, AdtDef, ParamEnv, Ty, TyCtxt};
+use rustc_middle::ty::{self, AdtDef, Ty, TyCtxt};
 use rustc_session::Session;
 
 /// A pass that seeks to optimize unnecessary moves of large enum types, if there is a large
@@ -39,8 +39,7 @@ impl<'tcx> crate::MirPass<'tcx> for EnumSizeOpt {
         // platform, but it will still be valid.
 
         let mut alloc_cache = FxHashMap::default();
-        let body_did = body.source.def_id();
-        let param_env = tcx.param_env_reveal_all_normalized(body_did);
+        let typing_env = body.typing_env(tcx);
 
         let blocks = body.basic_blocks.as_mut();
         let local_decls = &mut body.local_decls;
@@ -58,7 +57,7 @@ impl<'tcx> crate::MirPass<'tcx> for EnumSizeOpt {
                 let ty = lhs.ty(local_decls, tcx).ty;
 
                 let (adt_def, num_variants, alloc_id) =
-                    self.candidate(tcx, param_env, ty, &mut alloc_cache)?;
+                    self.candidate(tcx, typing_env, ty, &mut alloc_cache)?;
 
                 let source_info = st.source_info;
                 let span = source_info.span;
@@ -207,7 +206,7 @@ impl EnumSizeOpt {
     fn candidate<'tcx>(
         &self,
         tcx: TyCtxt<'tcx>,
-        param_env: ParamEnv<'tcx>,
+        typing_env: ty::TypingEnv<'tcx>,
         ty: Ty<'tcx>,
         alloc_cache: &mut FxHashMap<Ty<'tcx>, AllocId>,
     ) -> Option<(AdtDef<'tcx>, usize, AllocId)> {
@@ -215,7 +214,7 @@ impl EnumSizeOpt {
             ty::Adt(adt_def, _args) if adt_def.is_enum() => adt_def,
             _ => return None,
         };
-        let layout = tcx.layout_of(param_env.and(ty)).ok()?;
+        let layout = tcx.layout_of(typing_env.as_query_input(ty)).ok()?;
         let variants = match &layout.variants {
             Variants::Single { .. } => return None,
             Variants::Multiple { tag_encoding: TagEncoding::Niche { .. }, .. } => return None,
diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs
index d2d5facbbdc..5651bf469d5 100644
--- a/compiler/rustc_mir_transform/src/lib.rs
+++ b/compiler/rustc_mir_transform/src/lib.rs
@@ -333,10 +333,14 @@ fn mir_keys(tcx: TyCtxt<'_>, (): ()) -> FxIndexSet<LocalDefId> {
 }
 
 fn mir_const_qualif(tcx: TyCtxt<'_>, def: LocalDefId) -> ConstQualifs {
-    let const_kind = tcx.hir().body_const_context(def);
-
+    // N.B., this `borrow()` is guaranteed to be valid (i.e., the value
+    // cannot yet be stolen), because `mir_promoted()`, which steals
+    // from `mir_built()`, forces this query to execute before
+    // performing the steal.
+    let body = &tcx.mir_built(def).borrow();
+    let ccx = check_consts::ConstCx::new(tcx, body);
     // No need to const-check a non-const `fn`.
-    match const_kind {
+    match ccx.const_kind {
         Some(ConstContext::Const { .. } | ConstContext::Static(_) | ConstContext::ConstFn) => {}
         None => span_bug!(
             tcx.def_span(def),
@@ -344,20 +348,12 @@ fn mir_const_qualif(tcx: TyCtxt<'_>, def: LocalDefId) -> ConstQualifs {
         ),
     }
 
-    // N.B., this `borrow()` is guaranteed to be valid (i.e., the value
-    // cannot yet be stolen), because `mir_promoted()`, which steals
-    // from `mir_built()`, forces this query to execute before
-    // performing the steal.
-    let body = &tcx.mir_built(def).borrow();
-
     if body.return_ty().references_error() {
         // It's possible to reach here without an error being emitted (#121103).
         tcx.dcx().span_delayed_bug(body.span, "mir_const_qualif: MIR had errors");
         return Default::default();
     }
 
-    let ccx = check_consts::ConstCx { body, tcx, const_kind, param_env: tcx.param_env(def) };
-
     let mut validator = check_consts::check::Checker::new(&ccx);
     validator.check_body();
 
diff --git a/compiler/rustc_mir_transform/src/match_branches.rs b/compiler/rustc_mir_transform/src/match_branches.rs
index 237227f5294..ff027680c49 100644
--- a/compiler/rustc_mir_transform/src/match_branches.rs
+++ b/compiler/rustc_mir_transform/src/match_branches.rs
@@ -5,7 +5,7 @@ use rustc_index::IndexSlice;
 use rustc_middle::mir::patch::MirPatch;
 use rustc_middle::mir::*;
 use rustc_middle::ty::layout::{IntegerExt, TyAndLayout};
-use rustc_middle::ty::{ParamEnv, ScalarInt, Ty, TyCtxt};
+use rustc_middle::ty::{self, ScalarInt, Ty, TyCtxt};
 use rustc_type_ir::TyKind::*;
 
 use super::simplify::simplify_cfg;
@@ -19,8 +19,7 @@ impl<'tcx> crate::MirPass<'tcx> for MatchBranchSimplification {
 
     fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
         let def_id = body.source.def_id();
-        let param_env = tcx.param_env_reveal_all_normalized(def_id);
-
+        let typing_env = body.typing_env(tcx);
         let mut should_cleanup = false;
         for i in 0..body.basic_blocks.len() {
             let bbs = &*body.basic_blocks;
@@ -40,11 +39,11 @@ impl<'tcx> crate::MirPass<'tcx> for MatchBranchSimplification {
                 _ => continue,
             };
 
-            if SimplifyToIf.simplify(tcx, body, bb_idx, param_env).is_some() {
+            if SimplifyToIf.simplify(tcx, body, bb_idx, typing_env).is_some() {
                 should_cleanup = true;
                 continue;
             }
-            if SimplifyToExp::default().simplify(tcx, body, bb_idx, param_env).is_some() {
+            if SimplifyToExp::default().simplify(tcx, body, bb_idx, typing_env).is_some() {
                 should_cleanup = true;
                 continue;
             }
@@ -65,7 +64,7 @@ trait SimplifyMatch<'tcx> {
         tcx: TyCtxt<'tcx>,
         body: &mut Body<'tcx>,
         switch_bb_idx: BasicBlock,
-        param_env: ParamEnv<'tcx>,
+        typing_env: ty::TypingEnv<'tcx>,
     ) -> Option<()> {
         let bbs = &body.basic_blocks;
         let (discr, targets) = match bbs[switch_bb_idx].terminator().kind {
@@ -74,7 +73,7 @@ trait SimplifyMatch<'tcx> {
         };
 
         let discr_ty = discr.ty(body.local_decls(), tcx);
-        self.can_simplify(tcx, targets, param_env, bbs, discr_ty)?;
+        self.can_simplify(tcx, targets, typing_env, bbs, discr_ty)?;
 
         let mut patch = MirPatch::new(body);
 
@@ -90,7 +89,16 @@ trait SimplifyMatch<'tcx> {
         let parent_end = Location { block: switch_bb_idx, statement_index };
         patch.add_statement(parent_end, StatementKind::StorageLive(discr_local));
         patch.add_assign(parent_end, Place::from(discr_local), Rvalue::Use(discr));
-        self.new_stmts(tcx, targets, param_env, &mut patch, parent_end, bbs, discr_local, discr_ty);
+        self.new_stmts(
+            tcx,
+            targets,
+            typing_env,
+            &mut patch,
+            parent_end,
+            bbs,
+            discr_local,
+            discr_ty,
+        );
         patch.add_statement(parent_end, StatementKind::StorageDead(discr_local));
         patch.patch_terminator(switch_bb_idx, bbs[first].terminator().kind.clone());
         patch.apply(body);
@@ -104,7 +112,7 @@ trait SimplifyMatch<'tcx> {
         &mut self,
         tcx: TyCtxt<'tcx>,
         targets: &SwitchTargets,
-        param_env: ParamEnv<'tcx>,
+        typing_env: ty::TypingEnv<'tcx>,
         bbs: &IndexSlice<BasicBlock, BasicBlockData<'tcx>>,
         discr_ty: Ty<'tcx>,
     ) -> Option<()>;
@@ -113,7 +121,7 @@ trait SimplifyMatch<'tcx> {
         &self,
         tcx: TyCtxt<'tcx>,
         targets: &SwitchTargets,
-        param_env: ParamEnv<'tcx>,
+        typing_env: ty::TypingEnv<'tcx>,
         patch: &mut MirPatch<'tcx>,
         parent_end: Location,
         bbs: &IndexSlice<BasicBlock, BasicBlockData<'tcx>>,
@@ -160,7 +168,7 @@ impl<'tcx> SimplifyMatch<'tcx> for SimplifyToIf {
         &mut self,
         tcx: TyCtxt<'tcx>,
         targets: &SwitchTargets,
-        param_env: ParamEnv<'tcx>,
+        typing_env: ty::TypingEnv<'tcx>,
         bbs: &IndexSlice<BasicBlock, BasicBlockData<'tcx>>,
         _discr_ty: Ty<'tcx>,
     ) -> Option<()> {
@@ -197,8 +205,8 @@ impl<'tcx> SimplifyMatch<'tcx> for SimplifyToIf {
                 ) if lhs_f == lhs_s
                     && f_c.const_.ty().is_bool()
                     && s_c.const_.ty().is_bool()
-                    && f_c.const_.try_eval_bool(tcx, param_env).is_some()
-                    && s_c.const_.try_eval_bool(tcx, param_env).is_some() => {}
+                    && f_c.const_.try_eval_bool(tcx, typing_env).is_some()
+                    && s_c.const_.try_eval_bool(tcx, typing_env).is_some() => {}
 
                 // Otherwise we cannot optimize. Try another block.
                 _ => return None,
@@ -211,7 +219,7 @@ impl<'tcx> SimplifyMatch<'tcx> for SimplifyToIf {
         &self,
         tcx: TyCtxt<'tcx>,
         targets: &SwitchTargets,
-        param_env: ParamEnv<'tcx>,
+        typing_env: ty::TypingEnv<'tcx>,
         patch: &mut MirPatch<'tcx>,
         parent_end: Location,
         bbs: &IndexSlice<BasicBlock, BasicBlockData<'tcx>>,
@@ -235,15 +243,15 @@ impl<'tcx> SimplifyMatch<'tcx> for SimplifyToIf {
                     StatementKind::Assign(box (_, Rvalue::Use(Operand::Constant(s_c)))),
                 ) => {
                     // From earlier loop we know that we are dealing with bool constants only:
-                    let f_b = f_c.const_.try_eval_bool(tcx, param_env).unwrap();
-                    let s_b = s_c.const_.try_eval_bool(tcx, param_env).unwrap();
+                    let f_b = f_c.const_.try_eval_bool(tcx, typing_env).unwrap();
+                    let s_b = s_c.const_.try_eval_bool(tcx, typing_env).unwrap();
                     if f_b == s_b {
                         // Same value in both blocks. Use statement as is.
                         patch.add_statement(parent_end, f.kind.clone());
                     } else {
                         // Different value between blocks. Make value conditional on switch
                         // condition.
-                        let size = tcx.layout_of(param_env.and(discr_ty)).unwrap().size;
+                        let size = tcx.layout_of(typing_env.as_query_input(discr_ty)).unwrap().size;
                         let const_cmp = Operand::const_from_scalar(
                             tcx,
                             discr_ty,
@@ -363,7 +371,7 @@ impl<'tcx> SimplifyMatch<'tcx> for SimplifyToExp {
         &mut self,
         tcx: TyCtxt<'tcx>,
         targets: &SwitchTargets,
-        param_env: ParamEnv<'tcx>,
+        typing_env: ty::TypingEnv<'tcx>,
         bbs: &IndexSlice<BasicBlock, BasicBlockData<'tcx>>,
         discr_ty: Ty<'tcx>,
     ) -> Option<()> {
@@ -388,7 +396,7 @@ impl<'tcx> SimplifyMatch<'tcx> for SimplifyToExp {
             return None;
         }
 
-        let discr_layout = tcx.layout_of(param_env.and(discr_ty)).unwrap();
+        let discr_layout = tcx.layout_of(typing_env.as_query_input(discr_ty)).unwrap();
         let first_stmts = &bbs[first_target].statements;
         let (second_case_val, second_target) = target_iter.next().unwrap();
         let second_stmts = &bbs[second_target].statements;
@@ -414,8 +422,8 @@ impl<'tcx> SimplifyMatch<'tcx> for SimplifyToExp {
                     && f_c.const_.ty().is_integral() =>
                 {
                     match (
-                        f_c.const_.try_eval_scalar_int(tcx, param_env),
-                        s_c.const_.try_eval_scalar_int(tcx, param_env),
+                        f_c.const_.try_eval_scalar_int(tcx, typing_env),
+                        s_c.const_.try_eval_scalar_int(tcx, typing_env),
                     ) {
                         (Some(f), Some(s)) if f == s => ExpectedTransformKind::SameByEq {
                             place: lhs_f,
@@ -467,11 +475,11 @@ impl<'tcx> SimplifyMatch<'tcx> for SimplifyToExp {
                         StatementKind::Assign(box (lhs_s, Rvalue::Use(Operand::Constant(s_c)))),
                     ) if lhs_f == lhs_s
                         && s_c.const_.ty() == f_ty
-                        && s_c.const_.try_eval_scalar_int(tcx, param_env) == Some(scalar) => {}
+                        && s_c.const_.try_eval_scalar_int(tcx, typing_env) == Some(scalar) => {}
                     (
                         ExpectedTransformKind::Cast { place: lhs_f, ty: f_ty },
                         StatementKind::Assign(box (lhs_s, Rvalue::Use(Operand::Constant(s_c)))),
-                    ) if let Some(f) = s_c.const_.try_eval_scalar_int(tcx, param_env)
+                    ) if let Some(f) = s_c.const_.try_eval_scalar_int(tcx, typing_env)
                         && lhs_f == lhs_s
                         && s_c.const_.ty() == f_ty
                         && can_cast(tcx, other_val, discr_layout, f_ty, f) => {}
@@ -487,7 +495,7 @@ impl<'tcx> SimplifyMatch<'tcx> for SimplifyToExp {
         &self,
         _tcx: TyCtxt<'tcx>,
         targets: &SwitchTargets,
-        _param_env: ParamEnv<'tcx>,
+        _typing_env: ty::TypingEnv<'tcx>,
         patch: &mut MirPatch<'tcx>,
         parent_end: Location,
         bbs: &IndexSlice<BasicBlock, BasicBlockData<'tcx>>,
diff --git a/compiler/rustc_mir_transform/src/promote_consts.rs b/compiler/rustc_mir_transform/src/promote_consts.rs
index fa9a6bfcf7c..6be95b1f0f1 100644
--- a/compiler/rustc_mir_transform/src/promote_consts.rs
+++ b/compiler/rustc_mir_transform/src/promote_consts.rs
@@ -325,7 +325,7 @@ impl<'tcx> Validator<'_, 'tcx> {
                 if let TempState::Defined { location: loc, .. } = self.temps[local]
                     && let Left(statement) =  self.body.stmt_at(loc)
                     && let Some((_, Rvalue::Use(Operand::Constant(c)))) = statement.kind.as_assign()
-                    && let Some(idx) = c.const_.try_eval_target_usize(self.tcx, self.param_env)
+                    && let Some(idx) = c.const_.try_eval_target_usize(self.tcx, self.typing_env)
                     // Determine the type of the thing we are indexing.
                     && let ty::Array(_, len) = place_base.ty(self.body, self.tcx).ty.kind()
                     // It's an array; determine its length.
@@ -490,7 +490,7 @@ impl<'tcx> Validator<'_, 'tcx> {
                             // Integer division: the RHS must be a non-zero const.
                             let rhs_val = match rhs {
                                 Operand::Constant(c) => {
-                                    c.const_.try_eval_scalar_int(self.tcx, self.param_env)
+                                    c.const_.try_eval_scalar_int(self.tcx, self.typing_env)
                                 }
                                 _ => None,
                             };
@@ -509,7 +509,7 @@ impl<'tcx> Validator<'_, 'tcx> {
                                         let lhs_val = match lhs {
                                             Operand::Constant(c) => c
                                                 .const_
-                                                .try_eval_scalar_int(self.tcx, self.param_env),
+                                                .try_eval_scalar_int(self.tcx, self.typing_env),
                                             _ => None,
                                         };
                                         let lhs_min = sz.signed_int_min();
diff --git a/compiler/rustc_mir_transform/src/remove_uninit_drops.rs b/compiler/rustc_mir_transform/src/remove_uninit_drops.rs
index 20c34a7469e..f786c676e9e 100644
--- a/compiler/rustc_mir_transform/src/remove_uninit_drops.rs
+++ b/compiler/rustc_mir_transform/src/remove_uninit_drops.rs
@@ -1,7 +1,7 @@
 use rustc_abi::FieldIdx;
 use rustc_index::bit_set::ChunkedBitSet;
 use rustc_middle::mir::{Body, TerminatorKind};
-use rustc_middle::ty::{self, GenericArgsRef, ParamEnv, Ty, TyCtxt, VariantDef};
+use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt, VariantDef};
 use rustc_mir_dataflow::impls::MaybeInitializedPlaces;
 use rustc_mir_dataflow::move_paths::{LookupResult, MoveData, MovePathIndex};
 use rustc_mir_dataflow::{Analysis, MaybeReachable, move_path_children_matching};
@@ -18,8 +18,8 @@ pub(super) struct RemoveUninitDrops;
 
 impl<'tcx> crate::MirPass<'tcx> for RemoveUninitDrops {
     fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
-        let param_env = tcx.param_env(body.source.def_id());
-        let move_data = MoveData::gather_moves(body, tcx, |ty| ty.needs_drop(tcx, param_env));
+        let typing_env = body.typing_env(tcx);
+        let move_data = MoveData::gather_moves(body, tcx, |ty| ty.needs_drop(tcx, typing_env));
 
         let mut maybe_inits = MaybeInitializedPlaces::new(tcx, body, &move_data)
             .iterate_to_fixpoint(tcx, body, Some("remove_uninit_drops"))
@@ -40,7 +40,7 @@ impl<'tcx> crate::MirPass<'tcx> for RemoveUninitDrops {
 
             let should_keep = is_needs_drop_and_init(
                 tcx,
-                param_env,
+                typing_env,
                 maybe_inits,
                 &move_data,
                 place.ty(body, tcx).ty,
@@ -66,24 +66,24 @@ impl<'tcx> crate::MirPass<'tcx> for RemoveUninitDrops {
 
 fn is_needs_drop_and_init<'tcx>(
     tcx: TyCtxt<'tcx>,
-    param_env: ParamEnv<'tcx>,
+    typing_env: ty::TypingEnv<'tcx>,
     maybe_inits: &ChunkedBitSet<MovePathIndex>,
     move_data: &MoveData<'tcx>,
     ty: Ty<'tcx>,
     mpi: MovePathIndex,
 ) -> bool {
     // No need to look deeper if the root is definitely uninit or if it has no `Drop` impl.
-    if !maybe_inits.contains(mpi) || !ty.needs_drop(tcx, param_env) {
+    if !maybe_inits.contains(mpi) || !ty.needs_drop(tcx, typing_env) {
         return false;
     }
 
     let field_needs_drop_and_init = |(f, f_ty, mpi)| {
         let child = move_path_children_matching(move_data, mpi, |x| x.is_field_to(f));
         let Some(mpi) = child else {
-            return Ty::needs_drop(f_ty, tcx, param_env);
+            return Ty::needs_drop(f_ty, tcx, typing_env);
         };
 
-        is_needs_drop_and_init(tcx, param_env, maybe_inits, move_data, f_ty, mpi)
+        is_needs_drop_and_init(tcx, typing_env, maybe_inits, move_data, f_ty, mpi)
     };
 
     // This pass is only needed for const-checking, so it doesn't handle as many cases as
@@ -110,7 +110,7 @@ fn is_needs_drop_and_init<'tcx>(
                     let downcast =
                         move_path_children_matching(move_data, mpi, |x| x.is_downcast_to(vid));
                     let Some(dc_mpi) = downcast else {
-                        return variant_needs_drop(tcx, param_env, args, variant);
+                        return variant_needs_drop(tcx, typing_env, args, variant);
                     };
 
                     dc_mpi
@@ -139,12 +139,12 @@ fn is_needs_drop_and_init<'tcx>(
 
 fn variant_needs_drop<'tcx>(
     tcx: TyCtxt<'tcx>,
-    param_env: ParamEnv<'tcx>,
+    typing_env: ty::TypingEnv<'tcx>,
     args: GenericArgsRef<'tcx>,
     variant: &VariantDef,
 ) -> bool {
     variant.fields.iter().any(|field| {
         let f_ty = field.ty(tcx, args);
-        f_ty.needs_drop(tcx, param_env)
+        f_ty.needs_drop(tcx, typing_env)
     })
 }
diff --git a/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs b/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs
index 28925ba1beb..ad62b47a66d 100644
--- a/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs
+++ b/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs
@@ -16,18 +16,18 @@ impl<'tcx> crate::MirPass<'tcx> for RemoveUnneededDrops {
     fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
         trace!("Running RemoveUnneededDrops on {:?}", body.source);
 
-        let did = body.source.def_id();
-        let param_env = tcx.param_env_reveal_all_normalized(did);
+        let typing_env = body.typing_env(tcx);
         let mut should_simplify = false;
-
         for block in body.basic_blocks.as_mut() {
             let terminator = block.terminator_mut();
             if let TerminatorKind::Drop { place, target, .. } = terminator.kind {
                 let ty = place.ty(&body.local_decls, tcx);
-                if ty.ty.needs_drop(tcx, param_env) {
+                if ty.ty.needs_drop(tcx, typing_env) {
                     continue;
                 }
-                if !tcx.consider_optimizing(|| format!("RemoveUnneededDrops {did:?} ")) {
+                if !tcx.consider_optimizing(|| {
+                    format!("RemoveUnneededDrops {:?}", body.source.def_id())
+                }) {
                     continue;
                 }
                 debug!("SUCCESS: replacing `drop` with goto({:?})", target);
diff --git a/compiler/rustc_mir_transform/src/remove_zsts.rs b/compiler/rustc_mir_transform/src/remove_zsts.rs
index f13bb1c5993..2f723bccc19 100644
--- a/compiler/rustc_mir_transform/src/remove_zsts.rs
+++ b/compiler/rustc_mir_transform/src/remove_zsts.rs
@@ -21,9 +21,9 @@ impl<'tcx> crate::MirPass<'tcx> for RemoveZsts {
             return;
         }
 
-        let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id());
+        let typing_env = body.typing_env(tcx);
         let local_decls = &body.local_decls;
-        let mut replacer = Replacer { tcx, param_env, local_decls };
+        let mut replacer = Replacer { tcx, typing_env, local_decls };
         for var_debug_info in &mut body.var_debug_info {
             replacer.visit_var_debug_info(var_debug_info);
         }
@@ -35,7 +35,7 @@ impl<'tcx> crate::MirPass<'tcx> for RemoveZsts {
 
 struct Replacer<'a, 'tcx> {
     tcx: TyCtxt<'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
+    typing_env: ty::TypingEnv<'tcx>,
     local_decls: &'a LocalDecls<'tcx>,
 }
 
@@ -61,7 +61,7 @@ impl<'tcx> Replacer<'_, 'tcx> {
         if !maybe_zst(ty) {
             return false;
         }
-        let Ok(layout) = self.tcx.layout_of(self.param_env.and(ty)) else {
+        let Ok(layout) = self.tcx.layout_of(self.typing_env.as_query_input(ty)) else {
             return false;
         };
         layout.is_zst()
diff --git a/compiler/rustc_mir_transform/src/reveal_all.rs b/compiler/rustc_mir_transform/src/reveal_all.rs
index f3b2f78b31c..587032ee720 100644
--- a/compiler/rustc_mir_transform/src/reveal_all.rs
+++ b/compiler/rustc_mir_transform/src/reveal_all.rs
@@ -8,14 +8,16 @@ pub(super) struct RevealAll;
 
 impl<'tcx> crate::MirPass<'tcx> for RevealAll {
     fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
-        let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id());
-        RevealAllVisitor { tcx, param_env }.visit_body_preserves_cfg(body);
+        // FIXME(#132279): This is used during the phase transition from analysis
+        // to runtime, so we have to manually specify the correct typing mode.
+        let typing_env = ty::TypingEnv::post_analysis(tcx, body.source.def_id());
+        RevealAllVisitor { tcx, typing_env }.visit_body_preserves_cfg(body);
     }
 }
 
 struct RevealAllVisitor<'tcx> {
     tcx: TyCtxt<'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
+    typing_env: ty::TypingEnv<'tcx>,
 }
 
 impl<'tcx> MutVisitor<'tcx> for RevealAllVisitor<'tcx> {
@@ -53,7 +55,7 @@ impl<'tcx> MutVisitor<'tcx> for RevealAllVisitor<'tcx> {
         // We have to use `try_normalize_erasing_regions` here, since it's
         // possible that we visit impossible-to-satisfy where clauses here,
         // see #91745
-        if let Ok(c) = self.tcx.try_normalize_erasing_regions(self.param_env, constant.const_) {
+        if let Ok(c) = self.tcx.try_normalize_erasing_regions(self.typing_env, constant.const_) {
             constant.const_ = c;
         }
         self.super_const_operand(constant, location);
@@ -64,7 +66,7 @@ impl<'tcx> MutVisitor<'tcx> for RevealAllVisitor<'tcx> {
         // We have to use `try_normalize_erasing_regions` here, since it's
         // possible that we visit impossible-to-satisfy where clauses here,
         // see #91745
-        if let Ok(t) = self.tcx.try_normalize_erasing_regions(self.param_env, *ty) {
+        if let Ok(t) = self.tcx.try_normalize_erasing_regions(self.typing_env, *ty) {
             *ty = t;
         }
     }
diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs
index ffa11f5b213..f16cde7cd4e 100644
--- a/compiler/rustc_mir_transform/src/shim.rs
+++ b/compiler/rustc_mir_transform/src/shim.rs
@@ -274,9 +274,9 @@ fn build_drop_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, ty: Option<Ty<'tcx>>)
 
     if ty.is_some() {
         let patch = {
-            let param_env = tcx.param_env_reveal_all_normalized(def_id);
+            let typing_env = ty::TypingEnv::post_analysis(tcx, def_id);
             let mut elaborator =
-                DropShimElaborator { body: &body, patch: MirPatch::new(&body), tcx, param_env };
+                DropShimElaborator { body: &body, patch: MirPatch::new(&body), tcx, typing_env };
             let dropee = tcx.mk_place_deref(dropee_ptr);
             let resume_block = elaborator.patch.resume_block();
             elaborate_drops::elaborate_drop(
@@ -334,7 +334,7 @@ pub(super) struct DropShimElaborator<'a, 'tcx> {
     pub body: &'a Body<'tcx>,
     pub patch: MirPatch<'tcx>,
     pub tcx: TyCtxt<'tcx>,
-    pub param_env: ty::ParamEnv<'tcx>,
+    pub typing_env: ty::TypingEnv<'tcx>,
 }
 
 impl fmt::Debug for DropShimElaborator<'_, '_> {
@@ -355,8 +355,8 @@ impl<'a, 'tcx> DropElaborator<'a, 'tcx> for DropShimElaborator<'a, 'tcx> {
     fn tcx(&self) -> TyCtxt<'tcx> {
         self.tcx
     }
-    fn param_env(&self) -> ty::ParamEnv<'tcx> {
-        self.param_env
+    fn typing_env(&self) -> ty::TypingEnv<'tcx> {
+        self.typing_env
     }
 
     fn drop_style(&self, _path: Self::Path, mode: DropFlagMode) -> DropStyle {
@@ -914,7 +914,7 @@ fn build_call_shim<'tcx>(
 pub(super) fn build_adt_ctor(tcx: TyCtxt<'_>, ctor_id: DefId) -> Body<'_> {
     debug_assert!(tcx.is_constructor(ctor_id));
 
-    let param_env = tcx.param_env_reveal_all_normalized(ctor_id);
+    let typing_env = ty::TypingEnv::post_analysis(tcx, ctor_id);
 
     // Normalize the sig.
     let sig = tcx
@@ -922,7 +922,7 @@ pub(super) fn build_adt_ctor(tcx: TyCtxt<'_>, ctor_id: DefId) -> Body<'_> {
         .instantiate_identity()
         .no_bound_vars()
         .expect("LBR in ADT constructor signature");
-    let sig = tcx.normalize_erasing_regions(param_env, sig);
+    let sig = tcx.normalize_erasing_regions(typing_env, sig);
 
     let ty::Adt(adt_def, args) = sig.output().kind() else {
         bug!("unexpected type for ADT ctor {:?}", sig.output());
diff --git a/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs b/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs
index f1672272862..139b25be0ab 100644
--- a/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs
+++ b/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs
@@ -48,7 +48,7 @@ struct AsyncDestructorCtorShimBuilder<'tcx> {
     self_ty: Option<Ty<'tcx>>,
     span: Span,
     source_info: SourceInfo,
-    param_env: ty::ParamEnv<'tcx>,
+    typing_env: ty::TypingEnv<'tcx>,
 
     stack: Vec<Operand<'tcx>>,
     last_bb: BasicBlock,
@@ -86,14 +86,14 @@ impl<'tcx> AsyncDestructorCtorShimBuilder<'tcx> {
 
         // Usual case: noop() + unwind resume + return
         let mut bbs = IndexVec::with_capacity(3);
-        let param_env = tcx.param_env_reveal_all_normalized(def_id);
+        let typing_env = ty::TypingEnv::post_analysis(tcx, def_id);
         AsyncDestructorCtorShimBuilder {
             tcx,
             def_id,
             self_ty,
             span,
             source_info,
-            param_env,
+            typing_env,
 
             stack: Vec::with_capacity(Self::MAX_STACK_LEN),
             last_bb: bbs.push(BasicBlockData::new(None)),
@@ -422,7 +422,7 @@ impl<'tcx> AsyncDestructorCtorShimBuilder<'tcx> {
                         statements: Vec::new(),
                         terminator: Some(Terminator {
                             source_info,
-                            kind: if self.locals[local].ty.needs_drop(self.tcx, self.param_env) {
+                            kind: if self.locals[local].ty.needs_drop(self.tcx, self.typing_env) {
                                 TerminatorKind::Drop {
                                     place: local.into(),
                                     target: *top_cleanup_bb,
diff --git a/compiler/rustc_mir_transform/src/simplify_branches.rs b/compiler/rustc_mir_transform/src/simplify_branches.rs
index e83b4727c48..bea3d0d8557 100644
--- a/compiler/rustc_mir_transform/src/simplify_branches.rs
+++ b/compiler/rustc_mir_transform/src/simplify_branches.rs
@@ -18,14 +18,14 @@ impl<'tcx> crate::MirPass<'tcx> for SimplifyConstCondition {
 
     fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
         trace!("Running SimplifyConstCondition on {:?}", body.source);
-        let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id());
+        let typing_env = body.typing_env(tcx);
         'blocks: for block in body.basic_blocks_mut() {
             for stmt in block.statements.iter_mut() {
                 // Simplify `assume` of a known value: either a NOP or unreachable.
                 if let StatementKind::Intrinsic(box ref intrinsic) = stmt.kind
                     && let NonDivergingIntrinsic::Assume(discr) = intrinsic
                     && let Operand::Constant(ref c) = discr
-                    && let Some(constant) = c.const_.try_eval_bool(tcx, param_env)
+                    && let Some(constant) = c.const_.try_eval_bool(tcx, typing_env)
                 {
                     if constant {
                         stmt.make_nop();
@@ -42,7 +42,7 @@ impl<'tcx> crate::MirPass<'tcx> for SimplifyConstCondition {
                 TerminatorKind::SwitchInt {
                     discr: Operand::Constant(ref c), ref targets, ..
                 } => {
-                    let constant = c.const_.try_eval_bits(tcx, param_env);
+                    let constant = c.const_.try_eval_bits(tcx, typing_env);
                     if let Some(constant) = constant {
                         let target = targets.target_for_value(constant);
                         TerminatorKind::Goto { target }
@@ -52,7 +52,7 @@ impl<'tcx> crate::MirPass<'tcx> for SimplifyConstCondition {
                 }
                 TerminatorKind::Assert {
                     target, cond: Operand::Constant(ref c), expected, ..
-                } => match c.const_.try_eval_bool(tcx, param_env) {
+                } => match c.const_.try_eval_bool(tcx, typing_env) {
                     Some(v) if v == expected => TerminatorKind::Goto { target },
                     _ => continue,
                 },
diff --git a/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs b/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs
index 26496b7f3fe..b6d80173086 100644
--- a/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs
+++ b/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs
@@ -37,7 +37,7 @@ impl<'tcx> crate::MirPass<'tcx> for SimplifyComparisonIntegral {
         let opts = helper.find_optimizations();
         let mut storage_deads_to_insert = vec![];
         let mut storage_deads_to_remove: Vec<(usize, BasicBlock)> = vec![];
-        let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id());
+        let typing_env = body.typing_env(tcx);
         for opt in opts {
             trace!("SUCCESS: Applying {:?}", opt);
             // replace terminator with a switchInt that switches on the integer directly
@@ -46,7 +46,7 @@ impl<'tcx> crate::MirPass<'tcx> for SimplifyComparisonIntegral {
             let new_value = match opt.branch_value_scalar {
                 Scalar::Int(int) => {
                     let layout = tcx
-                        .layout_of(param_env.and(opt.branch_value_ty))
+                        .layout_of(typing_env.as_query_input(opt.branch_value_ty))
                         .expect("if we have an evaluated constant we must know the layout");
                     int.to_bits(layout.size)
                 }
diff --git a/compiler/rustc_mir_transform/src/sroa.rs b/compiler/rustc_mir_transform/src/sroa.rs
index 53bbb122096..52b9ec1e0a3 100644
--- a/compiler/rustc_mir_transform/src/sroa.rs
+++ b/compiler/rustc_mir_transform/src/sroa.rs
@@ -28,12 +28,12 @@ impl<'tcx> crate::MirPass<'tcx> for ScalarReplacementOfAggregates {
         }
 
         let mut excluded = excluded_locals(body);
-        let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id());
+        let typing_env = body.typing_env(tcx);
         loop {
             debug!(?excluded);
-            let escaping = escaping_locals(tcx, param_env, &excluded, body);
+            let escaping = escaping_locals(tcx, typing_env, &excluded, body);
             debug!(?escaping);
-            let replacements = compute_flattening(tcx, param_env, body, escaping);
+            let replacements = compute_flattening(tcx, typing_env, body, escaping);
             debug!(?replacements);
             let all_dead_locals = replace_flattened_locals(tcx, body, replacements);
             if !all_dead_locals.is_empty() {
@@ -59,7 +59,7 @@ impl<'tcx> crate::MirPass<'tcx> for ScalarReplacementOfAggregates {
 ///   client code.
 fn escaping_locals<'tcx>(
     tcx: TyCtxt<'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
+    typing_env: ty::TypingEnv<'tcx>,
     excluded: &BitSet<Local>,
     body: &Body<'tcx>,
 ) -> BitSet<Local> {
@@ -84,7 +84,7 @@ fn escaping_locals<'tcx>(
                 // niche, so we do not want to automatically exclude it.
                 return false;
             }
-            let Ok(layout) = tcx.layout_of(param_env.and(ty)) else {
+            let Ok(layout) = tcx.layout_of(typing_env.as_query_input(ty)) else {
                 // We can't get the layout
                 return true;
             };
@@ -196,7 +196,7 @@ impl<'tcx> ReplacementMap<'tcx> {
 /// The replacement will be done later in `ReplacementVisitor`.
 fn compute_flattening<'tcx>(
     tcx: TyCtxt<'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
+    typing_env: ty::TypingEnv<'tcx>,
     body: &mut Body<'tcx>,
     escaping: BitSet<Local>,
 ) -> ReplacementMap<'tcx> {
@@ -208,7 +208,7 @@ fn compute_flattening<'tcx>(
         }
         let decl = body.local_decls[local].clone();
         let ty = decl.ty;
-        iter_fields(ty, tcx, param_env, |variant, field, field_ty| {
+        iter_fields(ty, tcx, typing_env, |variant, field, field_ty| {
             if variant.is_some() {
                 // Downcasts are currently not supported.
                 return;
diff --git a/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs b/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs
index 3011af4d9d7..57e255b7c32 100644
--- a/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs
+++ b/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs
@@ -92,9 +92,7 @@ impl<'tcx> crate::MirPass<'tcx> for UnreachableEnumBranching {
 
             let Some(discriminant_ty) = get_switched_on_type(bb_data, tcx, body) else { continue };
 
-            let layout = tcx.layout_of(
-                tcx.param_env_reveal_all_normalized(body.source.def_id()).and(discriminant_ty),
-            );
+            let layout = tcx.layout_of(body.typing_env(tcx).as_query_input(discriminant_ty));
 
             let mut allowed_variants = if let Ok(layout) = layout {
                 // Find allowed variants based on uninhabited.
diff --git a/compiler/rustc_mir_transform/src/validate.rs b/compiler/rustc_mir_transform/src/validate.rs
index ae4e6ea6a74..ae0e6f594ee 100644
--- a/compiler/rustc_mir_transform/src/validate.rs
+++ b/compiler/rustc_mir_transform/src/validate.rs
@@ -12,8 +12,7 @@ use rustc_middle::mir::visit::{NonUseContext, PlaceContext, Visitor};
 use rustc_middle::mir::*;
 use rustc_middle::ty::adjustment::PointerCoercion;
 use rustc_middle::ty::{
-    self, CoroutineArgsExt, InstanceKind, ParamEnv, ScalarInt, Ty, TyCtxt, TypeVisitableExt,
-    Variance,
+    self, CoroutineArgsExt, InstanceKind, ScalarInt, Ty, TyCtxt, TypeVisitableExt, Variance,
 };
 use rustc_middle::{bug, span_bug};
 use rustc_trait_selection::traits::ObligationCtxt;
@@ -47,9 +46,10 @@ impl<'tcx> crate::MirPass<'tcx> for Validator {
         if matches!(body.source.instance, InstanceKind::Intrinsic(..) | InstanceKind::Virtual(..)) {
             return;
         }
+        debug_assert_eq!(self.mir_phase, body.phase);
         let def_id = body.source.def_id();
-        let mir_phase = self.mir_phase;
-        let param_env = mir_phase.param_env(tcx, def_id);
+        let mir_phase = body.phase;
+        let typing_env = body.typing_env(tcx);
         let can_unwind = if mir_phase <= MirPhase::Runtime(RuntimePhase::Initial) {
             // In this case `AbortUnwindingCalls` haven't yet been executed.
             true
@@ -86,7 +86,7 @@ impl<'tcx> crate::MirPass<'tcx> for Validator {
         cfg_checker.check_cleanup_control_flow();
 
         // Also run the TypeChecker.
-        for (location, msg) in validate_types(tcx, self.mir_phase, param_env, body, body) {
+        for (location, msg) in validate_types(tcx, self.mir_phase, typing_env, body, body) {
             cfg_checker.fail(location, msg);
         }
 
@@ -532,12 +532,12 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> {
 pub(super) fn validate_types<'tcx>(
     tcx: TyCtxt<'tcx>,
     mir_phase: MirPhase,
-    param_env: ty::ParamEnv<'tcx>,
+    typing_env: ty::TypingEnv<'tcx>,
     body: &Body<'tcx>,
     caller_body: &Body<'tcx>,
 ) -> Vec<(Location, String)> {
     let mut type_checker =
-        TypeChecker { body, caller_body, tcx, param_env, mir_phase, failures: Vec::new() };
+        TypeChecker { body, caller_body, tcx, typing_env, mir_phase, failures: Vec::new() };
     type_checker.visit_body(body);
     type_checker.failures
 }
@@ -546,7 +546,7 @@ struct TypeChecker<'a, 'tcx> {
     body: &'a Body<'tcx>,
     caller_body: &'a Body<'tcx>,
     tcx: TyCtxt<'tcx>,
-    param_env: ParamEnv<'tcx>,
+    typing_env: ty::TypingEnv<'tcx>,
     mir_phase: MirPhase,
     failures: Vec<(Location, String)>,
 }
@@ -582,14 +582,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
             Variance::Covariant
         };
 
-        crate::util::relate_types(
-            self.tcx,
-            self.body.typing_mode(self.tcx),
-            self.param_env,
-            variance,
-            src,
-            dest,
-        )
+        crate::util::relate_types(self.tcx, self.typing_env, variance, src, dest)
     }
 
     /// Check that the given predicate definitely holds in the param-env of this MIR body.
@@ -608,12 +601,12 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
             return true;
         }
 
-        let infcx = self.tcx.infer_ctxt().build(self.body.typing_mode(self.tcx));
+        let (infcx, param_env) = self.tcx.infer_ctxt().build_with_typing_env(self.typing_env);
         let ocx = ObligationCtxt::new(&infcx);
         ocx.register_obligation(Obligation::new(
             self.tcx,
             ObligationCause::dummy(),
-            self.param_env,
+            param_env,
             pred,
         ));
         ocx.select_all_or_error().is_empty()
@@ -630,7 +623,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
             if let Operand::Copy(place) = operand {
                 let ty = place.ty(&self.body.local_decls, self.tcx).ty;
 
-                if !ty.is_copy_modulo_regions(self.tcx, self.param_env) {
+                if !ty.is_copy_modulo_regions(self.tcx, self.typing_env.param_env) {
                     self.fail(location, format!("`Operand::Copy` with non-`Copy` type {ty}"));
                 }
             }
@@ -802,8 +795,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
             ProjectionElem::Subtype(ty) => {
                 if !util::sub_types(
                     self.tcx,
-                    self.body.typing_mode(self.tcx),
-                    self.param_env,
+                    self.typing_env,
                     ty,
                     place_ref.ty(&self.body.local_decls, self.tcx).ty,
                 ) {
@@ -916,7 +908,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
                     assert!(adt_def.is_union());
                     assert_eq!(idx, FIRST_VARIANT);
                     let dest_ty = self.tcx.normalize_erasing_regions(
-                        self.param_env,
+                        self.typing_env,
                         adt_def.non_enum_variant().fields[field].ty(self.tcx, args),
                     );
                     if let [field] = fields.raw.as_slice() {
@@ -938,7 +930,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
                     for (src, dest) in std::iter::zip(fields, &variant.fields) {
                         let dest_ty = self
                             .tcx
-                            .normalize_erasing_regions(self.param_env, dest.ty(self.tcx, args));
+                            .normalize_erasing_regions(self.typing_env, dest.ty(self.tcx, args));
                         if !self.mir_assign_valid_types(src.ty(self.body, self.tcx), dest_ty) {
                             self.fail(location, "adt field has the wrong type");
                         }
@@ -997,7 +989,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
                             }
 
                             // FIXME: check `Thin` instead of `Sized`
-                            if !in_pointee.is_sized(self.tcx, self.param_env) {
+                            if !in_pointee.is_sized(self.tcx, self.typing_env.param_env) {
                                 self.fail(location, "input pointer must be thin");
                             }
                         } else {
@@ -1012,7 +1004,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
                             if !self.mir_assign_valid_types(metadata_ty, self.tcx.types.usize) {
                                 self.fail(location, "slice metadata must be usize");
                             }
-                        } else if pointee_ty.is_sized(self.tcx, self.param_env) {
+                        } else if pointee_ty.is_sized(self.tcx, self.typing_env.param_env) {
                             if metadata_ty != self.tcx.types.unit {
                                 self.fail(location, "metadata for pointer-to-thin must be unit");
                             }
@@ -1301,8 +1293,8 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
 
                             if !self
                                 .tcx
-                                .normalize_erasing_regions(self.param_env, op_ty)
-                                .is_sized(self.tcx, self.param_env)
+                                .normalize_erasing_regions(self.typing_env, op_ty)
+                                .is_sized(self.tcx, self.typing_env.param_env)
                             {
                                 self.fail(
                                     location,
@@ -1311,8 +1303,8 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
                             }
                             if !self
                                 .tcx
-                                .normalize_erasing_regions(self.param_env, *target_type)
-                                .is_sized(self.tcx, self.param_env)
+                                .normalize_erasing_regions(self.typing_env, *target_type)
+                                .is_sized(self.tcx, self.typing_env.param_env)
                             {
                                 self.fail(
                                     location,
@@ -1353,7 +1345,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
                                 return;
                             };
 
-                            current_ty = self.tcx.normalize_erasing_regions(self.param_env, f_ty);
+                            current_ty = self.tcx.normalize_erasing_regions(self.typing_env, f_ty);
                         }
                         ty::Adt(adt_def, args) => {
                             let Some(field) = adt_def.variant(variant).fields.get(field) else {
@@ -1362,7 +1354,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
                             };
 
                             let f_ty = field.ty(self.tcx, args);
-                            current_ty = self.tcx.normalize_erasing_regions(self.param_env, f_ty);
+                            current_ty = self.tcx.normalize_erasing_regions(self.typing_env, f_ty);
                         }
                         _ => {
                             self.fail(
diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs
index 322deb539cd..1b94c627f81 100644
--- a/compiler/rustc_monomorphize/src/collector.rs
+++ b/compiler/rustc_monomorphize/src/collector.rs
@@ -427,7 +427,7 @@ fn collect_items_rec<'tcx>(
                 let DefKind::Static { nested, .. } = tcx.def_kind(def_id) else { bug!() };
                 // Nested statics have no type.
                 if !nested {
-                    let ty = instance.ty(tcx, ty::ParamEnv::reveal_all());
+                    let ty = instance.ty(tcx, ty::TypingEnv::fully_monomorphized());
                     visit_drop_use(tcx, ty, true, starting_item.span, &mut used_items);
                 }
 
@@ -636,7 +636,7 @@ impl<'a, 'tcx> MirUsedCollector<'a, 'tcx> {
         trace!("monomorphize: self.instance={:?}", self.instance);
         self.instance.instantiate_mir_and_normalize_erasing_regions(
             self.tcx,
-            ty::ParamEnv::reveal_all(),
+            ty::TypingEnv::fully_monomorphized(),
             ty::EarlyBinder::bind(value),
         )
     }
@@ -647,12 +647,11 @@ impl<'a, 'tcx> MirUsedCollector<'a, 'tcx> {
         constant: &mir::ConstOperand<'tcx>,
     ) -> Option<mir::ConstValue<'tcx>> {
         let const_ = self.monomorphize(constant.const_);
-        let param_env = ty::ParamEnv::reveal_all();
         // Evaluate the constant. This makes const eval failure a collection-time error (rather than
         // a codegen-time error). rustc stops after collection if there was an error, so this
         // ensures codegen never has to worry about failing consts.
         // (codegen relies on this and ICEs will happen if this is violated.)
-        match const_.eval(self.tcx, param_env, constant.span) {
+        match const_.eval(self.tcx, ty::TypingEnv::fully_monomorphized(), constant.span) {
             Ok(v) => Some(v),
             Err(ErrorHandled::TooGeneric(..)) => span_bug!(
                 constant.span,
@@ -863,9 +862,20 @@ fn visit_fn_use<'tcx>(
 ) {
     if let ty::FnDef(def_id, args) = *ty.kind() {
         let instance = if is_direct_call {
-            ty::Instance::expect_resolve(tcx, ty::ParamEnv::reveal_all(), def_id, args, source)
+            ty::Instance::expect_resolve(
+                tcx,
+                ty::TypingEnv::fully_monomorphized(),
+                def_id,
+                args,
+                source,
+            )
         } else {
-            match ty::Instance::resolve_for_fn_ptr(tcx, ty::ParamEnv::reveal_all(), def_id, args) {
+            match ty::Instance::resolve_for_fn_ptr(
+                tcx,
+                ty::TypingEnv::fully_monomorphized(),
+                def_id,
+                args,
+            ) {
                 Some(instance) => instance,
                 _ => bug!("failed to resolve instance for {ty}"),
             }
@@ -1024,12 +1034,12 @@ fn find_vtable_types_for_unsizing<'tcx>(
     target_ty: Ty<'tcx>,
 ) -> (Ty<'tcx>, Ty<'tcx>) {
     let ptr_vtable = |inner_source: Ty<'tcx>, inner_target: Ty<'tcx>| {
-        let param_env = ty::ParamEnv::reveal_all();
+        let typing_env = ty::TypingEnv::fully_monomorphized();
         let type_has_metadata = |ty: Ty<'tcx>| -> bool {
-            if ty.is_sized(tcx.tcx, param_env) {
+            if ty.is_sized(tcx.tcx, typing_env.param_env) {
                 return false;
             }
-            let tail = tcx.struct_tail_for_codegen(ty, param_env);
+            let tail = tcx.struct_tail_for_codegen(ty, typing_env);
             match tail.kind() {
                 ty::Foreign(..) => false,
                 ty::Str | ty::Slice(..) | ty::Dynamic(..) => true,
@@ -1039,7 +1049,7 @@ fn find_vtable_types_for_unsizing<'tcx>(
         if type_has_metadata(inner_source) {
             (inner_source, inner_target)
         } else {
-            tcx.struct_lockstep_tails_for_codegen(inner_source, inner_target, param_env)
+            tcx.struct_lockstep_tails_for_codegen(inner_source, inner_target, typing_env)
         }
     };
 
@@ -1270,8 +1280,13 @@ fn visit_mentioned_item<'tcx>(
     match *item {
         MentionedItem::Fn(ty) => {
             if let ty::FnDef(def_id, args) = *ty.kind() {
-                let instance =
-                    Instance::expect_resolve(tcx, ty::ParamEnv::reveal_all(), def_id, args, span);
+                let instance = Instance::expect_resolve(
+                    tcx,
+                    ty::TypingEnv::fully_monomorphized(),
+                    def_id,
+                    args,
+                    span,
+                );
                 // `visit_instance_use` was written for "used" item collection but works just as well
                 // for "mentioned" item collection.
                 // We can set `is_direct_call`; that just means we'll skip a bunch of shims that anyway
@@ -1487,13 +1502,13 @@ impl<'v> RootCollector<'_, 'v> {
         // regions must appear in the argument
         // listing.
         let main_ret_ty = self.tcx.normalize_erasing_regions(
-            ty::ParamEnv::reveal_all(),
+            ty::TypingEnv::fully_monomorphized(),
             main_ret_ty.no_bound_vars().unwrap(),
         );
 
         let start_instance = Instance::expect_resolve(
             self.tcx,
-            ty::ParamEnv::reveal_all(),
+            ty::TypingEnv::fully_monomorphized(),
             start_def_id,
             self.tcx.mk_args(&[main_ret_ty.into()]),
             DUMMY_SP,
@@ -1551,8 +1566,8 @@ fn create_mono_items_for_default_impls<'tcx>(
         return;
     }
 
-    let param_env = ty::ParamEnv::reveal_all();
-    let trait_ref = tcx.normalize_erasing_regions(param_env, trait_ref);
+    let typing_env = ty::TypingEnv::fully_monomorphized();
+    let trait_ref = tcx.normalize_erasing_regions(typing_env, trait_ref);
     let overridden_methods = tcx.impl_item_implementor_ids(item.owner_id);
     for method in tcx.provided_trait_methods(trait_ref.def_id) {
         if overridden_methods.contains_key(&method.def_id) {
@@ -1567,7 +1582,7 @@ fn create_mono_items_for_default_impls<'tcx>(
         // only has lifetime generic parameters. This is validated by calling
         // `own_requires_monomorphization` on both the impl and method.
         let args = trait_ref.args.extend_to(tcx, method.def_id, only_region_params);
-        let instance = ty::Instance::expect_resolve(tcx, param_env, method.def_id, args, DUMMY_SP);
+        let instance = ty::Instance::expect_resolve(tcx, typing_env, method.def_id, args, DUMMY_SP);
 
         let mono_item = create_fn_mono_item(tcx, instance, DUMMY_SP);
         if mono_item.node.is_instantiable(tcx) && tcx.should_codegen_locally(instance) {
diff --git a/compiler/rustc_monomorphize/src/lib.rs b/compiler/rustc_monomorphize/src/lib.rs
index eb576317678..0f08930fb4c 100644
--- a/compiler/rustc_monomorphize/src/lib.rs
+++ b/compiler/rustc_monomorphize/src/lib.rs
@@ -35,7 +35,9 @@ fn custom_coerce_unsize_info<'tcx>(
         [source_ty, target_ty],
     );
 
-    match tcx.codegen_select_candidate((ty::ParamEnv::reveal_all(), trait_ref)) {
+    match tcx
+        .codegen_select_candidate(ty::TypingEnv::fully_monomorphized().as_query_input(trait_ref))
+    {
         Ok(traits::ImplSource::UserDefined(traits::ImplSourceUserDefinedData {
             impl_def_id,
             ..
diff --git a/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs b/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs
index 02b361456e4..30e634d8252 100644
--- a/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs
+++ b/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs
@@ -3,7 +3,7 @@
 use rustc_hir::CRATE_HIR_ID;
 use rustc_middle::mir::{self, traversal};
 use rustc_middle::ty::inherent::*;
-use rustc_middle::ty::{self, Instance, InstanceKind, ParamEnv, Ty, TyCtxt};
+use rustc_middle::ty::{self, Instance, InstanceKind, Ty, TyCtxt};
 use rustc_session::lint::builtin::ABI_UNSUPPORTED_VECTOR_TYPES;
 use rustc_span::def_id::DefId;
 use rustc_span::{DUMMY_SP, Span, Symbol};
@@ -62,8 +62,9 @@ fn do_check_abi<'tcx>(
 /// Checks that the ABI of a given instance of a function does not contain vector-passed arguments
 /// or return values for which the corresponding target feature is not enabled.
 fn check_instance_abi<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) {
-    let param_env = ParamEnv::reveal_all();
-    let Ok(abi) = tcx.fn_abi_of_instance(param_env.and((instance, ty::List::empty()))) else {
+    let typing_env = ty::TypingEnv::fully_monomorphized();
+    let Ok(abi) = tcx.fn_abi_of_instance(typing_env.as_query_input((instance, ty::List::empty())))
+    else {
         // An error will be reported during codegen if we cannot determine the ABI of this
         // function.
         return;
@@ -100,18 +101,18 @@ fn check_call_site_abi<'tcx>(
         // "Rust" ABI never passes arguments in vector registers.
         return;
     }
-    let param_env = ParamEnv::reveal_all();
+    let typing_env = ty::TypingEnv::fully_monomorphized();
     let callee_abi = match *callee.kind() {
         ty::FnPtr(..) => {
-            tcx.fn_abi_of_fn_ptr(param_env.and((callee.fn_sig(tcx), ty::List::empty())))
+            tcx.fn_abi_of_fn_ptr(typing_env.as_query_input((callee.fn_sig(tcx), ty::List::empty())))
         }
         ty::FnDef(def_id, args) => {
             // Intrinsics are handled separately by the compiler.
             if tcx.intrinsic(def_id).is_some() {
                 return;
             }
-            let instance = ty::Instance::expect_resolve(tcx, param_env, def_id, args, DUMMY_SP);
-            tcx.fn_abi_of_instance(param_env.and((instance, ty::List::empty())))
+            let instance = ty::Instance::expect_resolve(tcx, typing_env, def_id, args, DUMMY_SP);
+            tcx.fn_abi_of_instance(typing_env.as_query_input((instance, ty::List::empty())))
         }
         _ => {
             panic!("Invalid function call");
@@ -151,7 +152,7 @@ fn check_callees_abi<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>, body: &m
                 let callee_ty = func.ty(body, tcx);
                 let callee_ty = instance.instantiate_mir_and_normalize_erasing_regions(
                     tcx,
-                    ty::ParamEnv::reveal_all(),
+                    ty::TypingEnv::fully_monomorphized(),
                     ty::EarlyBinder::bind(callee_ty),
                 );
                 check_call_site_abi(tcx, callee_ty, *fn_span, body.source.instance);
diff --git a/compiler/rustc_monomorphize/src/mono_checks/move_check.rs b/compiler/rustc_monomorphize/src/mono_checks/move_check.rs
index 7f04bdf46f1..438d49fd7fb 100644
--- a/compiler/rustc_monomorphize/src/mono_checks/move_check.rs
+++ b/compiler/rustc_monomorphize/src/mono_checks/move_check.rs
@@ -61,7 +61,7 @@ impl<'tcx> MoveCheckVisitor<'tcx> {
         trace!("monomorphize: self.instance={:?}", self.instance);
         self.instance.instantiate_mir_and_normalize_erasing_regions(
             self.tcx,
-            ty::ParamEnv::reveal_all(),
+            ty::TypingEnv::fully_monomorphized(),
             ty::EarlyBinder::bind(value),
         )
     }
@@ -128,7 +128,9 @@ impl<'tcx> MoveCheckVisitor<'tcx> {
     ) -> Option<Size> {
         let ty = operand.ty(self.body, self.tcx);
         let ty = self.monomorphize(ty);
-        let Ok(layout) = self.tcx.layout_of(ty::ParamEnv::reveal_all().and(ty)) else {
+        let Ok(layout) =
+            self.tcx.layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(ty))
+        else {
             return None;
         };
         if layout.size.bytes_usize() > limit.0 {
diff --git a/compiler/rustc_monomorphize/src/partitioning.rs b/compiler/rustc_monomorphize/src/partitioning.rs
index 84e08ea881d..7240cfce0f7 100644
--- a/compiler/rustc_monomorphize/src/partitioning.rs
+++ b/compiler/rustc_monomorphize/src/partitioning.rs
@@ -666,7 +666,7 @@ fn characteristic_def_id_of_mono_item<'tcx>(
                     // This is a method within an impl, find out what the self-type is:
                     let impl_self_ty = tcx.instantiate_and_normalize_erasing_regions(
                         instance.args,
-                        ty::ParamEnv::reveal_all(),
+                        ty::TypingEnv::fully_monomorphized(),
                         tcx.type_of(impl_def_id),
                     );
                     if let Some(def_id) = characteristic_def_id_of_type(impl_self_ty) {
diff --git a/compiler/rustc_monomorphize/src/util.rs b/compiler/rustc_monomorphize/src/util.rs
index 093a697beeb..deb4ab433bf 100644
--- a/compiler/rustc_monomorphize/src/util.rs
+++ b/compiler/rustc_monomorphize/src/util.rs
@@ -22,29 +22,29 @@ pub(crate) fn dump_closure_profile<'tcx>(tcx: TyCtxt<'tcx>, closure_instance: In
     let typeck_results = tcx.typeck(closure_def_id);
 
     if typeck_results.closure_size_eval.contains_key(&closure_def_id) {
-        let param_env = ty::ParamEnv::reveal_all();
+        let typing_env = ty::TypingEnv::fully_monomorphized();
 
         let ClosureSizeProfileData { before_feature_tys, after_feature_tys } =
             typeck_results.closure_size_eval[&closure_def_id];
 
         let before_feature_tys = tcx.instantiate_and_normalize_erasing_regions(
             closure_instance.args,
-            param_env,
+            typing_env,
             ty::EarlyBinder::bind(before_feature_tys),
         );
         let after_feature_tys = tcx.instantiate_and_normalize_erasing_regions(
             closure_instance.args,
-            param_env,
+            typing_env,
             ty::EarlyBinder::bind(after_feature_tys),
         );
 
         let new_size = tcx
-            .layout_of(param_env.and(after_feature_tys))
+            .layout_of(typing_env.as_query_input(after_feature_tys))
             .map(|l| format!("{:?}", l.size.bytes()))
             .unwrap_or_else(|e| format!("Failed {e:?}"));
 
         let old_size = tcx
-            .layout_of(param_env.and(before_feature_tys))
+            .layout_of(typing_env.as_query_input(before_feature_tys))
             .map(|l| format!("{:?}", l.size.bytes()))
             .unwrap_or_else(|e| format!("Failed {e:?}"));
 
diff --git a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs
index df4f0ffdd57..5f740590712 100644
--- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs
@@ -262,7 +262,11 @@ where
             return ecx.forced_ambiguity(MaybeCause::Ambiguity);
         }
 
-        if cx.layout_is_pointer_like(goal.param_env, goal.predicate.self_ty()) {
+        if cx.layout_is_pointer_like(
+            ecx.typing_mode(goal.param_env),
+            goal.param_env,
+            goal.predicate.self_ty(),
+        ) {
             ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
                 .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
         } else {
diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs
index 226de65445c..5023e83bd67 100644
--- a/compiler/rustc_parse/src/lexer/mod.rs
+++ b/compiler/rustc_parse/src/lexer/mod.rs
@@ -213,7 +213,7 @@ impl<'psess, 'src> StringReader<'psess, 'src> {
                     let ident = Symbol::intern(lifetime_name);
                     token::Lifetime(ident, IdentIsRaw::No)
                 }
-                rustc_lexer::TokenKind::InvalidIdent | rustc_lexer::TokenKind::InvalidPrefix
+                rustc_lexer::TokenKind::InvalidIdent
                     // Do not recover an identifier with emoji if the codepoint is a confusable
                     // with a recoverable substitution token, like `âž–`.
                     if !UNICODE_ARRAY.iter().any(|&(c, _, _)| {
@@ -359,8 +359,7 @@ impl<'psess, 'src> StringReader<'psess, 'src> {
                 rustc_lexer::TokenKind::Percent => token::BinOp(token::Percent),
 
                 rustc_lexer::TokenKind::Unknown
-                | rustc_lexer::TokenKind::InvalidIdent
-                | rustc_lexer::TokenKind::InvalidPrefix => {
+                | rustc_lexer::TokenKind::InvalidIdent => {
                     // Don't emit diagnostics for sequences of the same invalid token
                     if swallow_next_invalid > 0 {
                         swallow_next_invalid -= 1;
diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs
index 50a8b6542df..042ee96bbe8 100644
--- a/compiler/rustc_parse/src/parser/mod.rs
+++ b/compiler/rustc_parse/src/parser/mod.rs
@@ -641,9 +641,10 @@ impl<'a> Parser<'a> {
             return true;
         }
 
+        // Do an ASCII case-insensitive match, because all keywords are ASCII.
         if case == Case::Insensitive
             && let Some((ident, IdentIsRaw::No)) = self.token.ident()
-            && ident.as_str().to_lowercase() == kw.as_str().to_lowercase()
+            && ident.as_str().eq_ignore_ascii_case(kw.as_str())
         {
             true
         } else {
diff --git a/compiler/rustc_passes/src/abi_test.rs b/compiler/rustc_passes/src/abi_test.rs
index b1267562f7b..4db8584b884 100644
--- a/compiler/rustc_passes/src/abi_test.rs
+++ b/compiler/rustc_passes/src/abi_test.rs
@@ -59,9 +59,9 @@ fn unwrap_fn_abi<'tcx>(
 }
 
 fn dump_abi_of_fn_item(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribute) {
-    let param_env = tcx.param_env(item_def_id);
+    let typing_env = ty::TypingEnv::post_analysis(tcx, item_def_id);
     let args = GenericArgs::identity_for_item(tcx, item_def_id);
-    let instance = match Instance::try_resolve(tcx, param_env, item_def_id.into(), args) {
+    let instance = match Instance::try_resolve(tcx, typing_env, item_def_id.into(), args) {
         Ok(Some(instance)) => instance,
         Ok(None) => {
             // Not sure what to do here, but `LayoutError::Unknown` seems reasonable?
@@ -75,7 +75,9 @@ fn dump_abi_of_fn_item(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribut
         Err(_guaranteed) => return,
     };
     let abi = unwrap_fn_abi(
-        tcx.fn_abi_of_instance(param_env.and((instance, /* extra_args */ ty::List::empty()))),
+        tcx.fn_abi_of_instance(
+            typing_env.as_query_input((instance, /* extra_args */ ty::List::empty())),
+        ),
         tcx,
         item_def_id,
     );
@@ -117,10 +119,10 @@ fn test_abi_eq<'tcx>(abi1: &'tcx FnAbi<'tcx, Ty<'tcx>>, abi2: &'tcx FnAbi<'tcx,
 }
 
 fn dump_abi_of_fn_type(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribute) {
-    let param_env = tcx.param_env(item_def_id);
+    let typing_env = ty::TypingEnv::post_analysis(tcx, item_def_id);
     let ty = tcx.type_of(item_def_id).instantiate_identity();
     let span = tcx.def_span(item_def_id);
-    if !ensure_wf(tcx, param_env, ty, item_def_id, span) {
+    if !ensure_wf(tcx, typing_env, ty, item_def_id, span) {
         return;
     }
     let meta_items = attr.meta_item_list().unwrap_or_default();
@@ -134,10 +136,10 @@ fn dump_abi_of_fn_type(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribut
                     );
                 };
                 let abi = unwrap_fn_abi(
-                    tcx.fn_abi_of_fn_ptr(
-                        param_env
-                            .and((sig_tys.with(*hdr), /* extra_args */ ty::List::empty())),
-                    ),
+                    tcx.fn_abi_of_fn_ptr(typing_env.as_query_input((
+                        sig_tys.with(*hdr),
+                        /* extra_args */ ty::List::empty(),
+                    ))),
                     tcx,
                     item_def_id,
                 );
@@ -165,10 +167,10 @@ fn dump_abi_of_fn_type(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribut
                     );
                 };
                 let abi1 = unwrap_fn_abi(
-                    tcx.fn_abi_of_fn_ptr(
-                        param_env
-                            .and((sig_tys1.with(*hdr1), /* extra_args */ ty::List::empty())),
-                    ),
+                    tcx.fn_abi_of_fn_ptr(typing_env.as_query_input((
+                        sig_tys1.with(*hdr1),
+                        /* extra_args */ ty::List::empty(),
+                    ))),
                     tcx,
                     item_def_id,
                 );
@@ -179,10 +181,10 @@ fn dump_abi_of_fn_type(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribut
                     );
                 };
                 let abi2 = unwrap_fn_abi(
-                    tcx.fn_abi_of_fn_ptr(
-                        param_env
-                            .and((sig_tys2.with(*hdr2), /* extra_args */ ty::List::empty())),
-                    ),
+                    tcx.fn_abi_of_fn_ptr(typing_env.as_query_input((
+                        sig_tys2.with(*hdr2),
+                        /* extra_args */ ty::List::empty(),
+                    ))),
                     tcx,
                     item_def_id,
                 );
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index 836511325f4..87069e0b057 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -162,6 +162,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
                     self.check_rustc_std_internal_symbol(attr, span, target)
                 }
                 [sym::naked, ..] => self.check_naked(hir_id, attr, span, target, attrs),
+                [sym::rustc_as_ptr, ..] => {
+                    self.check_applied_to_fn_or_method(hir_id, attr, span, target)
+                }
                 [sym::rustc_never_returns_null_ptr, ..] => {
                     self.check_applied_to_fn_or_method(hir_id, attr, span, target)
                 }
diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs
index b1db66fa52d..ecf8d34ad84 100644
--- a/compiler/rustc_passes/src/dead.rs
+++ b/compiler/rustc_passes/src/dead.rs
@@ -273,7 +273,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
             data.get(expr.hir_id).expect("no offset_of_data for offset_of");
 
         let body_did = self.typeck_results().hir_owner.to_def_id();
-        let param_env = self.tcx.param_env(body_did);
+        let typing_env = ty::TypingEnv::non_body_analysis(self.tcx, body_did);
 
         let mut current_ty = container;
 
@@ -285,13 +285,13 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
                     self.insert_def_id(field.did);
                     let field_ty = field.ty(self.tcx, args);
 
-                    current_ty = self.tcx.normalize_erasing_regions(param_env, field_ty);
+                    current_ty = self.tcx.normalize_erasing_regions(typing_env, field_ty);
                 }
                 // we don't need to mark tuple fields as live,
                 // but we may need to mark subfields
                 ty::Tuple(tys) => {
                     current_ty =
-                        self.tcx.normalize_erasing_regions(param_env, tys[field.as_usize()]);
+                        self.tcx.normalize_erasing_regions(typing_env, tys[field.as_usize()]);
                 }
                 _ => span_bug!(expr.span, "named field access on non-ADT"),
             }
@@ -944,7 +944,10 @@ impl<'tcx> DeadVisitor<'tcx> {
         if is_positional
             && self
                 .tcx
-                .layout_of(self.tcx.param_env(field.did).and(field_type))
+                .layout_of(
+                    ty::TypingEnv::non_body_analysis(self.tcx, field.did)
+                        .as_query_input(field_type),
+                )
                 .map_or(true, |layout| layout.is_zst())
         {
             return ShouldWarnAboutField::No;
diff --git a/compiler/rustc_passes/src/hir_stats.rs b/compiler/rustc_passes/src/input_stats.rs
index 55fdbac8ad6..db34189be2a 100644
--- a/compiler/rustc_passes/src/hir_stats.rs
+++ b/compiler/rustc_passes/src/input_stats.rs
@@ -126,6 +126,7 @@ impl<'k> StatCollector<'k> {
         });
 
         let total_size = nodes.iter().map(|(_, node)| node.stats.count * node.stats.size).sum();
+        let total_count = nodes.iter().map(|(_, node)| node.stats.count).sum();
 
         eprintln!("{prefix} {title}");
         eprintln!(
@@ -167,7 +168,13 @@ impl<'k> StatCollector<'k> {
             }
         }
         eprintln!("{prefix} ----------------------------------------------------------------");
-        eprintln!("{} {:<18}{:>10}", prefix, "Total", to_readable_str(total_size));
+        eprintln!(
+            "{} {:<18}{:>10}        {:>14}",
+            prefix,
+            "Total",
+            to_readable_str(total_size),
+            to_readable_str(total_count),
+        );
         eprintln!("{prefix}");
     }
 }
diff --git a/compiler/rustc_passes/src/layout_test.rs b/compiler/rustc_passes/src/layout_test.rs
index 986dce5b56d..bb90b5a1e31 100644
--- a/compiler/rustc_passes/src/layout_test.rs
+++ b/compiler/rustc_passes/src/layout_test.rs
@@ -2,10 +2,9 @@ use rustc_abi::{HasDataLayout, TargetDataLayout};
 use rustc_ast::Attribute;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::LocalDefId;
-use rustc_middle::infer::canonical::ir::TypingMode;
 use rustc_middle::span_bug;
-use rustc_middle::ty::layout::{HasParamEnv, HasTyCtxt, LayoutError, LayoutOfHelpers};
-use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt};
+use rustc_middle::ty::layout::{HasTyCtxt, HasTypingEnv, LayoutError, LayoutOfHelpers};
+use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_span::Span;
 use rustc_span::source_map::Spanned;
 use rustc_span::symbol::sym;
@@ -39,11 +38,13 @@ pub fn test_layout(tcx: TyCtxt<'_>) {
 
 pub fn ensure_wf<'tcx>(
     tcx: TyCtxt<'tcx>,
-    param_env: ParamEnv<'tcx>,
+    typing_env: ty::TypingEnv<'tcx>,
     ty: Ty<'tcx>,
     def_id: LocalDefId,
     span: Span,
 ) -> bool {
+    let (infcx, param_env) = tcx.infer_ctxt().build_with_typing_env(typing_env);
+    let ocx = traits::ObligationCtxt::new_with_diagnostics(&infcx);
     let pred = ty::ClauseKind::WellFormed(ty.into());
     let obligation = traits::Obligation::new(
         tcx,
@@ -55,8 +56,6 @@ pub fn ensure_wf<'tcx>(
         param_env,
         pred,
     );
-    let infcx = tcx.infer_ctxt().build(TypingMode::from_param_env(param_env));
-    let ocx = traits::ObligationCtxt::new_with_diagnostics(&infcx);
     ocx.register_obligation(obligation);
     let errors = ocx.select_all_or_error();
     if !errors.is_empty() {
@@ -69,13 +68,13 @@ pub fn ensure_wf<'tcx>(
 }
 
 fn dump_layout_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribute) {
-    let param_env = tcx.param_env(item_def_id);
+    let typing_env = ty::TypingEnv::post_analysis(tcx, item_def_id);
     let ty = tcx.type_of(item_def_id).instantiate_identity();
     let span = tcx.def_span(item_def_id.to_def_id());
-    if !ensure_wf(tcx, param_env, ty, item_def_id, span) {
+    if !ensure_wf(tcx, typing_env, ty, item_def_id, span) {
         return;
     }
-    match tcx.layout_of(param_env.and(ty)) {
+    match tcx.layout_of(typing_env.as_query_input(ty)) {
         Ok(ty_layout) => {
             // Check out the `#[rustc_layout(..)]` attribute to tell what to dump.
             // The `..` are the names of fields to dump.
@@ -107,19 +106,15 @@ fn dump_layout_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribute) {
                             span,
                             homogeneous_aggregate: format!(
                                 "{:?}",
-                                ty_layout.homogeneous_aggregate(&UnwrapLayoutCx { tcx, param_env })
+                                ty_layout
+                                    .homogeneous_aggregate(&UnwrapLayoutCx { tcx, typing_env })
                             ),
                         });
                     }
 
                     sym::debug => {
-                        let normalized_ty = format!(
-                            "{}",
-                            tcx.normalize_erasing_regions(
-                                param_env.with_reveal_all_normalized(tcx),
-                                ty,
-                            )
-                        );
+                        let normalized_ty =
+                            format!("{}", tcx.normalize_erasing_regions(typing_env, ty));
                         // FIXME: using the `Debug` impl here isn't ideal.
                         let ty_layout = format!("{:#?}", *ty_layout);
                         tcx.dcx().emit_err(LayoutOf { span, normalized_ty, ty_layout });
@@ -140,7 +135,7 @@ fn dump_layout_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribute) {
 
 struct UnwrapLayoutCx<'tcx> {
     tcx: TyCtxt<'tcx>,
-    param_env: ParamEnv<'tcx>,
+    typing_env: ty::TypingEnv<'tcx>,
 }
 
 impl<'tcx> LayoutOfHelpers<'tcx> for UnwrapLayoutCx<'tcx> {
@@ -155,9 +150,9 @@ impl<'tcx> HasTyCtxt<'tcx> for UnwrapLayoutCx<'tcx> {
     }
 }
 
-impl<'tcx> HasParamEnv<'tcx> for UnwrapLayoutCx<'tcx> {
-    fn param_env(&self) -> ParamEnv<'tcx> {
-        self.param_env
+impl<'tcx> HasTypingEnv<'tcx> for UnwrapLayoutCx<'tcx> {
+    fn typing_env(&self) -> ty::TypingEnv<'tcx> {
+        self.typing_env
     }
 }
 
diff --git a/compiler/rustc_passes/src/lib.rs b/compiler/rustc_passes/src/lib.rs
index 664da65068d..8f53b71319d 100644
--- a/compiler/rustc_passes/src/lib.rs
+++ b/compiler/rustc_passes/src/lib.rs
@@ -27,7 +27,7 @@ pub mod entry;
 mod errors;
 #[cfg(debug_assertions)]
 pub mod hir_id_validator;
-pub mod hir_stats;
+pub mod input_stats;
 mod lang_items;
 pub mod layout_test;
 mod lib_features;
diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs
index 366f7dd293c..c6c99852952 100644
--- a/compiler/rustc_passes/src/liveness.rs
+++ b/compiler/rustc_passes/src/liveness.rs
@@ -1297,7 +1297,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
     fn check_is_ty_uninhabited(&mut self, expr: &Expr<'_>, succ: LiveNode) -> LiveNode {
         let ty = self.typeck_results.expr_ty(expr);
         let m = self.ir.tcx.parent_module(expr.hir_id).to_def_id();
-        if ty.is_inhabited_from(self.ir.tcx, m, self.param_env) {
+        if ty.is_inhabited_from(self.ir.tcx, m, ty::TypingEnv::from_param_env(self.param_env)) {
             return succ;
         }
         match self.ir.lnks[succ] {
diff --git a/compiler/rustc_pattern_analysis/src/rustc.rs b/compiler/rustc_pattern_analysis/src/rustc.rs
index 9ea5023064c..936e5235c55 100644
--- a/compiler/rustc_pattern_analysis/src/rustc.rs
+++ b/compiler/rustc_pattern_analysis/src/rustc.rs
@@ -9,6 +9,7 @@ use rustc_index::{Idx, IndexVec};
 use rustc_middle::middle::stability::EvalResult;
 use rustc_middle::mir::{self, Const};
 use rustc_middle::thir::{self, Pat, PatKind, PatRange, PatRangeBoundary};
+use rustc_middle::traits::Reveal;
 use rustc_middle::ty::layout::IntegerExt;
 use rustc_middle::ty::{
     self, FieldDef, OpaqueTypeKey, ScalarInt, Ty, TyCtxt, TypeVisitableExt, VariantDef,
@@ -108,6 +109,17 @@ impl<'p, 'tcx: 'p> fmt::Debug for RustcPatCtxt<'p, 'tcx> {
 }
 
 impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
+    pub fn typing_mode(&self) -> ty::TypingMode<'tcx> {
+        debug_assert_eq!(self.param_env.reveal(), Reveal::UserFacing);
+        // FIXME(#132279): This is inside of a body. If we need to use the `param_env`
+        // and `typing_mode` we should reveal opaques defined by that body.
+        ty::TypingMode::non_body_analysis()
+    }
+
+    pub fn typing_env(&self) -> ty::TypingEnv<'tcx> {
+        ty::TypingEnv { typing_mode: self.typing_mode(), param_env: self.param_env }
+    }
+
     /// Type inference occasionally gives us opaque types in places where corresponding patterns
     /// have more specific types. To avoid inconsistencies as well as detect opaque uninhabited
     /// types, we use the corresponding concrete type if possible.
@@ -139,7 +151,7 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
     pub fn is_uninhabited(&self, ty: Ty<'tcx>) -> bool {
         !ty.inhabited_predicate(self.tcx).apply_revealing_opaque(
             self.tcx,
-            self.param_env,
+            self.typing_env(),
             self.module,
             &|key| self.reveal_opaque_key(key),
         )
@@ -179,7 +191,7 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
         variant.fields.iter().map(move |field| {
             let ty = field.ty(self.tcx, args);
             // `field.ty()` doesn't normalize after instantiating.
-            let ty = self.tcx.normalize_erasing_regions(self.param_env, ty);
+            let ty = self.tcx.normalize_erasing_regions(self.typing_env(), ty);
             let ty = self.reveal_opaque_ty(ty);
             (field, ty)
         })
@@ -369,7 +381,7 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
                         let is_inhabited = v
                             .inhabited_predicate(cx.tcx, *def)
                             .instantiate(cx.tcx, args)
-                            .apply_revealing_opaque(cx.tcx, cx.param_env, cx.module, &|key| {
+                            .apply_revealing_opaque(cx.tcx, cx.typing_env(), cx.module, &|key| {
                                 cx.reveal_opaque_key(key)
                             });
                         // Variants that depend on a disabled unstable feature.
@@ -430,7 +442,7 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
         match bdy {
             PatRangeBoundary::NegInfinity => MaybeInfiniteInt::NegInfinity,
             PatRangeBoundary::Finite(value) => {
-                let bits = value.eval_bits(self.tcx, self.param_env);
+                let bits = value.eval_bits(self.tcx, self.typing_env());
                 match *ty.kind() {
                     ty::Int(ity) => {
                         let size = Integer::from_int_ty(&self.tcx, ity).size().bits();
@@ -539,7 +551,7 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
             PatKind::Constant { value } => {
                 match ty.kind() {
                     ty::Bool => {
-                        ctor = match value.try_eval_bool(cx.tcx, cx.param_env) {
+                        ctor = match value.try_eval_bool(cx.tcx, cx.typing_env()) {
                             Some(b) => Bool(b),
                             None => Opaque(OpaqueId::new()),
                         };
@@ -547,7 +559,7 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
                         arity = 0;
                     }
                     ty::Char | ty::Int(_) | ty::Uint(_) => {
-                        ctor = match value.try_eval_bits(cx.tcx, cx.param_env) {
+                        ctor = match value.try_eval_bits(cx.tcx, cx.typing_env()) {
                             Some(bits) => {
                                 let x = match *ty.kind() {
                                     ty::Int(ity) => {
@@ -564,7 +576,7 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
                         arity = 0;
                     }
                     ty::Float(ty::FloatTy::F16) => {
-                        ctor = match value.try_eval_bits(cx.tcx, cx.param_env) {
+                        ctor = match value.try_eval_bits(cx.tcx, cx.typing_env()) {
                             Some(bits) => {
                                 use rustc_apfloat::Float;
                                 let value = rustc_apfloat::ieee::Half::from_bits(bits);
@@ -576,7 +588,7 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
                         arity = 0;
                     }
                     ty::Float(ty::FloatTy::F32) => {
-                        ctor = match value.try_eval_bits(cx.tcx, cx.param_env) {
+                        ctor = match value.try_eval_bits(cx.tcx, cx.typing_env()) {
                             Some(bits) => {
                                 use rustc_apfloat::Float;
                                 let value = rustc_apfloat::ieee::Single::from_bits(bits);
@@ -588,7 +600,7 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
                         arity = 0;
                     }
                     ty::Float(ty::FloatTy::F64) => {
-                        ctor = match value.try_eval_bits(cx.tcx, cx.param_env) {
+                        ctor = match value.try_eval_bits(cx.tcx, cx.typing_env()) {
                             Some(bits) => {
                                 use rustc_apfloat::Float;
                                 let value = rustc_apfloat::ieee::Double::from_bits(bits);
@@ -600,7 +612,7 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
                         arity = 0;
                     }
                     ty::Float(ty::FloatTy::F128) => {
-                        ctor = match value.try_eval_bits(cx.tcx, cx.param_env) {
+                        ctor = match value.try_eval_bits(cx.tcx, cx.typing_env()) {
                             Some(bits) => {
                                 use rustc_apfloat::Float;
                                 let value = rustc_apfloat::ieee::Quad::from_bits(bits);
@@ -649,8 +661,8 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
                     }
                     ty::Float(fty) => {
                         use rustc_apfloat::Float;
-                        let lo = lo.as_finite().map(|c| c.eval_bits(cx.tcx, cx.param_env));
-                        let hi = hi.as_finite().map(|c| c.eval_bits(cx.tcx, cx.param_env));
+                        let lo = lo.as_finite().map(|c| c.eval_bits(cx.tcx, cx.typing_env()));
+                        let hi = hi.as_finite().map(|c| c.eval_bits(cx.tcx, cx.typing_env()));
                         match fty {
                             ty::FloatTy::F16 => {
                                 use rustc_apfloat::ieee::Half;
diff --git a/compiler/rustc_query_system/src/lib.rs b/compiler/rustc_query_system/src/lib.rs
index ba7a631fb54..a85e8a55a21 100644
--- a/compiler/rustc_query_system/src/lib.rs
+++ b/compiler/rustc_query_system/src/lib.rs
@@ -2,6 +2,7 @@
 #![allow(rustc::potential_query_instability, internal_features)]
 #![feature(assert_matches)]
 #![feature(core_intrinsics)]
+#![feature(dropck_eyepatch)]
 #![feature(hash_raw_entry)]
 #![feature(let_chains)]
 #![feature(min_specialization)]
diff --git a/compiler/rustc_query_system/src/query/caches.rs b/compiler/rustc_query_system/src/query/caches.rs
index a4ced3d2c24..e6f3d97742d 100644
--- a/compiler/rustc_query_system/src/query/caches.rs
+++ b/compiler/rustc_query_system/src/query/caches.rs
@@ -3,9 +3,10 @@ use std::hash::Hash;
 
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::sharded::{self, Sharded};
-use rustc_data_structures::sync::{Lock, OnceLock};
+use rustc_data_structures::sync::OnceLock;
+pub use rustc_data_structures::vec_cache::VecCache;
 use rustc_hir::def_id::LOCAL_CRATE;
-use rustc_index::{Idx, IndexVec};
+use rustc_index::Idx;
 use rustc_span::def_id::{DefId, DefIndex};
 
 use crate::dep_graph::DepNodeIndex;
@@ -100,52 +101,10 @@ where
     }
 }
 
-pub struct VecCache<K: Idx, V> {
-    cache: Lock<IndexVec<K, Option<(V, DepNodeIndex)>>>,
-}
-
-impl<K: Idx, V> Default for VecCache<K, V> {
-    fn default() -> Self {
-        VecCache { cache: Default::default() }
-    }
-}
-
-impl<K, V> QueryCache for VecCache<K, V>
-where
-    K: Eq + Idx + Copy + Debug,
-    V: Copy,
-{
-    type Key = K;
-    type Value = V;
-
-    #[inline(always)]
-    fn lookup(&self, key: &K) -> Option<(V, DepNodeIndex)> {
-        let lock = self.cache.lock();
-        if let Some(Some(value)) = lock.get(*key) { Some(*value) } else { None }
-    }
-
-    #[inline]
-    fn complete(&self, key: K, value: V, index: DepNodeIndex) {
-        let mut lock = self.cache.lock();
-        lock.insert(key, (value, index));
-    }
-
-    fn iter(&self, f: &mut dyn FnMut(&Self::Key, &Self::Value, DepNodeIndex)) {
-        for (k, v) in self.cache.lock().iter_enumerated() {
-            if let Some(v) = v {
-                f(&k, &v.0, v.1);
-            }
-        }
-    }
-}
-
 pub struct DefIdCache<V> {
     /// Stores the local DefIds in a dense map. Local queries are much more often dense, so this is
     /// a win over hashing query keys at marginal memory cost (~5% at most) compared to FxHashMap.
-    ///
-    /// The second element of the tuple is the set of keys actually present in the IndexVec, used
-    /// for faster iteration in `iter()`.
-    local: Lock<(IndexVec<DefIndex, Option<(V, DepNodeIndex)>>, Vec<DefIndex>)>,
+    local: VecCache<DefIndex, V, DepNodeIndex>,
     foreign: DefaultCache<DefId, V>,
 }
 
@@ -165,8 +124,7 @@ where
     #[inline(always)]
     fn lookup(&self, key: &DefId) -> Option<(V, DepNodeIndex)> {
         if key.krate == LOCAL_CRATE {
-            let cache = self.local.lock();
-            cache.0.get(key.index).and_then(|v| *v)
+            self.local.lookup(&key.index)
         } else {
             self.foreign.lookup(key)
         }
@@ -175,27 +133,39 @@ where
     #[inline]
     fn complete(&self, key: DefId, value: V, index: DepNodeIndex) {
         if key.krate == LOCAL_CRATE {
-            let mut cache = self.local.lock();
-            let (cache, present) = &mut *cache;
-            let slot = cache.ensure_contains_elem(key.index, Default::default);
-            if slot.is_none() {
-                // FIXME: Only store the present set when running in incremental mode. `iter` is not
-                // used outside of saving caches to disk and self-profile.
-                present.push(key.index);
-            }
-            *slot = Some((value, index));
+            self.local.complete(key.index, value, index)
         } else {
             self.foreign.complete(key, value, index)
         }
     }
 
     fn iter(&self, f: &mut dyn FnMut(&Self::Key, &Self::Value, DepNodeIndex)) {
-        let guard = self.local.lock();
-        let (cache, present) = &*guard;
-        for &idx in present.iter() {
-            let value = cache[idx].unwrap();
-            f(&DefId { krate: LOCAL_CRATE, index: idx }, &value.0, value.1);
-        }
+        self.local.iter(&mut |key, value, index| {
+            f(&DefId { krate: LOCAL_CRATE, index: *key }, value, index);
+        });
         self.foreign.iter(f);
     }
 }
+
+impl<K, V> QueryCache for VecCache<K, V, DepNodeIndex>
+where
+    K: Idx + Eq + Hash + Copy + Debug,
+    V: Copy,
+{
+    type Key = K;
+    type Value = V;
+
+    #[inline(always)]
+    fn lookup(&self, key: &K) -> Option<(V, DepNodeIndex)> {
+        self.lookup(key)
+    }
+
+    #[inline]
+    fn complete(&self, key: K, value: V, index: DepNodeIndex) {
+        self.complete(key, value, index)
+    }
+
+    fn iter(&self, f: &mut dyn FnMut(&Self::Key, &Self::Value, DepNodeIndex)) {
+        self.iter(f)
+    }
+}
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index 5437ca65935..5b78acd904a 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -535,14 +535,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
         filter_fn: &impl Fn(Res) -> bool,
         ctxt: Option<SyntaxContext>,
     ) {
-        for (key, resolution) in self.resolutions(module).borrow().iter() {
-            if let Some(binding) = resolution.borrow().binding {
-                let res = binding.res();
-                if filter_fn(res) && ctxt.map_or(true, |ctxt| ctxt == key.ident.span.ctxt()) {
-                    names.push(TypoSuggestion::typo_from_ident(key.ident, res));
-                }
+        module.for_each_child(self, |_this, ident, _ns, binding| {
+            let res = binding.res();
+            if filter_fn(res) && ctxt.map_or(true, |ctxt| ctxt == ident.span.ctxt()) {
+                names.push(TypoSuggestion::typo_from_ident(ident, res));
             }
-        }
+        });
     }
 
     /// Combines an error with provided span and emits it.
diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs
index b80e0e196ca..ad825d7813d 100644
--- a/compiler/rustc_resolve/src/ident.rs
+++ b/compiler/rustc_resolve/src/ident.rs
@@ -38,6 +38,12 @@ impl From<UsePrelude> for bool {
     }
 }
 
+#[derive(Debug, PartialEq)]
+enum Shadowing {
+    Restricted,
+    Unrestricted,
+}
+
 impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
     /// A generic scope visitor.
     /// Visits scopes in order to resolve some identifier in them or perform other actions.
@@ -311,13 +317,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
 
         // Walk backwards up the ribs in scope.
         let mut module = self.graph_root;
-        for i in (0..ribs.len()).rev() {
-            debug!("walk rib\n{:?}", ribs[i].bindings);
+        for (i, rib) in ribs.iter().enumerate().rev() {
+            debug!("walk rib\n{:?}", rib.bindings);
             // Use the rib kind to determine whether we are resolving parameters
             // (macro 2.0 hygiene) or local variables (`macro_rules` hygiene).
-            let rib_ident = if ribs[i].kind.contains_params() { normalized_ident } else { ident };
-            if let Some((original_rib_ident_def, res)) = ribs[i].bindings.get_key_value(&rib_ident)
-            {
+            let rib_ident = if rib.kind.contains_params() { normalized_ident } else { ident };
+            if let Some((original_rib_ident_def, res)) = rib.bindings.get_key_value(&rib_ident) {
                 // The ident resolves to a type parameter or local variable.
                 return Some(LexicalScopeBinding::Res(self.validate_res_from_ribs(
                     i,
@@ -329,7 +334,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
                 )));
             }
 
-            module = match ribs[i].kind {
+            module = match rib.kind {
                 RibKind::Module(module) => module,
                 RibKind::MacroDefinition(def) if def == self.macro_def(ident.span.ctxt()) => {
                     // If an invocation of this macro created `ident`, give up on `ident`
@@ -350,6 +355,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
                 ident,
                 ns,
                 parent_scope,
+                Shadowing::Unrestricted,
                 finalize.map(|finalize| Finalize { used: Used::Scope, ..finalize }),
                 ignore_binding,
                 None,
@@ -494,7 +500,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
                     Scope::CrateRoot => {
                         let root_ident = Ident::new(kw::PathRoot, ident.span);
                         let root_module = this.resolve_crate_root(root_ident);
-                        let binding = this.resolve_ident_in_module_ext(
+                        let binding = this.resolve_ident_in_module(
                             ModuleOrUniformRoot::Module(root_module),
                             ident,
                             ns,
@@ -516,12 +522,16 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
                     }
                     Scope::Module(module, derive_fallback_lint_id) => {
                         let adjusted_parent_scope = &ParentScope { module, ..*parent_scope };
-                        let binding = this.resolve_ident_in_module_unadjusted_ext(
+                        let binding = this.resolve_ident_in_module_unadjusted(
                             ModuleOrUniformRoot::Module(module),
                             ident,
                             ns,
                             adjusted_parent_scope,
-                            !matches!(scope_set, ScopeSet::Late(..)),
+                            if matches!(scope_set, ScopeSet::Late(..)) {
+                                Shadowing::Unrestricted
+                            } else {
+                                Shadowing::Restricted
+                            },
                             finalize.map(|finalize| Finalize { used: Used::Scope, ..finalize }),
                             ignore_binding,
                             ignore_import,
@@ -590,6 +600,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
                                 ident,
                                 ns,
                                 parent_scope,
+                                Shadowing::Unrestricted,
                                 None,
                                 ignore_binding,
                                 ignore_import,
@@ -748,7 +759,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
         parent_scope: &ParentScope<'ra>,
         ignore_import: Option<Import<'ra>>,
     ) -> Result<NameBinding<'ra>, Determinacy> {
-        self.resolve_ident_in_module_ext(module, ident, ns, parent_scope, None, None, ignore_import)
+        self.resolve_ident_in_module(module, ident, ns, parent_scope, None, None, ignore_import)
             .map_err(|(determinacy, _)| determinacy)
     }
 
@@ -756,29 +767,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
     pub(crate) fn resolve_ident_in_module(
         &mut self,
         module: ModuleOrUniformRoot<'ra>,
-        ident: Ident,
-        ns: Namespace,
-        parent_scope: &ParentScope<'ra>,
-        finalize: Option<Finalize>,
-        ignore_binding: Option<NameBinding<'ra>>,
-        ignore_import: Option<Import<'ra>>,
-    ) -> Result<NameBinding<'ra>, Determinacy> {
-        self.resolve_ident_in_module_ext(
-            module,
-            ident,
-            ns,
-            parent_scope,
-            finalize,
-            ignore_binding,
-            ignore_import,
-        )
-        .map_err(|(determinacy, _)| determinacy)
-    }
-
-    #[instrument(level = "debug", skip(self))]
-    fn resolve_ident_in_module_ext(
-        &mut self,
-        module: ModuleOrUniformRoot<'ra>,
         mut ident: Ident,
         ns: Namespace,
         parent_scope: &ParentScope<'ra>,
@@ -803,52 +791,28 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
                 // No adjustments
             }
         }
-        self.resolve_ident_in_module_unadjusted_ext(
+        self.resolve_ident_in_module_unadjusted(
             module,
             ident,
             ns,
             adjusted_parent_scope,
-            false,
+            Shadowing::Unrestricted,
             finalize,
             ignore_binding,
             ignore_import,
         )
     }
 
-    #[instrument(level = "debug", skip(self))]
-    fn resolve_ident_in_module_unadjusted(
-        &mut self,
-        module: ModuleOrUniformRoot<'ra>,
-        ident: Ident,
-        ns: Namespace,
-        parent_scope: &ParentScope<'ra>,
-        finalize: Option<Finalize>,
-        ignore_binding: Option<NameBinding<'ra>>,
-        ignore_import: Option<Import<'ra>>,
-    ) -> Result<NameBinding<'ra>, Determinacy> {
-        self.resolve_ident_in_module_unadjusted_ext(
-            module,
-            ident,
-            ns,
-            parent_scope,
-            false,
-            finalize,
-            ignore_binding,
-            ignore_import,
-        )
-        .map_err(|(determinacy, _)| determinacy)
-    }
-
     /// Attempts to resolve `ident` in namespaces `ns` of `module`.
     /// Invariant: if `finalize` is `Some`, expansion and import resolution must be complete.
     #[instrument(level = "debug", skip(self))]
-    fn resolve_ident_in_module_unadjusted_ext(
+    fn resolve_ident_in_module_unadjusted(
         &mut self,
         module: ModuleOrUniformRoot<'ra>,
         ident: Ident,
         ns: Namespace,
         parent_scope: &ParentScope<'ra>,
-        restricted_shadowing: bool,
+        shadowing: Shadowing,
         finalize: Option<Finalize>,
         // This binding should be ignored during in-module resolution, so that we don't get
         // "self-confirming" import resolutions during import validation and checking.
@@ -858,7 +822,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
         let module = match module {
             ModuleOrUniformRoot::Module(module) => module,
             ModuleOrUniformRoot::CrateRootAndExternPrelude => {
-                assert!(!restricted_shadowing);
+                assert_eq!(shadowing, Shadowing::Unrestricted);
                 let binding = self.early_resolve_ident_in_lexical_scope(
                     ident,
                     ScopeSet::AbsolutePath(ns),
@@ -871,7 +835,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
                 return binding.map_err(|determinacy| (determinacy, Weak::No));
             }
             ModuleOrUniformRoot::ExternPrelude => {
-                assert!(!restricted_shadowing);
+                assert_eq!(shadowing, Shadowing::Unrestricted);
                 return if ns != TypeNS {
                     Err((Determined, Weak::No))
                 } else if let Some(binding) = self.extern_prelude_get(ident, finalize.is_some()) {
@@ -884,7 +848,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
                 };
             }
             ModuleOrUniformRoot::CurrentScope => {
-                assert!(!restricted_shadowing);
+                assert_eq!(shadowing, Shadowing::Unrestricted);
                 if ns == TypeNS {
                     if ident.name == kw::Crate || ident.name == kw::DollarCrate {
                         let module = self.resolve_crate_root(ident);
@@ -943,7 +907,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
 
             // Forbid expanded shadowing to avoid time travel.
             if let Some(shadowed_glob) = resolution.shadowed_glob
-                && restricted_shadowing
+                && shadowing == Shadowing::Restricted
                 && binding.expansion != LocalExpnId::ROOT
                 && binding.res() != shadowed_glob.res()
             {
@@ -958,7 +922,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
                 });
             }
 
-            if !restricted_shadowing
+            if shadowing == Shadowing::Unrestricted
                 && binding.expansion != LocalExpnId::ROOT
                 && let NameBindingKind::Import { import, .. } = binding.kind
                 && matches!(import.kind, ImportKind::MacroExport)
@@ -1047,13 +1011,13 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
                 ignore_binding,
                 ignore_import,
             ) {
-                Err(Determined) => continue,
+                Err((Determined, _)) => continue,
                 Ok(binding)
                     if !self.is_accessible_from(binding.vis, single_import.parent_scope.module) =>
                 {
                     continue;
                 }
-                Ok(_) | Err(Undetermined) => return Err((Undetermined, Weak::No)),
+                Ok(_) | Err((Undetermined, _)) => return Err((Undetermined, Weak::No)),
             }
         }
 
@@ -1070,7 +1034,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
         // and prohibit access to macro-expanded `macro_export` macros instead (unless restricted
         // shadowing is enabled, see `macro_expanded_macro_export_errors`).
         if let Some(binding) = binding {
-            if binding.determined() || ns == MacroNS || restricted_shadowing {
+            if binding.determined() || ns == MacroNS || shadowing == Shadowing::Restricted {
                 return check_usable(self, binding);
             } else {
                 return Err((Undetermined, Weak::No));
@@ -1122,19 +1086,20 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
                 ident,
                 ns,
                 adjusted_parent_scope,
+                Shadowing::Unrestricted,
                 None,
                 ignore_binding,
                 ignore_import,
             );
 
             match result {
-                Err(Determined) => continue,
+                Err((Determined, _)) => continue,
                 Ok(binding)
                     if !self.is_accessible_from(binding.vis, glob_import.parent_scope.module) =>
                 {
                     continue;
                 }
-                Ok(_) | Err(Undetermined) => return Err((Undetermined, Weak::Yes)),
+                Ok(_) | Err((Undetermined, _)) => return Err((Undetermined, Weak::Yes)),
             }
         }
 
@@ -1200,7 +1165,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
                             // Still doesn't deal with upvars
                             if let Some(span) = finalize {
                                 let (span, resolution_error) = match item {
-                                    None if rib_ident.as_str() == "self" => (span, LowercaseSelf),
+                                    None if rib_ident.name == kw::SelfLower => {
+                                        (span, LowercaseSelf)
+                                    }
                                     None => {
                                         // If we have a `let name = expr;`, we have the span for
                                         // `name` and use that to see if it is followed by a type
@@ -1563,6 +1530,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
                     ignore_binding,
                     ignore_import,
                 )
+                .map_err(|(determinacy, _)| determinacy)
             } else if let Some(ribs) = ribs
                 && let Some(TypeNS | ValueNS) = opt_ns
             {
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index f4a85c358e3..26b345f5941 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -1688,9 +1688,9 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
             }
         }
 
+        let normalized_ident = ident.normalize_to_macros_2_0();
         let mut outer_res = None;
         for rib in lifetime_rib_iter {
-            let normalized_ident = ident.normalize_to_macros_2_0();
             if let Some((&outer, _)) = rib.bindings.get_key_value(&normalized_ident) {
                 outer_res = Some(outer);
                 break;
diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs
index 9abb3180388..e382295b8f6 100644
--- a/compiler/rustc_resolve/src/lib.rs
+++ b/compiler/rustc_resolve/src/lib.rs
@@ -1082,8 +1082,6 @@ pub struct Resolver<'ra, 'tcx> {
     binding_parent_modules: FxHashMap<NameBinding<'ra>, Module<'ra>>,
 
     underscore_disambiguator: u32,
-    /// Disambiguator for anonymous adts.
-    empty_disambiguator: u32,
 
     /// Maps glob imports to the names of items actually imported.
     glob_map: FxHashMap<LocalDefId, FxHashSet<Symbol>>,
@@ -1462,7 +1460,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
             module_children: Default::default(),
             trait_map: NodeMap::default(),
             underscore_disambiguator: 0,
-            empty_disambiguator: 0,
             empty_module,
             module_map,
             block_map: Default::default(),
@@ -1809,12 +1806,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
         assoc_item: Option<(Symbol, Namespace)>,
     ) -> bool {
         match (trait_module, assoc_item) {
-            (Some(trait_module), Some((name, ns))) => {
-                self.resolutions(trait_module).borrow().iter().any(|resolution| {
-                    let (&BindingKey { ident: assoc_ident, ns: assoc_ns, .. }, _) = resolution;
-                    assoc_ns == ns && assoc_ident.name == name
-                })
-            }
+            (Some(trait_module), Some((name, ns))) => self
+                .resolutions(trait_module)
+                .borrow()
+                .iter()
+                .any(|(key, _name_resolution)| key.ns == ns && key.ident.name == name),
             _ => true,
         }
     }
@@ -1842,9 +1838,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
         let disambiguator = if ident.name == kw::Underscore {
             self.underscore_disambiguator += 1;
             self.underscore_disambiguator
-        } else if ident.name == kw::Empty {
-            self.empty_disambiguator += 1;
-            self.empty_disambiguator
         } else {
             0
         };
diff --git a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs
index 0e6f905e7a1..2f4387e412d 100644
--- a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs
+++ b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs
@@ -133,7 +133,7 @@ fn encode_const<'tcx>(
             match ct_ty.kind() {
                 ty::Int(ity) => {
                     let bits = c
-                        .try_to_bits(tcx, ty::ParamEnv::reveal_all())
+                        .try_to_bits(tcx, ty::TypingEnv::fully_monomorphized())
                         .expect("expected monomorphic const in cfi");
                     let val = Integer::from_int_ty(&tcx, *ity).size().sign_extend(bits) as i128;
                     if val < 0 {
@@ -143,7 +143,7 @@ fn encode_const<'tcx>(
                 }
                 ty::Uint(_) => {
                     let val = c
-                        .try_to_bits(tcx, ty::ParamEnv::reveal_all())
+                        .try_to_bits(tcx, ty::TypingEnv::fully_monomorphized())
                         .expect("expected monomorphic const in cfi");
                     let _ = write!(s, "{val}");
                 }
diff --git a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/mod.rs b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/mod.rs
index 01568a0f61c..562e288afaa 100644
--- a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/mod.rs
+++ b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/mod.rs
@@ -117,7 +117,9 @@ pub fn typeid_for_instance<'tcx>(
         .unwrap_or_else(|| bug!("typeid_for_instance: invalid option(s) `{:?}`", options.bits()));
     let instance = transform_instance(tcx, instance, transform_ty_options);
     let fn_abi = tcx
-        .fn_abi_of_instance(ty::ParamEnv::reveal_all().and((instance, ty::List::empty())))
+        .fn_abi_of_instance(
+            ty::TypingEnv::fully_monomorphized().as_query_input((instance, ty::List::empty())),
+        )
         .unwrap_or_else(|error| {
             bug!("typeid_for_instance: couldn't get fn_abi of instance {instance:?}: {error:?}")
         });
diff --git a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs
index cba79a02f8b..9c01bd04353 100644
--- a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs
+++ b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs
@@ -136,18 +136,18 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for TransformTy<'tcx> {
                         return t;
                     }
                     let variant = adt_def.non_enum_variant();
-                    let param_env = self.tcx.param_env(variant.def_id);
+                    let typing_env = ty::TypingEnv::post_analysis(self.tcx, variant.def_id);
                     let field = variant.fields.iter().find(|field| {
                         let ty = self.tcx.type_of(field.did).instantiate_identity();
                         let is_zst = self
                             .tcx
-                            .layout_of(param_env.and(ty))
+                            .layout_of(typing_env.as_query_input(ty))
                             .is_ok_and(|layout| layout.is_zst());
                         !is_zst
                     });
                     if let Some(field) = field {
                         let ty0 = self.tcx.normalize_erasing_regions(
-                            ty::ParamEnv::reveal_all(),
+                            ty::TypingEnv::fully_monomorphized(),
                             field.ty(self.tcx, args),
                         );
                         // Generalize any repr(transparent) user-defined type that is either a
@@ -209,9 +209,9 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for TransformTy<'tcx> {
                 }
             }
 
-            ty::Alias(..) => {
-                self.fold_ty(self.tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), t))
-            }
+            ty::Alias(..) => self.fold_ty(
+                self.tcx.normalize_erasing_regions(ty::TypingEnv::fully_monomorphized(), t),
+            ),
 
             ty::Bound(..) | ty::Error(..) | ty::Infer(..) | ty::Param(..) | ty::Placeholder(..) => {
                 bug!("fold_ty: unexpected `{:?}`", t.kind());
@@ -241,7 +241,7 @@ fn trait_object_ty<'tcx>(tcx: TyCtxt<'tcx>, poly_trait_ref: ty::PolyTraitRef<'tc
                         let alias_ty =
                             ty::AliasTy::new_from_args(tcx, assoc_ty.def_id, super_trait_ref.args);
                         let resolved = tcx.normalize_erasing_regions(
-                            ty::ParamEnv::reveal_all(),
+                            ty::TypingEnv::fully_monomorphized(),
                             alias_ty.to_ty(tcx),
                         );
                         debug!("Resolved {:?} -> {resolved}", alias_ty.to_ty(tcx));
@@ -376,7 +376,7 @@ pub(crate) fn transform_instance<'tcx>(
             // implementation will not. We need to walk back to the more general trait method
             let trait_ref = tcx.instantiate_and_normalize_erasing_regions(
                 instance.args,
-                ty::ParamEnv::reveal_all(),
+                ty::TypingEnv::fully_monomorphized(),
                 trait_ref,
             );
             let invoke_ty = trait_object_ty(tcx, ty::Binder::dummy(trait_ref));
@@ -397,7 +397,7 @@ pub(crate) fn transform_instance<'tcx>(
         } else if tcx.is_closure_like(instance.def_id()) {
             // We're either a closure or a coroutine. Our goal is to find the trait we're defined on,
             // instantiate it, and take the type of its only method as our own.
-            let closure_ty = instance.ty(tcx, ty::ParamEnv::reveal_all());
+            let closure_ty = instance.ty(tcx, ty::TypingEnv::fully_monomorphized());
             let (trait_id, inputs) = match closure_ty.kind() {
                 ty::Closure(..) => {
                     let closure_args = instance.args.as_closure();
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index f485e8cace5..d94b503de18 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -1805,8 +1805,6 @@ options! {
         environment variable `RUSTC_GRAPHVIZ_FONT` (default: `Courier, monospace`)"),
     has_thread_local: Option<bool> = (None, parse_opt_bool, [TRACKED],
         "explicitly enable the `cfg(target_thread_local)` directive"),
-    hir_stats: bool = (false, parse_bool, [UNTRACKED],
-        "print some statistics about AST and HIR (default: no)"),
     human_readable_cgu_names: bool = (false, parse_bool, [TRACKED],
         "generate human-readable, predictable names for codegen units (default: no)"),
     identify_regions: bool = (false, parse_bool, [UNTRACKED],
@@ -1838,7 +1836,7 @@ options! {
     inline_mir_threshold: Option<usize> = (None, parse_opt_number, [TRACKED],
         "a default MIR inlining threshold (default: 50)"),
     input_stats: bool = (false, parse_bool, [UNTRACKED],
-        "gather statistics about the input (default: no)"),
+        "print some statistics about AST and HIR (default: no)"),
     instrument_mcount: bool = (false, parse_bool, [TRACKED],
         "insert function instrument code for mcount-based tracing (default: no)"),
     instrument_xray: Option<InstrumentXRay> = (None, parse_instrument_xray, [TRACKED],
diff --git a/compiler/rustc_smir/src/rustc_smir/alloc.rs b/compiler/rustc_smir/src/rustc_smir/alloc.rs
index 5c09879f60e..4e8db6096d4 100644
--- a/compiler/rustc_smir/src/rustc_smir/alloc.rs
+++ b/compiler/rustc_smir/src/rustc_smir/alloc.rs
@@ -41,7 +41,7 @@ pub(crate) fn try_new_allocation<'tcx>(
             let size = scalar.size();
             let align = tables
                 .tcx
-                .layout_of(rustc_middle::ty::ParamEnv::reveal_all().and(ty))
+                .layout_of(rustc_middle::ty::TypingEnv::fully_monomorphized().as_query_input(ty))
                 .map_err(|e| e.stable(tables))?
                 .align;
             let mut allocation = rustc_middle::mir::interpret::Allocation::uninit(size, align.abi);
@@ -53,7 +53,7 @@ pub(crate) fn try_new_allocation<'tcx>(
         ConstValue::ZeroSized => {
             let align = tables
                 .tcx
-                .layout_of(rustc_middle::ty::ParamEnv::empty().and(ty))
+                .layout_of(rustc_middle::ty::TypingEnv::fully_monomorphized().as_query_input(ty))
                 .map_err(|e| e.stable(tables))?
                 .align;
             new_empty_allocation(align.abi)
@@ -66,7 +66,7 @@ pub(crate) fn try_new_allocation<'tcx>(
                 rustc_middle::mir::interpret::Scalar::from_target_usize(meta, &tables.tcx);
             let layout = tables
                 .tcx
-                .layout_of(rustc_middle::ty::ParamEnv::reveal_all().and(ty))
+                .layout_of(rustc_middle::ty::TypingEnv::fully_monomorphized().as_query_input(ty))
                 .map_err(|e| e.stable(tables))?;
             let mut allocation =
                 rustc_middle::mir::interpret::Allocation::uninit(layout.size, layout.align.abi);
@@ -90,7 +90,7 @@ pub(crate) fn try_new_allocation<'tcx>(
             let alloc = tables.tcx.global_alloc(alloc_id).unwrap_memory();
             let ty_size = tables
                 .tcx
-                .layout_of(rustc_middle::ty::ParamEnv::reveal_all().and(ty))
+                .layout_of(rustc_middle::ty::TypingEnv::fully_monomorphized().as_query_input(ty))
                 .map_err(|e| e.stable(tables))?
                 .size;
             allocation_filter(&alloc.0, alloc_range(offset, ty_size), tables)
diff --git a/compiler/rustc_smir/src/rustc_smir/builder.rs b/compiler/rustc_smir/src/rustc_smir/builder.rs
index cd91fc26c10..2eb0cea0e85 100644
--- a/compiler/rustc_smir/src/rustc_smir/builder.rs
+++ b/compiler/rustc_smir/src/rustc_smir/builder.rs
@@ -40,7 +40,7 @@ impl<'tcx> BodyBuilder<'tcx> {
         {
             let mut mono_body = self.instance.instantiate_mir_and_normalize_erasing_regions(
                 tables.tcx,
-                ty::ParamEnv::reveal_all(),
+                ty::TypingEnv::fully_monomorphized(),
                 ty::EarlyBinder::bind(body),
             );
             self.visit_body(&mut mono_body);
@@ -60,7 +60,7 @@ impl<'tcx> MutVisitor<'tcx> for BodyBuilder<'tcx> {
         location: mir::Location,
     ) {
         let const_ = constant.const_;
-        let val = match const_.eval(self.tcx, ty::ParamEnv::reveal_all(), constant.span) {
+        let val = match const_.eval(self.tcx, ty::TypingEnv::fully_monomorphized(), constant.span) {
             Ok(v) => v,
             Err(mir::interpret::ErrorHandled::Reported(..)) => return,
             Err(mir::interpret::ErrorHandled::TooGeneric(..)) => {
diff --git a/compiler/rustc_smir/src/rustc_smir/context.rs b/compiler/rustc_smir/src/rustc_smir/context.rs
index 3db65692af7..b19adf321c3 100644
--- a/compiler/rustc_smir/src/rustc_smir/context.rs
+++ b/compiler/rustc_smir/src/rustc_smir/context.rs
@@ -11,7 +11,7 @@ use std::iter;
 use rustc_abi::HasDataLayout;
 use rustc_hir::LangItem;
 use rustc_middle::ty::layout::{
-    FnAbiOf, FnAbiOfHelpers, HasParamEnv, HasTyCtxt, LayoutOf, LayoutOfHelpers,
+    FnAbiOf, FnAbiOfHelpers, HasTyCtxt, HasTypingEnv, LayoutOf, LayoutOfHelpers,
 };
 use rustc_middle::ty::print::{with_forced_trimmed_paths, with_no_trimmed_paths};
 use rustc_middle::ty::{
@@ -410,7 +410,7 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
         let tcx = tables.tcx;
         let mir_const = cnst.internal(&mut *tables, tcx);
         mir_const
-            .try_eval_target_usize(tables.tcx, ParamEnv::empty())
+            .try_eval_target_usize(tables.tcx, ty::TypingEnv::fully_monomorphized())
             .ok_or_else(|| Error::new(format!("Const `{cnst:?}` cannot be encoded as u64")))
     }
     fn eval_target_usize_ty(&self, cnst: &TyConst) -> Result<u64, Error> {
@@ -428,7 +428,7 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
         let ty_internal = ty.internal(&mut *tables, tcx);
         let size = tables
             .tcx
-            .layout_of(ParamEnv::empty().and(ty_internal))
+            .layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(ty_internal))
             .map_err(|err| {
                 Error::new(format!(
                     "Cannot create a zero-sized constant for type `{ty_internal}`: {err}"
@@ -469,7 +469,11 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
         let mut tables = self.0.borrow_mut();
         let tcx = tables.tcx;
         let ty = ty::Ty::new_uint(tcx, uint_ty.internal(&mut *tables, tcx));
-        let size = tables.tcx.layout_of(ParamEnv::empty().and(ty)).unwrap().size;
+        let size = tables
+            .tcx
+            .layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(ty))
+            .unwrap()
+            .size;
 
         // We don't use Const::from_bits since it doesn't have any error checking.
         let scalar = ScalarInt::try_from_uint(value, size).ok_or_else(|| {
@@ -486,7 +490,11 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
         let mut tables = self.0.borrow_mut();
         let tcx = tables.tcx;
         let ty = ty::Ty::new_uint(tcx, uint_ty.internal(&mut *tables, tcx));
-        let size = tables.tcx.layout_of(ParamEnv::empty().and(ty)).unwrap().size;
+        let size = tables
+            .tcx
+            .layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(ty))
+            .unwrap()
+            .size;
 
         // We don't use Const::from_bits since it doesn't have any error checking.
         let scalar = ScalarInt::try_from_uint(value, size).ok_or_else(|| {
@@ -523,7 +531,11 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
         let def_ty = tables.tcx.type_of(item.internal(&mut *tables, tcx));
         tables
             .tcx
-            .instantiate_and_normalize_erasing_regions(args, ty::ParamEnv::reveal_all(), def_ty)
+            .instantiate_and_normalize_erasing_regions(
+                args,
+                ty::TypingEnv::fully_monomorphized(),
+                def_ty,
+            )
             .stable(&mut *tables)
     }
 
@@ -573,7 +585,7 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
         let mut tables = self.0.borrow_mut();
         let instance = tables.instances[def];
         assert!(!instance.has_non_region_param(), "{instance:?} needs further instantiation");
-        instance.ty(tables.tcx, ParamEnv::reveal_all()).stable(&mut *tables)
+        instance.ty(tables.tcx, ty::TypingEnv::fully_monomorphized()).stable(&mut *tables)
     }
 
     fn instance_args(&self, def: InstanceDef) -> GenericArgs {
@@ -642,7 +654,12 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
         let tcx = tables.tcx;
         let def_id = def.0.internal(&mut *tables, tcx);
         let args_ref = args.internal(&mut *tables, tcx);
-        match Instance::try_resolve(tables.tcx, ParamEnv::reveal_all(), def_id, args_ref) {
+        match Instance::try_resolve(
+            tables.tcx,
+            ty::TypingEnv::fully_monomorphized(),
+            def_id,
+            args_ref,
+        ) {
             Ok(Some(instance)) => Some(instance.stable(&mut *tables)),
             Ok(None) | Err(_) => None,
         }
@@ -665,8 +682,13 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
         let tcx = tables.tcx;
         let def_id = def.0.internal(&mut *tables, tcx);
         let args_ref = args.internal(&mut *tables, tcx);
-        Instance::resolve_for_fn_ptr(tables.tcx, ParamEnv::reveal_all(), def_id, args_ref)
-            .stable(&mut *tables)
+        Instance::resolve_for_fn_ptr(
+            tables.tcx,
+            ty::TypingEnv::fully_monomorphized(),
+            def_id,
+            args_ref,
+        )
+        .stable(&mut *tables)
     }
 
     fn resolve_closure(
@@ -827,9 +849,9 @@ impl<'tcx> LayoutOfHelpers<'tcx> for Tables<'tcx> {
     }
 }
 
-impl<'tcx> HasParamEnv<'tcx> for Tables<'tcx> {
-    fn param_env(&self) -> ty::ParamEnv<'tcx> {
-        ty::ParamEnv::reveal_all()
+impl<'tcx> HasTypingEnv<'tcx> for Tables<'tcx> {
+    fn typing_env(&self) -> ty::TypingEnv<'tcx> {
+        ty::TypingEnv::fully_monomorphized()
     }
 }
 
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index a562d34abde..a2d9859645f 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -316,6 +316,7 @@ symbols! {
         SubdiagMessage,
         Subdiagnostic,
         Sync,
+        SyncUnsafeCell,
         T,
         Target,
         ToOwned,
@@ -409,7 +410,6 @@ symbols! {
         arm,
         arm_target_feature,
         array,
-        as_mut_ptr,
         as_ptr,
         as_ref,
         as_str,
@@ -1226,6 +1226,7 @@ symbols! {
         min_const_generics,
         min_const_unsafe_fn,
         min_exhaustive_patterns,
+        min_generic_const_args,
         min_specialization,
         min_type_alias_impl_trait,
         minnumf128,
@@ -1654,6 +1655,7 @@ symbols! {
         rustc_allow_const_fn_unstable,
         rustc_allow_incoherent_impl,
         rustc_allowed_through_unstable_modules,
+        rustc_as_ptr,
         rustc_attrs,
         rustc_autodiff,
         rustc_box,
diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs
index 05b4ff327a9..94f51b87cff 100644
--- a/compiler/rustc_symbol_mangling/src/v0.rs
+++ b/compiler/rustc_symbol_mangling/src/v0.rs
@@ -26,7 +26,7 @@ pub(super) fn mangle<'tcx>(
 ) -> String {
     let def_id = instance.def_id();
     // FIXME(eddyb) this should ideally not be needed.
-    let args = tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), instance.args);
+    let args = tcx.normalize_erasing_regions(ty::TypingEnv::fully_monomorphized(), instance.args);
 
     let prefix = "_R";
     let mut cx: SymbolMangler<'_> = SymbolMangler {
@@ -237,15 +237,16 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> {
         if !args.is_empty() {
             param_env = EarlyBinder::bind(param_env).instantiate(self.tcx, args);
         }
+        let typing_env = ty::TypingEnv { typing_mode: ty::TypingMode::PostAnalysis, param_env };
 
         match &mut impl_trait_ref {
             Some(impl_trait_ref) => {
                 assert_eq!(impl_trait_ref.self_ty(), self_ty);
-                *impl_trait_ref = self.tcx.normalize_erasing_regions(param_env, *impl_trait_ref);
+                *impl_trait_ref = self.tcx.normalize_erasing_regions(typing_env, *impl_trait_ref);
                 self_ty = impl_trait_ref.self_ty();
             }
             None => {
-                self_ty = self.tcx.normalize_erasing_regions(param_env, self_ty);
+                self_ty = self.tcx.normalize_erasing_regions(typing_env, self_ty);
             }
         }
 
@@ -591,7 +592,7 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> {
                 ct_ty.print(self)?;
 
                 let mut bits = ct
-                    .try_to_bits(self.tcx, ty::ParamEnv::reveal_all())
+                    .try_to_bits(self.tcx, ty::TypingEnv::fully_monomorphized())
                     .expect("expected const to be monomorphic");
 
                 // Negative integer values are mangled using `n` as a "sign prefix".
diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs
index 808e6a50d85..9a7bdaa5b57 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs
@@ -528,7 +528,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
         // Find the method being called.
         let Ok(Some(instance)) = ty::Instance::try_resolve(
             tcx,
-            ctxt.param_env,
+            self.cx.typing_env(ctxt.param_env),
             ctxt.assoc_item.def_id,
             self.cx.resolve_vars_if_possible(ctxt.args),
         ) else {
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs
index 1109b11d2a7..4e7d7b79ff4 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs
@@ -2079,7 +2079,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                 cand.trait_ref = self
                     .tcx
                     .try_normalize_erasing_regions(
-                        self.tcx.param_env(cand.impl_def_id),
+                        ty::TypingEnv::non_body_analysis(self.tcx, cand.impl_def_id),
                         cand.trait_ref,
                     )
                     .unwrap_or(cand.trait_ref);
diff --git a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs
index c00246cfd7d..cf63f14fb93 100644
--- a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs
+++ b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs
@@ -513,7 +513,7 @@ fn check_receiver_correct<'tcx>(tcx: TyCtxt<'tcx>, trait_def_id: DefId, method:
 
     let method_def_id = method.def_id;
     let sig = tcx.fn_sig(method_def_id).instantiate_identity();
-    let param_env = tcx.param_env(method_def_id);
+    let typing_env = ty::TypingEnv::non_body_analysis(tcx, method_def_id);
     let receiver_ty = tcx.liberate_late_bound_regions(method_def_id, sig.input(0));
 
     if receiver_ty == tcx.types.self_param {
@@ -523,7 +523,7 @@ fn check_receiver_correct<'tcx>(tcx: TyCtxt<'tcx>, trait_def_id: DefId, method:
 
     // e.g., `Rc<()>`
     let unit_receiver_ty = receiver_for_self_ty(tcx, receiver_ty, tcx.types.unit, method_def_id);
-    match tcx.layout_of(param_env.and(unit_receiver_ty)).map(|l| l.backend_repr) {
+    match tcx.layout_of(typing_env.as_query_input(unit_receiver_ty)).map(|l| l.backend_repr) {
         Ok(BackendRepr::Scalar(..)) => (),
         abi => {
             tcx.dcx().span_delayed_bug(
@@ -538,7 +538,7 @@ fn check_receiver_correct<'tcx>(tcx: TyCtxt<'tcx>, trait_def_id: DefId, method:
     // e.g., `Rc<dyn Trait>`
     let trait_object_receiver =
         receiver_for_self_ty(tcx, receiver_ty, trait_object_ty, method_def_id);
-    match tcx.layout_of(param_env.and(trait_object_receiver)).map(|l| l.backend_repr) {
+    match tcx.layout_of(typing_env.as_query_input(trait_object_receiver)).map(|l| l.backend_repr) {
         Ok(BackendRepr::ScalarPair(..)) => (),
         abi => {
             tcx.dcx().span_delayed_bug(
diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs
index fe90066b4e7..c0603c06d42 100644
--- a/compiler/rustc_trait_selection/src/traits/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/mod.rs
@@ -611,11 +611,12 @@ pub fn try_evaluate_const<'tcx>(
             //
             // FIXME: `const_eval_resolve_for_typeck` should probably just set the env to `Reveal::All`
             // instead of having this logic here
-            let env = tcx.erase_regions(param_env).with_reveal_all_normalized(tcx);
+            let typing_env =
+                tcx.erase_regions(infcx.typing_env(param_env)).with_reveal_all_normalized(tcx);
             let erased_uv = tcx.erase_regions(uv);
 
             use rustc_middle::mir::interpret::ErrorHandled;
-            match tcx.const_eval_resolve_for_typeck(env, erased_uv, DUMMY_SP) {
+            match tcx.const_eval_resolve_for_typeck(typing_env, erased_uv, DUMMY_SP) {
                 Ok(Ok(val)) => Ok(ty::Const::new_value(
                     tcx,
                     val,
diff --git a/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs b/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs
index 4ff0910c9b9..1d3e8d43af7 100644
--- a/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs
@@ -144,7 +144,14 @@ pub fn compute_dropck_outlives_inner<'tcx>(
             result.overflows.len(),
             ty_stack.len()
         );
-        dtorck_constraint_for_ty_inner(tcx, param_env, DUMMY_SP, depth, ty, &mut constraints)?;
+        dtorck_constraint_for_ty_inner(
+            tcx,
+            ocx.infcx.typing_env(param_env),
+            DUMMY_SP,
+            depth,
+            ty,
+            &mut constraints,
+        )?;
 
         // "outlives" represent types/regions that may be touched
         // by a destructor.
@@ -196,10 +203,10 @@ pub fn compute_dropck_outlives_inner<'tcx>(
 
 /// Returns a set of constraints that needs to be satisfied in
 /// order for `ty` to be valid for destruction.
-#[instrument(level = "debug", skip(tcx, param_env, span, constraints))]
+#[instrument(level = "debug", skip(tcx, typing_env, span, constraints))]
 pub fn dtorck_constraint_for_ty_inner<'tcx>(
     tcx: TyCtxt<'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
+    typing_env: ty::TypingEnv<'tcx>,
     span: Span,
     depth: usize,
     ty: Ty<'tcx>,
@@ -234,20 +241,20 @@ pub fn dtorck_constraint_for_ty_inner<'tcx>(
         ty::Pat(ety, _) | ty::Array(ety, _) | ty::Slice(ety) => {
             // single-element containers, behave like their element
             rustc_data_structures::stack::ensure_sufficient_stack(|| {
-                dtorck_constraint_for_ty_inner(tcx, param_env, span, depth + 1, *ety, constraints)
+                dtorck_constraint_for_ty_inner(tcx, typing_env, span, depth + 1, *ety, constraints)
             })?;
         }
 
         ty::Tuple(tys) => rustc_data_structures::stack::ensure_sufficient_stack(|| {
             for ty in tys.iter() {
-                dtorck_constraint_for_ty_inner(tcx, param_env, span, depth + 1, ty, constraints)?;
+                dtorck_constraint_for_ty_inner(tcx, typing_env, span, depth + 1, ty, constraints)?;
             }
             Ok::<_, NoSolution>(())
         })?,
 
         ty::Closure(_, args) => rustc_data_structures::stack::ensure_sufficient_stack(|| {
             for ty in args.as_closure().upvar_tys() {
-                dtorck_constraint_for_ty_inner(tcx, param_env, span, depth + 1, ty, constraints)?;
+                dtorck_constraint_for_ty_inner(tcx, typing_env, span, depth + 1, ty, constraints)?;
             }
             Ok::<_, NoSolution>(())
         })?,
@@ -257,7 +264,7 @@ pub fn dtorck_constraint_for_ty_inner<'tcx>(
                 for ty in args.as_coroutine_closure().upvar_tys() {
                     dtorck_constraint_for_ty_inner(
                         tcx,
-                        param_env,
+                        typing_env,
                         span,
                         depth + 1,
                         ty,
@@ -296,7 +303,7 @@ pub fn dtorck_constraint_for_ty_inner<'tcx>(
             // While we conservatively assume that all coroutines require drop
             // to avoid query cycles during MIR building, we can check the actual
             // witness during borrowck to avoid unnecessary liveness constraints.
-            if args.witness().needs_drop(tcx, tcx.erase_regions(param_env)) {
+            if args.witness().needs_drop(tcx, tcx.erase_regions(typing_env)) {
                 constraints.outlives.extend(args.upvar_tys().iter().map(ty::GenericArg::from));
                 constraints.outlives.push(args.resume_ty().into());
             }
diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
index bf3f83ec827..1e0c487c4d4 100644
--- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
@@ -1224,16 +1224,20 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         // The regions of a type don't affect the size of the type
         let tcx = self.tcx();
         let self_ty = tcx.instantiate_bound_regions_with_erased(obligation.predicate.self_ty());
-        // We should erase regions from both the param-env and type, since both
-        // may have infer regions. Specifically, after canonicalizing and instantiating,
-        // early bound regions turn into region vars in both the new and old solver.
-        let key = tcx.erase_regions(obligation.param_env.and(self_ty));
+
         // But if there are inference variables, we have to wait until it's resolved.
-        if key.has_non_region_infer() {
+        if (obligation.param_env, self_ty).has_non_region_infer() {
             candidates.ambiguous = true;
             return;
         }
 
+        // We should erase regions from both the param-env and type, since both
+        // may have infer regions. Specifically, after canonicalizing and instantiating,
+        // early bound regions turn into region vars in both the new and old solver.
+        let key = self.infcx.pseudo_canonicalize_query(
+            tcx.erase_regions(obligation.param_env),
+            tcx.erase_regions(self_ty),
+        );
         if let Ok(layout) = tcx.layout_of(key)
             && layout.layout.is_pointer_like(&tcx.data_layout)
         {
diff --git a/compiler/rustc_trait_selection/src/traits/vtable.rs b/compiler/rustc_trait_selection/src/traits/vtable.rs
index bb56d6eaf54..8352d31d13a 100644
--- a/compiler/rustc_trait_selection/src/traits/vtable.rs
+++ b/compiler/rustc_trait_selection/src/traits/vtable.rs
@@ -276,8 +276,10 @@ fn vtable_entries<'tcx>(
                     // The trait type may have higher-ranked lifetimes in it;
                     // erase them if they appear, so that we get the type
                     // at some particular call site.
-                    let args =
-                        tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), args);
+                    let args = tcx.normalize_erasing_late_bound_regions(
+                        ty::TypingEnv::fully_monomorphized(),
+                        args,
+                    );
 
                     // It's possible that the method relies on where-clauses that
                     // do not hold for this particular set of type parameters.
@@ -294,7 +296,7 @@ fn vtable_entries<'tcx>(
 
                     let instance = ty::Instance::expect_resolve_for_vtable(
                         tcx,
-                        ty::ParamEnv::reveal_all(),
+                        ty::TypingEnv::fully_monomorphized(),
                         def_id,
                         args,
                         DUMMY_SP,
diff --git a/compiler/rustc_traits/src/codegen.rs b/compiler/rustc_traits/src/codegen.rs
index d8c1c50d79a..57225df0819 100644
--- a/compiler/rustc_traits/src/codegen.rs
+++ b/compiler/rustc_traits/src/codegen.rs
@@ -6,7 +6,7 @@
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_middle::bug;
 use rustc_middle::traits::CodegenObligationError;
-use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt, TypingMode};
+use rustc_middle::ty::{self, PseudoCanonicalInput, TyCtxt, TypeVisitableExt};
 use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
 use rustc_trait_selection::traits::{
     ImplSource, Obligation, ObligationCause, ObligationCtxt, ScrubbedTraitError, SelectionContext,
@@ -23,14 +23,15 @@ use tracing::debug;
 /// This also expects that `trait_ref` is fully normalized.
 pub(crate) fn codegen_select_candidate<'tcx>(
     tcx: TyCtxt<'tcx>,
-    (param_env, trait_ref): (ty::ParamEnv<'tcx>, ty::TraitRef<'tcx>),
+    key: PseudoCanonicalInput<'tcx, ty::TraitRef<'tcx>>,
 ) -> Result<&'tcx ImplSource<'tcx, ()>, CodegenObligationError> {
+    let PseudoCanonicalInput { typing_env, value: trait_ref } = key;
     // We expect the input to be fully normalized.
-    debug_assert_eq!(trait_ref, tcx.normalize_erasing_regions(param_env, trait_ref));
+    debug_assert_eq!(trait_ref, tcx.normalize_erasing_regions(typing_env, trait_ref));
 
     // Do the initial selection for the obligation. This yields the
     // shallow result we are looking for -- that is, what specific impl.
-    let infcx = tcx.infer_ctxt().ignoring_regions().build(TypingMode::from_param_env(param_env));
+    let (infcx, param_env) = tcx.infer_ctxt().ignoring_regions().build_with_typing_env(typing_env);
     let mut selcx = SelectionContext::new(&infcx);
 
     let obligation_cause = ObligationCause::dummy();
diff --git a/compiler/rustc_traits/src/dropck_outlives.rs b/compiler/rustc_traits/src/dropck_outlives.rs
index 4e5309eea28..51e4dbe81b3 100644
--- a/compiler/rustc_traits/src/dropck_outlives.rs
+++ b/compiler/rustc_traits/src/dropck_outlives.rs
@@ -5,7 +5,7 @@ use rustc_infer::infer::canonical::{Canonical, QueryResponse};
 use rustc_middle::bug;
 use rustc_middle::query::Providers;
 use rustc_middle::traits::query::{DropckConstraint, DropckOutlivesResult};
-use rustc_middle::ty::{GenericArgs, TyCtxt};
+use rustc_middle::ty::{self, GenericArgs, TyCtxt};
 use rustc_trait_selection::infer::InferCtxtBuilderExt;
 use rustc_trait_selection::traits::query::dropck_outlives::{
     compute_dropck_outlives_inner, dtorck_constraint_for_ty_inner,
@@ -35,7 +35,7 @@ pub(crate) fn adt_dtorck_constraint(
 ) -> Result<&DropckConstraint<'_>, NoSolution> {
     let def = tcx.adt_def(def_id);
     let span = tcx.def_span(def_id);
-    let param_env = tcx.param_env(def_id);
+    let typing_env = ty::TypingEnv::non_body_analysis(tcx, def_id);
     debug!("dtorck_constraint: {:?}", def);
 
     if def.is_manually_drop() {
@@ -57,7 +57,7 @@ pub(crate) fn adt_dtorck_constraint(
     let mut result = DropckConstraint::empty();
     for field in def.all_fields() {
         let fty = tcx.type_of(field.did).instantiate_identity();
-        dtorck_constraint_for_ty_inner(tcx, param_env, span, 0, fty, &mut result)?;
+        dtorck_constraint_for_ty_inner(tcx, typing_env, span, 0, fty, &mut result)?;
     }
     result.outlives.extend(tcx.destructor_constraints(def));
     dedup_dtorck_constraint(&mut result);
diff --git a/compiler/rustc_traits/src/normalize_erasing_regions.rs b/compiler/rustc_traits/src/normalize_erasing_regions.rs
index d79059a39a1..68ff66bbce7 100644
--- a/compiler/rustc_traits/src/normalize_erasing_regions.rs
+++ b/compiler/rustc_traits/src/normalize_erasing_regions.rs
@@ -1,7 +1,7 @@
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_middle::query::Providers;
 use rustc_middle::traits::query::NoSolution;
-use rustc_middle::ty::{self, ParamEnvAnd, TyCtxt, TypeFoldable, TypeVisitableExt, TypingMode};
+use rustc_middle::ty::{self, PseudoCanonicalInput, TyCtxt, TypeFoldable, TypeVisitableExt};
 use rustc_trait_selection::traits::query::normalize::QueryNormalizeExt;
 use rustc_trait_selection::traits::{Normalized, ObligationCause};
 use tracing::debug;
@@ -19,10 +19,10 @@ pub(crate) fn provide(p: &mut Providers) {
 
 fn try_normalize_after_erasing_regions<'tcx, T: TypeFoldable<TyCtxt<'tcx>> + PartialEq + Copy>(
     tcx: TyCtxt<'tcx>,
-    goal: ParamEnvAnd<'tcx, T>,
+    goal: PseudoCanonicalInput<'tcx, T>,
 ) -> Result<T, NoSolution> {
-    let ParamEnvAnd { param_env, value } = goal;
-    let infcx = tcx.infer_ctxt().build(TypingMode::from_param_env(param_env));
+    let PseudoCanonicalInput { typing_env, value } = goal;
+    let (infcx, param_env) = tcx.infer_ctxt().build_with_typing_env(typing_env);
     let cause = ObligationCause::dummy();
     match infcx.at(&cause, param_env).query_normalize(value) {
         Ok(Normalized { value: normalized_value, obligations: normalized_obligations }) => {
diff --git a/compiler/rustc_transmute/src/maybe_transmutable/mod.rs b/compiler/rustc_transmute/src/maybe_transmutable/mod.rs
index 9dabcea706f..023c8fad781 100644
--- a/compiler/rustc_transmute/src/maybe_transmutable/mod.rs
+++ b/compiler/rustc_transmute/src/maybe_transmutable/mod.rs
@@ -31,7 +31,7 @@ where
 #[cfg(feature = "rustc")]
 mod rustc {
     use rustc_middle::ty::layout::LayoutCx;
-    use rustc_middle::ty::{ParamEnv, Ty, TyCtxt};
+    use rustc_middle::ty::{Ty, TyCtxt, TypingEnv};
 
     use super::*;
     use crate::layout::tree::rustc::Err;
@@ -43,7 +43,7 @@ mod rustc {
         pub(crate) fn answer(self) -> Answer<<TyCtxt<'tcx> as QueryContext>::Ref> {
             let Self { src, dst, assume, context } = self;
 
-            let layout_cx = LayoutCx::new(context, ParamEnv::reveal_all());
+            let layout_cx = LayoutCx::new(context, TypingEnv::fully_monomorphized());
 
             // Convert `src` and `dst` from their rustc representations, to `Tree`-based
             // representations.
diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs
index 0184e93acf1..e2283383196 100644
--- a/compiler/rustc_ty_utils/src/abi.rs
+++ b/compiler/rustc_ty_utils/src/abi.rs
@@ -7,7 +7,7 @@ use rustc_hir::lang_items::LangItem;
 use rustc_middle::bug;
 use rustc_middle::query::Providers;
 use rustc_middle::ty::layout::{
-    FnAbiError, HasParamEnv, HasTyCtxt, LayoutCx, LayoutOf, TyAndLayout, fn_can_unwind,
+    FnAbiError, HasTyCtxt, HasTypingEnv, LayoutCx, LayoutOf, TyAndLayout, fn_can_unwind,
 };
 use rustc_middle::ty::{self, InstanceKind, Ty, TyCtxt};
 use rustc_session::config::OptLevel;
@@ -26,11 +26,11 @@ pub(crate) fn provide(providers: &mut Providers) {
 // for `Instance` (e.g. typeck would use `Ty::fn_sig` instead),
 // or should go through `FnAbi` instead, to avoid losing any
 // adjustments `fn_abi_of_instance` might be performing.
-#[tracing::instrument(level = "debug", skip(tcx, param_env))]
+#[tracing::instrument(level = "debug", skip(tcx, typing_env))]
 fn fn_sig_for_fn_abi<'tcx>(
     tcx: TyCtxt<'tcx>,
     instance: ty::Instance<'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
+    typing_env: ty::TypingEnv<'tcx>,
 ) -> ty::PolyFnSig<'tcx> {
     if let InstanceKind::ThreadLocalShim(..) = instance.def {
         return ty::Binder::dummy(tcx.mk_fn_sig(
@@ -42,7 +42,7 @@ fn fn_sig_for_fn_abi<'tcx>(
         ));
     }
 
-    let ty = instance.ty(tcx, param_env);
+    let ty = instance.ty(tcx, typing_env);
     match *ty.kind() {
         ty::FnDef(..) => {
             // HACK(davidtwco,eddyb): This is a workaround for polymorphization considering
@@ -56,7 +56,10 @@ fn fn_sig_for_fn_abi<'tcx>(
                 ty::FnDef(def_id, args) => tcx
                     .fn_sig(def_id)
                     .map_bound(|fn_sig| {
-                        tcx.normalize_erasing_regions(tcx.param_env(def_id), fn_sig)
+                        tcx.normalize_erasing_regions(
+                            ty::TypingEnv::non_body_analysis(tcx, def_id),
+                            fn_sig,
+                        )
                     })
                     .instantiate(tcx, args),
                 _ => unreachable!(),
@@ -329,27 +332,26 @@ fn conv_from_spec_abi(tcx: TyCtxt<'_>, abi: ExternAbi, c_variadic: bool) -> Conv
 
 fn fn_abi_of_fn_ptr<'tcx>(
     tcx: TyCtxt<'tcx>,
-    query: ty::ParamEnvAnd<'tcx, (ty::PolyFnSig<'tcx>, &'tcx ty::List<Ty<'tcx>>)>,
+    query: ty::PseudoCanonicalInput<'tcx, (ty::PolyFnSig<'tcx>, &'tcx ty::List<Ty<'tcx>>)>,
 ) -> Result<&'tcx FnAbi<'tcx, Ty<'tcx>>, &'tcx FnAbiError<'tcx>> {
-    let (param_env, (sig, extra_args)) = query.into_parts();
-
-    let cx = LayoutCx::new(tcx, param_env);
+    let ty::PseudoCanonicalInput { typing_env, value: (sig, extra_args) } = query;
+    let cx = LayoutCx::new(tcx, typing_env);
     fn_abi_new_uncached(&cx, sig, extra_args, None, None, false)
 }
 
 fn fn_abi_of_instance<'tcx>(
     tcx: TyCtxt<'tcx>,
-    query: ty::ParamEnvAnd<'tcx, (ty::Instance<'tcx>, &'tcx ty::List<Ty<'tcx>>)>,
+    query: ty::PseudoCanonicalInput<'tcx, (ty::Instance<'tcx>, &'tcx ty::List<Ty<'tcx>>)>,
 ) -> Result<&'tcx FnAbi<'tcx, Ty<'tcx>>, &'tcx FnAbiError<'tcx>> {
-    let (param_env, (instance, extra_args)) = query.into_parts();
+    let ty::PseudoCanonicalInput { typing_env, value: (instance, extra_args) } = query;
 
-    let sig = fn_sig_for_fn_abi(tcx, instance, param_env);
+    let sig = fn_sig_for_fn_abi(tcx, instance, typing_env);
 
     let caller_location =
         instance.def.requires_caller_location(tcx).then(|| tcx.caller_location_ty());
 
     fn_abi_new_uncached(
-        &LayoutCx::new(tcx, param_env),
+        &LayoutCx::new(tcx, typing_env),
         sig,
         extra_args,
         caller_location,
@@ -395,7 +397,7 @@ fn adjust_for_rust_scalar<'tcx>(
             Some(kind)
         } else if let Some(pointee) = drop_target_pointee {
             // The argument to `drop_in_place` is semantically equivalent to a mutable reference.
-            Some(PointerKind::MutableRef { unpin: pointee.is_unpin(tcx, cx.param_env()) })
+            Some(PointerKind::MutableRef { unpin: pointee.is_unpin(tcx, cx.typing_env.param_env) })
         } else {
             None
         };
@@ -542,7 +544,7 @@ fn fn_abi_sanity_check<'tcx>(
                 // With metadata. Must be unsized and not on the stack.
                 assert!(arg.layout.is_unsized() && !on_stack);
                 // Also, must not be `extern` type.
-                let tail = tcx.struct_tail_for_codegen(arg.layout.ty, cx.param_env());
+                let tail = tcx.struct_tail_for_codegen(arg.layout.ty, cx.typing_env);
                 if matches!(tail.kind(), ty::Foreign(..)) {
                     // These types do not have metadata, so having `meta_attrs` is bogus.
                     // Conceptually, unsized arguments must be copied around, which requires dynamically
@@ -573,7 +575,7 @@ fn fn_abi_new_uncached<'tcx>(
     force_thin_self_ptr: bool,
 ) -> Result<&'tcx FnAbi<'tcx, Ty<'tcx>>, &'tcx FnAbiError<'tcx>> {
     let tcx = cx.tcx();
-    let sig = tcx.normalize_erasing_late_bound_regions(cx.param_env, sig);
+    let sig = tcx.normalize_erasing_late_bound_regions(cx.typing_env, sig);
 
     let conv = conv_from_spec_abi(cx.tcx(), sig.abi, sig.c_variadic);
 
@@ -744,7 +746,7 @@ fn fn_abi_adjust_for_abi<'tcx>(
 
 #[tracing::instrument(level = "debug", skip(cx))]
 fn make_thin_self_ptr<'tcx>(
-    cx: &(impl HasTyCtxt<'tcx> + HasParamEnv<'tcx>),
+    cx: &(impl HasTyCtxt<'tcx> + HasTypingEnv<'tcx>),
     layout: TyAndLayout<'tcx>,
 ) -> TyAndLayout<'tcx> {
     let tcx = cx.tcx();
@@ -784,6 +786,6 @@ fn make_thin_self_ptr<'tcx>(
 
         // NOTE(eddyb) using an empty `ParamEnv`, and `unwrap`-ing the `Result`
         // should always work because the type is always `*mut ()`.
-        ..tcx.layout_of(ty::ParamEnv::reveal_all().and(unit_ptr_ty)).unwrap()
+        ..tcx.layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(unit_ptr_ty)).unwrap()
     }
 }
diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs
index 1d8a0880760..84fc03a8f13 100644
--- a/compiler/rustc_ty_utils/src/instance.rs
+++ b/compiler/rustc_ty_utils/src/instance.rs
@@ -6,7 +6,9 @@ use rustc_middle::bug;
 use rustc_middle::query::Providers;
 use rustc_middle::traits::{BuiltinImplSource, CodegenObligationError};
 use rustc_middle::ty::util::AsyncDropGlueMorphology;
-use rustc_middle::ty::{self, GenericArgsRef, Instance, TyCtxt, TypeVisitableExt, TypingMode};
+use rustc_middle::ty::{
+    self, GenericArgsRef, Instance, PseudoCanonicalInput, TyCtxt, TypeVisitableExt,
+};
 use rustc_span::sym;
 use rustc_trait_selection::traits;
 use rustc_type_ir::ClosureKind;
@@ -17,18 +19,18 @@ use crate::errors::UnexpectedFnPtrAssociatedItem;
 
 fn resolve_instance_raw<'tcx>(
     tcx: TyCtxt<'tcx>,
-    key: ty::ParamEnvAnd<'tcx, (DefId, GenericArgsRef<'tcx>)>,
+    key: ty::PseudoCanonicalInput<'tcx, (DefId, GenericArgsRef<'tcx>)>,
 ) -> Result<Option<Instance<'tcx>>, ErrorGuaranteed> {
-    let (param_env, (def_id, args)) = key.into_parts();
+    let PseudoCanonicalInput { typing_env, value: (def_id, args) } = key;
 
     let result = if let Some(trait_def_id) = tcx.trait_of_item(def_id) {
-        debug!(" => associated item, attempting to find impl in param_env {:#?}", param_env);
+        debug!(" => associated item, attempting to find impl in typing_env {:#?}", typing_env);
         resolve_associated_item(
             tcx,
             def_id,
-            param_env,
+            typing_env,
             trait_def_id,
-            tcx.normalize_erasing_regions(param_env, args),
+            tcx.normalize_erasing_regions(typing_env, args),
         )
     } else {
         let def = if tcx.intrinsic(def_id).is_some() {
@@ -37,7 +39,7 @@ fn resolve_instance_raw<'tcx>(
         } else if tcx.is_lang_item(def_id, LangItem::DropInPlace) {
             let ty = args.type_at(0);
 
-            if ty.needs_drop(tcx, param_env) {
+            if ty.needs_drop(tcx, typing_env) {
                 debug!(" => nontrivial drop glue");
                 match *ty.kind() {
                     ty::Closure(..)
@@ -93,15 +95,16 @@ fn resolve_instance_raw<'tcx>(
 fn resolve_associated_item<'tcx>(
     tcx: TyCtxt<'tcx>,
     trait_item_id: DefId,
-    param_env: ty::ParamEnv<'tcx>,
+    typing_env: ty::TypingEnv<'tcx>,
     trait_id: DefId,
     rcvr_args: GenericArgsRef<'tcx>,
 ) -> Result<Option<Instance<'tcx>>, ErrorGuaranteed> {
-    debug!(?trait_item_id, ?param_env, ?trait_id, ?rcvr_args, "resolve_associated_item");
+    debug!(?trait_item_id, ?typing_env, ?trait_id, ?rcvr_args, "resolve_associated_item");
 
     let trait_ref = ty::TraitRef::from_method(tcx, trait_id, rcvr_args);
 
-    let vtbl = match tcx.codegen_select_candidate((param_env, trait_ref)) {
+    let input = typing_env.as_query_input(trait_ref);
+    let vtbl = match tcx.codegen_select_candidate(input) {
         Ok(vtbl) => vtbl,
         Err(
             CodegenObligationError::Ambiguity
@@ -116,7 +119,7 @@ fn resolve_associated_item<'tcx>(
         traits::ImplSource::UserDefined(impl_data) => {
             debug!(
                 "resolving ImplSource::UserDefined: {:?}, {:?}, {:?}, {:?}",
-                param_env, trait_item_id, rcvr_args, impl_data
+                typing_env, trait_item_id, rcvr_args, impl_data
             );
             assert!(!rcvr_args.has_infer());
             assert!(!trait_ref.has_infer());
@@ -129,8 +132,9 @@ fn resolve_associated_item<'tcx>(
                 .unwrap_or_else(|| {
                     bug!("{:?} not found in {:?}", trait_item_id, impl_data.impl_def_id);
                 });
-            let infcx = tcx.infer_ctxt().build(TypingMode::PostAnalysis);
-            let param_env = param_env.with_reveal_all_normalized(tcx);
+
+            let typing_env = typing_env.with_reveal_all_normalized(tcx);
+            let (infcx, param_env) = tcx.infer_ctxt().build_with_typing_env(typing_env);
             let args = rcvr_args.rebase_onto(tcx, trait_def_id, impl_data.args);
             let args = translate_args(
                 &infcx,
diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs
index 63421dfdce6..02ee3f32915 100644
--- a/compiler/rustc_ty_utils/src/layout.rs
+++ b/compiler/rustc_ty_utils/src/layout.rs
@@ -19,7 +19,8 @@ use rustc_middle::ty::layout::{
 };
 use rustc_middle::ty::print::with_no_trimmed_paths;
 use rustc_middle::ty::{
-    self, AdtDef, CoroutineArgsExt, EarlyBinder, GenericArgsRef, Ty, TyCtxt, TypeVisitableExt,
+    self, AdtDef, CoroutineArgsExt, EarlyBinder, GenericArgsRef, PseudoCanonicalInput, Ty, TyCtxt,
+    TypeVisitableExt,
 };
 use rustc_session::{DataTypeKind, FieldInfo, FieldKind, SizeKind, VariantInfo};
 use rustc_span::sym;
@@ -40,22 +41,22 @@ pub(crate) fn provide(providers: &mut Providers) {
 #[instrument(skip(tcx, query), level = "debug")]
 fn layout_of<'tcx>(
     tcx: TyCtxt<'tcx>,
-    query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>,
+    query: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>,
 ) -> Result<TyAndLayout<'tcx>, &'tcx LayoutError<'tcx>> {
-    let (param_env, ty) = query.into_parts();
+    let PseudoCanonicalInput { typing_env, value: ty } = query;
     debug!(?ty);
 
     // Optimization: We convert to RevealAll and convert opaque types in the where bounds
     // to their hidden types. This reduces overall uncached invocations of `layout_of` and
     // is thus a small performance improvement.
-    let param_env = param_env.with_reveal_all_normalized(tcx);
+    let typing_env = typing_env.with_reveal_all_normalized(tcx);
     let unnormalized_ty = ty;
 
     // FIXME: We might want to have two different versions of `layout_of`:
     // One that can be called after typecheck has completed and can use
     // `normalize_erasing_regions` here and another one that can be called
     // before typecheck has completed and uses `try_normalize_erasing_regions`.
-    let ty = match tcx.try_normalize_erasing_regions(param_env, ty) {
+    let ty = match tcx.try_normalize_erasing_regions(typing_env, ty) {
         Ok(t) => t,
         Err(normalization_error) => {
             return Err(tcx
@@ -66,10 +67,10 @@ fn layout_of<'tcx>(
 
     if ty != unnormalized_ty {
         // Ensure this layout is also cached for the normalized type.
-        return tcx.layout_of(param_env.and(ty));
+        return tcx.layout_of(typing_env.as_query_input(ty));
     }
 
-    let cx = LayoutCx::new(tcx, param_env);
+    let cx = LayoutCx::new(tcx, typing_env);
 
     let layout = layout_of_uncached(&cx, ty)?;
     let layout = TyAndLayout { ty, layout };
@@ -104,7 +105,7 @@ fn map_error<'tcx>(
             // This is sometimes not a compile error if there are trivially false where clauses.
             // See `tests/ui/layout/trivial-bounds-sized.rs` for an example.
             assert!(field.layout.is_unsized(), "invalid layout error {err:#?}");
-            if !field.ty.is_sized(cx.tcx(), cx.param_env) {
+            if !field.ty.is_sized(cx.tcx(), cx.typing_env.param_env) {
                 cx.tcx().dcx().delayed_bug(format!(
                     "encountered unexpected unsized field in layout of {ty:?}: {field:#?}"
                 ));
@@ -152,7 +153,6 @@ fn layout_of_uncached<'tcx>(
     }
 
     let tcx = cx.tcx();
-    let param_env = cx.param_env;
     let dl = cx.data_layout();
     let scalar_unit = |value: Primitive| {
         let size = value.size(dl);
@@ -178,12 +178,12 @@ fn layout_of_uncached<'tcx>(
                     {
                         if let Some(start) = start {
                             scalar.valid_range_mut().start = start
-                                .try_to_bits(tcx, param_env)
+                                .try_to_bits(tcx, cx.typing_env)
                                 .ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?;
                         }
                         if let Some(end) = end {
                             let mut end = end
-                                .try_to_bits(tcx, param_env)
+                                .try_to_bits(tcx, cx.typing_env)
                                 .ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?;
                             if !include_end {
                                 end = end.wrapping_sub(1);
@@ -235,8 +235,8 @@ fn layout_of_uncached<'tcx>(
                 data_ptr.valid_range_mut().start = 1;
             }
 
-            let pointee = tcx.normalize_erasing_regions(param_env, pointee);
-            if pointee.is_sized(tcx, param_env) {
+            let pointee = tcx.normalize_erasing_regions(cx.typing_env, pointee);
+            if pointee.is_sized(tcx, cx.typing_env.param_env) {
                 return Ok(tcx.mk_layout(LayoutData::scalar(cx, data_ptr)));
             }
 
@@ -247,7 +247,7 @@ fn layout_of_uncached<'tcx>(
             {
                 let pointee_metadata = Ty::new_projection(tcx, metadata_def_id, [pointee]);
                 let metadata_ty =
-                    match tcx.try_normalize_erasing_regions(param_env, pointee_metadata) {
+                    match tcx.try_normalize_erasing_regions(cx.typing_env, pointee_metadata) {
                         Ok(metadata_ty) => metadata_ty,
                         Err(mut err) => {
                             // Usually `<Ty as Pointee>::Metadata` can't be normalized because
@@ -259,7 +259,7 @@ fn layout_of_uncached<'tcx>(
                             // that is an alias, which is likely the cause of the normalization
                             // error.
                             match tcx.try_normalize_erasing_regions(
-                                param_env,
+                                cx.typing_env,
                                 tcx.struct_tail_raw(pointee, |ty| ty, || {}),
                             ) {
                                 Ok(_) => {}
@@ -283,7 +283,7 @@ fn layout_of_uncached<'tcx>(
 
                 metadata
             } else {
-                let unsized_part = tcx.struct_tail_for_codegen(pointee, param_env);
+                let unsized_part = tcx.struct_tail_for_codegen(pointee, cx.typing_env);
 
                 match unsized_part.kind() {
                     ty::Foreign(..) => {
@@ -316,7 +316,7 @@ fn layout_of_uncached<'tcx>(
         // Arrays and slices.
         ty::Array(element, mut count) => {
             if count.has_aliases() {
-                count = tcx.normalize_erasing_regions(param_env, count);
+                count = tcx.normalize_erasing_regions(cx.typing_env, count);
                 if count.has_aliases() {
                     return Err(error(cx, LayoutError::Unknown(ty)));
                 }
@@ -331,7 +331,7 @@ fn layout_of_uncached<'tcx>(
                 .checked_mul(count, dl)
                 .ok_or_else(|| error(cx, LayoutError::SizeOverflow(ty)))?;
 
-            let abi = if count != 0 && ty.is_privately_uninhabited(tcx, param_env) {
+            let abi = if count != 0 && ty.is_privately_uninhabited(tcx, cx.typing_env) {
                 BackendRepr::Uninhabited
             } else {
                 BackendRepr::Memory { sized: true }
@@ -620,7 +620,11 @@ fn layout_of_uncached<'tcx>(
             // If the struct tail is sized and can be unsized, check that unsizing doesn't move the fields around.
             if cfg!(debug_assertions)
                 && maybe_unsized
-                && def.non_enum_variant().tail().ty(tcx, args).is_sized(tcx, cx.param_env)
+                && def
+                    .non_enum_variant()
+                    .tail()
+                    .ty(tcx, args)
+                    .is_sized(tcx, cx.typing_env.param_env)
             {
                 let mut variants = variants;
                 let tail_replacement = cx.layout_of(Ty::new_slice(tcx, tcx.types.u8)).unwrap();
@@ -1024,7 +1028,7 @@ fn record_layout_for_printing<'tcx>(cx: &LayoutCx<'tcx>, layout: TyAndLayout<'tc
     // Ignore layouts that are done with non-empty environments or
     // non-monomorphic layouts, as the user only wants to see the stuff
     // resulting from the final codegen session.
-    if layout.ty.has_non_region_param() || !cx.param_env.caller_bounds().is_empty() {
+    if layout.ty.has_non_region_param() || !cx.typing_env.param_env.caller_bounds().is_empty() {
         return;
     }
 
diff --git a/compiler/rustc_ty_utils/src/layout/invariant.rs b/compiler/rustc_ty_utils/src/layout/invariant.rs
index fc05dd8256b..26ea81daf78 100644
--- a/compiler/rustc_ty_utils/src/layout/invariant.rs
+++ b/compiler/rustc_ty_utils/src/layout/invariant.rs
@@ -9,7 +9,7 @@ pub(super) fn partially_check_layout<'tcx>(cx: &LayoutCx<'tcx>, layout: &TyAndLa
     let tcx = cx.tcx();
 
     // Type-level uninhabitedness should always imply ABI uninhabitedness.
-    if layout.ty.is_privately_uninhabited(tcx, cx.param_env) {
+    if layout.ty.is_privately_uninhabited(tcx, cx.typing_env) {
         assert!(layout.is_uninhabited());
     }
 
diff --git a/compiler/rustc_ty_utils/src/needs_drop.rs b/compiler/rustc_ty_utils/src/needs_drop.rs
index 5fecbd310b7..d462dbd9416 100644
--- a/compiler/rustc_ty_utils/src/needs_drop.rs
+++ b/compiler/rustc_ty_utils/src/needs_drop.rs
@@ -14,14 +14,17 @@ use crate::errors::NeedsDropOverflow;
 
 type NeedsDropResult<T> = Result<T, AlwaysRequiresDrop>;
 
-fn needs_drop_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
+fn needs_drop_raw<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    query: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>,
+) -> bool {
     // If we don't know a type doesn't need drop, for example if it's a type
     // parameter without a `Copy` bound, then we conservatively return that it
     // needs drop.
     let adt_has_dtor =
         |adt_def: ty::AdtDef<'tcx>| adt_def.destructor(tcx).map(|_| DtorType::Significant);
-    let res = drop_tys_helper(tcx, query.value, query.param_env, adt_has_dtor, false)
-        .filter(filter_array_elements(tcx, query.param_env))
+    let res = drop_tys_helper(tcx, query.value, query.typing_env, adt_has_dtor, false)
+        .filter(filter_array_elements(tcx, query.typing_env))
         .next()
         .is_some();
 
@@ -29,14 +32,17 @@ fn needs_drop_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>
     res
 }
 
-fn needs_async_drop_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
+fn needs_async_drop_raw<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    query: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>,
+) -> bool {
     // If we don't know a type doesn't need async drop, for example if it's a
     // type parameter without a `Copy` bound, then we conservatively return that
     // it needs async drop.
     let adt_has_async_dtor =
         |adt_def: ty::AdtDef<'tcx>| adt_def.async_destructor(tcx).map(|_| DtorType::Significant);
-    let res = drop_tys_helper(tcx, query.value, query.param_env, adt_has_async_dtor, false)
-        .filter(filter_array_elements(tcx, query.param_env))
+    let res = drop_tys_helper(tcx, query.value, query.typing_env, adt_has_async_dtor, false)
+        .filter(filter_array_elements(tcx, query.typing_env))
         .next()
         .is_some();
 
@@ -50,11 +56,11 @@ fn needs_async_drop_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty
 /// logic that is easier to follow while not repeating any checks that may thus diverge.
 fn filter_array_elements<'tcx>(
     tcx: TyCtxt<'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
+    typing_env: ty::TypingEnv<'tcx>,
 ) -> impl Fn(&Result<Ty<'tcx>, AlwaysRequiresDrop>) -> bool {
     move |ty| match ty {
         Ok(ty) => match *ty.kind() {
-            ty::Array(elem, _) => tcx.needs_drop_raw(param_env.and(elem)),
+            ty::Array(elem, _) => tcx.needs_drop_raw(typing_env.as_query_input(elem)),
             _ => true,
         },
         Err(AlwaysRequiresDrop) => true,
@@ -63,16 +69,16 @@ fn filter_array_elements<'tcx>(
 
 fn has_significant_drop_raw<'tcx>(
     tcx: TyCtxt<'tcx>,
-    query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>,
+    query: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>,
 ) -> bool {
     let res = drop_tys_helper(
         tcx,
         query.value,
-        query.param_env,
+        query.typing_env,
         adt_consider_insignificant_dtor(tcx),
         true,
     )
-    .filter(filter_array_elements(tcx, query.param_env))
+    .filter(filter_array_elements(tcx, query.typing_env))
     .next()
     .is_some();
     debug!("has_significant_drop_raw({:?}) = {:?}", query, res);
@@ -81,7 +87,7 @@ fn has_significant_drop_raw<'tcx>(
 
 struct NeedsDropTypes<'tcx, F> {
     tcx: TyCtxt<'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
+    typing_env: ty::TypingEnv<'tcx>,
     // Whether to reveal coroutine witnesses, this is set
     // to `false` unless we compute `needs_drop` for a coroutine witness.
     reveal_coroutine_witnesses: bool,
@@ -99,7 +105,7 @@ struct NeedsDropTypes<'tcx, F> {
 impl<'tcx, F> NeedsDropTypes<'tcx, F> {
     fn new(
         tcx: TyCtxt<'tcx>,
-        param_env: ty::ParamEnv<'tcx>,
+        typing_env: ty::TypingEnv<'tcx>,
         ty: Ty<'tcx>,
         adt_components: F,
     ) -> Self {
@@ -107,7 +113,7 @@ impl<'tcx, F> NeedsDropTypes<'tcx, F> {
         seen_tys.insert(ty);
         Self {
             tcx,
-            param_env,
+            typing_env,
             reveal_coroutine_witnesses: false,
             seen_tys,
             query_ty: ty,
@@ -180,7 +186,7 @@ where
                         }
                     }
 
-                    _ if component.is_copy_modulo_regions(tcx, self.param_env) => (),
+                    _ if component.is_copy_modulo_regions(tcx, self.typing_env.param_env) => (),
 
                     ty::Closure(_, args) => {
                         for upvar in args.as_closure().upvar_tys() {
@@ -204,7 +210,7 @@ where
                         };
                         for required_ty in tys {
                             let required = tcx
-                                .try_normalize_erasing_regions(self.param_env, required_ty)
+                                .try_normalize_erasing_regions(self.typing_env, required_ty)
                                 .unwrap_or(required_ty);
 
                             queue_type(self, required);
@@ -271,7 +277,7 @@ enum DtorType {
 fn drop_tys_helper<'tcx>(
     tcx: TyCtxt<'tcx>,
     ty: Ty<'tcx>,
-    param_env: rustc_middle::ty::ParamEnv<'tcx>,
+    typing_env: ty::TypingEnv<'tcx>,
     adt_has_dtor: impl Fn(ty::AdtDef<'tcx>) -> Option<DtorType>,
     only_significant: bool,
 ) -> impl Iterator<Item = NeedsDropResult<Ty<'tcx>>> {
@@ -337,7 +343,7 @@ fn drop_tys_helper<'tcx>(
         .map(|v| v.into_iter())
     };
 
-    NeedsDropTypes::new(tcx, param_env, ty, adt_components)
+    NeedsDropTypes::new(tcx, typing_env, ty, adt_components)
 }
 
 fn adt_consider_insignificant_dtor<'tcx>(
@@ -375,7 +381,7 @@ fn adt_drop_tys<'tcx>(
     drop_tys_helper(
         tcx,
         tcx.type_of(def_id).instantiate_identity(),
-        tcx.param_env(def_id),
+        ty::TypingEnv::non_body_analysis(tcx, def_id),
         adt_has_dtor,
         false,
     )
@@ -392,7 +398,7 @@ fn adt_significant_drop_tys(
     drop_tys_helper(
         tcx,
         tcx.type_of(def_id).instantiate_identity(), // identical to `tcx.make_adt(def, identity_args)`
-        tcx.param_env(def_id),
+        ty::TypingEnv::non_body_analysis(tcx, def_id),
         adt_consider_insignificant_dtor(tcx),
         true,
     )
diff --git a/compiler/rustc_type_ir/src/infer_ctxt.rs b/compiler/rustc_type_ir/src/infer_ctxt.rs
index aadb64f45d7..105ae76708b 100644
--- a/compiler/rustc_type_ir/src/infer_ctxt.rs
+++ b/compiler/rustc_type_ir/src/infer_ctxt.rs
@@ -1,6 +1,7 @@
 use derive_where::derive_where;
 #[cfg(feature = "nightly")]
 use rustc_macros::{HashStable_NoContext, TyDecodable, TyEncodable};
+use rustc_type_ir_macros::{TypeFoldable_Generic, TypeVisitable_Generic};
 
 use crate::fold::TypeFoldable;
 use crate::inherent::*;
@@ -20,6 +21,7 @@ use crate::{self as ty, Interner};
 /// If neither of these functions are available, feel free to reach out to
 /// t-types for help.
 #[derive_where(Clone, Copy, Hash, PartialEq, Eq, Debug; I: Interner)]
+#[derive(TypeVisitable_Generic, TypeFoldable_Generic)]
 #[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))]
 pub enum TypingMode<I: Interner> {
     /// When checking whether impls overlap, we check whether any obligations
diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs
index 36ddddccfa2..f988f003c0f 100644
--- a/compiler/rustc_type_ir/src/interner.rs
+++ b/compiler/rustc_type_ir/src/interner.rs
@@ -13,7 +13,7 @@ use crate::lang_items::TraitSolverLangItem;
 use crate::relate::Relate;
 use crate::solve::{CanonicalInput, ExternalConstraintsData, PredefinedOpaquesData, QueryResult};
 use crate::visit::{Flags, TypeSuperVisitable, TypeVisitable};
-use crate::{self as ty, search_graph};
+use crate::{self as ty, TypingMode, search_graph};
 
 pub trait Interner:
     Sized
@@ -277,7 +277,12 @@ pub trait Interner:
     fn coroutine_is_gen(self, coroutine_def_id: Self::DefId) -> bool;
     fn coroutine_is_async_gen(self, coroutine_def_id: Self::DefId) -> bool;
 
-    fn layout_is_pointer_like(self, param_env: Self::ParamEnv, ty: Self::Ty) -> bool;
+    fn layout_is_pointer_like(
+        self,
+        typing_mode: TypingMode<Self>,
+        param_env: Self::ParamEnv,
+        ty: Self::Ty,
+    ) -> bool;
 
     type UnsizingParams: Deref<Target = BitSet<u32>>;
     fn unsizing_params_for_adt(self, adt_def_id: Self::DefId) -> Self::UnsizingParams;
diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs
index bb6dd1d2d30..ac3e4626ee5 100644
--- a/library/alloc/src/boxed.rs
+++ b/library/alloc/src/boxed.rs
@@ -1500,6 +1500,7 @@ impl<T: ?Sized, A: Allocator> Box<T, A> {
     /// [`as_ptr`]: Self::as_ptr
     #[unstable(feature = "box_as_ptr", issue = "129090")]
     #[rustc_never_returns_null_ptr]
+    #[cfg_attr(not(bootstrap), rustc_as_ptr)]
     #[inline]
     pub fn as_mut_ptr(b: &mut Self) -> *mut T {
         // This is a primitive deref, not going through `DerefMut`, and therefore not materializing
@@ -1548,6 +1549,7 @@ impl<T: ?Sized, A: Allocator> Box<T, A> {
     /// [`as_ptr`]: Self::as_ptr
     #[unstable(feature = "box_as_ptr", issue = "129090")]
     #[rustc_never_returns_null_ptr]
+    #[cfg_attr(not(bootstrap), rustc_as_ptr)]
     #[inline]
     pub fn as_ptr(b: &Self) -> *const T {
         // This is a primitive deref, not going through `DerefMut`, and therefore not materializing
diff --git a/library/alloc/src/collections/btree/map.rs b/library/alloc/src/collections/btree/map.rs
index 66353ccfa47..213924d1d02 100644
--- a/library/alloc/src/collections/btree/map.rs
+++ b/library/alloc/src/collections/btree/map.rs
@@ -677,7 +677,11 @@ impl<K, V, A: Allocator + Clone> BTreeMap<K, V, A> {
         }
     }
 
-    /// Returns the key-value pair corresponding to the supplied key.
+    /// Returns the key-value pair corresponding to the supplied key. This is
+    /// potentially useful:
+    /// - for key types where non-identical keys can be considered equal;
+    /// - for getting the `&K` stored key value from a borrowed `&Q` lookup key; or
+    /// - for getting a reference to a key with the same lifetime as the collection.
     ///
     /// The supplied key may be any borrowed form of the map's key type, but the ordering
     /// on the borrowed form *must* match the ordering on the key type.
@@ -685,12 +689,46 @@ impl<K, V, A: Allocator + Clone> BTreeMap<K, V, A> {
     /// # Examples
     ///
     /// ```
+    /// use std::cmp::Ordering;
     /// use std::collections::BTreeMap;
     ///
+    /// #[derive(Clone, Copy, Debug)]
+    /// struct S {
+    ///     id: u32,
+    /// #   #[allow(unused)] // prevents a "field `name` is never read" error
+    ///     name: &'static str, // ignored by equality and ordering operations
+    /// }
+    ///
+    /// impl PartialEq for S {
+    ///     fn eq(&self, other: &S) -> bool {
+    ///         self.id == other.id
+    ///     }
+    /// }
+    ///
+    /// impl Eq for S {}
+    ///
+    /// impl PartialOrd for S {
+    ///     fn partial_cmp(&self, other: &S) -> Option<Ordering> {
+    ///         self.id.partial_cmp(&other.id)
+    ///     }
+    /// }
+    ///
+    /// impl Ord for S {
+    ///     fn cmp(&self, other: &S) -> Ordering {
+    ///         self.id.cmp(&other.id)
+    ///     }
+    /// }
+    ///
+    /// let j_a = S { id: 1, name: "Jessica" };
+    /// let j_b = S { id: 1, name: "Jess" };
+    /// let p = S { id: 2, name: "Paul" };
+    /// assert_eq!(j_a, j_b);
+    ///
     /// let mut map = BTreeMap::new();
-    /// map.insert(1, "a");
-    /// assert_eq!(map.get_key_value(&1), Some((&1, &"a")));
-    /// assert_eq!(map.get_key_value(&2), None);
+    /// map.insert(j_a, "Paris");
+    /// assert_eq!(map.get_key_value(&j_a), Some((&j_a, &"Paris")));
+    /// assert_eq!(map.get_key_value(&j_b), Some((&j_a, &"Paris"))); // the notable case
+    /// assert_eq!(map.get_key_value(&p), None);
     /// ```
     #[stable(feature = "map_get_key_value", since = "1.40.0")]
     pub fn get_key_value<Q: ?Sized>(&self, k: &Q) -> Option<(&K, &V)>
diff --git a/library/alloc/src/collections/vec_deque/iter.rs b/library/alloc/src/collections/vec_deque/iter.rs
index 6922ea9b79b..d3dbd10c863 100644
--- a/library/alloc/src/collections/vec_deque/iter.rs
+++ b/library/alloc/src/collections/vec_deque/iter.rs
@@ -19,6 +19,40 @@ impl<'a, T> Iter<'a, T> {
     pub(super) fn new(i1: slice::Iter<'a, T>, i2: slice::Iter<'a, T>) -> Self {
         Self { i1, i2 }
     }
+
+    /// Views the underlying data as a pair of subslices of the original data.
+    ///
+    /// The slices contain, in order, the contents of the deque not yet yielded
+    /// by the iterator.
+    ///
+    /// This has the same lifetime as the original `VecDeque`, and so the
+    /// iterator can continue to be used while this exists.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(vec_deque_iter_as_slices)]
+    ///
+    /// use std::collections::VecDeque;
+    ///
+    /// let mut deque = VecDeque::new();
+    /// deque.push_back(0);
+    /// deque.push_back(1);
+    /// deque.push_back(2);
+    /// deque.push_front(10);
+    /// deque.push_front(9);
+    /// deque.push_front(8);
+    ///
+    /// let mut iter = deque.iter();
+    /// iter.next();
+    /// iter.next_back();
+    ///
+    /// assert_eq!(iter.as_slices(), (&[9, 10][..], &[0, 1][..]));
+    /// ```
+    #[unstable(feature = "vec_deque_iter_as_slices", issue = "123947")]
+    pub fn as_slices(&self) -> (&'a [T], &'a [T]) {
+        (self.i1.as_slice(), self.i2.as_slice())
+    }
 }
 
 #[stable(feature = "collection_debug", since = "1.17.0")]
diff --git a/library/alloc/src/collections/vec_deque/iter_mut.rs b/library/alloc/src/collections/vec_deque/iter_mut.rs
index 84b74109580..0c5f06e752b 100644
--- a/library/alloc/src/collections/vec_deque/iter_mut.rs
+++ b/library/alloc/src/collections/vec_deque/iter_mut.rs
@@ -19,6 +19,113 @@ impl<'a, T> IterMut<'a, T> {
     pub(super) fn new(i1: slice::IterMut<'a, T>, i2: slice::IterMut<'a, T>) -> Self {
         Self { i1, i2 }
     }
+
+    /// Views the underlying data as a pair of subslices of the original data.
+    ///
+    /// The slices contain, in order, the contents of the deque not yet yielded
+    /// by the iterator.
+    ///
+    /// To avoid creating `&mut` references that alias, this is forced to
+    /// consume the iterator.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(vec_deque_iter_as_slices)]
+    ///
+    /// use std::collections::VecDeque;
+    ///
+    /// let mut deque = VecDeque::new();
+    /// deque.push_back(0);
+    /// deque.push_back(1);
+    /// deque.push_back(2);
+    /// deque.push_front(10);
+    /// deque.push_front(9);
+    /// deque.push_front(8);
+    ///
+    /// let mut iter = deque.iter_mut();
+    /// iter.next();
+    /// iter.next_back();
+    ///
+    /// let slices = iter.into_slices();
+    /// slices.0[0] = 42;
+    /// slices.1[0] = 24;
+    /// assert_eq!(deque.as_slices(), (&[8, 42, 10][..], &[24, 1, 2][..]));
+    /// ```
+    #[unstable(feature = "vec_deque_iter_as_slices", issue = "123947")]
+    pub fn into_slices(self) -> (&'a mut [T], &'a mut [T]) {
+        (self.i1.into_slice(), self.i2.into_slice())
+    }
+
+    /// Views the underlying data as a pair of subslices of the original data.
+    ///
+    /// The slices contain, in order, the contents of the deque not yet yielded
+    /// by the iterator.
+    ///
+    /// To avoid creating `&mut [T]` references that alias, the returned slices
+    /// borrow their lifetimes from the iterator the method is applied on.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(vec_deque_iter_as_slices)]
+    ///
+    /// use std::collections::VecDeque;
+    ///
+    /// let mut deque = VecDeque::new();
+    /// deque.push_back(0);
+    /// deque.push_back(1);
+    /// deque.push_back(2);
+    /// deque.push_front(10);
+    /// deque.push_front(9);
+    /// deque.push_front(8);
+    ///
+    /// let mut iter = deque.iter_mut();
+    /// iter.next();
+    /// iter.next_back();
+    ///
+    /// assert_eq!(iter.as_slices(), (&[9, 10][..], &[0, 1][..]));
+    /// ```
+    #[unstable(feature = "vec_deque_iter_as_slices", issue = "123947")]
+    pub fn as_slices(&self) -> (&[T], &[T]) {
+        (self.i1.as_slice(), self.i2.as_slice())
+    }
+
+    /// Views the underlying data as a pair of subslices of the original data.
+    ///
+    /// The slices contain, in order, the contents of the deque not yet yielded
+    /// by the iterator.
+    ///
+    /// To avoid creating `&mut [T]` references that alias, the returned slices
+    /// borrow their lifetimes from the iterator the method is applied on.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(vec_deque_iter_as_slices)]
+    ///
+    /// use std::collections::VecDeque;
+    ///
+    /// let mut deque = VecDeque::new();
+    /// deque.push_back(0);
+    /// deque.push_back(1);
+    /// deque.push_back(2);
+    /// deque.push_front(10);
+    /// deque.push_front(9);
+    /// deque.push_front(8);
+    ///
+    /// let mut iter = deque.iter_mut();
+    /// iter.next();
+    /// iter.next_back();
+    ///
+    /// iter.as_mut_slices().0[0] = 42;
+    /// iter.as_mut_slices().1[0] = 24;
+    /// assert_eq!(deque.as_slices(), (&[8, 42, 10][..], &[24, 1, 2][..]));
+    /// ```
+    #[unstable(feature = "vec_deque_iter_as_slices", issue = "123947")]
+    pub fn as_mut_slices(&mut self) -> (&mut [T], &mut [T]) {
+        (self.i1.as_mut_slice(), self.i2.as_mut_slice())
+    }
 }
 
 #[stable(feature = "collection_debug", since = "1.17.0")]
diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs
index dd9dfa3f5e2..7839fe04b8d 100644
--- a/library/alloc/src/lib.rs
+++ b/library/alloc/src/lib.rs
@@ -143,6 +143,7 @@
 #![feature(sized_type_properties)]
 #![feature(slice_from_ptr_range)]
 #![feature(slice_index_methods)]
+#![feature(slice_iter_mut_as_mut_slice)]
 #![feature(slice_ptr_get)]
 #![feature(slice_range)]
 #![feature(std_internals)]
diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs
index 07a1bd49321..990b7e8f761 100644
--- a/library/alloc/src/vec/mod.rs
+++ b/library/alloc/src/vec/mod.rs
@@ -1662,6 +1662,7 @@ impl<T, A: Allocator> Vec<T, A> {
     #[stable(feature = "vec_as_ptr", since = "1.37.0")]
     #[rustc_const_unstable(feature = "const_vec_string_slice", issue = "129041")]
     #[rustc_never_returns_null_ptr]
+    #[cfg_attr(not(bootstrap), rustc_as_ptr)]
     #[inline]
     pub const fn as_ptr(&self) -> *const T {
         // We shadow the slice method of the same name to avoid going through
@@ -1724,6 +1725,7 @@ impl<T, A: Allocator> Vec<T, A> {
     #[stable(feature = "vec_as_ptr", since = "1.37.0")]
     #[rustc_const_unstable(feature = "const_vec_string_slice", issue = "129041")]
     #[rustc_never_returns_null_ptr]
+    #[cfg_attr(not(bootstrap), rustc_as_ptr)]
     #[inline]
     pub const fn as_mut_ptr(&mut self) -> *mut T {
         // We shadow the slice method of the same name to avoid going through
diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs
index 1a461987c76..bfd2a71f97b 100644
--- a/library/core/src/cell.rs
+++ b/library/core/src/cell.rs
@@ -587,6 +587,7 @@ impl<T: ?Sized> Cell<T> {
     #[inline]
     #[stable(feature = "cell_as_ptr", since = "1.12.0")]
     #[rustc_const_stable(feature = "const_cell_as_ptr", since = "1.32.0")]
+    #[cfg_attr(not(bootstrap), rustc_as_ptr)]
     #[rustc_never_returns_null_ptr]
     pub const fn as_ptr(&self) -> *mut T {
         self.value.get()
@@ -1149,6 +1150,7 @@ impl<T: ?Sized> RefCell<T> {
     /// ```
     #[inline]
     #[stable(feature = "cell_as_ptr", since = "1.12.0")]
+    #[cfg_attr(not(bootstrap), rustc_as_ptr)]
     #[rustc_never_returns_null_ptr]
     pub fn as_ptr(&self) -> *mut T {
         self.value.get()
@@ -2158,6 +2160,7 @@ impl<T: ?Sized> UnsafeCell<T> {
     #[inline(always)]
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_const_stable(feature = "const_unsafecell_get", since = "1.32.0")]
+    #[cfg_attr(not(bootstrap), rustc_as_ptr)]
     #[rustc_never_returns_null_ptr]
     pub const fn get(&self) -> *mut T {
         // We can just cast the pointer from `UnsafeCell<T>` to `T` because of
@@ -2271,6 +2274,7 @@ impl<T: DispatchFromDyn<U>, U> DispatchFromDyn<UnsafeCell<U>> for UnsafeCell<T>
 /// See [`UnsafeCell`] for details.
 #[unstable(feature = "sync_unsafe_cell", issue = "95439")]
 #[repr(transparent)]
+#[rustc_diagnostic_item = "SyncUnsafeCell"]
 #[rustc_pub_transparent]
 pub struct SyncUnsafeCell<T: ?Sized> {
     value: UnsafeCell<T>,
@@ -2304,6 +2308,7 @@ impl<T: ?Sized> SyncUnsafeCell<T> {
     /// when casting to `&mut T`, and ensure that there are no mutations
     /// or mutable aliases going on when casting to `&T`
     #[inline]
+    #[cfg_attr(not(bootstrap), rustc_as_ptr)]
     #[rustc_never_returns_null_ptr]
     pub const fn get(&self) -> *mut T {
         self.value.get()
diff --git a/library/core/src/ffi/c_str.rs b/library/core/src/ffi/c_str.rs
index 85571222b5c..9e32f74227c 100644
--- a/library/core/src/ffi/c_str.rs
+++ b/library/core/src/ffi/c_str.rs
@@ -500,6 +500,7 @@ impl CStr {
     #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_const_stable(feature = "const_str_as_ptr", since = "1.32.0")]
+    #[cfg_attr(not(bootstrap), rustc_as_ptr)]
     #[rustc_never_returns_null_ptr]
     pub const fn as_ptr(&self) -> *const c_char {
         self.inner.as_ptr()
diff --git a/library/core/src/mem/maybe_uninit.rs b/library/core/src/mem/maybe_uninit.rs
index 8c6cdf57c58..58315cb74f0 100644
--- a/library/core/src/mem/maybe_uninit.rs
+++ b/library/core/src/mem/maybe_uninit.rs
@@ -525,6 +525,7 @@ impl<T> MaybeUninit<T> {
     /// until they are, it is advisable to avoid them.)
     #[stable(feature = "maybe_uninit", since = "1.36.0")]
     #[rustc_const_stable(feature = "const_maybe_uninit_as_ptr", since = "1.59.0")]
+    #[cfg_attr(not(bootstrap), rustc_as_ptr)]
     #[inline(always)]
     pub const fn as_ptr(&self) -> *const T {
         // `MaybeUninit` and `ManuallyDrop` are both `repr(transparent)` so we can cast the pointer.
@@ -566,6 +567,7 @@ impl<T> MaybeUninit<T> {
     /// until they are, it is advisable to avoid them.)
     #[stable(feature = "maybe_uninit", since = "1.36.0")]
     #[rustc_const_stable(feature = "const_maybe_uninit_as_mut_ptr", since = "1.83.0")]
+    #[cfg_attr(not(bootstrap), rustc_as_ptr)]
     #[inline(always)]
     pub const fn as_mut_ptr(&mut self) -> *mut T {
         // `MaybeUninit` and `ManuallyDrop` are both `repr(transparent)` so we can cast the pointer.
diff --git a/library/core/src/panic.rs b/library/core/src/panic.rs
index e702056f00a..179aadf0c28 100644
--- a/library/core/src/panic.rs
+++ b/library/core/src/panic.rs
@@ -215,7 +215,7 @@ pub macro const_panic {
                 #[noinline]
                 if const #[track_caller] #[inline] { // Inline this, to prevent codegen
                     $crate::panic!($const_msg)
-                } else #[track_caller] { // Do not inline this, it makes perf worse
+                } else #[track_caller] #[cfg_attr(bootstrap, inline)] { // Do not inline this, it makes perf worse
                     $crate::panic!($runtime_msg)
                 }
             )
diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs
index ef52cc44126..c855f963771 100644
--- a/library/core/src/slice/mod.rs
+++ b/library/core/src/slice/mod.rs
@@ -735,6 +735,7 @@ impl<T> [T] {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_const_stable(feature = "const_slice_as_ptr", since = "1.32.0")]
     #[rustc_never_returns_null_ptr]
+    #[cfg_attr(not(bootstrap), rustc_as_ptr)]
     #[inline(always)]
     #[must_use]
     pub const fn as_ptr(&self) -> *const T {
@@ -765,6 +766,7 @@ impl<T> [T] {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")]
     #[rustc_never_returns_null_ptr]
+    #[cfg_attr(not(bootstrap), rustc_as_ptr)]
     #[inline(always)]
     #[must_use]
     pub const fn as_mut_ptr(&mut self) -> *mut T {
diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs
index 5aecbf303f9..4629b770cb4 100644
--- a/library/core/src/str/mod.rs
+++ b/library/core/src/str/mod.rs
@@ -373,6 +373,7 @@ impl str {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_const_stable(feature = "rustc_str_as_ptr", since = "1.32.0")]
     #[rustc_never_returns_null_ptr]
+    #[cfg_attr(not(bootstrap), rustc_as_ptr)]
     #[must_use]
     #[inline(always)]
     pub const fn as_ptr(&self) -> *const u8 {
@@ -390,6 +391,7 @@ impl str {
     #[stable(feature = "str_as_mut_ptr", since = "1.36.0")]
     #[rustc_const_stable(feature = "const_str_as_mut", since = "1.83.0")]
     #[rustc_never_returns_null_ptr]
+    #[cfg_attr(not(bootstrap), rustc_as_ptr)]
     #[must_use]
     #[inline(always)]
     pub const fn as_mut_ptr(&mut self) -> *mut u8 {
diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs
index ded4f404d78..24bbc2f32cf 100644
--- a/library/std/src/collections/hash/map.rs
+++ b/library/std/src/collections/hash/map.rs
@@ -880,7 +880,11 @@ where
         self.base.get(k)
     }
 
-    /// Returns the key-value pair corresponding to the supplied key.
+    /// Returns the key-value pair corresponding to the supplied key. This is
+    /// potentially useful:
+    /// - for key types where non-identical keys can be considered equal;
+    /// - for getting the `&K` stored key value from a borrowed `&Q` lookup key; or
+    /// - for getting a reference to a key with the same lifetime as the collection.
     ///
     /// The supplied key may be any borrowed form of the map's key type, but
     /// [`Hash`] and [`Eq`] on the borrowed form *must* match those for
@@ -890,11 +894,39 @@ where
     ///
     /// ```
     /// use std::collections::HashMap;
+    /// use std::hash::{Hash, Hasher};
+    ///
+    /// #[derive(Clone, Copy, Debug)]
+    /// struct S {
+    ///     id: u32,
+    /// #   #[allow(unused)] // prevents a "field `name` is never read" error
+    ///     name: &'static str, // ignored by equality and hashing operations
+    /// }
+    ///
+    /// impl PartialEq for S {
+    ///     fn eq(&self, other: &S) -> bool {
+    ///         self.id == other.id
+    ///     }
+    /// }
+    ///
+    /// impl Eq for S {}
+    ///
+    /// impl Hash for S {
+    ///     fn hash<H: Hasher>(&self, state: &mut H) {
+    ///         self.id.hash(state);
+    ///     }
+    /// }
+    ///
+    /// let j_a = S { id: 1, name: "Jessica" };
+    /// let j_b = S { id: 1, name: "Jess" };
+    /// let p = S { id: 2, name: "Paul" };
+    /// assert_eq!(j_a, j_b);
     ///
     /// let mut map = HashMap::new();
-    /// map.insert(1, "a");
-    /// assert_eq!(map.get_key_value(&1), Some((&1, &"a")));
-    /// assert_eq!(map.get_key_value(&2), None);
+    /// map.insert(j_a, "Paris");
+    /// assert_eq!(map.get_key_value(&j_a), Some((&j_a, &"Paris")));
+    /// assert_eq!(map.get_key_value(&j_b), Some((&j_a, &"Paris"))); // the notable case
+    /// assert_eq!(map.get_key_value(&p), None);
     /// ```
     #[inline]
     #[stable(feature = "map_get_key_value", since = "1.40.0")]
diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs
index 76fdb1a4ffd..555e8804eab 100644
--- a/library/std/src/fs.rs
+++ b/library/std/src/fs.rs
@@ -2738,6 +2738,10 @@ pub fn create_dir_all<P: AsRef<Path>>(path: P) -> io::Result<()> {
 
 /// Removes an empty directory.
 ///
+/// If you want to remove a directory that is not empty, as well as all
+/// of its contents recursively, consider using [`remove_dir_all`]
+/// instead.
+///
 /// # Platform-specific behavior
 ///
 /// This function currently corresponds to the `rmdir` function on Unix
diff --git a/library/std/src/sync/rwlock/tests.rs b/library/std/src/sync/rwlock/tests.rs
index 02ac1c85b91..29cad4400f1 100644
--- a/library/std/src/sync/rwlock/tests.rs
+++ b/library/std/src/sync/rwlock/tests.rs
@@ -550,6 +550,9 @@ fn test_downgrade_observe() {
 }
 
 #[test]
+// FIXME: On macOS we use a provenance-incorrect implementation and Miri catches that issue.
+// See <https://github.com/rust-lang/rust/issues/121950> for details.
+#[cfg_attr(all(miri, target_os = "macos"), ignore)]
 fn test_downgrade_atomic() {
     const NEW_VALUE: i32 = -1;
 
diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs
index 227ee9d64f3..2c2cc58a9dd 100644
--- a/library/std/src/thread/mod.rs
+++ b/library/std/src/thread/mod.rs
@@ -188,6 +188,11 @@ mod current;
 pub use current::current;
 pub(crate) use current::{current_id, drop_current, set_current, try_current};
 
+mod spawnhook;
+
+#[unstable(feature = "thread_spawn_hook", issue = "132951")]
+pub use spawnhook::add_spawn_hook;
+
 ////////////////////////////////////////////////////////////////////////////////
 // Thread-local storage
 ////////////////////////////////////////////////////////////////////////////////
@@ -259,6 +264,8 @@ pub struct Builder {
     name: Option<String>,
     // The size of the stack for the spawned thread in bytes
     stack_size: Option<usize>,
+    // Skip running and inheriting the thread spawn hooks
+    no_hooks: bool,
 }
 
 impl Builder {
@@ -282,7 +289,7 @@ impl Builder {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn new() -> Builder {
-        Builder { name: None, stack_size: None }
+        Builder { name: None, stack_size: None, no_hooks: false }
     }
 
     /// Names the thread-to-be. Currently the name is used for identification
@@ -338,6 +345,16 @@ impl Builder {
         self
     }
 
+    /// Disables running and inheriting [spawn hooks](add_spawn_hook).
+    ///
+    /// Use this if the parent thread is in no way relevant for the child thread.
+    /// For example, when lazily spawning threads for a thread pool.
+    #[unstable(feature = "thread_spawn_hook", issue = "132951")]
+    pub fn no_hooks(mut self) -> Builder {
+        self.no_hooks = true;
+        self
+    }
+
     /// Spawns a new thread by taking ownership of the `Builder`, and returns an
     /// [`io::Result`] to its [`JoinHandle`].
     ///
@@ -460,7 +477,7 @@ impl Builder {
         F: Send,
         T: Send,
     {
-        let Builder { name, stack_size } = self;
+        let Builder { name, stack_size, no_hooks } = self;
 
         let stack_size = stack_size.unwrap_or_else(|| {
             static MIN: AtomicUsize = AtomicUsize::new(0);
@@ -485,6 +502,13 @@ impl Builder {
             Some(name) => Thread::new(id, name.into()),
             None => Thread::new_unnamed(id),
         };
+
+        let hooks = if no_hooks {
+            spawnhook::ChildSpawnHooks::default()
+        } else {
+            spawnhook::run_spawn_hooks(&my_thread)
+        };
+
         let their_thread = my_thread.clone();
 
         let my_packet: Arc<Packet<'scope, T>> = Arc::new(Packet {
@@ -494,9 +518,6 @@ impl Builder {
         });
         let their_packet = my_packet.clone();
 
-        let output_capture = crate::io::set_output_capture(None);
-        crate::io::set_output_capture(output_capture.clone());
-
         // Pass `f` in `MaybeUninit` because actually that closure might *run longer than the lifetime of `F`*.
         // See <https://github.com/rust-lang/rust/issues/101983> for more details.
         // To prevent leaks we use a wrapper that drops its contents.
@@ -534,10 +555,9 @@ impl Builder {
                 imp::Thread::set_name(name);
             }
 
-            crate::io::set_output_capture(output_capture);
-
             let f = f.into_inner();
             let try_result = panic::catch_unwind(panic::AssertUnwindSafe(|| {
+                crate::sys::backtrace::__rust_begin_short_backtrace(|| hooks.run());
                 crate::sys::backtrace::__rust_begin_short_backtrace(f)
             }));
             // SAFETY: `their_packet` as been built just above and moved by the
diff --git a/library/std/src/thread/spawnhook.rs b/library/std/src/thread/spawnhook.rs
new file mode 100644
index 00000000000..99b5ad9cb9f
--- /dev/null
+++ b/library/std/src/thread/spawnhook.rs
@@ -0,0 +1,148 @@
+use crate::cell::Cell;
+use crate::iter;
+use crate::sync::Arc;
+use crate::thread::Thread;
+
+crate::thread_local! {
+    /// A thread local linked list of spawn hooks.
+    ///
+    /// It is a linked list of Arcs, such that it can very cheaply be inhereted by spawned threads.
+    ///
+    /// (That technically makes it a set of linked lists with shared tails, so a linked tree.)
+    static SPAWN_HOOKS: Cell<SpawnHooks> = const { Cell::new(SpawnHooks { first: None }) };
+}
+
+#[derive(Default, Clone)]
+struct SpawnHooks {
+    first: Option<Arc<SpawnHook>>,
+}
+
+// Manually implement drop to prevent deep recursion when dropping linked Arc list.
+impl Drop for SpawnHooks {
+    fn drop(&mut self) {
+        let mut next = self.first.take();
+        while let Some(SpawnHook { hook, next: n }) = next.and_then(|n| Arc::into_inner(n)) {
+            drop(hook);
+            next = n;
+        }
+    }
+}
+
+struct SpawnHook {
+    hook: Box<dyn Send + Sync + Fn(&Thread) -> Box<dyn Send + FnOnce()>>,
+    next: Option<Arc<SpawnHook>>,
+}
+
+/// Registers a function to run for every newly thread spawned.
+///
+/// The hook is executed in the parent thread, and returns a function
+/// that will be executed in the new thread.
+///
+/// The hook is called with the `Thread` handle for the new thread.
+///
+/// The hook will only be added for the current thread and is inherited by the threads it spawns.
+/// In other words, adding a hook has no effect on already running threads (other than the current
+/// thread) and the threads they might spawn in the future.
+///
+/// Hooks can only be added, not removed.
+///
+/// The hooks will run in reverse order, starting with the most recently added.
+///
+/// # Usage
+///
+/// ```
+/// #![feature(thread_spawn_hook)]
+///
+/// std::thread::add_spawn_hook(|_| {
+///     ..; // This will run in the parent (spawning) thread.
+///     move || {
+///         ..; // This will run it the child (spawned) thread.
+///     }
+/// });
+/// ```
+///
+/// # Example
+///
+/// A spawn hook can be used to "inherit" a thread local from the parent thread:
+///
+/// ```
+/// #![feature(thread_spawn_hook)]
+///
+/// use std::cell::Cell;
+///
+/// thread_local! {
+///     static X: Cell<u32> = Cell::new(0);
+/// }
+///
+/// // This needs to be done once in the main thread before spawning any threads.
+/// std::thread::add_spawn_hook(|_| {
+///     // Get the value of X in the spawning thread.
+///     let value = X.get();
+///     // Set the value of X in the newly spawned thread.
+///     move || X.set(value)
+/// });
+///
+/// X.set(123);
+///
+/// std::thread::spawn(|| {
+///     assert_eq!(X.get(), 123);
+/// }).join().unwrap();
+/// ```
+#[unstable(feature = "thread_spawn_hook", issue = "132951")]
+pub fn add_spawn_hook<F, G>(hook: F)
+where
+    F: 'static + Send + Sync + Fn(&Thread) -> G,
+    G: 'static + Send + FnOnce(),
+{
+    SPAWN_HOOKS.with(|h| {
+        let mut hooks = h.take();
+        let next = hooks.first.take();
+        hooks.first = Some(Arc::new(SpawnHook {
+            hook: Box::new(move |thread| Box::new(hook(thread))),
+            next,
+        }));
+        h.set(hooks);
+    });
+}
+
+/// Runs all the spawn hooks.
+///
+/// Called on the parent thread.
+///
+/// Returns the functions to be called on the newly spawned thread.
+pub(super) fn run_spawn_hooks(thread: &Thread) -> ChildSpawnHooks {
+    // Get a snapshot of the spawn hooks.
+    // (Increments the refcount to the first node.)
+    let hooks = SPAWN_HOOKS.with(|hooks| {
+        let snapshot = hooks.take();
+        hooks.set(snapshot.clone());
+        snapshot
+    });
+    // Iterate over the hooks, run them, and collect the results in a vector.
+    let to_run: Vec<_> = iter::successors(hooks.first.as_deref(), |hook| hook.next.as_deref())
+        .map(|hook| (hook.hook)(thread))
+        .collect();
+    // Pass on the snapshot of the hooks and the results to the new thread,
+    // which will then run SpawnHookResults::run().
+    ChildSpawnHooks { hooks, to_run }
+}
+
+/// The results of running the spawn hooks.
+///
+/// This struct is sent to the new thread.
+/// It contains the inherited hooks and the closures to be run.
+#[derive(Default)]
+pub(super) struct ChildSpawnHooks {
+    hooks: SpawnHooks,
+    to_run: Vec<Box<dyn FnOnce() + Send>>,
+}
+
+impl ChildSpawnHooks {
+    // This is run on the newly spawned thread, directly at the start.
+    pub(super) fn run(self) {
+        SPAWN_HOOKS.set(self.hooks);
+        for run in self.to_run {
+            run();
+        }
+    }
+}
diff --git a/library/stdarch b/library/stdarch
-Subproject ff9a4445038eae46fd095188740946808581bc0
+Subproject e5e00aab0a8c8fa35fb7865e88fa82366f615c5
diff --git a/library/test/src/lib.rs b/library/test/src/lib.rs
index 30ccfe2af8d..47407df909b 100644
--- a/library/test/src/lib.rs
+++ b/library/test/src/lib.rs
@@ -24,6 +24,7 @@
 #![feature(process_exitcode_internals)]
 #![feature(panic_can_unwind)]
 #![feature(test)]
+#![feature(thread_spawn_hook)]
 #![allow(internal_features)]
 #![warn(rustdoc::unescaped_backticks)]
 
@@ -134,6 +135,16 @@ pub fn test_main(args: &[String], tests: Vec<TestDescAndFn>, options: Option<Opt
                 }
             });
             panic::set_hook(hook);
+            // Use a thread spawning hook to make new threads inherit output capturing.
+            std::thread::add_spawn_hook(|_| {
+                // Get and clone the output capture of the current thread.
+                let output_capture = io::set_output_capture(None);
+                io::set_output_capture(output_capture.clone());
+                // Set the output capture of the new thread.
+                || {
+                    io::set_output_capture(output_capture);
+                }
+            });
         }
         let res = console::run_tests_console(&opts, tests);
         // Prevent Valgrind from reporting reachable blocks in users' unit tests.
diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs
index 95b1303fa71..e706aba977b 100644
--- a/src/bootstrap/src/core/config/config.rs
+++ b/src/bootstrap/src/core/config/config.rs
@@ -1255,6 +1255,10 @@ impl Config {
             },
             out: PathBuf::from("build"),
 
+            // This is needed by codegen_ssa on macOS to ship `llvm-objcopy` aliased to
+            // `rust-objcopy` to workaround bad `strip`s on macOS.
+            llvm_tools_enabled: true,
+
             ..Default::default()
         }
     }
diff --git a/src/bootstrap/src/utils/change_tracker.rs b/src/bootstrap/src/utils/change_tracker.rs
index 1d05f94e3be..7f62ffb20db 100644
--- a/src/bootstrap/src/utils/change_tracker.rs
+++ b/src/bootstrap/src/utils/change_tracker.rs
@@ -300,4 +300,9 @@ pub const CONFIG_CHANGE_HISTORY: &[ChangeInfo] = &[
         severity: ChangeSeverity::Info,
         summary: "`download-rustc='if-unchanged'` is now a default option for library profile.",
     },
+    ChangeInfo {
+        change_id: 133207,
+        severity: ChangeSeverity::Info,
+        summary: "`rust.llvm-tools` is now enabled by default when no `config.toml` is provided.",
+    },
 ];
diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml
index eea97e98cc2..9a51a3f4268 100644
--- a/src/ci/github-actions/jobs.yml
+++ b/src/ci/github-actions/jobs.yml
@@ -465,7 +465,7 @@ auto:
       SCRIPT: python x.py dist bootstrap --include-default-paths
       DIST_REQUIRE_ALL_TOOLS: 1
       CODEGEN_BACKENDS: llvm,cranelift
-    <<: *job-windows-8c
+    <<: *job-windows
 
   - image: dist-aarch64-msvc
     env:
diff --git a/src/doc/edition-guide b/src/doc/edition-guide
-Subproject 2d482e203eb6d6e353814cf1415c5f94e590b9e
+Subproject 915f9b319c2823f310430ecdecd86264a7870d7
diff --git a/src/doc/nomicon b/src/doc/nomicon
-Subproject 456b904f791751892b01282fd2757904993c4c2
+Subproject eac89a3cbe6c4714e5029ae8b5a1c556fd4e8c4
diff --git a/src/doc/reference b/src/doc/reference
-Subproject da0f6dad767670da0e8cd5af8a7090db3272f62
+Subproject 41ccb0e6478305401dad92e8fd3d04a4304edb4
diff --git a/src/doc/rustc-dev-guide b/src/doc/rustc-dev-guide
-Subproject 6a5accdaf10255882b1e6c59dfe5f1c79ac9548
+Subproject b679e71c2d66c6fe13e06b99ac61773b866213f
diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md
index 18f76ac6fe0..f3d8a4edd6c 100644
--- a/src/doc/rustc/src/SUMMARY.md
+++ b/src/doc/rustc/src/SUMMARY.md
@@ -72,6 +72,8 @@
     - [riscv32imac-unknown-xous-elf](platform-support/riscv32imac-unknown-xous-elf.md)
     - [riscv64gc-unknown-linux-gnu](platform-support/riscv64gc-unknown-linux-gnu.md)
     - [riscv64gc-unknown-linux-musl](platform-support/riscv64gc-unknown-linux-musl.md)
+    - [s390x-unknown-linux-gnu](platform-support/s390x-unknown-linux-gnu.md)
+    - [s390x-unknown-linux-musl](platform-support/s390x-unknown-linux-musl.md)
     - [sparc-unknown-none-elf](./platform-support/sparc-unknown-none-elf.md)
     - [*-pc-windows-gnullvm](platform-support/pc-windows-gnullvm.md)
     - [\*-nto-qnx-\*](platform-support/nto-qnx.md)
diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md
index 500eaafb63f..243cb3b2fc8 100644
--- a/src/doc/rustc/src/platform-support.md
+++ b/src/doc/rustc/src/platform-support.md
@@ -99,7 +99,7 @@ target | notes
 `powerpc64le-unknown-linux-gnu` | PPC64LE Linux (kernel 3.10, glibc 2.17)
 [`riscv64gc-unknown-linux-gnu`](platform-support/riscv64gc-unknown-linux-gnu.md) | RISC-V Linux (kernel 4.20, glibc 2.29)
 [`riscv64gc-unknown-linux-musl`](platform-support/riscv64gc-unknown-linux-musl.md) | RISC-V Linux (kernel 4.20, musl 1.2.3)
-`s390x-unknown-linux-gnu` | S390x Linux (kernel 3.2, glibc 2.17)
+[`s390x-unknown-linux-gnu`](platform-support/s390x-unknown-linux-gnu.md) | S390x Linux (kernel 3.2, glibc 2.17)
 `x86_64-unknown-freebsd` | 64-bit FreeBSD
 `x86_64-unknown-illumos` | illumos
 `x86_64-unknown-linux-musl` | 64-bit Linux with musl 1.2.3
@@ -367,7 +367,7 @@ target | std | host | notes
 [`riscv64gc-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | OpenBSD/riscv64
 [`riscv64-linux-android`](platform-support/android.md) |   |   | RISC-V 64-bit Android
 [`riscv64-wrs-vxworks`](platform-support/vxworks.md) | ✓ |  |
-`s390x-unknown-linux-musl` |  |  | S390x Linux (kernel 3.2, musl 1.2.3)
+[`s390x-unknown-linux-musl`](platform-support/s390x-unknown-linux-musl.md) |  |  | S390x Linux (kernel 3.2, musl 1.2.3)
 `sparc-unknown-linux-gnu` | ✓ |  | 32-bit SPARC Linux
 [`sparc-unknown-none-elf`](./platform-support/sparc-unknown-none-elf.md) | * |  | Bare 32-bit SPARC V7+
 [`sparc64-unknown-netbsd`](platform-support/netbsd.md) | ✓ | ✓ | NetBSD/sparc64
diff --git a/src/doc/rustc/src/platform-support/s390x-unknown-linux-gnu.md b/src/doc/rustc/src/platform-support/s390x-unknown-linux-gnu.md
new file mode 100644
index 00000000000..60e06c404c0
--- /dev/null
+++ b/src/doc/rustc/src/platform-support/s390x-unknown-linux-gnu.md
@@ -0,0 +1,113 @@
+# `s390x-unknown-linux-gnu`
+
+**Tier: 2 (with Host Tools)**
+
+IBM z/Architecture (s390x) targets (including IBM Z and LinuxONE) running Linux.
+
+## Target maintainers
+
+- Ulrich Weigand, <ulrich.weigand@de.ibm.com>, [@uweigand](https://github.com/uweigand)
+- Josh Stone, <jistone@redhat.com>, [@cuviper](https://github.com/cuviper)
+
+## Requirements
+
+This target requires:
+
+* Linux Kernel version 3.2 or later
+* glibc 2.17 or later
+
+Code generated by the target uses the z/Architecture ISA assuming a minimum
+architecture level of z10 (Eighth Edition of the z/Architecture Principles
+of Operation), and is compliant with the s390x ELF ABI.
+
+Reference material:
+
+* [z/Architecture Principles of Operation][s390x-isa]
+* [z/Architecture ELF Application Binary Interface][s390x-abi]
+
+[s390x-isa]: https://publibfp.dhe.ibm.com/epubs/pdf/a227832d.pdf
+[s390x-abi]: https://github.com/IBM/s390x-abi
+
+## Building the target
+
+This target is distributed through `rustup`, and otherwise requires no
+special configuration.
+
+If you need to build your own Rust for some reason though, the target can be
+enabled in `config.toml`. For example:
+
+```toml
+[build]
+target = ["s390x-unknown-linux-gnu"]
+```
+
+## Building Rust programs
+
+On a s390x Linux host, the `s390x-unknown-linux-gnu` target should be
+automatically installed and used by default.
+
+On a non-s390x host, add the target:
+
+```bash
+rustup target add s390x-unknown-linux-gnu
+```
+
+Then cross compile crates with:
+
+```bash
+cargo build --target s390x-unknown-linux-gnu
+```
+
+## Testing
+
+There are no special requirements for testing and running the target.
+For testing cross builds on the host, please refer to the "Cross-compilation
+toolchains and C code" section below.
+
+## Cross-compilation toolchains and C code
+
+Rust code built using the target is compatible with C code compiled with
+GCC or Clang using the `s390x-unknown-linux-gnu` target triple (via either
+native or cross-compilation).
+
+On Ubuntu, a s390x cross-toolchain can be installed with:
+
+```bash
+apt install gcc-s390x-linux-gnu g++-s390x-linux-gnu libc6-dev-s390x-cross
+```
+
+Depending on your system, you may need to configure the target to use the GNU
+GCC linker. To use it, add the following to your `.cargo/config.toml`:
+
+```toml
+[target.s390x-unknown-linux-gnu]
+linker = "s390x-linux-gnu-gcc"
+```
+
+If your `s390x-linux-gnu-*` toolchain is not in your `PATH` you may need to
+configure additional settings:
+
+```toml
+[target.s390x-unknown-linux-gnu]
+# Adjust the paths to point at your toolchain
+cc = "/TOOLCHAIN_PATH/bin/s390x-linux-gnu-gcc"
+cxx = "/TOOLCHAIN_PATH/bin/s390x-linux-gnu-g++"
+ar = "/TOOLCHAIN_PATH/bin/s390x-linux-gnu-ar"
+ranlib = "/TOOLCHAIN_PATH/bin/s390x-linux-gnu-ranlib"
+linker = "/TOOLCHAIN_PATH/bin/s390x-linux-gnu-gcc"
+```
+
+To test cross compiled binaries on a non-s390x host, you can use
+[`qemu`](https://www.qemu.org/docs/master/system/target-s390x.html).
+On Ubuntu, a s390x emulator can be obtained with:
+
+```bash
+apt install qemu-system-s390x
+```
+
+Then, in `.cargo/config.toml` set the `runner`:
+
+```toml
+[target.s390x-unknown-linux-gnu]
+runner = "qemu-s390x-static -L /usr/s390x-linux-gnu"
+```
diff --git a/src/doc/rustc/src/platform-support/s390x-unknown-linux-musl.md b/src/doc/rustc/src/platform-support/s390x-unknown-linux-musl.md
new file mode 100644
index 00000000000..e00f8db7f8e
--- /dev/null
+++ b/src/doc/rustc/src/platform-support/s390x-unknown-linux-musl.md
@@ -0,0 +1,83 @@
+# `s390x-unknown-linux-musl`
+
+**Tier: 3**
+
+IBM z/Architecture (s390x) targets (including IBM Z and LinuxONE) running Linux.
+
+## Target maintainers
+
+- Ulrich Weigand, <ulrich.weigand@de.ibm.com>, [@uweigand](https://github.com/uweigand)
+
+## Requirements
+
+This target requires:
+
+* Linux Kernel version 3.2 or later
+* musl 1.2.3 or later
+
+Code generated by the target uses the z/Architecture ISA assuming a minimum
+architecture level of z10 (Eighth Edition of the z/Architecture Principles
+of Operation), and is compliant with the s390x ELF ABI.
+
+Reference material:
+
+* [z/Architecture Principles of Operation][s390x-isa]
+* [z/Architecture ELF Application Binary Interface][s390x-abi]
+
+[s390x-isa]: https://publibfp.dhe.ibm.com/epubs/pdf/a227832d.pdf
+[s390x-abi]: https://github.com/IBM/s390x-abi
+
+## Building the target
+
+Because it is Tier 3, Rust does not yet ship pre-compiled artifacts for this
+target.
+
+Therefore, you can build Rust with support for the target by adding it to the
+target list in `config.toml`, a sample configuration is shown below.
+
+```toml
+[build]
+target = ["s390x-unknown-linux-musl"]
+```
+
+## Building Rust programs
+
+Rust does not yet ship pre-compiled artifacts for this target. To compile for
+this target, you will first need to build Rust with the target enabled (see
+"Building the target" above).
+
+## Testing
+
+There are no special requirements for testing and running the target.
+For testing cross builds on the host, please refer to the "Cross-compilation
+toolchains and C code" section below.
+
+## Cross-compilation toolchains and C code
+
+Rust code built using the target is compatible with C code compiled with
+GCC or Clang using the `s390x-unknown-linux-musl` target triple (via either
+native or cross-compilation).
+
+Depending on your system, you may need to configure the target to use the GNU
+GCC linker. To use it, add the following to your `.cargo/config.toml`:
+
+```toml
+[target.s390x-unknown-linux-musl]
+linker = "s390x-linux-musl-gcc"
+```
+
+If your `s390x-linux-musl-*` toolchain is not in your `PATH` you may need to
+configure additional settings:
+
+```toml
+[target.s390x-unknown-linux-musl]
+# Adjust the paths to point at your toolchain
+cc = "/TOOLCHAIN_PATH/bin/s390x-linux-musl-gcc"
+cxx = "/TOOLCHAIN_PATH/bin/s390x-linux-musl-g++"
+ar = "/TOOLCHAIN_PATH/bin/s390x-linux-musl-ar"
+ranlib = "/TOOLCHAIN_PATH/bin/s390x-linux-musl-ranlib"
+linker = "/TOOLCHAIN_PATH/bin/s390x-linux-musl-gcc"
+```
+
+To test cross compiled binaries on a non-s390x host, you can use
+[`qemu`](https://www.qemu.org/docs/master/system/target-s390x.html).
diff --git a/src/doc/rustc/src/platform-support/wasm32-wasip2.md b/src/doc/rustc/src/platform-support/wasm32-wasip2.md
index bb2348b201e..40049ecfa5f 100644
--- a/src/doc/rustc/src/platform-support/wasm32-wasip2.md
+++ b/src/doc/rustc/src/platform-support/wasm32-wasip2.md
@@ -1,6 +1,6 @@
 # `wasm32-wasip2`
 
-**Tier: 3**
+**Tier: 2**
 
 The `wasm32-wasip2` target is a new and still (as of January 2024) an
 experimental target. This target is an extension to `wasm32-wasip1` target,
diff --git a/src/doc/rustdoc/src/command-line-arguments.md b/src/doc/rustdoc/src/command-line-arguments.md
index f8fb5284472..1af5e2b0e1d 100644
--- a/src/doc/rustdoc/src/command-line-arguments.md
+++ b/src/doc/rustdoc/src/command-line-arguments.md
@@ -447,32 +447,3 @@ This flag is **deprecated** and **has no effect**.
 Rustdoc only supports Rust source code and Markdown input formats. If the
 file ends in `.md` or `.markdown`, `rustdoc` treats it as a Markdown file.
 Otherwise, it assumes that the input file is Rust.
-
-## `--test-builder`: `rustc`-like program to build tests
-
-Using this flag looks like this:
-
-```bash
-$ rustdoc --test-builder /path/to/rustc src/lib.rs
-```
-
-Rustdoc will use the provided program to compile tests instead of the default `rustc` program from
-the sysroot.
-
-## `--test-builder-wrapper`: wrap calls to the test builder
-
-Using this flag looks like this:
-
-```bash
-$ rustdoc --test-builder-wrapper /path/to/rustc-wrapper src/lib.rs
-$ rustdoc \
-    --test-builder-wrapper rustc-wrapper1 \
-    --test-builder-wrapper rustc-wrapper2 \
-    --test-builder rustc \
-    src/lib.rs
-```
-
-Similar to cargo `build.rustc-wrapper` option, this flag takes a `rustc` wrapper program.
-The first argument to the program will be the test builder program.
-
-This flag can be passed multiple times to nest wrappers.
diff --git a/src/doc/rustdoc/src/unstable-features.md b/src/doc/rustdoc/src/unstable-features.md
index ebbe141b6f5..e9524c0b78d 100644
--- a/src/doc/rustdoc/src/unstable-features.md
+++ b/src/doc/rustdoc/src/unstable-features.md
@@ -627,3 +627,36 @@ add the `--scrape-tests` flag.
 
 This flag enables the generation of links in the source code pages which allow the reader
 to jump to a type definition.
+
+### `--test-builder`: `rustc`-like program to build tests
+
+ * Tracking issue: [#102981](https://github.com/rust-lang/rust/issues/102981)
+
+Using this flag looks like this:
+
+```bash
+$ rustdoc --test-builder /path/to/rustc src/lib.rs
+```
+
+Rustdoc will use the provided program to compile tests instead of the default `rustc` program from
+the sysroot.
+
+### `--test-builder-wrapper`: wrap calls to the test builder
+
+ * Tracking issue: [#102981](https://github.com/rust-lang/rust/issues/102981)
+
+Using this flag looks like this:
+
+```bash
+$ rustdoc -Zunstable-options --test-builder-wrapper /path/to/rustc-wrapper src/lib.rs
+$ rustdoc -Zunstable-options \
+    --test-builder-wrapper rustc-wrapper1 \
+    --test-builder-wrapper rustc-wrapper2 \
+    --test-builder rustc \
+    src/lib.rs
+```
+
+Similar to cargo `build.rustc-wrapper` option, this flag takes a `rustc` wrapper program.
+The first argument to the program will be the test builder program.
+
+This flag can be passed multiple times to nest wrappers.
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 9e11360cab4..e42350dc5e6 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -42,7 +42,8 @@ use rustc_errors::{FatalError, struct_span_code_err};
 use rustc_hir::PredicateOrigin;
 use rustc_hir::def::{CtorKind, DefKind, Res};
 use rustc_hir::def_id::{DefId, DefIdMap, DefIdSet, LOCAL_CRATE, LocalDefId};
-use rustc_hir_analysis::lower_ty;
+use rustc_hir_analysis::hir_ty_lowering::FeedConstTy;
+use rustc_hir_analysis::{lower_const_arg_for_rustdoc, lower_ty};
 use rustc_middle::metadata::Reexport;
 use rustc_middle::middle::resolve_bound_vars as rbv;
 use rustc_middle::ty::{self, AdtKind, GenericArgsRef, Ty, TyCtxt, TypeVisitableExt, TypingMode};
@@ -435,10 +436,10 @@ fn clean_middle_term<'tcx>(
 fn clean_hir_term<'tcx>(term: &hir::Term<'tcx>, cx: &mut DocContext<'tcx>) -> Term {
     match term {
         hir::Term::Ty(ty) => Term::Type(clean_ty(ty, cx)),
-        hir::Term::Const(c) => Term::Constant(clean_middle_const(
-            ty::Binder::dummy(ty::Const::from_const_arg(cx.tcx, c, ty::FeedConstTy::No)),
-            cx,
-        )),
+        hir::Term::Const(c) => {
+            let ct = lower_const_arg_for_rustdoc(cx.tcx, c, FeedConstTy::No);
+            Term::Constant(clean_middle_const(ty::Binder::dummy(ct), cx))
+        }
     }
 }
 
@@ -625,7 +626,7 @@ fn clean_generic_param<'tcx>(
             (param.name.ident().name, GenericParamDefKind::Const {
                 ty: Box::new(clean_ty(ty, cx)),
                 default: default.map(|ct| {
-                    Box::new(ty::Const::from_const_arg(cx.tcx, ct, ty::FeedConstTy::No).to_string())
+                    Box::new(lower_const_arg_for_rustdoc(cx.tcx, ct, FeedConstTy::No).to_string())
                 }),
                 synthetic,
             })
@@ -1813,14 +1814,14 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T
                     // `const_eval_poly` tries to first substitute generic parameters which
                     // results in an ICE while manually constructing the constant and using `eval`
                     // does nothing for `ConstKind::Param`.
-                    let ct = ty::Const::from_const_arg(cx.tcx, const_arg, ty::FeedConstTy::No);
+                    let ct = lower_const_arg_for_rustdoc(cx.tcx, const_arg, FeedConstTy::No);
                     let ct = if let hir::ConstArgKind::Anon(hir::AnonConst { def_id, .. }) =
                         const_arg.kind
                     {
                         // Only anon consts can implicitly capture params.
                         // FIXME: is this correct behavior?
-                        let param_env = cx.tcx.param_env(*def_id);
-                        cx.tcx.normalize_erasing_regions(param_env, ct)
+                        let typing_env = ty::TypingEnv::from_param_env(cx.tcx.param_env(*def_id));
+                        cx.tcx.normalize_erasing_regions(typing_env, ct)
                     } else {
                         ct
                     };
@@ -2039,7 +2040,7 @@ pub(crate) fn clean_middle_ty<'tcx>(
             format!("{pat:?}").into_boxed_str(),
         ),
         ty::Array(ty, n) => {
-            let n = cx.tcx.normalize_erasing_regions(cx.param_env, n);
+            let n = cx.tcx.normalize_erasing_regions(cx.typing_env(), n);
             let n = print_const(cx, n);
             Array(Box::new(clean_middle_ty(bound_ty.rebind(ty), cx, None, None)), n.into())
         }
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index e3a0dbe1a7f..a10a6a92bf5 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -772,8 +772,10 @@ impl Item {
                         .find(|field| {
                             let ty =
                                 field.ty(tcx, ty::GenericArgs::identity_for_item(tcx, field.did));
-                            tcx.layout_of(tcx.param_env(field.did).and(ty))
-                                .is_ok_and(|layout| !layout.is_1zst())
+                            tcx.layout_of(
+                                ty::TypingEnv::post_analysis(tcx, field.did).as_query_input(ty),
+                            )
+                            .is_ok_and(|layout| !layout.is_1zst())
                         })
                         .map_or_else(
                             || adt.all_fields().any(|field| field.vis.is_public()),
diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs
index e551e0170c6..d59b4e4081c 100644
--- a/src/librustdoc/clean/utils.rs
+++ b/src/librustdoc/clean/utils.rs
@@ -419,7 +419,10 @@ fn print_const_with_custom_print_scalar<'tcx>(
         }
         (mir::Const::Val(mir::ConstValue::Scalar(int), _), ty::Int(i)) => {
             let ty = ct.ty();
-            let size = tcx.layout_of(ty::ParamEnv::empty().and(ty)).unwrap().size;
+            let size = tcx
+                .layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(ty))
+                .unwrap()
+                .size;
             let sign_extended_data = int.assert_scalar_int().to_int(size);
             let mut output = if with_underscores {
                 format_integer_with_underscore_sep(&sign_extended_data.to_string())
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index d5f6bfe415d..a562a9eee71 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -19,7 +19,7 @@ use rustc_hir::{HirId, Path};
 use rustc_interface::interface;
 use rustc_lint::{MissingDoc, late_lint_mod};
 use rustc_middle::hir::nested_filter;
-use rustc_middle::ty::{ParamEnv, Ty, TyCtxt};
+use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt};
 use rustc_session::config::{self, CrateType, ErrorOutputType, Input, ResolveDocLinks};
 pub(crate) use rustc_session::config::{Options, UnstableOptions};
 use rustc_session::{Session, lint};
@@ -88,6 +88,13 @@ impl<'tcx> DocContext<'tcx> {
         ret
     }
 
+    pub(crate) fn typing_env(&self) -> ty::TypingEnv<'tcx> {
+        ty::TypingEnv {
+            typing_mode: ty::TypingMode::non_body_analysis(),
+            param_env: self.param_env,
+        }
+    }
+
     /// Call the closure with the given parameters set as
     /// the generic parameters for a type alias' RHS.
     pub(crate) fn enter_alias<F, R>(
diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs
index 4def80764ea..29f6f92a6b2 100644
--- a/src/librustdoc/html/highlight.rs
+++ b/src/librustdoc/html/highlight.rs
@@ -861,10 +861,9 @@ impl<'src> Classifier<'src> {
                 },
                 Some(c) => c,
             },
-            TokenKind::RawIdent
-            | TokenKind::UnknownPrefix
-            | TokenKind::InvalidPrefix
-            | TokenKind::InvalidIdent => Class::Ident(self.new_span(before, text)),
+            TokenKind::RawIdent | TokenKind::UnknownPrefix | TokenKind::InvalidIdent => {
+                Class::Ident(self.new_span(before, text))
+            }
             TokenKind::Lifetime { .. }
             | TokenKind::RawLifetime
             | TokenKind::UnknownPrefixLifetime => Class::Lifetime,
diff --git a/src/librustdoc/html/render/span_map.rs b/src/librustdoc/html/render/span_map.rs
index b314b060368..d4cca562d6c 100644
--- a/src/librustdoc/html/render/span_map.rs
+++ b/src/librustdoc/html/render/span_map.rs
@@ -36,7 +36,7 @@ pub(crate) enum LinkFromSrc {
 /// It returns the `krate`, the source code files and the `span` correspondence map.
 ///
 /// Note about the `span` correspondence map: the keys are actually `(lo, hi)` of `span`s. We don't
-/// need the `span` context later on, only their position, so instead of keep a whole `Span`, we
+/// need the `span` context later on, only their position, so instead of keeping a whole `Span`, we
 /// only keep the `lo` and `hi`.
 pub(crate) fn collect_spans_and_sources(
     tcx: TyCtxt<'_>,
@@ -45,9 +45,9 @@ pub(crate) fn collect_spans_and_sources(
     include_sources: bool,
     generate_link_to_definition: bool,
 ) -> (FxIndexMap<PathBuf, String>, FxHashMap<Span, LinkFromSrc>) {
-    let mut visitor = SpanMapVisitor { tcx, matches: FxHashMap::default() };
-
     if include_sources {
+        let mut visitor = SpanMapVisitor { tcx, matches: FxHashMap::default() };
+
         if generate_link_to_definition {
             tcx.hir().walk_toplevel_module(&mut visitor);
         }
@@ -76,7 +76,22 @@ impl<'tcx> SpanMapVisitor<'tcx> {
                 } else {
                     LinkFromSrc::External(def_id)
                 };
-                self.matches.insert(path.span, link);
+                // In case the path ends with generics, we remove them from the span.
+                let span = path
+                    .segments
+                    .last()
+                    .map(|last| {
+                        // In `use` statements, the included item is not in the path segments.
+                        // However, it doesn't matter because you can't have generics on `use`
+                        // statements.
+                        if path.span.contains(last.ident.span) {
+                            path.span.with_hi(last.ident.span.hi())
+                        } else {
+                            path.span
+                        }
+                    })
+                    .unwrap_or(path.span);
+                self.matches.insert(span, link);
             }
             Res::Local(_) => {
                 if let Some(span) = self.tcx.hir().res_span(path.res) {
diff --git a/src/librustdoc/html/render/type_layout.rs b/src/librustdoc/html/render/type_layout.rs
index d85ba3a2b14..9317844956d 100644
--- a/src/librustdoc/html/render/type_layout.rs
+++ b/src/librustdoc/html/render/type_layout.rs
@@ -37,9 +37,9 @@ pub(crate) fn document_type_layout<'a, 'cx: 'a>(
         }
 
         let tcx = cx.tcx();
-        let param_env = tcx.param_env(ty_def_id);
+        let typing_env = ty::TypingEnv::post_analysis(tcx, ty_def_id);
         let ty = tcx.type_of(ty_def_id).instantiate_identity();
-        let type_layout = tcx.layout_of(param_env.and(ty));
+        let type_layout = tcx.layout_of(typing_env.as_query_input(ty));
 
         let variants = if let Ok(type_layout) = type_layout
             && let Variants::Multiple { variants, tag, tag_encoding, .. } =
@@ -71,7 +71,7 @@ pub(crate) fn document_type_layout<'a, 'cx: 'a>(
             Vec::new()
         };
 
-        let type_layout_size = tcx.layout_of(param_env.and(ty)).map(|layout| {
+        let type_layout_size = tcx.layout_of(typing_env.as_query_input(ty)).map(|layout| {
             let is_unsized = layout.is_unsized();
             let is_uninhabited = layout.is_uninhabited();
             let size = layout.size.bytes();
diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js
index c1a021e9f8d..9e5cf497211 100644
--- a/src/librustdoc/html/static/js/search.js
+++ b/src/librustdoc/html/static/js/search.js
@@ -988,6 +988,12 @@ class VlqHexDecoder {
 }
 class RoaringBitmap {
     constructor(str) {
+        // https://github.com/RoaringBitmap/RoaringFormatSpec
+        //
+        // Roaring bitmaps are used for flags that can be kept in their
+        // compressed form, even when loaded into memory. This decoder
+        // turns the containers into objects, but uses byte array
+        // slices of the original format for the data payload.
         const strdecoded = atob(str);
         const u8array = new Uint8Array(strdecoded.length);
         for (let j = 0; j < strdecoded.length; ++j) {
@@ -1053,9 +1059,24 @@ class RoaringBitmap {
     contains(keyvalue) {
         const key = keyvalue >> 16;
         const value = keyvalue & 0xFFFF;
-        for (let i = 0; i < this.keys.length; ++i) {
-            if (this.keys[i] === key) {
-                return this.containers[i].contains(value);
+        // Binary search algorithm copied from
+        // https://en.wikipedia.org/wiki/Binary_search#Procedure
+        //
+        // Format is required by specification to be sorted.
+        // Because keys are 16 bits and unique, length can't be
+        // bigger than 2**16, and because we have 32 bits of safe int,
+        // left + right can't overflow.
+        let left = 0;
+        let right = this.keys.length - 1;
+        while (left <= right) {
+            const mid = Math.floor((left + right) / 2);
+            const x = this.keys[mid];
+            if (x < key) {
+                left = mid + 1;
+            } else if (x > key) {
+                right = mid - 1;
+            } else {
+                return this.containers[mid].contains(value);
             }
         }
         return false;
@@ -1068,11 +1089,23 @@ class RoaringBitmapRun {
         this.array = array;
     }
     contains(value) {
-        const l = this.runcount * 4;
-        for (let i = 0; i < l; i += 4) {
+        // Binary search algorithm copied from
+        // https://en.wikipedia.org/wiki/Binary_search#Procedure
+        //
+        // Since runcount is stored as 16 bits, left + right
+        // can't overflow.
+        let left = 0;
+        let right = this.runcount - 1;
+        while (left <= right) {
+            const mid = Math.floor((left + right) / 2);
+            const i = mid * 4;
             const start = this.array[i] | (this.array[i + 1] << 8);
             const lenm1 = this.array[i + 2] | (this.array[i + 3] << 8);
-            if (value >= start && value <= (start + lenm1)) {
+            if ((start + lenm1) < value) {
+                left = mid + 1;
+            } else if (start > value) {
+                right = mid - 1;
+            } else {
                 return true;
             }
         }
@@ -1085,10 +1118,22 @@ class RoaringBitmapArray {
         this.array = array;
     }
     contains(value) {
-        const l = this.cardinality * 2;
-        for (let i = 0; i < l; i += 2) {
-            const start = this.array[i] | (this.array[i + 1] << 8);
-            if (value === start) {
+        // Binary search algorithm copied from
+        // https://en.wikipedia.org/wiki/Binary_search#Procedure
+        //
+        // Since cardinality can't be higher than 4096, left + right
+        // cannot overflow.
+        let left = 0;
+        let right = this.cardinality - 1;
+        while (left <= right) {
+            const mid = Math.floor((left + right) / 2);
+            const i = mid * 2;
+            const x = this.array[i] | (this.array[i + 1] << 8);
+            if (x < value) {
+                left = mid + 1;
+            } else if (x > value) {
+                right = mid - 1;
+            } else {
                 return true;
             }
         }
diff --git a/src/tools/clippy/clippy_lints/src/assigning_clones.rs b/src/tools/clippy/clippy_lints/src/assigning_clones.rs
index 0b82c0cd04c..00626a37ef8 100644
--- a/src/tools/clippy/clippy_lints/src/assigning_clones.rs
+++ b/src/tools/clippy/clippy_lints/src/assigning_clones.rs
@@ -96,7 +96,7 @@ impl<'tcx> LateLintPass<'tcx> for AssigningClones {
                 },
                 _ => return,
             }
-            && let Ok(Some(resolved_fn)) = Instance::try_resolve(cx.tcx, cx.param_env, fn_id, fn_gen_args)
+            && let Ok(Some(resolved_fn)) = Instance::try_resolve(cx.tcx, cx.typing_env(), fn_id, fn_gen_args)
             // TODO: This check currently bails if the local variable has no initializer.
             // That is overly conservative - the lint should fire even if there was no initializer,
             // but the variable has been initialized before `lhs` was evaluated.
diff --git a/src/tools/clippy/clippy_lints/src/bool_assert_comparison.rs b/src/tools/clippy/clippy_lints/src/bool_assert_comparison.rs
index 7d89195eeca..adac2f27ea8 100644
--- a/src/tools/clippy/clippy_lints/src/bool_assert_comparison.rs
+++ b/src/tools/clippy/clippy_lints/src/bool_assert_comparison.rs
@@ -62,7 +62,7 @@ fn is_impl_not_trait_with_bool_out<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -
         })
         .is_some_and(|assoc_item| {
             let proj = Ty::new_projection(cx.tcx, assoc_item.def_id, cx.tcx.mk_args_trait(ty, []));
-            let nty = cx.tcx.normalize_erasing_regions(cx.param_env, proj);
+            let nty = cx.tcx.normalize_erasing_regions(cx.typing_env(), proj);
 
             nty.is_bool()
         })
diff --git a/src/tools/clippy/clippy_lints/src/dereference.rs b/src/tools/clippy/clippy_lints/src/dereference.rs
index b167d7f2208..f864b7a5a8a 100644
--- a/src/tools/clippy/clippy_lints/src/dereference.rs
+++ b/src/tools/clippy/clippy_lints/src/dereference.rs
@@ -17,7 +17,7 @@ use rustc_hir::{
 };
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability};
-use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt, TypeVisitableExt, TypeckResults};
+use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt, TypeckResults};
 use rustc_session::impl_lint_pass;
 use rustc_span::symbol::sym;
 use rustc_span::{Span, Symbol};
@@ -755,7 +755,8 @@ impl TyCoercionStability {
             DefinedTy::Hir(ty) => Self::for_hir_ty(ty),
             DefinedTy::Mir(ty) => Self::for_mir_ty(
                 cx.tcx,
-                ty.param_env,
+                // FIXME(#132279): convert `DefinedTy` to use `TypingEnv` instead.
+                ty::TypingEnv::from_param_env(ty.param_env),
                 cx.tcx.instantiate_bound_regions_with_erased(ty.value),
                 for_return,
             ),
@@ -823,12 +824,12 @@ impl TyCoercionStability {
         }
     }
 
-    fn for_mir_ty<'tcx>(tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, ty: Ty<'tcx>, for_return: bool) -> Self {
+    fn for_mir_ty<'tcx>(tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>, ty: Ty<'tcx>, for_return: bool) -> Self {
         let ty::Ref(_, mut ty, _) = *ty.kind() else {
             return Self::None;
         };
 
-        ty = tcx.try_normalize_erasing_regions(param_env, ty).unwrap_or(ty);
+        ty = tcx.try_normalize_erasing_regions(typing_env, ty).unwrap_or(ty);
         loop {
             break match *ty.kind() {
                 ty::Ref(_, ref_ty, _) => {
diff --git a/src/tools/clippy/clippy_lints/src/drop_forget_ref.rs b/src/tools/clippy/clippy_lints/src/drop_forget_ref.rs
index 55afdbf22e1..617982f4da3 100644
--- a/src/tools/clippy/clippy_lints/src/drop_forget_ref.rs
+++ b/src/tools/clippy/clippy_lints/src/drop_forget_ref.rs
@@ -99,7 +99,7 @@ impl<'tcx> LateLintPass<'tcx> for DropForgetRef {
                 sym::mem_forget if is_copy => return,
                 sym::mem_drop if is_type_lang_item(cx, arg_ty, LangItem::ManuallyDrop) => return,
                 sym::mem_drop
-                    if !(arg_ty.needs_drop(cx.tcx, cx.param_env)
+                    if !(arg_ty.needs_drop(cx.tcx, cx.typing_env())
                         || is_must_use_func_call(cx, arg)
                         || is_must_use_ty(cx, arg_ty)
                         || drop_is_single_call_in_arm) =>
@@ -107,7 +107,7 @@ impl<'tcx> LateLintPass<'tcx> for DropForgetRef {
                     (DROP_NON_DROP, DROP_NON_DROP_SUMMARY.into(), Some(arg.span))
                 },
                 sym::mem_forget => {
-                    if arg_ty.needs_drop(cx.tcx, cx.param_env) {
+                    if arg_ty.needs_drop(cx.tcx, cx.typing_env()) {
                         (
                             MEM_FORGET,
                             Cow::Owned(format!(
diff --git a/src/tools/clippy/clippy_lints/src/iter_not_returning_iterator.rs b/src/tools/clippy/clippy_lints/src/iter_not_returning_iterator.rs
index 25105817ad9..4bc6ad0798c 100644
--- a/src/tools/clippy/clippy_lints/src/iter_not_returning_iterator.rs
+++ b/src/tools/clippy/clippy_lints/src/iter_not_returning_iterator.rs
@@ -70,7 +70,7 @@ fn check_sig(cx: &LateContext<'_>, name: Symbol, sig: &FnSig<'_>, fn_id: LocalDe
             .instantiate_bound_regions_with_erased(cx.tcx.fn_sig(fn_id).instantiate_identity().output());
         let ret_ty = cx
             .tcx
-            .try_normalize_erasing_regions(cx.param_env, ret_ty)
+            .try_normalize_erasing_regions(cx.typing_env(), ret_ty)
             .unwrap_or(ret_ty);
         if cx
             .tcx
diff --git a/src/tools/clippy/clippy_lints/src/iter_without_into_iter.rs b/src/tools/clippy/clippy_lints/src/iter_without_into_iter.rs
index 314d0dfa26c..906da81b183 100644
--- a/src/tools/clippy/clippy_lints/src/iter_without_into_iter.rs
+++ b/src/tools/clippy/clippy_lints/src/iter_without_into_iter.rs
@@ -215,7 +215,7 @@ impl {self_ty_without_ref} {{
             && implements_trait(cx, ret_ty, iterator_did, &[])
             && let Some(iter_ty) = make_normalized_projection(
                 cx.tcx,
-                cx.param_env,
+                cx.typing_env(),
                 iterator_did,
                 sym::Item,
                 [ret_ty],
diff --git a/src/tools/clippy/clippy_lints/src/large_const_arrays.rs b/src/tools/clippy/clippy_lints/src/large_const_arrays.rs
index c5a2760234f..644365c9fe5 100644
--- a/src/tools/clippy/clippy_lints/src/large_const_arrays.rs
+++ b/src/tools/clippy/clippy_lints/src/large_const_arrays.rs
@@ -4,7 +4,7 @@ use rustc_errors::Applicability;
 use rustc_hir::{Item, ItemKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty::layout::LayoutOf;
-use rustc_middle::ty::{self, ParamEnv};
+use rustc_middle::ty;
 use rustc_session::impl_lint_pass;
 use rustc_span::{BytePos, Pos, Span};
 
@@ -57,7 +57,7 @@ impl<'tcx> LateLintPass<'tcx> for LargeConstArrays {
             && let ty = cx.tcx.type_of(item.owner_id).instantiate_identity()
             && let ty::Array(element_type, cst) = ty.kind()
             && let Some((ty::ValTree::Leaf(element_count), _)) = cx.tcx
-                .try_normalize_erasing_regions(ParamEnv::empty(), *cst).unwrap_or(*cst).try_to_valtree()
+                .try_normalize_erasing_regions(cx.typing_env(), *cst).unwrap_or(*cst).try_to_valtree()
             && let element_count = element_count.to_target_usize(cx.tcx)
             && let Ok(element_size) = cx.layout_of(*element_type).map(|l| l.size.bytes())
             && u128::from(self.maximum_allowed_size) < u128::from(element_count) * u128::from(element_size)
diff --git a/src/tools/clippy/clippy_lints/src/large_futures.rs b/src/tools/clippy/clippy_lints/src/large_futures.rs
index 25f9be8b2d7..593704f206a 100644
--- a/src/tools/clippy/clippy_lints/src/large_futures.rs
+++ b/src/tools/clippy/clippy_lints/src/large_futures.rs
@@ -63,7 +63,7 @@ impl<'tcx> LateLintPass<'tcx> for LargeFuture {
             && let ty = cx.typeck_results().expr_ty(arg)
             && let Some(future_trait_def_id) = cx.tcx.lang_items().future_trait()
             && implements_trait(cx, ty, future_trait_def_id, &[])
-            && let Ok(layout) = cx.tcx.layout_of(cx.param_env.and(ty))
+            && let Ok(layout) = cx.tcx.layout_of(cx.typing_env().as_query_input(ty))
             && let size = layout.layout.size()
             && size >= Size::from_bytes(self.future_size_threshold)
         {
diff --git a/src/tools/clippy/clippy_lints/src/large_stack_frames.rs b/src/tools/clippy/clippy_lints/src/large_stack_frames.rs
index d2bdf194ada..5ed948c02bb 100644
--- a/src/tools/clippy/clippy_lints/src/large_stack_frames.rs
+++ b/src/tools/clippy/clippy_lints/src/large_stack_frames.rs
@@ -150,11 +150,11 @@ impl<'tcx> LateLintPass<'tcx> for LargeStackFrames {
         }
 
         let mir = cx.tcx.optimized_mir(def_id);
-        let param_env = cx.tcx.param_env(def_id);
+        let typing_env = mir.typing_env(cx.tcx);
 
         let sizes_of_locals = || {
             mir.local_decls.iter().filter_map(|local| {
-                let layout = cx.tcx.layout_of(param_env.and(local.ty)).ok()?;
+                let layout = cx.tcx.layout_of(typing_env.as_query_input(local.ty)).ok()?;
                 Some((local, layout.size.bytes()))
             })
         };
diff --git a/src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs b/src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs
index ee561ea85ed..48318682f33 100644
--- a/src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs
@@ -151,7 +151,7 @@ fn is_ref_iterable<'tcx>(
                 // Using by value won't consume anything
                 if implements_trait(cx, self_ty, trait_id, &[])
                     && let Some(ty) =
-                        make_normalized_projection(cx.tcx, cx.param_env, trait_id, sym!(IntoIter), [self_ty])
+                        make_normalized_projection(cx.tcx, cx.typing_env(), trait_id, sym!(IntoIter), [self_ty])
                     && ty == res_ty
                 {
                     return Some((AdjustKind::None, self_ty));
@@ -168,7 +168,7 @@ fn is_ref_iterable<'tcx>(
                 };
                 if implements_trait(cx, self_ty, trait_id, &[])
                     && let Some(ty) =
-                        make_normalized_projection(cx.tcx, cx.param_env, trait_id, sym!(IntoIter), [self_ty])
+                        make_normalized_projection(cx.tcx, cx.typing_env(), trait_id, sym!(IntoIter), [self_ty])
                     && ty == res_ty
                 {
                     return Some((AdjustKind::reborrow(mutbl), self_ty));
@@ -181,7 +181,7 @@ fn is_ref_iterable<'tcx>(
             // Attempt to borrow
             let self_ty = Ty::new_ref(cx.tcx, cx.tcx.lifetimes.re_erased, self_ty, mutbl);
             if implements_trait(cx, self_ty, trait_id, &[])
-                && let Some(ty) = make_normalized_projection(cx.tcx, cx.param_env, trait_id, sym!(IntoIter), [self_ty])
+                && let Some(ty) = make_normalized_projection(cx.tcx, cx.typing_env(), trait_id, sym!(IntoIter), [self_ty])
                 && ty == res_ty
             {
                 return Some((AdjustKind::borrow(mutbl), self_ty));
@@ -204,7 +204,7 @@ fn is_ref_iterable<'tcx>(
                     && target != self_ty
                     && implements_trait(cx, target, trait_id, &[])
                     && let Some(ty) =
-                        make_normalized_projection(cx.tcx, cx.param_env, trait_id, sym!(IntoIter), [target])
+                        make_normalized_projection(cx.tcx, cx.typing_env(), trait_id, sym!(IntoIter), [target])
                     && ty == res_ty
                 {
                     Some((AdjustKind::auto_reborrow(mutbl), target))
@@ -222,7 +222,7 @@ fn is_ref_iterable<'tcx>(
                 if is_copy(cx, target)
                     && implements_trait(cx, target, trait_id, &[])
                     && let Some(ty) =
-                        make_normalized_projection(cx.tcx, cx.param_env, trait_id, sym!(IntoIter), [target])
+                        make_normalized_projection(cx.tcx, cx.typing_env(), trait_id, sym!(IntoIter), [target])
                     && ty == res_ty
                 {
                     Some((AdjustKind::Deref, target))
@@ -240,7 +240,7 @@ fn is_ref_iterable<'tcx>(
                 if self_ty.is_ref()
                     && implements_trait(cx, target, trait_id, &[])
                     && let Some(ty) =
-                        make_normalized_projection(cx.tcx, cx.param_env, trait_id, sym!(IntoIter), [target])
+                        make_normalized_projection(cx.tcx, cx.typing_env(), trait_id, sym!(IntoIter), [target])
                     && ty == res_ty
                 {
                     Some((AdjustKind::auto_borrow(mutbl), target))
diff --git a/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs b/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs
index 9c41528e647..c00b9b368c4 100644
--- a/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs
@@ -203,10 +203,10 @@ fn is_is_empty_sig(cx: &LateContext<'_>, call_id: HirId) -> bool {
 fn iterates_same_ty<'tcx>(cx: &LateContext<'tcx>, iter_ty: Ty<'tcx>, collect_ty: Ty<'tcx>) -> bool {
     if let Some(iter_trait) = cx.tcx.get_diagnostic_item(sym::Iterator)
         && let Some(into_iter_trait) = cx.tcx.get_diagnostic_item(sym::IntoIterator)
-        && let Some(iter_item_ty) = make_normalized_projection(cx.tcx, cx.param_env, iter_trait, sym::Item, [iter_ty])
+        && let Some(iter_item_ty) = make_normalized_projection(cx.tcx, cx.typing_env(), iter_trait, sym::Item, [iter_ty])
         && let Some(into_iter_item_proj) = make_projection(cx.tcx, into_iter_trait, sym::Item, [collect_ty])
         && let Ok(into_iter_item_ty) = cx.tcx.try_normalize_erasing_regions(
-            cx.param_env,
+            cx.typing_env(),
             Ty::new_projection_from_args(cx.tcx, into_iter_item_proj.def_id, into_iter_item_proj.args),
         )
     {
@@ -237,7 +237,7 @@ fn is_contains_sig(cx: &LateContext<'_>, call_id: HirId, iter_expr: &Expr<'_>) -
         )
         && let args = cx.tcx.mk_args(&[GenericArg::from(typeck.expr_ty_adjusted(iter_expr))])
         && let proj_ty = Ty::new_projection_from_args(cx.tcx, iter_item.def_id, args)
-        && let Ok(item_ty) = cx.tcx.try_normalize_erasing_regions(cx.param_env, proj_ty)
+        && let Ok(item_ty) = cx.tcx.try_normalize_erasing_regions(cx.typing_env(), proj_ty)
     {
         item_ty == EarlyBinder::bind(search_ty).instantiate(cx.tcx, cx.typeck_results().node_args(call_id))
     } else {
diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_min_or_max.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_min_or_max.rs
index 062d1348555..7d01bdc2269 100644
--- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_min_or_max.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_min_or_max.rs
@@ -19,7 +19,7 @@ pub(super) fn check<'tcx>(
     arg: &'tcx Expr<'_>,
 ) {
     let typeck_results = cx.typeck_results();
-    let ecx = ConstEvalCtxt::with_env(cx.tcx, cx.param_env, typeck_results);
+    let ecx = ConstEvalCtxt::with_env(cx.tcx, cx.typing_env(), typeck_results);
     if let Some(id) = typeck_results.type_dependent_def_id(expr.hir_id)
         && (cx.tcx.is_diagnostic_item(sym::cmp_ord_min, id) || cx.tcx.is_diagnostic_item(sym::cmp_ord_max, id))
     {
diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs
index 82549413fa9..84ea3554a35 100644
--- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs
@@ -578,7 +578,7 @@ fn can_change_type<'a>(cx: &LateContext<'a>, mut expr: &'a Expr<'a>, mut ty: Ty<
                         if output_ty.contains(param_ty) {
                             if let Ok(new_ty) = cx.tcx.try_instantiate_and_normalize_erasing_regions(
                                 new_subst,
-                                cx.param_env,
+                                cx.typing_env(),
                                 bound_fn_sig.rebind(output_ty),
                             ) {
                                 expr = parent_expr;
diff --git a/src/tools/clippy/clippy_lints/src/methods/zst_offset.rs b/src/tools/clippy/clippy_lints/src/methods/zst_offset.rs
index d33021c2a7b..102fa7bc895 100644
--- a/src/tools/clippy/clippy_lints/src/methods/zst_offset.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/zst_offset.rs
@@ -7,7 +7,7 @@ use super::ZST_OFFSET;
 
 pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr<'_>) {
     if let ty::RawPtr(ty, _) = cx.typeck_results().expr_ty(recv).kind()
-        && let Ok(layout) = cx.tcx.layout_of(cx.param_env.and(*ty))
+        && let Ok(layout) = cx.tcx.layout_of(cx.typing_env().as_query_input(*ty))
         && layout.is_zst()
     {
         span_lint(cx, ZST_OFFSET, expr.span, "offset calculation on zero-sized value");
diff --git a/src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs b/src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs
index c1424b9f1dc..43b885fbd2c 100644
--- a/src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs
@@ -421,7 +421,7 @@ fn replace_types<'tcx>(
                         .expect_ty(cx.tcx)
                         .to_ty(cx.tcx);
 
-                    if let Ok(projected_ty) = cx.tcx.try_normalize_erasing_regions(cx.param_env, projection)
+                    if let Ok(projected_ty) = cx.tcx.try_normalize_erasing_regions(cx.typing_env(), projection)
                         && args[term_param_ty.index as usize] != GenericArg::from(projected_ty)
                     {
                         deque.push_back((*term_param_ty, projected_ty));
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 5e20b406426..57fa4797c5e 100644
--- a/src/tools/clippy/clippy_lints/src/non_copy_const.rs
+++ b/src/tools/clippy/clippy_lints/src/non_copy_const.rs
@@ -278,23 +278,23 @@ impl<'tcx> NonCopyConst<'tcx> {
     fn is_value_unfrozen_expr(cx: &LateContext<'tcx>, hir_id: HirId, def_id: DefId, ty: Ty<'tcx>) -> bool {
         let args = cx.typeck_results().node_args(hir_id);
 
-        let result = Self::const_eval_resolve(cx.tcx, cx.param_env, ty::UnevaluatedConst::new(def_id, args), DUMMY_SP);
+        let result = Self::const_eval_resolve(cx.tcx, cx.typing_env(), ty::UnevaluatedConst::new(def_id, args), DUMMY_SP);
         Self::is_value_unfrozen_raw(cx, result, ty)
     }
 
     pub fn const_eval_resolve(
         tcx: TyCtxt<'tcx>,
-        param_env: ty::ParamEnv<'tcx>,
+        typing_env: ty::TypingEnv<'tcx>,
         ct: ty::UnevaluatedConst<'tcx>,
         span: Span,
     ) -> EvalToValTreeResult<'tcx> {
-        match ty::Instance::try_resolve(tcx, param_env, ct.def, ct.args) {
+        match ty::Instance::try_resolve(tcx, typing_env, ct.def, ct.args) {
             Ok(Some(instance)) => {
                 let cid = GlobalId {
                     instance,
                     promoted: None,
                 };
-                tcx.const_eval_global_id_for_typeck(param_env, cid, span)
+                tcx.const_eval_global_id_for_typeck(typing_env.param_env, cid, span)
             },
             Ok(None) => Err(ErrorHandled::TooGeneric(span)),
             Err(err) => Err(ErrorHandled::Reported(err.into(), span)),
@@ -321,7 +321,7 @@ impl<'tcx> LateLintPass<'tcx> for NonCopyConst<'tcx> {
 
             // Normalize assoc types because ones originated from generic params
             // bounded other traits could have their bound.
-            let normalized = cx.tcx.normalize_erasing_regions(cx.param_env, ty);
+            let normalized = cx.tcx.normalize_erasing_regions(cx.typing_env(), ty);
             if self.interior_mut.is_interior_mut_ty(cx, normalized)
                 // When there's no default value, lint it only according to its type;
                 // in other words, lint consts whose value *could* be unfrozen, not definitely is.
@@ -361,12 +361,12 @@ impl<'tcx> LateLintPass<'tcx> for NonCopyConst<'tcx> {
                             .trait_item_def_id
                         && cx
                             .tcx
-                            .layout_of(cx.tcx.param_env(of_trait_def_id).and(
+                            .layout_of(ty::TypingEnv::post_analysis(cx.tcx, of_trait_def_id).as_query_input(
                                 // Normalize assoc types because ones originated from generic params
                                 // bounded other traits could have their bound at the trait defs;
                                 // and, in that case, the definition is *not* generic.
                                 cx.tcx.normalize_erasing_regions(
-                                    cx.tcx.param_env(of_trait_def_id),
+                                    ty::TypingEnv::post_analysis(cx.tcx, of_trait_def_id),
                                     cx.tcx.type_of(of_assoc_item).instantiate_identity(),
                                 ),
                             ))
@@ -376,7 +376,7 @@ impl<'tcx> LateLintPass<'tcx> for NonCopyConst<'tcx> {
                             // similar to unknown layouts.
                             // e.g. `layout_of(...).is_err() || has_frozen_variant(...);`
                         && let ty = cx.tcx.type_of(impl_item.owner_id).instantiate_identity()
-                        && let normalized = cx.tcx.normalize_erasing_regions(cx.param_env, ty)
+                        && let normalized = cx.tcx.normalize_erasing_regions(cx.typing_env(), ty)
                         && self.interior_mut.is_interior_mut_ty(cx, normalized)
                         && Self::is_value_unfrozen_poly(cx, *body_id, normalized)
                     {
@@ -386,7 +386,7 @@ impl<'tcx> LateLintPass<'tcx> for NonCopyConst<'tcx> {
                 ItemKind::Impl(Impl { of_trait: None, .. }) => {
                     let ty = cx.tcx.type_of(impl_item.owner_id).instantiate_identity();
                     // Normalize assoc types originated from generic params.
-                    let normalized = cx.tcx.normalize_erasing_regions(cx.param_env, ty);
+                    let normalized = cx.tcx.normalize_erasing_regions(cx.typing_env(), ty);
 
                     if self.interior_mut.is_interior_mut_ty(cx, normalized)
                         && Self::is_value_unfrozen_poly(cx, *body_id, normalized)
diff --git a/src/tools/clippy/clippy_lints/src/operators/const_comparisons.rs b/src/tools/clippy/clippy_lints/src/operators/const_comparisons.rs
index 5d94cfab3b0..1a0bfd8b997 100644
--- a/src/tools/clippy/clippy_lints/src/operators/const_comparisons.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/const_comparisons.rs
@@ -26,7 +26,7 @@ fn comparison_to_const<'tcx>(
     if let ExprKind::Binary(operator, left, right) = expr.kind
         && let Ok(cmp_op) = CmpOp::try_from(operator.node)
     {
-        let ecx = ConstEvalCtxt::with_env(cx.tcx, cx.param_env, typeck);
+        let ecx = ConstEvalCtxt::with_env(cx.tcx, cx.typing_env(), typeck);
         match (ecx.eval(left), ecx.eval(right)) {
             (Some(_), Some(_)) => None,
             (_, Some(con)) => Some((cmp_op, left, right, con, typeck.expr_ty(right))),
diff --git a/src/tools/clippy/clippy_lints/src/operators/erasing_op.rs b/src/tools/clippy/clippy_lints/src/operators/erasing_op.rs
index 24bfe2b050b..e3fc8d8fea7 100644
--- a/src/tools/clippy/clippy_lints/src/operators/erasing_op.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/erasing_op.rs
@@ -39,7 +39,7 @@ fn check_op<'tcx>(
     other: &Expr<'tcx>,
     parent: &Expr<'tcx>,
 ) {
-    if ConstEvalCtxt::with_env(cx.tcx, cx.param_env, tck).eval_simple(op) == Some(Constant::Int(0)) {
+    if ConstEvalCtxt::with_env(cx.tcx, cx.typing_env(), tck).eval_simple(op) == Some(Constant::Int(0)) {
         if different_types(tck, other, parent) {
             return;
         }
diff --git a/src/tools/clippy/clippy_lints/src/operators/float_cmp.rs b/src/tools/clippy/clippy_lints/src/operators/float_cmp.rs
index ab5f91c1d67..8272d3643d4 100644
--- a/src/tools/clippy/clippy_lints/src/operators/float_cmp.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/float_cmp.rs
@@ -17,8 +17,7 @@ pub(crate) fn check<'tcx>(
     right: &'tcx Expr<'_>,
 ) {
     if (op == BinOpKind::Eq || op == BinOpKind::Ne) && is_float(cx, left) {
-        let typeck = cx.typeck_results();
-        let ecx = ConstEvalCtxt::with_env(cx.tcx, cx.param_env, typeck);
+        let ecx = ConstEvalCtxt::new(cx);
         let left_is_local = match ecx.eval_with_source(left) {
             Some((c, s)) if !is_allowed(&c) => s.is_local(),
             Some(_) => return,
diff --git a/src/tools/clippy/clippy_lints/src/redundant_slicing.rs b/src/tools/clippy/clippy_lints/src/redundant_slicing.rs
index dc66fb28fa8..0ac818c21d9 100644
--- a/src/tools/clippy/clippy_lints/src/redundant_slicing.rs
+++ b/src/tools/clippy/clippy_lints/src/redundant_slicing.rs
@@ -136,7 +136,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantSlicing {
                 });
             } else if let Some(target_id) = cx.tcx.lang_items().deref_target() {
                 if let Ok(deref_ty) = cx.tcx.try_normalize_erasing_regions(
-                    cx.param_env,
+                    cx.typing_env(),
                     Ty::new_projection_from_args(cx.tcx, target_id, cx.tcx.mk_args(&[GenericArg::from(indexed_ty)])),
                 ) {
                     if deref_ty == expr_ty {
diff --git a/src/tools/clippy/clippy_lints/src/returns.rs b/src/tools/clippy/clippy_lints/src/returns.rs
index 1e0f6dff1ab..aeff31d02d2 100644
--- a/src/tools/clippy/clippy_lints/src/returns.rs
+++ b/src/tools/clippy/clippy_lints/src/returns.rs
@@ -391,7 +391,7 @@ fn check_final_expr<'tcx>(
 
             if let Some(inner) = inner {
                 if for_each_unconsumed_temporary(cx, inner, |temporary_ty| {
-                    if temporary_ty.has_significant_drop(cx.tcx, cx.param_env)
+                    if temporary_ty.has_significant_drop(cx.tcx, cx.typing_env())
                         && temporary_ty
                             .walk()
                             .any(|arg| matches!(arg.unpack(), GenericArgKind::Lifetime(re) if !re.is_static()))
diff --git a/src/tools/clippy/clippy_lints/src/significant_drop_tightening.rs b/src/tools/clippy/clippy_lints/src/significant_drop_tightening.rs
index abd8363456d..1a5b958e6a6 100644
--- a/src/tools/clippy/clippy_lints/src/significant_drop_tightening.rs
+++ b/src/tools/clippy/clippy_lints/src/significant_drop_tightening.rs
@@ -154,7 +154,7 @@ impl<'cx, 'others, 'tcx> AttrChecker<'cx, 'others, 'tcx> {
         let ty = self
             .cx
             .tcx
-            .try_normalize_erasing_regions(self.cx.param_env, ty)
+            .try_normalize_erasing_regions(self.cx.typing_env(), ty)
             .unwrap_or(ty);
         match self.type_cache.entry(ty) {
             Entry::Occupied(e) => return *e.get(),
diff --git a/src/tools/clippy/clippy_lints/src/trailing_empty_array.rs b/src/tools/clippy/clippy_lints/src/trailing_empty_array.rs
index 52bb7c4bd68..50a1577b288 100644
--- a/src/tools/clippy/clippy_lints/src/trailing_empty_array.rs
+++ b/src/tools/clippy/clippy_lints/src/trailing_empty_array.rs
@@ -58,7 +58,7 @@ fn is_struct_with_trailing_zero_sized_array<'tcx>(cx: &LateContext<'tcx>, item:
         && let Some(last_field) = data.fields().last()
         && let field_ty = cx
             .tcx
-            .normalize_erasing_regions(cx.param_env, cx.tcx.type_of(last_field.def_id).instantiate_identity())
+            .normalize_erasing_regions(cx.typing_env(), cx.tcx.type_of(last_field.def_id).instantiate_identity())
         && let ty::Array(_, array_len) = *field_ty.kind()
         && let Some(0) = array_len.try_to_target_usize(cx.tcx)
     {
diff --git a/src/tools/clippy/clippy_lints/src/transmute/eager_transmute.rs b/src/tools/clippy/clippy_lints/src/transmute/eager_transmute.rs
index ca9daf2d2a0..1209bd5b34f 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/eager_transmute.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/eager_transmute.rs
@@ -88,8 +88,8 @@ pub(super) fn check<'tcx>(
         && is_normalizable(cx, cx.param_env, to_ty)
         // we only want to lint if the target type has a niche that is larger than the one of the source type
         // e.g. `u8` to `NonZero<u8>` should lint, but `NonZero<u8>` to `u8` should not
-        && let Ok(from_layout) = cx.tcx.layout_of(cx.param_env.and(from_ty))
-        && let Ok(to_layout) = cx.tcx.layout_of(cx.param_env.and(to_ty))
+        && let Ok(from_layout) = cx.tcx.layout_of(cx.typing_env().as_query_input(from_ty))
+        && let Ok(to_layout) = cx.tcx.layout_of(cx.typing_env().as_query_input(to_ty))
         && match (from_layout.largest_niche, to_layout.largest_niche) {
             (Some(from_niche), Some(to_niche)) => !range_fully_contained(from_niche.valid_range, to_niche.valid_range),
             (None, Some(_)) => true,
diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs
index 3b32e4396b9..4dc1290e8b1 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs
@@ -244,7 +244,7 @@ enum ReducedTy<'tcx> {
 /// Reduce structs containing a single non-zero sized field to it's contained type.
 fn reduce_ty<'tcx>(cx: &LateContext<'tcx>, mut ty: Ty<'tcx>) -> ReducedTy<'tcx> {
     loop {
-        ty = cx.tcx.try_normalize_erasing_regions(cx.param_env, ty).unwrap_or(ty);
+        ty = cx.tcx.try_normalize_erasing_regions(cx.typing_env(), ty).unwrap_or(ty);
         return match *ty.kind() {
             ty::Array(sub_ty, _) if matches!(sub_ty.kind(), ty::Int(_) | ty::Uint(_)) => {
                 ReducedTy::TypeErasure { raw_ptr_only: false }
@@ -297,8 +297,8 @@ fn reduce_ty<'tcx>(cx: &LateContext<'tcx>, mut ty: Ty<'tcx>) -> ReducedTy<'tcx>
 }
 
 fn is_zero_sized_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
-    if let Ok(ty) = cx.tcx.try_normalize_erasing_regions(cx.param_env, ty)
-        && let Ok(layout) = cx.tcx.layout_of(cx.param_env.and(ty))
+    if let Ok(ty) = cx.tcx.try_normalize_erasing_regions(cx.typing_env(), ty)
+        && let Ok(layout) = cx.tcx.layout_of(cx.typing_env().as_query_input(ty))
     {
         layout.layout.size().bytes() == 0
     } else {
diff --git a/src/tools/clippy/clippy_lints/src/transmute/utils.rs b/src/tools/clippy/clippy_lints/src/transmute/utils.rs
index e8ccd35b4da..5baa67b1f3e 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/utils.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/utils.rs
@@ -4,10 +4,11 @@ use rustc_middle::ty::Ty;
 // check if the component types of the transmuted collection and the result have different ABI,
 // size or alignment
 pub(super) fn is_layout_incompatible<'tcx>(cx: &LateContext<'tcx>, from: Ty<'tcx>, to: Ty<'tcx>) -> bool {
-    if let Ok(from) = cx.tcx.try_normalize_erasing_regions(cx.param_env, from)
-        && let Ok(to) = cx.tcx.try_normalize_erasing_regions(cx.param_env, to)
-        && let Ok(from_layout) = cx.tcx.layout_of(cx.param_env.and(from))
-        && let Ok(to_layout) = cx.tcx.layout_of(cx.param_env.and(to))
+    let typing_env = cx.typing_env();
+    if let Ok(from) = cx.tcx.try_normalize_erasing_regions(typing_env, from)
+        && let Ok(to) = cx.tcx.try_normalize_erasing_regions(typing_env, to)
+        && let Ok(from_layout) = cx.tcx.layout_of(typing_env.as_query_input(from))
+        && let Ok(to_layout) = cx.tcx.layout_of(typing_env.as_query_input(to))
     {
         from_layout.size != to_layout.size || from_layout.align.abi != to_layout.align.abi
     } else {
diff --git a/src/tools/clippy/clippy_lints/src/uninhabited_references.rs b/src/tools/clippy/clippy_lints/src/uninhabited_references.rs
index cfa565cf803..ee9ef017253 100644
--- a/src/tools/clippy/clippy_lints/src/uninhabited_references.rs
+++ b/src/tools/clippy/clippy_lints/src/uninhabited_references.rs
@@ -46,7 +46,7 @@ impl LateLintPass<'_> for UninhabitedReferences {
 
         if let ExprKind::Unary(UnOp::Deref, _) = expr.kind {
             let ty = cx.typeck_results().expr_ty_adjusted(expr);
-            if ty.is_privately_uninhabited(cx.tcx, cx.param_env) {
+            if ty.is_privately_uninhabited(cx.tcx, cx.typing_env()) {
                 span_lint(
                     cx,
                     UNINHABITED_REFERENCES,
@@ -71,7 +71,7 @@ impl LateLintPass<'_> for UninhabitedReferences {
         }
         if let FnRetTy::Return(hir_ty) = fndecl.output
             && let TyKind::Ref(_, mut_ty) = hir_ty.kind
-            && lower_ty(cx.tcx, mut_ty.ty).is_privately_uninhabited(cx.tcx, cx.param_env)
+            && lower_ty(cx.tcx, mut_ty.ty).is_privately_uninhabited(cx.tcx, cx.typing_env())
         {
             span_lint(
                 cx,
diff --git a/src/tools/clippy/clippy_utils/src/consts.rs b/src/tools/clippy/clippy_utils/src/consts.rs
index 24a02c7ef87..52c98646289 100644
--- a/src/tools/clippy/clippy_utils/src/consts.rs
+++ b/src/tools/clippy/clippy_utils/src/consts.rs
@@ -18,7 +18,7 @@ use rustc_lexer::tokenize;
 use rustc_lint::LateContext;
 use rustc_middle::mir::ConstValue;
 use rustc_middle::mir::interpret::{Scalar, alloc_range};
-use rustc_middle::ty::{self, FloatTy, IntTy, ParamEnv, ScalarInt, Ty, TyCtxt, TypeckResults, UintTy};
+use rustc_middle::ty::{self, FloatTy, IntTy, ScalarInt, Ty, TyCtxt, TypeckResults, UintTy};
 use rustc_middle::{bug, mir, span_bug};
 use rustc_span::def_id::DefId;
 use rustc_span::symbol::Ident;
@@ -387,7 +387,7 @@ impl Ord for FullInt {
 /// See the module level documentation for some context.
 pub struct ConstEvalCtxt<'tcx> {
     tcx: TyCtxt<'tcx>,
-    param_env: ParamEnv<'tcx>,
+    typing_env: ty::TypingEnv<'tcx>,
     typeck: &'tcx TypeckResults<'tcx>,
     source: Cell<ConstantSource>,
 }
@@ -398,17 +398,17 @@ impl<'tcx> ConstEvalCtxt<'tcx> {
     pub fn new(cx: &LateContext<'tcx>) -> Self {
         Self {
             tcx: cx.tcx,
-            param_env: cx.param_env,
+            typing_env: cx.typing_env(),
             typeck: cx.typeck_results(),
             source: Cell::new(ConstantSource::Local),
         }
     }
 
     /// Creates an evaluation context.
-    pub fn with_env(tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, typeck: &'tcx TypeckResults<'tcx>) -> Self {
+    pub fn with_env(tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>, typeck: &'tcx TypeckResults<'tcx>) -> Self {
         Self {
             tcx,
-            param_env,
+            typing_env,
             typeck,
             source: Cell::new(ConstantSource::Local),
         }
@@ -643,7 +643,7 @@ impl<'tcx> ConstEvalCtxt<'tcx> {
                 let args = self.typeck.node_args(id);
                 let result = self
                     .tcx
-                    .const_eval_resolve(self.param_env, mir::UnevaluatedConst::new(def_id, args), qpath.span())
+                    .const_eval_resolve(self.typing_env, mir::UnevaluatedConst::new(def_id, args), qpath.span())
                     .ok()
                     .map(|val| mir::Const::from_value(val, ty))?;
                 f(self, result)
diff --git a/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs b/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs
index a2e97919d04..7f0363ac942 100644
--- a/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs
+++ b/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs
@@ -105,7 +105,7 @@ fn res_has_significant_drop(res: Res, cx: &LateContext<'_>, e: &Expr<'_>) -> boo
     {
         cx.typeck_results()
             .expr_ty(e)
-            .has_significant_drop(cx.tcx, cx.param_env)
+            .has_significant_drop(cx.tcx, cx.typing_env())
     } else {
         false
     }
diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs
index c73ab4bfa68..ea866a78d87 100644
--- a/src/tools/clippy/clippy_utils/src/hir_utils.rs
+++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs
@@ -297,8 +297,8 @@ impl HirEqInterExpr<'_, '_, '_> {
         if let Some((typeck_lhs, typeck_rhs)) = self.inner.maybe_typeck_results
             && typeck_lhs.expr_ty(left) == typeck_rhs.expr_ty(right)
             && let (Some(l), Some(r)) = (
-                ConstEvalCtxt::with_env(self.inner.cx.tcx, self.inner.cx.param_env, typeck_lhs).eval_simple(left),
-                ConstEvalCtxt::with_env(self.inner.cx.tcx, self.inner.cx.param_env, typeck_rhs).eval_simple(right),
+                ConstEvalCtxt::with_env(self.inner.cx.tcx, self.inner.cx.typing_env(), typeck_lhs).eval_simple(left),
+                ConstEvalCtxt::with_env(self.inner.cx.tcx, self.inner.cx.typing_env(), typeck_rhs).eval_simple(right),
             )
             && l == r
         {
@@ -813,7 +813,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
     #[expect(clippy::too_many_lines)]
     pub fn hash_expr(&mut self, e: &Expr<'_>) {
         let simple_const = self.maybe_typeck_results.and_then(|typeck_results| {
-            ConstEvalCtxt::with_env(self.cx.tcx, self.cx.param_env, typeck_results).eval_simple(e)
+            ConstEvalCtxt::with_env(self.cx.tcx, self.cx.typing_env(), typeck_results).eval_simple(e)
         });
 
         // const hashing may result in the same hash as some unrelated node, so add a sort of
diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs
index 19316a90683..f28e5c9ed0e 100644
--- a/src/tools/clippy/clippy_utils/src/lib.rs
+++ b/src/tools/clippy/clippy_utils/src/lib.rs
@@ -1631,7 +1631,7 @@ pub fn is_integer_const(cx: &LateContext<'_>, e: &Expr<'_>, value: u128) -> bool
     }
     let enclosing_body = cx.tcx.hir().enclosing_body_owner(e.hir_id);
     if let Some(Constant::Int(v)) =
-        ConstEvalCtxt::with_env(cx.tcx, cx.tcx.param_env(enclosing_body), cx.tcx.typeck(enclosing_body)).eval(e)
+        ConstEvalCtxt::with_env(cx.tcx, cx.typing_env(), cx.tcx.typeck(enclosing_body)).eval(e)
     {
         return value == v;
     }
diff --git a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
index 971f8eeb1b3..abadca71400 100644
--- a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
+++ b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
@@ -142,7 +142,7 @@ fn check_rvalue<'tcx>(
                 // We cannot allow this for now.
                 return Err((span, "unsizing casts are only allowed for references right now".into()));
             };
-            let unsized_ty = tcx.struct_tail_for_codegen(pointee_ty, tcx.param_env(def_id));
+            let unsized_ty = tcx.struct_tail_for_codegen(pointee_ty, ty::TypingEnv::post_analysis(tcx, def_id));
             if let ty::Slice(_) | ty::Str = unsized_ty.kind() {
                 check_operand(tcx, op, span, body, msrv)?;
                 // Casting/coercing things to slices is fine.
@@ -408,15 +408,17 @@ fn is_ty_const_destruct<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, body: &Body<'tcx>
             return true;
         }
 
+
+        let (infcx, param_env) =
+            tcx.infer_ctxt().build_with_typing_env(body.typing_env(tcx));
         // FIXME(const_trait_impl) constness
         let obligation = Obligation::new(
             tcx,
             ObligationCause::dummy_with_span(body.span),
-            ConstCx::new(tcx, body).param_env,
+            param_env,
             TraitRef::new(tcx, tcx.require_lang_item(LangItem::Destruct, Some(body.span)), [ty]),
         );
 
-        let infcx = tcx.infer_ctxt().build(body.typing_mode(tcx));
         let mut selcx = SelectionContext::new(&infcx);
         let Some(impl_src) = selcx.select(&obligation).ok().flatten() else {
             return false;
@@ -434,5 +436,5 @@ fn is_ty_const_destruct<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, body: &Body<'tcx>
         ocx.select_all_or_error().is_empty()
     }
 
-    !ty.needs_drop(tcx, ConstCx::new(tcx, body).param_env)
+    !ty.needs_drop(tcx, ConstCx::new(tcx, body).typing_env)
 }
diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs
index 770cd9c3786..2aad867dc0d 100644
--- a/src/tools/clippy/clippy_utils/src/ty.rs
+++ b/src/tools/clippy/clippy_utils/src/ty.rs
@@ -467,7 +467,7 @@ pub fn needs_ordered_drop<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
         if !seen.insert(ty) {
             return false;
         }
-        if !ty.has_significant_drop(cx.tcx, cx.param_env) {
+        if !ty.has_significant_drop(cx.tcx, cx.typing_env()) {
             false
         }
         // Check for std types which implement drop, but only for memory allocation.
@@ -575,8 +575,9 @@ pub fn same_type_and_consts<'tcx>(a: Ty<'tcx>, b: Ty<'tcx>) -> bool {
 
 /// Checks if a given type looks safe to be uninitialized.
 pub fn is_uninit_value_valid_for_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
+    let typing_env = cx.typing_env().with_reveal_all_normalized(cx.tcx);
     cx.tcx
-        .check_validity_requirement((ValidityRequirement::Uninit, cx.param_env.and(ty)))
+        .check_validity_requirement((ValidityRequirement::Uninit, typing_env.as_query_input(ty)))
         .unwrap_or_else(|_| is_uninit_value_valid_for_ty_fallback(cx, ty))
 }
 
@@ -725,7 +726,7 @@ pub fn ty_sig<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option<ExprFnSig<'t
                 _ => None,
             }
         },
-        ty::Alias(ty::Projection, proj) => match cx.tcx.try_normalize_erasing_regions(cx.param_env, ty) {
+        ty::Alias(ty::Projection, proj) => match cx.tcx.try_normalize_erasing_regions(cx.typing_env(), ty) {
             Ok(normalized_ty) if normalized_ty != ty => ty_sig(cx, normalized_ty),
             _ => sig_for_projection(cx, proj).or_else(|| sig_from_bounds(cx, ty, cx.param_env.caller_bounds(), None)),
         },
@@ -1111,12 +1112,12 @@ pub fn make_projection<'tcx>(
 /// succeeds as well as everything checked by `make_projection`.
 pub fn make_normalized_projection<'tcx>(
     tcx: TyCtxt<'tcx>,
-    param_env: ParamEnv<'tcx>,
+    typing_env: ty::TypingEnv<'tcx>,
     container_id: DefId,
     assoc_ty: Symbol,
     args: impl IntoIterator<Item = impl Into<GenericArg<'tcx>>>,
 ) -> Option<Ty<'tcx>> {
-    fn helper<'tcx>(tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, ty: AliasTy<'tcx>) -> Option<Ty<'tcx>> {
+    fn helper<'tcx>(tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>, ty: AliasTy<'tcx>) -> Option<Ty<'tcx>> {
         #[cfg(debug_assertions)]
         if let Some((i, arg)) = ty
             .args
@@ -1132,7 +1133,7 @@ pub fn make_normalized_projection<'tcx>(
             );
             return None;
         }
-        match tcx.try_normalize_erasing_regions(param_env, Ty::new_projection_from_args(tcx, ty.def_id, ty.args)) {
+        match tcx.try_normalize_erasing_regions(typing_env, Ty::new_projection_from_args(tcx, ty.def_id, ty.args)) {
             Ok(ty) => Some(ty),
             Err(e) => {
                 debug_assert!(false, "failed to normalize type `{ty}`: {e:#?}");
@@ -1140,7 +1141,7 @@ pub fn make_normalized_projection<'tcx>(
             },
         }
     }
-    helper(tcx, param_env, make_projection(tcx, container_id, assoc_ty, args)?)
+    helper(tcx, typing_env, make_projection(tcx, container_id, assoc_ty, args)?)
 }
 
 /// Helper to check if given type has inner mutability such as [`std::cell::Cell`] or
@@ -1300,7 +1301,7 @@ pub fn deref_chain<'cx, 'tcx>(cx: &'cx LateContext<'tcx>, ty: Ty<'tcx>) -> impl
         if let Some(deref_did) = cx.tcx.lang_items().deref_trait()
             && implements_trait(cx, ty, deref_did, &[])
         {
-            make_normalized_projection(cx.tcx, cx.param_env, deref_did, sym::Target, [ty])
+            make_normalized_projection(cx.tcx, cx.typing_env(), deref_did, sym::Target, [ty])
         } else {
             None
         }
diff --git a/src/tools/miri/miri-script/Cargo.lock b/src/tools/miri/miri-script/Cargo.lock
index 8dad30df6d1..0c0fe477cdd 100644
--- a/src/tools/miri/miri-script/Cargo.lock
+++ b/src/tools/miri/miri-script/Cargo.lock
@@ -1,6 +1,6 @@
 # This file is automatically @generated by Cargo.
 # It is not intended for manual editing.
-version = 3
+version = 4
 
 [[package]]
 name = "anyhow"
@@ -521,15 +521,15 @@ checksum = "d135d17ab770252ad95e9a872d365cf3090e3be864a34ab46f48555993efc904"
 
 [[package]]
 name = "xshell"
-version = "0.2.6"
+version = "0.2.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6db0ab86eae739efd1b054a8d3d16041914030ac4e01cd1dca0cf252fd8b6437"
+checksum = "9e7290c623014758632efe00737145b6867b66292c42167f2ec381eb566a373d"
 dependencies = [
  "xshell-macros",
 ]
 
 [[package]]
 name = "xshell-macros"
-version = "0.2.6"
+version = "0.2.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9d422e8e38ec76e2f06ee439ccc765e9c6a9638b9e7c9f2e8255e4d41e8bd852"
+checksum = "32ac00cd3f8ec9c1d33fb3e7958a82df6989c42d747bd326c822b1d625283547"
diff --git a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs
index 16fcc26be33..745316913d9 100644
--- a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs
+++ b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs
@@ -12,7 +12,7 @@ use std::{cmp, mem};
 use rustc_abi::{BackendRepr, Size};
 use rustc_data_structures::fx::FxHashSet;
 use rustc_middle::mir::{Mutability, RetagKind};
-use rustc_middle::ty::layout::HasParamEnv;
+use rustc_middle::ty::layout::HasTypingEnv;
 use rustc_middle::ty::{self, Ty};
 
 use self::diagnostics::{RetagCause, RetagInfo};
diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs
index f92150758dc..255a3578aae 100644
--- a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs
+++ b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs
@@ -1,6 +1,6 @@
 use rustc_abi::{BackendRepr, Size};
 use rustc_middle::mir::{Mutability, RetagKind};
-use rustc_middle::ty::layout::HasParamEnv;
+use rustc_middle::ty::layout::HasTypingEnv;
 use rustc_middle::ty::{self, Ty};
 use rustc_span::def_id::DefId;
 
diff --git a/src/tools/miri/src/eval.rs b/src/tools/miri/src/eval.rs
index 1e56e104918..5ec497ef0ea 100644
--- a/src/tools/miri/src/eval.rs
+++ b/src/tools/miri/src/eval.rs
@@ -268,10 +268,14 @@ pub fn create_ecx<'tcx>(
     entry_type: EntryFnType,
     config: &MiriConfig,
 ) -> InterpResult<'tcx, InterpCx<'tcx, MiriMachine<'tcx>>> {
-    let param_env = ty::ParamEnv::reveal_all();
-    let layout_cx = LayoutCx::new(tcx, param_env);
-    let mut ecx =
-        InterpCx::new(tcx, rustc_span::DUMMY_SP, param_env, MiriMachine::new(config, layout_cx));
+    let typing_env = ty::TypingEnv::fully_monomorphized();
+    let layout_cx = LayoutCx::new(tcx, typing_env);
+    let mut ecx = InterpCx::new(
+        tcx,
+        rustc_span::DUMMY_SP,
+        typing_env.param_env,
+        MiriMachine::new(config, layout_cx)
+    );
 
     // Some parts of initialization require a full `InterpCx`.
     MiriMachine::late_init(&mut ecx, config, {
@@ -376,7 +380,7 @@ pub fn create_ecx<'tcx>(
             let main_ret_ty = main_ret_ty.no_bound_vars().unwrap();
             let start_instance = ty::Instance::try_resolve(
                 tcx,
-                ty::ParamEnv::reveal_all(),
+                typing_env,
                 start_id,
                 tcx.mk_args(&[ty::GenericArg::from(main_ret_ty)]),
             )
diff --git a/src/tools/miri/src/helpers.rs b/src/tools/miri/src/helpers.rs
index 526030bef2e..4b34f1686a0 100644
--- a/src/tools/miri/src/helpers.rs
+++ b/src/tools/miri/src/helpers.rs
@@ -116,8 +116,8 @@ pub fn resolve_path<'tcx>(
 /// Gets the layout of a type at a path.
 #[track_caller]
 pub fn path_ty_layout<'tcx>(cx: &impl LayoutOf<'tcx>, path: &[&str]) -> TyAndLayout<'tcx> {
-    let ty =
-        resolve_path(cx.tcx(), path, Namespace::TypeNS).ty(cx.tcx(), ty::ParamEnv::reveal_all());
+    let ty = resolve_path(cx.tcx(), path, Namespace::TypeNS)
+        .ty(cx.tcx(), cx.typing_env());
     cx.layout_of(ty).to_result().ok().unwrap()
 }
 
diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs
index 9668998aaa3..9c1951ec87a 100644
--- a/src/tools/miri/src/machine.rs
+++ b/src/tools/miri/src/machine.rs
@@ -1127,7 +1127,9 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> {
             };
             let info = ecx.get_alloc_info(alloc_id);
             let def_ty = ecx.tcx.type_of(def_id).instantiate_identity();
-            let extern_decl_layout = ecx.tcx.layout_of(ty::ParamEnv::empty().and(def_ty)).unwrap();
+            let extern_decl_layout = ecx.tcx.layout_of(
+                ecx.typing_env().as_query_input(def_ty)
+            ).unwrap();
             if extern_decl_layout.size != info.size || extern_decl_layout.align.abi != info.align {
                 throw_unsup_format!(
                     "extern static `{link_name}` has been declared as `{krate}::{name}` \
diff --git a/src/tools/rust-analyzer/crates/parser/src/lexed_str.rs b/src/tools/rust-analyzer/crates/parser/src/lexed_str.rs
index 3c0eb1b42a6..c97596d5097 100644
--- a/src/tools/rust-analyzer/crates/parser/src/lexed_str.rs
+++ b/src/tools/rust-analyzer/crates/parser/src/lexed_str.rs
@@ -183,7 +183,7 @@ impl<'a> Converter<'a> {
                 rustc_lexer::TokenKind::Ident => {
                     SyntaxKind::from_keyword(token_text, self.edition).unwrap_or(IDENT)
                 }
-                rustc_lexer::TokenKind::InvalidPrefix | rustc_lexer::TokenKind::InvalidIdent => {
+                rustc_lexer::TokenKind::InvalidIdent => {
                     err = "Ident contains invalid characters";
                     IDENT
                 }
diff --git a/tests/crashes/130687.rs b/tests/crashes/130687.rs
deleted file mode 100644
index 361be0905df..00000000000
--- a/tests/crashes/130687.rs
+++ /dev/null
@@ -1,4 +0,0 @@
-//@ known-bug: #130687
-//@ only-x86_64
-pub struct Data([u8; usize::MAX >> 16]);
-const _: &'static Data = &Data([0; usize::MAX >> 16]);
diff --git a/tests/crashes/132985.rs b/tests/crashes/132985.rs
new file mode 100644
index 00000000000..2735074f44d
--- /dev/null
+++ b/tests/crashes/132985.rs
@@ -0,0 +1,17 @@
+//@ known-bug: #132985
+//@ aux-build:aux132985.rs
+
+#![allow(incomplete_features)]
+#![feature(min_generic_const_args)]
+#![feature(adt_const_params)]
+
+extern crate aux132985;
+use aux132985::Foo;
+
+fn bar<const N: Foo>() {}
+
+fn baz() {
+    bar::<{ Foo }>();
+}
+
+fn main() {}
diff --git a/tests/crashes/auxiliary/aux132985.rs b/tests/crashes/auxiliary/aux132985.rs
new file mode 100644
index 00000000000..7ae5567bdc5
--- /dev/null
+++ b/tests/crashes/auxiliary/aux132985.rs
@@ -0,0 +1,6 @@
+#![feature(adt_const_params)]
+
+use std::marker::ConstParamTy;
+
+#[derive(Eq, PartialEq, ConstParamTy)]
+pub struct Foo;
diff --git a/tests/rustdoc/link-on-path-with-generics.rs b/tests/rustdoc/link-on-path-with-generics.rs
new file mode 100644
index 00000000000..22ba36c9f15
--- /dev/null
+++ b/tests/rustdoc/link-on-path-with-generics.rs
@@ -0,0 +1,14 @@
+// This test ensures that paths with generics still get their link to their definition
+// correctly generated.
+
+//@ compile-flags: -Zunstable-options --generate-link-to-definition
+#![crate_name = "foo"]
+
+//@ has 'src/foo/link-on-path-with-generics.rs.html'
+
+pub struct Soyo<T>(T);
+pub struct Saya;
+
+//@ has - '//pre[@class="rust"]//a[@href="#9"]' 'Soyo'
+//@ has - '//pre[@class="rust"]//a[@href="#10"]' 'Saya'
+pub fn bar<T>(s: Soyo<T>, x: Saya) {}
diff --git a/tests/ui/check-cfg/auxiliary/cfg_macro.rs b/tests/ui/check-cfg/auxiliary/cfg_macro.rs
new file mode 100644
index 00000000000..d68accd9202
--- /dev/null
+++ b/tests/ui/check-cfg/auxiliary/cfg_macro.rs
@@ -0,0 +1,11 @@
+// Inspired by https://github.com/rust-lang/cargo/issues/14775
+
+pub fn my_lib_func() {}
+
+#[macro_export]
+macro_rules! my_lib_macro {
+    () => {
+        #[cfg(my_lib_cfg)]
+        $crate::my_lib_func()
+    };
+}
diff --git a/tests/ui/check-cfg/report-in-external-macros.rs b/tests/ui/check-cfg/report-in-external-macros.rs
new file mode 100644
index 00000000000..56550b04af3
--- /dev/null
+++ b/tests/ui/check-cfg/report-in-external-macros.rs
@@ -0,0 +1,12 @@
+// This test checks that we emit the `unexpected_cfgs` lint even in code
+// coming from an external macro.
+
+//@ check-pass
+//@ no-auto-check-cfg
+//@ aux-crate: cfg_macro=cfg_macro.rs
+//@ compile-flags: --check-cfg=cfg()
+
+fn main() {
+    cfg_macro::my_lib_macro!();
+    //~^ WARNING unexpected `cfg` condition name
+}
diff --git a/tests/ui/check-cfg/report-in-external-macros.stderr b/tests/ui/check-cfg/report-in-external-macros.stderr
new file mode 100644
index 00000000000..11300a4e402
--- /dev/null
+++ b/tests/ui/check-cfg/report-in-external-macros.stderr
@@ -0,0 +1,14 @@
+warning: unexpected `cfg` condition name: `my_lib_cfg`
+  --> $DIR/report-in-external-macros.rs:10:5
+   |
+LL |     cfg_macro::my_lib_macro!();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `fmt_debug`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, and `windows`
+   = help: to expect this configuration use `--check-cfg=cfg(my_lib_cfg)`
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
+   = note: `#[warn(unexpected_cfgs)]` on by default
+   = note: this warning originates in the macro `cfg_macro::my_lib_macro` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/const-generics/auxiliary/xcrate-const-ctor-a.rs b/tests/ui/const-generics/auxiliary/xcrate-const-ctor-a.rs
new file mode 100644
index 00000000000..7ae5567bdc5
--- /dev/null
+++ b/tests/ui/const-generics/auxiliary/xcrate-const-ctor-a.rs
@@ -0,0 +1,6 @@
+#![feature(adt_const_params)]
+
+use std::marker::ConstParamTy;
+
+#[derive(Eq, PartialEq, ConstParamTy)]
+pub struct Foo;
diff --git a/tests/ui/const-generics/using-static-as-const-arg.rs b/tests/ui/const-generics/using-static-as-const-arg.rs
new file mode 100644
index 00000000000..2e8a2a14484
--- /dev/null
+++ b/tests/ui/const-generics/using-static-as-const-arg.rs
@@ -0,0 +1,7 @@
+//@ check-pass
+
+pub static STATIC: u32 = 0;
+pub struct Foo<const N: u32>;
+pub const FOO: Foo<{STATIC}> = Foo;
+
+fn main() {}
diff --git a/tests/ui/const-generics/xcrate-const-ctor-b.rs b/tests/ui/const-generics/xcrate-const-ctor-b.rs
new file mode 100644
index 00000000000..dce2e43b316
--- /dev/null
+++ b/tests/ui/const-generics/xcrate-const-ctor-b.rs
@@ -0,0 +1,15 @@
+//@ check-pass
+//@ aux-build:xcrate-const-ctor-a.rs
+
+#![feature(adt_const_params)]
+
+extern crate xcrate_const_ctor_a;
+use xcrate_const_ctor_a::Foo;
+
+fn bar<const N: Foo>() {}
+
+fn baz() {
+    bar::<{ Foo }>();
+}
+
+fn main() {}
diff --git a/tests/ui/consts/promoted_running_out_of_memory_issue-130687.rs b/tests/ui/consts/promoted_running_out_of_memory_issue-130687.rs
new file mode 100644
index 00000000000..b923a768cbf
--- /dev/null
+++ b/tests/ui/consts/promoted_running_out_of_memory_issue-130687.rs
@@ -0,0 +1,12 @@
+//! Ensure we do not ICE when a promoted fails to evaluate due to running out of memory.
+//! Also see <https://github.com/rust-lang/rust/issues/130687>.
+
+// Needs the max type size to be much bigger than the RAM people typically have.
+//@ only-64bit
+
+pub struct Data([u8; (1 << 47) - 1]);
+const _: &'static Data = &Data([0; (1 << 47) - 1]);
+//~^ERROR: evaluation of constant value failed
+//~| tried to allocate more memory than available to compiler
+
+fn main() {}
diff --git a/tests/ui/consts/promoted_running_out_of_memory_issue-130687.stderr b/tests/ui/consts/promoted_running_out_of_memory_issue-130687.stderr
new file mode 100644
index 00000000000..50e920f05f9
--- /dev/null
+++ b/tests/ui/consts/promoted_running_out_of_memory_issue-130687.stderr
@@ -0,0 +1,15 @@
+error[E0080]: evaluation of constant value failed
+  --> $DIR/promoted_running_out_of_memory_issue-130687.rs:8:32
+   |
+LL | const _: &'static Data = &Data([0; (1 << 47) - 1]);
+   |                                ^^^^^^^^^^^^^^^^^^ tried to allocate more memory than available to compiler
+
+note: erroneous constant encountered
+  --> $DIR/promoted_running_out_of_memory_issue-130687.rs:8:26
+   |
+LL | const _: &'static Data = &Data([0; (1 << 47) - 1]);
+   |                          ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/tests/ui/debuginfo/debuginfo-inline-callsite-location-macro-1.rs b/tests/ui/debuginfo/debuginfo-inline-callsite-location-macro-1.rs
new file mode 100644
index 00000000000..32ef849f47e
--- /dev/null
+++ b/tests/ui/debuginfo/debuginfo-inline-callsite-location-macro-1.rs
@@ -0,0 +1,4124 @@
+//@ check-pass
+//@ compile-flags: -Cdebuginfo=2 -Copt-level=0 -Zmir-enable-passes=+Inline
+//@ ignore-msvc
+// ignore-tidy-filelength
+
+#[derive(Default)]
+struct Something {}
+
+#[collapse_debuginfo(yes)]
+macro_rules! collapsed_macro {
+    ($code:expr) => {
+        // Important to use a function here, so it can be inlined
+        // at the MIR stage.
+        Something::default()
+    }
+}
+
+fn collapsed_debuginfo() {
+    // LLVM allows 12 bits for encoding discriminators, so 4096+1 calls to a
+    // MIR-inlined function will exhaust it. But because we're using
+    // collapse_debuginfo(yes) for this macro, we shouldn't need discriminators
+    // at all.
+    collapsed_macro!(1);
+    collapsed_macro!(2);
+    collapsed_macro!(3);
+    collapsed_macro!(4);
+    collapsed_macro!(5);
+    collapsed_macro!(6);
+    collapsed_macro!(7);
+    collapsed_macro!(8);
+    collapsed_macro!(9);
+    collapsed_macro!(10);
+    collapsed_macro!(11);
+    collapsed_macro!(12);
+    collapsed_macro!(13);
+    collapsed_macro!(14);
+    collapsed_macro!(15);
+    collapsed_macro!(16);
+    collapsed_macro!(17);
+    collapsed_macro!(18);
+    collapsed_macro!(19);
+    collapsed_macro!(20);
+    collapsed_macro!(21);
+    collapsed_macro!(22);
+    collapsed_macro!(23);
+    collapsed_macro!(24);
+    collapsed_macro!(25);
+    collapsed_macro!(26);
+    collapsed_macro!(27);
+    collapsed_macro!(28);
+    collapsed_macro!(29);
+    collapsed_macro!(30);
+    collapsed_macro!(31);
+    collapsed_macro!(32);
+    collapsed_macro!(33);
+    collapsed_macro!(34);
+    collapsed_macro!(35);
+    collapsed_macro!(36);
+    collapsed_macro!(37);
+    collapsed_macro!(38);
+    collapsed_macro!(39);
+    collapsed_macro!(40);
+    collapsed_macro!(41);
+    collapsed_macro!(42);
+    collapsed_macro!(43);
+    collapsed_macro!(44);
+    collapsed_macro!(45);
+    collapsed_macro!(46);
+    collapsed_macro!(47);
+    collapsed_macro!(48);
+    collapsed_macro!(49);
+    collapsed_macro!(50);
+    collapsed_macro!(51);
+    collapsed_macro!(52);
+    collapsed_macro!(53);
+    collapsed_macro!(54);
+    collapsed_macro!(55);
+    collapsed_macro!(56);
+    collapsed_macro!(57);
+    collapsed_macro!(58);
+    collapsed_macro!(59);
+    collapsed_macro!(60);
+    collapsed_macro!(61);
+    collapsed_macro!(62);
+    collapsed_macro!(63);
+    collapsed_macro!(64);
+    collapsed_macro!(65);
+    collapsed_macro!(66);
+    collapsed_macro!(67);
+    collapsed_macro!(68);
+    collapsed_macro!(69);
+    collapsed_macro!(70);
+    collapsed_macro!(71);
+    collapsed_macro!(72);
+    collapsed_macro!(73);
+    collapsed_macro!(74);
+    collapsed_macro!(75);
+    collapsed_macro!(76);
+    collapsed_macro!(77);
+    collapsed_macro!(78);
+    collapsed_macro!(79);
+    collapsed_macro!(80);
+    collapsed_macro!(81);
+    collapsed_macro!(82);
+    collapsed_macro!(83);
+    collapsed_macro!(84);
+    collapsed_macro!(85);
+    collapsed_macro!(86);
+    collapsed_macro!(87);
+    collapsed_macro!(88);
+    collapsed_macro!(89);
+    collapsed_macro!(90);
+    collapsed_macro!(91);
+    collapsed_macro!(92);
+    collapsed_macro!(93);
+    collapsed_macro!(94);
+    collapsed_macro!(95);
+    collapsed_macro!(96);
+    collapsed_macro!(97);
+    collapsed_macro!(98);
+    collapsed_macro!(99);
+    collapsed_macro!(100);
+    collapsed_macro!(101);
+    collapsed_macro!(102);
+    collapsed_macro!(103);
+    collapsed_macro!(104);
+    collapsed_macro!(105);
+    collapsed_macro!(106);
+    collapsed_macro!(107);
+    collapsed_macro!(108);
+    collapsed_macro!(109);
+    collapsed_macro!(110);
+    collapsed_macro!(111);
+    collapsed_macro!(112);
+    collapsed_macro!(113);
+    collapsed_macro!(114);
+    collapsed_macro!(115);
+    collapsed_macro!(116);
+    collapsed_macro!(117);
+    collapsed_macro!(118);
+    collapsed_macro!(119);
+    collapsed_macro!(120);
+    collapsed_macro!(121);
+    collapsed_macro!(122);
+    collapsed_macro!(123);
+    collapsed_macro!(124);
+    collapsed_macro!(125);
+    collapsed_macro!(126);
+    collapsed_macro!(127);
+    collapsed_macro!(128);
+    collapsed_macro!(129);
+    collapsed_macro!(130);
+    collapsed_macro!(131);
+    collapsed_macro!(132);
+    collapsed_macro!(133);
+    collapsed_macro!(134);
+    collapsed_macro!(135);
+    collapsed_macro!(136);
+    collapsed_macro!(137);
+    collapsed_macro!(138);
+    collapsed_macro!(139);
+    collapsed_macro!(140);
+    collapsed_macro!(141);
+    collapsed_macro!(142);
+    collapsed_macro!(143);
+    collapsed_macro!(144);
+    collapsed_macro!(145);
+    collapsed_macro!(146);
+    collapsed_macro!(147);
+    collapsed_macro!(148);
+    collapsed_macro!(149);
+    collapsed_macro!(150);
+    collapsed_macro!(151);
+    collapsed_macro!(152);
+    collapsed_macro!(153);
+    collapsed_macro!(154);
+    collapsed_macro!(155);
+    collapsed_macro!(156);
+    collapsed_macro!(157);
+    collapsed_macro!(158);
+    collapsed_macro!(159);
+    collapsed_macro!(160);
+    collapsed_macro!(161);
+    collapsed_macro!(162);
+    collapsed_macro!(163);
+    collapsed_macro!(164);
+    collapsed_macro!(165);
+    collapsed_macro!(166);
+    collapsed_macro!(167);
+    collapsed_macro!(168);
+    collapsed_macro!(169);
+    collapsed_macro!(170);
+    collapsed_macro!(171);
+    collapsed_macro!(172);
+    collapsed_macro!(173);
+    collapsed_macro!(174);
+    collapsed_macro!(175);
+    collapsed_macro!(176);
+    collapsed_macro!(177);
+    collapsed_macro!(178);
+    collapsed_macro!(179);
+    collapsed_macro!(180);
+    collapsed_macro!(181);
+    collapsed_macro!(182);
+    collapsed_macro!(183);
+    collapsed_macro!(184);
+    collapsed_macro!(185);
+    collapsed_macro!(186);
+    collapsed_macro!(187);
+    collapsed_macro!(188);
+    collapsed_macro!(189);
+    collapsed_macro!(190);
+    collapsed_macro!(191);
+    collapsed_macro!(192);
+    collapsed_macro!(193);
+    collapsed_macro!(194);
+    collapsed_macro!(195);
+    collapsed_macro!(196);
+    collapsed_macro!(197);
+    collapsed_macro!(198);
+    collapsed_macro!(199);
+    collapsed_macro!(200);
+    collapsed_macro!(201);
+    collapsed_macro!(202);
+    collapsed_macro!(203);
+    collapsed_macro!(204);
+    collapsed_macro!(205);
+    collapsed_macro!(206);
+    collapsed_macro!(207);
+    collapsed_macro!(208);
+    collapsed_macro!(209);
+    collapsed_macro!(210);
+    collapsed_macro!(211);
+    collapsed_macro!(212);
+    collapsed_macro!(213);
+    collapsed_macro!(214);
+    collapsed_macro!(215);
+    collapsed_macro!(216);
+    collapsed_macro!(217);
+    collapsed_macro!(218);
+    collapsed_macro!(219);
+    collapsed_macro!(220);
+    collapsed_macro!(221);
+    collapsed_macro!(222);
+    collapsed_macro!(223);
+    collapsed_macro!(224);
+    collapsed_macro!(225);
+    collapsed_macro!(226);
+    collapsed_macro!(227);
+    collapsed_macro!(228);
+    collapsed_macro!(229);
+    collapsed_macro!(230);
+    collapsed_macro!(231);
+    collapsed_macro!(232);
+    collapsed_macro!(233);
+    collapsed_macro!(234);
+    collapsed_macro!(235);
+    collapsed_macro!(236);
+    collapsed_macro!(237);
+    collapsed_macro!(238);
+    collapsed_macro!(239);
+    collapsed_macro!(240);
+    collapsed_macro!(241);
+    collapsed_macro!(242);
+    collapsed_macro!(243);
+    collapsed_macro!(244);
+    collapsed_macro!(245);
+    collapsed_macro!(246);
+    collapsed_macro!(247);
+    collapsed_macro!(248);
+    collapsed_macro!(249);
+    collapsed_macro!(250);
+    collapsed_macro!(251);
+    collapsed_macro!(252);
+    collapsed_macro!(253);
+    collapsed_macro!(254);
+    collapsed_macro!(255);
+    collapsed_macro!(256);
+    collapsed_macro!(257);
+    collapsed_macro!(258);
+    collapsed_macro!(259);
+    collapsed_macro!(260);
+    collapsed_macro!(261);
+    collapsed_macro!(262);
+    collapsed_macro!(263);
+    collapsed_macro!(264);
+    collapsed_macro!(265);
+    collapsed_macro!(266);
+    collapsed_macro!(267);
+    collapsed_macro!(268);
+    collapsed_macro!(269);
+    collapsed_macro!(270);
+    collapsed_macro!(271);
+    collapsed_macro!(272);
+    collapsed_macro!(273);
+    collapsed_macro!(274);
+    collapsed_macro!(275);
+    collapsed_macro!(276);
+    collapsed_macro!(277);
+    collapsed_macro!(278);
+    collapsed_macro!(279);
+    collapsed_macro!(280);
+    collapsed_macro!(281);
+    collapsed_macro!(282);
+    collapsed_macro!(283);
+    collapsed_macro!(284);
+    collapsed_macro!(285);
+    collapsed_macro!(286);
+    collapsed_macro!(287);
+    collapsed_macro!(288);
+    collapsed_macro!(289);
+    collapsed_macro!(290);
+    collapsed_macro!(291);
+    collapsed_macro!(292);
+    collapsed_macro!(293);
+    collapsed_macro!(294);
+    collapsed_macro!(295);
+    collapsed_macro!(296);
+    collapsed_macro!(297);
+    collapsed_macro!(298);
+    collapsed_macro!(299);
+    collapsed_macro!(300);
+    collapsed_macro!(301);
+    collapsed_macro!(302);
+    collapsed_macro!(303);
+    collapsed_macro!(304);
+    collapsed_macro!(305);
+    collapsed_macro!(306);
+    collapsed_macro!(307);
+    collapsed_macro!(308);
+    collapsed_macro!(309);
+    collapsed_macro!(310);
+    collapsed_macro!(311);
+    collapsed_macro!(312);
+    collapsed_macro!(313);
+    collapsed_macro!(314);
+    collapsed_macro!(315);
+    collapsed_macro!(316);
+    collapsed_macro!(317);
+    collapsed_macro!(318);
+    collapsed_macro!(319);
+    collapsed_macro!(320);
+    collapsed_macro!(321);
+    collapsed_macro!(322);
+    collapsed_macro!(323);
+    collapsed_macro!(324);
+    collapsed_macro!(325);
+    collapsed_macro!(326);
+    collapsed_macro!(327);
+    collapsed_macro!(328);
+    collapsed_macro!(329);
+    collapsed_macro!(330);
+    collapsed_macro!(331);
+    collapsed_macro!(332);
+    collapsed_macro!(333);
+    collapsed_macro!(334);
+    collapsed_macro!(335);
+    collapsed_macro!(336);
+    collapsed_macro!(337);
+    collapsed_macro!(338);
+    collapsed_macro!(339);
+    collapsed_macro!(340);
+    collapsed_macro!(341);
+    collapsed_macro!(342);
+    collapsed_macro!(343);
+    collapsed_macro!(344);
+    collapsed_macro!(345);
+    collapsed_macro!(346);
+    collapsed_macro!(347);
+    collapsed_macro!(348);
+    collapsed_macro!(349);
+    collapsed_macro!(350);
+    collapsed_macro!(351);
+    collapsed_macro!(352);
+    collapsed_macro!(353);
+    collapsed_macro!(354);
+    collapsed_macro!(355);
+    collapsed_macro!(356);
+    collapsed_macro!(357);
+    collapsed_macro!(358);
+    collapsed_macro!(359);
+    collapsed_macro!(360);
+    collapsed_macro!(361);
+    collapsed_macro!(362);
+    collapsed_macro!(363);
+    collapsed_macro!(364);
+    collapsed_macro!(365);
+    collapsed_macro!(366);
+    collapsed_macro!(367);
+    collapsed_macro!(368);
+    collapsed_macro!(369);
+    collapsed_macro!(370);
+    collapsed_macro!(371);
+    collapsed_macro!(372);
+    collapsed_macro!(373);
+    collapsed_macro!(374);
+    collapsed_macro!(375);
+    collapsed_macro!(376);
+    collapsed_macro!(377);
+    collapsed_macro!(378);
+    collapsed_macro!(379);
+    collapsed_macro!(380);
+    collapsed_macro!(381);
+    collapsed_macro!(382);
+    collapsed_macro!(383);
+    collapsed_macro!(384);
+    collapsed_macro!(385);
+    collapsed_macro!(386);
+    collapsed_macro!(387);
+    collapsed_macro!(388);
+    collapsed_macro!(389);
+    collapsed_macro!(390);
+    collapsed_macro!(391);
+    collapsed_macro!(392);
+    collapsed_macro!(393);
+    collapsed_macro!(394);
+    collapsed_macro!(395);
+    collapsed_macro!(396);
+    collapsed_macro!(397);
+    collapsed_macro!(398);
+    collapsed_macro!(399);
+    collapsed_macro!(400);
+    collapsed_macro!(401);
+    collapsed_macro!(402);
+    collapsed_macro!(403);
+    collapsed_macro!(404);
+    collapsed_macro!(405);
+    collapsed_macro!(406);
+    collapsed_macro!(407);
+    collapsed_macro!(408);
+    collapsed_macro!(409);
+    collapsed_macro!(410);
+    collapsed_macro!(411);
+    collapsed_macro!(412);
+    collapsed_macro!(413);
+    collapsed_macro!(414);
+    collapsed_macro!(415);
+    collapsed_macro!(416);
+    collapsed_macro!(417);
+    collapsed_macro!(418);
+    collapsed_macro!(419);
+    collapsed_macro!(420);
+    collapsed_macro!(421);
+    collapsed_macro!(422);
+    collapsed_macro!(423);
+    collapsed_macro!(424);
+    collapsed_macro!(425);
+    collapsed_macro!(426);
+    collapsed_macro!(427);
+    collapsed_macro!(428);
+    collapsed_macro!(429);
+    collapsed_macro!(430);
+    collapsed_macro!(431);
+    collapsed_macro!(432);
+    collapsed_macro!(433);
+    collapsed_macro!(434);
+    collapsed_macro!(435);
+    collapsed_macro!(436);
+    collapsed_macro!(437);
+    collapsed_macro!(438);
+    collapsed_macro!(439);
+    collapsed_macro!(440);
+    collapsed_macro!(441);
+    collapsed_macro!(442);
+    collapsed_macro!(443);
+    collapsed_macro!(444);
+    collapsed_macro!(445);
+    collapsed_macro!(446);
+    collapsed_macro!(447);
+    collapsed_macro!(448);
+    collapsed_macro!(449);
+    collapsed_macro!(450);
+    collapsed_macro!(451);
+    collapsed_macro!(452);
+    collapsed_macro!(453);
+    collapsed_macro!(454);
+    collapsed_macro!(455);
+    collapsed_macro!(456);
+    collapsed_macro!(457);
+    collapsed_macro!(458);
+    collapsed_macro!(459);
+    collapsed_macro!(460);
+    collapsed_macro!(461);
+    collapsed_macro!(462);
+    collapsed_macro!(463);
+    collapsed_macro!(464);
+    collapsed_macro!(465);
+    collapsed_macro!(466);
+    collapsed_macro!(467);
+    collapsed_macro!(468);
+    collapsed_macro!(469);
+    collapsed_macro!(470);
+    collapsed_macro!(471);
+    collapsed_macro!(472);
+    collapsed_macro!(473);
+    collapsed_macro!(474);
+    collapsed_macro!(475);
+    collapsed_macro!(476);
+    collapsed_macro!(477);
+    collapsed_macro!(478);
+    collapsed_macro!(479);
+    collapsed_macro!(480);
+    collapsed_macro!(481);
+    collapsed_macro!(482);
+    collapsed_macro!(483);
+    collapsed_macro!(484);
+    collapsed_macro!(485);
+    collapsed_macro!(486);
+    collapsed_macro!(487);
+    collapsed_macro!(488);
+    collapsed_macro!(489);
+    collapsed_macro!(490);
+    collapsed_macro!(491);
+    collapsed_macro!(492);
+    collapsed_macro!(493);
+    collapsed_macro!(494);
+    collapsed_macro!(495);
+    collapsed_macro!(496);
+    collapsed_macro!(497);
+    collapsed_macro!(498);
+    collapsed_macro!(499);
+    collapsed_macro!(500);
+    collapsed_macro!(501);
+    collapsed_macro!(502);
+    collapsed_macro!(503);
+    collapsed_macro!(504);
+    collapsed_macro!(505);
+    collapsed_macro!(506);
+    collapsed_macro!(507);
+    collapsed_macro!(508);
+    collapsed_macro!(509);
+    collapsed_macro!(510);
+    collapsed_macro!(511);
+    collapsed_macro!(512);
+    collapsed_macro!(513);
+    collapsed_macro!(514);
+    collapsed_macro!(515);
+    collapsed_macro!(516);
+    collapsed_macro!(517);
+    collapsed_macro!(518);
+    collapsed_macro!(519);
+    collapsed_macro!(520);
+    collapsed_macro!(521);
+    collapsed_macro!(522);
+    collapsed_macro!(523);
+    collapsed_macro!(524);
+    collapsed_macro!(525);
+    collapsed_macro!(526);
+    collapsed_macro!(527);
+    collapsed_macro!(528);
+    collapsed_macro!(529);
+    collapsed_macro!(530);
+    collapsed_macro!(531);
+    collapsed_macro!(532);
+    collapsed_macro!(533);
+    collapsed_macro!(534);
+    collapsed_macro!(535);
+    collapsed_macro!(536);
+    collapsed_macro!(537);
+    collapsed_macro!(538);
+    collapsed_macro!(539);
+    collapsed_macro!(540);
+    collapsed_macro!(541);
+    collapsed_macro!(542);
+    collapsed_macro!(543);
+    collapsed_macro!(544);
+    collapsed_macro!(545);
+    collapsed_macro!(546);
+    collapsed_macro!(547);
+    collapsed_macro!(548);
+    collapsed_macro!(549);
+    collapsed_macro!(550);
+    collapsed_macro!(551);
+    collapsed_macro!(552);
+    collapsed_macro!(553);
+    collapsed_macro!(554);
+    collapsed_macro!(555);
+    collapsed_macro!(556);
+    collapsed_macro!(557);
+    collapsed_macro!(558);
+    collapsed_macro!(559);
+    collapsed_macro!(560);
+    collapsed_macro!(561);
+    collapsed_macro!(562);
+    collapsed_macro!(563);
+    collapsed_macro!(564);
+    collapsed_macro!(565);
+    collapsed_macro!(566);
+    collapsed_macro!(567);
+    collapsed_macro!(568);
+    collapsed_macro!(569);
+    collapsed_macro!(570);
+    collapsed_macro!(571);
+    collapsed_macro!(572);
+    collapsed_macro!(573);
+    collapsed_macro!(574);
+    collapsed_macro!(575);
+    collapsed_macro!(576);
+    collapsed_macro!(577);
+    collapsed_macro!(578);
+    collapsed_macro!(579);
+    collapsed_macro!(580);
+    collapsed_macro!(581);
+    collapsed_macro!(582);
+    collapsed_macro!(583);
+    collapsed_macro!(584);
+    collapsed_macro!(585);
+    collapsed_macro!(586);
+    collapsed_macro!(587);
+    collapsed_macro!(588);
+    collapsed_macro!(589);
+    collapsed_macro!(590);
+    collapsed_macro!(591);
+    collapsed_macro!(592);
+    collapsed_macro!(593);
+    collapsed_macro!(594);
+    collapsed_macro!(595);
+    collapsed_macro!(596);
+    collapsed_macro!(597);
+    collapsed_macro!(598);
+    collapsed_macro!(599);
+    collapsed_macro!(600);
+    collapsed_macro!(601);
+    collapsed_macro!(602);
+    collapsed_macro!(603);
+    collapsed_macro!(604);
+    collapsed_macro!(605);
+    collapsed_macro!(606);
+    collapsed_macro!(607);
+    collapsed_macro!(608);
+    collapsed_macro!(609);
+    collapsed_macro!(610);
+    collapsed_macro!(611);
+    collapsed_macro!(612);
+    collapsed_macro!(613);
+    collapsed_macro!(614);
+    collapsed_macro!(615);
+    collapsed_macro!(616);
+    collapsed_macro!(617);
+    collapsed_macro!(618);
+    collapsed_macro!(619);
+    collapsed_macro!(620);
+    collapsed_macro!(621);
+    collapsed_macro!(622);
+    collapsed_macro!(623);
+    collapsed_macro!(624);
+    collapsed_macro!(625);
+    collapsed_macro!(626);
+    collapsed_macro!(627);
+    collapsed_macro!(628);
+    collapsed_macro!(629);
+    collapsed_macro!(630);
+    collapsed_macro!(631);
+    collapsed_macro!(632);
+    collapsed_macro!(633);
+    collapsed_macro!(634);
+    collapsed_macro!(635);
+    collapsed_macro!(636);
+    collapsed_macro!(637);
+    collapsed_macro!(638);
+    collapsed_macro!(639);
+    collapsed_macro!(640);
+    collapsed_macro!(641);
+    collapsed_macro!(642);
+    collapsed_macro!(643);
+    collapsed_macro!(644);
+    collapsed_macro!(645);
+    collapsed_macro!(646);
+    collapsed_macro!(647);
+    collapsed_macro!(648);
+    collapsed_macro!(649);
+    collapsed_macro!(650);
+    collapsed_macro!(651);
+    collapsed_macro!(652);
+    collapsed_macro!(653);
+    collapsed_macro!(654);
+    collapsed_macro!(655);
+    collapsed_macro!(656);
+    collapsed_macro!(657);
+    collapsed_macro!(658);
+    collapsed_macro!(659);
+    collapsed_macro!(660);
+    collapsed_macro!(661);
+    collapsed_macro!(662);
+    collapsed_macro!(663);
+    collapsed_macro!(664);
+    collapsed_macro!(665);
+    collapsed_macro!(666);
+    collapsed_macro!(667);
+    collapsed_macro!(668);
+    collapsed_macro!(669);
+    collapsed_macro!(670);
+    collapsed_macro!(671);
+    collapsed_macro!(672);
+    collapsed_macro!(673);
+    collapsed_macro!(674);
+    collapsed_macro!(675);
+    collapsed_macro!(676);
+    collapsed_macro!(677);
+    collapsed_macro!(678);
+    collapsed_macro!(679);
+    collapsed_macro!(680);
+    collapsed_macro!(681);
+    collapsed_macro!(682);
+    collapsed_macro!(683);
+    collapsed_macro!(684);
+    collapsed_macro!(685);
+    collapsed_macro!(686);
+    collapsed_macro!(687);
+    collapsed_macro!(688);
+    collapsed_macro!(689);
+    collapsed_macro!(690);
+    collapsed_macro!(691);
+    collapsed_macro!(692);
+    collapsed_macro!(693);
+    collapsed_macro!(694);
+    collapsed_macro!(695);
+    collapsed_macro!(696);
+    collapsed_macro!(697);
+    collapsed_macro!(698);
+    collapsed_macro!(699);
+    collapsed_macro!(700);
+    collapsed_macro!(701);
+    collapsed_macro!(702);
+    collapsed_macro!(703);
+    collapsed_macro!(704);
+    collapsed_macro!(705);
+    collapsed_macro!(706);
+    collapsed_macro!(707);
+    collapsed_macro!(708);
+    collapsed_macro!(709);
+    collapsed_macro!(710);
+    collapsed_macro!(711);
+    collapsed_macro!(712);
+    collapsed_macro!(713);
+    collapsed_macro!(714);
+    collapsed_macro!(715);
+    collapsed_macro!(716);
+    collapsed_macro!(717);
+    collapsed_macro!(718);
+    collapsed_macro!(719);
+    collapsed_macro!(720);
+    collapsed_macro!(721);
+    collapsed_macro!(722);
+    collapsed_macro!(723);
+    collapsed_macro!(724);
+    collapsed_macro!(725);
+    collapsed_macro!(726);
+    collapsed_macro!(727);
+    collapsed_macro!(728);
+    collapsed_macro!(729);
+    collapsed_macro!(730);
+    collapsed_macro!(731);
+    collapsed_macro!(732);
+    collapsed_macro!(733);
+    collapsed_macro!(734);
+    collapsed_macro!(735);
+    collapsed_macro!(736);
+    collapsed_macro!(737);
+    collapsed_macro!(738);
+    collapsed_macro!(739);
+    collapsed_macro!(740);
+    collapsed_macro!(741);
+    collapsed_macro!(742);
+    collapsed_macro!(743);
+    collapsed_macro!(744);
+    collapsed_macro!(745);
+    collapsed_macro!(746);
+    collapsed_macro!(747);
+    collapsed_macro!(748);
+    collapsed_macro!(749);
+    collapsed_macro!(750);
+    collapsed_macro!(751);
+    collapsed_macro!(752);
+    collapsed_macro!(753);
+    collapsed_macro!(754);
+    collapsed_macro!(755);
+    collapsed_macro!(756);
+    collapsed_macro!(757);
+    collapsed_macro!(758);
+    collapsed_macro!(759);
+    collapsed_macro!(760);
+    collapsed_macro!(761);
+    collapsed_macro!(762);
+    collapsed_macro!(763);
+    collapsed_macro!(764);
+    collapsed_macro!(765);
+    collapsed_macro!(766);
+    collapsed_macro!(767);
+    collapsed_macro!(768);
+    collapsed_macro!(769);
+    collapsed_macro!(770);
+    collapsed_macro!(771);
+    collapsed_macro!(772);
+    collapsed_macro!(773);
+    collapsed_macro!(774);
+    collapsed_macro!(775);
+    collapsed_macro!(776);
+    collapsed_macro!(777);
+    collapsed_macro!(778);
+    collapsed_macro!(779);
+    collapsed_macro!(780);
+    collapsed_macro!(781);
+    collapsed_macro!(782);
+    collapsed_macro!(783);
+    collapsed_macro!(784);
+    collapsed_macro!(785);
+    collapsed_macro!(786);
+    collapsed_macro!(787);
+    collapsed_macro!(788);
+    collapsed_macro!(789);
+    collapsed_macro!(790);
+    collapsed_macro!(791);
+    collapsed_macro!(792);
+    collapsed_macro!(793);
+    collapsed_macro!(794);
+    collapsed_macro!(795);
+    collapsed_macro!(796);
+    collapsed_macro!(797);
+    collapsed_macro!(798);
+    collapsed_macro!(799);
+    collapsed_macro!(800);
+    collapsed_macro!(801);
+    collapsed_macro!(802);
+    collapsed_macro!(803);
+    collapsed_macro!(804);
+    collapsed_macro!(805);
+    collapsed_macro!(806);
+    collapsed_macro!(807);
+    collapsed_macro!(808);
+    collapsed_macro!(809);
+    collapsed_macro!(810);
+    collapsed_macro!(811);
+    collapsed_macro!(812);
+    collapsed_macro!(813);
+    collapsed_macro!(814);
+    collapsed_macro!(815);
+    collapsed_macro!(816);
+    collapsed_macro!(817);
+    collapsed_macro!(818);
+    collapsed_macro!(819);
+    collapsed_macro!(820);
+    collapsed_macro!(821);
+    collapsed_macro!(822);
+    collapsed_macro!(823);
+    collapsed_macro!(824);
+    collapsed_macro!(825);
+    collapsed_macro!(826);
+    collapsed_macro!(827);
+    collapsed_macro!(828);
+    collapsed_macro!(829);
+    collapsed_macro!(830);
+    collapsed_macro!(831);
+    collapsed_macro!(832);
+    collapsed_macro!(833);
+    collapsed_macro!(834);
+    collapsed_macro!(835);
+    collapsed_macro!(836);
+    collapsed_macro!(837);
+    collapsed_macro!(838);
+    collapsed_macro!(839);
+    collapsed_macro!(840);
+    collapsed_macro!(841);
+    collapsed_macro!(842);
+    collapsed_macro!(843);
+    collapsed_macro!(844);
+    collapsed_macro!(845);
+    collapsed_macro!(846);
+    collapsed_macro!(847);
+    collapsed_macro!(848);
+    collapsed_macro!(849);
+    collapsed_macro!(850);
+    collapsed_macro!(851);
+    collapsed_macro!(852);
+    collapsed_macro!(853);
+    collapsed_macro!(854);
+    collapsed_macro!(855);
+    collapsed_macro!(856);
+    collapsed_macro!(857);
+    collapsed_macro!(858);
+    collapsed_macro!(859);
+    collapsed_macro!(860);
+    collapsed_macro!(861);
+    collapsed_macro!(862);
+    collapsed_macro!(863);
+    collapsed_macro!(864);
+    collapsed_macro!(865);
+    collapsed_macro!(866);
+    collapsed_macro!(867);
+    collapsed_macro!(868);
+    collapsed_macro!(869);
+    collapsed_macro!(870);
+    collapsed_macro!(871);
+    collapsed_macro!(872);
+    collapsed_macro!(873);
+    collapsed_macro!(874);
+    collapsed_macro!(875);
+    collapsed_macro!(876);
+    collapsed_macro!(877);
+    collapsed_macro!(878);
+    collapsed_macro!(879);
+    collapsed_macro!(880);
+    collapsed_macro!(881);
+    collapsed_macro!(882);
+    collapsed_macro!(883);
+    collapsed_macro!(884);
+    collapsed_macro!(885);
+    collapsed_macro!(886);
+    collapsed_macro!(887);
+    collapsed_macro!(888);
+    collapsed_macro!(889);
+    collapsed_macro!(890);
+    collapsed_macro!(891);
+    collapsed_macro!(892);
+    collapsed_macro!(893);
+    collapsed_macro!(894);
+    collapsed_macro!(895);
+    collapsed_macro!(896);
+    collapsed_macro!(897);
+    collapsed_macro!(898);
+    collapsed_macro!(899);
+    collapsed_macro!(900);
+    collapsed_macro!(901);
+    collapsed_macro!(902);
+    collapsed_macro!(903);
+    collapsed_macro!(904);
+    collapsed_macro!(905);
+    collapsed_macro!(906);
+    collapsed_macro!(907);
+    collapsed_macro!(908);
+    collapsed_macro!(909);
+    collapsed_macro!(910);
+    collapsed_macro!(911);
+    collapsed_macro!(912);
+    collapsed_macro!(913);
+    collapsed_macro!(914);
+    collapsed_macro!(915);
+    collapsed_macro!(916);
+    collapsed_macro!(917);
+    collapsed_macro!(918);
+    collapsed_macro!(919);
+    collapsed_macro!(920);
+    collapsed_macro!(921);
+    collapsed_macro!(922);
+    collapsed_macro!(923);
+    collapsed_macro!(924);
+    collapsed_macro!(925);
+    collapsed_macro!(926);
+    collapsed_macro!(927);
+    collapsed_macro!(928);
+    collapsed_macro!(929);
+    collapsed_macro!(930);
+    collapsed_macro!(931);
+    collapsed_macro!(932);
+    collapsed_macro!(933);
+    collapsed_macro!(934);
+    collapsed_macro!(935);
+    collapsed_macro!(936);
+    collapsed_macro!(937);
+    collapsed_macro!(938);
+    collapsed_macro!(939);
+    collapsed_macro!(940);
+    collapsed_macro!(941);
+    collapsed_macro!(942);
+    collapsed_macro!(943);
+    collapsed_macro!(944);
+    collapsed_macro!(945);
+    collapsed_macro!(946);
+    collapsed_macro!(947);
+    collapsed_macro!(948);
+    collapsed_macro!(949);
+    collapsed_macro!(950);
+    collapsed_macro!(951);
+    collapsed_macro!(952);
+    collapsed_macro!(953);
+    collapsed_macro!(954);
+    collapsed_macro!(955);
+    collapsed_macro!(956);
+    collapsed_macro!(957);
+    collapsed_macro!(958);
+    collapsed_macro!(959);
+    collapsed_macro!(960);
+    collapsed_macro!(961);
+    collapsed_macro!(962);
+    collapsed_macro!(963);
+    collapsed_macro!(964);
+    collapsed_macro!(965);
+    collapsed_macro!(966);
+    collapsed_macro!(967);
+    collapsed_macro!(968);
+    collapsed_macro!(969);
+    collapsed_macro!(970);
+    collapsed_macro!(971);
+    collapsed_macro!(972);
+    collapsed_macro!(973);
+    collapsed_macro!(974);
+    collapsed_macro!(975);
+    collapsed_macro!(976);
+    collapsed_macro!(977);
+    collapsed_macro!(978);
+    collapsed_macro!(979);
+    collapsed_macro!(980);
+    collapsed_macro!(981);
+    collapsed_macro!(982);
+    collapsed_macro!(983);
+    collapsed_macro!(984);
+    collapsed_macro!(985);
+    collapsed_macro!(986);
+    collapsed_macro!(987);
+    collapsed_macro!(988);
+    collapsed_macro!(989);
+    collapsed_macro!(990);
+    collapsed_macro!(991);
+    collapsed_macro!(992);
+    collapsed_macro!(993);
+    collapsed_macro!(994);
+    collapsed_macro!(995);
+    collapsed_macro!(996);
+    collapsed_macro!(997);
+    collapsed_macro!(998);
+    collapsed_macro!(999);
+    collapsed_macro!(1000);
+    collapsed_macro!(1001);
+    collapsed_macro!(1002);
+    collapsed_macro!(1003);
+    collapsed_macro!(1004);
+    collapsed_macro!(1005);
+    collapsed_macro!(1006);
+    collapsed_macro!(1007);
+    collapsed_macro!(1008);
+    collapsed_macro!(1009);
+    collapsed_macro!(1010);
+    collapsed_macro!(1011);
+    collapsed_macro!(1012);
+    collapsed_macro!(1013);
+    collapsed_macro!(1014);
+    collapsed_macro!(1015);
+    collapsed_macro!(1016);
+    collapsed_macro!(1017);
+    collapsed_macro!(1018);
+    collapsed_macro!(1019);
+    collapsed_macro!(1020);
+    collapsed_macro!(1021);
+    collapsed_macro!(1022);
+    collapsed_macro!(1023);
+    collapsed_macro!(1024);
+    collapsed_macro!(1025);
+    collapsed_macro!(1026);
+    collapsed_macro!(1027);
+    collapsed_macro!(1028);
+    collapsed_macro!(1029);
+    collapsed_macro!(1030);
+    collapsed_macro!(1031);
+    collapsed_macro!(1032);
+    collapsed_macro!(1033);
+    collapsed_macro!(1034);
+    collapsed_macro!(1035);
+    collapsed_macro!(1036);
+    collapsed_macro!(1037);
+    collapsed_macro!(1038);
+    collapsed_macro!(1039);
+    collapsed_macro!(1040);
+    collapsed_macro!(1041);
+    collapsed_macro!(1042);
+    collapsed_macro!(1043);
+    collapsed_macro!(1044);
+    collapsed_macro!(1045);
+    collapsed_macro!(1046);
+    collapsed_macro!(1047);
+    collapsed_macro!(1048);
+    collapsed_macro!(1049);
+    collapsed_macro!(1050);
+    collapsed_macro!(1051);
+    collapsed_macro!(1052);
+    collapsed_macro!(1053);
+    collapsed_macro!(1054);
+    collapsed_macro!(1055);
+    collapsed_macro!(1056);
+    collapsed_macro!(1057);
+    collapsed_macro!(1058);
+    collapsed_macro!(1059);
+    collapsed_macro!(1060);
+    collapsed_macro!(1061);
+    collapsed_macro!(1062);
+    collapsed_macro!(1063);
+    collapsed_macro!(1064);
+    collapsed_macro!(1065);
+    collapsed_macro!(1066);
+    collapsed_macro!(1067);
+    collapsed_macro!(1068);
+    collapsed_macro!(1069);
+    collapsed_macro!(1070);
+    collapsed_macro!(1071);
+    collapsed_macro!(1072);
+    collapsed_macro!(1073);
+    collapsed_macro!(1074);
+    collapsed_macro!(1075);
+    collapsed_macro!(1076);
+    collapsed_macro!(1077);
+    collapsed_macro!(1078);
+    collapsed_macro!(1079);
+    collapsed_macro!(1080);
+    collapsed_macro!(1081);
+    collapsed_macro!(1082);
+    collapsed_macro!(1083);
+    collapsed_macro!(1084);
+    collapsed_macro!(1085);
+    collapsed_macro!(1086);
+    collapsed_macro!(1087);
+    collapsed_macro!(1088);
+    collapsed_macro!(1089);
+    collapsed_macro!(1090);
+    collapsed_macro!(1091);
+    collapsed_macro!(1092);
+    collapsed_macro!(1093);
+    collapsed_macro!(1094);
+    collapsed_macro!(1095);
+    collapsed_macro!(1096);
+    collapsed_macro!(1097);
+    collapsed_macro!(1098);
+    collapsed_macro!(1099);
+    collapsed_macro!(1100);
+    collapsed_macro!(1101);
+    collapsed_macro!(1102);
+    collapsed_macro!(1103);
+    collapsed_macro!(1104);
+    collapsed_macro!(1105);
+    collapsed_macro!(1106);
+    collapsed_macro!(1107);
+    collapsed_macro!(1108);
+    collapsed_macro!(1109);
+    collapsed_macro!(1110);
+    collapsed_macro!(1111);
+    collapsed_macro!(1112);
+    collapsed_macro!(1113);
+    collapsed_macro!(1114);
+    collapsed_macro!(1115);
+    collapsed_macro!(1116);
+    collapsed_macro!(1117);
+    collapsed_macro!(1118);
+    collapsed_macro!(1119);
+    collapsed_macro!(1120);
+    collapsed_macro!(1121);
+    collapsed_macro!(1122);
+    collapsed_macro!(1123);
+    collapsed_macro!(1124);
+    collapsed_macro!(1125);
+    collapsed_macro!(1126);
+    collapsed_macro!(1127);
+    collapsed_macro!(1128);
+    collapsed_macro!(1129);
+    collapsed_macro!(1130);
+    collapsed_macro!(1131);
+    collapsed_macro!(1132);
+    collapsed_macro!(1133);
+    collapsed_macro!(1134);
+    collapsed_macro!(1135);
+    collapsed_macro!(1136);
+    collapsed_macro!(1137);
+    collapsed_macro!(1138);
+    collapsed_macro!(1139);
+    collapsed_macro!(1140);
+    collapsed_macro!(1141);
+    collapsed_macro!(1142);
+    collapsed_macro!(1143);
+    collapsed_macro!(1144);
+    collapsed_macro!(1145);
+    collapsed_macro!(1146);
+    collapsed_macro!(1147);
+    collapsed_macro!(1148);
+    collapsed_macro!(1149);
+    collapsed_macro!(1150);
+    collapsed_macro!(1151);
+    collapsed_macro!(1152);
+    collapsed_macro!(1153);
+    collapsed_macro!(1154);
+    collapsed_macro!(1155);
+    collapsed_macro!(1156);
+    collapsed_macro!(1157);
+    collapsed_macro!(1158);
+    collapsed_macro!(1159);
+    collapsed_macro!(1160);
+    collapsed_macro!(1161);
+    collapsed_macro!(1162);
+    collapsed_macro!(1163);
+    collapsed_macro!(1164);
+    collapsed_macro!(1165);
+    collapsed_macro!(1166);
+    collapsed_macro!(1167);
+    collapsed_macro!(1168);
+    collapsed_macro!(1169);
+    collapsed_macro!(1170);
+    collapsed_macro!(1171);
+    collapsed_macro!(1172);
+    collapsed_macro!(1173);
+    collapsed_macro!(1174);
+    collapsed_macro!(1175);
+    collapsed_macro!(1176);
+    collapsed_macro!(1177);
+    collapsed_macro!(1178);
+    collapsed_macro!(1179);
+    collapsed_macro!(1180);
+    collapsed_macro!(1181);
+    collapsed_macro!(1182);
+    collapsed_macro!(1183);
+    collapsed_macro!(1184);
+    collapsed_macro!(1185);
+    collapsed_macro!(1186);
+    collapsed_macro!(1187);
+    collapsed_macro!(1188);
+    collapsed_macro!(1189);
+    collapsed_macro!(1190);
+    collapsed_macro!(1191);
+    collapsed_macro!(1192);
+    collapsed_macro!(1193);
+    collapsed_macro!(1194);
+    collapsed_macro!(1195);
+    collapsed_macro!(1196);
+    collapsed_macro!(1197);
+    collapsed_macro!(1198);
+    collapsed_macro!(1199);
+    collapsed_macro!(1200);
+    collapsed_macro!(1201);
+    collapsed_macro!(1202);
+    collapsed_macro!(1203);
+    collapsed_macro!(1204);
+    collapsed_macro!(1205);
+    collapsed_macro!(1206);
+    collapsed_macro!(1207);
+    collapsed_macro!(1208);
+    collapsed_macro!(1209);
+    collapsed_macro!(1210);
+    collapsed_macro!(1211);
+    collapsed_macro!(1212);
+    collapsed_macro!(1213);
+    collapsed_macro!(1214);
+    collapsed_macro!(1215);
+    collapsed_macro!(1216);
+    collapsed_macro!(1217);
+    collapsed_macro!(1218);
+    collapsed_macro!(1219);
+    collapsed_macro!(1220);
+    collapsed_macro!(1221);
+    collapsed_macro!(1222);
+    collapsed_macro!(1223);
+    collapsed_macro!(1224);
+    collapsed_macro!(1225);
+    collapsed_macro!(1226);
+    collapsed_macro!(1227);
+    collapsed_macro!(1228);
+    collapsed_macro!(1229);
+    collapsed_macro!(1230);
+    collapsed_macro!(1231);
+    collapsed_macro!(1232);
+    collapsed_macro!(1233);
+    collapsed_macro!(1234);
+    collapsed_macro!(1235);
+    collapsed_macro!(1236);
+    collapsed_macro!(1237);
+    collapsed_macro!(1238);
+    collapsed_macro!(1239);
+    collapsed_macro!(1240);
+    collapsed_macro!(1241);
+    collapsed_macro!(1242);
+    collapsed_macro!(1243);
+    collapsed_macro!(1244);
+    collapsed_macro!(1245);
+    collapsed_macro!(1246);
+    collapsed_macro!(1247);
+    collapsed_macro!(1248);
+    collapsed_macro!(1249);
+    collapsed_macro!(1250);
+    collapsed_macro!(1251);
+    collapsed_macro!(1252);
+    collapsed_macro!(1253);
+    collapsed_macro!(1254);
+    collapsed_macro!(1255);
+    collapsed_macro!(1256);
+    collapsed_macro!(1257);
+    collapsed_macro!(1258);
+    collapsed_macro!(1259);
+    collapsed_macro!(1260);
+    collapsed_macro!(1261);
+    collapsed_macro!(1262);
+    collapsed_macro!(1263);
+    collapsed_macro!(1264);
+    collapsed_macro!(1265);
+    collapsed_macro!(1266);
+    collapsed_macro!(1267);
+    collapsed_macro!(1268);
+    collapsed_macro!(1269);
+    collapsed_macro!(1270);
+    collapsed_macro!(1271);
+    collapsed_macro!(1272);
+    collapsed_macro!(1273);
+    collapsed_macro!(1274);
+    collapsed_macro!(1275);
+    collapsed_macro!(1276);
+    collapsed_macro!(1277);
+    collapsed_macro!(1278);
+    collapsed_macro!(1279);
+    collapsed_macro!(1280);
+    collapsed_macro!(1281);
+    collapsed_macro!(1282);
+    collapsed_macro!(1283);
+    collapsed_macro!(1284);
+    collapsed_macro!(1285);
+    collapsed_macro!(1286);
+    collapsed_macro!(1287);
+    collapsed_macro!(1288);
+    collapsed_macro!(1289);
+    collapsed_macro!(1290);
+    collapsed_macro!(1291);
+    collapsed_macro!(1292);
+    collapsed_macro!(1293);
+    collapsed_macro!(1294);
+    collapsed_macro!(1295);
+    collapsed_macro!(1296);
+    collapsed_macro!(1297);
+    collapsed_macro!(1298);
+    collapsed_macro!(1299);
+    collapsed_macro!(1300);
+    collapsed_macro!(1301);
+    collapsed_macro!(1302);
+    collapsed_macro!(1303);
+    collapsed_macro!(1304);
+    collapsed_macro!(1305);
+    collapsed_macro!(1306);
+    collapsed_macro!(1307);
+    collapsed_macro!(1308);
+    collapsed_macro!(1309);
+    collapsed_macro!(1310);
+    collapsed_macro!(1311);
+    collapsed_macro!(1312);
+    collapsed_macro!(1313);
+    collapsed_macro!(1314);
+    collapsed_macro!(1315);
+    collapsed_macro!(1316);
+    collapsed_macro!(1317);
+    collapsed_macro!(1318);
+    collapsed_macro!(1319);
+    collapsed_macro!(1320);
+    collapsed_macro!(1321);
+    collapsed_macro!(1322);
+    collapsed_macro!(1323);
+    collapsed_macro!(1324);
+    collapsed_macro!(1325);
+    collapsed_macro!(1326);
+    collapsed_macro!(1327);
+    collapsed_macro!(1328);
+    collapsed_macro!(1329);
+    collapsed_macro!(1330);
+    collapsed_macro!(1331);
+    collapsed_macro!(1332);
+    collapsed_macro!(1333);
+    collapsed_macro!(1334);
+    collapsed_macro!(1335);
+    collapsed_macro!(1336);
+    collapsed_macro!(1337);
+    collapsed_macro!(1338);
+    collapsed_macro!(1339);
+    collapsed_macro!(1340);
+    collapsed_macro!(1341);
+    collapsed_macro!(1342);
+    collapsed_macro!(1343);
+    collapsed_macro!(1344);
+    collapsed_macro!(1345);
+    collapsed_macro!(1346);
+    collapsed_macro!(1347);
+    collapsed_macro!(1348);
+    collapsed_macro!(1349);
+    collapsed_macro!(1350);
+    collapsed_macro!(1351);
+    collapsed_macro!(1352);
+    collapsed_macro!(1353);
+    collapsed_macro!(1354);
+    collapsed_macro!(1355);
+    collapsed_macro!(1356);
+    collapsed_macro!(1357);
+    collapsed_macro!(1358);
+    collapsed_macro!(1359);
+    collapsed_macro!(1360);
+    collapsed_macro!(1361);
+    collapsed_macro!(1362);
+    collapsed_macro!(1363);
+    collapsed_macro!(1364);
+    collapsed_macro!(1365);
+    collapsed_macro!(1366);
+    collapsed_macro!(1367);
+    collapsed_macro!(1368);
+    collapsed_macro!(1369);
+    collapsed_macro!(1370);
+    collapsed_macro!(1371);
+    collapsed_macro!(1372);
+    collapsed_macro!(1373);
+    collapsed_macro!(1374);
+    collapsed_macro!(1375);
+    collapsed_macro!(1376);
+    collapsed_macro!(1377);
+    collapsed_macro!(1378);
+    collapsed_macro!(1379);
+    collapsed_macro!(1380);
+    collapsed_macro!(1381);
+    collapsed_macro!(1382);
+    collapsed_macro!(1383);
+    collapsed_macro!(1384);
+    collapsed_macro!(1385);
+    collapsed_macro!(1386);
+    collapsed_macro!(1387);
+    collapsed_macro!(1388);
+    collapsed_macro!(1389);
+    collapsed_macro!(1390);
+    collapsed_macro!(1391);
+    collapsed_macro!(1392);
+    collapsed_macro!(1393);
+    collapsed_macro!(1394);
+    collapsed_macro!(1395);
+    collapsed_macro!(1396);
+    collapsed_macro!(1397);
+    collapsed_macro!(1398);
+    collapsed_macro!(1399);
+    collapsed_macro!(1400);
+    collapsed_macro!(1401);
+    collapsed_macro!(1402);
+    collapsed_macro!(1403);
+    collapsed_macro!(1404);
+    collapsed_macro!(1405);
+    collapsed_macro!(1406);
+    collapsed_macro!(1407);
+    collapsed_macro!(1408);
+    collapsed_macro!(1409);
+    collapsed_macro!(1410);
+    collapsed_macro!(1411);
+    collapsed_macro!(1412);
+    collapsed_macro!(1413);
+    collapsed_macro!(1414);
+    collapsed_macro!(1415);
+    collapsed_macro!(1416);
+    collapsed_macro!(1417);
+    collapsed_macro!(1418);
+    collapsed_macro!(1419);
+    collapsed_macro!(1420);
+    collapsed_macro!(1421);
+    collapsed_macro!(1422);
+    collapsed_macro!(1423);
+    collapsed_macro!(1424);
+    collapsed_macro!(1425);
+    collapsed_macro!(1426);
+    collapsed_macro!(1427);
+    collapsed_macro!(1428);
+    collapsed_macro!(1429);
+    collapsed_macro!(1430);
+    collapsed_macro!(1431);
+    collapsed_macro!(1432);
+    collapsed_macro!(1433);
+    collapsed_macro!(1434);
+    collapsed_macro!(1435);
+    collapsed_macro!(1436);
+    collapsed_macro!(1437);
+    collapsed_macro!(1438);
+    collapsed_macro!(1439);
+    collapsed_macro!(1440);
+    collapsed_macro!(1441);
+    collapsed_macro!(1442);
+    collapsed_macro!(1443);
+    collapsed_macro!(1444);
+    collapsed_macro!(1445);
+    collapsed_macro!(1446);
+    collapsed_macro!(1447);
+    collapsed_macro!(1448);
+    collapsed_macro!(1449);
+    collapsed_macro!(1450);
+    collapsed_macro!(1451);
+    collapsed_macro!(1452);
+    collapsed_macro!(1453);
+    collapsed_macro!(1454);
+    collapsed_macro!(1455);
+    collapsed_macro!(1456);
+    collapsed_macro!(1457);
+    collapsed_macro!(1458);
+    collapsed_macro!(1459);
+    collapsed_macro!(1460);
+    collapsed_macro!(1461);
+    collapsed_macro!(1462);
+    collapsed_macro!(1463);
+    collapsed_macro!(1464);
+    collapsed_macro!(1465);
+    collapsed_macro!(1466);
+    collapsed_macro!(1467);
+    collapsed_macro!(1468);
+    collapsed_macro!(1469);
+    collapsed_macro!(1470);
+    collapsed_macro!(1471);
+    collapsed_macro!(1472);
+    collapsed_macro!(1473);
+    collapsed_macro!(1474);
+    collapsed_macro!(1475);
+    collapsed_macro!(1476);
+    collapsed_macro!(1477);
+    collapsed_macro!(1478);
+    collapsed_macro!(1479);
+    collapsed_macro!(1480);
+    collapsed_macro!(1481);
+    collapsed_macro!(1482);
+    collapsed_macro!(1483);
+    collapsed_macro!(1484);
+    collapsed_macro!(1485);
+    collapsed_macro!(1486);
+    collapsed_macro!(1487);
+    collapsed_macro!(1488);
+    collapsed_macro!(1489);
+    collapsed_macro!(1490);
+    collapsed_macro!(1491);
+    collapsed_macro!(1492);
+    collapsed_macro!(1493);
+    collapsed_macro!(1494);
+    collapsed_macro!(1495);
+    collapsed_macro!(1496);
+    collapsed_macro!(1497);
+    collapsed_macro!(1498);
+    collapsed_macro!(1499);
+    collapsed_macro!(1500);
+    collapsed_macro!(1501);
+    collapsed_macro!(1502);
+    collapsed_macro!(1503);
+    collapsed_macro!(1504);
+    collapsed_macro!(1505);
+    collapsed_macro!(1506);
+    collapsed_macro!(1507);
+    collapsed_macro!(1508);
+    collapsed_macro!(1509);
+    collapsed_macro!(1510);
+    collapsed_macro!(1511);
+    collapsed_macro!(1512);
+    collapsed_macro!(1513);
+    collapsed_macro!(1514);
+    collapsed_macro!(1515);
+    collapsed_macro!(1516);
+    collapsed_macro!(1517);
+    collapsed_macro!(1518);
+    collapsed_macro!(1519);
+    collapsed_macro!(1520);
+    collapsed_macro!(1521);
+    collapsed_macro!(1522);
+    collapsed_macro!(1523);
+    collapsed_macro!(1524);
+    collapsed_macro!(1525);
+    collapsed_macro!(1526);
+    collapsed_macro!(1527);
+    collapsed_macro!(1528);
+    collapsed_macro!(1529);
+    collapsed_macro!(1530);
+    collapsed_macro!(1531);
+    collapsed_macro!(1532);
+    collapsed_macro!(1533);
+    collapsed_macro!(1534);
+    collapsed_macro!(1535);
+    collapsed_macro!(1536);
+    collapsed_macro!(1537);
+    collapsed_macro!(1538);
+    collapsed_macro!(1539);
+    collapsed_macro!(1540);
+    collapsed_macro!(1541);
+    collapsed_macro!(1542);
+    collapsed_macro!(1543);
+    collapsed_macro!(1544);
+    collapsed_macro!(1545);
+    collapsed_macro!(1546);
+    collapsed_macro!(1547);
+    collapsed_macro!(1548);
+    collapsed_macro!(1549);
+    collapsed_macro!(1550);
+    collapsed_macro!(1551);
+    collapsed_macro!(1552);
+    collapsed_macro!(1553);
+    collapsed_macro!(1554);
+    collapsed_macro!(1555);
+    collapsed_macro!(1556);
+    collapsed_macro!(1557);
+    collapsed_macro!(1558);
+    collapsed_macro!(1559);
+    collapsed_macro!(1560);
+    collapsed_macro!(1561);
+    collapsed_macro!(1562);
+    collapsed_macro!(1563);
+    collapsed_macro!(1564);
+    collapsed_macro!(1565);
+    collapsed_macro!(1566);
+    collapsed_macro!(1567);
+    collapsed_macro!(1568);
+    collapsed_macro!(1569);
+    collapsed_macro!(1570);
+    collapsed_macro!(1571);
+    collapsed_macro!(1572);
+    collapsed_macro!(1573);
+    collapsed_macro!(1574);
+    collapsed_macro!(1575);
+    collapsed_macro!(1576);
+    collapsed_macro!(1577);
+    collapsed_macro!(1578);
+    collapsed_macro!(1579);
+    collapsed_macro!(1580);
+    collapsed_macro!(1581);
+    collapsed_macro!(1582);
+    collapsed_macro!(1583);
+    collapsed_macro!(1584);
+    collapsed_macro!(1585);
+    collapsed_macro!(1586);
+    collapsed_macro!(1587);
+    collapsed_macro!(1588);
+    collapsed_macro!(1589);
+    collapsed_macro!(1590);
+    collapsed_macro!(1591);
+    collapsed_macro!(1592);
+    collapsed_macro!(1593);
+    collapsed_macro!(1594);
+    collapsed_macro!(1595);
+    collapsed_macro!(1596);
+    collapsed_macro!(1597);
+    collapsed_macro!(1598);
+    collapsed_macro!(1599);
+    collapsed_macro!(1600);
+    collapsed_macro!(1601);
+    collapsed_macro!(1602);
+    collapsed_macro!(1603);
+    collapsed_macro!(1604);
+    collapsed_macro!(1605);
+    collapsed_macro!(1606);
+    collapsed_macro!(1607);
+    collapsed_macro!(1608);
+    collapsed_macro!(1609);
+    collapsed_macro!(1610);
+    collapsed_macro!(1611);
+    collapsed_macro!(1612);
+    collapsed_macro!(1613);
+    collapsed_macro!(1614);
+    collapsed_macro!(1615);
+    collapsed_macro!(1616);
+    collapsed_macro!(1617);
+    collapsed_macro!(1618);
+    collapsed_macro!(1619);
+    collapsed_macro!(1620);
+    collapsed_macro!(1621);
+    collapsed_macro!(1622);
+    collapsed_macro!(1623);
+    collapsed_macro!(1624);
+    collapsed_macro!(1625);
+    collapsed_macro!(1626);
+    collapsed_macro!(1627);
+    collapsed_macro!(1628);
+    collapsed_macro!(1629);
+    collapsed_macro!(1630);
+    collapsed_macro!(1631);
+    collapsed_macro!(1632);
+    collapsed_macro!(1633);
+    collapsed_macro!(1634);
+    collapsed_macro!(1635);
+    collapsed_macro!(1636);
+    collapsed_macro!(1637);
+    collapsed_macro!(1638);
+    collapsed_macro!(1639);
+    collapsed_macro!(1640);
+    collapsed_macro!(1641);
+    collapsed_macro!(1642);
+    collapsed_macro!(1643);
+    collapsed_macro!(1644);
+    collapsed_macro!(1645);
+    collapsed_macro!(1646);
+    collapsed_macro!(1647);
+    collapsed_macro!(1648);
+    collapsed_macro!(1649);
+    collapsed_macro!(1650);
+    collapsed_macro!(1651);
+    collapsed_macro!(1652);
+    collapsed_macro!(1653);
+    collapsed_macro!(1654);
+    collapsed_macro!(1655);
+    collapsed_macro!(1656);
+    collapsed_macro!(1657);
+    collapsed_macro!(1658);
+    collapsed_macro!(1659);
+    collapsed_macro!(1660);
+    collapsed_macro!(1661);
+    collapsed_macro!(1662);
+    collapsed_macro!(1663);
+    collapsed_macro!(1664);
+    collapsed_macro!(1665);
+    collapsed_macro!(1666);
+    collapsed_macro!(1667);
+    collapsed_macro!(1668);
+    collapsed_macro!(1669);
+    collapsed_macro!(1670);
+    collapsed_macro!(1671);
+    collapsed_macro!(1672);
+    collapsed_macro!(1673);
+    collapsed_macro!(1674);
+    collapsed_macro!(1675);
+    collapsed_macro!(1676);
+    collapsed_macro!(1677);
+    collapsed_macro!(1678);
+    collapsed_macro!(1679);
+    collapsed_macro!(1680);
+    collapsed_macro!(1681);
+    collapsed_macro!(1682);
+    collapsed_macro!(1683);
+    collapsed_macro!(1684);
+    collapsed_macro!(1685);
+    collapsed_macro!(1686);
+    collapsed_macro!(1687);
+    collapsed_macro!(1688);
+    collapsed_macro!(1689);
+    collapsed_macro!(1690);
+    collapsed_macro!(1691);
+    collapsed_macro!(1692);
+    collapsed_macro!(1693);
+    collapsed_macro!(1694);
+    collapsed_macro!(1695);
+    collapsed_macro!(1696);
+    collapsed_macro!(1697);
+    collapsed_macro!(1698);
+    collapsed_macro!(1699);
+    collapsed_macro!(1700);
+    collapsed_macro!(1701);
+    collapsed_macro!(1702);
+    collapsed_macro!(1703);
+    collapsed_macro!(1704);
+    collapsed_macro!(1705);
+    collapsed_macro!(1706);
+    collapsed_macro!(1707);
+    collapsed_macro!(1708);
+    collapsed_macro!(1709);
+    collapsed_macro!(1710);
+    collapsed_macro!(1711);
+    collapsed_macro!(1712);
+    collapsed_macro!(1713);
+    collapsed_macro!(1714);
+    collapsed_macro!(1715);
+    collapsed_macro!(1716);
+    collapsed_macro!(1717);
+    collapsed_macro!(1718);
+    collapsed_macro!(1719);
+    collapsed_macro!(1720);
+    collapsed_macro!(1721);
+    collapsed_macro!(1722);
+    collapsed_macro!(1723);
+    collapsed_macro!(1724);
+    collapsed_macro!(1725);
+    collapsed_macro!(1726);
+    collapsed_macro!(1727);
+    collapsed_macro!(1728);
+    collapsed_macro!(1729);
+    collapsed_macro!(1730);
+    collapsed_macro!(1731);
+    collapsed_macro!(1732);
+    collapsed_macro!(1733);
+    collapsed_macro!(1734);
+    collapsed_macro!(1735);
+    collapsed_macro!(1736);
+    collapsed_macro!(1737);
+    collapsed_macro!(1738);
+    collapsed_macro!(1739);
+    collapsed_macro!(1740);
+    collapsed_macro!(1741);
+    collapsed_macro!(1742);
+    collapsed_macro!(1743);
+    collapsed_macro!(1744);
+    collapsed_macro!(1745);
+    collapsed_macro!(1746);
+    collapsed_macro!(1747);
+    collapsed_macro!(1748);
+    collapsed_macro!(1749);
+    collapsed_macro!(1750);
+    collapsed_macro!(1751);
+    collapsed_macro!(1752);
+    collapsed_macro!(1753);
+    collapsed_macro!(1754);
+    collapsed_macro!(1755);
+    collapsed_macro!(1756);
+    collapsed_macro!(1757);
+    collapsed_macro!(1758);
+    collapsed_macro!(1759);
+    collapsed_macro!(1760);
+    collapsed_macro!(1761);
+    collapsed_macro!(1762);
+    collapsed_macro!(1763);
+    collapsed_macro!(1764);
+    collapsed_macro!(1765);
+    collapsed_macro!(1766);
+    collapsed_macro!(1767);
+    collapsed_macro!(1768);
+    collapsed_macro!(1769);
+    collapsed_macro!(1770);
+    collapsed_macro!(1771);
+    collapsed_macro!(1772);
+    collapsed_macro!(1773);
+    collapsed_macro!(1774);
+    collapsed_macro!(1775);
+    collapsed_macro!(1776);
+    collapsed_macro!(1777);
+    collapsed_macro!(1778);
+    collapsed_macro!(1779);
+    collapsed_macro!(1780);
+    collapsed_macro!(1781);
+    collapsed_macro!(1782);
+    collapsed_macro!(1783);
+    collapsed_macro!(1784);
+    collapsed_macro!(1785);
+    collapsed_macro!(1786);
+    collapsed_macro!(1787);
+    collapsed_macro!(1788);
+    collapsed_macro!(1789);
+    collapsed_macro!(1790);
+    collapsed_macro!(1791);
+    collapsed_macro!(1792);
+    collapsed_macro!(1793);
+    collapsed_macro!(1794);
+    collapsed_macro!(1795);
+    collapsed_macro!(1796);
+    collapsed_macro!(1797);
+    collapsed_macro!(1798);
+    collapsed_macro!(1799);
+    collapsed_macro!(1800);
+    collapsed_macro!(1801);
+    collapsed_macro!(1802);
+    collapsed_macro!(1803);
+    collapsed_macro!(1804);
+    collapsed_macro!(1805);
+    collapsed_macro!(1806);
+    collapsed_macro!(1807);
+    collapsed_macro!(1808);
+    collapsed_macro!(1809);
+    collapsed_macro!(1810);
+    collapsed_macro!(1811);
+    collapsed_macro!(1812);
+    collapsed_macro!(1813);
+    collapsed_macro!(1814);
+    collapsed_macro!(1815);
+    collapsed_macro!(1816);
+    collapsed_macro!(1817);
+    collapsed_macro!(1818);
+    collapsed_macro!(1819);
+    collapsed_macro!(1820);
+    collapsed_macro!(1821);
+    collapsed_macro!(1822);
+    collapsed_macro!(1823);
+    collapsed_macro!(1824);
+    collapsed_macro!(1825);
+    collapsed_macro!(1826);
+    collapsed_macro!(1827);
+    collapsed_macro!(1828);
+    collapsed_macro!(1829);
+    collapsed_macro!(1830);
+    collapsed_macro!(1831);
+    collapsed_macro!(1832);
+    collapsed_macro!(1833);
+    collapsed_macro!(1834);
+    collapsed_macro!(1835);
+    collapsed_macro!(1836);
+    collapsed_macro!(1837);
+    collapsed_macro!(1838);
+    collapsed_macro!(1839);
+    collapsed_macro!(1840);
+    collapsed_macro!(1841);
+    collapsed_macro!(1842);
+    collapsed_macro!(1843);
+    collapsed_macro!(1844);
+    collapsed_macro!(1845);
+    collapsed_macro!(1846);
+    collapsed_macro!(1847);
+    collapsed_macro!(1848);
+    collapsed_macro!(1849);
+    collapsed_macro!(1850);
+    collapsed_macro!(1851);
+    collapsed_macro!(1852);
+    collapsed_macro!(1853);
+    collapsed_macro!(1854);
+    collapsed_macro!(1855);
+    collapsed_macro!(1856);
+    collapsed_macro!(1857);
+    collapsed_macro!(1858);
+    collapsed_macro!(1859);
+    collapsed_macro!(1860);
+    collapsed_macro!(1861);
+    collapsed_macro!(1862);
+    collapsed_macro!(1863);
+    collapsed_macro!(1864);
+    collapsed_macro!(1865);
+    collapsed_macro!(1866);
+    collapsed_macro!(1867);
+    collapsed_macro!(1868);
+    collapsed_macro!(1869);
+    collapsed_macro!(1870);
+    collapsed_macro!(1871);
+    collapsed_macro!(1872);
+    collapsed_macro!(1873);
+    collapsed_macro!(1874);
+    collapsed_macro!(1875);
+    collapsed_macro!(1876);
+    collapsed_macro!(1877);
+    collapsed_macro!(1878);
+    collapsed_macro!(1879);
+    collapsed_macro!(1880);
+    collapsed_macro!(1881);
+    collapsed_macro!(1882);
+    collapsed_macro!(1883);
+    collapsed_macro!(1884);
+    collapsed_macro!(1885);
+    collapsed_macro!(1886);
+    collapsed_macro!(1887);
+    collapsed_macro!(1888);
+    collapsed_macro!(1889);
+    collapsed_macro!(1890);
+    collapsed_macro!(1891);
+    collapsed_macro!(1892);
+    collapsed_macro!(1893);
+    collapsed_macro!(1894);
+    collapsed_macro!(1895);
+    collapsed_macro!(1896);
+    collapsed_macro!(1897);
+    collapsed_macro!(1898);
+    collapsed_macro!(1899);
+    collapsed_macro!(1900);
+    collapsed_macro!(1901);
+    collapsed_macro!(1902);
+    collapsed_macro!(1903);
+    collapsed_macro!(1904);
+    collapsed_macro!(1905);
+    collapsed_macro!(1906);
+    collapsed_macro!(1907);
+    collapsed_macro!(1908);
+    collapsed_macro!(1909);
+    collapsed_macro!(1910);
+    collapsed_macro!(1911);
+    collapsed_macro!(1912);
+    collapsed_macro!(1913);
+    collapsed_macro!(1914);
+    collapsed_macro!(1915);
+    collapsed_macro!(1916);
+    collapsed_macro!(1917);
+    collapsed_macro!(1918);
+    collapsed_macro!(1919);
+    collapsed_macro!(1920);
+    collapsed_macro!(1921);
+    collapsed_macro!(1922);
+    collapsed_macro!(1923);
+    collapsed_macro!(1924);
+    collapsed_macro!(1925);
+    collapsed_macro!(1926);
+    collapsed_macro!(1927);
+    collapsed_macro!(1928);
+    collapsed_macro!(1929);
+    collapsed_macro!(1930);
+    collapsed_macro!(1931);
+    collapsed_macro!(1932);
+    collapsed_macro!(1933);
+    collapsed_macro!(1934);
+    collapsed_macro!(1935);
+    collapsed_macro!(1936);
+    collapsed_macro!(1937);
+    collapsed_macro!(1938);
+    collapsed_macro!(1939);
+    collapsed_macro!(1940);
+    collapsed_macro!(1941);
+    collapsed_macro!(1942);
+    collapsed_macro!(1943);
+    collapsed_macro!(1944);
+    collapsed_macro!(1945);
+    collapsed_macro!(1946);
+    collapsed_macro!(1947);
+    collapsed_macro!(1948);
+    collapsed_macro!(1949);
+    collapsed_macro!(1950);
+    collapsed_macro!(1951);
+    collapsed_macro!(1952);
+    collapsed_macro!(1953);
+    collapsed_macro!(1954);
+    collapsed_macro!(1955);
+    collapsed_macro!(1956);
+    collapsed_macro!(1957);
+    collapsed_macro!(1958);
+    collapsed_macro!(1959);
+    collapsed_macro!(1960);
+    collapsed_macro!(1961);
+    collapsed_macro!(1962);
+    collapsed_macro!(1963);
+    collapsed_macro!(1964);
+    collapsed_macro!(1965);
+    collapsed_macro!(1966);
+    collapsed_macro!(1967);
+    collapsed_macro!(1968);
+    collapsed_macro!(1969);
+    collapsed_macro!(1970);
+    collapsed_macro!(1971);
+    collapsed_macro!(1972);
+    collapsed_macro!(1973);
+    collapsed_macro!(1974);
+    collapsed_macro!(1975);
+    collapsed_macro!(1976);
+    collapsed_macro!(1977);
+    collapsed_macro!(1978);
+    collapsed_macro!(1979);
+    collapsed_macro!(1980);
+    collapsed_macro!(1981);
+    collapsed_macro!(1982);
+    collapsed_macro!(1983);
+    collapsed_macro!(1984);
+    collapsed_macro!(1985);
+    collapsed_macro!(1986);
+    collapsed_macro!(1987);
+    collapsed_macro!(1988);
+    collapsed_macro!(1989);
+    collapsed_macro!(1990);
+    collapsed_macro!(1991);
+    collapsed_macro!(1992);
+    collapsed_macro!(1993);
+    collapsed_macro!(1994);
+    collapsed_macro!(1995);
+    collapsed_macro!(1996);
+    collapsed_macro!(1997);
+    collapsed_macro!(1998);
+    collapsed_macro!(1999);
+    collapsed_macro!(2000);
+    collapsed_macro!(2001);
+    collapsed_macro!(2002);
+    collapsed_macro!(2003);
+    collapsed_macro!(2004);
+    collapsed_macro!(2005);
+    collapsed_macro!(2006);
+    collapsed_macro!(2007);
+    collapsed_macro!(2008);
+    collapsed_macro!(2009);
+    collapsed_macro!(2010);
+    collapsed_macro!(2011);
+    collapsed_macro!(2012);
+    collapsed_macro!(2013);
+    collapsed_macro!(2014);
+    collapsed_macro!(2015);
+    collapsed_macro!(2016);
+    collapsed_macro!(2017);
+    collapsed_macro!(2018);
+    collapsed_macro!(2019);
+    collapsed_macro!(2020);
+    collapsed_macro!(2021);
+    collapsed_macro!(2022);
+    collapsed_macro!(2023);
+    collapsed_macro!(2024);
+    collapsed_macro!(2025);
+    collapsed_macro!(2026);
+    collapsed_macro!(2027);
+    collapsed_macro!(2028);
+    collapsed_macro!(2029);
+    collapsed_macro!(2030);
+    collapsed_macro!(2031);
+    collapsed_macro!(2032);
+    collapsed_macro!(2033);
+    collapsed_macro!(2034);
+    collapsed_macro!(2035);
+    collapsed_macro!(2036);
+    collapsed_macro!(2037);
+    collapsed_macro!(2038);
+    collapsed_macro!(2039);
+    collapsed_macro!(2040);
+    collapsed_macro!(2041);
+    collapsed_macro!(2042);
+    collapsed_macro!(2043);
+    collapsed_macro!(2044);
+    collapsed_macro!(2045);
+    collapsed_macro!(2046);
+    collapsed_macro!(2047);
+    collapsed_macro!(2048);
+    collapsed_macro!(2049);
+    collapsed_macro!(2050);
+    collapsed_macro!(2051);
+    collapsed_macro!(2052);
+    collapsed_macro!(2053);
+    collapsed_macro!(2054);
+    collapsed_macro!(2055);
+    collapsed_macro!(2056);
+    collapsed_macro!(2057);
+    collapsed_macro!(2058);
+    collapsed_macro!(2059);
+    collapsed_macro!(2060);
+    collapsed_macro!(2061);
+    collapsed_macro!(2062);
+    collapsed_macro!(2063);
+    collapsed_macro!(2064);
+    collapsed_macro!(2065);
+    collapsed_macro!(2066);
+    collapsed_macro!(2067);
+    collapsed_macro!(2068);
+    collapsed_macro!(2069);
+    collapsed_macro!(2070);
+    collapsed_macro!(2071);
+    collapsed_macro!(2072);
+    collapsed_macro!(2073);
+    collapsed_macro!(2074);
+    collapsed_macro!(2075);
+    collapsed_macro!(2076);
+    collapsed_macro!(2077);
+    collapsed_macro!(2078);
+    collapsed_macro!(2079);
+    collapsed_macro!(2080);
+    collapsed_macro!(2081);
+    collapsed_macro!(2082);
+    collapsed_macro!(2083);
+    collapsed_macro!(2084);
+    collapsed_macro!(2085);
+    collapsed_macro!(2086);
+    collapsed_macro!(2087);
+    collapsed_macro!(2088);
+    collapsed_macro!(2089);
+    collapsed_macro!(2090);
+    collapsed_macro!(2091);
+    collapsed_macro!(2092);
+    collapsed_macro!(2093);
+    collapsed_macro!(2094);
+    collapsed_macro!(2095);
+    collapsed_macro!(2096);
+    collapsed_macro!(2097);
+    collapsed_macro!(2098);
+    collapsed_macro!(2099);
+    collapsed_macro!(2100);
+    collapsed_macro!(2101);
+    collapsed_macro!(2102);
+    collapsed_macro!(2103);
+    collapsed_macro!(2104);
+    collapsed_macro!(2105);
+    collapsed_macro!(2106);
+    collapsed_macro!(2107);
+    collapsed_macro!(2108);
+    collapsed_macro!(2109);
+    collapsed_macro!(2110);
+    collapsed_macro!(2111);
+    collapsed_macro!(2112);
+    collapsed_macro!(2113);
+    collapsed_macro!(2114);
+    collapsed_macro!(2115);
+    collapsed_macro!(2116);
+    collapsed_macro!(2117);
+    collapsed_macro!(2118);
+    collapsed_macro!(2119);
+    collapsed_macro!(2120);
+    collapsed_macro!(2121);
+    collapsed_macro!(2122);
+    collapsed_macro!(2123);
+    collapsed_macro!(2124);
+    collapsed_macro!(2125);
+    collapsed_macro!(2126);
+    collapsed_macro!(2127);
+    collapsed_macro!(2128);
+    collapsed_macro!(2129);
+    collapsed_macro!(2130);
+    collapsed_macro!(2131);
+    collapsed_macro!(2132);
+    collapsed_macro!(2133);
+    collapsed_macro!(2134);
+    collapsed_macro!(2135);
+    collapsed_macro!(2136);
+    collapsed_macro!(2137);
+    collapsed_macro!(2138);
+    collapsed_macro!(2139);
+    collapsed_macro!(2140);
+    collapsed_macro!(2141);
+    collapsed_macro!(2142);
+    collapsed_macro!(2143);
+    collapsed_macro!(2144);
+    collapsed_macro!(2145);
+    collapsed_macro!(2146);
+    collapsed_macro!(2147);
+    collapsed_macro!(2148);
+    collapsed_macro!(2149);
+    collapsed_macro!(2150);
+    collapsed_macro!(2151);
+    collapsed_macro!(2152);
+    collapsed_macro!(2153);
+    collapsed_macro!(2154);
+    collapsed_macro!(2155);
+    collapsed_macro!(2156);
+    collapsed_macro!(2157);
+    collapsed_macro!(2158);
+    collapsed_macro!(2159);
+    collapsed_macro!(2160);
+    collapsed_macro!(2161);
+    collapsed_macro!(2162);
+    collapsed_macro!(2163);
+    collapsed_macro!(2164);
+    collapsed_macro!(2165);
+    collapsed_macro!(2166);
+    collapsed_macro!(2167);
+    collapsed_macro!(2168);
+    collapsed_macro!(2169);
+    collapsed_macro!(2170);
+    collapsed_macro!(2171);
+    collapsed_macro!(2172);
+    collapsed_macro!(2173);
+    collapsed_macro!(2174);
+    collapsed_macro!(2175);
+    collapsed_macro!(2176);
+    collapsed_macro!(2177);
+    collapsed_macro!(2178);
+    collapsed_macro!(2179);
+    collapsed_macro!(2180);
+    collapsed_macro!(2181);
+    collapsed_macro!(2182);
+    collapsed_macro!(2183);
+    collapsed_macro!(2184);
+    collapsed_macro!(2185);
+    collapsed_macro!(2186);
+    collapsed_macro!(2187);
+    collapsed_macro!(2188);
+    collapsed_macro!(2189);
+    collapsed_macro!(2190);
+    collapsed_macro!(2191);
+    collapsed_macro!(2192);
+    collapsed_macro!(2193);
+    collapsed_macro!(2194);
+    collapsed_macro!(2195);
+    collapsed_macro!(2196);
+    collapsed_macro!(2197);
+    collapsed_macro!(2198);
+    collapsed_macro!(2199);
+    collapsed_macro!(2200);
+    collapsed_macro!(2201);
+    collapsed_macro!(2202);
+    collapsed_macro!(2203);
+    collapsed_macro!(2204);
+    collapsed_macro!(2205);
+    collapsed_macro!(2206);
+    collapsed_macro!(2207);
+    collapsed_macro!(2208);
+    collapsed_macro!(2209);
+    collapsed_macro!(2210);
+    collapsed_macro!(2211);
+    collapsed_macro!(2212);
+    collapsed_macro!(2213);
+    collapsed_macro!(2214);
+    collapsed_macro!(2215);
+    collapsed_macro!(2216);
+    collapsed_macro!(2217);
+    collapsed_macro!(2218);
+    collapsed_macro!(2219);
+    collapsed_macro!(2220);
+    collapsed_macro!(2221);
+    collapsed_macro!(2222);
+    collapsed_macro!(2223);
+    collapsed_macro!(2224);
+    collapsed_macro!(2225);
+    collapsed_macro!(2226);
+    collapsed_macro!(2227);
+    collapsed_macro!(2228);
+    collapsed_macro!(2229);
+    collapsed_macro!(2230);
+    collapsed_macro!(2231);
+    collapsed_macro!(2232);
+    collapsed_macro!(2233);
+    collapsed_macro!(2234);
+    collapsed_macro!(2235);
+    collapsed_macro!(2236);
+    collapsed_macro!(2237);
+    collapsed_macro!(2238);
+    collapsed_macro!(2239);
+    collapsed_macro!(2240);
+    collapsed_macro!(2241);
+    collapsed_macro!(2242);
+    collapsed_macro!(2243);
+    collapsed_macro!(2244);
+    collapsed_macro!(2245);
+    collapsed_macro!(2246);
+    collapsed_macro!(2247);
+    collapsed_macro!(2248);
+    collapsed_macro!(2249);
+    collapsed_macro!(2250);
+    collapsed_macro!(2251);
+    collapsed_macro!(2252);
+    collapsed_macro!(2253);
+    collapsed_macro!(2254);
+    collapsed_macro!(2255);
+    collapsed_macro!(2256);
+    collapsed_macro!(2257);
+    collapsed_macro!(2258);
+    collapsed_macro!(2259);
+    collapsed_macro!(2260);
+    collapsed_macro!(2261);
+    collapsed_macro!(2262);
+    collapsed_macro!(2263);
+    collapsed_macro!(2264);
+    collapsed_macro!(2265);
+    collapsed_macro!(2266);
+    collapsed_macro!(2267);
+    collapsed_macro!(2268);
+    collapsed_macro!(2269);
+    collapsed_macro!(2270);
+    collapsed_macro!(2271);
+    collapsed_macro!(2272);
+    collapsed_macro!(2273);
+    collapsed_macro!(2274);
+    collapsed_macro!(2275);
+    collapsed_macro!(2276);
+    collapsed_macro!(2277);
+    collapsed_macro!(2278);
+    collapsed_macro!(2279);
+    collapsed_macro!(2280);
+    collapsed_macro!(2281);
+    collapsed_macro!(2282);
+    collapsed_macro!(2283);
+    collapsed_macro!(2284);
+    collapsed_macro!(2285);
+    collapsed_macro!(2286);
+    collapsed_macro!(2287);
+    collapsed_macro!(2288);
+    collapsed_macro!(2289);
+    collapsed_macro!(2290);
+    collapsed_macro!(2291);
+    collapsed_macro!(2292);
+    collapsed_macro!(2293);
+    collapsed_macro!(2294);
+    collapsed_macro!(2295);
+    collapsed_macro!(2296);
+    collapsed_macro!(2297);
+    collapsed_macro!(2298);
+    collapsed_macro!(2299);
+    collapsed_macro!(2300);
+    collapsed_macro!(2301);
+    collapsed_macro!(2302);
+    collapsed_macro!(2303);
+    collapsed_macro!(2304);
+    collapsed_macro!(2305);
+    collapsed_macro!(2306);
+    collapsed_macro!(2307);
+    collapsed_macro!(2308);
+    collapsed_macro!(2309);
+    collapsed_macro!(2310);
+    collapsed_macro!(2311);
+    collapsed_macro!(2312);
+    collapsed_macro!(2313);
+    collapsed_macro!(2314);
+    collapsed_macro!(2315);
+    collapsed_macro!(2316);
+    collapsed_macro!(2317);
+    collapsed_macro!(2318);
+    collapsed_macro!(2319);
+    collapsed_macro!(2320);
+    collapsed_macro!(2321);
+    collapsed_macro!(2322);
+    collapsed_macro!(2323);
+    collapsed_macro!(2324);
+    collapsed_macro!(2325);
+    collapsed_macro!(2326);
+    collapsed_macro!(2327);
+    collapsed_macro!(2328);
+    collapsed_macro!(2329);
+    collapsed_macro!(2330);
+    collapsed_macro!(2331);
+    collapsed_macro!(2332);
+    collapsed_macro!(2333);
+    collapsed_macro!(2334);
+    collapsed_macro!(2335);
+    collapsed_macro!(2336);
+    collapsed_macro!(2337);
+    collapsed_macro!(2338);
+    collapsed_macro!(2339);
+    collapsed_macro!(2340);
+    collapsed_macro!(2341);
+    collapsed_macro!(2342);
+    collapsed_macro!(2343);
+    collapsed_macro!(2344);
+    collapsed_macro!(2345);
+    collapsed_macro!(2346);
+    collapsed_macro!(2347);
+    collapsed_macro!(2348);
+    collapsed_macro!(2349);
+    collapsed_macro!(2350);
+    collapsed_macro!(2351);
+    collapsed_macro!(2352);
+    collapsed_macro!(2353);
+    collapsed_macro!(2354);
+    collapsed_macro!(2355);
+    collapsed_macro!(2356);
+    collapsed_macro!(2357);
+    collapsed_macro!(2358);
+    collapsed_macro!(2359);
+    collapsed_macro!(2360);
+    collapsed_macro!(2361);
+    collapsed_macro!(2362);
+    collapsed_macro!(2363);
+    collapsed_macro!(2364);
+    collapsed_macro!(2365);
+    collapsed_macro!(2366);
+    collapsed_macro!(2367);
+    collapsed_macro!(2368);
+    collapsed_macro!(2369);
+    collapsed_macro!(2370);
+    collapsed_macro!(2371);
+    collapsed_macro!(2372);
+    collapsed_macro!(2373);
+    collapsed_macro!(2374);
+    collapsed_macro!(2375);
+    collapsed_macro!(2376);
+    collapsed_macro!(2377);
+    collapsed_macro!(2378);
+    collapsed_macro!(2379);
+    collapsed_macro!(2380);
+    collapsed_macro!(2381);
+    collapsed_macro!(2382);
+    collapsed_macro!(2383);
+    collapsed_macro!(2384);
+    collapsed_macro!(2385);
+    collapsed_macro!(2386);
+    collapsed_macro!(2387);
+    collapsed_macro!(2388);
+    collapsed_macro!(2389);
+    collapsed_macro!(2390);
+    collapsed_macro!(2391);
+    collapsed_macro!(2392);
+    collapsed_macro!(2393);
+    collapsed_macro!(2394);
+    collapsed_macro!(2395);
+    collapsed_macro!(2396);
+    collapsed_macro!(2397);
+    collapsed_macro!(2398);
+    collapsed_macro!(2399);
+    collapsed_macro!(2400);
+    collapsed_macro!(2401);
+    collapsed_macro!(2402);
+    collapsed_macro!(2403);
+    collapsed_macro!(2404);
+    collapsed_macro!(2405);
+    collapsed_macro!(2406);
+    collapsed_macro!(2407);
+    collapsed_macro!(2408);
+    collapsed_macro!(2409);
+    collapsed_macro!(2410);
+    collapsed_macro!(2411);
+    collapsed_macro!(2412);
+    collapsed_macro!(2413);
+    collapsed_macro!(2414);
+    collapsed_macro!(2415);
+    collapsed_macro!(2416);
+    collapsed_macro!(2417);
+    collapsed_macro!(2418);
+    collapsed_macro!(2419);
+    collapsed_macro!(2420);
+    collapsed_macro!(2421);
+    collapsed_macro!(2422);
+    collapsed_macro!(2423);
+    collapsed_macro!(2424);
+    collapsed_macro!(2425);
+    collapsed_macro!(2426);
+    collapsed_macro!(2427);
+    collapsed_macro!(2428);
+    collapsed_macro!(2429);
+    collapsed_macro!(2430);
+    collapsed_macro!(2431);
+    collapsed_macro!(2432);
+    collapsed_macro!(2433);
+    collapsed_macro!(2434);
+    collapsed_macro!(2435);
+    collapsed_macro!(2436);
+    collapsed_macro!(2437);
+    collapsed_macro!(2438);
+    collapsed_macro!(2439);
+    collapsed_macro!(2440);
+    collapsed_macro!(2441);
+    collapsed_macro!(2442);
+    collapsed_macro!(2443);
+    collapsed_macro!(2444);
+    collapsed_macro!(2445);
+    collapsed_macro!(2446);
+    collapsed_macro!(2447);
+    collapsed_macro!(2448);
+    collapsed_macro!(2449);
+    collapsed_macro!(2450);
+    collapsed_macro!(2451);
+    collapsed_macro!(2452);
+    collapsed_macro!(2453);
+    collapsed_macro!(2454);
+    collapsed_macro!(2455);
+    collapsed_macro!(2456);
+    collapsed_macro!(2457);
+    collapsed_macro!(2458);
+    collapsed_macro!(2459);
+    collapsed_macro!(2460);
+    collapsed_macro!(2461);
+    collapsed_macro!(2462);
+    collapsed_macro!(2463);
+    collapsed_macro!(2464);
+    collapsed_macro!(2465);
+    collapsed_macro!(2466);
+    collapsed_macro!(2467);
+    collapsed_macro!(2468);
+    collapsed_macro!(2469);
+    collapsed_macro!(2470);
+    collapsed_macro!(2471);
+    collapsed_macro!(2472);
+    collapsed_macro!(2473);
+    collapsed_macro!(2474);
+    collapsed_macro!(2475);
+    collapsed_macro!(2476);
+    collapsed_macro!(2477);
+    collapsed_macro!(2478);
+    collapsed_macro!(2479);
+    collapsed_macro!(2480);
+    collapsed_macro!(2481);
+    collapsed_macro!(2482);
+    collapsed_macro!(2483);
+    collapsed_macro!(2484);
+    collapsed_macro!(2485);
+    collapsed_macro!(2486);
+    collapsed_macro!(2487);
+    collapsed_macro!(2488);
+    collapsed_macro!(2489);
+    collapsed_macro!(2490);
+    collapsed_macro!(2491);
+    collapsed_macro!(2492);
+    collapsed_macro!(2493);
+    collapsed_macro!(2494);
+    collapsed_macro!(2495);
+    collapsed_macro!(2496);
+    collapsed_macro!(2497);
+    collapsed_macro!(2498);
+    collapsed_macro!(2499);
+    collapsed_macro!(2500);
+    collapsed_macro!(2501);
+    collapsed_macro!(2502);
+    collapsed_macro!(2503);
+    collapsed_macro!(2504);
+    collapsed_macro!(2505);
+    collapsed_macro!(2506);
+    collapsed_macro!(2507);
+    collapsed_macro!(2508);
+    collapsed_macro!(2509);
+    collapsed_macro!(2510);
+    collapsed_macro!(2511);
+    collapsed_macro!(2512);
+    collapsed_macro!(2513);
+    collapsed_macro!(2514);
+    collapsed_macro!(2515);
+    collapsed_macro!(2516);
+    collapsed_macro!(2517);
+    collapsed_macro!(2518);
+    collapsed_macro!(2519);
+    collapsed_macro!(2520);
+    collapsed_macro!(2521);
+    collapsed_macro!(2522);
+    collapsed_macro!(2523);
+    collapsed_macro!(2524);
+    collapsed_macro!(2525);
+    collapsed_macro!(2526);
+    collapsed_macro!(2527);
+    collapsed_macro!(2528);
+    collapsed_macro!(2529);
+    collapsed_macro!(2530);
+    collapsed_macro!(2531);
+    collapsed_macro!(2532);
+    collapsed_macro!(2533);
+    collapsed_macro!(2534);
+    collapsed_macro!(2535);
+    collapsed_macro!(2536);
+    collapsed_macro!(2537);
+    collapsed_macro!(2538);
+    collapsed_macro!(2539);
+    collapsed_macro!(2540);
+    collapsed_macro!(2541);
+    collapsed_macro!(2542);
+    collapsed_macro!(2543);
+    collapsed_macro!(2544);
+    collapsed_macro!(2545);
+    collapsed_macro!(2546);
+    collapsed_macro!(2547);
+    collapsed_macro!(2548);
+    collapsed_macro!(2549);
+    collapsed_macro!(2550);
+    collapsed_macro!(2551);
+    collapsed_macro!(2552);
+    collapsed_macro!(2553);
+    collapsed_macro!(2554);
+    collapsed_macro!(2555);
+    collapsed_macro!(2556);
+    collapsed_macro!(2557);
+    collapsed_macro!(2558);
+    collapsed_macro!(2559);
+    collapsed_macro!(2560);
+    collapsed_macro!(2561);
+    collapsed_macro!(2562);
+    collapsed_macro!(2563);
+    collapsed_macro!(2564);
+    collapsed_macro!(2565);
+    collapsed_macro!(2566);
+    collapsed_macro!(2567);
+    collapsed_macro!(2568);
+    collapsed_macro!(2569);
+    collapsed_macro!(2570);
+    collapsed_macro!(2571);
+    collapsed_macro!(2572);
+    collapsed_macro!(2573);
+    collapsed_macro!(2574);
+    collapsed_macro!(2575);
+    collapsed_macro!(2576);
+    collapsed_macro!(2577);
+    collapsed_macro!(2578);
+    collapsed_macro!(2579);
+    collapsed_macro!(2580);
+    collapsed_macro!(2581);
+    collapsed_macro!(2582);
+    collapsed_macro!(2583);
+    collapsed_macro!(2584);
+    collapsed_macro!(2585);
+    collapsed_macro!(2586);
+    collapsed_macro!(2587);
+    collapsed_macro!(2588);
+    collapsed_macro!(2589);
+    collapsed_macro!(2590);
+    collapsed_macro!(2591);
+    collapsed_macro!(2592);
+    collapsed_macro!(2593);
+    collapsed_macro!(2594);
+    collapsed_macro!(2595);
+    collapsed_macro!(2596);
+    collapsed_macro!(2597);
+    collapsed_macro!(2598);
+    collapsed_macro!(2599);
+    collapsed_macro!(2600);
+    collapsed_macro!(2601);
+    collapsed_macro!(2602);
+    collapsed_macro!(2603);
+    collapsed_macro!(2604);
+    collapsed_macro!(2605);
+    collapsed_macro!(2606);
+    collapsed_macro!(2607);
+    collapsed_macro!(2608);
+    collapsed_macro!(2609);
+    collapsed_macro!(2610);
+    collapsed_macro!(2611);
+    collapsed_macro!(2612);
+    collapsed_macro!(2613);
+    collapsed_macro!(2614);
+    collapsed_macro!(2615);
+    collapsed_macro!(2616);
+    collapsed_macro!(2617);
+    collapsed_macro!(2618);
+    collapsed_macro!(2619);
+    collapsed_macro!(2620);
+    collapsed_macro!(2621);
+    collapsed_macro!(2622);
+    collapsed_macro!(2623);
+    collapsed_macro!(2624);
+    collapsed_macro!(2625);
+    collapsed_macro!(2626);
+    collapsed_macro!(2627);
+    collapsed_macro!(2628);
+    collapsed_macro!(2629);
+    collapsed_macro!(2630);
+    collapsed_macro!(2631);
+    collapsed_macro!(2632);
+    collapsed_macro!(2633);
+    collapsed_macro!(2634);
+    collapsed_macro!(2635);
+    collapsed_macro!(2636);
+    collapsed_macro!(2637);
+    collapsed_macro!(2638);
+    collapsed_macro!(2639);
+    collapsed_macro!(2640);
+    collapsed_macro!(2641);
+    collapsed_macro!(2642);
+    collapsed_macro!(2643);
+    collapsed_macro!(2644);
+    collapsed_macro!(2645);
+    collapsed_macro!(2646);
+    collapsed_macro!(2647);
+    collapsed_macro!(2648);
+    collapsed_macro!(2649);
+    collapsed_macro!(2650);
+    collapsed_macro!(2651);
+    collapsed_macro!(2652);
+    collapsed_macro!(2653);
+    collapsed_macro!(2654);
+    collapsed_macro!(2655);
+    collapsed_macro!(2656);
+    collapsed_macro!(2657);
+    collapsed_macro!(2658);
+    collapsed_macro!(2659);
+    collapsed_macro!(2660);
+    collapsed_macro!(2661);
+    collapsed_macro!(2662);
+    collapsed_macro!(2663);
+    collapsed_macro!(2664);
+    collapsed_macro!(2665);
+    collapsed_macro!(2666);
+    collapsed_macro!(2667);
+    collapsed_macro!(2668);
+    collapsed_macro!(2669);
+    collapsed_macro!(2670);
+    collapsed_macro!(2671);
+    collapsed_macro!(2672);
+    collapsed_macro!(2673);
+    collapsed_macro!(2674);
+    collapsed_macro!(2675);
+    collapsed_macro!(2676);
+    collapsed_macro!(2677);
+    collapsed_macro!(2678);
+    collapsed_macro!(2679);
+    collapsed_macro!(2680);
+    collapsed_macro!(2681);
+    collapsed_macro!(2682);
+    collapsed_macro!(2683);
+    collapsed_macro!(2684);
+    collapsed_macro!(2685);
+    collapsed_macro!(2686);
+    collapsed_macro!(2687);
+    collapsed_macro!(2688);
+    collapsed_macro!(2689);
+    collapsed_macro!(2690);
+    collapsed_macro!(2691);
+    collapsed_macro!(2692);
+    collapsed_macro!(2693);
+    collapsed_macro!(2694);
+    collapsed_macro!(2695);
+    collapsed_macro!(2696);
+    collapsed_macro!(2697);
+    collapsed_macro!(2698);
+    collapsed_macro!(2699);
+    collapsed_macro!(2700);
+    collapsed_macro!(2701);
+    collapsed_macro!(2702);
+    collapsed_macro!(2703);
+    collapsed_macro!(2704);
+    collapsed_macro!(2705);
+    collapsed_macro!(2706);
+    collapsed_macro!(2707);
+    collapsed_macro!(2708);
+    collapsed_macro!(2709);
+    collapsed_macro!(2710);
+    collapsed_macro!(2711);
+    collapsed_macro!(2712);
+    collapsed_macro!(2713);
+    collapsed_macro!(2714);
+    collapsed_macro!(2715);
+    collapsed_macro!(2716);
+    collapsed_macro!(2717);
+    collapsed_macro!(2718);
+    collapsed_macro!(2719);
+    collapsed_macro!(2720);
+    collapsed_macro!(2721);
+    collapsed_macro!(2722);
+    collapsed_macro!(2723);
+    collapsed_macro!(2724);
+    collapsed_macro!(2725);
+    collapsed_macro!(2726);
+    collapsed_macro!(2727);
+    collapsed_macro!(2728);
+    collapsed_macro!(2729);
+    collapsed_macro!(2730);
+    collapsed_macro!(2731);
+    collapsed_macro!(2732);
+    collapsed_macro!(2733);
+    collapsed_macro!(2734);
+    collapsed_macro!(2735);
+    collapsed_macro!(2736);
+    collapsed_macro!(2737);
+    collapsed_macro!(2738);
+    collapsed_macro!(2739);
+    collapsed_macro!(2740);
+    collapsed_macro!(2741);
+    collapsed_macro!(2742);
+    collapsed_macro!(2743);
+    collapsed_macro!(2744);
+    collapsed_macro!(2745);
+    collapsed_macro!(2746);
+    collapsed_macro!(2747);
+    collapsed_macro!(2748);
+    collapsed_macro!(2749);
+    collapsed_macro!(2750);
+    collapsed_macro!(2751);
+    collapsed_macro!(2752);
+    collapsed_macro!(2753);
+    collapsed_macro!(2754);
+    collapsed_macro!(2755);
+    collapsed_macro!(2756);
+    collapsed_macro!(2757);
+    collapsed_macro!(2758);
+    collapsed_macro!(2759);
+    collapsed_macro!(2760);
+    collapsed_macro!(2761);
+    collapsed_macro!(2762);
+    collapsed_macro!(2763);
+    collapsed_macro!(2764);
+    collapsed_macro!(2765);
+    collapsed_macro!(2766);
+    collapsed_macro!(2767);
+    collapsed_macro!(2768);
+    collapsed_macro!(2769);
+    collapsed_macro!(2770);
+    collapsed_macro!(2771);
+    collapsed_macro!(2772);
+    collapsed_macro!(2773);
+    collapsed_macro!(2774);
+    collapsed_macro!(2775);
+    collapsed_macro!(2776);
+    collapsed_macro!(2777);
+    collapsed_macro!(2778);
+    collapsed_macro!(2779);
+    collapsed_macro!(2780);
+    collapsed_macro!(2781);
+    collapsed_macro!(2782);
+    collapsed_macro!(2783);
+    collapsed_macro!(2784);
+    collapsed_macro!(2785);
+    collapsed_macro!(2786);
+    collapsed_macro!(2787);
+    collapsed_macro!(2788);
+    collapsed_macro!(2789);
+    collapsed_macro!(2790);
+    collapsed_macro!(2791);
+    collapsed_macro!(2792);
+    collapsed_macro!(2793);
+    collapsed_macro!(2794);
+    collapsed_macro!(2795);
+    collapsed_macro!(2796);
+    collapsed_macro!(2797);
+    collapsed_macro!(2798);
+    collapsed_macro!(2799);
+    collapsed_macro!(2800);
+    collapsed_macro!(2801);
+    collapsed_macro!(2802);
+    collapsed_macro!(2803);
+    collapsed_macro!(2804);
+    collapsed_macro!(2805);
+    collapsed_macro!(2806);
+    collapsed_macro!(2807);
+    collapsed_macro!(2808);
+    collapsed_macro!(2809);
+    collapsed_macro!(2810);
+    collapsed_macro!(2811);
+    collapsed_macro!(2812);
+    collapsed_macro!(2813);
+    collapsed_macro!(2814);
+    collapsed_macro!(2815);
+    collapsed_macro!(2816);
+    collapsed_macro!(2817);
+    collapsed_macro!(2818);
+    collapsed_macro!(2819);
+    collapsed_macro!(2820);
+    collapsed_macro!(2821);
+    collapsed_macro!(2822);
+    collapsed_macro!(2823);
+    collapsed_macro!(2824);
+    collapsed_macro!(2825);
+    collapsed_macro!(2826);
+    collapsed_macro!(2827);
+    collapsed_macro!(2828);
+    collapsed_macro!(2829);
+    collapsed_macro!(2830);
+    collapsed_macro!(2831);
+    collapsed_macro!(2832);
+    collapsed_macro!(2833);
+    collapsed_macro!(2834);
+    collapsed_macro!(2835);
+    collapsed_macro!(2836);
+    collapsed_macro!(2837);
+    collapsed_macro!(2838);
+    collapsed_macro!(2839);
+    collapsed_macro!(2840);
+    collapsed_macro!(2841);
+    collapsed_macro!(2842);
+    collapsed_macro!(2843);
+    collapsed_macro!(2844);
+    collapsed_macro!(2845);
+    collapsed_macro!(2846);
+    collapsed_macro!(2847);
+    collapsed_macro!(2848);
+    collapsed_macro!(2849);
+    collapsed_macro!(2850);
+    collapsed_macro!(2851);
+    collapsed_macro!(2852);
+    collapsed_macro!(2853);
+    collapsed_macro!(2854);
+    collapsed_macro!(2855);
+    collapsed_macro!(2856);
+    collapsed_macro!(2857);
+    collapsed_macro!(2858);
+    collapsed_macro!(2859);
+    collapsed_macro!(2860);
+    collapsed_macro!(2861);
+    collapsed_macro!(2862);
+    collapsed_macro!(2863);
+    collapsed_macro!(2864);
+    collapsed_macro!(2865);
+    collapsed_macro!(2866);
+    collapsed_macro!(2867);
+    collapsed_macro!(2868);
+    collapsed_macro!(2869);
+    collapsed_macro!(2870);
+    collapsed_macro!(2871);
+    collapsed_macro!(2872);
+    collapsed_macro!(2873);
+    collapsed_macro!(2874);
+    collapsed_macro!(2875);
+    collapsed_macro!(2876);
+    collapsed_macro!(2877);
+    collapsed_macro!(2878);
+    collapsed_macro!(2879);
+    collapsed_macro!(2880);
+    collapsed_macro!(2881);
+    collapsed_macro!(2882);
+    collapsed_macro!(2883);
+    collapsed_macro!(2884);
+    collapsed_macro!(2885);
+    collapsed_macro!(2886);
+    collapsed_macro!(2887);
+    collapsed_macro!(2888);
+    collapsed_macro!(2889);
+    collapsed_macro!(2890);
+    collapsed_macro!(2891);
+    collapsed_macro!(2892);
+    collapsed_macro!(2893);
+    collapsed_macro!(2894);
+    collapsed_macro!(2895);
+    collapsed_macro!(2896);
+    collapsed_macro!(2897);
+    collapsed_macro!(2898);
+    collapsed_macro!(2899);
+    collapsed_macro!(2900);
+    collapsed_macro!(2901);
+    collapsed_macro!(2902);
+    collapsed_macro!(2903);
+    collapsed_macro!(2904);
+    collapsed_macro!(2905);
+    collapsed_macro!(2906);
+    collapsed_macro!(2907);
+    collapsed_macro!(2908);
+    collapsed_macro!(2909);
+    collapsed_macro!(2910);
+    collapsed_macro!(2911);
+    collapsed_macro!(2912);
+    collapsed_macro!(2913);
+    collapsed_macro!(2914);
+    collapsed_macro!(2915);
+    collapsed_macro!(2916);
+    collapsed_macro!(2917);
+    collapsed_macro!(2918);
+    collapsed_macro!(2919);
+    collapsed_macro!(2920);
+    collapsed_macro!(2921);
+    collapsed_macro!(2922);
+    collapsed_macro!(2923);
+    collapsed_macro!(2924);
+    collapsed_macro!(2925);
+    collapsed_macro!(2926);
+    collapsed_macro!(2927);
+    collapsed_macro!(2928);
+    collapsed_macro!(2929);
+    collapsed_macro!(2930);
+    collapsed_macro!(2931);
+    collapsed_macro!(2932);
+    collapsed_macro!(2933);
+    collapsed_macro!(2934);
+    collapsed_macro!(2935);
+    collapsed_macro!(2936);
+    collapsed_macro!(2937);
+    collapsed_macro!(2938);
+    collapsed_macro!(2939);
+    collapsed_macro!(2940);
+    collapsed_macro!(2941);
+    collapsed_macro!(2942);
+    collapsed_macro!(2943);
+    collapsed_macro!(2944);
+    collapsed_macro!(2945);
+    collapsed_macro!(2946);
+    collapsed_macro!(2947);
+    collapsed_macro!(2948);
+    collapsed_macro!(2949);
+    collapsed_macro!(2950);
+    collapsed_macro!(2951);
+    collapsed_macro!(2952);
+    collapsed_macro!(2953);
+    collapsed_macro!(2954);
+    collapsed_macro!(2955);
+    collapsed_macro!(2956);
+    collapsed_macro!(2957);
+    collapsed_macro!(2958);
+    collapsed_macro!(2959);
+    collapsed_macro!(2960);
+    collapsed_macro!(2961);
+    collapsed_macro!(2962);
+    collapsed_macro!(2963);
+    collapsed_macro!(2964);
+    collapsed_macro!(2965);
+    collapsed_macro!(2966);
+    collapsed_macro!(2967);
+    collapsed_macro!(2968);
+    collapsed_macro!(2969);
+    collapsed_macro!(2970);
+    collapsed_macro!(2971);
+    collapsed_macro!(2972);
+    collapsed_macro!(2973);
+    collapsed_macro!(2974);
+    collapsed_macro!(2975);
+    collapsed_macro!(2976);
+    collapsed_macro!(2977);
+    collapsed_macro!(2978);
+    collapsed_macro!(2979);
+    collapsed_macro!(2980);
+    collapsed_macro!(2981);
+    collapsed_macro!(2982);
+    collapsed_macro!(2983);
+    collapsed_macro!(2984);
+    collapsed_macro!(2985);
+    collapsed_macro!(2986);
+    collapsed_macro!(2987);
+    collapsed_macro!(2988);
+    collapsed_macro!(2989);
+    collapsed_macro!(2990);
+    collapsed_macro!(2991);
+    collapsed_macro!(2992);
+    collapsed_macro!(2993);
+    collapsed_macro!(2994);
+    collapsed_macro!(2995);
+    collapsed_macro!(2996);
+    collapsed_macro!(2997);
+    collapsed_macro!(2998);
+    collapsed_macro!(2999);
+    collapsed_macro!(3000);
+    collapsed_macro!(3001);
+    collapsed_macro!(3002);
+    collapsed_macro!(3003);
+    collapsed_macro!(3004);
+    collapsed_macro!(3005);
+    collapsed_macro!(3006);
+    collapsed_macro!(3007);
+    collapsed_macro!(3008);
+    collapsed_macro!(3009);
+    collapsed_macro!(3010);
+    collapsed_macro!(3011);
+    collapsed_macro!(3012);
+    collapsed_macro!(3013);
+    collapsed_macro!(3014);
+    collapsed_macro!(3015);
+    collapsed_macro!(3016);
+    collapsed_macro!(3017);
+    collapsed_macro!(3018);
+    collapsed_macro!(3019);
+    collapsed_macro!(3020);
+    collapsed_macro!(3021);
+    collapsed_macro!(3022);
+    collapsed_macro!(3023);
+    collapsed_macro!(3024);
+    collapsed_macro!(3025);
+    collapsed_macro!(3026);
+    collapsed_macro!(3027);
+    collapsed_macro!(3028);
+    collapsed_macro!(3029);
+    collapsed_macro!(3030);
+    collapsed_macro!(3031);
+    collapsed_macro!(3032);
+    collapsed_macro!(3033);
+    collapsed_macro!(3034);
+    collapsed_macro!(3035);
+    collapsed_macro!(3036);
+    collapsed_macro!(3037);
+    collapsed_macro!(3038);
+    collapsed_macro!(3039);
+    collapsed_macro!(3040);
+    collapsed_macro!(3041);
+    collapsed_macro!(3042);
+    collapsed_macro!(3043);
+    collapsed_macro!(3044);
+    collapsed_macro!(3045);
+    collapsed_macro!(3046);
+    collapsed_macro!(3047);
+    collapsed_macro!(3048);
+    collapsed_macro!(3049);
+    collapsed_macro!(3050);
+    collapsed_macro!(3051);
+    collapsed_macro!(3052);
+    collapsed_macro!(3053);
+    collapsed_macro!(3054);
+    collapsed_macro!(3055);
+    collapsed_macro!(3056);
+    collapsed_macro!(3057);
+    collapsed_macro!(3058);
+    collapsed_macro!(3059);
+    collapsed_macro!(3060);
+    collapsed_macro!(3061);
+    collapsed_macro!(3062);
+    collapsed_macro!(3063);
+    collapsed_macro!(3064);
+    collapsed_macro!(3065);
+    collapsed_macro!(3066);
+    collapsed_macro!(3067);
+    collapsed_macro!(3068);
+    collapsed_macro!(3069);
+    collapsed_macro!(3070);
+    collapsed_macro!(3071);
+    collapsed_macro!(3072);
+    collapsed_macro!(3073);
+    collapsed_macro!(3074);
+    collapsed_macro!(3075);
+    collapsed_macro!(3076);
+    collapsed_macro!(3077);
+    collapsed_macro!(3078);
+    collapsed_macro!(3079);
+    collapsed_macro!(3080);
+    collapsed_macro!(3081);
+    collapsed_macro!(3082);
+    collapsed_macro!(3083);
+    collapsed_macro!(3084);
+    collapsed_macro!(3085);
+    collapsed_macro!(3086);
+    collapsed_macro!(3087);
+    collapsed_macro!(3088);
+    collapsed_macro!(3089);
+    collapsed_macro!(3090);
+    collapsed_macro!(3091);
+    collapsed_macro!(3092);
+    collapsed_macro!(3093);
+    collapsed_macro!(3094);
+    collapsed_macro!(3095);
+    collapsed_macro!(3096);
+    collapsed_macro!(3097);
+    collapsed_macro!(3098);
+    collapsed_macro!(3099);
+    collapsed_macro!(3100);
+    collapsed_macro!(3101);
+    collapsed_macro!(3102);
+    collapsed_macro!(3103);
+    collapsed_macro!(3104);
+    collapsed_macro!(3105);
+    collapsed_macro!(3106);
+    collapsed_macro!(3107);
+    collapsed_macro!(3108);
+    collapsed_macro!(3109);
+    collapsed_macro!(3110);
+    collapsed_macro!(3111);
+    collapsed_macro!(3112);
+    collapsed_macro!(3113);
+    collapsed_macro!(3114);
+    collapsed_macro!(3115);
+    collapsed_macro!(3116);
+    collapsed_macro!(3117);
+    collapsed_macro!(3118);
+    collapsed_macro!(3119);
+    collapsed_macro!(3120);
+    collapsed_macro!(3121);
+    collapsed_macro!(3122);
+    collapsed_macro!(3123);
+    collapsed_macro!(3124);
+    collapsed_macro!(3125);
+    collapsed_macro!(3126);
+    collapsed_macro!(3127);
+    collapsed_macro!(3128);
+    collapsed_macro!(3129);
+    collapsed_macro!(3130);
+    collapsed_macro!(3131);
+    collapsed_macro!(3132);
+    collapsed_macro!(3133);
+    collapsed_macro!(3134);
+    collapsed_macro!(3135);
+    collapsed_macro!(3136);
+    collapsed_macro!(3137);
+    collapsed_macro!(3138);
+    collapsed_macro!(3139);
+    collapsed_macro!(3140);
+    collapsed_macro!(3141);
+    collapsed_macro!(3142);
+    collapsed_macro!(3143);
+    collapsed_macro!(3144);
+    collapsed_macro!(3145);
+    collapsed_macro!(3146);
+    collapsed_macro!(3147);
+    collapsed_macro!(3148);
+    collapsed_macro!(3149);
+    collapsed_macro!(3150);
+    collapsed_macro!(3151);
+    collapsed_macro!(3152);
+    collapsed_macro!(3153);
+    collapsed_macro!(3154);
+    collapsed_macro!(3155);
+    collapsed_macro!(3156);
+    collapsed_macro!(3157);
+    collapsed_macro!(3158);
+    collapsed_macro!(3159);
+    collapsed_macro!(3160);
+    collapsed_macro!(3161);
+    collapsed_macro!(3162);
+    collapsed_macro!(3163);
+    collapsed_macro!(3164);
+    collapsed_macro!(3165);
+    collapsed_macro!(3166);
+    collapsed_macro!(3167);
+    collapsed_macro!(3168);
+    collapsed_macro!(3169);
+    collapsed_macro!(3170);
+    collapsed_macro!(3171);
+    collapsed_macro!(3172);
+    collapsed_macro!(3173);
+    collapsed_macro!(3174);
+    collapsed_macro!(3175);
+    collapsed_macro!(3176);
+    collapsed_macro!(3177);
+    collapsed_macro!(3178);
+    collapsed_macro!(3179);
+    collapsed_macro!(3180);
+    collapsed_macro!(3181);
+    collapsed_macro!(3182);
+    collapsed_macro!(3183);
+    collapsed_macro!(3184);
+    collapsed_macro!(3185);
+    collapsed_macro!(3186);
+    collapsed_macro!(3187);
+    collapsed_macro!(3188);
+    collapsed_macro!(3189);
+    collapsed_macro!(3190);
+    collapsed_macro!(3191);
+    collapsed_macro!(3192);
+    collapsed_macro!(3193);
+    collapsed_macro!(3194);
+    collapsed_macro!(3195);
+    collapsed_macro!(3196);
+    collapsed_macro!(3197);
+    collapsed_macro!(3198);
+    collapsed_macro!(3199);
+    collapsed_macro!(3200);
+    collapsed_macro!(3201);
+    collapsed_macro!(3202);
+    collapsed_macro!(3203);
+    collapsed_macro!(3204);
+    collapsed_macro!(3205);
+    collapsed_macro!(3206);
+    collapsed_macro!(3207);
+    collapsed_macro!(3208);
+    collapsed_macro!(3209);
+    collapsed_macro!(3210);
+    collapsed_macro!(3211);
+    collapsed_macro!(3212);
+    collapsed_macro!(3213);
+    collapsed_macro!(3214);
+    collapsed_macro!(3215);
+    collapsed_macro!(3216);
+    collapsed_macro!(3217);
+    collapsed_macro!(3218);
+    collapsed_macro!(3219);
+    collapsed_macro!(3220);
+    collapsed_macro!(3221);
+    collapsed_macro!(3222);
+    collapsed_macro!(3223);
+    collapsed_macro!(3224);
+    collapsed_macro!(3225);
+    collapsed_macro!(3226);
+    collapsed_macro!(3227);
+    collapsed_macro!(3228);
+    collapsed_macro!(3229);
+    collapsed_macro!(3230);
+    collapsed_macro!(3231);
+    collapsed_macro!(3232);
+    collapsed_macro!(3233);
+    collapsed_macro!(3234);
+    collapsed_macro!(3235);
+    collapsed_macro!(3236);
+    collapsed_macro!(3237);
+    collapsed_macro!(3238);
+    collapsed_macro!(3239);
+    collapsed_macro!(3240);
+    collapsed_macro!(3241);
+    collapsed_macro!(3242);
+    collapsed_macro!(3243);
+    collapsed_macro!(3244);
+    collapsed_macro!(3245);
+    collapsed_macro!(3246);
+    collapsed_macro!(3247);
+    collapsed_macro!(3248);
+    collapsed_macro!(3249);
+    collapsed_macro!(3250);
+    collapsed_macro!(3251);
+    collapsed_macro!(3252);
+    collapsed_macro!(3253);
+    collapsed_macro!(3254);
+    collapsed_macro!(3255);
+    collapsed_macro!(3256);
+    collapsed_macro!(3257);
+    collapsed_macro!(3258);
+    collapsed_macro!(3259);
+    collapsed_macro!(3260);
+    collapsed_macro!(3261);
+    collapsed_macro!(3262);
+    collapsed_macro!(3263);
+    collapsed_macro!(3264);
+    collapsed_macro!(3265);
+    collapsed_macro!(3266);
+    collapsed_macro!(3267);
+    collapsed_macro!(3268);
+    collapsed_macro!(3269);
+    collapsed_macro!(3270);
+    collapsed_macro!(3271);
+    collapsed_macro!(3272);
+    collapsed_macro!(3273);
+    collapsed_macro!(3274);
+    collapsed_macro!(3275);
+    collapsed_macro!(3276);
+    collapsed_macro!(3277);
+    collapsed_macro!(3278);
+    collapsed_macro!(3279);
+    collapsed_macro!(3280);
+    collapsed_macro!(3281);
+    collapsed_macro!(3282);
+    collapsed_macro!(3283);
+    collapsed_macro!(3284);
+    collapsed_macro!(3285);
+    collapsed_macro!(3286);
+    collapsed_macro!(3287);
+    collapsed_macro!(3288);
+    collapsed_macro!(3289);
+    collapsed_macro!(3290);
+    collapsed_macro!(3291);
+    collapsed_macro!(3292);
+    collapsed_macro!(3293);
+    collapsed_macro!(3294);
+    collapsed_macro!(3295);
+    collapsed_macro!(3296);
+    collapsed_macro!(3297);
+    collapsed_macro!(3298);
+    collapsed_macro!(3299);
+    collapsed_macro!(3300);
+    collapsed_macro!(3301);
+    collapsed_macro!(3302);
+    collapsed_macro!(3303);
+    collapsed_macro!(3304);
+    collapsed_macro!(3305);
+    collapsed_macro!(3306);
+    collapsed_macro!(3307);
+    collapsed_macro!(3308);
+    collapsed_macro!(3309);
+    collapsed_macro!(3310);
+    collapsed_macro!(3311);
+    collapsed_macro!(3312);
+    collapsed_macro!(3313);
+    collapsed_macro!(3314);
+    collapsed_macro!(3315);
+    collapsed_macro!(3316);
+    collapsed_macro!(3317);
+    collapsed_macro!(3318);
+    collapsed_macro!(3319);
+    collapsed_macro!(3320);
+    collapsed_macro!(3321);
+    collapsed_macro!(3322);
+    collapsed_macro!(3323);
+    collapsed_macro!(3324);
+    collapsed_macro!(3325);
+    collapsed_macro!(3326);
+    collapsed_macro!(3327);
+    collapsed_macro!(3328);
+    collapsed_macro!(3329);
+    collapsed_macro!(3330);
+    collapsed_macro!(3331);
+    collapsed_macro!(3332);
+    collapsed_macro!(3333);
+    collapsed_macro!(3334);
+    collapsed_macro!(3335);
+    collapsed_macro!(3336);
+    collapsed_macro!(3337);
+    collapsed_macro!(3338);
+    collapsed_macro!(3339);
+    collapsed_macro!(3340);
+    collapsed_macro!(3341);
+    collapsed_macro!(3342);
+    collapsed_macro!(3343);
+    collapsed_macro!(3344);
+    collapsed_macro!(3345);
+    collapsed_macro!(3346);
+    collapsed_macro!(3347);
+    collapsed_macro!(3348);
+    collapsed_macro!(3349);
+    collapsed_macro!(3350);
+    collapsed_macro!(3351);
+    collapsed_macro!(3352);
+    collapsed_macro!(3353);
+    collapsed_macro!(3354);
+    collapsed_macro!(3355);
+    collapsed_macro!(3356);
+    collapsed_macro!(3357);
+    collapsed_macro!(3358);
+    collapsed_macro!(3359);
+    collapsed_macro!(3360);
+    collapsed_macro!(3361);
+    collapsed_macro!(3362);
+    collapsed_macro!(3363);
+    collapsed_macro!(3364);
+    collapsed_macro!(3365);
+    collapsed_macro!(3366);
+    collapsed_macro!(3367);
+    collapsed_macro!(3368);
+    collapsed_macro!(3369);
+    collapsed_macro!(3370);
+    collapsed_macro!(3371);
+    collapsed_macro!(3372);
+    collapsed_macro!(3373);
+    collapsed_macro!(3374);
+    collapsed_macro!(3375);
+    collapsed_macro!(3376);
+    collapsed_macro!(3377);
+    collapsed_macro!(3378);
+    collapsed_macro!(3379);
+    collapsed_macro!(3380);
+    collapsed_macro!(3381);
+    collapsed_macro!(3382);
+    collapsed_macro!(3383);
+    collapsed_macro!(3384);
+    collapsed_macro!(3385);
+    collapsed_macro!(3386);
+    collapsed_macro!(3387);
+    collapsed_macro!(3388);
+    collapsed_macro!(3389);
+    collapsed_macro!(3390);
+    collapsed_macro!(3391);
+    collapsed_macro!(3392);
+    collapsed_macro!(3393);
+    collapsed_macro!(3394);
+    collapsed_macro!(3395);
+    collapsed_macro!(3396);
+    collapsed_macro!(3397);
+    collapsed_macro!(3398);
+    collapsed_macro!(3399);
+    collapsed_macro!(3400);
+    collapsed_macro!(3401);
+    collapsed_macro!(3402);
+    collapsed_macro!(3403);
+    collapsed_macro!(3404);
+    collapsed_macro!(3405);
+    collapsed_macro!(3406);
+    collapsed_macro!(3407);
+    collapsed_macro!(3408);
+    collapsed_macro!(3409);
+    collapsed_macro!(3410);
+    collapsed_macro!(3411);
+    collapsed_macro!(3412);
+    collapsed_macro!(3413);
+    collapsed_macro!(3414);
+    collapsed_macro!(3415);
+    collapsed_macro!(3416);
+    collapsed_macro!(3417);
+    collapsed_macro!(3418);
+    collapsed_macro!(3419);
+    collapsed_macro!(3420);
+    collapsed_macro!(3421);
+    collapsed_macro!(3422);
+    collapsed_macro!(3423);
+    collapsed_macro!(3424);
+    collapsed_macro!(3425);
+    collapsed_macro!(3426);
+    collapsed_macro!(3427);
+    collapsed_macro!(3428);
+    collapsed_macro!(3429);
+    collapsed_macro!(3430);
+    collapsed_macro!(3431);
+    collapsed_macro!(3432);
+    collapsed_macro!(3433);
+    collapsed_macro!(3434);
+    collapsed_macro!(3435);
+    collapsed_macro!(3436);
+    collapsed_macro!(3437);
+    collapsed_macro!(3438);
+    collapsed_macro!(3439);
+    collapsed_macro!(3440);
+    collapsed_macro!(3441);
+    collapsed_macro!(3442);
+    collapsed_macro!(3443);
+    collapsed_macro!(3444);
+    collapsed_macro!(3445);
+    collapsed_macro!(3446);
+    collapsed_macro!(3447);
+    collapsed_macro!(3448);
+    collapsed_macro!(3449);
+    collapsed_macro!(3450);
+    collapsed_macro!(3451);
+    collapsed_macro!(3452);
+    collapsed_macro!(3453);
+    collapsed_macro!(3454);
+    collapsed_macro!(3455);
+    collapsed_macro!(3456);
+    collapsed_macro!(3457);
+    collapsed_macro!(3458);
+    collapsed_macro!(3459);
+    collapsed_macro!(3460);
+    collapsed_macro!(3461);
+    collapsed_macro!(3462);
+    collapsed_macro!(3463);
+    collapsed_macro!(3464);
+    collapsed_macro!(3465);
+    collapsed_macro!(3466);
+    collapsed_macro!(3467);
+    collapsed_macro!(3468);
+    collapsed_macro!(3469);
+    collapsed_macro!(3470);
+    collapsed_macro!(3471);
+    collapsed_macro!(3472);
+    collapsed_macro!(3473);
+    collapsed_macro!(3474);
+    collapsed_macro!(3475);
+    collapsed_macro!(3476);
+    collapsed_macro!(3477);
+    collapsed_macro!(3478);
+    collapsed_macro!(3479);
+    collapsed_macro!(3480);
+    collapsed_macro!(3481);
+    collapsed_macro!(3482);
+    collapsed_macro!(3483);
+    collapsed_macro!(3484);
+    collapsed_macro!(3485);
+    collapsed_macro!(3486);
+    collapsed_macro!(3487);
+    collapsed_macro!(3488);
+    collapsed_macro!(3489);
+    collapsed_macro!(3490);
+    collapsed_macro!(3491);
+    collapsed_macro!(3492);
+    collapsed_macro!(3493);
+    collapsed_macro!(3494);
+    collapsed_macro!(3495);
+    collapsed_macro!(3496);
+    collapsed_macro!(3497);
+    collapsed_macro!(3498);
+    collapsed_macro!(3499);
+    collapsed_macro!(3500);
+    collapsed_macro!(3501);
+    collapsed_macro!(3502);
+    collapsed_macro!(3503);
+    collapsed_macro!(3504);
+    collapsed_macro!(3505);
+    collapsed_macro!(3506);
+    collapsed_macro!(3507);
+    collapsed_macro!(3508);
+    collapsed_macro!(3509);
+    collapsed_macro!(3510);
+    collapsed_macro!(3511);
+    collapsed_macro!(3512);
+    collapsed_macro!(3513);
+    collapsed_macro!(3514);
+    collapsed_macro!(3515);
+    collapsed_macro!(3516);
+    collapsed_macro!(3517);
+    collapsed_macro!(3518);
+    collapsed_macro!(3519);
+    collapsed_macro!(3520);
+    collapsed_macro!(3521);
+    collapsed_macro!(3522);
+    collapsed_macro!(3523);
+    collapsed_macro!(3524);
+    collapsed_macro!(3525);
+    collapsed_macro!(3526);
+    collapsed_macro!(3527);
+    collapsed_macro!(3528);
+    collapsed_macro!(3529);
+    collapsed_macro!(3530);
+    collapsed_macro!(3531);
+    collapsed_macro!(3532);
+    collapsed_macro!(3533);
+    collapsed_macro!(3534);
+    collapsed_macro!(3535);
+    collapsed_macro!(3536);
+    collapsed_macro!(3537);
+    collapsed_macro!(3538);
+    collapsed_macro!(3539);
+    collapsed_macro!(3540);
+    collapsed_macro!(3541);
+    collapsed_macro!(3542);
+    collapsed_macro!(3543);
+    collapsed_macro!(3544);
+    collapsed_macro!(3545);
+    collapsed_macro!(3546);
+    collapsed_macro!(3547);
+    collapsed_macro!(3548);
+    collapsed_macro!(3549);
+    collapsed_macro!(3550);
+    collapsed_macro!(3551);
+    collapsed_macro!(3552);
+    collapsed_macro!(3553);
+    collapsed_macro!(3554);
+    collapsed_macro!(3555);
+    collapsed_macro!(3556);
+    collapsed_macro!(3557);
+    collapsed_macro!(3558);
+    collapsed_macro!(3559);
+    collapsed_macro!(3560);
+    collapsed_macro!(3561);
+    collapsed_macro!(3562);
+    collapsed_macro!(3563);
+    collapsed_macro!(3564);
+    collapsed_macro!(3565);
+    collapsed_macro!(3566);
+    collapsed_macro!(3567);
+    collapsed_macro!(3568);
+    collapsed_macro!(3569);
+    collapsed_macro!(3570);
+    collapsed_macro!(3571);
+    collapsed_macro!(3572);
+    collapsed_macro!(3573);
+    collapsed_macro!(3574);
+    collapsed_macro!(3575);
+    collapsed_macro!(3576);
+    collapsed_macro!(3577);
+    collapsed_macro!(3578);
+    collapsed_macro!(3579);
+    collapsed_macro!(3580);
+    collapsed_macro!(3581);
+    collapsed_macro!(3582);
+    collapsed_macro!(3583);
+    collapsed_macro!(3584);
+    collapsed_macro!(3585);
+    collapsed_macro!(3586);
+    collapsed_macro!(3587);
+    collapsed_macro!(3588);
+    collapsed_macro!(3589);
+    collapsed_macro!(3590);
+    collapsed_macro!(3591);
+    collapsed_macro!(3592);
+    collapsed_macro!(3593);
+    collapsed_macro!(3594);
+    collapsed_macro!(3595);
+    collapsed_macro!(3596);
+    collapsed_macro!(3597);
+    collapsed_macro!(3598);
+    collapsed_macro!(3599);
+    collapsed_macro!(3600);
+    collapsed_macro!(3601);
+    collapsed_macro!(3602);
+    collapsed_macro!(3603);
+    collapsed_macro!(3604);
+    collapsed_macro!(3605);
+    collapsed_macro!(3606);
+    collapsed_macro!(3607);
+    collapsed_macro!(3608);
+    collapsed_macro!(3609);
+    collapsed_macro!(3610);
+    collapsed_macro!(3611);
+    collapsed_macro!(3612);
+    collapsed_macro!(3613);
+    collapsed_macro!(3614);
+    collapsed_macro!(3615);
+    collapsed_macro!(3616);
+    collapsed_macro!(3617);
+    collapsed_macro!(3618);
+    collapsed_macro!(3619);
+    collapsed_macro!(3620);
+    collapsed_macro!(3621);
+    collapsed_macro!(3622);
+    collapsed_macro!(3623);
+    collapsed_macro!(3624);
+    collapsed_macro!(3625);
+    collapsed_macro!(3626);
+    collapsed_macro!(3627);
+    collapsed_macro!(3628);
+    collapsed_macro!(3629);
+    collapsed_macro!(3630);
+    collapsed_macro!(3631);
+    collapsed_macro!(3632);
+    collapsed_macro!(3633);
+    collapsed_macro!(3634);
+    collapsed_macro!(3635);
+    collapsed_macro!(3636);
+    collapsed_macro!(3637);
+    collapsed_macro!(3638);
+    collapsed_macro!(3639);
+    collapsed_macro!(3640);
+    collapsed_macro!(3641);
+    collapsed_macro!(3642);
+    collapsed_macro!(3643);
+    collapsed_macro!(3644);
+    collapsed_macro!(3645);
+    collapsed_macro!(3646);
+    collapsed_macro!(3647);
+    collapsed_macro!(3648);
+    collapsed_macro!(3649);
+    collapsed_macro!(3650);
+    collapsed_macro!(3651);
+    collapsed_macro!(3652);
+    collapsed_macro!(3653);
+    collapsed_macro!(3654);
+    collapsed_macro!(3655);
+    collapsed_macro!(3656);
+    collapsed_macro!(3657);
+    collapsed_macro!(3658);
+    collapsed_macro!(3659);
+    collapsed_macro!(3660);
+    collapsed_macro!(3661);
+    collapsed_macro!(3662);
+    collapsed_macro!(3663);
+    collapsed_macro!(3664);
+    collapsed_macro!(3665);
+    collapsed_macro!(3666);
+    collapsed_macro!(3667);
+    collapsed_macro!(3668);
+    collapsed_macro!(3669);
+    collapsed_macro!(3670);
+    collapsed_macro!(3671);
+    collapsed_macro!(3672);
+    collapsed_macro!(3673);
+    collapsed_macro!(3674);
+    collapsed_macro!(3675);
+    collapsed_macro!(3676);
+    collapsed_macro!(3677);
+    collapsed_macro!(3678);
+    collapsed_macro!(3679);
+    collapsed_macro!(3680);
+    collapsed_macro!(3681);
+    collapsed_macro!(3682);
+    collapsed_macro!(3683);
+    collapsed_macro!(3684);
+    collapsed_macro!(3685);
+    collapsed_macro!(3686);
+    collapsed_macro!(3687);
+    collapsed_macro!(3688);
+    collapsed_macro!(3689);
+    collapsed_macro!(3690);
+    collapsed_macro!(3691);
+    collapsed_macro!(3692);
+    collapsed_macro!(3693);
+    collapsed_macro!(3694);
+    collapsed_macro!(3695);
+    collapsed_macro!(3696);
+    collapsed_macro!(3697);
+    collapsed_macro!(3698);
+    collapsed_macro!(3699);
+    collapsed_macro!(3700);
+    collapsed_macro!(3701);
+    collapsed_macro!(3702);
+    collapsed_macro!(3703);
+    collapsed_macro!(3704);
+    collapsed_macro!(3705);
+    collapsed_macro!(3706);
+    collapsed_macro!(3707);
+    collapsed_macro!(3708);
+    collapsed_macro!(3709);
+    collapsed_macro!(3710);
+    collapsed_macro!(3711);
+    collapsed_macro!(3712);
+    collapsed_macro!(3713);
+    collapsed_macro!(3714);
+    collapsed_macro!(3715);
+    collapsed_macro!(3716);
+    collapsed_macro!(3717);
+    collapsed_macro!(3718);
+    collapsed_macro!(3719);
+    collapsed_macro!(3720);
+    collapsed_macro!(3721);
+    collapsed_macro!(3722);
+    collapsed_macro!(3723);
+    collapsed_macro!(3724);
+    collapsed_macro!(3725);
+    collapsed_macro!(3726);
+    collapsed_macro!(3727);
+    collapsed_macro!(3728);
+    collapsed_macro!(3729);
+    collapsed_macro!(3730);
+    collapsed_macro!(3731);
+    collapsed_macro!(3732);
+    collapsed_macro!(3733);
+    collapsed_macro!(3734);
+    collapsed_macro!(3735);
+    collapsed_macro!(3736);
+    collapsed_macro!(3737);
+    collapsed_macro!(3738);
+    collapsed_macro!(3739);
+    collapsed_macro!(3740);
+    collapsed_macro!(3741);
+    collapsed_macro!(3742);
+    collapsed_macro!(3743);
+    collapsed_macro!(3744);
+    collapsed_macro!(3745);
+    collapsed_macro!(3746);
+    collapsed_macro!(3747);
+    collapsed_macro!(3748);
+    collapsed_macro!(3749);
+    collapsed_macro!(3750);
+    collapsed_macro!(3751);
+    collapsed_macro!(3752);
+    collapsed_macro!(3753);
+    collapsed_macro!(3754);
+    collapsed_macro!(3755);
+    collapsed_macro!(3756);
+    collapsed_macro!(3757);
+    collapsed_macro!(3758);
+    collapsed_macro!(3759);
+    collapsed_macro!(3760);
+    collapsed_macro!(3761);
+    collapsed_macro!(3762);
+    collapsed_macro!(3763);
+    collapsed_macro!(3764);
+    collapsed_macro!(3765);
+    collapsed_macro!(3766);
+    collapsed_macro!(3767);
+    collapsed_macro!(3768);
+    collapsed_macro!(3769);
+    collapsed_macro!(3770);
+    collapsed_macro!(3771);
+    collapsed_macro!(3772);
+    collapsed_macro!(3773);
+    collapsed_macro!(3774);
+    collapsed_macro!(3775);
+    collapsed_macro!(3776);
+    collapsed_macro!(3777);
+    collapsed_macro!(3778);
+    collapsed_macro!(3779);
+    collapsed_macro!(3780);
+    collapsed_macro!(3781);
+    collapsed_macro!(3782);
+    collapsed_macro!(3783);
+    collapsed_macro!(3784);
+    collapsed_macro!(3785);
+    collapsed_macro!(3786);
+    collapsed_macro!(3787);
+    collapsed_macro!(3788);
+    collapsed_macro!(3789);
+    collapsed_macro!(3790);
+    collapsed_macro!(3791);
+    collapsed_macro!(3792);
+    collapsed_macro!(3793);
+    collapsed_macro!(3794);
+    collapsed_macro!(3795);
+    collapsed_macro!(3796);
+    collapsed_macro!(3797);
+    collapsed_macro!(3798);
+    collapsed_macro!(3799);
+    collapsed_macro!(3800);
+    collapsed_macro!(3801);
+    collapsed_macro!(3802);
+    collapsed_macro!(3803);
+    collapsed_macro!(3804);
+    collapsed_macro!(3805);
+    collapsed_macro!(3806);
+    collapsed_macro!(3807);
+    collapsed_macro!(3808);
+    collapsed_macro!(3809);
+    collapsed_macro!(3810);
+    collapsed_macro!(3811);
+    collapsed_macro!(3812);
+    collapsed_macro!(3813);
+    collapsed_macro!(3814);
+    collapsed_macro!(3815);
+    collapsed_macro!(3816);
+    collapsed_macro!(3817);
+    collapsed_macro!(3818);
+    collapsed_macro!(3819);
+    collapsed_macro!(3820);
+    collapsed_macro!(3821);
+    collapsed_macro!(3822);
+    collapsed_macro!(3823);
+    collapsed_macro!(3824);
+    collapsed_macro!(3825);
+    collapsed_macro!(3826);
+    collapsed_macro!(3827);
+    collapsed_macro!(3828);
+    collapsed_macro!(3829);
+    collapsed_macro!(3830);
+    collapsed_macro!(3831);
+    collapsed_macro!(3832);
+    collapsed_macro!(3833);
+    collapsed_macro!(3834);
+    collapsed_macro!(3835);
+    collapsed_macro!(3836);
+    collapsed_macro!(3837);
+    collapsed_macro!(3838);
+    collapsed_macro!(3839);
+    collapsed_macro!(3840);
+    collapsed_macro!(3841);
+    collapsed_macro!(3842);
+    collapsed_macro!(3843);
+    collapsed_macro!(3844);
+    collapsed_macro!(3845);
+    collapsed_macro!(3846);
+    collapsed_macro!(3847);
+    collapsed_macro!(3848);
+    collapsed_macro!(3849);
+    collapsed_macro!(3850);
+    collapsed_macro!(3851);
+    collapsed_macro!(3852);
+    collapsed_macro!(3853);
+    collapsed_macro!(3854);
+    collapsed_macro!(3855);
+    collapsed_macro!(3856);
+    collapsed_macro!(3857);
+    collapsed_macro!(3858);
+    collapsed_macro!(3859);
+    collapsed_macro!(3860);
+    collapsed_macro!(3861);
+    collapsed_macro!(3862);
+    collapsed_macro!(3863);
+    collapsed_macro!(3864);
+    collapsed_macro!(3865);
+    collapsed_macro!(3866);
+    collapsed_macro!(3867);
+    collapsed_macro!(3868);
+    collapsed_macro!(3869);
+    collapsed_macro!(3870);
+    collapsed_macro!(3871);
+    collapsed_macro!(3872);
+    collapsed_macro!(3873);
+    collapsed_macro!(3874);
+    collapsed_macro!(3875);
+    collapsed_macro!(3876);
+    collapsed_macro!(3877);
+    collapsed_macro!(3878);
+    collapsed_macro!(3879);
+    collapsed_macro!(3880);
+    collapsed_macro!(3881);
+    collapsed_macro!(3882);
+    collapsed_macro!(3883);
+    collapsed_macro!(3884);
+    collapsed_macro!(3885);
+    collapsed_macro!(3886);
+    collapsed_macro!(3887);
+    collapsed_macro!(3888);
+    collapsed_macro!(3889);
+    collapsed_macro!(3890);
+    collapsed_macro!(3891);
+    collapsed_macro!(3892);
+    collapsed_macro!(3893);
+    collapsed_macro!(3894);
+    collapsed_macro!(3895);
+    collapsed_macro!(3896);
+    collapsed_macro!(3897);
+    collapsed_macro!(3898);
+    collapsed_macro!(3899);
+    collapsed_macro!(3900);
+    collapsed_macro!(3901);
+    collapsed_macro!(3902);
+    collapsed_macro!(3903);
+    collapsed_macro!(3904);
+    collapsed_macro!(3905);
+    collapsed_macro!(3906);
+    collapsed_macro!(3907);
+    collapsed_macro!(3908);
+    collapsed_macro!(3909);
+    collapsed_macro!(3910);
+    collapsed_macro!(3911);
+    collapsed_macro!(3912);
+    collapsed_macro!(3913);
+    collapsed_macro!(3914);
+    collapsed_macro!(3915);
+    collapsed_macro!(3916);
+    collapsed_macro!(3917);
+    collapsed_macro!(3918);
+    collapsed_macro!(3919);
+    collapsed_macro!(3920);
+    collapsed_macro!(3921);
+    collapsed_macro!(3922);
+    collapsed_macro!(3923);
+    collapsed_macro!(3924);
+    collapsed_macro!(3925);
+    collapsed_macro!(3926);
+    collapsed_macro!(3927);
+    collapsed_macro!(3928);
+    collapsed_macro!(3929);
+    collapsed_macro!(3930);
+    collapsed_macro!(3931);
+    collapsed_macro!(3932);
+    collapsed_macro!(3933);
+    collapsed_macro!(3934);
+    collapsed_macro!(3935);
+    collapsed_macro!(3936);
+    collapsed_macro!(3937);
+    collapsed_macro!(3938);
+    collapsed_macro!(3939);
+    collapsed_macro!(3940);
+    collapsed_macro!(3941);
+    collapsed_macro!(3942);
+    collapsed_macro!(3943);
+    collapsed_macro!(3944);
+    collapsed_macro!(3945);
+    collapsed_macro!(3946);
+    collapsed_macro!(3947);
+    collapsed_macro!(3948);
+    collapsed_macro!(3949);
+    collapsed_macro!(3950);
+    collapsed_macro!(3951);
+    collapsed_macro!(3952);
+    collapsed_macro!(3953);
+    collapsed_macro!(3954);
+    collapsed_macro!(3955);
+    collapsed_macro!(3956);
+    collapsed_macro!(3957);
+    collapsed_macro!(3958);
+    collapsed_macro!(3959);
+    collapsed_macro!(3960);
+    collapsed_macro!(3961);
+    collapsed_macro!(3962);
+    collapsed_macro!(3963);
+    collapsed_macro!(3964);
+    collapsed_macro!(3965);
+    collapsed_macro!(3966);
+    collapsed_macro!(3967);
+    collapsed_macro!(3968);
+    collapsed_macro!(3969);
+    collapsed_macro!(3970);
+    collapsed_macro!(3971);
+    collapsed_macro!(3972);
+    collapsed_macro!(3973);
+    collapsed_macro!(3974);
+    collapsed_macro!(3975);
+    collapsed_macro!(3976);
+    collapsed_macro!(3977);
+    collapsed_macro!(3978);
+    collapsed_macro!(3979);
+    collapsed_macro!(3980);
+    collapsed_macro!(3981);
+    collapsed_macro!(3982);
+    collapsed_macro!(3983);
+    collapsed_macro!(3984);
+    collapsed_macro!(3985);
+    collapsed_macro!(3986);
+    collapsed_macro!(3987);
+    collapsed_macro!(3988);
+    collapsed_macro!(3989);
+    collapsed_macro!(3990);
+    collapsed_macro!(3991);
+    collapsed_macro!(3992);
+    collapsed_macro!(3993);
+    collapsed_macro!(3994);
+    collapsed_macro!(3995);
+    collapsed_macro!(3996);
+    collapsed_macro!(3997);
+    collapsed_macro!(3998);
+    collapsed_macro!(3999);
+    collapsed_macro!(4000);
+    collapsed_macro!(4001);
+    collapsed_macro!(4002);
+    collapsed_macro!(4003);
+    collapsed_macro!(4004);
+    collapsed_macro!(4005);
+    collapsed_macro!(4006);
+    collapsed_macro!(4007);
+    collapsed_macro!(4008);
+    collapsed_macro!(4009);
+    collapsed_macro!(4010);
+    collapsed_macro!(4011);
+    collapsed_macro!(4012);
+    collapsed_macro!(4013);
+    collapsed_macro!(4014);
+    collapsed_macro!(4015);
+    collapsed_macro!(4016);
+    collapsed_macro!(4017);
+    collapsed_macro!(4018);
+    collapsed_macro!(4019);
+    collapsed_macro!(4020);
+    collapsed_macro!(4021);
+    collapsed_macro!(4022);
+    collapsed_macro!(4023);
+    collapsed_macro!(4024);
+    collapsed_macro!(4025);
+    collapsed_macro!(4026);
+    collapsed_macro!(4027);
+    collapsed_macro!(4028);
+    collapsed_macro!(4029);
+    collapsed_macro!(4030);
+    collapsed_macro!(4031);
+    collapsed_macro!(4032);
+    collapsed_macro!(4033);
+    collapsed_macro!(4034);
+    collapsed_macro!(4035);
+    collapsed_macro!(4036);
+    collapsed_macro!(4037);
+    collapsed_macro!(4038);
+    collapsed_macro!(4039);
+    collapsed_macro!(4040);
+    collapsed_macro!(4041);
+    collapsed_macro!(4042);
+    collapsed_macro!(4043);
+    collapsed_macro!(4044);
+    collapsed_macro!(4045);
+    collapsed_macro!(4046);
+    collapsed_macro!(4047);
+    collapsed_macro!(4048);
+    collapsed_macro!(4049);
+    collapsed_macro!(4050);
+    collapsed_macro!(4051);
+    collapsed_macro!(4052);
+    collapsed_macro!(4053);
+    collapsed_macro!(4054);
+    collapsed_macro!(4055);
+    collapsed_macro!(4056);
+    collapsed_macro!(4057);
+    collapsed_macro!(4058);
+    collapsed_macro!(4059);
+    collapsed_macro!(4060);
+    collapsed_macro!(4061);
+    collapsed_macro!(4062);
+    collapsed_macro!(4063);
+    collapsed_macro!(4064);
+    collapsed_macro!(4065);
+    collapsed_macro!(4066);
+    collapsed_macro!(4067);
+    collapsed_macro!(4068);
+    collapsed_macro!(4069);
+    collapsed_macro!(4070);
+    collapsed_macro!(4071);
+    collapsed_macro!(4072);
+    collapsed_macro!(4073);
+    collapsed_macro!(4074);
+    collapsed_macro!(4075);
+    collapsed_macro!(4076);
+    collapsed_macro!(4077);
+    collapsed_macro!(4078);
+    collapsed_macro!(4079);
+    collapsed_macro!(4080);
+    collapsed_macro!(4081);
+    collapsed_macro!(4082);
+    collapsed_macro!(4083);
+    collapsed_macro!(4084);
+    collapsed_macro!(4085);
+    collapsed_macro!(4086);
+    collapsed_macro!(4087);
+    collapsed_macro!(4088);
+    collapsed_macro!(4089);
+    collapsed_macro!(4090);
+    collapsed_macro!(4091);
+    collapsed_macro!(4092);
+    collapsed_macro!(4093);
+    collapsed_macro!(4094);
+    collapsed_macro!(4095);
+    collapsed_macro!(4096);
+    collapsed_macro!(4097);
+}
+
+fn main() {
+    collapsed_debuginfo();
+}
diff --git a/tests/ui/debuginfo/debuginfo-inline-callsite-location-macro-2.rs b/tests/ui/debuginfo/debuginfo-inline-callsite-location-macro-2.rs
new file mode 100644
index 00000000000..3696ed37a20
--- /dev/null
+++ b/tests/ui/debuginfo/debuginfo-inline-callsite-location-macro-2.rs
@@ -0,0 +1,4122 @@
+//@ check-pass
+//@ compile-flags: -Cdebuginfo=2 -Copt-level=0 -Zmir-enable-passes=+Inline
+//@ ignore-msvc
+// ignore-tidy-filelength
+
+#[derive(Default)]
+struct Something {}
+
+macro_rules! simple_macro {
+    ($code:expr) => {
+        // Important to use a function here, so it can be inlined
+        // at the MIR stage.
+        Something::default()
+    }
+}
+
+fn uncollapsed_debuginfo() {
+    // LLVM allows 12 bits for encoding discriminators, so 4096+1 calls to a
+    // MIR-inlined function will exhaust it. At that point we will start
+    // dropping debug info (and tracing::warn!).
+    simple_macro!(1);
+    simple_macro!(2);
+    simple_macro!(3);
+    simple_macro!(4);
+    simple_macro!(5);
+    simple_macro!(6);
+    simple_macro!(7);
+    simple_macro!(8);
+    simple_macro!(9);
+    simple_macro!(10);
+    simple_macro!(11);
+    simple_macro!(12);
+    simple_macro!(13);
+    simple_macro!(14);
+    simple_macro!(15);
+    simple_macro!(16);
+    simple_macro!(17);
+    simple_macro!(18);
+    simple_macro!(19);
+    simple_macro!(20);
+    simple_macro!(21);
+    simple_macro!(22);
+    simple_macro!(23);
+    simple_macro!(24);
+    simple_macro!(25);
+    simple_macro!(26);
+    simple_macro!(27);
+    simple_macro!(28);
+    simple_macro!(29);
+    simple_macro!(30);
+    simple_macro!(31);
+    simple_macro!(32);
+    simple_macro!(33);
+    simple_macro!(34);
+    simple_macro!(35);
+    simple_macro!(36);
+    simple_macro!(37);
+    simple_macro!(38);
+    simple_macro!(39);
+    simple_macro!(40);
+    simple_macro!(41);
+    simple_macro!(42);
+    simple_macro!(43);
+    simple_macro!(44);
+    simple_macro!(45);
+    simple_macro!(46);
+    simple_macro!(47);
+    simple_macro!(48);
+    simple_macro!(49);
+    simple_macro!(50);
+    simple_macro!(51);
+    simple_macro!(52);
+    simple_macro!(53);
+    simple_macro!(54);
+    simple_macro!(55);
+    simple_macro!(56);
+    simple_macro!(57);
+    simple_macro!(58);
+    simple_macro!(59);
+    simple_macro!(60);
+    simple_macro!(61);
+    simple_macro!(62);
+    simple_macro!(63);
+    simple_macro!(64);
+    simple_macro!(65);
+    simple_macro!(66);
+    simple_macro!(67);
+    simple_macro!(68);
+    simple_macro!(69);
+    simple_macro!(70);
+    simple_macro!(71);
+    simple_macro!(72);
+    simple_macro!(73);
+    simple_macro!(74);
+    simple_macro!(75);
+    simple_macro!(76);
+    simple_macro!(77);
+    simple_macro!(78);
+    simple_macro!(79);
+    simple_macro!(80);
+    simple_macro!(81);
+    simple_macro!(82);
+    simple_macro!(83);
+    simple_macro!(84);
+    simple_macro!(85);
+    simple_macro!(86);
+    simple_macro!(87);
+    simple_macro!(88);
+    simple_macro!(89);
+    simple_macro!(90);
+    simple_macro!(91);
+    simple_macro!(92);
+    simple_macro!(93);
+    simple_macro!(94);
+    simple_macro!(95);
+    simple_macro!(96);
+    simple_macro!(97);
+    simple_macro!(98);
+    simple_macro!(99);
+    simple_macro!(100);
+    simple_macro!(101);
+    simple_macro!(102);
+    simple_macro!(103);
+    simple_macro!(104);
+    simple_macro!(105);
+    simple_macro!(106);
+    simple_macro!(107);
+    simple_macro!(108);
+    simple_macro!(109);
+    simple_macro!(110);
+    simple_macro!(111);
+    simple_macro!(112);
+    simple_macro!(113);
+    simple_macro!(114);
+    simple_macro!(115);
+    simple_macro!(116);
+    simple_macro!(117);
+    simple_macro!(118);
+    simple_macro!(119);
+    simple_macro!(120);
+    simple_macro!(121);
+    simple_macro!(122);
+    simple_macro!(123);
+    simple_macro!(124);
+    simple_macro!(125);
+    simple_macro!(126);
+    simple_macro!(127);
+    simple_macro!(128);
+    simple_macro!(129);
+    simple_macro!(130);
+    simple_macro!(131);
+    simple_macro!(132);
+    simple_macro!(133);
+    simple_macro!(134);
+    simple_macro!(135);
+    simple_macro!(136);
+    simple_macro!(137);
+    simple_macro!(138);
+    simple_macro!(139);
+    simple_macro!(140);
+    simple_macro!(141);
+    simple_macro!(142);
+    simple_macro!(143);
+    simple_macro!(144);
+    simple_macro!(145);
+    simple_macro!(146);
+    simple_macro!(147);
+    simple_macro!(148);
+    simple_macro!(149);
+    simple_macro!(150);
+    simple_macro!(151);
+    simple_macro!(152);
+    simple_macro!(153);
+    simple_macro!(154);
+    simple_macro!(155);
+    simple_macro!(156);
+    simple_macro!(157);
+    simple_macro!(158);
+    simple_macro!(159);
+    simple_macro!(160);
+    simple_macro!(161);
+    simple_macro!(162);
+    simple_macro!(163);
+    simple_macro!(164);
+    simple_macro!(165);
+    simple_macro!(166);
+    simple_macro!(167);
+    simple_macro!(168);
+    simple_macro!(169);
+    simple_macro!(170);
+    simple_macro!(171);
+    simple_macro!(172);
+    simple_macro!(173);
+    simple_macro!(174);
+    simple_macro!(175);
+    simple_macro!(176);
+    simple_macro!(177);
+    simple_macro!(178);
+    simple_macro!(179);
+    simple_macro!(180);
+    simple_macro!(181);
+    simple_macro!(182);
+    simple_macro!(183);
+    simple_macro!(184);
+    simple_macro!(185);
+    simple_macro!(186);
+    simple_macro!(187);
+    simple_macro!(188);
+    simple_macro!(189);
+    simple_macro!(190);
+    simple_macro!(191);
+    simple_macro!(192);
+    simple_macro!(193);
+    simple_macro!(194);
+    simple_macro!(195);
+    simple_macro!(196);
+    simple_macro!(197);
+    simple_macro!(198);
+    simple_macro!(199);
+    simple_macro!(200);
+    simple_macro!(201);
+    simple_macro!(202);
+    simple_macro!(203);
+    simple_macro!(204);
+    simple_macro!(205);
+    simple_macro!(206);
+    simple_macro!(207);
+    simple_macro!(208);
+    simple_macro!(209);
+    simple_macro!(210);
+    simple_macro!(211);
+    simple_macro!(212);
+    simple_macro!(213);
+    simple_macro!(214);
+    simple_macro!(215);
+    simple_macro!(216);
+    simple_macro!(217);
+    simple_macro!(218);
+    simple_macro!(219);
+    simple_macro!(220);
+    simple_macro!(221);
+    simple_macro!(222);
+    simple_macro!(223);
+    simple_macro!(224);
+    simple_macro!(225);
+    simple_macro!(226);
+    simple_macro!(227);
+    simple_macro!(228);
+    simple_macro!(229);
+    simple_macro!(230);
+    simple_macro!(231);
+    simple_macro!(232);
+    simple_macro!(233);
+    simple_macro!(234);
+    simple_macro!(235);
+    simple_macro!(236);
+    simple_macro!(237);
+    simple_macro!(238);
+    simple_macro!(239);
+    simple_macro!(240);
+    simple_macro!(241);
+    simple_macro!(242);
+    simple_macro!(243);
+    simple_macro!(244);
+    simple_macro!(245);
+    simple_macro!(246);
+    simple_macro!(247);
+    simple_macro!(248);
+    simple_macro!(249);
+    simple_macro!(250);
+    simple_macro!(251);
+    simple_macro!(252);
+    simple_macro!(253);
+    simple_macro!(254);
+    simple_macro!(255);
+    simple_macro!(256);
+    simple_macro!(257);
+    simple_macro!(258);
+    simple_macro!(259);
+    simple_macro!(260);
+    simple_macro!(261);
+    simple_macro!(262);
+    simple_macro!(263);
+    simple_macro!(264);
+    simple_macro!(265);
+    simple_macro!(266);
+    simple_macro!(267);
+    simple_macro!(268);
+    simple_macro!(269);
+    simple_macro!(270);
+    simple_macro!(271);
+    simple_macro!(272);
+    simple_macro!(273);
+    simple_macro!(274);
+    simple_macro!(275);
+    simple_macro!(276);
+    simple_macro!(277);
+    simple_macro!(278);
+    simple_macro!(279);
+    simple_macro!(280);
+    simple_macro!(281);
+    simple_macro!(282);
+    simple_macro!(283);
+    simple_macro!(284);
+    simple_macro!(285);
+    simple_macro!(286);
+    simple_macro!(287);
+    simple_macro!(288);
+    simple_macro!(289);
+    simple_macro!(290);
+    simple_macro!(291);
+    simple_macro!(292);
+    simple_macro!(293);
+    simple_macro!(294);
+    simple_macro!(295);
+    simple_macro!(296);
+    simple_macro!(297);
+    simple_macro!(298);
+    simple_macro!(299);
+    simple_macro!(300);
+    simple_macro!(301);
+    simple_macro!(302);
+    simple_macro!(303);
+    simple_macro!(304);
+    simple_macro!(305);
+    simple_macro!(306);
+    simple_macro!(307);
+    simple_macro!(308);
+    simple_macro!(309);
+    simple_macro!(310);
+    simple_macro!(311);
+    simple_macro!(312);
+    simple_macro!(313);
+    simple_macro!(314);
+    simple_macro!(315);
+    simple_macro!(316);
+    simple_macro!(317);
+    simple_macro!(318);
+    simple_macro!(319);
+    simple_macro!(320);
+    simple_macro!(321);
+    simple_macro!(322);
+    simple_macro!(323);
+    simple_macro!(324);
+    simple_macro!(325);
+    simple_macro!(326);
+    simple_macro!(327);
+    simple_macro!(328);
+    simple_macro!(329);
+    simple_macro!(330);
+    simple_macro!(331);
+    simple_macro!(332);
+    simple_macro!(333);
+    simple_macro!(334);
+    simple_macro!(335);
+    simple_macro!(336);
+    simple_macro!(337);
+    simple_macro!(338);
+    simple_macro!(339);
+    simple_macro!(340);
+    simple_macro!(341);
+    simple_macro!(342);
+    simple_macro!(343);
+    simple_macro!(344);
+    simple_macro!(345);
+    simple_macro!(346);
+    simple_macro!(347);
+    simple_macro!(348);
+    simple_macro!(349);
+    simple_macro!(350);
+    simple_macro!(351);
+    simple_macro!(352);
+    simple_macro!(353);
+    simple_macro!(354);
+    simple_macro!(355);
+    simple_macro!(356);
+    simple_macro!(357);
+    simple_macro!(358);
+    simple_macro!(359);
+    simple_macro!(360);
+    simple_macro!(361);
+    simple_macro!(362);
+    simple_macro!(363);
+    simple_macro!(364);
+    simple_macro!(365);
+    simple_macro!(366);
+    simple_macro!(367);
+    simple_macro!(368);
+    simple_macro!(369);
+    simple_macro!(370);
+    simple_macro!(371);
+    simple_macro!(372);
+    simple_macro!(373);
+    simple_macro!(374);
+    simple_macro!(375);
+    simple_macro!(376);
+    simple_macro!(377);
+    simple_macro!(378);
+    simple_macro!(379);
+    simple_macro!(380);
+    simple_macro!(381);
+    simple_macro!(382);
+    simple_macro!(383);
+    simple_macro!(384);
+    simple_macro!(385);
+    simple_macro!(386);
+    simple_macro!(387);
+    simple_macro!(388);
+    simple_macro!(389);
+    simple_macro!(390);
+    simple_macro!(391);
+    simple_macro!(392);
+    simple_macro!(393);
+    simple_macro!(394);
+    simple_macro!(395);
+    simple_macro!(396);
+    simple_macro!(397);
+    simple_macro!(398);
+    simple_macro!(399);
+    simple_macro!(400);
+    simple_macro!(401);
+    simple_macro!(402);
+    simple_macro!(403);
+    simple_macro!(404);
+    simple_macro!(405);
+    simple_macro!(406);
+    simple_macro!(407);
+    simple_macro!(408);
+    simple_macro!(409);
+    simple_macro!(410);
+    simple_macro!(411);
+    simple_macro!(412);
+    simple_macro!(413);
+    simple_macro!(414);
+    simple_macro!(415);
+    simple_macro!(416);
+    simple_macro!(417);
+    simple_macro!(418);
+    simple_macro!(419);
+    simple_macro!(420);
+    simple_macro!(421);
+    simple_macro!(422);
+    simple_macro!(423);
+    simple_macro!(424);
+    simple_macro!(425);
+    simple_macro!(426);
+    simple_macro!(427);
+    simple_macro!(428);
+    simple_macro!(429);
+    simple_macro!(430);
+    simple_macro!(431);
+    simple_macro!(432);
+    simple_macro!(433);
+    simple_macro!(434);
+    simple_macro!(435);
+    simple_macro!(436);
+    simple_macro!(437);
+    simple_macro!(438);
+    simple_macro!(439);
+    simple_macro!(440);
+    simple_macro!(441);
+    simple_macro!(442);
+    simple_macro!(443);
+    simple_macro!(444);
+    simple_macro!(445);
+    simple_macro!(446);
+    simple_macro!(447);
+    simple_macro!(448);
+    simple_macro!(449);
+    simple_macro!(450);
+    simple_macro!(451);
+    simple_macro!(452);
+    simple_macro!(453);
+    simple_macro!(454);
+    simple_macro!(455);
+    simple_macro!(456);
+    simple_macro!(457);
+    simple_macro!(458);
+    simple_macro!(459);
+    simple_macro!(460);
+    simple_macro!(461);
+    simple_macro!(462);
+    simple_macro!(463);
+    simple_macro!(464);
+    simple_macro!(465);
+    simple_macro!(466);
+    simple_macro!(467);
+    simple_macro!(468);
+    simple_macro!(469);
+    simple_macro!(470);
+    simple_macro!(471);
+    simple_macro!(472);
+    simple_macro!(473);
+    simple_macro!(474);
+    simple_macro!(475);
+    simple_macro!(476);
+    simple_macro!(477);
+    simple_macro!(478);
+    simple_macro!(479);
+    simple_macro!(480);
+    simple_macro!(481);
+    simple_macro!(482);
+    simple_macro!(483);
+    simple_macro!(484);
+    simple_macro!(485);
+    simple_macro!(486);
+    simple_macro!(487);
+    simple_macro!(488);
+    simple_macro!(489);
+    simple_macro!(490);
+    simple_macro!(491);
+    simple_macro!(492);
+    simple_macro!(493);
+    simple_macro!(494);
+    simple_macro!(495);
+    simple_macro!(496);
+    simple_macro!(497);
+    simple_macro!(498);
+    simple_macro!(499);
+    simple_macro!(500);
+    simple_macro!(501);
+    simple_macro!(502);
+    simple_macro!(503);
+    simple_macro!(504);
+    simple_macro!(505);
+    simple_macro!(506);
+    simple_macro!(507);
+    simple_macro!(508);
+    simple_macro!(509);
+    simple_macro!(510);
+    simple_macro!(511);
+    simple_macro!(512);
+    simple_macro!(513);
+    simple_macro!(514);
+    simple_macro!(515);
+    simple_macro!(516);
+    simple_macro!(517);
+    simple_macro!(518);
+    simple_macro!(519);
+    simple_macro!(520);
+    simple_macro!(521);
+    simple_macro!(522);
+    simple_macro!(523);
+    simple_macro!(524);
+    simple_macro!(525);
+    simple_macro!(526);
+    simple_macro!(527);
+    simple_macro!(528);
+    simple_macro!(529);
+    simple_macro!(530);
+    simple_macro!(531);
+    simple_macro!(532);
+    simple_macro!(533);
+    simple_macro!(534);
+    simple_macro!(535);
+    simple_macro!(536);
+    simple_macro!(537);
+    simple_macro!(538);
+    simple_macro!(539);
+    simple_macro!(540);
+    simple_macro!(541);
+    simple_macro!(542);
+    simple_macro!(543);
+    simple_macro!(544);
+    simple_macro!(545);
+    simple_macro!(546);
+    simple_macro!(547);
+    simple_macro!(548);
+    simple_macro!(549);
+    simple_macro!(550);
+    simple_macro!(551);
+    simple_macro!(552);
+    simple_macro!(553);
+    simple_macro!(554);
+    simple_macro!(555);
+    simple_macro!(556);
+    simple_macro!(557);
+    simple_macro!(558);
+    simple_macro!(559);
+    simple_macro!(560);
+    simple_macro!(561);
+    simple_macro!(562);
+    simple_macro!(563);
+    simple_macro!(564);
+    simple_macro!(565);
+    simple_macro!(566);
+    simple_macro!(567);
+    simple_macro!(568);
+    simple_macro!(569);
+    simple_macro!(570);
+    simple_macro!(571);
+    simple_macro!(572);
+    simple_macro!(573);
+    simple_macro!(574);
+    simple_macro!(575);
+    simple_macro!(576);
+    simple_macro!(577);
+    simple_macro!(578);
+    simple_macro!(579);
+    simple_macro!(580);
+    simple_macro!(581);
+    simple_macro!(582);
+    simple_macro!(583);
+    simple_macro!(584);
+    simple_macro!(585);
+    simple_macro!(586);
+    simple_macro!(587);
+    simple_macro!(588);
+    simple_macro!(589);
+    simple_macro!(590);
+    simple_macro!(591);
+    simple_macro!(592);
+    simple_macro!(593);
+    simple_macro!(594);
+    simple_macro!(595);
+    simple_macro!(596);
+    simple_macro!(597);
+    simple_macro!(598);
+    simple_macro!(599);
+    simple_macro!(600);
+    simple_macro!(601);
+    simple_macro!(602);
+    simple_macro!(603);
+    simple_macro!(604);
+    simple_macro!(605);
+    simple_macro!(606);
+    simple_macro!(607);
+    simple_macro!(608);
+    simple_macro!(609);
+    simple_macro!(610);
+    simple_macro!(611);
+    simple_macro!(612);
+    simple_macro!(613);
+    simple_macro!(614);
+    simple_macro!(615);
+    simple_macro!(616);
+    simple_macro!(617);
+    simple_macro!(618);
+    simple_macro!(619);
+    simple_macro!(620);
+    simple_macro!(621);
+    simple_macro!(622);
+    simple_macro!(623);
+    simple_macro!(624);
+    simple_macro!(625);
+    simple_macro!(626);
+    simple_macro!(627);
+    simple_macro!(628);
+    simple_macro!(629);
+    simple_macro!(630);
+    simple_macro!(631);
+    simple_macro!(632);
+    simple_macro!(633);
+    simple_macro!(634);
+    simple_macro!(635);
+    simple_macro!(636);
+    simple_macro!(637);
+    simple_macro!(638);
+    simple_macro!(639);
+    simple_macro!(640);
+    simple_macro!(641);
+    simple_macro!(642);
+    simple_macro!(643);
+    simple_macro!(644);
+    simple_macro!(645);
+    simple_macro!(646);
+    simple_macro!(647);
+    simple_macro!(648);
+    simple_macro!(649);
+    simple_macro!(650);
+    simple_macro!(651);
+    simple_macro!(652);
+    simple_macro!(653);
+    simple_macro!(654);
+    simple_macro!(655);
+    simple_macro!(656);
+    simple_macro!(657);
+    simple_macro!(658);
+    simple_macro!(659);
+    simple_macro!(660);
+    simple_macro!(661);
+    simple_macro!(662);
+    simple_macro!(663);
+    simple_macro!(664);
+    simple_macro!(665);
+    simple_macro!(666);
+    simple_macro!(667);
+    simple_macro!(668);
+    simple_macro!(669);
+    simple_macro!(670);
+    simple_macro!(671);
+    simple_macro!(672);
+    simple_macro!(673);
+    simple_macro!(674);
+    simple_macro!(675);
+    simple_macro!(676);
+    simple_macro!(677);
+    simple_macro!(678);
+    simple_macro!(679);
+    simple_macro!(680);
+    simple_macro!(681);
+    simple_macro!(682);
+    simple_macro!(683);
+    simple_macro!(684);
+    simple_macro!(685);
+    simple_macro!(686);
+    simple_macro!(687);
+    simple_macro!(688);
+    simple_macro!(689);
+    simple_macro!(690);
+    simple_macro!(691);
+    simple_macro!(692);
+    simple_macro!(693);
+    simple_macro!(694);
+    simple_macro!(695);
+    simple_macro!(696);
+    simple_macro!(697);
+    simple_macro!(698);
+    simple_macro!(699);
+    simple_macro!(700);
+    simple_macro!(701);
+    simple_macro!(702);
+    simple_macro!(703);
+    simple_macro!(704);
+    simple_macro!(705);
+    simple_macro!(706);
+    simple_macro!(707);
+    simple_macro!(708);
+    simple_macro!(709);
+    simple_macro!(710);
+    simple_macro!(711);
+    simple_macro!(712);
+    simple_macro!(713);
+    simple_macro!(714);
+    simple_macro!(715);
+    simple_macro!(716);
+    simple_macro!(717);
+    simple_macro!(718);
+    simple_macro!(719);
+    simple_macro!(720);
+    simple_macro!(721);
+    simple_macro!(722);
+    simple_macro!(723);
+    simple_macro!(724);
+    simple_macro!(725);
+    simple_macro!(726);
+    simple_macro!(727);
+    simple_macro!(728);
+    simple_macro!(729);
+    simple_macro!(730);
+    simple_macro!(731);
+    simple_macro!(732);
+    simple_macro!(733);
+    simple_macro!(734);
+    simple_macro!(735);
+    simple_macro!(736);
+    simple_macro!(737);
+    simple_macro!(738);
+    simple_macro!(739);
+    simple_macro!(740);
+    simple_macro!(741);
+    simple_macro!(742);
+    simple_macro!(743);
+    simple_macro!(744);
+    simple_macro!(745);
+    simple_macro!(746);
+    simple_macro!(747);
+    simple_macro!(748);
+    simple_macro!(749);
+    simple_macro!(750);
+    simple_macro!(751);
+    simple_macro!(752);
+    simple_macro!(753);
+    simple_macro!(754);
+    simple_macro!(755);
+    simple_macro!(756);
+    simple_macro!(757);
+    simple_macro!(758);
+    simple_macro!(759);
+    simple_macro!(760);
+    simple_macro!(761);
+    simple_macro!(762);
+    simple_macro!(763);
+    simple_macro!(764);
+    simple_macro!(765);
+    simple_macro!(766);
+    simple_macro!(767);
+    simple_macro!(768);
+    simple_macro!(769);
+    simple_macro!(770);
+    simple_macro!(771);
+    simple_macro!(772);
+    simple_macro!(773);
+    simple_macro!(774);
+    simple_macro!(775);
+    simple_macro!(776);
+    simple_macro!(777);
+    simple_macro!(778);
+    simple_macro!(779);
+    simple_macro!(780);
+    simple_macro!(781);
+    simple_macro!(782);
+    simple_macro!(783);
+    simple_macro!(784);
+    simple_macro!(785);
+    simple_macro!(786);
+    simple_macro!(787);
+    simple_macro!(788);
+    simple_macro!(789);
+    simple_macro!(790);
+    simple_macro!(791);
+    simple_macro!(792);
+    simple_macro!(793);
+    simple_macro!(794);
+    simple_macro!(795);
+    simple_macro!(796);
+    simple_macro!(797);
+    simple_macro!(798);
+    simple_macro!(799);
+    simple_macro!(800);
+    simple_macro!(801);
+    simple_macro!(802);
+    simple_macro!(803);
+    simple_macro!(804);
+    simple_macro!(805);
+    simple_macro!(806);
+    simple_macro!(807);
+    simple_macro!(808);
+    simple_macro!(809);
+    simple_macro!(810);
+    simple_macro!(811);
+    simple_macro!(812);
+    simple_macro!(813);
+    simple_macro!(814);
+    simple_macro!(815);
+    simple_macro!(816);
+    simple_macro!(817);
+    simple_macro!(818);
+    simple_macro!(819);
+    simple_macro!(820);
+    simple_macro!(821);
+    simple_macro!(822);
+    simple_macro!(823);
+    simple_macro!(824);
+    simple_macro!(825);
+    simple_macro!(826);
+    simple_macro!(827);
+    simple_macro!(828);
+    simple_macro!(829);
+    simple_macro!(830);
+    simple_macro!(831);
+    simple_macro!(832);
+    simple_macro!(833);
+    simple_macro!(834);
+    simple_macro!(835);
+    simple_macro!(836);
+    simple_macro!(837);
+    simple_macro!(838);
+    simple_macro!(839);
+    simple_macro!(840);
+    simple_macro!(841);
+    simple_macro!(842);
+    simple_macro!(843);
+    simple_macro!(844);
+    simple_macro!(845);
+    simple_macro!(846);
+    simple_macro!(847);
+    simple_macro!(848);
+    simple_macro!(849);
+    simple_macro!(850);
+    simple_macro!(851);
+    simple_macro!(852);
+    simple_macro!(853);
+    simple_macro!(854);
+    simple_macro!(855);
+    simple_macro!(856);
+    simple_macro!(857);
+    simple_macro!(858);
+    simple_macro!(859);
+    simple_macro!(860);
+    simple_macro!(861);
+    simple_macro!(862);
+    simple_macro!(863);
+    simple_macro!(864);
+    simple_macro!(865);
+    simple_macro!(866);
+    simple_macro!(867);
+    simple_macro!(868);
+    simple_macro!(869);
+    simple_macro!(870);
+    simple_macro!(871);
+    simple_macro!(872);
+    simple_macro!(873);
+    simple_macro!(874);
+    simple_macro!(875);
+    simple_macro!(876);
+    simple_macro!(877);
+    simple_macro!(878);
+    simple_macro!(879);
+    simple_macro!(880);
+    simple_macro!(881);
+    simple_macro!(882);
+    simple_macro!(883);
+    simple_macro!(884);
+    simple_macro!(885);
+    simple_macro!(886);
+    simple_macro!(887);
+    simple_macro!(888);
+    simple_macro!(889);
+    simple_macro!(890);
+    simple_macro!(891);
+    simple_macro!(892);
+    simple_macro!(893);
+    simple_macro!(894);
+    simple_macro!(895);
+    simple_macro!(896);
+    simple_macro!(897);
+    simple_macro!(898);
+    simple_macro!(899);
+    simple_macro!(900);
+    simple_macro!(901);
+    simple_macro!(902);
+    simple_macro!(903);
+    simple_macro!(904);
+    simple_macro!(905);
+    simple_macro!(906);
+    simple_macro!(907);
+    simple_macro!(908);
+    simple_macro!(909);
+    simple_macro!(910);
+    simple_macro!(911);
+    simple_macro!(912);
+    simple_macro!(913);
+    simple_macro!(914);
+    simple_macro!(915);
+    simple_macro!(916);
+    simple_macro!(917);
+    simple_macro!(918);
+    simple_macro!(919);
+    simple_macro!(920);
+    simple_macro!(921);
+    simple_macro!(922);
+    simple_macro!(923);
+    simple_macro!(924);
+    simple_macro!(925);
+    simple_macro!(926);
+    simple_macro!(927);
+    simple_macro!(928);
+    simple_macro!(929);
+    simple_macro!(930);
+    simple_macro!(931);
+    simple_macro!(932);
+    simple_macro!(933);
+    simple_macro!(934);
+    simple_macro!(935);
+    simple_macro!(936);
+    simple_macro!(937);
+    simple_macro!(938);
+    simple_macro!(939);
+    simple_macro!(940);
+    simple_macro!(941);
+    simple_macro!(942);
+    simple_macro!(943);
+    simple_macro!(944);
+    simple_macro!(945);
+    simple_macro!(946);
+    simple_macro!(947);
+    simple_macro!(948);
+    simple_macro!(949);
+    simple_macro!(950);
+    simple_macro!(951);
+    simple_macro!(952);
+    simple_macro!(953);
+    simple_macro!(954);
+    simple_macro!(955);
+    simple_macro!(956);
+    simple_macro!(957);
+    simple_macro!(958);
+    simple_macro!(959);
+    simple_macro!(960);
+    simple_macro!(961);
+    simple_macro!(962);
+    simple_macro!(963);
+    simple_macro!(964);
+    simple_macro!(965);
+    simple_macro!(966);
+    simple_macro!(967);
+    simple_macro!(968);
+    simple_macro!(969);
+    simple_macro!(970);
+    simple_macro!(971);
+    simple_macro!(972);
+    simple_macro!(973);
+    simple_macro!(974);
+    simple_macro!(975);
+    simple_macro!(976);
+    simple_macro!(977);
+    simple_macro!(978);
+    simple_macro!(979);
+    simple_macro!(980);
+    simple_macro!(981);
+    simple_macro!(982);
+    simple_macro!(983);
+    simple_macro!(984);
+    simple_macro!(985);
+    simple_macro!(986);
+    simple_macro!(987);
+    simple_macro!(988);
+    simple_macro!(989);
+    simple_macro!(990);
+    simple_macro!(991);
+    simple_macro!(992);
+    simple_macro!(993);
+    simple_macro!(994);
+    simple_macro!(995);
+    simple_macro!(996);
+    simple_macro!(997);
+    simple_macro!(998);
+    simple_macro!(999);
+    simple_macro!(1000);
+    simple_macro!(1001);
+    simple_macro!(1002);
+    simple_macro!(1003);
+    simple_macro!(1004);
+    simple_macro!(1005);
+    simple_macro!(1006);
+    simple_macro!(1007);
+    simple_macro!(1008);
+    simple_macro!(1009);
+    simple_macro!(1010);
+    simple_macro!(1011);
+    simple_macro!(1012);
+    simple_macro!(1013);
+    simple_macro!(1014);
+    simple_macro!(1015);
+    simple_macro!(1016);
+    simple_macro!(1017);
+    simple_macro!(1018);
+    simple_macro!(1019);
+    simple_macro!(1020);
+    simple_macro!(1021);
+    simple_macro!(1022);
+    simple_macro!(1023);
+    simple_macro!(1024);
+    simple_macro!(1025);
+    simple_macro!(1026);
+    simple_macro!(1027);
+    simple_macro!(1028);
+    simple_macro!(1029);
+    simple_macro!(1030);
+    simple_macro!(1031);
+    simple_macro!(1032);
+    simple_macro!(1033);
+    simple_macro!(1034);
+    simple_macro!(1035);
+    simple_macro!(1036);
+    simple_macro!(1037);
+    simple_macro!(1038);
+    simple_macro!(1039);
+    simple_macro!(1040);
+    simple_macro!(1041);
+    simple_macro!(1042);
+    simple_macro!(1043);
+    simple_macro!(1044);
+    simple_macro!(1045);
+    simple_macro!(1046);
+    simple_macro!(1047);
+    simple_macro!(1048);
+    simple_macro!(1049);
+    simple_macro!(1050);
+    simple_macro!(1051);
+    simple_macro!(1052);
+    simple_macro!(1053);
+    simple_macro!(1054);
+    simple_macro!(1055);
+    simple_macro!(1056);
+    simple_macro!(1057);
+    simple_macro!(1058);
+    simple_macro!(1059);
+    simple_macro!(1060);
+    simple_macro!(1061);
+    simple_macro!(1062);
+    simple_macro!(1063);
+    simple_macro!(1064);
+    simple_macro!(1065);
+    simple_macro!(1066);
+    simple_macro!(1067);
+    simple_macro!(1068);
+    simple_macro!(1069);
+    simple_macro!(1070);
+    simple_macro!(1071);
+    simple_macro!(1072);
+    simple_macro!(1073);
+    simple_macro!(1074);
+    simple_macro!(1075);
+    simple_macro!(1076);
+    simple_macro!(1077);
+    simple_macro!(1078);
+    simple_macro!(1079);
+    simple_macro!(1080);
+    simple_macro!(1081);
+    simple_macro!(1082);
+    simple_macro!(1083);
+    simple_macro!(1084);
+    simple_macro!(1085);
+    simple_macro!(1086);
+    simple_macro!(1087);
+    simple_macro!(1088);
+    simple_macro!(1089);
+    simple_macro!(1090);
+    simple_macro!(1091);
+    simple_macro!(1092);
+    simple_macro!(1093);
+    simple_macro!(1094);
+    simple_macro!(1095);
+    simple_macro!(1096);
+    simple_macro!(1097);
+    simple_macro!(1098);
+    simple_macro!(1099);
+    simple_macro!(1100);
+    simple_macro!(1101);
+    simple_macro!(1102);
+    simple_macro!(1103);
+    simple_macro!(1104);
+    simple_macro!(1105);
+    simple_macro!(1106);
+    simple_macro!(1107);
+    simple_macro!(1108);
+    simple_macro!(1109);
+    simple_macro!(1110);
+    simple_macro!(1111);
+    simple_macro!(1112);
+    simple_macro!(1113);
+    simple_macro!(1114);
+    simple_macro!(1115);
+    simple_macro!(1116);
+    simple_macro!(1117);
+    simple_macro!(1118);
+    simple_macro!(1119);
+    simple_macro!(1120);
+    simple_macro!(1121);
+    simple_macro!(1122);
+    simple_macro!(1123);
+    simple_macro!(1124);
+    simple_macro!(1125);
+    simple_macro!(1126);
+    simple_macro!(1127);
+    simple_macro!(1128);
+    simple_macro!(1129);
+    simple_macro!(1130);
+    simple_macro!(1131);
+    simple_macro!(1132);
+    simple_macro!(1133);
+    simple_macro!(1134);
+    simple_macro!(1135);
+    simple_macro!(1136);
+    simple_macro!(1137);
+    simple_macro!(1138);
+    simple_macro!(1139);
+    simple_macro!(1140);
+    simple_macro!(1141);
+    simple_macro!(1142);
+    simple_macro!(1143);
+    simple_macro!(1144);
+    simple_macro!(1145);
+    simple_macro!(1146);
+    simple_macro!(1147);
+    simple_macro!(1148);
+    simple_macro!(1149);
+    simple_macro!(1150);
+    simple_macro!(1151);
+    simple_macro!(1152);
+    simple_macro!(1153);
+    simple_macro!(1154);
+    simple_macro!(1155);
+    simple_macro!(1156);
+    simple_macro!(1157);
+    simple_macro!(1158);
+    simple_macro!(1159);
+    simple_macro!(1160);
+    simple_macro!(1161);
+    simple_macro!(1162);
+    simple_macro!(1163);
+    simple_macro!(1164);
+    simple_macro!(1165);
+    simple_macro!(1166);
+    simple_macro!(1167);
+    simple_macro!(1168);
+    simple_macro!(1169);
+    simple_macro!(1170);
+    simple_macro!(1171);
+    simple_macro!(1172);
+    simple_macro!(1173);
+    simple_macro!(1174);
+    simple_macro!(1175);
+    simple_macro!(1176);
+    simple_macro!(1177);
+    simple_macro!(1178);
+    simple_macro!(1179);
+    simple_macro!(1180);
+    simple_macro!(1181);
+    simple_macro!(1182);
+    simple_macro!(1183);
+    simple_macro!(1184);
+    simple_macro!(1185);
+    simple_macro!(1186);
+    simple_macro!(1187);
+    simple_macro!(1188);
+    simple_macro!(1189);
+    simple_macro!(1190);
+    simple_macro!(1191);
+    simple_macro!(1192);
+    simple_macro!(1193);
+    simple_macro!(1194);
+    simple_macro!(1195);
+    simple_macro!(1196);
+    simple_macro!(1197);
+    simple_macro!(1198);
+    simple_macro!(1199);
+    simple_macro!(1200);
+    simple_macro!(1201);
+    simple_macro!(1202);
+    simple_macro!(1203);
+    simple_macro!(1204);
+    simple_macro!(1205);
+    simple_macro!(1206);
+    simple_macro!(1207);
+    simple_macro!(1208);
+    simple_macro!(1209);
+    simple_macro!(1210);
+    simple_macro!(1211);
+    simple_macro!(1212);
+    simple_macro!(1213);
+    simple_macro!(1214);
+    simple_macro!(1215);
+    simple_macro!(1216);
+    simple_macro!(1217);
+    simple_macro!(1218);
+    simple_macro!(1219);
+    simple_macro!(1220);
+    simple_macro!(1221);
+    simple_macro!(1222);
+    simple_macro!(1223);
+    simple_macro!(1224);
+    simple_macro!(1225);
+    simple_macro!(1226);
+    simple_macro!(1227);
+    simple_macro!(1228);
+    simple_macro!(1229);
+    simple_macro!(1230);
+    simple_macro!(1231);
+    simple_macro!(1232);
+    simple_macro!(1233);
+    simple_macro!(1234);
+    simple_macro!(1235);
+    simple_macro!(1236);
+    simple_macro!(1237);
+    simple_macro!(1238);
+    simple_macro!(1239);
+    simple_macro!(1240);
+    simple_macro!(1241);
+    simple_macro!(1242);
+    simple_macro!(1243);
+    simple_macro!(1244);
+    simple_macro!(1245);
+    simple_macro!(1246);
+    simple_macro!(1247);
+    simple_macro!(1248);
+    simple_macro!(1249);
+    simple_macro!(1250);
+    simple_macro!(1251);
+    simple_macro!(1252);
+    simple_macro!(1253);
+    simple_macro!(1254);
+    simple_macro!(1255);
+    simple_macro!(1256);
+    simple_macro!(1257);
+    simple_macro!(1258);
+    simple_macro!(1259);
+    simple_macro!(1260);
+    simple_macro!(1261);
+    simple_macro!(1262);
+    simple_macro!(1263);
+    simple_macro!(1264);
+    simple_macro!(1265);
+    simple_macro!(1266);
+    simple_macro!(1267);
+    simple_macro!(1268);
+    simple_macro!(1269);
+    simple_macro!(1270);
+    simple_macro!(1271);
+    simple_macro!(1272);
+    simple_macro!(1273);
+    simple_macro!(1274);
+    simple_macro!(1275);
+    simple_macro!(1276);
+    simple_macro!(1277);
+    simple_macro!(1278);
+    simple_macro!(1279);
+    simple_macro!(1280);
+    simple_macro!(1281);
+    simple_macro!(1282);
+    simple_macro!(1283);
+    simple_macro!(1284);
+    simple_macro!(1285);
+    simple_macro!(1286);
+    simple_macro!(1287);
+    simple_macro!(1288);
+    simple_macro!(1289);
+    simple_macro!(1290);
+    simple_macro!(1291);
+    simple_macro!(1292);
+    simple_macro!(1293);
+    simple_macro!(1294);
+    simple_macro!(1295);
+    simple_macro!(1296);
+    simple_macro!(1297);
+    simple_macro!(1298);
+    simple_macro!(1299);
+    simple_macro!(1300);
+    simple_macro!(1301);
+    simple_macro!(1302);
+    simple_macro!(1303);
+    simple_macro!(1304);
+    simple_macro!(1305);
+    simple_macro!(1306);
+    simple_macro!(1307);
+    simple_macro!(1308);
+    simple_macro!(1309);
+    simple_macro!(1310);
+    simple_macro!(1311);
+    simple_macro!(1312);
+    simple_macro!(1313);
+    simple_macro!(1314);
+    simple_macro!(1315);
+    simple_macro!(1316);
+    simple_macro!(1317);
+    simple_macro!(1318);
+    simple_macro!(1319);
+    simple_macro!(1320);
+    simple_macro!(1321);
+    simple_macro!(1322);
+    simple_macro!(1323);
+    simple_macro!(1324);
+    simple_macro!(1325);
+    simple_macro!(1326);
+    simple_macro!(1327);
+    simple_macro!(1328);
+    simple_macro!(1329);
+    simple_macro!(1330);
+    simple_macro!(1331);
+    simple_macro!(1332);
+    simple_macro!(1333);
+    simple_macro!(1334);
+    simple_macro!(1335);
+    simple_macro!(1336);
+    simple_macro!(1337);
+    simple_macro!(1338);
+    simple_macro!(1339);
+    simple_macro!(1340);
+    simple_macro!(1341);
+    simple_macro!(1342);
+    simple_macro!(1343);
+    simple_macro!(1344);
+    simple_macro!(1345);
+    simple_macro!(1346);
+    simple_macro!(1347);
+    simple_macro!(1348);
+    simple_macro!(1349);
+    simple_macro!(1350);
+    simple_macro!(1351);
+    simple_macro!(1352);
+    simple_macro!(1353);
+    simple_macro!(1354);
+    simple_macro!(1355);
+    simple_macro!(1356);
+    simple_macro!(1357);
+    simple_macro!(1358);
+    simple_macro!(1359);
+    simple_macro!(1360);
+    simple_macro!(1361);
+    simple_macro!(1362);
+    simple_macro!(1363);
+    simple_macro!(1364);
+    simple_macro!(1365);
+    simple_macro!(1366);
+    simple_macro!(1367);
+    simple_macro!(1368);
+    simple_macro!(1369);
+    simple_macro!(1370);
+    simple_macro!(1371);
+    simple_macro!(1372);
+    simple_macro!(1373);
+    simple_macro!(1374);
+    simple_macro!(1375);
+    simple_macro!(1376);
+    simple_macro!(1377);
+    simple_macro!(1378);
+    simple_macro!(1379);
+    simple_macro!(1380);
+    simple_macro!(1381);
+    simple_macro!(1382);
+    simple_macro!(1383);
+    simple_macro!(1384);
+    simple_macro!(1385);
+    simple_macro!(1386);
+    simple_macro!(1387);
+    simple_macro!(1388);
+    simple_macro!(1389);
+    simple_macro!(1390);
+    simple_macro!(1391);
+    simple_macro!(1392);
+    simple_macro!(1393);
+    simple_macro!(1394);
+    simple_macro!(1395);
+    simple_macro!(1396);
+    simple_macro!(1397);
+    simple_macro!(1398);
+    simple_macro!(1399);
+    simple_macro!(1400);
+    simple_macro!(1401);
+    simple_macro!(1402);
+    simple_macro!(1403);
+    simple_macro!(1404);
+    simple_macro!(1405);
+    simple_macro!(1406);
+    simple_macro!(1407);
+    simple_macro!(1408);
+    simple_macro!(1409);
+    simple_macro!(1410);
+    simple_macro!(1411);
+    simple_macro!(1412);
+    simple_macro!(1413);
+    simple_macro!(1414);
+    simple_macro!(1415);
+    simple_macro!(1416);
+    simple_macro!(1417);
+    simple_macro!(1418);
+    simple_macro!(1419);
+    simple_macro!(1420);
+    simple_macro!(1421);
+    simple_macro!(1422);
+    simple_macro!(1423);
+    simple_macro!(1424);
+    simple_macro!(1425);
+    simple_macro!(1426);
+    simple_macro!(1427);
+    simple_macro!(1428);
+    simple_macro!(1429);
+    simple_macro!(1430);
+    simple_macro!(1431);
+    simple_macro!(1432);
+    simple_macro!(1433);
+    simple_macro!(1434);
+    simple_macro!(1435);
+    simple_macro!(1436);
+    simple_macro!(1437);
+    simple_macro!(1438);
+    simple_macro!(1439);
+    simple_macro!(1440);
+    simple_macro!(1441);
+    simple_macro!(1442);
+    simple_macro!(1443);
+    simple_macro!(1444);
+    simple_macro!(1445);
+    simple_macro!(1446);
+    simple_macro!(1447);
+    simple_macro!(1448);
+    simple_macro!(1449);
+    simple_macro!(1450);
+    simple_macro!(1451);
+    simple_macro!(1452);
+    simple_macro!(1453);
+    simple_macro!(1454);
+    simple_macro!(1455);
+    simple_macro!(1456);
+    simple_macro!(1457);
+    simple_macro!(1458);
+    simple_macro!(1459);
+    simple_macro!(1460);
+    simple_macro!(1461);
+    simple_macro!(1462);
+    simple_macro!(1463);
+    simple_macro!(1464);
+    simple_macro!(1465);
+    simple_macro!(1466);
+    simple_macro!(1467);
+    simple_macro!(1468);
+    simple_macro!(1469);
+    simple_macro!(1470);
+    simple_macro!(1471);
+    simple_macro!(1472);
+    simple_macro!(1473);
+    simple_macro!(1474);
+    simple_macro!(1475);
+    simple_macro!(1476);
+    simple_macro!(1477);
+    simple_macro!(1478);
+    simple_macro!(1479);
+    simple_macro!(1480);
+    simple_macro!(1481);
+    simple_macro!(1482);
+    simple_macro!(1483);
+    simple_macro!(1484);
+    simple_macro!(1485);
+    simple_macro!(1486);
+    simple_macro!(1487);
+    simple_macro!(1488);
+    simple_macro!(1489);
+    simple_macro!(1490);
+    simple_macro!(1491);
+    simple_macro!(1492);
+    simple_macro!(1493);
+    simple_macro!(1494);
+    simple_macro!(1495);
+    simple_macro!(1496);
+    simple_macro!(1497);
+    simple_macro!(1498);
+    simple_macro!(1499);
+    simple_macro!(1500);
+    simple_macro!(1501);
+    simple_macro!(1502);
+    simple_macro!(1503);
+    simple_macro!(1504);
+    simple_macro!(1505);
+    simple_macro!(1506);
+    simple_macro!(1507);
+    simple_macro!(1508);
+    simple_macro!(1509);
+    simple_macro!(1510);
+    simple_macro!(1511);
+    simple_macro!(1512);
+    simple_macro!(1513);
+    simple_macro!(1514);
+    simple_macro!(1515);
+    simple_macro!(1516);
+    simple_macro!(1517);
+    simple_macro!(1518);
+    simple_macro!(1519);
+    simple_macro!(1520);
+    simple_macro!(1521);
+    simple_macro!(1522);
+    simple_macro!(1523);
+    simple_macro!(1524);
+    simple_macro!(1525);
+    simple_macro!(1526);
+    simple_macro!(1527);
+    simple_macro!(1528);
+    simple_macro!(1529);
+    simple_macro!(1530);
+    simple_macro!(1531);
+    simple_macro!(1532);
+    simple_macro!(1533);
+    simple_macro!(1534);
+    simple_macro!(1535);
+    simple_macro!(1536);
+    simple_macro!(1537);
+    simple_macro!(1538);
+    simple_macro!(1539);
+    simple_macro!(1540);
+    simple_macro!(1541);
+    simple_macro!(1542);
+    simple_macro!(1543);
+    simple_macro!(1544);
+    simple_macro!(1545);
+    simple_macro!(1546);
+    simple_macro!(1547);
+    simple_macro!(1548);
+    simple_macro!(1549);
+    simple_macro!(1550);
+    simple_macro!(1551);
+    simple_macro!(1552);
+    simple_macro!(1553);
+    simple_macro!(1554);
+    simple_macro!(1555);
+    simple_macro!(1556);
+    simple_macro!(1557);
+    simple_macro!(1558);
+    simple_macro!(1559);
+    simple_macro!(1560);
+    simple_macro!(1561);
+    simple_macro!(1562);
+    simple_macro!(1563);
+    simple_macro!(1564);
+    simple_macro!(1565);
+    simple_macro!(1566);
+    simple_macro!(1567);
+    simple_macro!(1568);
+    simple_macro!(1569);
+    simple_macro!(1570);
+    simple_macro!(1571);
+    simple_macro!(1572);
+    simple_macro!(1573);
+    simple_macro!(1574);
+    simple_macro!(1575);
+    simple_macro!(1576);
+    simple_macro!(1577);
+    simple_macro!(1578);
+    simple_macro!(1579);
+    simple_macro!(1580);
+    simple_macro!(1581);
+    simple_macro!(1582);
+    simple_macro!(1583);
+    simple_macro!(1584);
+    simple_macro!(1585);
+    simple_macro!(1586);
+    simple_macro!(1587);
+    simple_macro!(1588);
+    simple_macro!(1589);
+    simple_macro!(1590);
+    simple_macro!(1591);
+    simple_macro!(1592);
+    simple_macro!(1593);
+    simple_macro!(1594);
+    simple_macro!(1595);
+    simple_macro!(1596);
+    simple_macro!(1597);
+    simple_macro!(1598);
+    simple_macro!(1599);
+    simple_macro!(1600);
+    simple_macro!(1601);
+    simple_macro!(1602);
+    simple_macro!(1603);
+    simple_macro!(1604);
+    simple_macro!(1605);
+    simple_macro!(1606);
+    simple_macro!(1607);
+    simple_macro!(1608);
+    simple_macro!(1609);
+    simple_macro!(1610);
+    simple_macro!(1611);
+    simple_macro!(1612);
+    simple_macro!(1613);
+    simple_macro!(1614);
+    simple_macro!(1615);
+    simple_macro!(1616);
+    simple_macro!(1617);
+    simple_macro!(1618);
+    simple_macro!(1619);
+    simple_macro!(1620);
+    simple_macro!(1621);
+    simple_macro!(1622);
+    simple_macro!(1623);
+    simple_macro!(1624);
+    simple_macro!(1625);
+    simple_macro!(1626);
+    simple_macro!(1627);
+    simple_macro!(1628);
+    simple_macro!(1629);
+    simple_macro!(1630);
+    simple_macro!(1631);
+    simple_macro!(1632);
+    simple_macro!(1633);
+    simple_macro!(1634);
+    simple_macro!(1635);
+    simple_macro!(1636);
+    simple_macro!(1637);
+    simple_macro!(1638);
+    simple_macro!(1639);
+    simple_macro!(1640);
+    simple_macro!(1641);
+    simple_macro!(1642);
+    simple_macro!(1643);
+    simple_macro!(1644);
+    simple_macro!(1645);
+    simple_macro!(1646);
+    simple_macro!(1647);
+    simple_macro!(1648);
+    simple_macro!(1649);
+    simple_macro!(1650);
+    simple_macro!(1651);
+    simple_macro!(1652);
+    simple_macro!(1653);
+    simple_macro!(1654);
+    simple_macro!(1655);
+    simple_macro!(1656);
+    simple_macro!(1657);
+    simple_macro!(1658);
+    simple_macro!(1659);
+    simple_macro!(1660);
+    simple_macro!(1661);
+    simple_macro!(1662);
+    simple_macro!(1663);
+    simple_macro!(1664);
+    simple_macro!(1665);
+    simple_macro!(1666);
+    simple_macro!(1667);
+    simple_macro!(1668);
+    simple_macro!(1669);
+    simple_macro!(1670);
+    simple_macro!(1671);
+    simple_macro!(1672);
+    simple_macro!(1673);
+    simple_macro!(1674);
+    simple_macro!(1675);
+    simple_macro!(1676);
+    simple_macro!(1677);
+    simple_macro!(1678);
+    simple_macro!(1679);
+    simple_macro!(1680);
+    simple_macro!(1681);
+    simple_macro!(1682);
+    simple_macro!(1683);
+    simple_macro!(1684);
+    simple_macro!(1685);
+    simple_macro!(1686);
+    simple_macro!(1687);
+    simple_macro!(1688);
+    simple_macro!(1689);
+    simple_macro!(1690);
+    simple_macro!(1691);
+    simple_macro!(1692);
+    simple_macro!(1693);
+    simple_macro!(1694);
+    simple_macro!(1695);
+    simple_macro!(1696);
+    simple_macro!(1697);
+    simple_macro!(1698);
+    simple_macro!(1699);
+    simple_macro!(1700);
+    simple_macro!(1701);
+    simple_macro!(1702);
+    simple_macro!(1703);
+    simple_macro!(1704);
+    simple_macro!(1705);
+    simple_macro!(1706);
+    simple_macro!(1707);
+    simple_macro!(1708);
+    simple_macro!(1709);
+    simple_macro!(1710);
+    simple_macro!(1711);
+    simple_macro!(1712);
+    simple_macro!(1713);
+    simple_macro!(1714);
+    simple_macro!(1715);
+    simple_macro!(1716);
+    simple_macro!(1717);
+    simple_macro!(1718);
+    simple_macro!(1719);
+    simple_macro!(1720);
+    simple_macro!(1721);
+    simple_macro!(1722);
+    simple_macro!(1723);
+    simple_macro!(1724);
+    simple_macro!(1725);
+    simple_macro!(1726);
+    simple_macro!(1727);
+    simple_macro!(1728);
+    simple_macro!(1729);
+    simple_macro!(1730);
+    simple_macro!(1731);
+    simple_macro!(1732);
+    simple_macro!(1733);
+    simple_macro!(1734);
+    simple_macro!(1735);
+    simple_macro!(1736);
+    simple_macro!(1737);
+    simple_macro!(1738);
+    simple_macro!(1739);
+    simple_macro!(1740);
+    simple_macro!(1741);
+    simple_macro!(1742);
+    simple_macro!(1743);
+    simple_macro!(1744);
+    simple_macro!(1745);
+    simple_macro!(1746);
+    simple_macro!(1747);
+    simple_macro!(1748);
+    simple_macro!(1749);
+    simple_macro!(1750);
+    simple_macro!(1751);
+    simple_macro!(1752);
+    simple_macro!(1753);
+    simple_macro!(1754);
+    simple_macro!(1755);
+    simple_macro!(1756);
+    simple_macro!(1757);
+    simple_macro!(1758);
+    simple_macro!(1759);
+    simple_macro!(1760);
+    simple_macro!(1761);
+    simple_macro!(1762);
+    simple_macro!(1763);
+    simple_macro!(1764);
+    simple_macro!(1765);
+    simple_macro!(1766);
+    simple_macro!(1767);
+    simple_macro!(1768);
+    simple_macro!(1769);
+    simple_macro!(1770);
+    simple_macro!(1771);
+    simple_macro!(1772);
+    simple_macro!(1773);
+    simple_macro!(1774);
+    simple_macro!(1775);
+    simple_macro!(1776);
+    simple_macro!(1777);
+    simple_macro!(1778);
+    simple_macro!(1779);
+    simple_macro!(1780);
+    simple_macro!(1781);
+    simple_macro!(1782);
+    simple_macro!(1783);
+    simple_macro!(1784);
+    simple_macro!(1785);
+    simple_macro!(1786);
+    simple_macro!(1787);
+    simple_macro!(1788);
+    simple_macro!(1789);
+    simple_macro!(1790);
+    simple_macro!(1791);
+    simple_macro!(1792);
+    simple_macro!(1793);
+    simple_macro!(1794);
+    simple_macro!(1795);
+    simple_macro!(1796);
+    simple_macro!(1797);
+    simple_macro!(1798);
+    simple_macro!(1799);
+    simple_macro!(1800);
+    simple_macro!(1801);
+    simple_macro!(1802);
+    simple_macro!(1803);
+    simple_macro!(1804);
+    simple_macro!(1805);
+    simple_macro!(1806);
+    simple_macro!(1807);
+    simple_macro!(1808);
+    simple_macro!(1809);
+    simple_macro!(1810);
+    simple_macro!(1811);
+    simple_macro!(1812);
+    simple_macro!(1813);
+    simple_macro!(1814);
+    simple_macro!(1815);
+    simple_macro!(1816);
+    simple_macro!(1817);
+    simple_macro!(1818);
+    simple_macro!(1819);
+    simple_macro!(1820);
+    simple_macro!(1821);
+    simple_macro!(1822);
+    simple_macro!(1823);
+    simple_macro!(1824);
+    simple_macro!(1825);
+    simple_macro!(1826);
+    simple_macro!(1827);
+    simple_macro!(1828);
+    simple_macro!(1829);
+    simple_macro!(1830);
+    simple_macro!(1831);
+    simple_macro!(1832);
+    simple_macro!(1833);
+    simple_macro!(1834);
+    simple_macro!(1835);
+    simple_macro!(1836);
+    simple_macro!(1837);
+    simple_macro!(1838);
+    simple_macro!(1839);
+    simple_macro!(1840);
+    simple_macro!(1841);
+    simple_macro!(1842);
+    simple_macro!(1843);
+    simple_macro!(1844);
+    simple_macro!(1845);
+    simple_macro!(1846);
+    simple_macro!(1847);
+    simple_macro!(1848);
+    simple_macro!(1849);
+    simple_macro!(1850);
+    simple_macro!(1851);
+    simple_macro!(1852);
+    simple_macro!(1853);
+    simple_macro!(1854);
+    simple_macro!(1855);
+    simple_macro!(1856);
+    simple_macro!(1857);
+    simple_macro!(1858);
+    simple_macro!(1859);
+    simple_macro!(1860);
+    simple_macro!(1861);
+    simple_macro!(1862);
+    simple_macro!(1863);
+    simple_macro!(1864);
+    simple_macro!(1865);
+    simple_macro!(1866);
+    simple_macro!(1867);
+    simple_macro!(1868);
+    simple_macro!(1869);
+    simple_macro!(1870);
+    simple_macro!(1871);
+    simple_macro!(1872);
+    simple_macro!(1873);
+    simple_macro!(1874);
+    simple_macro!(1875);
+    simple_macro!(1876);
+    simple_macro!(1877);
+    simple_macro!(1878);
+    simple_macro!(1879);
+    simple_macro!(1880);
+    simple_macro!(1881);
+    simple_macro!(1882);
+    simple_macro!(1883);
+    simple_macro!(1884);
+    simple_macro!(1885);
+    simple_macro!(1886);
+    simple_macro!(1887);
+    simple_macro!(1888);
+    simple_macro!(1889);
+    simple_macro!(1890);
+    simple_macro!(1891);
+    simple_macro!(1892);
+    simple_macro!(1893);
+    simple_macro!(1894);
+    simple_macro!(1895);
+    simple_macro!(1896);
+    simple_macro!(1897);
+    simple_macro!(1898);
+    simple_macro!(1899);
+    simple_macro!(1900);
+    simple_macro!(1901);
+    simple_macro!(1902);
+    simple_macro!(1903);
+    simple_macro!(1904);
+    simple_macro!(1905);
+    simple_macro!(1906);
+    simple_macro!(1907);
+    simple_macro!(1908);
+    simple_macro!(1909);
+    simple_macro!(1910);
+    simple_macro!(1911);
+    simple_macro!(1912);
+    simple_macro!(1913);
+    simple_macro!(1914);
+    simple_macro!(1915);
+    simple_macro!(1916);
+    simple_macro!(1917);
+    simple_macro!(1918);
+    simple_macro!(1919);
+    simple_macro!(1920);
+    simple_macro!(1921);
+    simple_macro!(1922);
+    simple_macro!(1923);
+    simple_macro!(1924);
+    simple_macro!(1925);
+    simple_macro!(1926);
+    simple_macro!(1927);
+    simple_macro!(1928);
+    simple_macro!(1929);
+    simple_macro!(1930);
+    simple_macro!(1931);
+    simple_macro!(1932);
+    simple_macro!(1933);
+    simple_macro!(1934);
+    simple_macro!(1935);
+    simple_macro!(1936);
+    simple_macro!(1937);
+    simple_macro!(1938);
+    simple_macro!(1939);
+    simple_macro!(1940);
+    simple_macro!(1941);
+    simple_macro!(1942);
+    simple_macro!(1943);
+    simple_macro!(1944);
+    simple_macro!(1945);
+    simple_macro!(1946);
+    simple_macro!(1947);
+    simple_macro!(1948);
+    simple_macro!(1949);
+    simple_macro!(1950);
+    simple_macro!(1951);
+    simple_macro!(1952);
+    simple_macro!(1953);
+    simple_macro!(1954);
+    simple_macro!(1955);
+    simple_macro!(1956);
+    simple_macro!(1957);
+    simple_macro!(1958);
+    simple_macro!(1959);
+    simple_macro!(1960);
+    simple_macro!(1961);
+    simple_macro!(1962);
+    simple_macro!(1963);
+    simple_macro!(1964);
+    simple_macro!(1965);
+    simple_macro!(1966);
+    simple_macro!(1967);
+    simple_macro!(1968);
+    simple_macro!(1969);
+    simple_macro!(1970);
+    simple_macro!(1971);
+    simple_macro!(1972);
+    simple_macro!(1973);
+    simple_macro!(1974);
+    simple_macro!(1975);
+    simple_macro!(1976);
+    simple_macro!(1977);
+    simple_macro!(1978);
+    simple_macro!(1979);
+    simple_macro!(1980);
+    simple_macro!(1981);
+    simple_macro!(1982);
+    simple_macro!(1983);
+    simple_macro!(1984);
+    simple_macro!(1985);
+    simple_macro!(1986);
+    simple_macro!(1987);
+    simple_macro!(1988);
+    simple_macro!(1989);
+    simple_macro!(1990);
+    simple_macro!(1991);
+    simple_macro!(1992);
+    simple_macro!(1993);
+    simple_macro!(1994);
+    simple_macro!(1995);
+    simple_macro!(1996);
+    simple_macro!(1997);
+    simple_macro!(1998);
+    simple_macro!(1999);
+    simple_macro!(2000);
+    simple_macro!(2001);
+    simple_macro!(2002);
+    simple_macro!(2003);
+    simple_macro!(2004);
+    simple_macro!(2005);
+    simple_macro!(2006);
+    simple_macro!(2007);
+    simple_macro!(2008);
+    simple_macro!(2009);
+    simple_macro!(2010);
+    simple_macro!(2011);
+    simple_macro!(2012);
+    simple_macro!(2013);
+    simple_macro!(2014);
+    simple_macro!(2015);
+    simple_macro!(2016);
+    simple_macro!(2017);
+    simple_macro!(2018);
+    simple_macro!(2019);
+    simple_macro!(2020);
+    simple_macro!(2021);
+    simple_macro!(2022);
+    simple_macro!(2023);
+    simple_macro!(2024);
+    simple_macro!(2025);
+    simple_macro!(2026);
+    simple_macro!(2027);
+    simple_macro!(2028);
+    simple_macro!(2029);
+    simple_macro!(2030);
+    simple_macro!(2031);
+    simple_macro!(2032);
+    simple_macro!(2033);
+    simple_macro!(2034);
+    simple_macro!(2035);
+    simple_macro!(2036);
+    simple_macro!(2037);
+    simple_macro!(2038);
+    simple_macro!(2039);
+    simple_macro!(2040);
+    simple_macro!(2041);
+    simple_macro!(2042);
+    simple_macro!(2043);
+    simple_macro!(2044);
+    simple_macro!(2045);
+    simple_macro!(2046);
+    simple_macro!(2047);
+    simple_macro!(2048);
+    simple_macro!(2049);
+    simple_macro!(2050);
+    simple_macro!(2051);
+    simple_macro!(2052);
+    simple_macro!(2053);
+    simple_macro!(2054);
+    simple_macro!(2055);
+    simple_macro!(2056);
+    simple_macro!(2057);
+    simple_macro!(2058);
+    simple_macro!(2059);
+    simple_macro!(2060);
+    simple_macro!(2061);
+    simple_macro!(2062);
+    simple_macro!(2063);
+    simple_macro!(2064);
+    simple_macro!(2065);
+    simple_macro!(2066);
+    simple_macro!(2067);
+    simple_macro!(2068);
+    simple_macro!(2069);
+    simple_macro!(2070);
+    simple_macro!(2071);
+    simple_macro!(2072);
+    simple_macro!(2073);
+    simple_macro!(2074);
+    simple_macro!(2075);
+    simple_macro!(2076);
+    simple_macro!(2077);
+    simple_macro!(2078);
+    simple_macro!(2079);
+    simple_macro!(2080);
+    simple_macro!(2081);
+    simple_macro!(2082);
+    simple_macro!(2083);
+    simple_macro!(2084);
+    simple_macro!(2085);
+    simple_macro!(2086);
+    simple_macro!(2087);
+    simple_macro!(2088);
+    simple_macro!(2089);
+    simple_macro!(2090);
+    simple_macro!(2091);
+    simple_macro!(2092);
+    simple_macro!(2093);
+    simple_macro!(2094);
+    simple_macro!(2095);
+    simple_macro!(2096);
+    simple_macro!(2097);
+    simple_macro!(2098);
+    simple_macro!(2099);
+    simple_macro!(2100);
+    simple_macro!(2101);
+    simple_macro!(2102);
+    simple_macro!(2103);
+    simple_macro!(2104);
+    simple_macro!(2105);
+    simple_macro!(2106);
+    simple_macro!(2107);
+    simple_macro!(2108);
+    simple_macro!(2109);
+    simple_macro!(2110);
+    simple_macro!(2111);
+    simple_macro!(2112);
+    simple_macro!(2113);
+    simple_macro!(2114);
+    simple_macro!(2115);
+    simple_macro!(2116);
+    simple_macro!(2117);
+    simple_macro!(2118);
+    simple_macro!(2119);
+    simple_macro!(2120);
+    simple_macro!(2121);
+    simple_macro!(2122);
+    simple_macro!(2123);
+    simple_macro!(2124);
+    simple_macro!(2125);
+    simple_macro!(2126);
+    simple_macro!(2127);
+    simple_macro!(2128);
+    simple_macro!(2129);
+    simple_macro!(2130);
+    simple_macro!(2131);
+    simple_macro!(2132);
+    simple_macro!(2133);
+    simple_macro!(2134);
+    simple_macro!(2135);
+    simple_macro!(2136);
+    simple_macro!(2137);
+    simple_macro!(2138);
+    simple_macro!(2139);
+    simple_macro!(2140);
+    simple_macro!(2141);
+    simple_macro!(2142);
+    simple_macro!(2143);
+    simple_macro!(2144);
+    simple_macro!(2145);
+    simple_macro!(2146);
+    simple_macro!(2147);
+    simple_macro!(2148);
+    simple_macro!(2149);
+    simple_macro!(2150);
+    simple_macro!(2151);
+    simple_macro!(2152);
+    simple_macro!(2153);
+    simple_macro!(2154);
+    simple_macro!(2155);
+    simple_macro!(2156);
+    simple_macro!(2157);
+    simple_macro!(2158);
+    simple_macro!(2159);
+    simple_macro!(2160);
+    simple_macro!(2161);
+    simple_macro!(2162);
+    simple_macro!(2163);
+    simple_macro!(2164);
+    simple_macro!(2165);
+    simple_macro!(2166);
+    simple_macro!(2167);
+    simple_macro!(2168);
+    simple_macro!(2169);
+    simple_macro!(2170);
+    simple_macro!(2171);
+    simple_macro!(2172);
+    simple_macro!(2173);
+    simple_macro!(2174);
+    simple_macro!(2175);
+    simple_macro!(2176);
+    simple_macro!(2177);
+    simple_macro!(2178);
+    simple_macro!(2179);
+    simple_macro!(2180);
+    simple_macro!(2181);
+    simple_macro!(2182);
+    simple_macro!(2183);
+    simple_macro!(2184);
+    simple_macro!(2185);
+    simple_macro!(2186);
+    simple_macro!(2187);
+    simple_macro!(2188);
+    simple_macro!(2189);
+    simple_macro!(2190);
+    simple_macro!(2191);
+    simple_macro!(2192);
+    simple_macro!(2193);
+    simple_macro!(2194);
+    simple_macro!(2195);
+    simple_macro!(2196);
+    simple_macro!(2197);
+    simple_macro!(2198);
+    simple_macro!(2199);
+    simple_macro!(2200);
+    simple_macro!(2201);
+    simple_macro!(2202);
+    simple_macro!(2203);
+    simple_macro!(2204);
+    simple_macro!(2205);
+    simple_macro!(2206);
+    simple_macro!(2207);
+    simple_macro!(2208);
+    simple_macro!(2209);
+    simple_macro!(2210);
+    simple_macro!(2211);
+    simple_macro!(2212);
+    simple_macro!(2213);
+    simple_macro!(2214);
+    simple_macro!(2215);
+    simple_macro!(2216);
+    simple_macro!(2217);
+    simple_macro!(2218);
+    simple_macro!(2219);
+    simple_macro!(2220);
+    simple_macro!(2221);
+    simple_macro!(2222);
+    simple_macro!(2223);
+    simple_macro!(2224);
+    simple_macro!(2225);
+    simple_macro!(2226);
+    simple_macro!(2227);
+    simple_macro!(2228);
+    simple_macro!(2229);
+    simple_macro!(2230);
+    simple_macro!(2231);
+    simple_macro!(2232);
+    simple_macro!(2233);
+    simple_macro!(2234);
+    simple_macro!(2235);
+    simple_macro!(2236);
+    simple_macro!(2237);
+    simple_macro!(2238);
+    simple_macro!(2239);
+    simple_macro!(2240);
+    simple_macro!(2241);
+    simple_macro!(2242);
+    simple_macro!(2243);
+    simple_macro!(2244);
+    simple_macro!(2245);
+    simple_macro!(2246);
+    simple_macro!(2247);
+    simple_macro!(2248);
+    simple_macro!(2249);
+    simple_macro!(2250);
+    simple_macro!(2251);
+    simple_macro!(2252);
+    simple_macro!(2253);
+    simple_macro!(2254);
+    simple_macro!(2255);
+    simple_macro!(2256);
+    simple_macro!(2257);
+    simple_macro!(2258);
+    simple_macro!(2259);
+    simple_macro!(2260);
+    simple_macro!(2261);
+    simple_macro!(2262);
+    simple_macro!(2263);
+    simple_macro!(2264);
+    simple_macro!(2265);
+    simple_macro!(2266);
+    simple_macro!(2267);
+    simple_macro!(2268);
+    simple_macro!(2269);
+    simple_macro!(2270);
+    simple_macro!(2271);
+    simple_macro!(2272);
+    simple_macro!(2273);
+    simple_macro!(2274);
+    simple_macro!(2275);
+    simple_macro!(2276);
+    simple_macro!(2277);
+    simple_macro!(2278);
+    simple_macro!(2279);
+    simple_macro!(2280);
+    simple_macro!(2281);
+    simple_macro!(2282);
+    simple_macro!(2283);
+    simple_macro!(2284);
+    simple_macro!(2285);
+    simple_macro!(2286);
+    simple_macro!(2287);
+    simple_macro!(2288);
+    simple_macro!(2289);
+    simple_macro!(2290);
+    simple_macro!(2291);
+    simple_macro!(2292);
+    simple_macro!(2293);
+    simple_macro!(2294);
+    simple_macro!(2295);
+    simple_macro!(2296);
+    simple_macro!(2297);
+    simple_macro!(2298);
+    simple_macro!(2299);
+    simple_macro!(2300);
+    simple_macro!(2301);
+    simple_macro!(2302);
+    simple_macro!(2303);
+    simple_macro!(2304);
+    simple_macro!(2305);
+    simple_macro!(2306);
+    simple_macro!(2307);
+    simple_macro!(2308);
+    simple_macro!(2309);
+    simple_macro!(2310);
+    simple_macro!(2311);
+    simple_macro!(2312);
+    simple_macro!(2313);
+    simple_macro!(2314);
+    simple_macro!(2315);
+    simple_macro!(2316);
+    simple_macro!(2317);
+    simple_macro!(2318);
+    simple_macro!(2319);
+    simple_macro!(2320);
+    simple_macro!(2321);
+    simple_macro!(2322);
+    simple_macro!(2323);
+    simple_macro!(2324);
+    simple_macro!(2325);
+    simple_macro!(2326);
+    simple_macro!(2327);
+    simple_macro!(2328);
+    simple_macro!(2329);
+    simple_macro!(2330);
+    simple_macro!(2331);
+    simple_macro!(2332);
+    simple_macro!(2333);
+    simple_macro!(2334);
+    simple_macro!(2335);
+    simple_macro!(2336);
+    simple_macro!(2337);
+    simple_macro!(2338);
+    simple_macro!(2339);
+    simple_macro!(2340);
+    simple_macro!(2341);
+    simple_macro!(2342);
+    simple_macro!(2343);
+    simple_macro!(2344);
+    simple_macro!(2345);
+    simple_macro!(2346);
+    simple_macro!(2347);
+    simple_macro!(2348);
+    simple_macro!(2349);
+    simple_macro!(2350);
+    simple_macro!(2351);
+    simple_macro!(2352);
+    simple_macro!(2353);
+    simple_macro!(2354);
+    simple_macro!(2355);
+    simple_macro!(2356);
+    simple_macro!(2357);
+    simple_macro!(2358);
+    simple_macro!(2359);
+    simple_macro!(2360);
+    simple_macro!(2361);
+    simple_macro!(2362);
+    simple_macro!(2363);
+    simple_macro!(2364);
+    simple_macro!(2365);
+    simple_macro!(2366);
+    simple_macro!(2367);
+    simple_macro!(2368);
+    simple_macro!(2369);
+    simple_macro!(2370);
+    simple_macro!(2371);
+    simple_macro!(2372);
+    simple_macro!(2373);
+    simple_macro!(2374);
+    simple_macro!(2375);
+    simple_macro!(2376);
+    simple_macro!(2377);
+    simple_macro!(2378);
+    simple_macro!(2379);
+    simple_macro!(2380);
+    simple_macro!(2381);
+    simple_macro!(2382);
+    simple_macro!(2383);
+    simple_macro!(2384);
+    simple_macro!(2385);
+    simple_macro!(2386);
+    simple_macro!(2387);
+    simple_macro!(2388);
+    simple_macro!(2389);
+    simple_macro!(2390);
+    simple_macro!(2391);
+    simple_macro!(2392);
+    simple_macro!(2393);
+    simple_macro!(2394);
+    simple_macro!(2395);
+    simple_macro!(2396);
+    simple_macro!(2397);
+    simple_macro!(2398);
+    simple_macro!(2399);
+    simple_macro!(2400);
+    simple_macro!(2401);
+    simple_macro!(2402);
+    simple_macro!(2403);
+    simple_macro!(2404);
+    simple_macro!(2405);
+    simple_macro!(2406);
+    simple_macro!(2407);
+    simple_macro!(2408);
+    simple_macro!(2409);
+    simple_macro!(2410);
+    simple_macro!(2411);
+    simple_macro!(2412);
+    simple_macro!(2413);
+    simple_macro!(2414);
+    simple_macro!(2415);
+    simple_macro!(2416);
+    simple_macro!(2417);
+    simple_macro!(2418);
+    simple_macro!(2419);
+    simple_macro!(2420);
+    simple_macro!(2421);
+    simple_macro!(2422);
+    simple_macro!(2423);
+    simple_macro!(2424);
+    simple_macro!(2425);
+    simple_macro!(2426);
+    simple_macro!(2427);
+    simple_macro!(2428);
+    simple_macro!(2429);
+    simple_macro!(2430);
+    simple_macro!(2431);
+    simple_macro!(2432);
+    simple_macro!(2433);
+    simple_macro!(2434);
+    simple_macro!(2435);
+    simple_macro!(2436);
+    simple_macro!(2437);
+    simple_macro!(2438);
+    simple_macro!(2439);
+    simple_macro!(2440);
+    simple_macro!(2441);
+    simple_macro!(2442);
+    simple_macro!(2443);
+    simple_macro!(2444);
+    simple_macro!(2445);
+    simple_macro!(2446);
+    simple_macro!(2447);
+    simple_macro!(2448);
+    simple_macro!(2449);
+    simple_macro!(2450);
+    simple_macro!(2451);
+    simple_macro!(2452);
+    simple_macro!(2453);
+    simple_macro!(2454);
+    simple_macro!(2455);
+    simple_macro!(2456);
+    simple_macro!(2457);
+    simple_macro!(2458);
+    simple_macro!(2459);
+    simple_macro!(2460);
+    simple_macro!(2461);
+    simple_macro!(2462);
+    simple_macro!(2463);
+    simple_macro!(2464);
+    simple_macro!(2465);
+    simple_macro!(2466);
+    simple_macro!(2467);
+    simple_macro!(2468);
+    simple_macro!(2469);
+    simple_macro!(2470);
+    simple_macro!(2471);
+    simple_macro!(2472);
+    simple_macro!(2473);
+    simple_macro!(2474);
+    simple_macro!(2475);
+    simple_macro!(2476);
+    simple_macro!(2477);
+    simple_macro!(2478);
+    simple_macro!(2479);
+    simple_macro!(2480);
+    simple_macro!(2481);
+    simple_macro!(2482);
+    simple_macro!(2483);
+    simple_macro!(2484);
+    simple_macro!(2485);
+    simple_macro!(2486);
+    simple_macro!(2487);
+    simple_macro!(2488);
+    simple_macro!(2489);
+    simple_macro!(2490);
+    simple_macro!(2491);
+    simple_macro!(2492);
+    simple_macro!(2493);
+    simple_macro!(2494);
+    simple_macro!(2495);
+    simple_macro!(2496);
+    simple_macro!(2497);
+    simple_macro!(2498);
+    simple_macro!(2499);
+    simple_macro!(2500);
+    simple_macro!(2501);
+    simple_macro!(2502);
+    simple_macro!(2503);
+    simple_macro!(2504);
+    simple_macro!(2505);
+    simple_macro!(2506);
+    simple_macro!(2507);
+    simple_macro!(2508);
+    simple_macro!(2509);
+    simple_macro!(2510);
+    simple_macro!(2511);
+    simple_macro!(2512);
+    simple_macro!(2513);
+    simple_macro!(2514);
+    simple_macro!(2515);
+    simple_macro!(2516);
+    simple_macro!(2517);
+    simple_macro!(2518);
+    simple_macro!(2519);
+    simple_macro!(2520);
+    simple_macro!(2521);
+    simple_macro!(2522);
+    simple_macro!(2523);
+    simple_macro!(2524);
+    simple_macro!(2525);
+    simple_macro!(2526);
+    simple_macro!(2527);
+    simple_macro!(2528);
+    simple_macro!(2529);
+    simple_macro!(2530);
+    simple_macro!(2531);
+    simple_macro!(2532);
+    simple_macro!(2533);
+    simple_macro!(2534);
+    simple_macro!(2535);
+    simple_macro!(2536);
+    simple_macro!(2537);
+    simple_macro!(2538);
+    simple_macro!(2539);
+    simple_macro!(2540);
+    simple_macro!(2541);
+    simple_macro!(2542);
+    simple_macro!(2543);
+    simple_macro!(2544);
+    simple_macro!(2545);
+    simple_macro!(2546);
+    simple_macro!(2547);
+    simple_macro!(2548);
+    simple_macro!(2549);
+    simple_macro!(2550);
+    simple_macro!(2551);
+    simple_macro!(2552);
+    simple_macro!(2553);
+    simple_macro!(2554);
+    simple_macro!(2555);
+    simple_macro!(2556);
+    simple_macro!(2557);
+    simple_macro!(2558);
+    simple_macro!(2559);
+    simple_macro!(2560);
+    simple_macro!(2561);
+    simple_macro!(2562);
+    simple_macro!(2563);
+    simple_macro!(2564);
+    simple_macro!(2565);
+    simple_macro!(2566);
+    simple_macro!(2567);
+    simple_macro!(2568);
+    simple_macro!(2569);
+    simple_macro!(2570);
+    simple_macro!(2571);
+    simple_macro!(2572);
+    simple_macro!(2573);
+    simple_macro!(2574);
+    simple_macro!(2575);
+    simple_macro!(2576);
+    simple_macro!(2577);
+    simple_macro!(2578);
+    simple_macro!(2579);
+    simple_macro!(2580);
+    simple_macro!(2581);
+    simple_macro!(2582);
+    simple_macro!(2583);
+    simple_macro!(2584);
+    simple_macro!(2585);
+    simple_macro!(2586);
+    simple_macro!(2587);
+    simple_macro!(2588);
+    simple_macro!(2589);
+    simple_macro!(2590);
+    simple_macro!(2591);
+    simple_macro!(2592);
+    simple_macro!(2593);
+    simple_macro!(2594);
+    simple_macro!(2595);
+    simple_macro!(2596);
+    simple_macro!(2597);
+    simple_macro!(2598);
+    simple_macro!(2599);
+    simple_macro!(2600);
+    simple_macro!(2601);
+    simple_macro!(2602);
+    simple_macro!(2603);
+    simple_macro!(2604);
+    simple_macro!(2605);
+    simple_macro!(2606);
+    simple_macro!(2607);
+    simple_macro!(2608);
+    simple_macro!(2609);
+    simple_macro!(2610);
+    simple_macro!(2611);
+    simple_macro!(2612);
+    simple_macro!(2613);
+    simple_macro!(2614);
+    simple_macro!(2615);
+    simple_macro!(2616);
+    simple_macro!(2617);
+    simple_macro!(2618);
+    simple_macro!(2619);
+    simple_macro!(2620);
+    simple_macro!(2621);
+    simple_macro!(2622);
+    simple_macro!(2623);
+    simple_macro!(2624);
+    simple_macro!(2625);
+    simple_macro!(2626);
+    simple_macro!(2627);
+    simple_macro!(2628);
+    simple_macro!(2629);
+    simple_macro!(2630);
+    simple_macro!(2631);
+    simple_macro!(2632);
+    simple_macro!(2633);
+    simple_macro!(2634);
+    simple_macro!(2635);
+    simple_macro!(2636);
+    simple_macro!(2637);
+    simple_macro!(2638);
+    simple_macro!(2639);
+    simple_macro!(2640);
+    simple_macro!(2641);
+    simple_macro!(2642);
+    simple_macro!(2643);
+    simple_macro!(2644);
+    simple_macro!(2645);
+    simple_macro!(2646);
+    simple_macro!(2647);
+    simple_macro!(2648);
+    simple_macro!(2649);
+    simple_macro!(2650);
+    simple_macro!(2651);
+    simple_macro!(2652);
+    simple_macro!(2653);
+    simple_macro!(2654);
+    simple_macro!(2655);
+    simple_macro!(2656);
+    simple_macro!(2657);
+    simple_macro!(2658);
+    simple_macro!(2659);
+    simple_macro!(2660);
+    simple_macro!(2661);
+    simple_macro!(2662);
+    simple_macro!(2663);
+    simple_macro!(2664);
+    simple_macro!(2665);
+    simple_macro!(2666);
+    simple_macro!(2667);
+    simple_macro!(2668);
+    simple_macro!(2669);
+    simple_macro!(2670);
+    simple_macro!(2671);
+    simple_macro!(2672);
+    simple_macro!(2673);
+    simple_macro!(2674);
+    simple_macro!(2675);
+    simple_macro!(2676);
+    simple_macro!(2677);
+    simple_macro!(2678);
+    simple_macro!(2679);
+    simple_macro!(2680);
+    simple_macro!(2681);
+    simple_macro!(2682);
+    simple_macro!(2683);
+    simple_macro!(2684);
+    simple_macro!(2685);
+    simple_macro!(2686);
+    simple_macro!(2687);
+    simple_macro!(2688);
+    simple_macro!(2689);
+    simple_macro!(2690);
+    simple_macro!(2691);
+    simple_macro!(2692);
+    simple_macro!(2693);
+    simple_macro!(2694);
+    simple_macro!(2695);
+    simple_macro!(2696);
+    simple_macro!(2697);
+    simple_macro!(2698);
+    simple_macro!(2699);
+    simple_macro!(2700);
+    simple_macro!(2701);
+    simple_macro!(2702);
+    simple_macro!(2703);
+    simple_macro!(2704);
+    simple_macro!(2705);
+    simple_macro!(2706);
+    simple_macro!(2707);
+    simple_macro!(2708);
+    simple_macro!(2709);
+    simple_macro!(2710);
+    simple_macro!(2711);
+    simple_macro!(2712);
+    simple_macro!(2713);
+    simple_macro!(2714);
+    simple_macro!(2715);
+    simple_macro!(2716);
+    simple_macro!(2717);
+    simple_macro!(2718);
+    simple_macro!(2719);
+    simple_macro!(2720);
+    simple_macro!(2721);
+    simple_macro!(2722);
+    simple_macro!(2723);
+    simple_macro!(2724);
+    simple_macro!(2725);
+    simple_macro!(2726);
+    simple_macro!(2727);
+    simple_macro!(2728);
+    simple_macro!(2729);
+    simple_macro!(2730);
+    simple_macro!(2731);
+    simple_macro!(2732);
+    simple_macro!(2733);
+    simple_macro!(2734);
+    simple_macro!(2735);
+    simple_macro!(2736);
+    simple_macro!(2737);
+    simple_macro!(2738);
+    simple_macro!(2739);
+    simple_macro!(2740);
+    simple_macro!(2741);
+    simple_macro!(2742);
+    simple_macro!(2743);
+    simple_macro!(2744);
+    simple_macro!(2745);
+    simple_macro!(2746);
+    simple_macro!(2747);
+    simple_macro!(2748);
+    simple_macro!(2749);
+    simple_macro!(2750);
+    simple_macro!(2751);
+    simple_macro!(2752);
+    simple_macro!(2753);
+    simple_macro!(2754);
+    simple_macro!(2755);
+    simple_macro!(2756);
+    simple_macro!(2757);
+    simple_macro!(2758);
+    simple_macro!(2759);
+    simple_macro!(2760);
+    simple_macro!(2761);
+    simple_macro!(2762);
+    simple_macro!(2763);
+    simple_macro!(2764);
+    simple_macro!(2765);
+    simple_macro!(2766);
+    simple_macro!(2767);
+    simple_macro!(2768);
+    simple_macro!(2769);
+    simple_macro!(2770);
+    simple_macro!(2771);
+    simple_macro!(2772);
+    simple_macro!(2773);
+    simple_macro!(2774);
+    simple_macro!(2775);
+    simple_macro!(2776);
+    simple_macro!(2777);
+    simple_macro!(2778);
+    simple_macro!(2779);
+    simple_macro!(2780);
+    simple_macro!(2781);
+    simple_macro!(2782);
+    simple_macro!(2783);
+    simple_macro!(2784);
+    simple_macro!(2785);
+    simple_macro!(2786);
+    simple_macro!(2787);
+    simple_macro!(2788);
+    simple_macro!(2789);
+    simple_macro!(2790);
+    simple_macro!(2791);
+    simple_macro!(2792);
+    simple_macro!(2793);
+    simple_macro!(2794);
+    simple_macro!(2795);
+    simple_macro!(2796);
+    simple_macro!(2797);
+    simple_macro!(2798);
+    simple_macro!(2799);
+    simple_macro!(2800);
+    simple_macro!(2801);
+    simple_macro!(2802);
+    simple_macro!(2803);
+    simple_macro!(2804);
+    simple_macro!(2805);
+    simple_macro!(2806);
+    simple_macro!(2807);
+    simple_macro!(2808);
+    simple_macro!(2809);
+    simple_macro!(2810);
+    simple_macro!(2811);
+    simple_macro!(2812);
+    simple_macro!(2813);
+    simple_macro!(2814);
+    simple_macro!(2815);
+    simple_macro!(2816);
+    simple_macro!(2817);
+    simple_macro!(2818);
+    simple_macro!(2819);
+    simple_macro!(2820);
+    simple_macro!(2821);
+    simple_macro!(2822);
+    simple_macro!(2823);
+    simple_macro!(2824);
+    simple_macro!(2825);
+    simple_macro!(2826);
+    simple_macro!(2827);
+    simple_macro!(2828);
+    simple_macro!(2829);
+    simple_macro!(2830);
+    simple_macro!(2831);
+    simple_macro!(2832);
+    simple_macro!(2833);
+    simple_macro!(2834);
+    simple_macro!(2835);
+    simple_macro!(2836);
+    simple_macro!(2837);
+    simple_macro!(2838);
+    simple_macro!(2839);
+    simple_macro!(2840);
+    simple_macro!(2841);
+    simple_macro!(2842);
+    simple_macro!(2843);
+    simple_macro!(2844);
+    simple_macro!(2845);
+    simple_macro!(2846);
+    simple_macro!(2847);
+    simple_macro!(2848);
+    simple_macro!(2849);
+    simple_macro!(2850);
+    simple_macro!(2851);
+    simple_macro!(2852);
+    simple_macro!(2853);
+    simple_macro!(2854);
+    simple_macro!(2855);
+    simple_macro!(2856);
+    simple_macro!(2857);
+    simple_macro!(2858);
+    simple_macro!(2859);
+    simple_macro!(2860);
+    simple_macro!(2861);
+    simple_macro!(2862);
+    simple_macro!(2863);
+    simple_macro!(2864);
+    simple_macro!(2865);
+    simple_macro!(2866);
+    simple_macro!(2867);
+    simple_macro!(2868);
+    simple_macro!(2869);
+    simple_macro!(2870);
+    simple_macro!(2871);
+    simple_macro!(2872);
+    simple_macro!(2873);
+    simple_macro!(2874);
+    simple_macro!(2875);
+    simple_macro!(2876);
+    simple_macro!(2877);
+    simple_macro!(2878);
+    simple_macro!(2879);
+    simple_macro!(2880);
+    simple_macro!(2881);
+    simple_macro!(2882);
+    simple_macro!(2883);
+    simple_macro!(2884);
+    simple_macro!(2885);
+    simple_macro!(2886);
+    simple_macro!(2887);
+    simple_macro!(2888);
+    simple_macro!(2889);
+    simple_macro!(2890);
+    simple_macro!(2891);
+    simple_macro!(2892);
+    simple_macro!(2893);
+    simple_macro!(2894);
+    simple_macro!(2895);
+    simple_macro!(2896);
+    simple_macro!(2897);
+    simple_macro!(2898);
+    simple_macro!(2899);
+    simple_macro!(2900);
+    simple_macro!(2901);
+    simple_macro!(2902);
+    simple_macro!(2903);
+    simple_macro!(2904);
+    simple_macro!(2905);
+    simple_macro!(2906);
+    simple_macro!(2907);
+    simple_macro!(2908);
+    simple_macro!(2909);
+    simple_macro!(2910);
+    simple_macro!(2911);
+    simple_macro!(2912);
+    simple_macro!(2913);
+    simple_macro!(2914);
+    simple_macro!(2915);
+    simple_macro!(2916);
+    simple_macro!(2917);
+    simple_macro!(2918);
+    simple_macro!(2919);
+    simple_macro!(2920);
+    simple_macro!(2921);
+    simple_macro!(2922);
+    simple_macro!(2923);
+    simple_macro!(2924);
+    simple_macro!(2925);
+    simple_macro!(2926);
+    simple_macro!(2927);
+    simple_macro!(2928);
+    simple_macro!(2929);
+    simple_macro!(2930);
+    simple_macro!(2931);
+    simple_macro!(2932);
+    simple_macro!(2933);
+    simple_macro!(2934);
+    simple_macro!(2935);
+    simple_macro!(2936);
+    simple_macro!(2937);
+    simple_macro!(2938);
+    simple_macro!(2939);
+    simple_macro!(2940);
+    simple_macro!(2941);
+    simple_macro!(2942);
+    simple_macro!(2943);
+    simple_macro!(2944);
+    simple_macro!(2945);
+    simple_macro!(2946);
+    simple_macro!(2947);
+    simple_macro!(2948);
+    simple_macro!(2949);
+    simple_macro!(2950);
+    simple_macro!(2951);
+    simple_macro!(2952);
+    simple_macro!(2953);
+    simple_macro!(2954);
+    simple_macro!(2955);
+    simple_macro!(2956);
+    simple_macro!(2957);
+    simple_macro!(2958);
+    simple_macro!(2959);
+    simple_macro!(2960);
+    simple_macro!(2961);
+    simple_macro!(2962);
+    simple_macro!(2963);
+    simple_macro!(2964);
+    simple_macro!(2965);
+    simple_macro!(2966);
+    simple_macro!(2967);
+    simple_macro!(2968);
+    simple_macro!(2969);
+    simple_macro!(2970);
+    simple_macro!(2971);
+    simple_macro!(2972);
+    simple_macro!(2973);
+    simple_macro!(2974);
+    simple_macro!(2975);
+    simple_macro!(2976);
+    simple_macro!(2977);
+    simple_macro!(2978);
+    simple_macro!(2979);
+    simple_macro!(2980);
+    simple_macro!(2981);
+    simple_macro!(2982);
+    simple_macro!(2983);
+    simple_macro!(2984);
+    simple_macro!(2985);
+    simple_macro!(2986);
+    simple_macro!(2987);
+    simple_macro!(2988);
+    simple_macro!(2989);
+    simple_macro!(2990);
+    simple_macro!(2991);
+    simple_macro!(2992);
+    simple_macro!(2993);
+    simple_macro!(2994);
+    simple_macro!(2995);
+    simple_macro!(2996);
+    simple_macro!(2997);
+    simple_macro!(2998);
+    simple_macro!(2999);
+    simple_macro!(3000);
+    simple_macro!(3001);
+    simple_macro!(3002);
+    simple_macro!(3003);
+    simple_macro!(3004);
+    simple_macro!(3005);
+    simple_macro!(3006);
+    simple_macro!(3007);
+    simple_macro!(3008);
+    simple_macro!(3009);
+    simple_macro!(3010);
+    simple_macro!(3011);
+    simple_macro!(3012);
+    simple_macro!(3013);
+    simple_macro!(3014);
+    simple_macro!(3015);
+    simple_macro!(3016);
+    simple_macro!(3017);
+    simple_macro!(3018);
+    simple_macro!(3019);
+    simple_macro!(3020);
+    simple_macro!(3021);
+    simple_macro!(3022);
+    simple_macro!(3023);
+    simple_macro!(3024);
+    simple_macro!(3025);
+    simple_macro!(3026);
+    simple_macro!(3027);
+    simple_macro!(3028);
+    simple_macro!(3029);
+    simple_macro!(3030);
+    simple_macro!(3031);
+    simple_macro!(3032);
+    simple_macro!(3033);
+    simple_macro!(3034);
+    simple_macro!(3035);
+    simple_macro!(3036);
+    simple_macro!(3037);
+    simple_macro!(3038);
+    simple_macro!(3039);
+    simple_macro!(3040);
+    simple_macro!(3041);
+    simple_macro!(3042);
+    simple_macro!(3043);
+    simple_macro!(3044);
+    simple_macro!(3045);
+    simple_macro!(3046);
+    simple_macro!(3047);
+    simple_macro!(3048);
+    simple_macro!(3049);
+    simple_macro!(3050);
+    simple_macro!(3051);
+    simple_macro!(3052);
+    simple_macro!(3053);
+    simple_macro!(3054);
+    simple_macro!(3055);
+    simple_macro!(3056);
+    simple_macro!(3057);
+    simple_macro!(3058);
+    simple_macro!(3059);
+    simple_macro!(3060);
+    simple_macro!(3061);
+    simple_macro!(3062);
+    simple_macro!(3063);
+    simple_macro!(3064);
+    simple_macro!(3065);
+    simple_macro!(3066);
+    simple_macro!(3067);
+    simple_macro!(3068);
+    simple_macro!(3069);
+    simple_macro!(3070);
+    simple_macro!(3071);
+    simple_macro!(3072);
+    simple_macro!(3073);
+    simple_macro!(3074);
+    simple_macro!(3075);
+    simple_macro!(3076);
+    simple_macro!(3077);
+    simple_macro!(3078);
+    simple_macro!(3079);
+    simple_macro!(3080);
+    simple_macro!(3081);
+    simple_macro!(3082);
+    simple_macro!(3083);
+    simple_macro!(3084);
+    simple_macro!(3085);
+    simple_macro!(3086);
+    simple_macro!(3087);
+    simple_macro!(3088);
+    simple_macro!(3089);
+    simple_macro!(3090);
+    simple_macro!(3091);
+    simple_macro!(3092);
+    simple_macro!(3093);
+    simple_macro!(3094);
+    simple_macro!(3095);
+    simple_macro!(3096);
+    simple_macro!(3097);
+    simple_macro!(3098);
+    simple_macro!(3099);
+    simple_macro!(3100);
+    simple_macro!(3101);
+    simple_macro!(3102);
+    simple_macro!(3103);
+    simple_macro!(3104);
+    simple_macro!(3105);
+    simple_macro!(3106);
+    simple_macro!(3107);
+    simple_macro!(3108);
+    simple_macro!(3109);
+    simple_macro!(3110);
+    simple_macro!(3111);
+    simple_macro!(3112);
+    simple_macro!(3113);
+    simple_macro!(3114);
+    simple_macro!(3115);
+    simple_macro!(3116);
+    simple_macro!(3117);
+    simple_macro!(3118);
+    simple_macro!(3119);
+    simple_macro!(3120);
+    simple_macro!(3121);
+    simple_macro!(3122);
+    simple_macro!(3123);
+    simple_macro!(3124);
+    simple_macro!(3125);
+    simple_macro!(3126);
+    simple_macro!(3127);
+    simple_macro!(3128);
+    simple_macro!(3129);
+    simple_macro!(3130);
+    simple_macro!(3131);
+    simple_macro!(3132);
+    simple_macro!(3133);
+    simple_macro!(3134);
+    simple_macro!(3135);
+    simple_macro!(3136);
+    simple_macro!(3137);
+    simple_macro!(3138);
+    simple_macro!(3139);
+    simple_macro!(3140);
+    simple_macro!(3141);
+    simple_macro!(3142);
+    simple_macro!(3143);
+    simple_macro!(3144);
+    simple_macro!(3145);
+    simple_macro!(3146);
+    simple_macro!(3147);
+    simple_macro!(3148);
+    simple_macro!(3149);
+    simple_macro!(3150);
+    simple_macro!(3151);
+    simple_macro!(3152);
+    simple_macro!(3153);
+    simple_macro!(3154);
+    simple_macro!(3155);
+    simple_macro!(3156);
+    simple_macro!(3157);
+    simple_macro!(3158);
+    simple_macro!(3159);
+    simple_macro!(3160);
+    simple_macro!(3161);
+    simple_macro!(3162);
+    simple_macro!(3163);
+    simple_macro!(3164);
+    simple_macro!(3165);
+    simple_macro!(3166);
+    simple_macro!(3167);
+    simple_macro!(3168);
+    simple_macro!(3169);
+    simple_macro!(3170);
+    simple_macro!(3171);
+    simple_macro!(3172);
+    simple_macro!(3173);
+    simple_macro!(3174);
+    simple_macro!(3175);
+    simple_macro!(3176);
+    simple_macro!(3177);
+    simple_macro!(3178);
+    simple_macro!(3179);
+    simple_macro!(3180);
+    simple_macro!(3181);
+    simple_macro!(3182);
+    simple_macro!(3183);
+    simple_macro!(3184);
+    simple_macro!(3185);
+    simple_macro!(3186);
+    simple_macro!(3187);
+    simple_macro!(3188);
+    simple_macro!(3189);
+    simple_macro!(3190);
+    simple_macro!(3191);
+    simple_macro!(3192);
+    simple_macro!(3193);
+    simple_macro!(3194);
+    simple_macro!(3195);
+    simple_macro!(3196);
+    simple_macro!(3197);
+    simple_macro!(3198);
+    simple_macro!(3199);
+    simple_macro!(3200);
+    simple_macro!(3201);
+    simple_macro!(3202);
+    simple_macro!(3203);
+    simple_macro!(3204);
+    simple_macro!(3205);
+    simple_macro!(3206);
+    simple_macro!(3207);
+    simple_macro!(3208);
+    simple_macro!(3209);
+    simple_macro!(3210);
+    simple_macro!(3211);
+    simple_macro!(3212);
+    simple_macro!(3213);
+    simple_macro!(3214);
+    simple_macro!(3215);
+    simple_macro!(3216);
+    simple_macro!(3217);
+    simple_macro!(3218);
+    simple_macro!(3219);
+    simple_macro!(3220);
+    simple_macro!(3221);
+    simple_macro!(3222);
+    simple_macro!(3223);
+    simple_macro!(3224);
+    simple_macro!(3225);
+    simple_macro!(3226);
+    simple_macro!(3227);
+    simple_macro!(3228);
+    simple_macro!(3229);
+    simple_macro!(3230);
+    simple_macro!(3231);
+    simple_macro!(3232);
+    simple_macro!(3233);
+    simple_macro!(3234);
+    simple_macro!(3235);
+    simple_macro!(3236);
+    simple_macro!(3237);
+    simple_macro!(3238);
+    simple_macro!(3239);
+    simple_macro!(3240);
+    simple_macro!(3241);
+    simple_macro!(3242);
+    simple_macro!(3243);
+    simple_macro!(3244);
+    simple_macro!(3245);
+    simple_macro!(3246);
+    simple_macro!(3247);
+    simple_macro!(3248);
+    simple_macro!(3249);
+    simple_macro!(3250);
+    simple_macro!(3251);
+    simple_macro!(3252);
+    simple_macro!(3253);
+    simple_macro!(3254);
+    simple_macro!(3255);
+    simple_macro!(3256);
+    simple_macro!(3257);
+    simple_macro!(3258);
+    simple_macro!(3259);
+    simple_macro!(3260);
+    simple_macro!(3261);
+    simple_macro!(3262);
+    simple_macro!(3263);
+    simple_macro!(3264);
+    simple_macro!(3265);
+    simple_macro!(3266);
+    simple_macro!(3267);
+    simple_macro!(3268);
+    simple_macro!(3269);
+    simple_macro!(3270);
+    simple_macro!(3271);
+    simple_macro!(3272);
+    simple_macro!(3273);
+    simple_macro!(3274);
+    simple_macro!(3275);
+    simple_macro!(3276);
+    simple_macro!(3277);
+    simple_macro!(3278);
+    simple_macro!(3279);
+    simple_macro!(3280);
+    simple_macro!(3281);
+    simple_macro!(3282);
+    simple_macro!(3283);
+    simple_macro!(3284);
+    simple_macro!(3285);
+    simple_macro!(3286);
+    simple_macro!(3287);
+    simple_macro!(3288);
+    simple_macro!(3289);
+    simple_macro!(3290);
+    simple_macro!(3291);
+    simple_macro!(3292);
+    simple_macro!(3293);
+    simple_macro!(3294);
+    simple_macro!(3295);
+    simple_macro!(3296);
+    simple_macro!(3297);
+    simple_macro!(3298);
+    simple_macro!(3299);
+    simple_macro!(3300);
+    simple_macro!(3301);
+    simple_macro!(3302);
+    simple_macro!(3303);
+    simple_macro!(3304);
+    simple_macro!(3305);
+    simple_macro!(3306);
+    simple_macro!(3307);
+    simple_macro!(3308);
+    simple_macro!(3309);
+    simple_macro!(3310);
+    simple_macro!(3311);
+    simple_macro!(3312);
+    simple_macro!(3313);
+    simple_macro!(3314);
+    simple_macro!(3315);
+    simple_macro!(3316);
+    simple_macro!(3317);
+    simple_macro!(3318);
+    simple_macro!(3319);
+    simple_macro!(3320);
+    simple_macro!(3321);
+    simple_macro!(3322);
+    simple_macro!(3323);
+    simple_macro!(3324);
+    simple_macro!(3325);
+    simple_macro!(3326);
+    simple_macro!(3327);
+    simple_macro!(3328);
+    simple_macro!(3329);
+    simple_macro!(3330);
+    simple_macro!(3331);
+    simple_macro!(3332);
+    simple_macro!(3333);
+    simple_macro!(3334);
+    simple_macro!(3335);
+    simple_macro!(3336);
+    simple_macro!(3337);
+    simple_macro!(3338);
+    simple_macro!(3339);
+    simple_macro!(3340);
+    simple_macro!(3341);
+    simple_macro!(3342);
+    simple_macro!(3343);
+    simple_macro!(3344);
+    simple_macro!(3345);
+    simple_macro!(3346);
+    simple_macro!(3347);
+    simple_macro!(3348);
+    simple_macro!(3349);
+    simple_macro!(3350);
+    simple_macro!(3351);
+    simple_macro!(3352);
+    simple_macro!(3353);
+    simple_macro!(3354);
+    simple_macro!(3355);
+    simple_macro!(3356);
+    simple_macro!(3357);
+    simple_macro!(3358);
+    simple_macro!(3359);
+    simple_macro!(3360);
+    simple_macro!(3361);
+    simple_macro!(3362);
+    simple_macro!(3363);
+    simple_macro!(3364);
+    simple_macro!(3365);
+    simple_macro!(3366);
+    simple_macro!(3367);
+    simple_macro!(3368);
+    simple_macro!(3369);
+    simple_macro!(3370);
+    simple_macro!(3371);
+    simple_macro!(3372);
+    simple_macro!(3373);
+    simple_macro!(3374);
+    simple_macro!(3375);
+    simple_macro!(3376);
+    simple_macro!(3377);
+    simple_macro!(3378);
+    simple_macro!(3379);
+    simple_macro!(3380);
+    simple_macro!(3381);
+    simple_macro!(3382);
+    simple_macro!(3383);
+    simple_macro!(3384);
+    simple_macro!(3385);
+    simple_macro!(3386);
+    simple_macro!(3387);
+    simple_macro!(3388);
+    simple_macro!(3389);
+    simple_macro!(3390);
+    simple_macro!(3391);
+    simple_macro!(3392);
+    simple_macro!(3393);
+    simple_macro!(3394);
+    simple_macro!(3395);
+    simple_macro!(3396);
+    simple_macro!(3397);
+    simple_macro!(3398);
+    simple_macro!(3399);
+    simple_macro!(3400);
+    simple_macro!(3401);
+    simple_macro!(3402);
+    simple_macro!(3403);
+    simple_macro!(3404);
+    simple_macro!(3405);
+    simple_macro!(3406);
+    simple_macro!(3407);
+    simple_macro!(3408);
+    simple_macro!(3409);
+    simple_macro!(3410);
+    simple_macro!(3411);
+    simple_macro!(3412);
+    simple_macro!(3413);
+    simple_macro!(3414);
+    simple_macro!(3415);
+    simple_macro!(3416);
+    simple_macro!(3417);
+    simple_macro!(3418);
+    simple_macro!(3419);
+    simple_macro!(3420);
+    simple_macro!(3421);
+    simple_macro!(3422);
+    simple_macro!(3423);
+    simple_macro!(3424);
+    simple_macro!(3425);
+    simple_macro!(3426);
+    simple_macro!(3427);
+    simple_macro!(3428);
+    simple_macro!(3429);
+    simple_macro!(3430);
+    simple_macro!(3431);
+    simple_macro!(3432);
+    simple_macro!(3433);
+    simple_macro!(3434);
+    simple_macro!(3435);
+    simple_macro!(3436);
+    simple_macro!(3437);
+    simple_macro!(3438);
+    simple_macro!(3439);
+    simple_macro!(3440);
+    simple_macro!(3441);
+    simple_macro!(3442);
+    simple_macro!(3443);
+    simple_macro!(3444);
+    simple_macro!(3445);
+    simple_macro!(3446);
+    simple_macro!(3447);
+    simple_macro!(3448);
+    simple_macro!(3449);
+    simple_macro!(3450);
+    simple_macro!(3451);
+    simple_macro!(3452);
+    simple_macro!(3453);
+    simple_macro!(3454);
+    simple_macro!(3455);
+    simple_macro!(3456);
+    simple_macro!(3457);
+    simple_macro!(3458);
+    simple_macro!(3459);
+    simple_macro!(3460);
+    simple_macro!(3461);
+    simple_macro!(3462);
+    simple_macro!(3463);
+    simple_macro!(3464);
+    simple_macro!(3465);
+    simple_macro!(3466);
+    simple_macro!(3467);
+    simple_macro!(3468);
+    simple_macro!(3469);
+    simple_macro!(3470);
+    simple_macro!(3471);
+    simple_macro!(3472);
+    simple_macro!(3473);
+    simple_macro!(3474);
+    simple_macro!(3475);
+    simple_macro!(3476);
+    simple_macro!(3477);
+    simple_macro!(3478);
+    simple_macro!(3479);
+    simple_macro!(3480);
+    simple_macro!(3481);
+    simple_macro!(3482);
+    simple_macro!(3483);
+    simple_macro!(3484);
+    simple_macro!(3485);
+    simple_macro!(3486);
+    simple_macro!(3487);
+    simple_macro!(3488);
+    simple_macro!(3489);
+    simple_macro!(3490);
+    simple_macro!(3491);
+    simple_macro!(3492);
+    simple_macro!(3493);
+    simple_macro!(3494);
+    simple_macro!(3495);
+    simple_macro!(3496);
+    simple_macro!(3497);
+    simple_macro!(3498);
+    simple_macro!(3499);
+    simple_macro!(3500);
+    simple_macro!(3501);
+    simple_macro!(3502);
+    simple_macro!(3503);
+    simple_macro!(3504);
+    simple_macro!(3505);
+    simple_macro!(3506);
+    simple_macro!(3507);
+    simple_macro!(3508);
+    simple_macro!(3509);
+    simple_macro!(3510);
+    simple_macro!(3511);
+    simple_macro!(3512);
+    simple_macro!(3513);
+    simple_macro!(3514);
+    simple_macro!(3515);
+    simple_macro!(3516);
+    simple_macro!(3517);
+    simple_macro!(3518);
+    simple_macro!(3519);
+    simple_macro!(3520);
+    simple_macro!(3521);
+    simple_macro!(3522);
+    simple_macro!(3523);
+    simple_macro!(3524);
+    simple_macro!(3525);
+    simple_macro!(3526);
+    simple_macro!(3527);
+    simple_macro!(3528);
+    simple_macro!(3529);
+    simple_macro!(3530);
+    simple_macro!(3531);
+    simple_macro!(3532);
+    simple_macro!(3533);
+    simple_macro!(3534);
+    simple_macro!(3535);
+    simple_macro!(3536);
+    simple_macro!(3537);
+    simple_macro!(3538);
+    simple_macro!(3539);
+    simple_macro!(3540);
+    simple_macro!(3541);
+    simple_macro!(3542);
+    simple_macro!(3543);
+    simple_macro!(3544);
+    simple_macro!(3545);
+    simple_macro!(3546);
+    simple_macro!(3547);
+    simple_macro!(3548);
+    simple_macro!(3549);
+    simple_macro!(3550);
+    simple_macro!(3551);
+    simple_macro!(3552);
+    simple_macro!(3553);
+    simple_macro!(3554);
+    simple_macro!(3555);
+    simple_macro!(3556);
+    simple_macro!(3557);
+    simple_macro!(3558);
+    simple_macro!(3559);
+    simple_macro!(3560);
+    simple_macro!(3561);
+    simple_macro!(3562);
+    simple_macro!(3563);
+    simple_macro!(3564);
+    simple_macro!(3565);
+    simple_macro!(3566);
+    simple_macro!(3567);
+    simple_macro!(3568);
+    simple_macro!(3569);
+    simple_macro!(3570);
+    simple_macro!(3571);
+    simple_macro!(3572);
+    simple_macro!(3573);
+    simple_macro!(3574);
+    simple_macro!(3575);
+    simple_macro!(3576);
+    simple_macro!(3577);
+    simple_macro!(3578);
+    simple_macro!(3579);
+    simple_macro!(3580);
+    simple_macro!(3581);
+    simple_macro!(3582);
+    simple_macro!(3583);
+    simple_macro!(3584);
+    simple_macro!(3585);
+    simple_macro!(3586);
+    simple_macro!(3587);
+    simple_macro!(3588);
+    simple_macro!(3589);
+    simple_macro!(3590);
+    simple_macro!(3591);
+    simple_macro!(3592);
+    simple_macro!(3593);
+    simple_macro!(3594);
+    simple_macro!(3595);
+    simple_macro!(3596);
+    simple_macro!(3597);
+    simple_macro!(3598);
+    simple_macro!(3599);
+    simple_macro!(3600);
+    simple_macro!(3601);
+    simple_macro!(3602);
+    simple_macro!(3603);
+    simple_macro!(3604);
+    simple_macro!(3605);
+    simple_macro!(3606);
+    simple_macro!(3607);
+    simple_macro!(3608);
+    simple_macro!(3609);
+    simple_macro!(3610);
+    simple_macro!(3611);
+    simple_macro!(3612);
+    simple_macro!(3613);
+    simple_macro!(3614);
+    simple_macro!(3615);
+    simple_macro!(3616);
+    simple_macro!(3617);
+    simple_macro!(3618);
+    simple_macro!(3619);
+    simple_macro!(3620);
+    simple_macro!(3621);
+    simple_macro!(3622);
+    simple_macro!(3623);
+    simple_macro!(3624);
+    simple_macro!(3625);
+    simple_macro!(3626);
+    simple_macro!(3627);
+    simple_macro!(3628);
+    simple_macro!(3629);
+    simple_macro!(3630);
+    simple_macro!(3631);
+    simple_macro!(3632);
+    simple_macro!(3633);
+    simple_macro!(3634);
+    simple_macro!(3635);
+    simple_macro!(3636);
+    simple_macro!(3637);
+    simple_macro!(3638);
+    simple_macro!(3639);
+    simple_macro!(3640);
+    simple_macro!(3641);
+    simple_macro!(3642);
+    simple_macro!(3643);
+    simple_macro!(3644);
+    simple_macro!(3645);
+    simple_macro!(3646);
+    simple_macro!(3647);
+    simple_macro!(3648);
+    simple_macro!(3649);
+    simple_macro!(3650);
+    simple_macro!(3651);
+    simple_macro!(3652);
+    simple_macro!(3653);
+    simple_macro!(3654);
+    simple_macro!(3655);
+    simple_macro!(3656);
+    simple_macro!(3657);
+    simple_macro!(3658);
+    simple_macro!(3659);
+    simple_macro!(3660);
+    simple_macro!(3661);
+    simple_macro!(3662);
+    simple_macro!(3663);
+    simple_macro!(3664);
+    simple_macro!(3665);
+    simple_macro!(3666);
+    simple_macro!(3667);
+    simple_macro!(3668);
+    simple_macro!(3669);
+    simple_macro!(3670);
+    simple_macro!(3671);
+    simple_macro!(3672);
+    simple_macro!(3673);
+    simple_macro!(3674);
+    simple_macro!(3675);
+    simple_macro!(3676);
+    simple_macro!(3677);
+    simple_macro!(3678);
+    simple_macro!(3679);
+    simple_macro!(3680);
+    simple_macro!(3681);
+    simple_macro!(3682);
+    simple_macro!(3683);
+    simple_macro!(3684);
+    simple_macro!(3685);
+    simple_macro!(3686);
+    simple_macro!(3687);
+    simple_macro!(3688);
+    simple_macro!(3689);
+    simple_macro!(3690);
+    simple_macro!(3691);
+    simple_macro!(3692);
+    simple_macro!(3693);
+    simple_macro!(3694);
+    simple_macro!(3695);
+    simple_macro!(3696);
+    simple_macro!(3697);
+    simple_macro!(3698);
+    simple_macro!(3699);
+    simple_macro!(3700);
+    simple_macro!(3701);
+    simple_macro!(3702);
+    simple_macro!(3703);
+    simple_macro!(3704);
+    simple_macro!(3705);
+    simple_macro!(3706);
+    simple_macro!(3707);
+    simple_macro!(3708);
+    simple_macro!(3709);
+    simple_macro!(3710);
+    simple_macro!(3711);
+    simple_macro!(3712);
+    simple_macro!(3713);
+    simple_macro!(3714);
+    simple_macro!(3715);
+    simple_macro!(3716);
+    simple_macro!(3717);
+    simple_macro!(3718);
+    simple_macro!(3719);
+    simple_macro!(3720);
+    simple_macro!(3721);
+    simple_macro!(3722);
+    simple_macro!(3723);
+    simple_macro!(3724);
+    simple_macro!(3725);
+    simple_macro!(3726);
+    simple_macro!(3727);
+    simple_macro!(3728);
+    simple_macro!(3729);
+    simple_macro!(3730);
+    simple_macro!(3731);
+    simple_macro!(3732);
+    simple_macro!(3733);
+    simple_macro!(3734);
+    simple_macro!(3735);
+    simple_macro!(3736);
+    simple_macro!(3737);
+    simple_macro!(3738);
+    simple_macro!(3739);
+    simple_macro!(3740);
+    simple_macro!(3741);
+    simple_macro!(3742);
+    simple_macro!(3743);
+    simple_macro!(3744);
+    simple_macro!(3745);
+    simple_macro!(3746);
+    simple_macro!(3747);
+    simple_macro!(3748);
+    simple_macro!(3749);
+    simple_macro!(3750);
+    simple_macro!(3751);
+    simple_macro!(3752);
+    simple_macro!(3753);
+    simple_macro!(3754);
+    simple_macro!(3755);
+    simple_macro!(3756);
+    simple_macro!(3757);
+    simple_macro!(3758);
+    simple_macro!(3759);
+    simple_macro!(3760);
+    simple_macro!(3761);
+    simple_macro!(3762);
+    simple_macro!(3763);
+    simple_macro!(3764);
+    simple_macro!(3765);
+    simple_macro!(3766);
+    simple_macro!(3767);
+    simple_macro!(3768);
+    simple_macro!(3769);
+    simple_macro!(3770);
+    simple_macro!(3771);
+    simple_macro!(3772);
+    simple_macro!(3773);
+    simple_macro!(3774);
+    simple_macro!(3775);
+    simple_macro!(3776);
+    simple_macro!(3777);
+    simple_macro!(3778);
+    simple_macro!(3779);
+    simple_macro!(3780);
+    simple_macro!(3781);
+    simple_macro!(3782);
+    simple_macro!(3783);
+    simple_macro!(3784);
+    simple_macro!(3785);
+    simple_macro!(3786);
+    simple_macro!(3787);
+    simple_macro!(3788);
+    simple_macro!(3789);
+    simple_macro!(3790);
+    simple_macro!(3791);
+    simple_macro!(3792);
+    simple_macro!(3793);
+    simple_macro!(3794);
+    simple_macro!(3795);
+    simple_macro!(3796);
+    simple_macro!(3797);
+    simple_macro!(3798);
+    simple_macro!(3799);
+    simple_macro!(3800);
+    simple_macro!(3801);
+    simple_macro!(3802);
+    simple_macro!(3803);
+    simple_macro!(3804);
+    simple_macro!(3805);
+    simple_macro!(3806);
+    simple_macro!(3807);
+    simple_macro!(3808);
+    simple_macro!(3809);
+    simple_macro!(3810);
+    simple_macro!(3811);
+    simple_macro!(3812);
+    simple_macro!(3813);
+    simple_macro!(3814);
+    simple_macro!(3815);
+    simple_macro!(3816);
+    simple_macro!(3817);
+    simple_macro!(3818);
+    simple_macro!(3819);
+    simple_macro!(3820);
+    simple_macro!(3821);
+    simple_macro!(3822);
+    simple_macro!(3823);
+    simple_macro!(3824);
+    simple_macro!(3825);
+    simple_macro!(3826);
+    simple_macro!(3827);
+    simple_macro!(3828);
+    simple_macro!(3829);
+    simple_macro!(3830);
+    simple_macro!(3831);
+    simple_macro!(3832);
+    simple_macro!(3833);
+    simple_macro!(3834);
+    simple_macro!(3835);
+    simple_macro!(3836);
+    simple_macro!(3837);
+    simple_macro!(3838);
+    simple_macro!(3839);
+    simple_macro!(3840);
+    simple_macro!(3841);
+    simple_macro!(3842);
+    simple_macro!(3843);
+    simple_macro!(3844);
+    simple_macro!(3845);
+    simple_macro!(3846);
+    simple_macro!(3847);
+    simple_macro!(3848);
+    simple_macro!(3849);
+    simple_macro!(3850);
+    simple_macro!(3851);
+    simple_macro!(3852);
+    simple_macro!(3853);
+    simple_macro!(3854);
+    simple_macro!(3855);
+    simple_macro!(3856);
+    simple_macro!(3857);
+    simple_macro!(3858);
+    simple_macro!(3859);
+    simple_macro!(3860);
+    simple_macro!(3861);
+    simple_macro!(3862);
+    simple_macro!(3863);
+    simple_macro!(3864);
+    simple_macro!(3865);
+    simple_macro!(3866);
+    simple_macro!(3867);
+    simple_macro!(3868);
+    simple_macro!(3869);
+    simple_macro!(3870);
+    simple_macro!(3871);
+    simple_macro!(3872);
+    simple_macro!(3873);
+    simple_macro!(3874);
+    simple_macro!(3875);
+    simple_macro!(3876);
+    simple_macro!(3877);
+    simple_macro!(3878);
+    simple_macro!(3879);
+    simple_macro!(3880);
+    simple_macro!(3881);
+    simple_macro!(3882);
+    simple_macro!(3883);
+    simple_macro!(3884);
+    simple_macro!(3885);
+    simple_macro!(3886);
+    simple_macro!(3887);
+    simple_macro!(3888);
+    simple_macro!(3889);
+    simple_macro!(3890);
+    simple_macro!(3891);
+    simple_macro!(3892);
+    simple_macro!(3893);
+    simple_macro!(3894);
+    simple_macro!(3895);
+    simple_macro!(3896);
+    simple_macro!(3897);
+    simple_macro!(3898);
+    simple_macro!(3899);
+    simple_macro!(3900);
+    simple_macro!(3901);
+    simple_macro!(3902);
+    simple_macro!(3903);
+    simple_macro!(3904);
+    simple_macro!(3905);
+    simple_macro!(3906);
+    simple_macro!(3907);
+    simple_macro!(3908);
+    simple_macro!(3909);
+    simple_macro!(3910);
+    simple_macro!(3911);
+    simple_macro!(3912);
+    simple_macro!(3913);
+    simple_macro!(3914);
+    simple_macro!(3915);
+    simple_macro!(3916);
+    simple_macro!(3917);
+    simple_macro!(3918);
+    simple_macro!(3919);
+    simple_macro!(3920);
+    simple_macro!(3921);
+    simple_macro!(3922);
+    simple_macro!(3923);
+    simple_macro!(3924);
+    simple_macro!(3925);
+    simple_macro!(3926);
+    simple_macro!(3927);
+    simple_macro!(3928);
+    simple_macro!(3929);
+    simple_macro!(3930);
+    simple_macro!(3931);
+    simple_macro!(3932);
+    simple_macro!(3933);
+    simple_macro!(3934);
+    simple_macro!(3935);
+    simple_macro!(3936);
+    simple_macro!(3937);
+    simple_macro!(3938);
+    simple_macro!(3939);
+    simple_macro!(3940);
+    simple_macro!(3941);
+    simple_macro!(3942);
+    simple_macro!(3943);
+    simple_macro!(3944);
+    simple_macro!(3945);
+    simple_macro!(3946);
+    simple_macro!(3947);
+    simple_macro!(3948);
+    simple_macro!(3949);
+    simple_macro!(3950);
+    simple_macro!(3951);
+    simple_macro!(3952);
+    simple_macro!(3953);
+    simple_macro!(3954);
+    simple_macro!(3955);
+    simple_macro!(3956);
+    simple_macro!(3957);
+    simple_macro!(3958);
+    simple_macro!(3959);
+    simple_macro!(3960);
+    simple_macro!(3961);
+    simple_macro!(3962);
+    simple_macro!(3963);
+    simple_macro!(3964);
+    simple_macro!(3965);
+    simple_macro!(3966);
+    simple_macro!(3967);
+    simple_macro!(3968);
+    simple_macro!(3969);
+    simple_macro!(3970);
+    simple_macro!(3971);
+    simple_macro!(3972);
+    simple_macro!(3973);
+    simple_macro!(3974);
+    simple_macro!(3975);
+    simple_macro!(3976);
+    simple_macro!(3977);
+    simple_macro!(3978);
+    simple_macro!(3979);
+    simple_macro!(3980);
+    simple_macro!(3981);
+    simple_macro!(3982);
+    simple_macro!(3983);
+    simple_macro!(3984);
+    simple_macro!(3985);
+    simple_macro!(3986);
+    simple_macro!(3987);
+    simple_macro!(3988);
+    simple_macro!(3989);
+    simple_macro!(3990);
+    simple_macro!(3991);
+    simple_macro!(3992);
+    simple_macro!(3993);
+    simple_macro!(3994);
+    simple_macro!(3995);
+    simple_macro!(3996);
+    simple_macro!(3997);
+    simple_macro!(3998);
+    simple_macro!(3999);
+    simple_macro!(4000);
+    simple_macro!(4001);
+    simple_macro!(4002);
+    simple_macro!(4003);
+    simple_macro!(4004);
+    simple_macro!(4005);
+    simple_macro!(4006);
+    simple_macro!(4007);
+    simple_macro!(4008);
+    simple_macro!(4009);
+    simple_macro!(4010);
+    simple_macro!(4011);
+    simple_macro!(4012);
+    simple_macro!(4013);
+    simple_macro!(4014);
+    simple_macro!(4015);
+    simple_macro!(4016);
+    simple_macro!(4017);
+    simple_macro!(4018);
+    simple_macro!(4019);
+    simple_macro!(4020);
+    simple_macro!(4021);
+    simple_macro!(4022);
+    simple_macro!(4023);
+    simple_macro!(4024);
+    simple_macro!(4025);
+    simple_macro!(4026);
+    simple_macro!(4027);
+    simple_macro!(4028);
+    simple_macro!(4029);
+    simple_macro!(4030);
+    simple_macro!(4031);
+    simple_macro!(4032);
+    simple_macro!(4033);
+    simple_macro!(4034);
+    simple_macro!(4035);
+    simple_macro!(4036);
+    simple_macro!(4037);
+    simple_macro!(4038);
+    simple_macro!(4039);
+    simple_macro!(4040);
+    simple_macro!(4041);
+    simple_macro!(4042);
+    simple_macro!(4043);
+    simple_macro!(4044);
+    simple_macro!(4045);
+    simple_macro!(4046);
+    simple_macro!(4047);
+    simple_macro!(4048);
+    simple_macro!(4049);
+    simple_macro!(4050);
+    simple_macro!(4051);
+    simple_macro!(4052);
+    simple_macro!(4053);
+    simple_macro!(4054);
+    simple_macro!(4055);
+    simple_macro!(4056);
+    simple_macro!(4057);
+    simple_macro!(4058);
+    simple_macro!(4059);
+    simple_macro!(4060);
+    simple_macro!(4061);
+    simple_macro!(4062);
+    simple_macro!(4063);
+    simple_macro!(4064);
+    simple_macro!(4065);
+    simple_macro!(4066);
+    simple_macro!(4067);
+    simple_macro!(4068);
+    simple_macro!(4069);
+    simple_macro!(4070);
+    simple_macro!(4071);
+    simple_macro!(4072);
+    simple_macro!(4073);
+    simple_macro!(4074);
+    simple_macro!(4075);
+    simple_macro!(4076);
+    simple_macro!(4077);
+    simple_macro!(4078);
+    simple_macro!(4079);
+    simple_macro!(4080);
+    simple_macro!(4081);
+    simple_macro!(4082);
+    simple_macro!(4083);
+    simple_macro!(4084);
+    simple_macro!(4085);
+    simple_macro!(4086);
+    simple_macro!(4087);
+    simple_macro!(4088);
+    simple_macro!(4089);
+    simple_macro!(4090);
+    simple_macro!(4091);
+    simple_macro!(4092);
+    simple_macro!(4093);
+    simple_macro!(4094);
+    simple_macro!(4095);
+    simple_macro!(4096);
+    simple_macro!(4097);
+}
+
+fn main() {
+    uncollapsed_debuginfo();
+}
diff --git a/tests/ui/diagnostic_namespace/deny_malformed_attribute.rs b/tests/ui/diagnostic_namespace/deny_malformed_attribute.rs
index 1d946a14aff..a46c856d38e 100644
--- a/tests/ui/diagnostic_namespace/deny_malformed_attribute.rs
+++ b/tests/ui/diagnostic_namespace/deny_malformed_attribute.rs
@@ -1,3 +1,5 @@
+//@ reference: attributes.diagnostic.namespace.unknown-invalid-syntax
+
 #![deny(unknown_or_malformed_diagnostic_attributes)]
 
 #[diagnostic::unknown_attribute]
diff --git a/tests/ui/diagnostic_namespace/deny_malformed_attribute.stderr b/tests/ui/diagnostic_namespace/deny_malformed_attribute.stderr
index a646d3613de..32be9db5317 100644
--- a/tests/ui/diagnostic_namespace/deny_malformed_attribute.stderr
+++ b/tests/ui/diagnostic_namespace/deny_malformed_attribute.stderr
@@ -1,11 +1,11 @@
 error: unknown diagnostic attribute
-  --> $DIR/deny_malformed_attribute.rs:3:15
+  --> $DIR/deny_malformed_attribute.rs:5:15
    |
 LL | #[diagnostic::unknown_attribute]
    |               ^^^^^^^^^^^^^^^^^
    |
 note: the lint level is defined here
-  --> $DIR/deny_malformed_attribute.rs:1:9
+  --> $DIR/deny_malformed_attribute.rs:3:9
    |
 LL | #![deny(unknown_or_malformed_diagnostic_attributes)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/diagnostic_namespace/malformed_foreign_on_unimplemented.rs b/tests/ui/diagnostic_namespace/malformed_foreign_on_unimplemented.rs
index 8b7467a17d0..b90dd0c7c94 100644
--- a/tests/ui/diagnostic_namespace/malformed_foreign_on_unimplemented.rs
+++ b/tests/ui/diagnostic_namespace/malformed_foreign_on_unimplemented.rs
@@ -1,5 +1,6 @@
 //@ edition:2021
 //@ aux-build:bad_on_unimplemented.rs
+//@ reference: attributes.diagnostic.on_unimplemented.syntax
 
 // Do not ICE when encountering a malformed `#[diagnostic::on_unimplemented]` annotation in a
 // dependency when incorrectly used (#124651).
diff --git a/tests/ui/diagnostic_namespace/malformed_foreign_on_unimplemented.stderr b/tests/ui/diagnostic_namespace/malformed_foreign_on_unimplemented.stderr
index c3e56550b70..f1258ad6b9a 100644
--- a/tests/ui/diagnostic_namespace/malformed_foreign_on_unimplemented.stderr
+++ b/tests/ui/diagnostic_namespace/malformed_foreign_on_unimplemented.stderr
@@ -1,5 +1,5 @@
 error[E0277]: the trait bound `(): bad_on_unimplemented::MissingAttr` is not satisfied
-  --> $DIR/malformed_foreign_on_unimplemented.rs:22:18
+  --> $DIR/malformed_foreign_on_unimplemented.rs:23:18
    |
 LL |     missing_attr(());
    |     ------------ ^^ the trait `bad_on_unimplemented::MissingAttr` is not implemented for `()`
@@ -7,13 +7,13 @@ LL |     missing_attr(());
    |     required by a bound introduced by this call
    |
 note: required by a bound in `missing_attr`
-  --> $DIR/malformed_foreign_on_unimplemented.rs:11:20
+  --> $DIR/malformed_foreign_on_unimplemented.rs:12:20
    |
 LL | fn missing_attr<T: MissingAttr>(_: T) {}
    |                    ^^^^^^^^^^^ required by this bound in `missing_attr`
 
 error[E0277]: the trait bound `(): bad_on_unimplemented::DuplicateAttr` is not satisfied
-  --> $DIR/malformed_foreign_on_unimplemented.rs:23:20
+  --> $DIR/malformed_foreign_on_unimplemented.rs:24:20
    |
 LL |     duplicate_attr(());
    |     -------------- ^^ a
@@ -22,13 +22,13 @@ LL |     duplicate_attr(());
    |
    = help: the trait `bad_on_unimplemented::DuplicateAttr` is not implemented for `()`
 note: required by a bound in `duplicate_attr`
-  --> $DIR/malformed_foreign_on_unimplemented.rs:12:22
+  --> $DIR/malformed_foreign_on_unimplemented.rs:13:22
    |
 LL | fn duplicate_attr<T: DuplicateAttr>(_: T) {}
    |                      ^^^^^^^^^^^^^ required by this bound in `duplicate_attr`
 
 error[E0277]: the trait bound `(): bad_on_unimplemented::NotMetaList` is not satisfied
-  --> $DIR/malformed_foreign_on_unimplemented.rs:24:19
+  --> $DIR/malformed_foreign_on_unimplemented.rs:25:19
    |
 LL |     not_meta_list(());
    |     ------------- ^^ the trait `bad_on_unimplemented::NotMetaList` is not implemented for `()`
@@ -36,13 +36,13 @@ LL |     not_meta_list(());
    |     required by a bound introduced by this call
    |
 note: required by a bound in `not_meta_list`
-  --> $DIR/malformed_foreign_on_unimplemented.rs:13:21
+  --> $DIR/malformed_foreign_on_unimplemented.rs:14:21
    |
 LL | fn not_meta_list<T: NotMetaList>(_: T) {}
    |                     ^^^^^^^^^^^ required by this bound in `not_meta_list`
 
 error[E0277]: the trait bound `(): bad_on_unimplemented::Empty` is not satisfied
-  --> $DIR/malformed_foreign_on_unimplemented.rs:25:11
+  --> $DIR/malformed_foreign_on_unimplemented.rs:26:11
    |
 LL |     empty(());
    |     ----- ^^ the trait `bad_on_unimplemented::Empty` is not implemented for `()`
@@ -50,13 +50,13 @@ LL |     empty(());
    |     required by a bound introduced by this call
    |
 note: required by a bound in `empty`
-  --> $DIR/malformed_foreign_on_unimplemented.rs:14:13
+  --> $DIR/malformed_foreign_on_unimplemented.rs:15:13
    |
 LL | fn empty<T: Empty>(_: T) {}
    |             ^^^^^ required by this bound in `empty`
 
 error[E0277]: the trait bound `(): bad_on_unimplemented::WrongDelim` is not satisfied
-  --> $DIR/malformed_foreign_on_unimplemented.rs:26:17
+  --> $DIR/malformed_foreign_on_unimplemented.rs:27:17
    |
 LL |     wrong_delim(());
    |     ----------- ^^ the trait `bad_on_unimplemented::WrongDelim` is not implemented for `()`
@@ -64,13 +64,13 @@ LL |     wrong_delim(());
    |     required by a bound introduced by this call
    |
 note: required by a bound in `wrong_delim`
-  --> $DIR/malformed_foreign_on_unimplemented.rs:15:19
+  --> $DIR/malformed_foreign_on_unimplemented.rs:16:19
    |
 LL | fn wrong_delim<T: WrongDelim>(_: T) {}
    |                   ^^^^^^^^^^ required by this bound in `wrong_delim`
 
 error[E0277]: the trait bound `(): bad_on_unimplemented::BadFormatter<()>` is not satisfied
-  --> $DIR/malformed_foreign_on_unimplemented.rs:27:19
+  --> $DIR/malformed_foreign_on_unimplemented.rs:28:19
    |
 LL |     bad_formatter(());
    |     ------------- ^^ ()
@@ -79,13 +79,13 @@ LL |     bad_formatter(());
    |
    = help: the trait `bad_on_unimplemented::BadFormatter<()>` is not implemented for `()`
 note: required by a bound in `bad_formatter`
-  --> $DIR/malformed_foreign_on_unimplemented.rs:16:21
+  --> $DIR/malformed_foreign_on_unimplemented.rs:17:21
    |
 LL | fn bad_formatter<T: BadFormatter<()>>(_: T) {}
    |                     ^^^^^^^^^^^^^^^^ required by this bound in `bad_formatter`
 
 error[E0277]: the trait bound `(): bad_on_unimplemented::NoImplicitArgs` is not satisfied
-  --> $DIR/malformed_foreign_on_unimplemented.rs:28:22
+  --> $DIR/malformed_foreign_on_unimplemented.rs:29:22
    |
 LL |     no_implicit_args(());
    |     ---------------- ^^ test {}
@@ -94,13 +94,13 @@ LL |     no_implicit_args(());
    |
    = help: the trait `bad_on_unimplemented::NoImplicitArgs` is not implemented for `()`
 note: required by a bound in `no_implicit_args`
-  --> $DIR/malformed_foreign_on_unimplemented.rs:17:24
+  --> $DIR/malformed_foreign_on_unimplemented.rs:18:24
    |
 LL | fn no_implicit_args<T: NoImplicitArgs>(_: T) {}
    |                        ^^^^^^^^^^^^^^ required by this bound in `no_implicit_args`
 
 error[E0277]: the trait bound `(): bad_on_unimplemented::MissingArg` is not satisfied
-  --> $DIR/malformed_foreign_on_unimplemented.rs:29:17
+  --> $DIR/malformed_foreign_on_unimplemented.rs:30:17
    |
 LL |     missing_arg(());
    |     ----------- ^^ {missing}
@@ -109,13 +109,13 @@ LL |     missing_arg(());
    |
    = help: the trait `bad_on_unimplemented::MissingArg` is not implemented for `()`
 note: required by a bound in `missing_arg`
-  --> $DIR/malformed_foreign_on_unimplemented.rs:18:19
+  --> $DIR/malformed_foreign_on_unimplemented.rs:19:19
    |
 LL | fn missing_arg<T: MissingArg>(_: T) {}
    |                   ^^^^^^^^^^ required by this bound in `missing_arg`
 
 error[E0277]: the trait bound `(): bad_on_unimplemented::BadArg` is not satisfied
-  --> $DIR/malformed_foreign_on_unimplemented.rs:30:13
+  --> $DIR/malformed_foreign_on_unimplemented.rs:31:13
    |
 LL |     bad_arg(());
    |     ------- ^^ {_}
@@ -124,7 +124,7 @@ LL |     bad_arg(());
    |
    = help: the trait `bad_on_unimplemented::BadArg` is not implemented for `()`
 note: required by a bound in `bad_arg`
-  --> $DIR/malformed_foreign_on_unimplemented.rs:19:15
+  --> $DIR/malformed_foreign_on_unimplemented.rs:20:15
    |
 LL | fn bad_arg<T: BadArg>(_: T) {}
    |               ^^^^^^ required by this bound in `bad_arg`
diff --git a/tests/ui/diagnostic_namespace/non_existing_attributes_accepted.rs b/tests/ui/diagnostic_namespace/non_existing_attributes_accepted.rs
index f6957b1448d..02c1352482c 100644
--- a/tests/ui/diagnostic_namespace/non_existing_attributes_accepted.rs
+++ b/tests/ui/diagnostic_namespace/non_existing_attributes_accepted.rs
@@ -1,4 +1,5 @@
 //@ check-pass
+//@ reference: attributes.diagnostic.namespace.unknown-invalid-syntax
 #[diagnostic::non_existing_attribute]
 //~^WARN unknown diagnostic attribute
 pub trait Bar {
diff --git a/tests/ui/diagnostic_namespace/non_existing_attributes_accepted.stderr b/tests/ui/diagnostic_namespace/non_existing_attributes_accepted.stderr
index c073ec9b103..753077b365e 100644
--- a/tests/ui/diagnostic_namespace/non_existing_attributes_accepted.stderr
+++ b/tests/ui/diagnostic_namespace/non_existing_attributes_accepted.stderr
@@ -1,5 +1,5 @@
 warning: unknown diagnostic attribute
-  --> $DIR/non_existing_attributes_accepted.rs:2:15
+  --> $DIR/non_existing_attributes_accepted.rs:3:15
    |
 LL | #[diagnostic::non_existing_attribute]
    |               ^^^^^^^^^^^^^^^^^^^^^^
@@ -7,7 +7,7 @@ LL | #[diagnostic::non_existing_attribute]
    = note: `#[warn(unknown_or_malformed_diagnostic_attributes)]` on by default
 
 warning: unknown diagnostic attribute
-  --> $DIR/non_existing_attributes_accepted.rs:7:15
+  --> $DIR/non_existing_attributes_accepted.rs:8:15
    |
 LL | #[diagnostic::non_existing_attribute(with_option = "foo")]
    |               ^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/broken_format.rs b/tests/ui/diagnostic_namespace/on_unimplemented/broken_format.rs
index 3ca58b28181..44f269eb967 100644
--- a/tests/ui/diagnostic_namespace/on_unimplemented/broken_format.rs
+++ b/tests/ui/diagnostic_namespace/on_unimplemented/broken_format.rs
@@ -1,3 +1,4 @@
+//@ reference: attributes.diagnostic.on_unimplemented.invalid-string
 #[diagnostic::on_unimplemented(message = "{{Test } thing")]
 //~^WARN unmatched `}` found
 //~|WARN unmatched `}` found
diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/broken_format.stderr b/tests/ui/diagnostic_namespace/on_unimplemented/broken_format.stderr
index b4ed06cb63d..7fd51c7527f 100644
--- a/tests/ui/diagnostic_namespace/on_unimplemented/broken_format.stderr
+++ b/tests/ui/diagnostic_namespace/on_unimplemented/broken_format.stderr
@@ -1,5 +1,5 @@
 warning: unmatched `}` found
-  --> $DIR/broken_format.rs:1:32
+  --> $DIR/broken_format.rs:2:32
    |
 LL | #[diagnostic::on_unimplemented(message = "{{Test } thing")]
    |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -7,7 +7,7 @@ LL | #[diagnostic::on_unimplemented(message = "{{Test } thing")]
    = note: `#[warn(unknown_or_malformed_diagnostic_attributes)]` on by default
 
 warning: positional format arguments are not allowed here
-  --> $DIR/broken_format.rs:6:32
+  --> $DIR/broken_format.rs:7:32
    |
 LL | #[diagnostic::on_unimplemented(message = "Test {}")]
    |                                ^^^^^^^^^^^^^^^^^^^
@@ -15,7 +15,7 @@ LL | #[diagnostic::on_unimplemented(message = "Test {}")]
    = help: only named format arguments with the name of one of the generic types are allowed in this context
 
 warning: positional format arguments are not allowed here
-  --> $DIR/broken_format.rs:11:32
+  --> $DIR/broken_format.rs:12:32
    |
 LL | #[diagnostic::on_unimplemented(message = "Test {1:}")]
    |                                ^^^^^^^^^^^^^^^^^^^^^
@@ -23,7 +23,7 @@ LL | #[diagnostic::on_unimplemented(message = "Test {1:}")]
    = help: only named format arguments with the name of one of the generic types are allowed in this context
 
 warning: invalid format specifier
-  --> $DIR/broken_format.rs:16:32
+  --> $DIR/broken_format.rs:17:32
    |
 LL | #[diagnostic::on_unimplemented(message = "Test {Self:123}")]
    |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -31,19 +31,19 @@ LL | #[diagnostic::on_unimplemented(message = "Test {Self:123}")]
    = help: no format specifier are supported in this position
 
 warning: expected `}`, found `!`
-  --> $DIR/broken_format.rs:21:32
+  --> $DIR/broken_format.rs:22:32
    |
 LL | #[diagnostic::on_unimplemented(message = "Test {Self:!}")]
    |                                ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unmatched `}` found
-  --> $DIR/broken_format.rs:21:32
+  --> $DIR/broken_format.rs:22:32
    |
 LL | #[diagnostic::on_unimplemented(message = "Test {Self:!}")]
    |                                ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unmatched `}` found
-  --> $DIR/broken_format.rs:1:32
+  --> $DIR/broken_format.rs:2:32
    |
 LL | #[diagnostic::on_unimplemented(message = "{{Test } thing")]
    |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -51,7 +51,7 @@ LL | #[diagnostic::on_unimplemented(message = "{{Test } thing")]
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error[E0277]: {{Test } thing
-  --> $DIR/broken_format.rs:35:13
+  --> $DIR/broken_format.rs:36:13
    |
 LL |     check_1(());
    |     ------- ^^ the trait `ImportantTrait1` is not implemented for `()`
@@ -59,18 +59,18 @@ LL |     check_1(());
    |     required by a bound introduced by this call
    |
 help: this trait has no implementations, consider adding one
-  --> $DIR/broken_format.rs:4:1
+  --> $DIR/broken_format.rs:5:1
    |
 LL | trait ImportantTrait1 {}
    | ^^^^^^^^^^^^^^^^^^^^^
 note: required by a bound in `check_1`
-  --> $DIR/broken_format.rs:28:20
+  --> $DIR/broken_format.rs:29:20
    |
 LL | fn check_1(_: impl ImportantTrait1) {}
    |                    ^^^^^^^^^^^^^^^ required by this bound in `check_1`
 
 warning: positional format arguments are not allowed here
-  --> $DIR/broken_format.rs:6:32
+  --> $DIR/broken_format.rs:7:32
    |
 LL | #[diagnostic::on_unimplemented(message = "Test {}")]
    |                                ^^^^^^^^^^^^^^^^^^^
@@ -79,7 +79,7 @@ LL | #[diagnostic::on_unimplemented(message = "Test {}")]
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error[E0277]: Test {}
-  --> $DIR/broken_format.rs:37:13
+  --> $DIR/broken_format.rs:38:13
    |
 LL |     check_2(());
    |     ------- ^^ the trait `ImportantTrait2` is not implemented for `()`
@@ -87,18 +87,18 @@ LL |     check_2(());
    |     required by a bound introduced by this call
    |
 help: this trait has no implementations, consider adding one
-  --> $DIR/broken_format.rs:9:1
+  --> $DIR/broken_format.rs:10:1
    |
 LL | trait ImportantTrait2 {}
    | ^^^^^^^^^^^^^^^^^^^^^
 note: required by a bound in `check_2`
-  --> $DIR/broken_format.rs:29:20
+  --> $DIR/broken_format.rs:30:20
    |
 LL | fn check_2(_: impl ImportantTrait2) {}
    |                    ^^^^^^^^^^^^^^^ required by this bound in `check_2`
 
 warning: positional format arguments are not allowed here
-  --> $DIR/broken_format.rs:11:32
+  --> $DIR/broken_format.rs:12:32
    |
 LL | #[diagnostic::on_unimplemented(message = "Test {1:}")]
    |                                ^^^^^^^^^^^^^^^^^^^^^
@@ -107,7 +107,7 @@ LL | #[diagnostic::on_unimplemented(message = "Test {1:}")]
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error[E0277]: Test {1}
-  --> $DIR/broken_format.rs:39:13
+  --> $DIR/broken_format.rs:40:13
    |
 LL |     check_3(());
    |     ------- ^^ the trait `ImportantTrait3` is not implemented for `()`
@@ -115,18 +115,18 @@ LL |     check_3(());
    |     required by a bound introduced by this call
    |
 help: this trait has no implementations, consider adding one
-  --> $DIR/broken_format.rs:14:1
+  --> $DIR/broken_format.rs:15:1
    |
 LL | trait ImportantTrait3 {}
    | ^^^^^^^^^^^^^^^^^^^^^
 note: required by a bound in `check_3`
-  --> $DIR/broken_format.rs:30:20
+  --> $DIR/broken_format.rs:31:20
    |
 LL | fn check_3(_: impl ImportantTrait3) {}
    |                    ^^^^^^^^^^^^^^^ required by this bound in `check_3`
 
 warning: invalid format specifier
-  --> $DIR/broken_format.rs:16:32
+  --> $DIR/broken_format.rs:17:32
    |
 LL | #[diagnostic::on_unimplemented(message = "Test {Self:123}")]
    |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -135,7 +135,7 @@ LL | #[diagnostic::on_unimplemented(message = "Test {Self:123}")]
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error[E0277]: Test ()
-  --> $DIR/broken_format.rs:41:13
+  --> $DIR/broken_format.rs:42:13
    |
 LL |     check_4(());
    |     ------- ^^ the trait `ImportantTrait4` is not implemented for `()`
@@ -143,18 +143,18 @@ LL |     check_4(());
    |     required by a bound introduced by this call
    |
 help: this trait has no implementations, consider adding one
-  --> $DIR/broken_format.rs:19:1
+  --> $DIR/broken_format.rs:20:1
    |
 LL | trait ImportantTrait4 {}
    | ^^^^^^^^^^^^^^^^^^^^^
 note: required by a bound in `check_4`
-  --> $DIR/broken_format.rs:31:20
+  --> $DIR/broken_format.rs:32:20
    |
 LL | fn check_4(_: impl ImportantTrait4) {}
    |                    ^^^^^^^^^^^^^^^ required by this bound in `check_4`
 
 warning: expected `}`, found `!`
-  --> $DIR/broken_format.rs:21:32
+  --> $DIR/broken_format.rs:22:32
    |
 LL | #[diagnostic::on_unimplemented(message = "Test {Self:!}")]
    |                                ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -162,7 +162,7 @@ LL | #[diagnostic::on_unimplemented(message = "Test {Self:!}")]
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 warning: unmatched `}` found
-  --> $DIR/broken_format.rs:21:32
+  --> $DIR/broken_format.rs:22:32
    |
 LL | #[diagnostic::on_unimplemented(message = "Test {Self:!}")]
    |                                ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -170,7 +170,7 @@ LL | #[diagnostic::on_unimplemented(message = "Test {Self:!}")]
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error[E0277]: Test {Self:!}
-  --> $DIR/broken_format.rs:43:13
+  --> $DIR/broken_format.rs:44:13
    |
 LL |     check_5(());
    |     ------- ^^ the trait `ImportantTrait5` is not implemented for `()`
@@ -178,12 +178,12 @@ LL |     check_5(());
    |     required by a bound introduced by this call
    |
 help: this trait has no implementations, consider adding one
-  --> $DIR/broken_format.rs:26:1
+  --> $DIR/broken_format.rs:27:1
    |
 LL | trait ImportantTrait5 {}
    | ^^^^^^^^^^^^^^^^^^^^^
 note: required by a bound in `check_5`
-  --> $DIR/broken_format.rs:32:20
+  --> $DIR/broken_format.rs:33:20
    |
 LL | fn check_5(_: impl ImportantTrait5) {}
    |                    ^^^^^^^^^^^^^^^ required by this bound in `check_5`
diff --git a/tests/ui/traits/custom-on-unimplemented-diagnostic.rs b/tests/ui/diagnostic_namespace/on_unimplemented/custom-on-unimplemented-diagnostic.rs
index d7e257ef3bb..1173c939038 100644
--- a/tests/ui/traits/custom-on-unimplemented-diagnostic.rs
+++ b/tests/ui/diagnostic_namespace/on_unimplemented/custom-on-unimplemented-diagnostic.rs
@@ -1,3 +1,5 @@
+//@ reference: attributes.diagnostic.on_unimplemented.intro
+//@ reference: attributes.diagnostic.on_unimplemented.keys
 #[diagnostic::on_unimplemented(message = "my message", label = "my label", note = "my note")]
 pub trait ProviderLt {}
 
diff --git a/tests/ui/traits/custom-on-unimplemented-diagnostic.stderr b/tests/ui/diagnostic_namespace/on_unimplemented/custom-on-unimplemented-diagnostic.stderr
index f9788360d06..4c1838620b3 100644
--- a/tests/ui/traits/custom-on-unimplemented-diagnostic.stderr
+++ b/tests/ui/diagnostic_namespace/on_unimplemented/custom-on-unimplemented-diagnostic.stderr
@@ -1,5 +1,5 @@
 error[E0599]: my message
-  --> $DIR/custom-on-unimplemented-diagnostic.rs:15:7
+  --> $DIR/custom-on-unimplemented-diagnostic.rs:17:7
    |
 LL | struct B;
    | -------- method `request` not found for this struct because it doesn't satisfy `B: ProviderExt` or `B: ProviderLt`
@@ -8,7 +8,7 @@ LL |     B.request();
    |       ^^^^^^^ my label
    |
 note: trait bound `B: ProviderLt` was not satisfied
-  --> $DIR/custom-on-unimplemented-diagnostic.rs:10:18
+  --> $DIR/custom-on-unimplemented-diagnostic.rs:12:18
    |
 LL | impl<T: ?Sized + ProviderLt> ProviderExt for T {}
    |                  ^^^^^^^^^^  -----------     -
@@ -16,13 +16,13 @@ LL | impl<T: ?Sized + ProviderLt> ProviderExt for T {}
    |                  unsatisfied trait bound introduced here
    = note: my note
 note: the trait `ProviderLt` must be implemented
-  --> $DIR/custom-on-unimplemented-diagnostic.rs:2:1
+  --> $DIR/custom-on-unimplemented-diagnostic.rs:4:1
    |
 LL | pub trait ProviderLt {}
    | ^^^^^^^^^^^^^^^^^^^^
    = help: items from traits can only be used if the trait is implemented and in scope
 note: `ProviderExt` defines an item `request`, perhaps you need to implement it
-  --> $DIR/custom-on-unimplemented-diagnostic.rs:4:1
+  --> $DIR/custom-on-unimplemented-diagnostic.rs:6:1
    |
 LL | pub trait ProviderExt {
    | ^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/do_not_accept_options_of_the_internal_rustc_attribute.rs b/tests/ui/diagnostic_namespace/on_unimplemented/do_not_accept_options_of_the_internal_rustc_attribute.rs
index 30a85ff2199..b76b550fcb2 100644
--- a/tests/ui/diagnostic_namespace/on_unimplemented/do_not_accept_options_of_the_internal_rustc_attribute.rs
+++ b/tests/ui/diagnostic_namespace/on_unimplemented/do_not_accept_options_of_the_internal_rustc_attribute.rs
@@ -1,3 +1,7 @@
+//@ reference: attributes.diagnostic.on_unimplemented.format-parameters
+//@ reference: attributes.diagnostic.on_unimplemented.keys
+//@ reference: attributes.diagnostic.on_unimplemented.syntax
+//@ reference: attributes.diagnostic.on_unimplemented.invalid-formats
 #[diagnostic::on_unimplemented(
     on(_Self = "&str"),
     //~^WARN malformed `on_unimplemented` attribute
diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/do_not_accept_options_of_the_internal_rustc_attribute.stderr b/tests/ui/diagnostic_namespace/on_unimplemented/do_not_accept_options_of_the_internal_rustc_attribute.stderr
index e34b917f67e..bb455d92940 100644
--- a/tests/ui/diagnostic_namespace/on_unimplemented/do_not_accept_options_of_the_internal_rustc_attribute.stderr
+++ b/tests/ui/diagnostic_namespace/on_unimplemented/do_not_accept_options_of_the_internal_rustc_attribute.stderr
@@ -1,5 +1,5 @@
 warning: `#[diagnostic::on_unimplemented]` can only be applied to trait definitions
-  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:22:1
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:26:1
    |
 LL | #[diagnostic::on_unimplemented(message = "Not allowed to apply it on a impl")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -7,7 +7,7 @@ LL | #[diagnostic::on_unimplemented(message = "Not allowed to apply it on a impl
    = note: `#[warn(unknown_or_malformed_diagnostic_attributes)]` on by default
 
 warning: malformed `on_unimplemented` attribute
-  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:2:5
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:6:5
    |
 LL |     on(_Self = "&str"),
    |     ^^^^^^^^^^^^^^^^^^ invalid option found here
@@ -15,7 +15,7 @@ LL |     on(_Self = "&str"),
    = help: only `message`, `note` and `label` are allowed as options
 
 warning: malformed `on_unimplemented` attribute
-  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:8:5
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:12:5
    |
 LL |     parent_label = "in this scope",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid option found here
@@ -23,7 +23,7 @@ LL |     parent_label = "in this scope",
    = help: only `message`, `note` and `label` are allowed as options
 
 warning: malformed `on_unimplemented` attribute
-  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:11:5
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:15:5
    |
 LL |     append_const_msg
    |     ^^^^^^^^^^^^^^^^ invalid option found here
@@ -31,7 +31,7 @@ LL |     append_const_msg
    = help: only `message`, `note` and `label` are allowed as options
 
 warning: malformed `on_unimplemented` attribute
-  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:17:32
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:21:32
    |
 LL | #[diagnostic::on_unimplemented = "Message"]
    |                                ^^^^^^^^^^^ invalid option found here
@@ -39,7 +39,7 @@ LL | #[diagnostic::on_unimplemented = "Message"]
    = help: only `message`, `note` and `label` are allowed as options
 
 warning: there is no parameter `from_desugaring` on trait `Baz`
-  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:29:5
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:33:5
    |
 LL |     message = "{from_desugaring}{direct}{cause}{integral}{integer}",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -47,7 +47,7 @@ LL |     message = "{from_desugaring}{direct}{cause}{integral}{integer}",
    = help: expect either a generic argument name or `{Self}` as format argument
 
 warning: there is no parameter `direct` on trait `Baz`
-  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:29:5
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:33:5
    |
 LL |     message = "{from_desugaring}{direct}{cause}{integral}{integer}",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -55,7 +55,7 @@ LL |     message = "{from_desugaring}{direct}{cause}{integral}{integer}",
    = help: expect either a generic argument name or `{Self}` as format argument
 
 warning: there is no parameter `cause` on trait `Baz`
-  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:29:5
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:33:5
    |
 LL |     message = "{from_desugaring}{direct}{cause}{integral}{integer}",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -63,7 +63,7 @@ LL |     message = "{from_desugaring}{direct}{cause}{integral}{integer}",
    = help: expect either a generic argument name or `{Self}` as format argument
 
 warning: there is no parameter `integral` on trait `Baz`
-  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:29:5
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:33:5
    |
 LL |     message = "{from_desugaring}{direct}{cause}{integral}{integer}",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -71,7 +71,7 @@ LL |     message = "{from_desugaring}{direct}{cause}{integral}{integer}",
    = help: expect either a generic argument name or `{Self}` as format argument
 
 warning: there is no parameter `integer` on trait `Baz`
-  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:29:5
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:33:5
    |
 LL |     message = "{from_desugaring}{direct}{cause}{integral}{integer}",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -79,7 +79,7 @@ LL |     message = "{from_desugaring}{direct}{cause}{integral}{integer}",
    = help: expect either a generic argument name or `{Self}` as format argument
 
 warning: there is no parameter `float` on trait `Baz`
-  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:40:5
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:44:5
    |
 LL |     label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -87,7 +87,7 @@ LL |     label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
    = help: expect either a generic argument name or `{Self}` as format argument
 
 warning: there is no parameter `_Self` on trait `Baz`
-  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:40:5
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:44:5
    |
 LL |     label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -95,7 +95,7 @@ LL |     label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
    = help: expect either a generic argument name or `{Self}` as format argument
 
 warning: there is no parameter `crate_local` on trait `Baz`
-  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:40:5
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:44:5
    |
 LL |     label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -103,7 +103,7 @@ LL |     label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
    = help: expect either a generic argument name or `{Self}` as format argument
 
 warning: there is no parameter `Trait` on trait `Baz`
-  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:40:5
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:44:5
    |
 LL |     label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -111,7 +111,7 @@ LL |     label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
    = help: expect either a generic argument name or `{Self}` as format argument
 
 warning: there is no parameter `ItemContext` on trait `Baz`
-  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:40:5
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:44:5
    |
 LL |     label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -119,7 +119,7 @@ LL |     label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
    = help: expect either a generic argument name or `{Self}` as format argument
 
 warning: malformed `on_unimplemented` attribute
-  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:2:5
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:6:5
    |
 LL |     on(_Self = "&str"),
    |     ^^^^^^^^^^^^^^^^^^ invalid option found here
@@ -128,7 +128,7 @@ LL |     on(_Self = "&str"),
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 warning: malformed `on_unimplemented` attribute
-  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:8:5
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:12:5
    |
 LL |     parent_label = "in this scope",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid option found here
@@ -137,7 +137,7 @@ LL |     parent_label = "in this scope",
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 warning: malformed `on_unimplemented` attribute
-  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:11:5
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:15:5
    |
 LL |     append_const_msg
    |     ^^^^^^^^^^^^^^^^ invalid option found here
@@ -146,7 +146,7 @@ LL |     append_const_msg
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error[E0277]: trait has `()` and `i32` as params
-  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:59:15
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:63:15
    |
 LL |     takes_foo(());
    |     --------- ^^ trait has `()` and `i32` as params
@@ -156,18 +156,18 @@ LL |     takes_foo(());
    = help: the trait `Foo<i32>` is not implemented for `()`
    = note: trait has `()` and `i32` as params
 help: this trait has no implementations, consider adding one
-  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:15:1
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:19:1
    |
 LL | trait Foo<T> {}
    | ^^^^^^^^^^^^
 note: required by a bound in `takes_foo`
-  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:54:22
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:58:22
    |
 LL | fn takes_foo(_: impl Foo<i32>) {}
    |                      ^^^^^^^^ required by this bound in `takes_foo`
 
 warning: malformed `on_unimplemented` attribute
-  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:17:32
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:21:32
    |
 LL | #[diagnostic::on_unimplemented = "Message"]
    |                                ^^^^^^^^^^^ invalid option found here
@@ -176,7 +176,7 @@ LL | #[diagnostic::on_unimplemented = "Message"]
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error[E0277]: the trait bound `(): Bar` is not satisfied
-  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:61:15
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:65:15
    |
 LL |     takes_bar(());
    |     --------- ^^ the trait `Bar` is not implemented for `()`
@@ -185,13 +185,13 @@ LL |     takes_bar(());
    |
    = help: the trait `Bar` is implemented for `i32`
 note: required by a bound in `takes_bar`
-  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:55:22
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:59:22
    |
 LL | fn takes_bar(_: impl Bar) {}
    |                      ^^^ required by this bound in `takes_bar`
 
 warning: there is no parameter `from_desugaring` on trait `Baz`
-  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:29:5
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:33:5
    |
 LL |     message = "{from_desugaring}{direct}{cause}{integral}{integer}",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -200,7 +200,7 @@ LL |     message = "{from_desugaring}{direct}{cause}{integral}{integer}",
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 warning: there is no parameter `direct` on trait `Baz`
-  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:29:5
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:33:5
    |
 LL |     message = "{from_desugaring}{direct}{cause}{integral}{integer}",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -209,7 +209,7 @@ LL |     message = "{from_desugaring}{direct}{cause}{integral}{integer}",
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 warning: there is no parameter `cause` on trait `Baz`
-  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:29:5
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:33:5
    |
 LL |     message = "{from_desugaring}{direct}{cause}{integral}{integer}",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -218,7 +218,7 @@ LL |     message = "{from_desugaring}{direct}{cause}{integral}{integer}",
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 warning: there is no parameter `integral` on trait `Baz`
-  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:29:5
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:33:5
    |
 LL |     message = "{from_desugaring}{direct}{cause}{integral}{integer}",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -227,7 +227,7 @@ LL |     message = "{from_desugaring}{direct}{cause}{integral}{integer}",
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 warning: there is no parameter `integer` on trait `Baz`
-  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:29:5
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:33:5
    |
 LL |     message = "{from_desugaring}{direct}{cause}{integral}{integer}",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -236,7 +236,7 @@ LL |     message = "{from_desugaring}{direct}{cause}{integral}{integer}",
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 warning: there is no parameter `float` on trait `Baz`
-  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:40:5
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:44:5
    |
 LL |     label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -245,7 +245,7 @@ LL |     label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 warning: there is no parameter `_Self` on trait `Baz`
-  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:40:5
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:44:5
    |
 LL |     label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -254,7 +254,7 @@ LL |     label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 warning: there is no parameter `crate_local` on trait `Baz`
-  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:40:5
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:44:5
    |
 LL |     label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -263,7 +263,7 @@ LL |     label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 warning: there is no parameter `Trait` on trait `Baz`
-  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:40:5
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:44:5
    |
 LL |     label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -272,7 +272,7 @@ LL |     label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 warning: there is no parameter `ItemContext` on trait `Baz`
-  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:40:5
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:44:5
    |
 LL |     label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -281,7 +281,7 @@ LL |     label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error[E0277]: {from_desugaring}{direct}{cause}{integral}{integer}
-  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:63:15
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:67:15
    |
 LL |     takes_baz(());
    |     --------- ^^ {float}{_Self}{crate_local}{Trait}{ItemContext}
@@ -290,12 +290,12 @@ LL |     takes_baz(());
    |
    = help: the trait `Baz` is not implemented for `()`
 help: this trait has no implementations, consider adding one
-  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:52:1
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:56:1
    |
 LL | trait Baz {}
    | ^^^^^^^^^
 note: required by a bound in `takes_baz`
-  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:56:22
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:60:22
    |
 LL | fn takes_baz(_: impl Baz) {}
    |                      ^^^ required by this bound in `takes_baz`
diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/do_not_fail_parsing_on_invalid_options_1.rs b/tests/ui/diagnostic_namespace/on_unimplemented/do_not_fail_parsing_on_invalid_options_1.rs
index b4234066bb1..8328c10d2a0 100644
--- a/tests/ui/diagnostic_namespace/on_unimplemented/do_not_fail_parsing_on_invalid_options_1.rs
+++ b/tests/ui/diagnostic_namespace/on_unimplemented/do_not_fail_parsing_on_invalid_options_1.rs
@@ -1,3 +1,5 @@
+//@ reference: attributes.diagnostic.on_unimplemented.syntax
+//@ reference: attributes.diagnostic.on_unimplemented.unknown-keys
 #[diagnostic::on_unimplemented(unsupported = "foo")]
 //~^WARN malformed `on_unimplemented` attribute
 //~|WARN malformed `on_unimplemented` attribute
diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/do_not_fail_parsing_on_invalid_options_1.stderr b/tests/ui/diagnostic_namespace/on_unimplemented/do_not_fail_parsing_on_invalid_options_1.stderr
index dc0c1948236..11263580b15 100644
--- a/tests/ui/diagnostic_namespace/on_unimplemented/do_not_fail_parsing_on_invalid_options_1.stderr
+++ b/tests/ui/diagnostic_namespace/on_unimplemented/do_not_fail_parsing_on_invalid_options_1.stderr
@@ -1,5 +1,5 @@
 warning: `#[diagnostic::on_unimplemented]` can only be applied to trait definitions
-  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:6:1
+  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:8:1
    |
 LL | #[diagnostic::on_unimplemented(message = "Baz")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -7,7 +7,7 @@ LL | #[diagnostic::on_unimplemented(message = "Baz")]
    = note: `#[warn(unknown_or_malformed_diagnostic_attributes)]` on by default
 
 warning: malformed `on_unimplemented` attribute
-  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:1:32
+  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:3:32
    |
 LL | #[diagnostic::on_unimplemented(unsupported = "foo")]
    |                                ^^^^^^^^^^^^^^^^^^^ invalid option found here
@@ -15,7 +15,7 @@ LL | #[diagnostic::on_unimplemented(unsupported = "foo")]
    = help: only `message`, `note` and `label` are allowed as options
 
 warning: malformed `on_unimplemented` attribute
-  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:10:50
+  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:12:50
    |
 LL | #[diagnostic::on_unimplemented(message = "Boom", unsupported = "Bar")]
    |                                                  ^^^^^^^^^^^^^^^^^^^ invalid option found here
@@ -23,7 +23,7 @@ LL | #[diagnostic::on_unimplemented(message = "Boom", unsupported = "Bar")]
    = help: only `message`, `note` and `label` are allowed as options
 
 warning: malformed `on_unimplemented` attribute
-  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:15:50
+  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:17:50
    |
 LL | #[diagnostic::on_unimplemented(message = "Boom", on(_Self = "i32", message = "whatever"))]
    |                                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid option found here
@@ -31,7 +31,7 @@ LL | #[diagnostic::on_unimplemented(message = "Boom", on(_Self = "i32", message
    = help: only `message`, `note` and `label` are allowed as options
 
 warning: malformed `on_unimplemented` attribute
-  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:20:32
+  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:22:32
    |
 LL | #[diagnostic::on_unimplemented = "boom"]
    |                                ^^^^^^^^ invalid option found here
@@ -39,7 +39,7 @@ LL | #[diagnostic::on_unimplemented = "boom"]
    = help: only `message`, `note` and `label` are allowed as options
 
 warning: missing options for `on_unimplemented` attribute
-  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:24:1
+  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:26:1
    |
 LL | #[diagnostic::on_unimplemented]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -47,7 +47,7 @@ LL | #[diagnostic::on_unimplemented]
    = help: at least one of the `message`, `note` and `label` options are expected
 
 warning: there is no parameter `DoesNotExist` on trait `Test`
-  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:29:32
+  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:31:32
    |
 LL | #[diagnostic::on_unimplemented(message = "{DoesNotExist}")]
    |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -55,7 +55,7 @@ LL | #[diagnostic::on_unimplemented(message = "{DoesNotExist}")]
    = help: expect either a generic argument name or `{Self}` as format argument
 
 warning: malformed `on_unimplemented` attribute
-  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:1:32
+  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:3:32
    |
 LL | #[diagnostic::on_unimplemented(unsupported = "foo")]
    |                                ^^^^^^^^^^^^^^^^^^^ invalid option found here
@@ -64,7 +64,7 @@ LL | #[diagnostic::on_unimplemented(unsupported = "foo")]
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error[E0277]: the trait bound `i32: Foo` is not satisfied
-  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:41:14
+  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:43:14
    |
 LL |     take_foo(1_i32);
    |     -------- ^^^^^ the trait `Foo` is not implemented for `i32`
@@ -72,18 +72,18 @@ LL |     take_foo(1_i32);
    |     required by a bound introduced by this call
    |
 help: this trait has no implementations, consider adding one
-  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:4:1
+  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:6:1
    |
 LL | trait Foo {}
    | ^^^^^^^^^
 note: required by a bound in `take_foo`
-  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:34:21
+  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:36:21
    |
 LL | fn take_foo(_: impl Foo) {}
    |                     ^^^ required by this bound in `take_foo`
 
 warning: malformed `on_unimplemented` attribute
-  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:10:50
+  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:12:50
    |
 LL | #[diagnostic::on_unimplemented(message = "Boom", unsupported = "Bar")]
    |                                                  ^^^^^^^^^^^^^^^^^^^ invalid option found here
@@ -92,7 +92,7 @@ LL | #[diagnostic::on_unimplemented(message = "Boom", unsupported = "Bar")]
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error[E0277]: Boom
-  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:43:14
+  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:45:14
    |
 LL |     take_baz(1_i32);
    |     -------- ^^^^^ the trait `Baz` is not implemented for `i32`
@@ -100,18 +100,18 @@ LL |     take_baz(1_i32);
    |     required by a bound introduced by this call
    |
 help: this trait has no implementations, consider adding one
-  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:13:1
+  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:15:1
    |
 LL | trait Baz {}
    | ^^^^^^^^^
 note: required by a bound in `take_baz`
-  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:35:21
+  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:37:21
    |
 LL | fn take_baz(_: impl Baz) {}
    |                     ^^^ required by this bound in `take_baz`
 
 warning: malformed `on_unimplemented` attribute
-  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:15:50
+  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:17:50
    |
 LL | #[diagnostic::on_unimplemented(message = "Boom", on(_Self = "i32", message = "whatever"))]
    |                                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid option found here
@@ -120,7 +120,7 @@ LL | #[diagnostic::on_unimplemented(message = "Boom", on(_Self = "i32", message
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error[E0277]: Boom
-  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:45:15
+  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:47:15
    |
 LL |     take_boom(1_i32);
    |     --------- ^^^^^ the trait `Boom` is not implemented for `i32`
@@ -128,18 +128,18 @@ LL |     take_boom(1_i32);
    |     required by a bound introduced by this call
    |
 help: this trait has no implementations, consider adding one
-  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:18:1
+  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:20:1
    |
 LL | trait Boom {}
    | ^^^^^^^^^^
 note: required by a bound in `take_boom`
-  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:36:22
+  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:38:22
    |
 LL | fn take_boom(_: impl Boom) {}
    |                      ^^^^ required by this bound in `take_boom`
 
 warning: missing options for `on_unimplemented` attribute
-  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:24:1
+  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:26:1
    |
 LL | #[diagnostic::on_unimplemented]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -148,7 +148,7 @@ LL | #[diagnostic::on_unimplemented]
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error[E0277]: the trait bound `i32: Whatever` is not satisfied
-  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:47:19
+  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:49:19
    |
 LL |     take_whatever(1_i32);
    |     ------------- ^^^^^ the trait `Whatever` is not implemented for `i32`
@@ -156,18 +156,18 @@ LL |     take_whatever(1_i32);
    |     required by a bound introduced by this call
    |
 help: this trait has no implementations, consider adding one
-  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:27:1
+  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:29:1
    |
 LL | trait Whatever {}
    | ^^^^^^^^^^^^^^
 note: required by a bound in `take_whatever`
-  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:37:26
+  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:39:26
    |
 LL | fn take_whatever(_: impl Whatever) {}
    |                          ^^^^^^^^ required by this bound in `take_whatever`
 
 warning: there is no parameter `DoesNotExist` on trait `Test`
-  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:29:32
+  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:31:32
    |
 LL | #[diagnostic::on_unimplemented(message = "{DoesNotExist}")]
    |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -176,7 +176,7 @@ LL | #[diagnostic::on_unimplemented(message = "{DoesNotExist}")]
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error[E0277]: {DoesNotExist}
-  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:49:15
+  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:51:15
    |
 LL |     take_test(());
    |     --------- ^^ the trait `Test` is not implemented for `()`
@@ -184,12 +184,12 @@ LL |     take_test(());
    |     required by a bound introduced by this call
    |
 help: this trait has no implementations, consider adding one
-  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:32:1
+  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:34:1
    |
 LL | trait Test {}
    | ^^^^^^^^^^
 note: required by a bound in `take_test`
-  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:38:22
+  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:40:22
    |
 LL | fn take_test(_: impl Test) {}
    |                      ^^^^ required by this bound in `take_test`
diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/error_is_shown_in_downstream_crates.rs b/tests/ui/diagnostic_namespace/on_unimplemented/error_is_shown_in_downstream_crates.rs
index 7eaff73dca1..dff209d4761 100644
--- a/tests/ui/diagnostic_namespace/on_unimplemented/error_is_shown_in_downstream_crates.rs
+++ b/tests/ui/diagnostic_namespace/on_unimplemented/error_is_shown_in_downstream_crates.rs
@@ -1,4 +1,5 @@
 //@ aux-build:other.rs
+//@ reference: attributes.diagnostic.on_unimplemented.intro
 
 extern crate other;
 
diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/error_is_shown_in_downstream_crates.stderr b/tests/ui/diagnostic_namespace/on_unimplemented/error_is_shown_in_downstream_crates.stderr
index a9968538d0d..c0dd6d9628a 100644
--- a/tests/ui/diagnostic_namespace/on_unimplemented/error_is_shown_in_downstream_crates.stderr
+++ b/tests/ui/diagnostic_namespace/on_unimplemented/error_is_shown_in_downstream_crates.stderr
@@ -1,5 +1,5 @@
 error[E0277]: Message
-  --> $DIR/error_is_shown_in_downstream_crates.rs:10:14
+  --> $DIR/error_is_shown_in_downstream_crates.rs:11:14
    |
 LL |     take_foo(());
    |     -------- ^^ label
@@ -9,7 +9,7 @@ LL |     take_foo(());
    = help: the trait `Foo` is not implemented for `()`
    = note: Note
 note: required by a bound in `take_foo`
-  --> $DIR/error_is_shown_in_downstream_crates.rs:7:21
+  --> $DIR/error_is_shown_in_downstream_crates.rs:8:21
    |
 LL | fn take_foo(_: impl Foo) {}
    |                     ^^^ required by this bound in `take_foo`
diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/ignore_unsupported_options_and_continue_to_use_fallback.rs b/tests/ui/diagnostic_namespace/on_unimplemented/ignore_unsupported_options_and_continue_to_use_fallback.rs
index 5b25fb234bc..c638681173d 100644
--- a/tests/ui/diagnostic_namespace/on_unimplemented/ignore_unsupported_options_and_continue_to_use_fallback.rs
+++ b/tests/ui/diagnostic_namespace/on_unimplemented/ignore_unsupported_options_and_continue_to_use_fallback.rs
@@ -1,3 +1,5 @@
+//@ reference: attributes.diagnostic.on_unimplemented.repetition
+//@ reference: attributes.diagnostic.on_unimplemented.syntax
 #[diagnostic::on_unimplemented(
     if(Self = "()"),
     //~^WARN malformed `on_unimplemented` attribute
diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/ignore_unsupported_options_and_continue_to_use_fallback.stderr b/tests/ui/diagnostic_namespace/on_unimplemented/ignore_unsupported_options_and_continue_to_use_fallback.stderr
index 56d125e20e5..e00846da77b 100644
--- a/tests/ui/diagnostic_namespace/on_unimplemented/ignore_unsupported_options_and_continue_to_use_fallback.stderr
+++ b/tests/ui/diagnostic_namespace/on_unimplemented/ignore_unsupported_options_and_continue_to_use_fallback.stderr
@@ -1,5 +1,5 @@
 warning: malformed `on_unimplemented` attribute
-  --> $DIR/ignore_unsupported_options_and_continue_to_use_fallback.rs:2:5
+  --> $DIR/ignore_unsupported_options_and_continue_to_use_fallback.rs:4:5
    |
 LL |     if(Self = "()"),
    |     ^^^^^^^^^^^^^^^ invalid option found here
@@ -8,7 +8,7 @@ LL |     if(Self = "()"),
    = note: `#[warn(unknown_or_malformed_diagnostic_attributes)]` on by default
 
 warning: `message` is ignored due to previous definition of `message`
-  --> $DIR/ignore_unsupported_options_and_continue_to_use_fallback.rs:8:32
+  --> $DIR/ignore_unsupported_options_and_continue_to_use_fallback.rs:10:32
    |
 LL |     message = "custom message",
    |     -------------------------- `message` is first declared here
@@ -17,7 +17,7 @@ LL | #[diagnostic::on_unimplemented(message = "fallback!!")]
    |                                ^^^^^^^^^^^^^^^^^^^^^^ `message` is already declared here
 
 warning: malformed `on_unimplemented` attribute
-  --> $DIR/ignore_unsupported_options_and_continue_to_use_fallback.rs:2:5
+  --> $DIR/ignore_unsupported_options_and_continue_to_use_fallback.rs:4:5
    |
 LL |     if(Self = "()"),
    |     ^^^^^^^^^^^^^^^ invalid option found here
@@ -26,7 +26,7 @@ LL |     if(Self = "()"),
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 warning: `message` is ignored due to previous definition of `message`
-  --> $DIR/ignore_unsupported_options_and_continue_to_use_fallback.rs:8:32
+  --> $DIR/ignore_unsupported_options_and_continue_to_use_fallback.rs:10:32
    |
 LL |     message = "custom message",
    |     -------------------------- `message` is first declared here
@@ -37,7 +37,7 @@ LL | #[diagnostic::on_unimplemented(message = "fallback!!")]
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error[E0277]: custom message
-  --> $DIR/ignore_unsupported_options_and_continue_to_use_fallback.rs:18:15
+  --> $DIR/ignore_unsupported_options_and_continue_to_use_fallback.rs:20:15
    |
 LL |     takes_foo(());
    |     --------- ^^ fallback label
@@ -48,12 +48,12 @@ LL |     takes_foo(());
    = note: custom note
    = note: fallback note
 help: this trait has no implementations, consider adding one
-  --> $DIR/ignore_unsupported_options_and_continue_to_use_fallback.rs:13:1
+  --> $DIR/ignore_unsupported_options_and_continue_to_use_fallback.rs:15:1
    |
 LL | trait Foo {}
    | ^^^^^^^^^
 note: required by a bound in `takes_foo`
-  --> $DIR/ignore_unsupported_options_and_continue_to_use_fallback.rs:15:22
+  --> $DIR/ignore_unsupported_options_and_continue_to_use_fallback.rs:17:22
    |
 LL | fn takes_foo(_: impl Foo) {}
    |                      ^^^ required by this bound in `takes_foo`
diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/multiple_notes.rs b/tests/ui/diagnostic_namespace/on_unimplemented/multiple_notes.rs
index a5982f6492c..dc0f850031e 100644
--- a/tests/ui/diagnostic_namespace/on_unimplemented/multiple_notes.rs
+++ b/tests/ui/diagnostic_namespace/on_unimplemented/multiple_notes.rs
@@ -1,3 +1,4 @@
+//@ reference: attributes.diagnostic.on_unimplemented.note-repetition
 #[diagnostic::on_unimplemented(message = "Foo", label = "Bar", note = "Baz", note = "Boom")]
 trait Foo {}
 
diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/multiple_notes.stderr b/tests/ui/diagnostic_namespace/on_unimplemented/multiple_notes.stderr
index 93a0d0b3f41..6567269be3b 100644
--- a/tests/ui/diagnostic_namespace/on_unimplemented/multiple_notes.stderr
+++ b/tests/ui/diagnostic_namespace/on_unimplemented/multiple_notes.stderr
@@ -1,5 +1,5 @@
 error[E0277]: Foo
-  --> $DIR/multiple_notes.rs:12:15
+  --> $DIR/multiple_notes.rs:13:15
    |
 LL |     takes_foo(());
    |     --------- ^^ Bar
@@ -10,18 +10,18 @@ LL |     takes_foo(());
    = note: Baz
    = note: Boom
 help: this trait has no implementations, consider adding one
-  --> $DIR/multiple_notes.rs:2:1
+  --> $DIR/multiple_notes.rs:3:1
    |
 LL | trait Foo {}
    | ^^^^^^^^^
 note: required by a bound in `takes_foo`
-  --> $DIR/multiple_notes.rs:8:22
+  --> $DIR/multiple_notes.rs:9:22
    |
 LL | fn takes_foo(_: impl Foo) {}
    |                      ^^^ required by this bound in `takes_foo`
 
 error[E0277]: Bar
-  --> $DIR/multiple_notes.rs:14:15
+  --> $DIR/multiple_notes.rs:15:15
    |
 LL |     takes_bar(());
    |     --------- ^^ Foo
@@ -32,12 +32,12 @@ LL |     takes_bar(());
    = note: Baz
    = note: Baz2
 help: this trait has no implementations, consider adding one
-  --> $DIR/multiple_notes.rs:6:1
+  --> $DIR/multiple_notes.rs:7:1
    |
 LL | trait Bar {}
    | ^^^^^^^^^
 note: required by a bound in `takes_bar`
-  --> $DIR/multiple_notes.rs:9:22
+  --> $DIR/multiple_notes.rs:10:22
    |
 LL | fn takes_bar(_: impl Bar) {}
    |                      ^^^ required by this bound in `takes_bar`
diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/on_unimplemented_simple.rs b/tests/ui/diagnostic_namespace/on_unimplemented/on_unimplemented_simple.rs
index 7ca03127759..e584077c643 100644
--- a/tests/ui/diagnostic_namespace/on_unimplemented/on_unimplemented_simple.rs
+++ b/tests/ui/diagnostic_namespace/on_unimplemented/on_unimplemented_simple.rs
@@ -1,3 +1,5 @@
+//@ reference: attributes.diagnostic.on_unimplemented.intro
+//@ reference: attributes.diagnostic.on_unimplemented.keys
 #[diagnostic::on_unimplemented(message = "Foo", label = "Bar", note = "Baz")]
 trait Foo {}
 
diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/on_unimplemented_simple.stderr b/tests/ui/diagnostic_namespace/on_unimplemented/on_unimplemented_simple.stderr
index 6b17f40c6dd..de57f7044bf 100644
--- a/tests/ui/diagnostic_namespace/on_unimplemented/on_unimplemented_simple.stderr
+++ b/tests/ui/diagnostic_namespace/on_unimplemented/on_unimplemented_simple.stderr
@@ -1,5 +1,5 @@
 error[E0277]: Foo
-  --> $DIR/on_unimplemented_simple.rs:7:15
+  --> $DIR/on_unimplemented_simple.rs:9:15
    |
 LL |     takes_foo(());
    |     --------- ^^ Bar
@@ -9,12 +9,12 @@ LL |     takes_foo(());
    = help: the trait `Foo` is not implemented for `()`
    = note: Baz
 help: this trait has no implementations, consider adding one
-  --> $DIR/on_unimplemented_simple.rs:2:1
+  --> $DIR/on_unimplemented_simple.rs:4:1
    |
 LL | trait Foo {}
    | ^^^^^^^^^
 note: required by a bound in `takes_foo`
-  --> $DIR/on_unimplemented_simple.rs:4:22
+  --> $DIR/on_unimplemented_simple.rs:6:22
    |
 LL | fn takes_foo(_: impl Foo) {}
    |                      ^^^ required by this bound in `takes_foo`
diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/report_warning_on_duplicated_options.rs b/tests/ui/diagnostic_namespace/on_unimplemented/report_warning_on_duplicated_options.rs
index 8c0b8150417..d0eb608c40f 100644
--- a/tests/ui/diagnostic_namespace/on_unimplemented/report_warning_on_duplicated_options.rs
+++ b/tests/ui/diagnostic_namespace/on_unimplemented/report_warning_on_duplicated_options.rs
@@ -1,3 +1,4 @@
+//@ reference: attributes.diagnostic.on_unimplemented.repetition
 #[diagnostic::on_unimplemented(
     message = "first message",
     label = "first label",
diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/report_warning_on_duplicated_options.stderr b/tests/ui/diagnostic_namespace/on_unimplemented/report_warning_on_duplicated_options.stderr
index 43ab6bf25a1..feafe2cee76 100644
--- a/tests/ui/diagnostic_namespace/on_unimplemented/report_warning_on_duplicated_options.stderr
+++ b/tests/ui/diagnostic_namespace/on_unimplemented/report_warning_on_duplicated_options.stderr
@@ -1,5 +1,5 @@
 warning: `message` is ignored due to previous definition of `message`
-  --> $DIR/report_warning_on_duplicated_options.rs:7:5
+  --> $DIR/report_warning_on_duplicated_options.rs:8:5
    |
 LL |     message = "first message",
    |     ------------------------- `message` is first declared here
@@ -10,7 +10,7 @@ LL |     message = "second message",
    = note: `#[warn(unknown_or_malformed_diagnostic_attributes)]` on by default
 
 warning: `label` is ignored due to previous definition of `label`
-  --> $DIR/report_warning_on_duplicated_options.rs:10:5
+  --> $DIR/report_warning_on_duplicated_options.rs:11:5
    |
 LL |     label = "first label",
    |     --------------------- `label` is first declared here
@@ -19,7 +19,7 @@ LL |     label = "second label",
    |     ^^^^^^^^^^^^^^^^^^^^^^ `label` is already declared here
 
 warning: `message` is ignored due to previous definition of `message`
-  --> $DIR/report_warning_on_duplicated_options.rs:7:5
+  --> $DIR/report_warning_on_duplicated_options.rs:8:5
    |
 LL |     message = "first message",
    |     ------------------------- `message` is first declared here
@@ -30,7 +30,7 @@ LL |     message = "second message",
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 warning: `label` is ignored due to previous definition of `label`
-  --> $DIR/report_warning_on_duplicated_options.rs:10:5
+  --> $DIR/report_warning_on_duplicated_options.rs:11:5
    |
 LL |     label = "first label",
    |     --------------------- `label` is first declared here
@@ -41,7 +41,7 @@ LL |     label = "second label",
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error[E0277]: first message
-  --> $DIR/report_warning_on_duplicated_options.rs:21:15
+  --> $DIR/report_warning_on_duplicated_options.rs:22:15
    |
 LL |     takes_foo(());
    |     --------- ^^ first label
@@ -52,12 +52,12 @@ LL |     takes_foo(());
    = note: custom note
    = note: second note
 help: this trait has no implementations, consider adding one
-  --> $DIR/report_warning_on_duplicated_options.rs:15:1
+  --> $DIR/report_warning_on_duplicated_options.rs:16:1
    |
 LL | trait Foo {}
    | ^^^^^^^^^
 note: required by a bound in `takes_foo`
-  --> $DIR/report_warning_on_duplicated_options.rs:18:22
+  --> $DIR/report_warning_on_duplicated_options.rs:19:22
    |
 LL | fn takes_foo(_: impl Foo) {}
    |                      ^^^ required by this bound in `takes_foo`
diff --git a/tests/ui/diagnostic_namespace/suggest_typos.rs b/tests/ui/diagnostic_namespace/suggest_typos.rs
index b25f097a8ad..6fa4f800462 100644
--- a/tests/ui/diagnostic_namespace/suggest_typos.rs
+++ b/tests/ui/diagnostic_namespace/suggest_typos.rs
@@ -1,3 +1,4 @@
+//@ reference: attributes.diagnostic.namespace.unknown-invalid-syntax
 #![deny(unknown_or_malformed_diagnostic_attributes)]
 
 #[diagnostic::onunimplemented]
diff --git a/tests/ui/diagnostic_namespace/suggest_typos.stderr b/tests/ui/diagnostic_namespace/suggest_typos.stderr
index 307311258f2..ff4ee9717d4 100644
--- a/tests/ui/diagnostic_namespace/suggest_typos.stderr
+++ b/tests/ui/diagnostic_namespace/suggest_typos.stderr
@@ -1,11 +1,11 @@
 error: unknown diagnostic attribute
-  --> $DIR/suggest_typos.rs:3:15
+  --> $DIR/suggest_typos.rs:4:15
    |
 LL | #[diagnostic::onunimplemented]
    |               ^^^^^^^^^^^^^^^
    |
 note: the lint level is defined here
-  --> $DIR/suggest_typos.rs:1:9
+  --> $DIR/suggest_typos.rs:2:9
    |
 LL | #![deny(unknown_or_malformed_diagnostic_attributes)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -15,7 +15,7 @@ LL | #[diagnostic::on_unimplemented]
    |               ~~~~~~~~~~~~~~~~
 
 error: unknown diagnostic attribute
-  --> $DIR/suggest_typos.rs:8:15
+  --> $DIR/suggest_typos.rs:9:15
    |
 LL | #[diagnostic::un_onimplemented]
    |               ^^^^^^^^^^^^^^^^
@@ -26,7 +26,7 @@ LL | #[diagnostic::on_unimplemented]
    |               ~~~~~~~~~~~~~~~~
 
 error: unknown diagnostic attribute
-  --> $DIR/suggest_typos.rs:13:15
+  --> $DIR/suggest_typos.rs:14:15
    |
 LL | #[diagnostic::on_implemented]
    |               ^^^^^^^^^^^^^^
diff --git a/tests/ui/feature-gates/feature-gate-min-generic-const-args.rs b/tests/ui/feature-gates/feature-gate-min-generic-const-args.rs
new file mode 100644
index 00000000000..171509876d1
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-min-generic-const-args.rs
@@ -0,0 +1,11 @@
+trait Trait {
+    const ASSOC: usize;
+}
+
+// FIXME(min_generic_const_args): implement support for this, behind the feature gate
+fn foo<T: Trait>() -> [u8; <T as Trait>::ASSOC] {
+    //~^ ERROR generic parameters may not be used in const operations
+    loop {}
+}
+
+fn main() {}
diff --git a/tests/ui/feature-gates/feature-gate-min-generic-const-args.stderr b/tests/ui/feature-gates/feature-gate-min-generic-const-args.stderr
new file mode 100644
index 00000000000..04d96b4c11e
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-min-generic-const-args.stderr
@@ -0,0 +1,11 @@
+error: generic parameters may not be used in const operations
+  --> $DIR/feature-gate-min-generic-const-args.rs:6:29
+   |
+LL | fn foo<T: Trait>() -> [u8; <T as Trait>::ASSOC] {
+   |                             ^ cannot perform const operation using `T`
+   |
+   = note: type parameters may not be used in const expressions
+   = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/lint/dangling-pointers-from-temporaries/types.rs b/tests/ui/lint/dangling-pointers-from-temporaries/types.rs
index 2b515d3e6d5..17c3eca89e2 100644
--- a/tests/ui/lint/dangling-pointers-from-temporaries/types.rs
+++ b/tests/ui/lint/dangling-pointers-from-temporaries/types.rs
@@ -1,6 +1,7 @@
 #![deny(dangling_pointers_from_temporaries)]
+#![feature(sync_unsafe_cell)]
 
-use std::cell::Cell;
+use std::cell::{Cell, SyncUnsafeCell, UnsafeCell};
 use std::ffi::{CStr, CString};
 use std::mem::MaybeUninit;
 
@@ -47,6 +48,10 @@ fn main() {
     //~^ ERROR a dangling pointer will be produced because the temporary `MaybeUninit<u8>` will be dropped
     declval::<Vec<AsPtrFake>>().as_ptr();
     //~^ ERROR a dangling pointer will be produced because the temporary `Vec<AsPtrFake>` will be dropped
+    declval::<UnsafeCell<u8>>().get();
+    //~^ ERROR a dangling pointer will be produced because the temporary `UnsafeCell<u8>` will be dropped
+    declval::<SyncUnsafeCell<u8>>().get();
+    //~^ ERROR a dangling pointer will be produced because the temporary `SyncUnsafeCell<u8>` will be dropped
     declval::<Box<AsPtrFake>>().as_ptr();
     declval::<AsPtrFake>().as_ptr();
 }
diff --git a/tests/ui/lint/dangling-pointers-from-temporaries/types.stderr b/tests/ui/lint/dangling-pointers-from-temporaries/types.stderr
index c582a4c6540..250ed6dc9e3 100644
--- a/tests/ui/lint/dangling-pointers-from-temporaries/types.stderr
+++ b/tests/ui/lint/dangling-pointers-from-temporaries/types.stderr
@@ -1,5 +1,5 @@
 error: a dangling pointer will be produced because the temporary `CString` will be dropped
-  --> $DIR/types.rs:20:26
+  --> $DIR/types.rs:21:26
    |
 LL |     declval::<CString>().as_ptr();
    |     -------------------- ^^^^^^ this pointer will immediately be invalid
@@ -15,7 +15,7 @@ LL | #![deny(dangling_pointers_from_temporaries)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: a dangling pointer will be produced because the temporary `String` will be dropped
-  --> $DIR/types.rs:22:25
+  --> $DIR/types.rs:23:25
    |
 LL |     declval::<String>().as_ptr();
    |     ------------------- ^^^^^^ this pointer will immediately be invalid
@@ -26,7 +26,7 @@ LL |     declval::<String>().as_ptr();
    = help: for more information, see <https://doc.rust-lang.org/reference/destructors.html>
 
 error: a dangling pointer will be produced because the temporary `Vec<u8>` will be dropped
-  --> $DIR/types.rs:24:26
+  --> $DIR/types.rs:25:26
    |
 LL |     declval::<Vec<u8>>().as_ptr();
    |     -------------------- ^^^^^^ this pointer will immediately be invalid
@@ -37,7 +37,7 @@ LL |     declval::<Vec<u8>>().as_ptr();
    = help: for more information, see <https://doc.rust-lang.org/reference/destructors.html>
 
 error: a dangling pointer will be produced because the temporary `Box<CString>` will be dropped
-  --> $DIR/types.rs:26:31
+  --> $DIR/types.rs:27:31
    |
 LL |     declval::<Box<CString>>().as_ptr();
    |     ------------------------- ^^^^^^ this pointer will immediately be invalid
@@ -48,7 +48,7 @@ LL |     declval::<Box<CString>>().as_ptr();
    = help: for more information, see <https://doc.rust-lang.org/reference/destructors.html>
 
 error: a dangling pointer will be produced because the temporary `Box<[u8]>` will be dropped
-  --> $DIR/types.rs:28:28
+  --> $DIR/types.rs:29:28
    |
 LL |     declval::<Box<[u8]>>().as_ptr();
    |     ---------------------- ^^^^^^ this pointer will immediately be invalid
@@ -59,7 +59,7 @@ LL |     declval::<Box<[u8]>>().as_ptr();
    = help: for more information, see <https://doc.rust-lang.org/reference/destructors.html>
 
 error: a dangling pointer will be produced because the temporary `Box<str>` will be dropped
-  --> $DIR/types.rs:30:27
+  --> $DIR/types.rs:31:27
    |
 LL |     declval::<Box<str>>().as_ptr();
    |     --------------------- ^^^^^^ this pointer will immediately be invalid
@@ -70,7 +70,7 @@ LL |     declval::<Box<str>>().as_ptr();
    = help: for more information, see <https://doc.rust-lang.org/reference/destructors.html>
 
 error: a dangling pointer will be produced because the temporary `Box<CStr>` will be dropped
-  --> $DIR/types.rs:32:28
+  --> $DIR/types.rs:33:28
    |
 LL |     declval::<Box<CStr>>().as_ptr();
    |     ---------------------- ^^^^^^ this pointer will immediately be invalid
@@ -81,7 +81,7 @@ LL |     declval::<Box<CStr>>().as_ptr();
    = help: for more information, see <https://doc.rust-lang.org/reference/destructors.html>
 
 error: a dangling pointer will be produced because the temporary `[u8; 10]` will be dropped
-  --> $DIR/types.rs:34:27
+  --> $DIR/types.rs:35:27
    |
 LL |     declval::<[u8; 10]>().as_ptr();
    |     --------------------- ^^^^^^ this pointer will immediately be invalid
@@ -92,7 +92,7 @@ LL |     declval::<[u8; 10]>().as_ptr();
    = help: for more information, see <https://doc.rust-lang.org/reference/destructors.html>
 
 error: a dangling pointer will be produced because the temporary `Box<[u8; 10]>` will be dropped
-  --> $DIR/types.rs:36:32
+  --> $DIR/types.rs:37:32
    |
 LL |     declval::<Box<[u8; 10]>>().as_ptr();
    |     -------------------------- ^^^^^^ this pointer will immediately be invalid
@@ -103,7 +103,7 @@ LL |     declval::<Box<[u8; 10]>>().as_ptr();
    = help: for more information, see <https://doc.rust-lang.org/reference/destructors.html>
 
 error: a dangling pointer will be produced because the temporary `Box<Vec<u8>>` will be dropped
-  --> $DIR/types.rs:38:31
+  --> $DIR/types.rs:39:31
    |
 LL |     declval::<Box<Vec<u8>>>().as_ptr();
    |     ------------------------- ^^^^^^ this pointer will immediately be invalid
@@ -114,7 +114,7 @@ LL |     declval::<Box<Vec<u8>>>().as_ptr();
    = help: for more information, see <https://doc.rust-lang.org/reference/destructors.html>
 
 error: a dangling pointer will be produced because the temporary `Box<String>` will be dropped
-  --> $DIR/types.rs:40:30
+  --> $DIR/types.rs:41:30
    |
 LL |     declval::<Box<String>>().as_ptr();
    |     ------------------------ ^^^^^^ this pointer will immediately be invalid
@@ -125,7 +125,7 @@ LL |     declval::<Box<String>>().as_ptr();
    = help: for more information, see <https://doc.rust-lang.org/reference/destructors.html>
 
 error: a dangling pointer will be produced because the temporary `Box<Box<Box<Box<[u8]>>>>` will be dropped
-  --> $DIR/types.rs:42:43
+  --> $DIR/types.rs:43:43
    |
 LL |     declval::<Box<Box<Box<Box<[u8]>>>>>().as_ptr();
    |     ------------------------------------- ^^^^^^ this pointer will immediately be invalid
@@ -136,7 +136,7 @@ LL |     declval::<Box<Box<Box<Box<[u8]>>>>>().as_ptr();
    = help: for more information, see <https://doc.rust-lang.org/reference/destructors.html>
 
 error: a dangling pointer will be produced because the temporary `Cell<u8>` will be dropped
-  --> $DIR/types.rs:44:27
+  --> $DIR/types.rs:45:27
    |
 LL |     declval::<Cell<u8>>().as_ptr();
    |     --------------------- ^^^^^^ this pointer will immediately be invalid
@@ -147,7 +147,7 @@ LL |     declval::<Cell<u8>>().as_ptr();
    = help: for more information, see <https://doc.rust-lang.org/reference/destructors.html>
 
 error: a dangling pointer will be produced because the temporary `MaybeUninit<u8>` will be dropped
-  --> $DIR/types.rs:46:34
+  --> $DIR/types.rs:47:34
    |
 LL |     declval::<MaybeUninit<u8>>().as_ptr();
    |     ---------------------------- ^^^^^^ this pointer will immediately be invalid
@@ -158,7 +158,7 @@ LL |     declval::<MaybeUninit<u8>>().as_ptr();
    = help: for more information, see <https://doc.rust-lang.org/reference/destructors.html>
 
 error: a dangling pointer will be produced because the temporary `Vec<AsPtrFake>` will be dropped
-  --> $DIR/types.rs:48:33
+  --> $DIR/types.rs:49:33
    |
 LL |     declval::<Vec<AsPtrFake>>().as_ptr();
    |     --------------------------- ^^^^^^ this pointer will immediately be invalid
@@ -168,5 +168,27 @@ LL |     declval::<Vec<AsPtrFake>>().as_ptr();
    = note: pointers do not have a lifetime; when calling `as_ptr` the `Vec<AsPtrFake>` will be deallocated at the end of the statement because nothing is referencing it as far as the type system is concerned
    = help: for more information, see <https://doc.rust-lang.org/reference/destructors.html>
 
-error: aborting due to 15 previous errors
+error: a dangling pointer will be produced because the temporary `UnsafeCell<u8>` will be dropped
+  --> $DIR/types.rs:51:33
+   |
+LL |     declval::<UnsafeCell<u8>>().get();
+   |     --------------------------- ^^^ this pointer will immediately be invalid
+   |     |
+   |     this `UnsafeCell<u8>` is deallocated at the end of the statement, bind it to a variable to extend its lifetime
+   |
+   = note: pointers do not have a lifetime; when calling `get` the `UnsafeCell<u8>` will be deallocated at the end of the statement because nothing is referencing it as far as the type system is concerned
+   = help: for more information, see <https://doc.rust-lang.org/reference/destructors.html>
+
+error: a dangling pointer will be produced because the temporary `SyncUnsafeCell<u8>` will be dropped
+  --> $DIR/types.rs:53:37
+   |
+LL |     declval::<SyncUnsafeCell<u8>>().get();
+   |     ------------------------------- ^^^ this pointer will immediately be invalid
+   |     |
+   |     this `SyncUnsafeCell<u8>` is deallocated at the end of the statement, bind it to a variable to extend its lifetime
+   |
+   = note: pointers do not have a lifetime; when calling `get` the `SyncUnsafeCell<u8>` will be deallocated at the end of the statement because nothing is referencing it as far as the type system is concerned
+   = help: for more information, see <https://doc.rust-lang.org/reference/destructors.html>
+
+error: aborting due to 17 previous errors
 
diff --git a/tests/ui/stats/hir-stats.rs b/tests/ui/stats/input-stats.rs
index 7c5da8cf554..f19a53cc610 100644
--- a/tests/ui/stats/hir-stats.rs
+++ b/tests/ui/stats/input-stats.rs
@@ -1,6 +1,6 @@
 //@ check-pass
-//@ compile-flags: -Zhir-stats
-//@ only-x86_64
+//@ compile-flags: -Zinput-stats
+//@ only-64bit
 // layout randomization affects the hir stat output
 //@ needs-deterministic-layouts
 
@@ -11,7 +11,7 @@
 
 
 // The aim here is to include at least one of every different type of top-level
-// AST/HIR node reported by `-Zhir-stats`.
+// AST/HIR node reported by `-Zinput-stats`.
 
 #![allow(dead_code)]
 
diff --git a/tests/ui/stats/hir-stats.stderr b/tests/ui/stats/input-stats.stderr
index bd0c8cbc3b1..2cc2c8019fa 100644
--- a/tests/ui/stats/hir-stats.stderr
+++ b/tests/ui/stats/input-stats.stderr
@@ -53,7 +53,7 @@ ast-stats-1 - Enum                     136 ( 2.0%)             1
 ast-stats-1 - Fn                       272 ( 4.1%)             2
 ast-stats-1 - Use                      408 ( 6.1%)             3
 ast-stats-1 ----------------------------------------------------------------
-ast-stats-1 Total                  6_640
+ast-stats-1 Total                  6_640                   116
 ast-stats-1
 ast-stats-2 POST EXPANSION AST STATS
 ast-stats-2 Name                Accumulated Size         Count     Item Size
@@ -113,7 +113,7 @@ ast-stats-2 - ForeignMod               136 ( 1.9%)             1
 ast-stats-2 - Fn                       272 ( 3.7%)             2
 ast-stats-2 - Use                      544 ( 7.5%)             4
 ast-stats-2 ----------------------------------------------------------------
-ast-stats-2 Total                  7_288
+ast-stats-2 Total                  7_288                   127
 ast-stats-2
 hir-stats HIR STATS
 hir-stats Name                Accumulated Size         Count     Item Size
@@ -174,5 +174,5 @@ hir-stats - Use                      352 ( 3.9%)             4
 hir-stats Path                   1_240 (13.7%)            31            40
 hir-stats PathSegment            1_920 (21.3%)            40            48
 hir-stats ----------------------------------------------------------------
-hir-stats Total                  9_024
+hir-stats Total                  9_024                   180
 hir-stats
diff --git a/tests/ui/traits/negative-bounds/on-unimplemented.rs b/tests/ui/traits/negative-bounds/on-unimplemented.rs
index 34582590861..5f2a705ed56 100644
--- a/tests/ui/traits/negative-bounds/on-unimplemented.rs
+++ b/tests/ui/traits/negative-bounds/on-unimplemented.rs
@@ -1,3 +1,5 @@
+//@ reference: attributes.diagnostic.on_unimplemented.intro
+
 #![feature(negative_bounds)]
 
 #[diagnostic::on_unimplemented(message = "this ain't fooing")]
diff --git a/tests/ui/traits/negative-bounds/on-unimplemented.stderr b/tests/ui/traits/negative-bounds/on-unimplemented.stderr
index ed473d57917..8a295611010 100644
--- a/tests/ui/traits/negative-bounds/on-unimplemented.stderr
+++ b/tests/ui/traits/negative-bounds/on-unimplemented.stderr
@@ -1,5 +1,5 @@
 error[E0277]: the trait bound `NotFoo: !Foo` is not satisfied
-  --> $DIR/on-unimplemented.rs:7:15
+  --> $DIR/on-unimplemented.rs:9:15
    |
 LL | fn hello() -> impl !Foo {
    |               ^^^^^^^^^ the trait bound `NotFoo: !Foo` is not satisfied
diff --git a/triagebot.toml b/triagebot.toml
index 6154ffedc14..2483bfc4a41 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -901,7 +901,7 @@ message = "This PR changes a file inside `tests/crashes`. If a crash was fixed,
 message = "Changes to the code generated for builtin derived traits."
 cc = ["@nnethercote"]
 
-[mentions."tests/ui/stats/hir-stats.stderr"]
+[mentions."tests/ui/stats/input-stats.stderr"]
 message = "Changes to the size of AST and/or HIR nodes."
 cc = ["@nnethercote"]