about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock19
-rw-r--r--compiler/rustc_abi/src/lib.rs4
-rw-r--r--compiler/rustc_ast_passes/src/ast_validation.rs36
-rw-r--r--compiler/rustc_ast_passes/src/feature_gate.rs55
-rw-r--r--compiler/rustc_attr/src/builtin.rs2
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs12
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs8
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/mod.rs2
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/region_errors.rs4
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/region_name.rs20
-rw-r--r--compiler/rustc_borrowck/src/region_infer/mod.rs4
-rw-r--r--compiler/rustc_borrowck/src/region_infer/opaque_types.rs2
-rw-r--r--compiler/rustc_borrowck/src/type_check/liveness/mod.rs8
-rw-r--r--compiler/rustc_borrowck/src/type_check/mod.rs6
-rw-r--r--compiler/rustc_borrowck/src/universal_regions.rs29
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/debug.rs10
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/generic/mod.rs8
-rw-r--r--compiler/rustc_builtin_macros/src/standard_library_imports.rs2
-rw-r--r--compiler/rustc_codegen_cranelift/src/codegen_i128.rs4
-rw-r--r--compiler/rustc_codegen_cranelift/src/driver/aot.rs18
-rw-r--r--compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs2
-rw-r--r--compiler/rustc_codegen_cranelift/src/main_shim.rs2
-rw-r--r--compiler/rustc_codegen_cranelift/src/num.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/attributes.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/back/write.rs19
-rw-r--r--compiler/rustc_codegen_llvm/src/consts.rs4
-rw-r--r--compiler/rustc_codegen_llvm/src/context.rs13
-rw-r--r--compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs4
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/mod.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/intrinsic.rs7
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm/ffi.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/type_of.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/back/link.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/base.rs10
-rw-r--r--compiler/rustc_codegen_ssa/src/codegen_attrs.rs3
-rw-r--r--compiler/rustc_codegen_ssa/src/lib.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/mod.rs3
-rw-r--r--compiler/rustc_codegen_ssa/src/target_features.rs1
-rw-r--r--compiler/rustc_const_eval/src/interpret/intrinsics/caller_location.rs4
-rw-r--r--compiler/rustc_const_eval/src/interpret/memory.rs6
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/mod.rs2
-rw-r--r--compiler/rustc_const_eval/src/transform/promote_consts.rs2
-rw-r--r--compiler/rustc_const_eval/src/transform/validate.rs2
-rw-r--r--compiler/rustc_data_structures/src/profiling.rs11
-rw-r--r--compiler/rustc_errors/src/emitter.rs3
-rw-r--r--compiler/rustc_errors/src/lib.rs31
-rw-r--r--compiler/rustc_expand/src/config.rs10
-rw-r--r--compiler/rustc_feature/src/active.rs6
-rw-r--r--compiler/rustc_hir/src/hir.rs11
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/generics.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/mod.rs102
-rw-r--r--compiler/rustc_hir_analysis/src/check/check.rs28
-rw-r--r--compiler/rustc_hir_analysis/src/check/compare_impl_item.rs106
-rw-r--r--compiler/rustc_hir_analysis/src/check/dropck.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/check/intrinsic.rs47
-rw-r--r--compiler/rustc_hir_analysis/src/check/intrinsicck.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/check/mod.rs12
-rw-r--r--compiler/rustc_hir_analysis/src/check/wfcheck.rs61
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/builtin.rs10
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs14
-rw-r--r--compiler/rustc_hir_analysis/src/collect.rs22
-rw-r--r--compiler/rustc_hir_analysis/src/collect/generics_of.rs16
-rw-r--r--compiler/rustc_hir_analysis/src/collect/predicates_of.rs63
-rw-r--r--compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs (renamed from compiler/rustc_hir_analysis/src/collect/lifetimes.rs)521
-rw-r--r--compiler/rustc_hir_analysis/src/collect/type_of.rs30
-rw-r--r--compiler/rustc_hir_analysis/src/impl_wf_check.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs11
-rw-r--r--compiler/rustc_hir_analysis/src/lib.rs11
-rw-r--r--compiler/rustc_hir_analysis/src/outlives/explicit.rs1
-rw-r--r--compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/variance/constraints.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/variance/solve.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/check.rs10
-rw-r--r--compiler/rustc_hir_typeck/src/closure.rs4
-rw-r--r--compiler/rustc_hir_typeck/src/coercion.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/demand.rs6
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs23
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs23
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs123
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/generator_interior/mod.rs16
-rw-r--r--compiler/rustc_hir_typeck/src/lib.rs4
-rw-r--r--compiler/rustc_hir_typeck/src/method/confirm.rs10
-rw-r--r--compiler/rustc_hir_typeck/src/method/probe.rs35
-rw-r--r--compiler/rustc_hir_typeck/src/method/suggest.rs24
-rw-r--r--compiler/rustc_hir_typeck/src/upvar.rs6
-rw-r--r--compiler/rustc_infer/src/infer/canonical/canonicalizer.rs5
-rw-r--r--compiler/rustc_infer/src/infer/canonical/mod.rs2
-rw-r--r--compiler/rustc_infer/src/infer/canonical/query_response.rs13
-rw-r--r--compiler/rustc_infer/src/infer/combine.rs4
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs2
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs32
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs2
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs12
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs12
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs10
-rw-r--r--compiler/rustc_infer/src/infer/higher_ranked/mod.rs4
-rw-r--r--compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs4
-rw-r--r--compiler/rustc_infer/src/infer/mod.rs12
-rw-r--r--compiler/rustc_infer/src/infer/outlives/mod.rs1
-rw-r--r--compiler/rustc_infer/src/infer/region_constraints/leak_check.rs10
-rw-r--r--compiler/rustc_infer/src/infer/region_constraints/mod.rs6
-rw-r--r--compiler/rustc_infer/src/infer/resolve.rs2
-rw-r--r--compiler/rustc_infer/src/traits/util.rs5
-rw-r--r--compiler/rustc_lexer/src/lib.rs43
-rw-r--r--compiler/rustc_lexer/src/tests.rs2
-rw-r--r--compiler/rustc_lint/src/builtin.rs43
-rw-r--r--compiler/rustc_lint/src/context.rs10
-rw-r--r--compiler/rustc_lint/src/deref_into_dyn_supertrait.rs4
-rw-r--r--compiler/rustc_lint/src/for_loops_over_fallibles.rs7
-rw-r--r--compiler/rustc_lint/src/internal.rs2
-rw-r--r--compiler/rustc_lint/src/lints.rs5
-rw-r--r--compiler/rustc_lint/src/pass_by_value.rs2
-rw-r--r--compiler/rustc_lint/src/types.rs8
-rw-r--r--compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp10
-rw-r--r--compiler/rustc_metadata/src/native_libs.rs3
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs2
-rw-r--r--compiler/rustc_metadata/src/rmeta/encoder.rs3
-rw-r--r--compiler/rustc_metadata/src/rmeta/mod.rs4
-rw-r--r--compiler/rustc_middle/src/dep_graph/mod.rs4
-rw-r--r--compiler/rustc_middle/src/hir/map/mod.rs2
-rw-r--r--compiler/rustc_middle/src/hir/mod.rs2
-rw-r--r--compiler/rustc_middle/src/infer/canonical.rs2
-rw-r--r--compiler/rustc_middle/src/middle/codegen_fn_attrs.rs3
-rw-r--r--compiler/rustc_middle/src/middle/mod.rs2
-rw-r--r--compiler/rustc_middle/src/middle/resolve_bound_vars.rs (renamed from compiler/rustc_middle/src/middle/resolve_lifetime.rs)16
-rw-r--r--compiler/rustc_middle/src/mir/mod.rs16
-rw-r--r--compiler/rustc_middle/src/mir/tcx.rs6
-rw-r--r--compiler/rustc_middle/src/mir/visit.rs6
-rw-r--r--compiler/rustc_middle/src/query/mod.rs15
-rw-r--r--compiler/rustc_middle/src/traits/mod.rs6
-rw-r--r--compiler/rustc_middle/src/traits/specialization_graph.rs10
-rw-r--r--compiler/rustc_middle/src/ty/assoc.rs14
-rw-r--r--compiler/rustc_middle/src/ty/consts.rs39
-rw-r--r--compiler/rustc_middle/src/ty/context.rs303
-rw-r--r--compiler/rustc_middle/src/ty/diagnostics.rs6
-rw-r--r--compiler/rustc_middle/src/ty/fast_reject.rs4
-rw-r--r--compiler/rustc_middle/src/ty/flags.rs4
-rw-r--r--compiler/rustc_middle/src/ty/fold.rs18
-rw-r--r--compiler/rustc_middle/src/ty/generics.rs6
-rw-r--r--compiler/rustc_middle/src/ty/inhabitedness/mod.rs2
-rw-r--r--compiler/rustc_middle/src/ty/instance.rs6
-rw-r--r--compiler/rustc_middle/src/ty/layout.rs2
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs12
-rw-r--r--compiler/rustc_middle/src/ty/opaque_types.rs2
-rw-r--r--compiler/rustc_middle/src/ty/parameterized.rs2
-rw-r--r--compiler/rustc_middle/src/ty/print/mod.rs2
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs31
-rw-r--r--compiler/rustc_middle/src/ty/query.rs110
-rw-r--r--compiler/rustc_middle/src/ty/relate.rs5
-rw-r--r--compiler/rustc_middle/src/ty/structural_impls.rs3
-rw-r--r--compiler/rustc_middle/src/ty/sty.rs10
-rw-r--r--compiler/rustc_middle/src/ty/subst.rs8
-rw-r--r--compiler/rustc_middle/src/ty/trait_def.rs2
-rw-r--r--compiler/rustc_middle/src/ty/util.rs19
-rw-r--r--compiler/rustc_mir_build/src/build/expr/into.rs2
-rw-r--r--compiler/rustc_mir_build/src/build/matches/test.rs9
-rw-r--r--compiler/rustc_mir_build/src/build/mod.rs2
-rw-r--r--compiler/rustc_mir_build/src/thir/cx/mod.rs10
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs8
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/mod.rs6
-rw-r--r--compiler/rustc_mir_dataflow/src/impls/liveness.rs8
-rw-r--r--compiler/rustc_mir_transform/src/abort_unwinding_calls.rs2
-rw-r--r--compiler/rustc_mir_transform/src/const_prop.rs2
-rw-r--r--compiler/rustc_mir_transform/src/const_prop_lint.rs2
-rw-r--r--compiler/rustc_mir_transform/src/ctfe_limit.rs3
-rw-r--r--compiler/rustc_mir_transform/src/deduce_param_attrs.rs2
-rw-r--r--compiler/rustc_mir_transform/src/dest_prop.rs6
-rw-r--r--compiler/rustc_mir_transform/src/elaborate_box_derefs.rs6
-rw-r--r--compiler/rustc_mir_transform/src/ffi_unwind_calls.rs2
-rw-r--r--compiler/rustc_mir_transform/src/function_item_references.rs8
-rw-r--r--compiler/rustc_mir_transform/src/generator.rs6
-rw-r--r--compiler/rustc_mir_transform/src/inline.rs4
-rw-r--r--compiler/rustc_mir_transform/src/instcombine.rs6
-rw-r--r--compiler/rustc_mir_transform/src/large_enums.rs7
-rw-r--r--compiler/rustc_mir_transform/src/remove_zsts.rs2
-rw-r--r--compiler/rustc_mir_transform/src/shim.rs4
-rw-r--r--compiler/rustc_mir_transform/src/simplify.rs2
-rw-r--r--compiler/rustc_mir_transform/src/ssa.rs2
-rw-r--r--compiler/rustc_monomorphize/src/collector.rs3
-rw-r--r--compiler/rustc_monomorphize/src/partitioning/default.rs2
-rw-r--r--compiler/rustc_parse/src/lexer/mod.rs9
-rw-r--r--compiler/rustc_parse/src/parser/mod.rs24
-rw-r--r--compiler/rustc_parse/src/parser/path.rs2
-rw-r--r--compiler/rustc_parse/src/parser/ty.rs5
-rw-r--r--compiler/rustc_parse_format/src/lib.rs2
-rw-r--r--compiler/rustc_passes/src/check_attr.rs4
-rw-r--r--compiler/rustc_passes/src/dead.rs4
-rw-r--r--compiler/rustc_passes/src/diagnostic_items.rs7
-rw-r--r--compiler/rustc_passes/src/layout_test.rs2
-rw-r--r--compiler/rustc_passes/src/stability.rs2
-rw-r--r--compiler/rustc_privacy/src/lib.rs35
-rw-r--r--compiler/rustc_query_impl/src/lib.rs4
-rw-r--r--compiler/rustc_query_impl/src/plumbing.rs74
-rw-r--r--compiler/rustc_query_system/src/dep_graph/mod.rs6
-rw-r--r--compiler/rustc_query_system/src/dep_graph/serialized.rs3
-rw-r--r--compiler/rustc_query_system/src/query/caches.rs171
-rw-r--r--compiler/rustc_query_system/src/query/config.rs9
-rw-r--r--compiler/rustc_query_system/src/query/mod.rs16
-rw-r--r--compiler/rustc_query_system/src/query/plumbing.rs73
-rw-r--r--compiler/rustc_resolve/src/late.rs10
-rw-r--r--compiler/rustc_resolve/src/late/diagnostics.rs8
-rw-r--r--compiler/rustc_resolve/src/rustdoc.rs2
-rw-r--r--compiler/rustc_session/src/config.rs10
-rw-r--r--compiler/rustc_session/src/errors.rs28
-rw-r--r--compiler/rustc_session/src/filesearch.rs2
-rw-r--r--compiler/rustc_session/src/options.rs7
-rw-r--r--compiler/rustc_session/src/parse.rs6
-rw-r--r--compiler/rustc_session/src/session.rs4
-rw-r--r--compiler/rustc_span/src/def_id.rs4
-rw-r--r--compiler/rustc_span/src/symbol.rs1
-rw-r--r--compiler/rustc_symbol_mangling/src/legacy.rs2
-rw-r--r--compiler/rustc_symbol_mangling/src/lib.rs3
-rw-r--r--compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs31
-rw-r--r--compiler/rustc_target/src/spec/aarch64_apple_ios.rs7
-rw-r--r--compiler/rustc_target/src/spec/aarch64_apple_ios_sim.rs7
-rw-r--r--compiler/rustc_target/src/spec/aarch64_unknown_none.rs2
-rw-r--r--compiler/rustc_target/src/spec/armebv7r_none_eabi.rs2
-rw-r--r--compiler/rustc_target/src/spec/armebv7r_none_eabihf.rs2
-rw-r--r--compiler/rustc_target/src/spec/armv4t_none_eabi.rs2
-rw-r--r--compiler/rustc_target/src/spec/armv7a_none_eabi.rs2
-rw-r--r--compiler/rustc_target/src/spec/armv7a_none_eabihf.rs2
-rw-r--r--compiler/rustc_target/src/spec/armv7r_none_eabi.rs2
-rw-r--r--compiler/rustc_target/src/spec/armv7r_none_eabihf.rs2
-rw-r--r--compiler/rustc_target/src/spec/hexagon_unknown_linux_musl.rs2
-rw-r--r--compiler/rustc_target/src/spec/mod.rs34
-rw-r--r--compiler/rustc_target/src/spec/riscv64gc_unknown_none_elf.rs3
-rw-r--r--compiler/rustc_target/src/spec/riscv64imac_unknown_none_elf.rs3
-rw-r--r--compiler/rustc_target/src/spec/thumb_base.rs2
-rw-r--r--compiler/rustc_target/src/spec/thumbv4t_none_eabi.rs2
-rw-r--r--compiler/rustc_target/src/spec/x86_64_apple_ios.rs7
-rw-r--r--compiler/rustc_target/src/spec/x86_64_unknown_none.rs2
-rw-r--r--compiler/rustc_trait_selection/src/solve/mod.rs15
-rw-r--r--compiler/rustc_trait_selection/src/solve/project_goals.rs4
-rw-r--r--compiler/rustc_trait_selection/src/solve/trait_goals.rs4
-rw-r--r--compiler/rustc_trait_selection/src/solve/trait_goals/structural_traits.rs6
-rw-r--r--compiler/rustc_trait_selection/src/traits/auto_trait.rs1
-rw-r--r--compiler/rustc_trait_selection/src/traits/coherence.rs6
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs9
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs19
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs25
-rw-r--r--compiler/rustc_trait_selection/src/traits/fulfill.rs14
-rw-r--r--compiler/rustc_trait_selection/src/traits/mod.rs10
-rw-r--r--compiler/rustc_trait_selection/src/traits/object_safety.rs24
-rw-r--r--compiler/rustc_trait_selection/src/traits/project.rs16
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/normalize.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/type_op/outlives.rs6
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs9
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/confirmation.rs16
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/mod.rs22
-rw-r--r--compiler/rustc_trait_selection/src/traits/specialize/mod.rs8
-rw-r--r--compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/vtable.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/wf.rs5
-rw-r--r--compiler/rustc_traits/src/chalk/db.rs8
-rw-r--r--compiler/rustc_traits/src/chalk/lowering.rs24
-rw-r--r--compiler/rustc_traits/src/dropck_outlives.rs2
-rw-r--r--compiler/rustc_traits/src/implied_outlives_bounds.rs3
-rw-r--r--compiler/rustc_traits/src/normalize_erasing_regions.rs1
-rw-r--r--compiler/rustc_traits/src/type_op.rs4
-rw-r--r--compiler/rustc_ty_utils/src/abi.rs16
-rw-r--r--compiler/rustc_ty_utils/src/assoc.rs2
-rw-r--r--compiler/rustc_ty_utils/src/consts.rs2
-rw-r--r--compiler/rustc_ty_utils/src/implied_bounds.rs2
-rw-r--r--compiler/rustc_ty_utils/src/instance.rs3
-rw-r--r--compiler/rustc_ty_utils/src/layout.rs7
-rw-r--r--compiler/rustc_ty_utils/src/needs_drop.rs16
-rw-r--r--compiler/rustc_ty_utils/src/representability.rs4
-rw-r--r--compiler/rustc_ty_utils/src/ty.rs16
-rw-r--r--compiler/rustc_type_ir/src/lib.rs73
-rw-r--r--library/core/src/iter/traits/iterator.rs22
-rw-r--r--src/bootstrap/check.rs3
-rw-r--r--src/bootstrap/compile.rs73
-rw-r--r--src/bootstrap/config.rs5
-rwxr-xr-xsrc/bootstrap/configure.py26
-rw-r--r--src/bootstrap/flags.rs11
-rw-r--r--src/bootstrap/native.rs25
-rw-r--r--src/bootstrap/run.rs1
-rw-r--r--src/bootstrap/test.rs1
-rw-r--r--src/doc/unstable-book/src/compiler-flags/sanitizer.md20
-rw-r--r--src/librustdoc/clean/auto_trait.rs2
-rw-r--r--src/librustdoc/clean/blanket_impl.rs2
-rw-r--r--src/librustdoc/clean/inline.rs19
-rw-r--r--src/librustdoc/clean/mod.rs220
-rw-r--r--src/librustdoc/clean/utils.rs4
-rw-r--r--src/librustdoc/formats/cache.rs2
-rw-r--r--src/librustdoc/html/format.rs6
-rw-r--r--src/librustdoc/html/render/print_item.rs2
-rw-r--r--src/librustdoc/passes/collect_intra_doc_links.rs18
-rw-r--r--src/librustdoc/passes/collect_trait_impls.rs2
-rw-r--r--src/librustdoc/scrape_examples.rs2
m---------src/tools/cargo0
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/cast_ptr_alignment.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/copy_iterator.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/default.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/dereference.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/derivable_impls.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/derive.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/empty_enum.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/enum_clike.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/eta_reduction.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/implicit_saturating_sub.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/inherent_impl.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/large_enum_variant.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/rest_pat_in_fully_bound_struct.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/bytes_count_to_len.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/case_sensitive_file_extension_comparisons.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/get_first.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/implicit_clone.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/manual_ok_or.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/map_clone.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/map_err_ignore.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/mod.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/mut_mutex_lock.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/needless_collect.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/open_options.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/path_buf_push_overwrite.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/stable_sort_primitive.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/suspicious_splitn.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/unnecessary_sort_by.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/utils.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/vec_resize_to_zero.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/mut_reference.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/new_without_default.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/non_copy_const.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/ptr.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/redundant_slicing.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/self_named_constructors.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/use_self.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/internal_lints/interning_defined_symbol.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/internal_lints/msrv_attr_impl.rs1
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs4
-rw-r--r--src/tools/clippy/clippy_utils/src/eager_or_lazy.rs4
-rw-r--r--src/tools/clippy/clippy_utils/src/lib.rs4
-rw-r--r--src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs3
-rw-r--r--src/tools/clippy/clippy_utils/src/ty.rs4
-rw-r--r--src/tools/compiletest/src/header.rs2
-rw-r--r--src/tools/compiletest/src/util.rs13
-rw-r--r--src/tools/miri/rust-version2
-rw-r--r--src/tools/miri/src/eval.rs2
-rw-r--r--src/tools/miri/src/machine.rs4
-rw-r--r--src/tools/tidy/src/ui_tests.rs2
-rw-r--r--tests/codegen/sanitizer-kasan-emits-instrumentation.rs47
-rw-r--r--tests/mir-opt/funky_arms.float_to_exponential_common.ConstProp.diff10
-rw-r--r--tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.a.Inline.after.mir6
-rw-r--r--tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.b.Inline.after.mir18
-rw-r--r--tests/rustdoc/reexport-attr-merge.rs33
-rw-r--r--tests/ui/alloc-error/alloc-error-handler-bad-signature-3.stderr9
-rw-r--r--tests/ui/argument-suggestions/basic.stderr9
-rw-r--r--tests/ui/argument-suggestions/exotic-calls.stderr36
-rw-r--r--tests/ui/argument-suggestions/extra_arguments.stderr145
-rw-r--r--tests/ui/argument-suggestions/issue-101097.stderr6
-rw-r--r--tests/ui/argument-suggestions/issue-97484.stderr11
-rw-r--r--tests/ui/argument-suggestions/mixed_cases.stderr13
-rw-r--r--tests/ui/associated-types/issue-38821.rs (renamed from tests/ui/issues/issue-38821.rs)0
-rw-r--r--tests/ui/associated-types/issue-38821.stderr (renamed from tests/ui/issues/issue-38821.stderr)0
-rw-r--r--tests/ui/borrowck/issue-83924.fixed (renamed from tests/ui/issues/issue-83924.fixed)0
-rw-r--r--tests/ui/borrowck/issue-83924.rs (renamed from tests/ui/issues/issue-83924.rs)0
-rw-r--r--tests/ui/borrowck/issue-83924.stderr (renamed from tests/ui/issues/issue-83924.stderr)0
-rw-r--r--tests/ui/bounds-lifetime.stderr11
-rw-r--r--tests/ui/closures/binder/const-bound.rs7
-rw-r--r--tests/ui/closures/binder/const-bound.stderr17
-rw-r--r--tests/ui/closures/binder/disallow-const.stderr6
-rw-r--r--tests/ui/closures/binder/disallow-ty.stderr6
-rw-r--r--tests/ui/closures/binder/type-bound-2.rs7
-rw-r--r--tests/ui/closures/binder/type-bound-2.stderr17
-rw-r--r--tests/ui/closures/binder/type-bound.rs7
-rw-r--r--tests/ui/closures/binder/type-bound.stderr17
-rw-r--r--tests/ui/conditional-compilation/cfg-generic-params.stderr46
-rw-r--r--tests/ui/const-generics/nested-type.min.stderr11
-rw-r--r--tests/ui/const-generics/nested-type.rs2
-rw-r--r--tests/ui/consts/issue-33903.rs (renamed from tests/ui/issues/issue-33903.rs)0
-rw-r--r--tests/ui/consts/issue-54582.rs (renamed from tests/ui/issues/issue-54582.rs)0
-rw-r--r--tests/ui/drop/issue-2735-2.rs (renamed from tests/ui/issues/issue-2735-2.rs)0
-rw-r--r--tests/ui/drop/issue-2735-3.rs (renamed from tests/ui/issues/issue-2735-3.rs)0
-rw-r--r--tests/ui/drop/issue-2735.rs (renamed from tests/ui/issues/issue-2735.rs)0
-rw-r--r--tests/ui/error-codes/E0057.stderr9
-rw-r--r--tests/ui/feature-gates/feature-gate-non_lifetime_binders.rs4
-rw-r--r--tests/ui/feature-gates/feature-gate-non_lifetime_binders.stderr12
-rw-r--r--tests/ui/fmt/issue-75307.rs (renamed from tests/ui/issues/issue-75307.rs)0
-rw-r--r--tests/ui/fmt/issue-75307.stderr (renamed from tests/ui/issues/issue-75307.stderr)0
-rw-r--r--tests/ui/higher-rank-trait-bounds/hrtb-wrong-kind.stderr11
-rw-r--r--tests/ui/higher-rank-trait-bounds/issue-39292.rs (renamed from tests/ui/issues/issue-39292.rs)0
-rw-r--r--tests/ui/issues/issue-16939.stderr9
-rw-r--r--tests/ui/issues/issue-26094.rs2
-rw-r--r--tests/ui/issues/issue-26094.stderr9
-rw-r--r--tests/ui/issues/issue-4935.stderr9
-rw-r--r--tests/ui/lexer/issue-108019-bad-emoji-recovery.rs45
-rw-r--r--tests/ui/lexer/issue-108019-bad-emoji-recovery.stderr86
-rw-r--r--tests/ui/lint/issue-108155.rs15
-rw-r--r--tests/ui/loops/issue-50576.rs (renamed from tests/ui/issues/issue-50576.rs)0
-rw-r--r--tests/ui/loops/issue-50576.stderr (renamed from tests/ui/issues/issue-50576.stderr)0
-rw-r--r--tests/ui/methods/method-call-err-msg.stderr9
-rw-r--r--tests/ui/mismatched_types/overloaded-calls-bad.stderr7
-rw-r--r--tests/ui/moves/issue-22536-copy-mustnt-zero.rs (renamed from tests/ui/issues/issue-22536-copy-mustnt-zero.rs)0
-rw-r--r--tests/ui/nll/issue-27583.rs (renamed from tests/ui/issues/issue-27583.rs)0
-rw-r--r--tests/ui/nll/issue-48179.rs (renamed from tests/ui/issues/issue-48179.rs)0
-rw-r--r--tests/ui/nll/issue-75777.rs (renamed from tests/ui/issues/issue-75777.rs)0
-rw-r--r--tests/ui/nll/issue-75777.stderr (renamed from tests/ui/issues/issue-75777.stderr)0
-rw-r--r--tests/ui/parser/numeric-lifetime.rs4
-rw-r--r--tests/ui/parser/numeric-lifetime.stderr4
-rw-r--r--tests/ui/parser/recover-fn-ptr-with-generics.stderr12
-rw-r--r--tests/ui/recursion_limit/issue-40003.rs (renamed from tests/ui/issues/issue-40003.rs)0
-rw-r--r--tests/ui/repr/16-bit-repr-c-enum.rs52
-rw-r--r--tests/ui/resolve/resolve-primitive-fallback.stderr9
-rw-r--r--tests/ui/sanitize/cfg-kasan.rs28
-rw-r--r--tests/ui/span/issue-34264.stderr18
-rw-r--r--tests/ui/suggestions/args-instead-of-tuple-errors.stderr14
-rw-r--r--tests/ui/traits/alias/issue-108072-unmet-trait-alias-bound.rs11
-rw-r--r--tests/ui/traits/alias/issue-108072-unmet-trait-alias-bound.stderr19
-rw-r--r--tests/ui/traits/alias/issue-108132-unmet-trait-alias-bound-on-generic-impl.rs15
-rw-r--r--tests/ui/traits/alias/issue-108132-unmet-trait-alias-bound-on-generic-impl.stderr25
-rw-r--r--tests/ui/traits/non_lifetime_binders/basic.rs19
-rw-r--r--tests/ui/traits/non_lifetime_binders/basic.stderr11
-rw-r--r--tests/ui/traits/non_lifetime_binders/fail.rs23
-rw-r--r--tests/ui/traits/non_lifetime_binders/fail.stderr43
-rw-r--r--tests/ui/traits/non_lifetime_binders/on-dyn.rs13
-rw-r--r--tests/ui/traits/non_lifetime_binders/on-dyn.stderr17
-rw-r--r--tests/ui/traits/non_lifetime_binders/on-ptr.rs13
-rw-r--r--tests/ui/traits/non_lifetime_binders/on-ptr.stderr17
-rw-r--r--tests/ui/tuple/wrong_argument_ice-3.stderr7
-rw-r--r--tests/ui/tuple/wrong_argument_ice-4.stderr9
-rw-r--r--tests/ui/type/type-ascription-instead-of-initializer.stderr9
-rw-r--r--tests/ui/typeck/issue-53712.rs (renamed from tests/ui/issues/issue-53712.rs)0
-rw-r--r--tests/ui/typeck/issue-53712.stderr (renamed from tests/ui/issues/issue-53712.stderr)0
-rw-r--r--tests/ui/typeck/issue-7813.rs (renamed from tests/ui/issues/issue-7813.rs)0
-rw-r--r--tests/ui/typeck/issue-7813.stderr (renamed from tests/ui/issues/issue-7813.stderr)0
-rw-r--r--tests/ui/typeck/remove-extra-argument.stderr9
-rw-r--r--tests/ui/typeck/struct-enum-wrong-args.stderr36
-rw-r--r--triagebot.toml4
434 files changed, 3550 insertions, 2190 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 6a1525f7530..d02cab38ae8 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -782,7 +782,7 @@ dependencies = [
  "declare_clippy_lint",
  "if_chain",
  "itertools",
- "pulldown-cmark 0.9.2",
+ "pulldown-cmark",
  "quine-mc_cluskey",
  "regex-syntax",
  "rustc-semver",
@@ -2555,7 +2555,7 @@ dependencies = [
  "memchr",
  "once_cell",
  "opener",
- "pulldown-cmark 0.9.2",
+ "pulldown-cmark",
  "regex",
  "serde",
  "serde_json",
@@ -2572,7 +2572,7 @@ dependencies = [
  "anyhow",
  "handlebars 3.5.5",
  "pretty_assertions",
- "pulldown-cmark 0.7.2",
+ "pulldown-cmark",
  "same-file",
  "serde_json",
  "url",
@@ -3271,17 +3271,6 @@ dependencies = [
 
 [[package]]
 name = "pulldown-cmark"
-version = "0.7.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ca36dea94d187597e104a5c8e4b07576a8a45aa5db48a65e12940d3eb7461f55"
-dependencies = [
- "bitflags",
- "memchr",
- "unicase",
-]
-
-[[package]]
-name = "pulldown-cmark"
 version = "0.9.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "2d9cc634bc78768157b5cbfe988ffcd1dcba95cd2b2f03a88316c08c6d00ed63"
@@ -4583,7 +4572,7 @@ name = "rustc_resolve"
 version = "0.0.0"
 dependencies = [
  "bitflags",
- "pulldown-cmark 0.9.2",
+ "pulldown-cmark",
  "rustc_arena",
  "rustc_ast",
  "rustc_ast_pretty",
diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs
index c88a60c62b9..aa3a666b0b2 100644
--- a/compiler/rustc_abi/src/lib.rs
+++ b/compiler/rustc_abi/src/lib.rs
@@ -171,7 +171,9 @@ pub struct TargetDataLayout {
 
     pub instruction_address_space: AddressSpace,
 
-    /// Minimum size of #[repr(C)] enums (default I32 bits)
+    /// Minimum size of #[repr(C)] enums (default c_int::BITS, usually 32)
+    /// Note: This isn't in LLVM's data layout string, it is `short_enum`
+    /// so the only valid spec for LLVM is c_int::BITS or 8
     pub c_enum_min_size: Integer,
 }
 
diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs
index 902b4b1a1ec..d1ae8c1fdbd 100644
--- a/compiler/rustc_ast_passes/src/ast_validation.rs
+++ b/compiler/rustc_ast_passes/src/ast_validation.rs
@@ -271,7 +271,7 @@ impl<'a> AstValidator<'a> {
 
         self.session.emit_err(InvalidVisibility {
             span: vis.span,
-            implied: if vis.kind.is_pub() { Some(vis.span) } else { None },
+            implied: vis.kind.is_pub().then_some(vis.span),
             note,
         });
     }
@@ -294,27 +294,6 @@ impl<'a> AstValidator<'a> {
         }
     }
 
-    fn check_late_bound_lifetime_defs(&self, params: &[GenericParam]) {
-        // Check only lifetime parameters are present and that the lifetime
-        // parameters that are present have no bounds.
-        let non_lt_param_spans: Vec<_> = params
-            .iter()
-            .filter_map(|param| match param.kind {
-                GenericParamKind::Lifetime { .. } => {
-                    if !param.bounds.is_empty() {
-                        let spans: Vec<_> = param.bounds.iter().map(|b| b.span()).collect();
-                        self.session.emit_err(ForbiddenLifetimeBound { spans });
-                    }
-                    None
-                }
-                _ => Some(param.ident.span),
-            })
-            .collect();
-        if !non_lt_param_spans.is_empty() {
-            self.session.emit_err(ForbiddenNonLifetimeParam { spans: non_lt_param_spans });
-        }
-    }
-
     fn check_fn_decl(&self, fn_decl: &FnDecl, self_semantic: SelfSemantic) {
         self.check_decl_num_args(fn_decl);
         self.check_decl_cvaradic_pos(fn_decl);
@@ -745,7 +724,6 @@ impl<'a> AstValidator<'a> {
                     )
                     .emit();
                 });
-                self.check_late_bound_lifetime_defs(&bfty.generic_params);
                 if let Extern::Implicit(_) = bfty.ext {
                     let sig_span = self.session.source_map().next_point(ty.span.shrink_to_lo());
                     self.maybe_lint_missing_abi(sig_span, ty.id);
@@ -1318,9 +1296,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
         for predicate in &generics.where_clause.predicates {
             match predicate {
                 WherePredicate::BoundPredicate(bound_pred) => {
-                    // A type binding, eg `for<'c> Foo: Send+Clone+'c`
-                    self.check_late_bound_lifetime_defs(&bound_pred.bound_generic_params);
-
                     // This is slightly complicated. Our representation for poly-trait-refs contains a single
                     // binder and thus we only allow a single level of quantification. However,
                     // the syntax of Rust permits quantification in two places in where clauses,
@@ -1396,11 +1371,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
         visit::walk_param_bound(self, bound)
     }
 
-    fn visit_poly_trait_ref(&mut self, t: &'a PolyTraitRef) {
-        self.check_late_bound_lifetime_defs(&t.bound_generic_params);
-        visit::walk_poly_trait_ref(self, t);
-    }
-
     fn visit_variant_data(&mut self, s: &'a VariantData) {
         self.with_banned_assoc_ty_bound(|this| visit::walk_struct_def(this, s))
     }
@@ -1437,10 +1407,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                 .emit();
         }
 
-        if let FnKind::Closure(ClosureBinder::For { generic_params, .. }, ..) = fk {
-            self.check_late_bound_lifetime_defs(generic_params);
-        }
-
         if let FnKind::Fn(
             _,
             _,
diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs
index 89ba6f936d1..3af2ef4e727 100644
--- a/compiler/rustc_ast_passes/src/feature_gate.rs
+++ b/compiler/rustc_ast_passes/src/feature_gate.rs
@@ -11,6 +11,8 @@ use rustc_span::symbol::sym;
 use rustc_span::Span;
 use rustc_target::spec::abi;
 
+use crate::errors::ForbiddenLifetimeBound;
+
 macro_rules! gate_feature_fn {
     ($visitor: expr, $has_feature: expr, $span: expr, $name: expr, $explain: expr, $help: expr) => {{
         let (visitor, has_feature, span, name, explain, help) =
@@ -136,6 +138,34 @@ impl<'a> PostExpansionVisitor<'a> {
         }
         ImplTraitVisitor { vis: self }.visit_ty(ty);
     }
+
+    fn check_late_bound_lifetime_defs(&self, params: &[ast::GenericParam]) {
+        // Check only lifetime parameters are present and that the lifetime
+        // parameters that are present have no bounds.
+        let non_lt_param_spans: Vec<_> = params
+            .iter()
+            .filter_map(|param| match param.kind {
+                ast::GenericParamKind::Lifetime { .. } => None,
+                _ => Some(param.ident.span),
+            })
+            .collect();
+        // FIXME: gate_feature_post doesn't really handle multispans...
+        if !non_lt_param_spans.is_empty() && !self.features.non_lifetime_binders {
+            feature_err(
+                &self.sess.parse_sess,
+                sym::non_lifetime_binders,
+                non_lt_param_spans,
+                rustc_errors::fluent::ast_passes_forbidden_non_lifetime_param,
+            )
+            .emit();
+        }
+        for param in params {
+            if !param.bounds.is_empty() {
+                let spans: Vec<_> = param.bounds.iter().map(|b| b.span()).collect();
+                self.sess.emit_err(ForbiddenLifetimeBound { spans });
+            }
+        }
+    }
 }
 
 impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
@@ -147,7 +177,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
             ..
         }) = attr_info
         {
-            gate_feature_fn!(self, has_feature, attr.span, *name, descr);
+            gate_feature_fn!(self, has_feature, attr.span, *name, *descr);
         }
         // Check unstable flavors of the `#[doc]` attribute.
         if attr.has_name(sym::doc) {
@@ -306,6 +336,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
             ast::TyKind::BareFn(bare_fn_ty) => {
                 // Function pointers cannot be `const`
                 self.check_extern(bare_fn_ty.ext, ast::Const::No);
+                self.check_late_bound_lifetime_defs(&bare_fn_ty.generic_params);
             }
             ast::TyKind::Never => {
                 gate_feature_post!(&self, never_type, ty.span, "the `!` type is experimental");
@@ -318,6 +349,19 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
         visit::walk_ty(self, ty)
     }
 
+    fn visit_generics(&mut self, g: &'a ast::Generics) {
+        for predicate in &g.where_clause.predicates {
+            match predicate {
+                ast::WherePredicate::BoundPredicate(bound_pred) => {
+                    // A type binding, eg `for<'c> Foo: Send+Clone+'c`
+                    self.check_late_bound_lifetime_defs(&bound_pred.bound_generic_params);
+                }
+                _ => {}
+            }
+        }
+        visit::walk_generics(self, g);
+    }
+
     fn visit_fn_ret_ty(&mut self, ret_ty: &'a ast::FnRetTy) {
         if let ast::FnRetTy::Ty(output_ty) = ret_ty {
             if let ast::TyKind::Never = output_ty.kind {
@@ -437,12 +481,21 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
         visit::walk_pat(self, pattern)
     }
 
+    fn visit_poly_trait_ref(&mut self, t: &'a ast::PolyTraitRef) {
+        self.check_late_bound_lifetime_defs(&t.bound_generic_params);
+        visit::walk_poly_trait_ref(self, t);
+    }
+
     fn visit_fn(&mut self, fn_kind: FnKind<'a>, span: Span, _: NodeId) {
         if let Some(header) = fn_kind.header() {
             // Stability of const fn methods are covered in `visit_assoc_item` below.
             self.check_extern(header.ext, header.constness);
         }
 
+        if let FnKind::Closure(ast::ClosureBinder::For { generic_params, .. }, ..) = fn_kind {
+            self.check_late_bound_lifetime_defs(generic_params);
+        }
+
         if fn_kind.ctxt() != Some(FnCtxt::Foreign) && fn_kind.decl().c_variadic() {
             gate_feature_post!(&self, c_variadic, span, "C-variadic functions are unstable");
         }
diff --git a/compiler/rustc_attr/src/builtin.rs b/compiler/rustc_attr/src/builtin.rs
index 40531c1c164..3d240108b4a 100644
--- a/compiler/rustc_attr/src/builtin.rs
+++ b/compiler/rustc_attr/src/builtin.rs
@@ -731,7 +731,7 @@ pub fn eval_condition(
                             sess,
                             sym::cfg_target_compact,
                             cfg.span,
-                            &"compact `cfg(target(..))` is experimental and subject to change"
+                            "compact `cfg(target(..))` is experimental and subject to change"
                         ).emit();
                     }
 
diff --git a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs
index 1550958ab8e..d51cc652bfd 100644
--- a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs
@@ -180,20 +180,20 @@ trait TypeOpInfo<'tcx> {
             return;
         };
 
-        let placeholder_region = tcx.mk_region(ty::RePlaceholder(ty::Placeholder {
+        let placeholder_region = tcx.mk_re_placeholder(ty::Placeholder {
             name: placeholder.name,
             universe: adjusted_universe.into(),
-        }));
+        });
 
         let error_region =
             if let RegionElement::PlaceholderRegion(error_placeholder) = error_element {
                 let adjusted_universe =
                     error_placeholder.universe.as_u32().checked_sub(base_universe.as_u32());
                 adjusted_universe.map(|adjusted| {
-                    tcx.mk_region(ty::RePlaceholder(ty::Placeholder {
+                    tcx.mk_re_placeholder(ty::Placeholder {
                         name: error_placeholder.name,
                         universe: adjusted.into(),
-                    }))
+                    })
                 })
             } else {
                 None
@@ -390,7 +390,7 @@ fn try_extract_error_from_fulfill_cx<'tcx>(
         error_region,
         &region_constraints,
         |vid| ocx.infcx.region_var_origin(vid),
-        |vid| ocx.infcx.universe_of_region(ocx.infcx.tcx.mk_region(ty::ReVar(vid))),
+        |vid| ocx.infcx.universe_of_region(ocx.infcx.tcx.mk_re_var(vid)),
     )
 }
 
@@ -411,7 +411,7 @@ fn try_extract_error_from_region_constraints<'tcx>(
                 }
                 // FIXME: Should this check the universe of the var?
                 Constraint::VarSubReg(vid, sup) if sup == placeholder_region => {
-                    Some((infcx.tcx.mk_region(ty::ReVar(vid)), cause.clone()))
+                    Some((infcx.tcx.mk_re_var(vid), cause.clone()))
                 }
                 _ => None,
             }
diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index 7b07c2a4633..b2d72654a2a 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -1186,11 +1186,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                 return None;
             };
             debug!("checking call args for uses of inner_param: {:?}", args);
-            if args.contains(&Operand::Move(inner_param)) {
-                Some((loc, term))
-            } else {
-                None
-            }
+            args.contains(&Operand::Move(inner_param)).then_some((loc, term))
         }) else {
             debug!("no uses of inner_param found as a by-move call arg");
             return;
@@ -2596,7 +2592,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             if is_closure {
                 None
             } else {
-                let ty = self.infcx.tcx.type_of(self.mir_def_id());
+                let ty = self.infcx.tcx.type_of(self.mir_def_id()).subst_identity();
                 match ty.kind() {
                     ty::FnDef(_, _) | ty::FnPtr(_) => self.annotate_fn_sig(
                         self.mir_def_id(),
diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs
index c4e4e0517ec..f5bd99f15ab 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mod.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs
@@ -1185,7 +1185,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                     let parent_self_ty =
                         matches!(tcx.def_kind(parent_did), rustc_hir::def::DefKind::Impl { .. })
                             .then_some(parent_did)
-                            .and_then(|did| match tcx.type_of(did).kind() {
+                            .and_then(|did| match tcx.type_of(did).subst_identity().kind() {
                                 ty::Adt(def, ..) => Some(def.did()),
                                 _ => None,
                             });
diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
index 7901a5046ab..a2fa3018234 100644
--- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
@@ -575,7 +575,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
 
         let mut output_ty = self.regioncx.universal_regions().unnormalized_output_ty;
         if let ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) = *output_ty.kind() {
-            output_ty = self.infcx.tcx.type_of(def_id)
+            output_ty = self.infcx.tcx.type_of(def_id).subst_identity()
         };
 
         debug!("report_fnmut_error: output_ty={:?}", output_ty);
@@ -896,7 +896,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
             debug!(?fn_did, ?substs);
 
             // Only suggest this on function calls, not closures
-            let ty = tcx.type_of(fn_did);
+            let ty = tcx.type_of(fn_did).subst_identity();
             debug!("ty: {:?}, ty.kind: {:?}", ty, ty.kind());
             if let ty::Closure(_, _) = ty.kind() {
                 return;
diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs
index a82e695d649..f6881a2e5bc 100644
--- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs
@@ -280,17 +280,10 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
 
         debug!("give_region_a_name: error_region = {:?}", error_region);
         match *error_region {
-            ty::ReEarlyBound(ebr) => {
-                if ebr.has_name() {
-                    let span = tcx.hir().span_if_local(ebr.def_id).unwrap_or(DUMMY_SP);
-                    Some(RegionName {
-                        name: ebr.name,
-                        source: RegionNameSource::NamedEarlyBoundRegion(span),
-                    })
-                } else {
-                    None
-                }
-            }
+            ty::ReEarlyBound(ebr) => ebr.has_name().then(|| {
+                let span = tcx.hir().span_if_local(ebr.def_id).unwrap_or(DUMMY_SP);
+                RegionName { name: ebr.name, source: RegionNameSource::NamedEarlyBoundRegion(span) }
+            }),
 
             ty::ReStatic => {
                 Some(RegionName { name: kw::StaticLifetime, source: RegionNameSource::Static })
@@ -856,8 +849,9 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
             return None;
         };
 
-        let found = tcx
-            .any_free_region_meets(&tcx.type_of(region_parent), |r| *r == ty::ReEarlyBound(region));
+        let found = tcx.any_free_region_meets(&tcx.type_of(region_parent).subst_identity(), |r| {
+            *r == ty::ReEarlyBound(region)
+        });
 
         Some(RegionName {
             name: self.synthesize_region_name(),
diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs
index f2693bded59..83fdb6066c6 100644
--- a/compiler/rustc_borrowck/src/region_infer/mod.rs
+++ b/compiler/rustc_borrowck/src/region_infer/mod.rs
@@ -1297,7 +1297,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
             let vid = self.to_region_vid(r);
             let scc = self.constraint_sccs.scc(vid);
             let repr = self.scc_representatives[scc];
-            tcx.mk_region(ty::ReVar(repr))
+            tcx.mk_re_var(repr)
         })
     }
 
@@ -1719,7 +1719,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
             }
 
             // If not, report an error.
-            let member_region = infcx.tcx.mk_region(ty::ReVar(member_region_vid));
+            let member_region = infcx.tcx.mk_re_var(member_region_vid);
             errors_buffer.push(RegionErrorKind::UnexpectedHiddenRegion {
                 span: m_c.definition_span,
                 hidden_ty: m_c.hidden_ty,
diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
index c7b22d5f2e6..bb42301828d 100644
--- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
+++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
@@ -91,7 +91,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
                     }
                     None => {
                         subst_regions.push(vid);
-                        infcx.tcx.re_error_with_message(
+                        infcx.tcx.mk_re_error_with_message(
                             concrete_type.span,
                             "opaque type with non-universal region substs",
                         )
diff --git a/compiler/rustc_borrowck/src/type_check/liveness/mod.rs b/compiler/rustc_borrowck/src/type_check/liveness/mod.rs
index d5c401ae1c6..a411aec518e 100644
--- a/compiler/rustc_borrowck/src/type_check/liveness/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/liveness/mod.rs
@@ -50,13 +50,11 @@ pub(super) fn generate<'mir, 'tcx>(
         compute_relevant_live_locals(typeck.tcx(), &free_regions, &body);
     let facts_enabled = use_polonius || AllFacts::enabled(typeck.tcx());
 
-    let polonius_drop_used = if facts_enabled {
+    let polonius_drop_used = facts_enabled.then(|| {
         let mut drop_used = Vec::new();
         polonius::populate_access_facts(typeck, body, location_table, move_data, &mut drop_used);
-        Some(drop_used)
-    } else {
-        None
-    };
+        drop_used
+    });
 
     trace::trace(
         typeck,
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index 5b7adae66ac..004b945eada 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -137,7 +137,7 @@ pub(crate) fn type_check<'mir, 'tcx>(
     upvars: &[Upvar<'tcx>],
     use_polonius: bool,
 ) -> MirTypeckResults<'tcx> {
-    let implicit_region_bound = infcx.tcx.mk_region(ty::ReVar(universal_regions.fr_fn_body));
+    let implicit_region_bound = infcx.tcx.mk_re_var(universal_regions.fr_fn_body);
     let mut constraints = MirTypeckRegionConstraints {
         placeholder_indices: PlaceholderIndices::default(),
         placeholder_index_to_region: IndexVec::default(),
@@ -402,7 +402,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
                     );
                 }
             } else if let Some(static_def_id) = constant.check_static_ptr(tcx) {
-                let unnormalized_ty = tcx.type_of(static_def_id);
+                let unnormalized_ty = tcx.type_of(static_def_id).subst_identity();
                 let normalized_ty = self.cx.normalize(unnormalized_ty, locations);
                 let literal_ty = constant.literal.ty().builtin_deref(true).unwrap().ty;
 
@@ -2589,7 +2589,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
             DefKind::InlineConst => substs.as_inline_const().parent_substs(),
             other => bug!("unexpected item {:?}", other),
         };
-        let parent_substs = tcx.mk_substs(parent_substs.iter());
+        let parent_substs = tcx.intern_substs(parent_substs);
 
         assert_eq!(typeck_root_substs.len(), parent_substs.len());
         if let Err(_) = self.eq_substs(
diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs
index 56930c89b2c..efa5a29c5dd 100644
--- a/compiler/rustc_borrowck/src/universal_regions.rs
+++ b/compiler/rustc_borrowck/src/universal_regions.rs
@@ -480,15 +480,10 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
                     LangItem::VaList,
                     Some(self.infcx.tcx.def_span(self.mir_def.did)),
                 );
-                let region = self
-                    .infcx
-                    .tcx
-                    .mk_region(ty::ReVar(self.infcx.next_nll_region_var(FR).to_region_vid()));
-                let va_list_ty = self
-                    .infcx
-                    .tcx
-                    .bound_type_of(va_list_did)
-                    .subst(self.infcx.tcx, &[region.into()]);
+                let region =
+                    self.infcx.tcx.mk_re_var(self.infcx.next_nll_region_var(FR).to_region_vid());
+                let va_list_ty =
+                    self.infcx.tcx.type_of(va_list_did).subst(self.infcx.tcx, &[region.into()]);
 
                 unnormalized_input_tys = self.infcx.tcx.mk_type_list(
                     unnormalized_input_tys.iter().copied().chain(iter::once(va_list_ty)),
@@ -531,7 +526,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
         match tcx.hir().body_owner_kind(self.mir_def.did) {
             BodyOwnerKind::Closure | BodyOwnerKind::Fn => {
                 let defining_ty = if self.mir_def.did.to_def_id() == typeck_root_def_id {
-                    tcx.type_of(typeck_root_def_id)
+                    tcx.type_of(typeck_root_def_id).subst_identity()
                 } else {
                     let tables = tcx.typeck(self.mir_def.did);
                     tables.node_type(self.mir_hir_id)
@@ -636,7 +631,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
                     var: ty::BoundVar::from_usize(bound_vars.len() - 1),
                     kind: ty::BrEnv,
                 };
-                let env_region = ty::ReLateBound(ty::INNERMOST, br);
+                let env_region = tcx.mk_re_late_bound(ty::INNERMOST, br);
                 let closure_ty = tcx.closure_env_ty(def_id, substs, env_region).unwrap();
 
                 // The "inputs" of the closure in the
@@ -677,7 +672,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
                 // For a constant body, there are no inputs, and one
                 // "output" (the type of the constant).
                 assert_eq!(self.mir_def.did.to_def_id(), def_id);
-                let ty = tcx.type_of(self.mir_def.def_id_for_type_of());
+                let ty = tcx.type_of(self.mir_def.def_id_for_type_of()).subst_identity();
                 let ty = indices.fold_to_region_vids(tcx, ty);
                 ty::Binder::dummy(tcx.intern_type_list(&[ty]))
             }
@@ -748,10 +743,7 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
     {
         let (value, _map) = self.tcx.replace_late_bound_regions(value, |br| {
             debug!(?br);
-            let liberated_region = self.tcx.mk_region(ty::ReFree(ty::FreeRegion {
-                scope: all_outlive_scope.to_def_id(),
-                bound_region: br.kind,
-            }));
+            let liberated_region = self.tcx.mk_re_free(all_outlive_scope.to_def_id(), br.kind);
             let region_vid = self.next_nll_region_var(origin);
             indices.insert_late_bound_region(liberated_region, region_vid.to_region_vid());
             debug!(?liberated_region, ?region_vid);
@@ -843,7 +835,7 @@ impl<'tcx> UniversalRegionIndices<'tcx> {
     where
         T: TypeFoldable<'tcx>,
     {
-        tcx.fold_regions(value, |region, _| tcx.mk_region(ty::ReVar(self.to_region_vid(region))))
+        tcx.fold_regions(value, |region, _| tcx.mk_re_var(self.to_region_vid(region)))
     }
 }
 
@@ -883,8 +875,7 @@ fn for_each_late_bound_region_in_item<'tcx>(
 
     for bound_var in tcx.late_bound_vars(tcx.hir().local_def_id_to_hir_id(mir_def_id)) {
         let ty::BoundVariableKind::Region(bound_region) = bound_var else { continue; };
-        let liberated_region = tcx
-            .mk_region(ty::ReFree(ty::FreeRegion { scope: mir_def_id.to_def_id(), bound_region }));
+        let liberated_region = tcx.mk_re_free(mir_def_id.to_def_id(), bound_region);
         f(liberated_region);
     }
 }
diff --git a/compiler/rustc_builtin_macros/src/deriving/debug.rs b/compiler/rustc_builtin_macros/src/deriving/debug.rs
index e8a353b1c8f..d30e8ba4b93 100644
--- a/compiler/rustc_builtin_macros/src/deriving/debug.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/debug.rs
@@ -135,19 +135,17 @@ fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>
         }
 
         // `let names: &'static _ = &["field1", "field2"];`
-        let names_let = if is_struct {
+        let names_let = is_struct.then(|| {
             let lt_static = Some(cx.lifetime_static(span));
             let ty_static_ref = cx.ty_ref(span, cx.ty_infer(span), lt_static, ast::Mutability::Not);
-            Some(cx.stmt_let_ty(
+            cx.stmt_let_ty(
                 span,
                 false,
                 Ident::new(sym::names, span),
                 Some(ty_static_ref),
                 cx.expr_array_ref(span, name_exprs),
-            ))
-        } else {
-            None
-        };
+            )
+        });
 
         // `let values: &[&dyn Debug] = &[&&self.field1, &&self.field2];`
         let path_debug = cx.path_global(span, cx.std_path(&[sym::fmt, sym::Debug]));
diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
index dd5c85531fd..38878ba7012 100644
--- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
@@ -941,13 +941,11 @@ impl<'a> MethodDef<'a> {
         let mut nonself_arg_tys = Vec::new();
         let span = trait_.span;
 
-        let explicit_self = if self.explicit_self {
+        let explicit_self = self.explicit_self.then(|| {
             let (self_expr, explicit_self) = ty::get_explicit_self(cx, span);
             selflike_args.push(self_expr);
-            Some(explicit_self)
-        } else {
-            None
-        };
+            explicit_self
+        });
 
         for (ty, name) in self.nonself_args.iter() {
             let ast_ty = ty.to_ty(cx, span, type_ident, generics);
diff --git a/compiler/rustc_builtin_macros/src/standard_library_imports.rs b/compiler/rustc_builtin_macros/src/standard_library_imports.rs
index f73f20c84a3..e67c0dba685 100644
--- a/compiler/rustc_builtin_macros/src/standard_library_imports.rs
+++ b/compiler/rustc_builtin_macros/src/standard_library_imports.rs
@@ -62,7 +62,7 @@ pub fn inject(
     // the one with the prelude.
     let name = names[0];
 
-    let root = (edition == Edition2015).then(|| kw::PathRoot);
+    let root = (edition == Edition2015).then_some(kw::PathRoot);
 
     let import_path = root
         .iter()
diff --git a/compiler/rustc_codegen_cranelift/src/codegen_i128.rs b/compiler/rustc_codegen_cranelift/src/codegen_i128.rs
index 638b2d573b5..b4a2537b5ea 100644
--- a/compiler/rustc_codegen_cranelift/src/codegen_i128.rs
+++ b/compiler/rustc_codegen_cranelift/src/codegen_i128.rs
@@ -56,7 +56,7 @@ pub(crate) fn maybe_codegen<'tcx>(
                     Some(fx.easy_call("__multi3", &[lhs, rhs], val_ty))
                 }
             } else {
-                let out_ty = fx.tcx.mk_tup([lhs.layout().ty, fx.tcx.types.bool].iter());
+                let out_ty = fx.tcx.intern_tup(&[lhs.layout().ty, fx.tcx.types.bool]);
                 let oflow = CPlace::new_stack_slot(fx, fx.layout_of(fx.tcx.types.i32));
                 let lhs = lhs.load_scalar(fx);
                 let rhs = rhs.load_scalar(fx);
@@ -78,7 +78,7 @@ pub(crate) fn maybe_codegen<'tcx>(
         }
         BinOp::Add | BinOp::Sub | BinOp::Mul => {
             assert!(checked);
-            let out_ty = fx.tcx.mk_tup([lhs.layout().ty, fx.tcx.types.bool].iter());
+            let out_ty = fx.tcx.intern_tup(&[lhs.layout().ty, fx.tcx.types.bool]);
             let out_place = CPlace::new_stack_slot(fx, fx.layout_of(out_ty));
             let (param_types, args) = if fx.tcx.sess.target.is_like_windows {
                 let (lhs_ptr, lhs_extra) = lhs.force_stack(fx);
diff --git a/compiler/rustc_codegen_cranelift/src/driver/aot.rs b/compiler/rustc_codegen_cranelift/src/driver/aot.rs
index 58b01dfb5b0..7c6fd9f6f1e 100644
--- a/compiler/rustc_codegen_cranelift/src/driver/aot.rs
+++ b/compiler/rustc_codegen_cranelift/src/driver/aot.rs
@@ -248,17 +248,13 @@ fn reuse_workproduct_for_cgu(
             dwarf_object: None,
             bytecode: None,
         },
-        module_global_asm: if has_global_asm {
-            Some(CompiledModule {
-                name: cgu.name().to_string(),
-                kind: ModuleKind::Regular,
-                object: Some(obj_out_global_asm),
-                dwarf_object: None,
-                bytecode: None,
-            })
-        } else {
-            None
-        },
+        module_global_asm: has_global_asm.then(|| CompiledModule {
+            name: cgu.name().to_string(),
+            kind: ModuleKind::Regular,
+            object: Some(obj_out_global_asm),
+            dwarf_object: None,
+            bytecode: None,
+        }),
         existing_work_product: Some((cgu.work_product_id(), work_product)),
     })
 }
diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs
index d2ae6978ca2..cbac2e66765 100644
--- a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs
+++ b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs
@@ -191,7 +191,7 @@ fn llvm_add_sub<'tcx>(
     // carry0 | carry1 -> carry or borrow respectively
     let cb_out = fx.bcx.ins().bor(cb0, cb1);
 
-    let layout = fx.layout_of(fx.tcx.mk_tup([fx.tcx.types.u8, fx.tcx.types.u64].iter()));
+    let layout = fx.layout_of(fx.tcx.intern_tup(&[fx.tcx.types.u8, fx.tcx.types.u64]));
     let val = CValue::by_val_pair(cb_out, c, layout);
     ret.write_cvalue(fx, val);
 }
diff --git a/compiler/rustc_codegen_cranelift/src/main_shim.rs b/compiler/rustc_codegen_cranelift/src/main_shim.rs
index 3e3b6857134..26327107df4 100644
--- a/compiler/rustc_codegen_cranelift/src/main_shim.rs
+++ b/compiler/rustc_codegen_cranelift/src/main_shim.rs
@@ -119,7 +119,7 @@ pub(crate) fn maybe_create_entry_wrapper(
                     tcx,
                     ParamEnv::reveal_all(),
                     report.def_id,
-                    tcx.mk_substs([GenericArg::from(main_ret_ty)].iter()),
+                    tcx.intern_substs(&[GenericArg::from(main_ret_ty)]),
                 )
                 .unwrap()
                 .unwrap()
diff --git a/compiler/rustc_codegen_cranelift/src/num.rs b/compiler/rustc_codegen_cranelift/src/num.rs
index afacbec6445..05905a7bcdf 100644
--- a/compiler/rustc_codegen_cranelift/src/num.rs
+++ b/compiler/rustc_codegen_cranelift/src/num.rs
@@ -289,7 +289,7 @@ pub(crate) fn codegen_checked_int_binop<'tcx>(
         _ => bug!("binop {:?} on checked int/uint lhs: {:?} rhs: {:?}", bin_op, in_lhs, in_rhs),
     };
 
-    let out_layout = fx.layout_of(fx.tcx.mk_tup([in_lhs.layout().ty, fx.tcx.types.bool].iter()));
+    let out_layout = fx.layout_of(fx.tcx.intern_tup(&[in_lhs.layout().ty, fx.tcx.types.bool]));
     CValue::by_val_pair(res, has_overflow, out_layout)
 }
 
diff --git a/compiler/rustc_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs
index 7a4ec494c8e..651d644ebb6 100644
--- a/compiler/rustc_codegen_llvm/src/attributes.rs
+++ b/compiler/rustc_codegen_llvm/src/attributes.rs
@@ -62,7 +62,7 @@ pub fn sanitize_attrs<'ll>(
 ) -> SmallVec<[&'ll Attribute; 4]> {
     let mut attrs = SmallVec::new();
     let enabled = cx.tcx.sess.opts.unstable_opts.sanitizer - no_sanitize;
-    if enabled.contains(SanitizerSet::ADDRESS) {
+    if enabled.contains(SanitizerSet::ADDRESS) || enabled.contains(SanitizerSet::KERNELADDRESS) {
         attrs.push(llvm::AttributeKind::SanitizeAddress.create_attr(cx.llcx));
     }
     if enabled.contains(SanitizerSet::MEMORY) {
diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs
index 38f8733763d..40f0594b40d 100644
--- a/compiler/rustc_codegen_llvm/src/back/write.rs
+++ b/compiler/rustc_codegen_llvm/src/back/write.rs
@@ -412,11 +412,7 @@ fn get_pgo_sample_use_path(config: &ModuleConfig) -> Option<CString> {
 }
 
 fn get_instr_profile_output_path(config: &ModuleConfig) -> Option<CString> {
-    if config.instrument_coverage {
-        Some(CString::new("default_%m_%p.profraw").unwrap())
-    } else {
-        None
-    }
+    config.instrument_coverage.then(|| CString::new("default_%m_%p.profraw").unwrap())
 }
 
 pub(crate) unsafe fn llvm_optimize(
@@ -446,16 +442,19 @@ pub(crate) unsafe fn llvm_optimize(
             sanitize_thread: config.sanitizer.contains(SanitizerSet::THREAD),
             sanitize_hwaddress: config.sanitizer.contains(SanitizerSet::HWADDRESS),
             sanitize_hwaddress_recover: config.sanitizer_recover.contains(SanitizerSet::HWADDRESS),
+            sanitize_kernel_address: config.sanitizer.contains(SanitizerSet::KERNELADDRESS),
+            sanitize_kernel_address_recover: config
+                .sanitizer_recover
+                .contains(SanitizerSet::KERNELADDRESS),
         })
     } else {
         None
     };
 
-    let mut llvm_profiler = if cgcx.prof.llvm_recording_enabled() {
-        Some(LlvmSelfProfiler::new(cgcx.prof.get_self_profiler().unwrap()))
-    } else {
-        None
-    };
+    let mut llvm_profiler = cgcx
+        .prof
+        .llvm_recording_enabled()
+        .then(|| LlvmSelfProfiler::new(cgcx.prof.get_self_profiler().unwrap()));
 
     let llvm_selfprofiler =
         llvm_profiler.as_mut().map(|s| s as *mut _ as *mut c_void).unwrap_or(std::ptr::null_mut());
diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs
index 92629aa18d4..9116e71beac 100644
--- a/compiler/rustc_codegen_llvm/src/consts.rs
+++ b/compiler/rustc_codegen_llvm/src/consts.rs
@@ -521,7 +521,7 @@ impl<'ll> StaticMethods for CodegenCx<'ll, '_> {
 
                 // The semantics of #[used] in Rust only require the symbol to make it into the
                 // object file. It is explicitly allowed for the linker to strip the symbol if it
-                // is dead, which means we are allowed use `llvm.compiler.used` instead of
+                // is dead, which means we are allowed to use `llvm.compiler.used` instead of
                 // `llvm.used` here.
                 //
                 // Additionally, https://reviews.llvm.org/D97448 in LLVM 13 started emitting unique
@@ -532,7 +532,7 @@ impl<'ll> StaticMethods for CodegenCx<'ll, '_> {
                 // That said, we only ever emit these when compiling for ELF targets, unless
                 // `#[used(compiler)]` is explicitly requested. This is to avoid similar breakage
                 // on other targets, in particular MachO targets have *their* static constructor
-                // lists broken if `llvm.compiler.used` is emitted rather than llvm.used. However,
+                // lists broken if `llvm.compiler.used` is emitted rather than `llvm.used`. However,
                 // that check happens when assigning the `CodegenFnAttrFlags` in `rustc_hir_analysis`,
                 // so we don't need to take care of it here.
                 self.add_compiler_used_global(g);
diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs
index 120dc59dfb3..37ee0e14020 100644
--- a/compiler/rustc_codegen_llvm/src/context.rs
+++ b/compiler/rustc_codegen_llvm/src/context.rs
@@ -145,8 +145,13 @@ pub unsafe fn create_module<'ll>(
     let llvm_version = llvm_util::get_version();
     if llvm_version < (16, 0, 0) {
         if sess.target.arch == "s390x" {
+            // LLVM 16 data layout changed to always set 64-bit vector alignment,
+            // which is conditional in earlier LLVM versions.
+            // https://reviews.llvm.org/D131158 for the discussion.
             target_data_layout = target_data_layout.replace("-v128:64", "");
         } else if sess.target.arch == "riscv64" {
+            // LLVM 16 introduced this change so as to produce more efficient code.
+            // See https://reviews.llvm.org/D116735 for the discussion.
             target_data_layout = target_data_layout.replace("-n32:64-", "-n64-");
         }
     }
@@ -402,12 +407,8 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
 
         let (llcx, llmod) = (&*llvm_module.llcx, llvm_module.llmod());
 
-        let coverage_cx = if tcx.sess.instrument_coverage() {
-            let covctx = coverageinfo::CrateCoverageContext::new();
-            Some(covctx)
-        } else {
-            None
-        };
+        let coverage_cx =
+            tcx.sess.instrument_coverage().then(coverageinfo::CrateCoverageContext::new);
 
         let dbg_cx = if tcx.sess.opts.debuginfo != DebugInfo::None {
             let dctx = debuginfo::CodegenUnitDebugContext::new(llmod);
diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs
index ace15cfb024..3dc0ac03312 100644
--- a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs
+++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs
@@ -27,8 +27,6 @@ use rustc_middle::ty::Instance;
 use std::cell::RefCell;
 use std::ffi::CString;
 
-use std::iter;
-
 pub mod mapgen;
 
 const UNUSED_FUNCTION_COUNTER_ID: CounterValueReference = CounterValueReference::START;
@@ -201,7 +199,7 @@ fn declare_unused_fn<'tcx>(cx: &CodegenCx<'_, 'tcx>, def_id: DefId) -> Instance<
         tcx.symbol_name(instance).name,
         cx.fn_abi_of_fn_ptr(
             ty::Binder::dummy(tcx.mk_fn_sig(
-                iter::once(tcx.mk_unit()),
+                [tcx.mk_unit()],
                 tcx.mk_unit(),
                 false,
                 hir::Unsafety::Unsafe,
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
index ca7a07d8391..cef403b9f8b 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
@@ -508,7 +508,7 @@ impl<'ll, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> {
                     let impl_self_ty = cx.tcx.subst_and_normalize_erasing_regions(
                         instance.substs,
                         ty::ParamEnv::reveal_all(),
-                        cx.tcx.type_of(impl_def_id),
+                        cx.tcx.type_of(impl_def_id).skip_binder(),
                     );
 
                     // Only "class" methods are generally understood by LLVM,
diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs
index b0295481ca5..39afb4af6f6 100644
--- a/compiler/rustc_codegen_llvm/src/intrinsic.rs
+++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs
@@ -22,7 +22,6 @@ use rustc_target::abi::{self, Align, HasDataLayout, Primitive};
 use rustc_target::spec::{HasTargetSpec, PanicStrategy};
 
 use std::cmp::Ordering;
-use std::iter;
 
 fn get_simple_intrinsic<'ll>(
     cx: &CodegenCx<'ll, '_>,
@@ -798,7 +797,7 @@ fn get_rust_try_fn<'ll, 'tcx>(
     let i8p = tcx.mk_mut_ptr(tcx.types.i8);
     // `unsafe fn(*mut i8) -> ()`
     let try_fn_ty = tcx.mk_fn_ptr(ty::Binder::dummy(tcx.mk_fn_sig(
-        iter::once(i8p),
+        [i8p],
         tcx.mk_unit(),
         false,
         hir::Unsafety::Unsafe,
@@ -806,7 +805,7 @@ fn get_rust_try_fn<'ll, 'tcx>(
     )));
     // `unsafe fn(*mut i8, *mut i8) -> ()`
     let catch_fn_ty = tcx.mk_fn_ptr(ty::Binder::dummy(tcx.mk_fn_sig(
-        [i8p, i8p].iter().cloned(),
+        [i8p, i8p],
         tcx.mk_unit(),
         false,
         hir::Unsafety::Unsafe,
@@ -814,7 +813,7 @@ fn get_rust_try_fn<'ll, 'tcx>(
     )));
     // `unsafe fn(unsafe fn(*mut i8) -> (), *mut i8, unsafe fn(*mut i8, *mut i8) -> ()) -> i32`
     let rust_fn_sig = ty::Binder::dummy(cx.tcx.mk_fn_sig(
-        [try_fn_ty, i8p, catch_fn_ty].into_iter(),
+        [try_fn_ty, i8p, catch_fn_ty],
         tcx.types.i32,
         false,
         hir::Unsafety::Unsafe,
diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
index 8b4861962b2..7aab666fc5e 100644
--- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
@@ -482,6 +482,8 @@ pub struct SanitizerOptions {
     pub sanitize_thread: bool,
     pub sanitize_hwaddress: bool,
     pub sanitize_hwaddress_recover: bool,
+    pub sanitize_kernel_address: bool,
+    pub sanitize_kernel_address_recover: bool,
 }
 
 /// LLVMRelocMode
diff --git a/compiler/rustc_codegen_llvm/src/type_of.rs b/compiler/rustc_codegen_llvm/src/type_of.rs
index 0cb4bc806a1..cc8ff947fc3 100644
--- a/compiler/rustc_codegen_llvm/src/type_of.rs
+++ b/compiler/rustc_codegen_llvm/src/type_of.rs
@@ -154,7 +154,7 @@ fn struct_llfields<'a, 'tcx>(
     } else {
         debug!("struct_llfields: offset: {:?} stride: {:?}", offset, layout.size);
     }
-    let field_remapping = if padding_used { Some(field_remapping) } else { None };
+    let field_remapping = padding_used.then_some(field_remapping);
     (result, packed, field_remapping)
 }
 
diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs
index 6fe8527ada6..8aa744ce935 100644
--- a/compiler/rustc_codegen_ssa/src/back/link.rs
+++ b/compiler/rustc_codegen_ssa/src/back/link.rs
@@ -2024,7 +2024,7 @@ fn linker_with_args<'a>(
         .native_libraries
         .iter()
         .filter_map(|(cnum, libraries)| {
-            (dependency_linkage[cnum.as_usize() - 1] != Linkage::Static).then(|| libraries)
+            (dependency_linkage[cnum.as_usize() - 1] != Linkage::Static).then_some(libraries)
         })
         .flatten();
     for (raw_dylib_name, raw_dylib_imports) in
diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs
index 6e136db3895..023d38e9312 100644
--- a/compiler/rustc_codegen_ssa/src/base.rs
+++ b/compiler/rustc_codegen_ssa/src/base.rs
@@ -579,7 +579,7 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
         }
     }
 
-    let metadata_module = if need_metadata_module {
+    let metadata_module = need_metadata_module.then(|| {
         // Emit compressed metadata object.
         let metadata_cgu_name =
             cgu_name_builder.build_cgu_name(LOCAL_CRATE, &["crate"], Some("metadata")).to_string();
@@ -594,17 +594,15 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
             if let Err(error) = std::fs::write(&file_name, data) {
                 tcx.sess.emit_fatal(errors::MetadataObjectFileWrite { error });
             }
-            Some(CompiledModule {
+            CompiledModule {
                 name: metadata_cgu_name,
                 kind: ModuleKind::Metadata,
                 object: Some(file_name),
                 dwarf_object: None,
                 bytecode: None,
-            })
+            }
         })
-    } else {
-        None
-    };
+    });
 
     let ongoing_codegen = start_async_codegen(
         backend.clone(),
diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
index 3ebbb2cbdfb..7d5c0048626 100644
--- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
+++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
@@ -295,7 +295,8 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: DefId) -> CodegenFnAttrs {
             if let Some(list) = attr.meta_item_list() {
                 for item in list.iter() {
                     if item.has_name(sym::address) {
-                        codegen_fn_attrs.no_sanitize |= SanitizerSet::ADDRESS;
+                        codegen_fn_attrs.no_sanitize |=
+                            SanitizerSet::ADDRESS | SanitizerSet::KERNELADDRESS;
                     } else if item.has_name(sym::cfi) {
                         codegen_fn_attrs.no_sanitize |= SanitizerSet::CFI;
                     } else if item.has_name(sym::kcfi) {
diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs
index d5530c47680..7d51cee307e 100644
--- a/compiler/rustc_codegen_ssa/src/lib.rs
+++ b/compiler/rustc_codegen_ssa/src/lib.rs
@@ -13,7 +13,7 @@
 
 //! This crate contains codegen code that is used by all codegen backends (LLVM and others).
 //! The backend-agnostic functions of this crate use functions defined in various traits that
-//! have to be implemented by each backends.
+//! have to be implemented by each backend.
 
 #[macro_use]
 extern crate rustc_macros;
diff --git a/compiler/rustc_codegen_ssa/src/mir/mod.rs b/compiler/rustc_codegen_ssa/src/mir/mod.rs
index de1734332d4..eec91ffa44a 100644
--- a/compiler/rustc_codegen_ssa/src/mir/mod.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/mod.rs
@@ -167,8 +167,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
         start_bx.set_personality_fn(cx.eh_personality());
     }
 
-    let cleanup_kinds =
-        if base::wants_msvc_seh(cx.tcx().sess) { Some(analyze::cleanup_kinds(&mir)) } else { None };
+    let cleanup_kinds = base::wants_msvc_seh(cx.tcx().sess).then(|| analyze::cleanup_kinds(&mir));
 
     let cached_llbbs: IndexVec<mir::BasicBlock, CachedLlbb<Bx::BasicBlock>> =
         mir.basic_blocks
diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs
index a6afbad5b24..0432a9c5a12 100644
--- a/compiler/rustc_codegen_ssa/src/target_features.rs
+++ b/compiler/rustc_codegen_ssa/src/target_features.rs
@@ -286,6 +286,7 @@ const WASM_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
     ("mutable-globals", Some(sym::wasm_target_feature)),
     ("nontrapping-fptoint", Some(sym::wasm_target_feature)),
     ("reference-types", Some(sym::wasm_target_feature)),
+    ("relaxed-simd", Some(sym::wasm_target_feature)),
     ("sign-ext", Some(sym::wasm_target_feature)),
     ("simd128", None),
     // tidy-alphabetical-end
diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics/caller_location.rs b/compiler/rustc_const_eval/src/interpret/intrinsics/caller_location.rs
index 5042c6bac99..f6a3937870e 100644
--- a/compiler/rustc_const_eval/src/interpret/intrinsics/caller_location.rs
+++ b/compiler/rustc_const_eval/src/interpret/intrinsics/caller_location.rs
@@ -95,8 +95,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         // Allocate memory for `CallerLocation` struct.
         let loc_ty = self
             .tcx
-            .bound_type_of(self.tcx.require_lang_item(LangItem::PanicLocation, None))
-            .subst(*self.tcx, self.tcx.mk_substs([self.tcx.lifetimes.re_erased.into()].iter()));
+            .type_of(self.tcx.require_lang_item(LangItem::PanicLocation, None))
+            .subst(*self.tcx, self.tcx.intern_substs(&[self.tcx.lifetimes.re_erased.into()]));
         let loc_layout = self.layout_of(loc_ty).unwrap();
         let location = self.allocate(loc_layout, MemoryKind::CallerLocation).unwrap();
 
diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs
index 635987d039e..f4e03ad8c59 100644
--- a/compiler/rustc_const_eval/src/interpret/memory.rs
+++ b/compiler/rustc_const_eval/src/interpret/memory.rs
@@ -690,7 +690,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 assert!(self.tcx.is_static(def_id));
                 assert!(!self.tcx.is_thread_local_static(def_id));
                 // Use size and align of the type.
-                let ty = self.tcx.type_of(def_id);
+                let ty = self
+                    .tcx
+                    .type_of(def_id)
+                    .no_bound_vars()
+                    .expect("statics should not have generic parameters");
                 let layout = self.tcx.layout_of(ParamEnv::empty().and(ty)).unwrap();
                 assert!(layout.is_sized());
                 (layout.size, layout.align.abi, AllocKind::LiveData)
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/mod.rs b/compiler/rustc_const_eval/src/transform/check_consts/mod.rs
index e841500bf3e..0e4501922f4 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/mod.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/mod.rs
@@ -68,7 +68,7 @@ impl<'mir, 'tcx> ConstCx<'mir, 'tcx> {
     pub fn fn_sig(&self) -> PolyFnSig<'tcx> {
         let did = self.def_id().to_def_id();
         if self.tcx.is_closure(did) {
-            let ty = self.tcx.type_of(did);
+            let ty = self.tcx.type_of(did).subst_identity();
             let ty::Closure(_, substs) = ty.kind() else { bug!("type_of closure not ty::Closure") };
             substs.as_closure().sig()
         } else {
diff --git a/compiler/rustc_const_eval/src/transform/promote_consts.rs b/compiler/rustc_const_eval/src/transform/promote_consts.rs
index 7009d3b38ae..19367d708ee 100644
--- a/compiler/rustc_const_eval/src/transform/promote_consts.rs
+++ b/compiler/rustc_const_eval/src/transform/promote_consts.rs
@@ -898,7 +898,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
         assert_eq!(self.new_block(), START_BLOCK);
         self.visit_rvalue(
             &mut rvalue,
-            Location { block: BasicBlock::new(0), statement_index: usize::MAX },
+            Location { block: START_BLOCK, statement_index: usize::MAX },
         );
 
         let span = self.promoted.span;
diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs
index 56c60d59d28..67dbf29da3b 100644
--- a/compiler/rustc_const_eval/src/transform/validate.rs
+++ b/compiler/rustc_const_eval/src/transform/validate.rs
@@ -334,7 +334,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
 
                 let kind = match parent_ty.ty.kind() {
                     &ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
-                        self.tcx.bound_type_of(def_id).subst(self.tcx, substs).kind()
+                        self.tcx.type_of(def_id).subst(self.tcx, substs).kind()
                     }
                     kind => kind,
                 };
diff --git a/compiler/rustc_data_structures/src/profiling.rs b/compiler/rustc_data_structures/src/profiling.rs
index 3aca03f6e5c..44331683694 100644
--- a/compiler/rustc_data_structures/src/profiling.rs
+++ b/compiler/rustc_data_structures/src/profiling.rs
@@ -207,8 +207,7 @@ impl SelfProfilerRef {
     /// a measureme event, "verbose" generic activities also print a timing entry to
     /// stderr if the compiler is invoked with -Ztime-passes.
     pub fn verbose_generic_activity(&self, event_label: &'static str) -> VerboseTimingGuard<'_> {
-        let message =
-            if self.print_verbose_generic_activities { Some(event_label.to_owned()) } else { None };
+        let message = self.print_verbose_generic_activities.then(|| event_label.to_owned());
 
         VerboseTimingGuard::start(message, self.generic_activity(event_label))
     }
@@ -222,11 +221,9 @@ impl SelfProfilerRef {
     where
         A: Borrow<str> + Into<String>,
     {
-        let message = if self.print_verbose_generic_activities {
-            Some(format!("{}({})", event_label, event_arg.borrow()))
-        } else {
-            None
-        };
+        let message = self
+            .print_verbose_generic_activities
+            .then(|| format!("{}({})", event_label, event_arg.borrow()));
 
         VerboseTimingGuard::start(message, self.generic_activity_with_arg(event_label, event_arg))
     }
diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs
index 4f2cc8b0351..211bbf4f50e 100644
--- a/compiler/rustc_errors/src/emitter.rs
+++ b/compiler/rustc_errors/src/emitter.rs
@@ -1768,7 +1768,7 @@ impl EmitterWriter {
 
         // Render the replacements for each suggestion
         let suggestions = suggestion.splice_lines(sm);
-        debug!("emit_suggestion_default: suggestions={:?}", suggestions);
+        debug!(?suggestions);
 
         if suggestions.is_empty() {
             // Suggestions coming from macros can have malformed spans. This is a heavy handed
@@ -1797,6 +1797,7 @@ impl EmitterWriter {
         for (complete, parts, highlights, only_capitalization) in
             suggestions.iter().take(MAX_SUGGESTIONS)
         {
+            debug!(?complete, ?parts, ?highlights);
             notice_capitalization |= only_capitalization;
 
             let has_deletion = parts.iter().any(|p| p.is_deletion(sm));
diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs
index 83b733d4c06..8c39feca88a 100644
--- a/compiler/rustc_errors/src/lib.rs
+++ b/compiler/rustc_errors/src/lib.rs
@@ -471,6 +471,8 @@ pub enum StashKey {
     /// When an invalid lifetime e.g. `'2` should be reinterpreted
     /// as a char literal in the parser
     LifetimeIsChar,
+    /// When an invalid lifetime e.g. `'🐱` contains emoji.
+    LifetimeContainsEmoji,
     /// Maybe there was a typo where a comma was forgotten before
     /// FRU syntax
     MaybeFruTypo,
@@ -1066,29 +1068,26 @@ impl Handler {
     }
 
     pub fn has_errors(&self) -> Option<ErrorGuaranteed> {
-        if self.inner.borrow().has_errors() { Some(ErrorGuaranteed(())) } else { None }
+        self.inner.borrow().has_errors().then(ErrorGuaranteed::unchecked_claim_error_was_emitted)
     }
 
     pub fn has_errors_or_lint_errors(&self) -> Option<ErrorGuaranteed> {
-        if self.inner.borrow().has_errors_or_lint_errors() {
-            Some(ErrorGuaranteed::unchecked_claim_error_was_emitted())
-        } else {
-            None
-        }
+        self.inner
+            .borrow()
+            .has_errors_or_lint_errors()
+            .then(ErrorGuaranteed::unchecked_claim_error_was_emitted)
     }
     pub fn has_errors_or_delayed_span_bugs(&self) -> Option<ErrorGuaranteed> {
-        if self.inner.borrow().has_errors_or_delayed_span_bugs() {
-            Some(ErrorGuaranteed::unchecked_claim_error_was_emitted())
-        } else {
-            None
-        }
+        self.inner
+            .borrow()
+            .has_errors_or_delayed_span_bugs()
+            .then(ErrorGuaranteed::unchecked_claim_error_was_emitted)
     }
     pub fn is_compilation_going_to_fail(&self) -> Option<ErrorGuaranteed> {
-        if self.inner.borrow().is_compilation_going_to_fail() {
-            Some(ErrorGuaranteed::unchecked_claim_error_was_emitted())
-        } else {
-            None
-        }
+        self.inner
+            .borrow()
+            .is_compilation_going_to_fail()
+            .then(ErrorGuaranteed::unchecked_claim_error_was_emitted)
     }
 
     pub fn print_error_count(&self, registry: &Registry) {
diff --git a/compiler/rustc_expand/src/config.rs b/compiler/rustc_expand/src/config.rs
index 1fcbdfd9be5..5c845ae6d0b 100644
--- a/compiler/rustc_expand/src/config.rs
+++ b/compiler/rustc_expand/src/config.rs
@@ -238,12 +238,10 @@ macro_rules! configure {
 impl<'a> StripUnconfigured<'a> {
     pub fn configure<T: HasAttrs + HasTokens>(&self, mut node: T) -> Option<T> {
         self.process_cfg_attrs(&mut node);
-        if self.in_cfg(node.attrs()) {
+        self.in_cfg(node.attrs()).then(|| {
             self.try_configure_tokens(&mut node);
-            Some(node)
-        } else {
-            None
-        }
+            node
+        })
     }
 
     fn try_configure_tokens<T: HasTokens>(&self, node: &mut T) {
@@ -257,7 +255,7 @@ impl<'a> StripUnconfigured<'a> {
 
     fn configure_krate_attrs(&self, mut attrs: ast::AttrVec) -> Option<ast::AttrVec> {
         attrs.flat_map_in_place(|attr| self.process_cfg_attr(attr));
-        if self.in_cfg(&attrs) { Some(attrs) } else { None }
+        self.in_cfg(&attrs).then_some(attrs)
     }
 
     /// Performs cfg-expansion on `stream`, producing a new `AttrTokenStream`.
diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs
index 21d211eefbe..6d8f7e4a0f6 100644
--- a/compiler/rustc_feature/src/active.rs
+++ b/compiler/rustc_feature/src/active.rs
@@ -164,8 +164,6 @@ declare_features! (
     (active, multiple_supertrait_upcastable, "CURRENT_RUSTC_VERSION", None, None),
     /// Allows using `#[omit_gdb_pretty_printer_section]`.
     (active, omit_gdb_pretty_printer_section, "1.5.0", None, None),
-    /// Allows using `+bundled,+whole-archive` native libs.
-    (active, packed_bundled_libs, "1.67.0", None, None),
     /// Allows using `#[prelude_import]` on glob `use` items.
     (active, prelude_import, "1.2.0", None, None),
     /// Used to identify crates that contain the profiler runtime.
@@ -217,6 +215,8 @@ declare_features! (
     (active, linkage, "1.0.0", Some(29603), None),
     /// Allows declaring with `#![needs_panic_runtime]` that a panic runtime is needed.
     (active, needs_panic_runtime, "1.10.0", Some(32837), None),
+    /// Allows using `+bundled,+whole-archive` native libs.
+    (active, packed_bundled_libs, "CURRENT_RUSTC_VERSION", Some(108081), None),
     /// Allows using the `#![panic_runtime]` attribute.
     (active, panic_runtime, "1.10.0", Some(32837), None),
     /// Allows using `#[rustc_allow_const_fn_unstable]`.
@@ -473,6 +473,8 @@ declare_features! (
     (active, no_sanitize, "1.42.0", Some(39699), None),
     /// Allows using the `non_exhaustive_omitted_patterns` lint.
     (active, non_exhaustive_omitted_patterns_lint, "1.57.0", Some(89554), None),
+    /// Allows `for<T>` binders in where-clauses
+    (incomplete, non_lifetime_binders, "CURRENT_RUSTC_VERSION", Some(108185), None),
     /// Allows making `dyn Trait` well-formed even if `Trait` is not object safe.
     /// In that case, `dyn Trait: Trait` does not hold. Moreover, coercions and
     /// casts in safe Rust to `dyn Trait` for such a `Trait` is also forbidden.
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index 7cb3b6e1525..80ec1caf521 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -574,14 +574,11 @@ impl<'hir> Generics<'hir> {
 
     /// If there are generic parameters, return where to introduce a new one.
     pub fn span_for_param_suggestion(&self) -> Option<Span> {
-        if self.params.iter().any(|p| self.span.contains(p.span)) {
+        self.params.iter().any(|p| self.span.contains(p.span)).then(|| {
             // `fn foo<A>(t: impl Trait)`
             //          ^ suggest `, T: Trait` here
-            let span = self.span.with_lo(self.span.hi() - BytePos(1)).shrink_to_lo();
-            Some(span)
-        } else {
-            None
-        }
+            self.span.with_lo(self.span.hi() - BytePos(1)).shrink_to_lo()
+        })
     }
 
     /// `Span` where further predicates would be suggested, accounting for trailing commas, like
@@ -639,7 +636,7 @@ impl<'hir> Generics<'hir> {
                 // We include bounds that come from a `#[derive(_)]` but point at the user's code,
                 // as we use this method to get a span appropriate for suggestions.
                 let bs = bound.span();
-                if bs.can_be_used_for_suggestions() { Some(bs.shrink_to_hi()) } else { None }
+                bs.can_be_used_for_suggestions().then(|| bs.shrink_to_hi())
             },
         )
     }
diff --git a/compiler/rustc_hir_analysis/src/astconv/generics.rs b/compiler/rustc_hir_analysis/src/astconv/generics.rs
index 5e8f727df69..e5e20aa78d9 100644
--- a/compiler/rustc_hir_analysis/src/astconv/generics.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/generics.rs
@@ -77,7 +77,7 @@ fn generic_arg_mismatch_err(
             Res::Def(DefKind::TyParam, src_def_id) => {
                 if let Some(param_local_id) = param.def_id.as_local() {
                     let param_name = tcx.hir().ty_param_name(param_local_id);
-                    let param_type = tcx.type_of(param.def_id);
+                    let param_type = tcx.type_of(param.def_id).subst_identity();
                     if param_type.is_suggestable(tcx, false) {
                         err.span_suggestion(
                             tcx.def_span(src_def_id),
@@ -97,7 +97,7 @@ fn generic_arg_mismatch_err(
         (
             GenericArg::Type(hir::Ty { kind: hir::TyKind::Array(_, len), .. }),
             GenericParamDefKind::Const { .. },
-        ) if tcx.type_of(param.def_id) == tcx.types.usize => {
+        ) if tcx.type_of(param.def_id).skip_binder() == tcx.types.usize => {
             let snippet = sess.source_map().span_to_snippet(tcx.hir().span(len.hir_id()));
             if let Ok(snippet) = snippet {
                 err.span_suggestion(
diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs
index 46dc4141e66..2ff47237b1b 100644
--- a/compiler/rustc_hir_analysis/src/astconv/mod.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs
@@ -14,7 +14,7 @@ use crate::errors::{
     AmbiguousLifetimeBound, MultipleRelaxedDefaultBounds, TraitObjectDeclaredWithNoTraits,
     TypeofReservedKeywordUsed, ValueOfAssociatedStructAlreadySpecified,
 };
-use crate::middle::resolve_lifetime as rl;
+use crate::middle::resolve_bound_vars as rbv;
 use crate::require_c_abi_if_c_variadic;
 use rustc_ast::TraitObjectSyntax;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
@@ -30,9 +30,9 @@ use rustc_hir::{GenericArg, GenericArgs, OpaqueTyOrigin};
 use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
 use rustc_middle::middle::stability::AllowUnstable;
 use rustc_middle::ty::subst::{self, GenericArgKind, InternalSubsts, SubstsRef};
+use rustc_middle::ty::DynKind;
 use rustc_middle::ty::GenericParamDefKind;
 use rustc_middle::ty::{self, Const, DefIdTree, IsSuggestable, Ty, TyCtxt, TypeVisitable};
-use rustc_middle::ty::{DynKind, EarlyBinder};
 use rustc_session::lint::builtin::{AMBIGUOUS_ASSOCIATED_ITEMS, BARE_TRAIT_OBJECTS};
 use rustc_span::edition::Edition;
 use rustc_span::lev_distance::find_best_match_for_name;
@@ -225,36 +225,37 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         let tcx = self.tcx();
         let lifetime_name = |def_id| tcx.hir().name(tcx.hir().local_def_id_to_hir_id(def_id));
 
-        match tcx.named_region(lifetime.hir_id) {
-            Some(rl::Region::Static) => tcx.lifetimes.re_static,
+        match tcx.named_bound_var(lifetime.hir_id) {
+            Some(rbv::ResolvedArg::StaticLifetime) => tcx.lifetimes.re_static,
 
-            Some(rl::Region::LateBound(debruijn, index, def_id)) => {
+            Some(rbv::ResolvedArg::LateBound(debruijn, index, def_id)) => {
                 let name = lifetime_name(def_id.expect_local());
                 let br = ty::BoundRegion {
                     var: ty::BoundVar::from_u32(index),
                     kind: ty::BrNamed(def_id, name),
                 };
-                tcx.mk_region(ty::ReLateBound(debruijn, br))
+                tcx.mk_re_late_bound(debruijn, br)
             }
 
-            Some(rl::Region::EarlyBound(def_id)) => {
+            Some(rbv::ResolvedArg::EarlyBound(def_id)) => {
                 let name = tcx.hir().ty_param_name(def_id.expect_local());
                 let item_def_id = tcx.hir().ty_param_owner(def_id.expect_local());
                 let generics = tcx.generics_of(item_def_id);
                 let index = generics.param_def_id_to_index[&def_id];
-                tcx.mk_region(ty::ReEarlyBound(ty::EarlyBoundRegion { def_id, index, name }))
+                tcx.mk_re_early_bound(ty::EarlyBoundRegion { def_id, index, name })
             }
 
-            Some(rl::Region::Free(scope, id)) => {
+            Some(rbv::ResolvedArg::Free(scope, id)) => {
                 let name = lifetime_name(id.expect_local());
-                tcx.mk_region(ty::ReFree(ty::FreeRegion {
-                    scope,
-                    bound_region: ty::BrNamed(id, name),
-                }))
+                tcx.mk_re_free(scope, ty::BrNamed(id, name))
 
                 // (*) -- not late-bound, won't change
             }
 
+            Some(rbv::ResolvedArg::Error(_)) => {
+                bug!("only ty/ct should resolve as ResolvedArg::Error")
+            }
+
             None => {
                 self.re_infer(def, lifetime.ident.span).unwrap_or_else(|| {
                     debug!(?lifetime, "unelided lifetime in signature");
@@ -263,7 +264,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                     // elision. `resolve_lifetime` should have
                     // reported an error in this case -- but if
                     // not, let's error out.
-                    tcx.re_error_with_message(lifetime.ident.span, "unelided lifetime in signature")
+                    tcx.mk_re_error_with_message(
+                        lifetime.ident.span,
+                        "unelided lifetime in signature",
+                    )
                 })
             }
         }
@@ -450,7 +454,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                         .into()
                     }
                     (&GenericParamDefKind::Const { .. }, hir::GenericArg::Infer(inf)) => {
-                        let ty = tcx.at(self.span).type_of(param.def_id);
+                        let ty = tcx
+                            .at(self.span)
+                            .type_of(param.def_id)
+                            .no_bound_vars()
+                            .expect("const parameter types cannot be generic");
                         if self.astconv.allow_ty_infer() {
                             self.astconv.ct_infer(ty, Some(param), inf.span).into()
                         } else {
@@ -477,7 +485,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                             debug!(?param, "unelided lifetime in signature");
 
                             // This indicates an illegal lifetime in a non-assoc-trait position
-                            tcx.re_error_with_message(self.span, "unelided lifetime in signature")
+                            tcx.mk_re_error_with_message(
+                                self.span,
+                                "unelided lifetime in signature",
+                            )
                         })
                         .into(),
                     GenericParamDefKind::Type { has_default, .. } => {
@@ -491,7 +502,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                                 // Avoid ICE #86756 when type error recovery goes awry.
                                 return tcx.ty_error().into();
                             }
-                            tcx.at(self.span).bound_type_of(param.def_id).subst(tcx, substs).into()
+                            tcx.at(self.span).type_of(param.def_id).subst(tcx, substs).into()
                         } else if infer_args {
                             self.astconv.ty_infer(Some(param), self.span).into()
                         } else {
@@ -500,7 +511,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                         }
                     }
                     GenericParamDefKind::Const { has_default } => {
-                        let ty = tcx.at(self.span).type_of(param.def_id);
+                        let ty = tcx
+                            .at(self.span)
+                            .type_of(param.def_id)
+                            .no_bound_vars()
+                            .expect("const parameter types cannot be generic");
                         if ty.references_error() {
                             return tcx.const_error(ty).into();
                         }
@@ -1227,7 +1242,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                             }
                             hir::def::DefKind::AssocConst => tcx
                                 .const_error_with_guaranteed(
-                                    tcx.bound_type_of(assoc_item_def_id)
+                                    tcx.type_of(assoc_item_def_id)
                                         .subst(tcx, projection_ty.skip_binder().substs),
                                     reported,
                                 )
@@ -1264,7 +1279,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         item_segment: &hir::PathSegment<'_>,
     ) -> Ty<'tcx> {
         let substs = self.ast_path_substs_for_ty(span, did, item_segment);
-        self.tcx().at(span).bound_type_of(did).subst(self.tcx(), substs)
+        self.tcx().at(span).type_of(did).subst(self.tcx(), substs)
     }
 
     fn conv_object_ty_poly_trait_ref(
@@ -1317,7 +1332,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                     ty::Clause::TypeOutlives(_) => {
                         // Do nothing, we deal with regions separately
                     }
-                    ty::Clause::RegionOutlives(_) => bug!(),
+                    ty::Clause::RegionOutlives(_) | ty::Clause::ConstArgHasType(..) => bug!(),
                 },
                 ty::PredicateKind::WellFormed(_)
                 | ty::PredicateKind::AliasEq(..)
@@ -1597,14 +1612,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             .collect::<SmallVec<[_; 8]>>();
         v.sort_by(|a, b| a.skip_binder().stable_cmp(tcx, &b.skip_binder()));
         v.dedup();
-        let existential_predicates = tcx.mk_poly_existential_predicates(v.into_iter());
+        let existential_predicates = tcx.intern_poly_existential_predicates(&v);
 
         // Use explicitly-specified region bound.
         let region_bound = if !lifetime.is_elided() {
             self.ast_region_to_region(lifetime, None)
         } else {
             self.compute_object_lifetime_bound(span, existential_predicates).unwrap_or_else(|| {
-                if tcx.named_region(lifetime.hir_id).is_some() {
+                if tcx.named_bound_var(lifetime.hir_id).is_some() {
                     self.ast_region_to_region(lifetime, None)
                 } else {
                     self.re_infer(None, span).unwrap_or_else(|| {
@@ -1622,7 +1637,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                         } else {
                             err.emit()
                         };
-                        tcx.re_error(e)
+                        tcx.mk_re_error(e)
                     })
                 }
             })
@@ -2043,7 +2058,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                     assoc_segment,
                     adt_substs,
                 );
-                let ty = tcx.bound_type_of(assoc_ty_did).subst(tcx, item_substs);
+                let ty = tcx.type_of(assoc_ty_did).subst(tcx, item_substs);
                 return Ok((ty, DefKind::AssocTy, assoc_ty_did));
             }
         }
@@ -2597,6 +2612,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         &self,
         opt_self_ty: Option<Ty<'tcx>>,
         path: &hir::Path<'_>,
+        hir_id: hir::HirId,
         permit_variants: bool,
     ) -> Ty<'tcx> {
         let tcx = self.tcx();
@@ -2660,11 +2676,26 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                     }
                 });
 
-                let def_id = def_id.expect_local();
-                let item_def_id = tcx.hir().ty_param_owner(def_id);
-                let generics = tcx.generics_of(item_def_id);
-                let index = generics.param_def_id_to_index[&def_id.to_def_id()];
-                tcx.mk_ty_param(index, tcx.hir().ty_param_name(def_id))
+                match tcx.named_bound_var(hir_id) {
+                    Some(rbv::ResolvedArg::LateBound(debruijn, index, _)) => {
+                        let name =
+                            tcx.hir().name(tcx.hir().local_def_id_to_hir_id(def_id.expect_local()));
+                        let br = ty::BoundTy {
+                            var: ty::BoundVar::from_u32(index),
+                            kind: ty::BoundTyKind::Param(def_id, name),
+                        };
+                        tcx.mk_ty(ty::Bound(debruijn, br))
+                    }
+                    Some(rbv::ResolvedArg::EarlyBound(_)) => {
+                        let def_id = def_id.expect_local();
+                        let item_def_id = tcx.hir().ty_param_owner(def_id);
+                        let generics = tcx.generics_of(item_def_id);
+                        let index = generics.param_def_id_to_index[&def_id.to_def_id()];
+                        tcx.mk_ty_param(index, tcx.hir().ty_param_name(def_id))
+                    }
+                    Some(rbv::ResolvedArg::Error(guar)) => tcx.ty_error_with_guaranteed(guar),
+                    arg => bug!("unexpected bound var resolution for {hir_id:?}: {arg:?}"),
+                }
             }
             Res::SelfTyParam { .. } => {
                 // `Self` in trait or type alias.
@@ -2685,7 +2716,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 // `Self` in impl (we know the concrete type).
                 assert_eq!(opt_self_ty, None);
                 // Try to evaluate any array length constants.
-                let ty = tcx.at(span).type_of(def_id);
+                let ty = tcx.at(span).type_of(def_id).subst_identity();
                 let span_of_impl = tcx.span_of_impl(def_id);
                 self.prohibit_generics(path.segments.iter(), |err| {
                     let def_id = match *ty.kind() {
@@ -2882,12 +2913,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                     TraitObjectSyntax::Dyn | TraitObjectSyntax::None => ty::Dyn,
                     TraitObjectSyntax::DynStar => ty::DynStar,
                 };
+
                 self.conv_object_ty_poly_trait_ref(ast_ty.span, bounds, lifetime, borrowed, repr)
             }
             hir::TyKind::Path(hir::QPath::Resolved(maybe_qself, path)) => {
                 debug!(?maybe_qself, ?path);
                 let opt_self_ty = maybe_qself.as_ref().map(|qself| self.ast_ty_to_ty(qself));
-                self.res_to_ty(opt_self_ty, path, false)
+                self.res_to_ty(opt_self_ty, path, ast_ty.hir_id, false)
             }
             &hir::TyKind::OpaqueDef(item_id, lifetimes, in_trait) => {
                 let opaque_ty = tcx.hir().item(item_id);
@@ -2919,7 +2951,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                     None,
                     ty::BoundConstness::NotConst,
                 );
-                EarlyBinder(tcx.at(span).type_of(def_id)).subst(tcx, substs)
+                tcx.at(span).type_of(def_id).subst(tcx, substs)
             }
             hir::TyKind::Array(ty, length) => {
                 let length = match length {
@@ -2932,7 +2964,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 tcx.mk_array_with_const_len(self.ast_ty_to_ty(ty), length)
             }
             hir::TyKind::Typeof(e) => {
-                let ty_erased = tcx.type_of(e.def_id);
+                let ty_erased = tcx.type_of(e.def_id).subst_identity();
                 let ty = tcx.fold_regions(ty_erased, |r, _| {
                     if r.is_erased() { tcx.lifetimes.re_static } else { r }
                 });
@@ -3060,7 +3092,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
 
         debug!(?output_ty);
 
-        let fn_ty = tcx.mk_fn_sig(input_tys.into_iter(), output_ty, decl.c_variadic, unsafety, abi);
+        let fn_ty = tcx.mk_fn_sig(input_tys, output_ty, decl.c_variadic, unsafety, abi);
         let bare_fn_ty = ty::Binder::bind_with_vars(fn_ty, bound_vars);
 
         if !self.allow_ty_infer() && !(visitor.0.is_empty() && infer_replacements.is_empty()) {
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index 49ad09800a5..04396c883d3 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -93,7 +93,7 @@ fn check_union(tcx: TyCtxt<'_>, def_id: LocalDefId) {
 
 /// Check that the fields of the `union` do not need dropping.
 fn check_union_fields(tcx: TyCtxt<'_>, span: Span, item_def_id: LocalDefId) -> bool {
-    let item_type = tcx.type_of(item_def_id);
+    let item_type = tcx.type_of(item_def_id).subst_identity();
     if let ty::Adt(def, substs) = item_type.kind() {
         assert!(def.is_union());
 
@@ -170,7 +170,7 @@ fn check_static_inhabited(tcx: TyCtxt<'_>, def_id: LocalDefId) {
     // would be enough to check this for `extern` statics, as statics with an initializer will
     // have UB during initialization if they are uninhabited, but there also seems to be no good
     // reason to allow any statics to be uninhabited.
-    let ty = tcx.type_of(def_id);
+    let ty = tcx.type_of(def_id).subst_identity();
     let span = tcx.def_span(def_id);
     let layout = match tcx.layout_of(ParamEnv::reveal_all().and(ty)) {
         Ok(l) => l,
@@ -227,7 +227,7 @@ fn check_opaque(tcx: TyCtxt<'_>, id: hir::ItemId) {
     if !tcx.features().impl_trait_projections {
         check_opaque_for_inheriting_lifetimes(tcx, item.owner_id.def_id, span);
     }
-    if tcx.type_of(item.owner_id.def_id).references_error() {
+    if tcx.type_of(item.owner_id.def_id).subst_identity().references_error() {
         return;
     }
     if check_opaque_for_cycles(tcx, item.owner_id.def_id, substs, span, &origin).is_err() {
@@ -425,7 +425,7 @@ fn check_opaque_meets_bounds<'tcx>(
     //
     // FIXME: Consider wrapping the hidden type in an existential `Binder` and instantiating it
     // here rather than using ReErased.
-    let hidden_ty = tcx.bound_type_of(def_id.to_def_id()).subst(tcx, substs);
+    let hidden_ty = tcx.type_of(def_id.to_def_id()).subst(tcx, substs);
     let hidden_ty = tcx.fold_regions(hidden_ty, |re, _dbi| match re.kind() {
         ty::ReErased => infcx.next_region_var(RegionVariableOrigin::MiscVariable(span)),
         _ => re,
@@ -492,7 +492,7 @@ fn is_enum_of_nonnullable_ptr<'tcx>(
 
 fn check_static_linkage(tcx: TyCtxt<'_>, def_id: LocalDefId) {
     if tcx.codegen_fn_attrs(def_id).import_linkage.is_some() {
-        if match tcx.type_of(def_id).kind() {
+        if match tcx.type_of(def_id).subst_identity().kind() {
             ty::RawPtr(_) => false,
             ty::Adt(adt_def, substs) => !is_enum_of_nonnullable_ptr(tcx, *adt_def, *substs),
             _ => true,
@@ -537,7 +537,7 @@ fn check_item_type(tcx: TyCtxt<'_>, id: hir::ItemId) {
             let assoc_items = tcx.associated_items(id.owner_id);
             check_on_unimplemented(tcx, id);
 
-            for assoc_item in assoc_items.in_definition_order() {
+            for &assoc_item in assoc_items.in_definition_order() {
                 match assoc_item.kind {
                     ty::AssocKind::Fn => {
                         let abi = tcx.fn_sig(assoc_item.def_id).skip_binder().abi();
@@ -578,7 +578,7 @@ fn check_item_type(tcx: TyCtxt<'_>, id: hir::ItemId) {
             }
         }
         DefKind::TyAlias => {
-            let pty_ty = tcx.type_of(id.owner_id);
+            let pty_ty = tcx.type_of(id.owner_id).subst_identity();
             let generics = tcx.generics_of(id.owner_id);
             check_type_params_are_used(tcx, &generics, pty_ty);
         }
@@ -670,7 +670,7 @@ pub(super) fn check_on_unimplemented(tcx: TyCtxt<'_>, item: hir::ItemId) {
 pub(super) fn check_specialization_validity<'tcx>(
     tcx: TyCtxt<'tcx>,
     trait_def: &ty::TraitDef,
-    trait_item: &ty::AssocItem,
+    trait_item: ty::AssocItem,
     impl_id: DefId,
     impl_item: DefId,
 ) {
@@ -767,17 +767,17 @@ fn check_impl_items_against_trait<'tcx>(
                 ));
             }
             ty::AssocKind::Fn => {
-                compare_impl_method(tcx, &ty_impl_item, &ty_trait_item, impl_trait_ref);
+                compare_impl_method(tcx, ty_impl_item, ty_trait_item, impl_trait_ref);
             }
             ty::AssocKind::Type => {
-                compare_impl_ty(tcx, &ty_impl_item, &ty_trait_item, impl_trait_ref);
+                compare_impl_ty(tcx, ty_impl_item, ty_trait_item, impl_trait_ref);
             }
         }
 
         check_specialization_validity(
             tcx,
             trait_def,
-            &ty_trait_item,
+            ty_trait_item,
             impl_id.to_def_id(),
             impl_item,
         );
@@ -854,7 +854,7 @@ fn check_impl_items_against_trait<'tcx>(
 }
 
 pub fn check_simd(tcx: TyCtxt<'_>, sp: Span, def_id: LocalDefId) {
-    let t = tcx.type_of(def_id);
+    let t = tcx.type_of(def_id).subst_identity();
     if let ty::Adt(def, substs) = t.kind()
         && def.is_struct()
     {
@@ -974,7 +974,7 @@ pub(super) fn check_packed(tcx: TyCtxt<'_>, sp: Span, def: ty::AdtDef<'_>) {
                             &if first {
                                 format!(
                                     "`{}` contains a field of type `{}`",
-                                    tcx.type_of(def.did()),
+                                    tcx.type_of(def.did()).subst_identity(),
                                     ident
                                 )
                             } else {
@@ -996,7 +996,7 @@ pub(super) fn check_packed_inner(
     def_id: DefId,
     stack: &mut Vec<DefId>,
 ) -> Option<Vec<(DefId, Span)>> {
-    if let ty::Adt(def, substs) = tcx.type_of(def_id).kind() {
+    if let ty::Adt(def, substs) = tcx.type_of(def_id).subst_identity().kind() {
         if def.is_struct() || def.is_union() {
             if def.repr().align.is_some() {
                 return Some(vec![(def.did(), DUMMY_SP)]);
diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
index 6b0eade2d32..a9fcc8e6250 100644
--- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
@@ -37,8 +37,8 @@ use std::iter;
 /// - `impl_trait_ref`: the TraitRef corresponding to the trait implementation
 pub(super) fn compare_impl_method<'tcx>(
     tcx: TyCtxt<'tcx>,
-    impl_m: &ty::AssocItem,
-    trait_m: &ty::AssocItem,
+    impl_m: ty::AssocItem,
+    trait_m: ty::AssocItem,
     impl_trait_ref: ty::TraitRef<'tcx>,
 ) {
     debug!("compare_impl_method(impl_trait_ref={:?})", impl_trait_ref);
@@ -129,8 +129,8 @@ pub(super) fn compare_impl_method<'tcx>(
 #[instrument(level = "debug", skip(tcx, impl_trait_ref))]
 fn compare_method_predicate_entailment<'tcx>(
     tcx: TyCtxt<'tcx>,
-    impl_m: &ty::AssocItem,
-    trait_m: &ty::AssocItem,
+    impl_m: ty::AssocItem,
+    trait_m: ty::AssocItem,
     impl_trait_ref: ty::TraitRef<'tcx>,
     check_implied_wf: CheckImpliedWfMode,
 ) -> Result<(), ErrorGuaranteed> {
@@ -381,8 +381,8 @@ fn compare_method_predicate_entailment<'tcx>(
 fn extract_bad_args_for_implies_lint<'tcx>(
     tcx: TyCtxt<'tcx>,
     errors: &[infer::RegionResolutionError<'tcx>],
-    (trait_m, trait_sig): (&ty::AssocItem, ty::FnSig<'tcx>),
-    (impl_m, impl_sig): (&ty::AssocItem, ty::FnSig<'tcx>),
+    (trait_m, trait_sig): (ty::AssocItem, ty::FnSig<'tcx>),
+    (impl_m, impl_sig): (ty::AssocItem, ty::FnSig<'tcx>),
     hir_id: hir::HirId,
 ) -> Vec<(Span, Option<String>)> {
     let mut blame_generics = vec![];
@@ -464,14 +464,10 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for RemapLateBound<'_, 'tcx> {
 
     fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
         if let ty::ReFree(fr) = *r {
-            self.tcx.mk_region(ty::ReFree(ty::FreeRegion {
-                bound_region: self
-                    .mapping
-                    .get(&fr.bound_region)
-                    .copied()
-                    .unwrap_or(fr.bound_region),
-                ..fr
-            }))
+            self.tcx.mk_re_free(
+                fr.scope,
+                self.mapping.get(&fr.bound_region).copied().unwrap_or(fr.bound_region),
+            )
         } else {
             r
         }
@@ -480,7 +476,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for RemapLateBound<'_, 'tcx> {
 
 fn emit_implied_wf_lint<'tcx>(
     tcx: TyCtxt<'tcx>,
-    impl_m: &ty::AssocItem,
+    impl_m: ty::AssocItem,
     hir_id: hir::HirId,
     bad_args: Vec<(Span, Option<String>)>,
 ) {
@@ -527,8 +523,8 @@ enum CheckImpliedWfMode {
 
 fn compare_asyncness<'tcx>(
     tcx: TyCtxt<'tcx>,
-    impl_m: &ty::AssocItem,
-    trait_m: &ty::AssocItem,
+    impl_m: ty::AssocItem,
+    trait_m: ty::AssocItem,
 ) -> Result<(), ErrorGuaranteed> {
     if tcx.asyncness(trait_m.def_id) == hir::IsAsync::Async {
         match tcx.fn_sig(impl_m.def_id).skip_binder().skip_binder().output().kind() {
@@ -777,13 +773,13 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
                     }
                     let Some(ty::ReEarlyBound(e)) = map.get(&region.into()).map(|r| r.expect_region().kind())
                     else {
-                        return tcx.re_error_with_message(return_span, "expected ReFree to map to ReEarlyBound")
+                        return tcx.mk_re_error_with_message(return_span, "expected ReFree to map to ReEarlyBound")
                     };
-                    tcx.mk_region(ty::ReEarlyBound(ty::EarlyBoundRegion {
+                    tcx.mk_re_early_bound(ty::EarlyBoundRegion {
                         def_id: e.def_id,
                         name: e.name,
                         index: (e.index as usize - num_trait_substs + num_impl_substs) as u32,
-                    }))
+                    })
                 });
                 debug!(%ty);
                 collected_tys.insert(def_id, ty);
@@ -873,8 +869,8 @@ fn report_trait_method_mismatch<'tcx>(
     infcx: &InferCtxt<'tcx>,
     mut cause: ObligationCause<'tcx>,
     terr: TypeError<'tcx>,
-    (trait_m, trait_sig): (&ty::AssocItem, ty::FnSig<'tcx>),
-    (impl_m, impl_sig): (&ty::AssocItem, ty::FnSig<'tcx>),
+    (trait_m, trait_sig): (ty::AssocItem, ty::FnSig<'tcx>),
+    (impl_m, impl_sig): (ty::AssocItem, ty::FnSig<'tcx>),
     impl_trait_ref: ty::TraitRef<'tcx>,
 ) -> ErrorGuaranteed {
     let tcx = infcx.tcx;
@@ -967,8 +963,8 @@ fn report_trait_method_mismatch<'tcx>(
 
 fn check_region_bounds_on_impl_item<'tcx>(
     tcx: TyCtxt<'tcx>,
-    impl_m: &ty::AssocItem,
-    trait_m: &ty::AssocItem,
+    impl_m: ty::AssocItem,
+    trait_m: ty::AssocItem,
     delay: bool,
 ) -> Result<(), ErrorGuaranteed> {
     let impl_generics = tcx.generics_of(impl_m.def_id);
@@ -1042,7 +1038,7 @@ fn check_region_bounds_on_impl_item<'tcx>(
             .sess
             .create_err(LifetimesOrBoundsMismatchOnTrait {
                 span,
-                item_kind: assoc_item_kind_str(impl_m),
+                item_kind: assoc_item_kind_str(&impl_m),
                 ident: impl_m.ident(tcx),
                 generics_span,
                 bounds_span,
@@ -1060,8 +1056,8 @@ fn extract_spans_for_error_reporting<'tcx>(
     infcx: &infer::InferCtxt<'tcx>,
     terr: TypeError<'_>,
     cause: &ObligationCause<'tcx>,
-    impl_m: &ty::AssocItem,
-    trait_m: &ty::AssocItem,
+    impl_m: ty::AssocItem,
+    trait_m: ty::AssocItem,
 ) -> (Span, Option<Span>) {
     let tcx = infcx.tcx;
     let mut impl_args = {
@@ -1084,8 +1080,8 @@ fn extract_spans_for_error_reporting<'tcx>(
 
 fn compare_self_type<'tcx>(
     tcx: TyCtxt<'tcx>,
-    impl_m: &ty::AssocItem,
-    trait_m: &ty::AssocItem,
+    impl_m: ty::AssocItem,
+    trait_m: ty::AssocItem,
     impl_trait_ref: ty::TraitRef<'tcx>,
 ) -> Result<(), ErrorGuaranteed> {
     // Try to give more informative error messages about self typing
@@ -1096,7 +1092,7 @@ fn compare_self_type<'tcx>(
     // inscrutable, particularly for cases where one method has no
     // self.
 
-    let self_string = |method: &ty::AssocItem| {
+    let self_string = |method: ty::AssocItem| {
         let untransformed_self_ty = match method.container {
             ty::ImplContainer => impl_trait_ref.self_ty(),
             ty::TraitContainer => tcx.types.self_param,
@@ -1186,8 +1182,8 @@ fn compare_self_type<'tcx>(
 /// [`compare_generic_param_kinds`]. This function also does not handle lifetime parameters
 fn compare_number_of_generics<'tcx>(
     tcx: TyCtxt<'tcx>,
-    impl_: &ty::AssocItem,
-    trait_: &ty::AssocItem,
+    impl_: ty::AssocItem,
+    trait_: ty::AssocItem,
     delay: bool,
 ) -> Result<(), ErrorGuaranteed> {
     let trait_own_counts = tcx.generics_of(trait_.def_id).own_counts();
@@ -1207,7 +1203,7 @@ fn compare_number_of_generics<'tcx>(
         ("const", trait_own_counts.consts, impl_own_counts.consts),
     ];
 
-    let item_kind = assoc_item_kind_str(impl_);
+    let item_kind = assoc_item_kind_str(&impl_);
 
     let mut err_occurred = None;
     for (kind, trait_count, impl_count) in matchings {
@@ -1329,8 +1325,8 @@ fn compare_number_of_generics<'tcx>(
 
 fn compare_number_of_method_arguments<'tcx>(
     tcx: TyCtxt<'tcx>,
-    impl_m: &ty::AssocItem,
-    trait_m: &ty::AssocItem,
+    impl_m: ty::AssocItem,
+    trait_m: ty::AssocItem,
 ) -> Result<(), ErrorGuaranteed> {
     let impl_m_fty = tcx.fn_sig(impl_m.def_id);
     let trait_m_fty = tcx.fn_sig(trait_m.def_id);
@@ -1409,8 +1405,8 @@ fn compare_number_of_method_arguments<'tcx>(
 
 fn compare_synthetic_generics<'tcx>(
     tcx: TyCtxt<'tcx>,
-    impl_m: &ty::AssocItem,
-    trait_m: &ty::AssocItem,
+    impl_m: ty::AssocItem,
+    trait_m: ty::AssocItem,
 ) -> Result<(), ErrorGuaranteed> {
     // FIXME(chrisvittal) Clean up this function, list of FIXME items:
     //     1. Better messages for the span labels
@@ -1563,8 +1559,8 @@ fn compare_synthetic_generics<'tcx>(
 /// This function does not handle lifetime parameters
 fn compare_generic_param_kinds<'tcx>(
     tcx: TyCtxt<'tcx>,
-    impl_item: &ty::AssocItem,
-    trait_item: &ty::AssocItem,
+    impl_item: ty::AssocItem,
+    trait_item: ty::AssocItem,
     delay: bool,
 ) -> Result<(), ErrorGuaranteed> {
     assert_eq!(impl_item.kind, trait_item.kind);
@@ -1609,7 +1605,11 @@ fn compare_generic_param_kinds<'tcx>(
 
             let make_param_message = |prefix: &str, param: &ty::GenericParamDef| match param.kind {
                 Const { .. } => {
-                    format!("{} const parameter of type `{}`", prefix, tcx.type_of(param.def_id))
+                    format!(
+                        "{} const parameter of type `{}`",
+                        prefix,
+                        tcx.type_of(param.def_id).subst_identity()
+                    )
                 }
                 Type { .. } => format!("{} type parameter", prefix),
                 Lifetime { .. } => unreachable!(),
@@ -1658,8 +1658,8 @@ pub(super) fn compare_impl_const_raw(
     // Create a parameter environment that represents the implementation's
     // method.
     // Compute placeholder form of impl and trait const tys.
-    let impl_ty = tcx.type_of(impl_const_item_def.to_def_id());
-    let trait_ty = tcx.bound_type_of(trait_const_item_def).subst(tcx, trait_to_impl_substs);
+    let impl_ty = tcx.type_of(impl_const_item_def.to_def_id()).subst_identity();
+    let trait_ty = tcx.type_of(trait_const_item_def).subst(tcx, trait_to_impl_substs);
     let mut cause = ObligationCause::new(
         impl_c_span,
         impl_const_item_def,
@@ -1736,8 +1736,8 @@ pub(super) fn compare_impl_const_raw(
 
 pub(super) fn compare_impl_ty<'tcx>(
     tcx: TyCtxt<'tcx>,
-    impl_ty: &ty::AssocItem,
-    trait_ty: &ty::AssocItem,
+    impl_ty: ty::AssocItem,
+    trait_ty: ty::AssocItem,
     impl_trait_ref: ty::TraitRef<'tcx>,
 ) {
     debug!("compare_impl_type(impl_trait_ref={:?})", impl_trait_ref);
@@ -1754,8 +1754,8 @@ pub(super) fn compare_impl_ty<'tcx>(
 /// instead of associated functions.
 fn compare_type_predicate_entailment<'tcx>(
     tcx: TyCtxt<'tcx>,
-    impl_ty: &ty::AssocItem,
-    trait_ty: &ty::AssocItem,
+    impl_ty: ty::AssocItem,
+    trait_ty: ty::AssocItem,
     impl_trait_ref: ty::TraitRef<'tcx>,
 ) -> Result<(), ErrorGuaranteed> {
     let impl_substs = InternalSubsts::identity_for_item(tcx, impl_ty.def_id);
@@ -1855,8 +1855,8 @@ fn compare_type_predicate_entailment<'tcx>(
 #[instrument(level = "debug", skip(tcx))]
 pub(super) fn check_type_bounds<'tcx>(
     tcx: TyCtxt<'tcx>,
-    trait_ty: &ty::AssocItem,
-    impl_ty: &ty::AssocItem,
+    trait_ty: ty::AssocItem,
+    impl_ty: ty::AssocItem,
     impl_trait_ref: ty::TraitRef<'tcx>,
 ) -> Result<(), ErrorGuaranteed> {
     // Given
@@ -1920,10 +1920,10 @@ pub(super) fn check_type_bounds<'tcx>(
             let kind = ty::BoundRegionKind::BrNamed(param.def_id, param.name);
             let bound_var = ty::BoundVariableKind::Region(kind);
             bound_vars.push(bound_var);
-            tcx.mk_region(ty::ReLateBound(
+            tcx.mk_re_late_bound(
                 ty::INNERMOST,
                 ty::BoundRegion { var: ty::BoundVar::from_usize(bound_vars.len() - 1), kind },
-            ))
+            )
             .into()
         }
         GenericParamDefKind::Const { .. } => {
@@ -1931,17 +1931,17 @@ pub(super) fn check_type_bounds<'tcx>(
             bound_vars.push(bound_var);
             tcx.mk_const(
                 ty::ConstKind::Bound(ty::INNERMOST, ty::BoundVar::from_usize(bound_vars.len() - 1)),
-                tcx.type_of(param.def_id),
+                tcx.type_of(param.def_id).subst_identity(),
             )
             .into()
         }
     });
-    let bound_vars = tcx.mk_bound_variable_kinds(bound_vars.into_iter());
+    let bound_vars = tcx.intern_bound_variable_kinds(&bound_vars);
     let impl_ty_substs = tcx.intern_substs(&substs);
     let container_id = impl_ty.container_id(tcx);
 
     let rebased_substs = impl_ty_substs.rebase_onto(tcx, container_id, impl_trait_ref.substs);
-    let impl_ty_value = tcx.type_of(impl_ty.def_id);
+    let impl_ty_value = tcx.type_of(impl_ty.def_id).subst_identity();
 
     let param_env = tcx.param_env(impl_ty.def_id);
 
diff --git a/compiler/rustc_hir_analysis/src/check/dropck.rs b/compiler/rustc_hir_analysis/src/check/dropck.rs
index 64fd61c1359..c84e3461226 100644
--- a/compiler/rustc_hir_analysis/src/check/dropck.rs
+++ b/compiler/rustc_hir_analysis/src/check/dropck.rs
@@ -27,7 +27,7 @@ use rustc_middle::ty::{self, Predicate, Ty, TyCtxt};
 ///    cannot do `struct S<T>; impl<T:Clone> Drop for S<T> { ... }`).
 ///
 pub fn check_drop_impl(tcx: TyCtxt<'_>, drop_impl_did: DefId) -> Result<(), ErrorGuaranteed> {
-    let dtor_self_type = tcx.type_of(drop_impl_did);
+    let dtor_self_type = tcx.type_of(drop_impl_did).subst_identity();
     let dtor_predicates = tcx.predicates_of(drop_impl_did);
     match dtor_self_type.kind() {
         ty::Adt(adt_def, self_to_impl_substs) => {
diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
index 955cacf03b1..4720fea8ef4 100644
--- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs
+++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
@@ -15,8 +15,6 @@ use rustc_middle::ty::{self, TyCtxt};
 use rustc_span::symbol::{kw, sym, Symbol};
 use rustc_target::spec::abi::Abi;
 
-use std::iter;
-
 fn equate_intrinsic_type<'tcx>(
     tcx: TyCtxt<'tcx>,
     it: &hir::ForeignItem<'_>,
@@ -139,25 +137,21 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
     let intrinsic_name = tcx.item_name(intrinsic_id);
     let name_str = intrinsic_name.as_str();
 
-    let bound_vars = tcx.mk_bound_variable_kinds(
-        [
-            ty::BoundVariableKind::Region(ty::BrAnon(0, None)),
-            ty::BoundVariableKind::Region(ty::BrEnv),
-        ]
-        .iter()
-        .copied(),
-    );
+    let bound_vars = tcx.intern_bound_variable_kinds(&[
+        ty::BoundVariableKind::Region(ty::BrAnon(0, None)),
+        ty::BoundVariableKind::Region(ty::BrEnv),
+    ]);
     let mk_va_list_ty = |mutbl| {
         tcx.lang_items().va_list().map(|did| {
-            let region = tcx.mk_region(ty::ReLateBound(
+            let region = tcx.mk_re_late_bound(
                 ty::INNERMOST,
                 ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon(0, None) },
-            ));
-            let env_region = tcx.mk_region(ty::ReLateBound(
+            );
+            let env_region = tcx.mk_re_late_bound(
                 ty::INNERMOST,
                 ty::BoundRegion { var: ty::BoundVar::from_u32(1), kind: ty::BrEnv },
-            ));
-            let va_list_ty = tcx.bound_type_of(did).subst(tcx, &[region.into()]);
+            );
+            let va_list_ty = tcx.type_of(did).subst(tcx, &[region.into()]);
             (tcx.mk_ref(env_region, ty::TypeAndMut { ty: va_list_ty, mutbl }), va_list_ty)
         })
     };
@@ -377,24 +371,22 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
                     ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon(0, None) };
                 (
                     1,
-                    vec![
-                        tcx.mk_imm_ref(tcx.mk_region(ty::ReLateBound(ty::INNERMOST, br)), param(0)),
-                    ],
-                    tcx.mk_projection(discriminant_def_id, tcx.mk_substs([param(0).into()].iter())),
+                    vec![tcx.mk_imm_ref(tcx.mk_re_late_bound(ty::INNERMOST, br), param(0))],
+                    tcx.mk_projection(discriminant_def_id, tcx.intern_substs(&[param(0).into()])),
                 )
             }
 
             kw::Try => {
                 let mut_u8 = tcx.mk_mut_ptr(tcx.types.u8);
                 let try_fn_ty = ty::Binder::dummy(tcx.mk_fn_sig(
-                    iter::once(mut_u8),
+                    [mut_u8],
                     tcx.mk_unit(),
                     false,
                     hir::Unsafety::Normal,
                     Abi::Rust,
                 ));
                 let catch_fn_ty = ty::Binder::dummy(tcx.mk_fn_sig(
-                    [mut_u8, mut_u8].iter().cloned(),
+                    [mut_u8, mut_u8],
                     tcx.mk_unit(),
                     false,
                     hir::Unsafety::Normal,
@@ -430,8 +422,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
             sym::raw_eq => {
                 let br =
                     ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon(0, None) };
-                let param_ty =
-                    tcx.mk_imm_ref(tcx.mk_region(ty::ReLateBound(ty::INNERMOST, br)), param(0));
+                let param_ty = tcx.mk_imm_ref(tcx.mk_re_late_bound(ty::INNERMOST, br), param(0));
                 (1, vec![param_ty; 2], tcx.types.bool)
             }
 
@@ -450,7 +441,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
         };
         (n_tps, 0, inputs, output, unsafety)
     };
-    let sig = tcx.mk_fn_sig(inputs.into_iter(), output, false, unsafety, Abi::RustIntrinsic);
+    let sig = tcx.mk_fn_sig(inputs, output, false, unsafety, Abi::RustIntrinsic);
     let sig = ty::Binder::bind_with_vars(sig, bound_vars);
     equate_intrinsic_type(tcx, it, n_tps, n_lts, sig)
 }
@@ -548,13 +539,7 @@ pub fn check_platform_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>)
         }
     };
 
-    let sig = tcx.mk_fn_sig(
-        inputs.into_iter(),
-        output,
-        false,
-        hir::Unsafety::Unsafe,
-        Abi::PlatformIntrinsic,
-    );
+    let sig = tcx.mk_fn_sig(inputs, output, false, hir::Unsafety::Unsafe, Abi::PlatformIntrinsic);
     let sig = ty::Binder::dummy(sig);
     equate_intrinsic_type(tcx, it, n_tps, 0, sig)
 }
diff --git a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs
index 56ac18c4927..b3e76010da3 100644
--- a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs
+++ b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs
@@ -414,7 +414,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
                 // Check that sym actually points to a function. Later passes
                 // depend on this.
                 hir::InlineAsmOperand::SymFn { anon_const } => {
-                    let ty = self.tcx.type_of(anon_const.def_id);
+                    let ty = self.tcx.type_of(anon_const.def_id).subst_identity();
                     match ty.kind() {
                         ty::Never | ty::Error(_) => {}
                         ty::FnDef(..) => {}
diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs
index 7b013cabc3a..9acfc1b3d29 100644
--- a/compiler/rustc_hir_analysis/src/check/mod.rs
+++ b/compiler/rustc_hir_analysis/src/check/mod.rs
@@ -199,7 +199,7 @@ fn report_forbidden_specialization(tcx: TyCtxt<'_>, impl_item: DefId, parent_imp
 fn missing_items_err(
     tcx: TyCtxt<'_>,
     impl_span: Span,
-    missing_items: &[&ty::AssocItem],
+    missing_items: &[ty::AssocItem],
     full_impl_span: Span,
 ) {
     let missing_items_msg = missing_items
@@ -225,7 +225,7 @@ fn missing_items_err(
     let padding =
         tcx.sess.source_map().indentation_before(sugg_sp).unwrap_or_else(|| String::new());
 
-    for trait_item in missing_items {
+    for &trait_item in missing_items {
         let snippet = suggestion_signature(trait_item, tcx);
         let code = format!("{}{}\n{}", padding, snippet, padding);
         let msg = format!("implement the missing item: `{snippet}`");
@@ -272,7 +272,7 @@ fn default_body_is_unstable(
     reason: Option<Symbol>,
     issue: Option<NonZeroU32>,
 ) {
-    let missing_item_name = &tcx.associated_item(item_did).name;
+    let missing_item_name = tcx.associated_item(item_did).name;
     let use_of_unstable_library_feature_note = match reason {
         Some(r) => format!("use of unstable library feature '{feature}': {r}"),
         None => format!("use of unstable library feature '{feature}'"),
@@ -365,7 +365,7 @@ fn fn_sig_suggestion<'tcx>(
     sig: ty::FnSig<'tcx>,
     ident: Ident,
     predicates: ty::GenericPredicates<'tcx>,
-    assoc: &ty::AssocItem,
+    assoc: ty::AssocItem,
 ) -> String {
     let args = sig
         .inputs()
@@ -433,7 +433,7 @@ pub fn ty_kind_suggestion(ty: Ty<'_>) -> Option<&'static str> {
 /// Return placeholder code for the given associated item.
 /// Similar to `ty::AssocItem::suggestion`, but appropriate for use as the code snippet of a
 /// structured suggestion.
-fn suggestion_signature(assoc: &ty::AssocItem, tcx: TyCtxt<'_>) -> String {
+fn suggestion_signature(assoc: ty::AssocItem, tcx: TyCtxt<'_>) -> String {
     match assoc.kind {
         ty::AssocKind::Fn => {
             // We skip the binder here because the binder would deanonymize all
@@ -450,7 +450,7 @@ fn suggestion_signature(assoc: &ty::AssocItem, tcx: TyCtxt<'_>) -> String {
         }
         ty::AssocKind::Type => format!("type {} = Type;", assoc.name),
         ty::AssocKind::Const => {
-            let ty = tcx.type_of(assoc.def_id);
+            let ty = tcx.type_of(assoc.def_id).subst_identity();
             let val = ty_kind_suggestion(ty).unwrap_or("value");
             format!("const {}: {} = {};", assoc.name, ty, val)
         }
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index c64d507f828..66c3904af96 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -607,12 +607,11 @@ fn gather_gat_bounds<'tcx, T: TypeFoldable<'tcx>>(
                 // Same for the region. In our example, 'a corresponds
                 // to the 'me parameter.
                 let region_param = gat_generics.param_at(*region_a_idx, tcx);
-                let region_param =
-                    tcx.mk_region(ty::RegionKind::ReEarlyBound(ty::EarlyBoundRegion {
-                        def_id: region_param.def_id,
-                        index: region_param.index,
-                        name: region_param.name,
-                    }));
+                let region_param = tcx.mk_re_early_bound(ty::EarlyBoundRegion {
+                    def_id: region_param.def_id,
+                    index: region_param.index,
+                    name: region_param.name,
+                });
                 // The predicate we expect to see. (In our example,
                 // `Self: 'me`.)
                 let clause = ty::PredicateKind::Clause(ty::Clause::TypeOutlives(
@@ -645,20 +644,18 @@ fn gather_gat_bounds<'tcx, T: TypeFoldable<'tcx>>(
                 debug!("required clause: {region_a} must outlive {region_b}");
                 // Translate into the generic parameters of the GAT.
                 let region_a_param = gat_generics.param_at(*region_a_idx, tcx);
-                let region_a_param =
-                    tcx.mk_region(ty::RegionKind::ReEarlyBound(ty::EarlyBoundRegion {
-                        def_id: region_a_param.def_id,
-                        index: region_a_param.index,
-                        name: region_a_param.name,
-                    }));
+                let region_a_param = tcx.mk_re_early_bound(ty::EarlyBoundRegion {
+                    def_id: region_a_param.def_id,
+                    index: region_a_param.index,
+                    name: region_a_param.name,
+                });
                 // Same for the region.
                 let region_b_param = gat_generics.param_at(*region_b_idx, tcx);
-                let region_b_param =
-                    tcx.mk_region(ty::RegionKind::ReEarlyBound(ty::EarlyBoundRegion {
-                        def_id: region_b_param.def_id,
-                        index: region_b_param.index,
-                        name: region_b_param.name,
-                    }));
+                let region_b_param = tcx.mk_re_early_bound(ty::EarlyBoundRegion {
+                    def_id: region_b_param.def_id,
+                    index: region_b_param.index,
+                    name: region_b_param.name,
+                });
                 // The predicate we expect to see.
                 let clause = ty::PredicateKind::Clause(ty::Clause::RegionOutlives(
                     ty::OutlivesPredicate(region_a_param, region_b_param),
@@ -877,7 +874,7 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) {
 
         // Const parameters are well formed if their type is structural match.
         hir::GenericParamKind::Const { ty: hir_ty, default: _ } => {
-            let ty = tcx.type_of(param.def_id);
+            let ty = tcx.type_of(param.def_id).subst_identity();
 
             if tcx.features().adt_const_params {
                 if let Some(non_structural_match_ty) =
@@ -1014,12 +1011,12 @@ fn check_associated_item(
 
         let self_ty = match item.container {
             ty::TraitContainer => tcx.types.self_param,
-            ty::ImplContainer => tcx.type_of(item.container_id(tcx)),
+            ty::ImplContainer => tcx.type_of(item.container_id(tcx)).subst_identity(),
         };
 
         match item.kind {
             ty::AssocKind::Const => {
-                let ty = tcx.type_of(item.def_id);
+                let ty = tcx.type_of(item.def_id).subst_identity();
                 let ty = wfcx.normalize(span, Some(WellFormedLoc::Ty(item_id)), ty);
                 wfcx.register_wf_obligation(span, loc, ty.into());
             }
@@ -1040,7 +1037,7 @@ fn check_associated_item(
                     check_associated_type_bounds(wfcx, item, span)
                 }
                 if item.defaultness(tcx).has_value() {
-                    let ty = tcx.type_of(item.def_id);
+                    let ty = tcx.type_of(item.def_id).subst_identity();
                     let ty = wfcx.normalize(span, Some(WellFormedLoc::Ty(item_id)), ty);
                     wfcx.register_wf_obligation(span, loc, ty.into());
                 }
@@ -1073,7 +1070,7 @@ fn check_type_defn<'tcx>(tcx: TyCtxt<'tcx>, item: &hir::Item<'tcx>, all_sized: b
                 let field_id = field.did.expect_local();
                 let hir::FieldDef { ty: hir_ty, .. } =
                     tcx.hir().get_by_def_id(field_id).expect_field();
-                let ty = wfcx.normalize(hir_ty.span, None, tcx.type_of(field.did));
+                let ty = wfcx.normalize(hir_ty.span, None, tcx.type_of(field.did).subst_identity());
                 wfcx.register_wf_obligation(
                     hir_ty.span,
                     Some(WellFormedLoc::Ty(field_id)),
@@ -1085,7 +1082,7 @@ fn check_type_defn<'tcx>(tcx: TyCtxt<'tcx>, item: &hir::Item<'tcx>, all_sized: b
             // intermediate types must be sized.
             let needs_drop_copy = || {
                 packed && {
-                    let ty = tcx.type_of(variant.fields.last().unwrap().did);
+                    let ty = tcx.type_of(variant.fields.last().unwrap().did).subst_identity();
                     let ty = tcx.erase_regions(ty);
                     if ty.needs_infer() {
                         tcx.sess
@@ -1107,7 +1104,7 @@ fn check_type_defn<'tcx>(tcx: TyCtxt<'tcx>, item: &hir::Item<'tcx>, all_sized: b
                 let field_id = field.did.expect_local();
                 let hir::FieldDef { ty: hir_ty, .. } =
                     tcx.hir().get_by_def_id(field_id).expect_field();
-                let ty = wfcx.normalize(hir_ty.span, None, tcx.type_of(field.did));
+                let ty = wfcx.normalize(hir_ty.span, None, tcx.type_of(field.did).subst_identity());
                 wfcx.register_bound(
                     traits::ObligationCause::new(
                         hir_ty.span,
@@ -1183,7 +1180,7 @@ fn check_trait(tcx: TyCtxt<'_>, item: &hir::Item<'_>) {
 ///
 /// Assuming the defaults are used, check that all predicates (bounds on the
 /// assoc type and where clauses on the trait) hold.
-fn check_associated_type_bounds(wfcx: &WfCheckingCtxt<'_, '_>, item: &ty::AssocItem, span: Span) {
+fn check_associated_type_bounds(wfcx: &WfCheckingCtxt<'_, '_>, item: ty::AssocItem, span: Span) {
     let bounds = wfcx.tcx().explicit_item_bounds(item.def_id);
 
     debug!("check_associated_type_bounds: bounds={:?}", bounds);
@@ -1218,7 +1215,7 @@ fn check_item_type(tcx: TyCtxt<'_>, item_id: LocalDefId, ty_span: Span, allow_fo
     debug!("check_item_type: {:?}", item_id);
 
     enter_wf_checking_ctxt(tcx, ty_span, item_id, |wfcx| {
-        let ty = tcx.type_of(item_id);
+        let ty = tcx.type_of(item_id).subst_identity();
         let item_ty = wfcx.normalize(ty_span, Some(WellFormedLoc::Ty(item_id)), ty);
 
         let mut forbid_unsized = true;
@@ -1303,7 +1300,7 @@ fn check_impl<'tcx>(
                 wfcx.register_obligations(obligations);
             }
             None => {
-                let self_ty = tcx.type_of(item.owner_id);
+                let self_ty = tcx.type_of(item.owner_id).subst_identity();
                 let self_ty = wfcx.normalize(
                     item.span,
                     Some(WellFormedLoc::Ty(item.hir_id().expect_owner().def_id)),
@@ -1348,7 +1345,7 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id
         match param.kind {
             GenericParamDefKind::Type { .. } => {
                 if is_our_default(param) {
-                    let ty = tcx.type_of(param.def_id);
+                    let ty = tcx.type_of(param.def_id).subst_identity();
                     // Ignore dependent defaults -- that is, where the default of one type
                     // parameter includes another (e.g., `<T, U = T>`). In those cases, we can't
                     // be sure if it will error or not as user might always specify the other.
@@ -1400,7 +1397,7 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id
             GenericParamDefKind::Type { .. } => {
                 // If the param has a default, ...
                 if is_our_default(param) {
-                    let default_ty = tcx.type_of(param.def_id);
+                    let default_ty = tcx.type_of(param.def_id).subst_identity();
                     // ... and it's not a dependent default, ...
                     if !default_ty.needs_subst() {
                         // ... then substitute it with the default.
@@ -1633,7 +1630,7 @@ const HELP_FOR_SELF_TYPE: &str = "consider changing to `self`, `&self`, `&mut se
 fn check_method_receiver<'tcx>(
     wfcx: &WfCheckingCtxt<'_, 'tcx>,
     fn_sig: &hir::FnSig<'_>,
-    method: &ty::AssocItem,
+    method: ty::AssocItem,
     self_ty: Ty<'tcx>,
 ) {
     let tcx = wfcx.tcx();
@@ -1816,7 +1813,7 @@ fn check_variances_for_type_defn<'tcx>(
     item: &hir::Item<'tcx>,
     hir_generics: &hir::Generics<'_>,
 ) {
-    let ty = tcx.type_of(item.owner_id);
+    let ty = tcx.type_of(item.owner_id).subst_identity();
     if tcx.has_error_field(ty) {
         return;
     }
diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs
index c0ba385987d..51c5f297051 100644
--- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs
@@ -50,7 +50,7 @@ impl<'tcx> Checker<'tcx> {
 
 fn visit_implementation_of_drop(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
     // Destructors only work on local ADT types.
-    match tcx.type_of(impl_did).kind() {
+    match tcx.type_of(impl_did).subst_identity().kind() {
         ty::Adt(def, _) if def.did().is_local() => return,
         ty::Error(_) => return,
         _ => {}
@@ -64,7 +64,7 @@ fn visit_implementation_of_drop(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
 fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
     debug!("visit_implementation_of_copy: impl_did={:?}", impl_did);
 
-    let self_type = tcx.type_of(impl_did);
+    let self_type = tcx.type_of(impl_did).subst_identity();
     debug!("visit_implementation_of_copy: self_type={:?} (bound)", self_type);
 
     let param_env = tcx.param_env(impl_did);
@@ -206,7 +206,7 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef
 
     let dispatch_from_dyn_trait = tcx.require_lang_item(LangItem::DispatchFromDyn, Some(span));
 
-    let source = tcx.type_of(impl_did);
+    let source = tcx.type_of(impl_did).subst_identity();
     assert!(!source.has_escaping_bound_vars());
     let target = {
         let trait_ref = tcx.impl_trait_ref(impl_did).unwrap().subst_identity();
@@ -370,7 +370,7 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUn
         tcx.sess.fatal(&format!("`CoerceUnsized` implementation {}", err.to_string()));
     });
 
-    let source = tcx.type_of(impl_did);
+    let source = tcx.type_of(impl_did).subst_identity();
     let trait_ref = tcx.impl_trait_ref(impl_did).unwrap().subst_identity();
     assert_eq!(trait_ref.def_id, coerce_unsized_trait);
     let target = trait_ref.substs.type_at(1);
@@ -482,7 +482,7 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUn
                 .filter_map(|(i, f)| {
                     let (a, b) = (f.ty(tcx, substs_a), f.ty(tcx, substs_b));
 
-                    if tcx.type_of(f.did).is_phantom_data() {
+                    if tcx.type_of(f.did).subst_identity().is_phantom_data() {
                         // Ignore PhantomData fields
                         return None;
                     }
diff --git a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs
index f0b6ab03ad6..02f3eeee0e7 100644
--- a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs
@@ -173,7 +173,7 @@ impl<'tcx> InherentCollect<'tcx> {
 
         let id = id.owner_id.def_id;
         let item_span = self.tcx.def_span(id);
-        let self_ty = self.tcx.type_of(id);
+        let self_ty = self.tcx.type_of(id).subst_identity();
         match *self_ty.kind() {
             ty::Adt(def, _) => self.check_def_id(id, self_ty, def.did()),
             ty::Foreign(did) => self.check_def_id(id, self_ty, did),
diff --git a/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs b/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs
index a9331af4eab..7bca4edcc8c 100644
--- a/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs
@@ -27,8 +27,8 @@ impl<'tcx> InherentOverlapChecker<'tcx> {
     /// namespace.
     fn impls_have_common_items(
         &self,
-        impl_items1: &ty::AssocItems<'_>,
-        impl_items2: &ty::AssocItems<'_>,
+        impl_items1: &ty::AssocItems,
+        impl_items2: &ty::AssocItems,
     ) -> bool {
         let mut impl_items1 = &impl_items1;
         let mut impl_items2 = &impl_items2;
@@ -38,10 +38,10 @@ impl<'tcx> InherentOverlapChecker<'tcx> {
             std::mem::swap(&mut impl_items1, &mut impl_items2);
         }
 
-        for item1 in impl_items1.in_definition_order() {
+        for &item1 in impl_items1.in_definition_order() {
             let collision = impl_items2
                 .filter_by_name_unhygienic(item1.name)
-                .any(|item2| self.compare_hygienically(item1, item2));
+                .any(|&item2| self.compare_hygienically(item1, item2));
 
             if collision {
                 return true;
@@ -51,7 +51,7 @@ impl<'tcx> InherentOverlapChecker<'tcx> {
         false
     }
 
-    fn compare_hygienically(&self, item1: &ty::AssocItem, item2: &ty::AssocItem) -> bool {
+    fn compare_hygienically(&self, item1: ty::AssocItem, item2: ty::AssocItem) -> bool {
         // Symbols and namespace match, compare hygienically.
         item1.kind.namespace() == item2.kind.namespace()
             && item1.ident(self.tcx).normalize_to_macros_2_0()
@@ -98,10 +98,10 @@ impl<'tcx> InherentOverlapChecker<'tcx> {
         let impl_items1 = self.tcx.associated_items(impl1);
         let impl_items2 = self.tcx.associated_items(impl2);
 
-        for item1 in impl_items1.in_definition_order() {
+        for &item1 in impl_items1.in_definition_order() {
             let collision = impl_items2
                 .filter_by_name_unhygienic(item1.name)
-                .find(|item2| self.compare_hygienically(item1, item2));
+                .find(|&&item2| self.compare_hygienically(item1, item2));
 
             if let Some(item2) = collision {
                 let name = item1.ident(self.tcx).normalize_to_macros_2_0();
diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs
index 9f33d84ab52..ed3d50bfafa 100644
--- a/compiler/rustc_hir_analysis/src/collect.rs
+++ b/compiler/rustc_hir_analysis/src/collect.rs
@@ -41,8 +41,8 @@ use std::iter;
 
 mod generics_of;
 mod item_bounds;
-mod lifetimes;
 mod predicates_of;
+mod resolve_bound_vars;
 mod type_of;
 
 ///////////////////////////////////////////////////////////////////////////
@@ -53,7 +53,7 @@ fn collect_mod_item_types(tcx: TyCtxt<'_>, module_def_id: LocalDefId) {
 }
 
 pub fn provide(providers: &mut Providers) {
-    lifetimes::provide(providers);
+    resolve_bound_vars::provide(providers);
     *providers = Providers {
         opt_const_param_of: type_of::opt_const_param_of,
         type_of: type_of::type_of,
@@ -458,13 +458,11 @@ impl<'tcx> AstConv<'tcx> for ItemCtxt<'tcx> {
                                         self.tcx.replace_late_bound_regions_uncached(
                                             poly_trait_ref,
                                             |_| {
-                                                self.tcx.mk_region(ty::ReEarlyBound(
-                                                    ty::EarlyBoundRegion {
-                                                        def_id: item_def_id,
-                                                        index: 0,
-                                                        name: Symbol::intern(&lt_name),
-                                                    },
-                                                ))
+                                                self.tcx.mk_re_early_bound(ty::EarlyBoundRegion {
+                                                    def_id: item_def_id,
+                                                    index: 0,
+                                                    name: Symbol::intern(&lt_name),
+                                                })
                                             }
                                         ),
                                     ),
@@ -1145,8 +1143,8 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::EarlyBinder<ty::PolyFnSig<'_>>
         }
 
         Ctor(data) | Variant(hir::Variant { data, .. }) if data.ctor().is_some() => {
-            let ty = tcx.type_of(tcx.hir().get_parent_item(hir_id));
-            let inputs = data.fields().iter().map(|f| tcx.type_of(f.def_id));
+            let ty = tcx.type_of(tcx.hir().get_parent_item(hir_id)).subst_identity();
+            let inputs = data.fields().iter().map(|f| tcx.type_of(f.def_id).subst_identity());
             ty::Binder::dummy(tcx.mk_fn_sig(
                 inputs,
                 ty,
@@ -1347,7 +1345,7 @@ fn impl_trait_ref(tcx: TyCtxt<'_>, def_id: DefId) -> Option<ty::EarlyBinder<ty::
         .of_trait
         .as_ref()
         .map(|ast_trait_ref| {
-            let selfty = tcx.type_of(def_id);
+            let selfty = tcx.type_of(def_id).subst_identity();
             icx.astconv().instantiate_mono_trait_ref(
                 ast_trait_ref,
                 selfty,
diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs
index 014ee9fcc20..127d4fa908b 100644
--- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs
@@ -1,4 +1,4 @@
-use crate::middle::resolve_lifetime as rl;
+use crate::middle::resolve_bound_vars as rbv;
 use hir::{
     intravisit::{self, Visitor},
     GenericParamKind, HirId, Node,
@@ -394,10 +394,16 @@ fn has_late_bound_regions<'tcx>(tcx: TyCtxt<'tcx>, node: Node<'tcx>) -> Option<S
                 return;
             }
 
-            match self.tcx.named_region(lt.hir_id) {
-                Some(rl::Region::Static | rl::Region::EarlyBound(..)) => {}
-                Some(rl::Region::LateBound(debruijn, _, _)) if debruijn < self.outer_index => {}
-                Some(rl::Region::LateBound(..) | rl::Region::Free(..)) | None => {
+            match self.tcx.named_bound_var(lt.hir_id) {
+                Some(rbv::ResolvedArg::StaticLifetime | rbv::ResolvedArg::EarlyBound(..)) => {}
+                Some(rbv::ResolvedArg::LateBound(debruijn, _, _))
+                    if debruijn < self.outer_index => {}
+                Some(
+                    rbv::ResolvedArg::LateBound(..)
+                    | rbv::ResolvedArg::Free(..)
+                    | rbv::ResolvedArg::Error(_),
+                )
+                | None => {
                     self.has_late_bound_regions = Some(lt.ident.span);
                 }
             }
diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
index d0d67ae9257..2badd66e346 100644
--- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
@@ -9,8 +9,8 @@ use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::intravisit::{self, Visitor};
 use rustc_middle::ty::subst::InternalSubsts;
-use rustc_middle::ty::ToPredicate;
 use rustc_middle::ty::{self, Ty, TyCtxt};
+use rustc_middle::ty::{GenericPredicates, ToPredicate};
 use rustc_span::symbol::{sym, Ident};
 use rustc_span::{Span, DUMMY_SP};
 
@@ -151,7 +151,8 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
     trace!(?generics);
 
     // Collect the predicates that were written inline by the user on each
-    // type parameter (e.g., `<T: Foo>`).
+    // type parameter (e.g., `<T: Foo>`). Also add `ConstArgHasType` predicates
+    // for each const parameter.
     for param in ast_generics.params {
         match param.kind {
             // We already dealt with early bound lifetimes above.
@@ -175,7 +176,19 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
                 trace!(?predicates);
             }
             GenericParamKind::Const { .. } => {
-                // Bounds on const parameters are currently not possible.
+                let name = param.name.ident().name;
+                let param_const = ty::ParamConst::new(index, name);
+
+                let ct_ty = tcx.type_of(param.def_id.to_def_id()).subst_identity();
+
+                let ct = tcx.mk_const(param_const, ct_ty);
+
+                let predicate = ty::Binder::dummy(ty::PredicateKind::Clause(
+                    ty::Clause::ConstArgHasType(ct, ct_ty),
+                ))
+                .to_predicate(tcx);
+                predicates.insert((predicate, param.span));
+
                 index += 1;
             }
         }
@@ -251,7 +264,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
     // in trait checking. See `setup_constraining_predicates`
     // for details.
     if let Node::Item(&Item { kind: ItemKind::Impl { .. }, .. }) = node {
-        let self_ty = tcx.type_of(def_id);
+        let self_ty = tcx.type_of(def_id).subst_identity();
         let trait_ref = tcx.impl_trait_ref(def_id).map(ty::EarlyBinder::subst_identity);
         cgp::setup_constraining_predicates(
             tcx,
@@ -284,11 +297,11 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
 
             let Some(dup_index) = generics.param_def_id_to_index(tcx, dup_def) else { bug!() };
 
-            let dup_region = tcx.mk_region(ty::ReEarlyBound(ty::EarlyBoundRegion {
+            let dup_region = tcx.mk_re_early_bound(ty::EarlyBoundRegion {
                 def_id: dup_def,
                 index: dup_index,
                 name: duplicate.name.ident().name,
-            }));
+            });
             predicates.push((
                 ty::Binder::dummy(ty::PredicateKind::Clause(ty::Clause::RegionOutlives(
                     ty::OutlivesPredicate(orig_region, dup_region),
@@ -439,7 +452,9 @@ pub(super) fn explicit_predicates_of<'tcx>(
             let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
             let parent_def_id = tcx.hir().get_parent_item(hir_id);
 
-            if tcx.hir().opt_const_param_default_param_def_id(hir_id).is_some() {
+            if let Some(defaulted_param_def_id) =
+                tcx.hir().opt_const_param_default_param_def_id(hir_id)
+            {
                 // In `generics_of` we set the generics' parent to be our parent's parent which means that
                 // we lose out on the predicates of our actual parent if we dont return those predicates here.
                 // (See comment in `generics_of` for more information on why the parent shenanigans is necessary)
@@ -452,7 +467,39 @@ pub(super) fn explicit_predicates_of<'tcx>(
                 //
                 // In the above code we want the anon const to have predicates in its param env for `T: Trait`
                 // and we would be calling `explicit_predicates_of(Foo)` here
-                return tcx.explicit_predicates_of(parent_def_id);
+                let parent_preds = tcx.explicit_predicates_of(parent_def_id);
+
+                // If we dont filter out `ConstArgHasType` predicates then every single defaulted const parameter
+                // will ICE because of #106994. FIXME(generic_const_exprs): remove this when a more general solution
+                // to #106994 is implemented.
+                let filtered_predicates = parent_preds
+                    .predicates
+                    .into_iter()
+                    .filter(|(pred, _)| {
+                        if let ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(ct, _)) =
+                            pred.kind().skip_binder()
+                        {
+                            match ct.kind() {
+                                ty::ConstKind::Param(param_const) => {
+                                    let defaulted_param_idx = tcx
+                                        .generics_of(parent_def_id)
+                                        .param_def_id_to_index[&defaulted_param_def_id.to_def_id()];
+                                    param_const.index < defaulted_param_idx
+                                }
+                                _ => bug!(
+                                    "`ConstArgHasType` in `predicates_of`\
+                                 that isn't a `Param` const"
+                                ),
+                            }
+                        } else {
+                            true
+                        }
+                    })
+                    .cloned();
+                return GenericPredicates {
+                    parent: parent_preds.parent,
+                    predicates: { tcx.arena.alloc_from_iter(filtered_predicates) },
+                };
             }
 
             let parent_def_kind = tcx.def_kind(parent_def_id);
diff --git a/compiler/rustc_hir_analysis/src/collect/lifetimes.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
index d8606f759b2..c0c90e47a75 100644
--- a/compiler/rustc_hir_analysis/src/collect/lifetimes.rs
+++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
@@ -16,7 +16,7 @@ use rustc_hir::intravisit::{self, Visitor};
 use rustc_hir::{GenericArg, GenericParam, GenericParamKind, HirIdMap, LifetimeName, Node};
 use rustc_middle::bug;
 use rustc_middle::hir::nested_filter;
-use rustc_middle::middle::resolve_lifetime::*;
+use rustc_middle::middle::resolve_bound_vars::*;
 use rustc_middle::ty::{self, ir::TypeVisitor, DefIdTree, TyCtxt, TypeSuperVisitable};
 use rustc_span::def_id::DefId;
 use rustc_span::symbol::{sym, Ident};
@@ -24,59 +24,61 @@ use rustc_span::Span;
 use std::fmt;
 
 trait RegionExt {
-    fn early(param: &GenericParam<'_>) -> (LocalDefId, Region);
+    fn early(param: &GenericParam<'_>) -> (LocalDefId, ResolvedArg);
 
-    fn late(index: u32, param: &GenericParam<'_>) -> (LocalDefId, Region);
+    fn late(index: u32, param: &GenericParam<'_>) -> (LocalDefId, ResolvedArg);
 
     fn id(&self) -> Option<DefId>;
 
-    fn shifted(self, amount: u32) -> Region;
+    fn shifted(self, amount: u32) -> ResolvedArg;
 }
 
-impl RegionExt for Region {
-    fn early(param: &GenericParam<'_>) -> (LocalDefId, Region) {
-        debug!("Region::early: def_id={:?}", param.def_id);
-        (param.def_id, Region::EarlyBound(param.def_id.to_def_id()))
+impl RegionExt for ResolvedArg {
+    fn early(param: &GenericParam<'_>) -> (LocalDefId, ResolvedArg) {
+        debug!("ResolvedArg::early: def_id={:?}", param.def_id);
+        (param.def_id, ResolvedArg::EarlyBound(param.def_id.to_def_id()))
     }
 
-    fn late(idx: u32, param: &GenericParam<'_>) -> (LocalDefId, Region) {
+    fn late(idx: u32, param: &GenericParam<'_>) -> (LocalDefId, ResolvedArg) {
         let depth = ty::INNERMOST;
         debug!(
-            "Region::late: idx={:?}, param={:?} depth={:?} def_id={:?}",
+            "ResolvedArg::late: idx={:?}, param={:?} depth={:?} def_id={:?}",
             idx, param, depth, param.def_id,
         );
-        (param.def_id, Region::LateBound(depth, idx, param.def_id.to_def_id()))
+        (param.def_id, ResolvedArg::LateBound(depth, idx, param.def_id.to_def_id()))
     }
 
     fn id(&self) -> Option<DefId> {
         match *self {
-            Region::Static => None,
+            ResolvedArg::StaticLifetime | ResolvedArg::Error(_) => None,
 
-            Region::EarlyBound(id) | Region::LateBound(_, _, id) | Region::Free(_, id) => Some(id),
+            ResolvedArg::EarlyBound(id)
+            | ResolvedArg::LateBound(_, _, id)
+            | ResolvedArg::Free(_, id) => Some(id),
         }
     }
 
-    fn shifted(self, amount: u32) -> Region {
+    fn shifted(self, amount: u32) -> ResolvedArg {
         match self {
-            Region::LateBound(debruijn, idx, id) => {
-                Region::LateBound(debruijn.shifted_in(amount), idx, id)
+            ResolvedArg::LateBound(debruijn, idx, id) => {
+                ResolvedArg::LateBound(debruijn.shifted_in(amount), idx, id)
             }
             _ => self,
         }
     }
 }
 
-/// Maps the id of each lifetime reference to the lifetime decl
+/// Maps the id of each bound variable reference to the variable decl
 /// that it corresponds to.
 ///
-/// FIXME. This struct gets converted to a `ResolveLifetimes` for
+/// FIXME. This struct gets converted to a `ResolveBoundVars` for
 /// actual use. It has the same data, but indexed by `LocalDefId`. This
 /// is silly.
 #[derive(Debug, Default)]
-struct NamedRegionMap {
-    // maps from every use of a named (not anonymous) lifetime to a
-    // `Region` describing how that region is bound
-    defs: HirIdMap<Region>,
+struct NamedVarMap {
+    // maps from every use of a named (not anonymous) bound var to a
+    // `ResolvedArg` describing how that variable is bound
+    defs: HirIdMap<ResolvedArg>,
 
     // Maps relevant hir items to the bound vars on them. These include:
     // - function defs
@@ -87,9 +89,9 @@ struct NamedRegionMap {
     late_bound_vars: HirIdMap<Vec<ty::BoundVariableKind>>,
 }
 
-struct LifetimeContext<'a, 'tcx> {
+struct BoundVarContext<'a, 'tcx> {
     tcx: TyCtxt<'tcx>,
-    map: &'a mut NamedRegionMap,
+    map: &'a mut NamedVarMap,
     scope: ScopeRef<'a>,
 }
 
@@ -102,7 +104,7 @@ enum Scope<'a> {
     Binder {
         /// We use an IndexMap here because we want these lifetimes in order
         /// for diagnostics.
-        lifetimes: FxIndexMap<LocalDefId, Region>,
+        bound_vars: FxIndexMap<LocalDefId, ResolvedArg>,
 
         scope_type: BinderScopeType,
 
@@ -141,7 +143,7 @@ enum Scope<'a> {
     /// inferred in a function body or potentially error outside one),
     /// for the default choice of lifetime in a trait object type.
     ObjectLifetimeDefault {
-        lifetime: Option<Region>,
+        lifetime: Option<ResolvedArg>,
         s: ScopeRef<'a>,
     },
 
@@ -150,7 +152,7 @@ enum Scope<'a> {
     /// lifetimes encountered when identifying the trait that an associated type
     /// is declared on.
     Supertrait {
-        lifetimes: Vec<ty::BoundVariableKind>,
+        bound_vars: Vec<ty::BoundVariableKind>,
         s: ScopeRef<'a>,
     },
 
@@ -185,9 +187,9 @@ struct TruncatedScopeDebug<'a>(&'a Scope<'a>);
 impl<'a> fmt::Debug for TruncatedScopeDebug<'a> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match self.0 {
-            Scope::Binder { lifetimes, scope_type, hir_id, where_bound_origin, s: _ } => f
+            Scope::Binder { bound_vars, scope_type, hir_id, where_bound_origin, s: _ } => f
                 .debug_struct("Binder")
-                .field("lifetimes", lifetimes)
+                .field("bound_vars", bound_vars)
                 .field("scope_type", scope_type)
                 .field("hir_id", hir_id)
                 .field("where_bound_origin", where_bound_origin)
@@ -202,9 +204,9 @@ impl<'a> fmt::Debug for TruncatedScopeDebug<'a> {
                 .field("lifetime", lifetime)
                 .field("s", &"..")
                 .finish(),
-            Scope::Supertrait { lifetimes, s: _ } => f
+            Scope::Supertrait { bound_vars, s: _ } => f
                 .debug_struct("Supertrait")
-                .field("lifetimes", lifetimes)
+                .field("bound_vars", bound_vars)
                 .field("s", &"..")
                 .finish(),
             Scope::TraitRefBoundary { s: _ } => f.debug_struct("TraitRefBoundary").finish(),
@@ -219,27 +221,27 @@ type ScopeRef<'a> = &'a Scope<'a>;
 
 pub(crate) fn provide(providers: &mut ty::query::Providers) {
     *providers = ty::query::Providers {
-        resolve_lifetimes,
+        resolve_bound_vars,
 
-        named_region_map: |tcx, id| tcx.resolve_lifetimes(id).defs.get(&id),
+        named_variable_map: |tcx, id| tcx.resolve_bound_vars(id).defs.get(&id),
         is_late_bound_map,
         object_lifetime_default,
-        late_bound_vars_map: |tcx, id| tcx.resolve_lifetimes(id).late_bound_vars.get(&id),
+        late_bound_vars_map: |tcx, id| tcx.resolve_bound_vars(id).late_bound_vars.get(&id),
 
         ..*providers
     };
 }
 
-/// Computes the `ResolveLifetimes` map that contains data for an entire `Item`.
+/// Computes the `ResolveBoundVars` map that contains data for an entire `Item`.
 /// You should not read the result of this query directly, but rather use
-/// `named_region_map`, `is_late_bound_map`, etc.
+/// `named_variable_map`, `is_late_bound_map`, etc.
 #[instrument(level = "debug", skip(tcx))]
-fn resolve_lifetimes(tcx: TyCtxt<'_>, local_def_id: hir::OwnerId) -> ResolveLifetimes {
-    let mut named_region_map =
-        NamedRegionMap { defs: Default::default(), late_bound_vars: Default::default() };
-    let mut visitor = LifetimeContext {
+fn resolve_bound_vars(tcx: TyCtxt<'_>, local_def_id: hir::OwnerId) -> ResolveBoundVars {
+    let mut named_variable_map =
+        NamedVarMap { defs: Default::default(), late_bound_vars: Default::default() };
+    let mut visitor = BoundVarContext {
         tcx,
-        map: &mut named_region_map,
+        map: &mut named_variable_map,
         scope: &Scope::Root { opt_parent_item: None },
     };
     match tcx.hir().owner(local_def_id) {
@@ -260,13 +262,13 @@ fn resolve_lifetimes(tcx: TyCtxt<'_>, local_def_id: hir::OwnerId) -> ResolveLife
         hir::OwnerNode::Crate(_) => {}
     }
 
-    let mut rl = ResolveLifetimes::default();
+    let mut rl = ResolveBoundVars::default();
 
-    for (hir_id, v) in named_region_map.defs {
+    for (hir_id, v) in named_variable_map.defs {
         let map = rl.defs.entry(hir_id.owner).or_default();
         map.insert(hir_id.local_id, v);
     }
-    for (hir_id, v) in named_region_map.late_bound_vars {
+    for (hir_id, v) in named_variable_map.late_bound_vars {
         let map = rl.late_bound_vars.entry(hir_id.owner).or_default();
         map.insert(hir_id.local_id, v);
     }
@@ -276,21 +278,33 @@ fn resolve_lifetimes(tcx: TyCtxt<'_>, local_def_id: hir::OwnerId) -> ResolveLife
     rl
 }
 
-fn late_region_as_bound_region(tcx: TyCtxt<'_>, region: &Region) -> ty::BoundVariableKind {
-    match region {
-        Region::LateBound(_, _, def_id) => {
+fn late_arg_as_bound_arg<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    arg: &ResolvedArg,
+    param: &GenericParam<'tcx>,
+) -> ty::BoundVariableKind {
+    match arg {
+        ResolvedArg::LateBound(_, _, def_id) => {
             let name = tcx.hir().name(tcx.hir().local_def_id_to_hir_id(def_id.expect_local()));
-            ty::BoundVariableKind::Region(ty::BrNamed(*def_id, name))
+            match param.kind {
+                GenericParamKind::Lifetime { .. } => {
+                    ty::BoundVariableKind::Region(ty::BrNamed(*def_id, name))
+                }
+                GenericParamKind::Type { .. } => {
+                    ty::BoundVariableKind::Ty(ty::BoundTyKind::Param(*def_id, name))
+                }
+                GenericParamKind::Const { .. } => ty::BoundVariableKind::Const,
+            }
         }
-        _ => bug!("{:?} is not a late region", region),
+        _ => bug!("{:?} is not a late argument", arg),
     }
 }
 
-impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
+impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
     /// Returns the binders in scope and the type of `Binder` that should be created for a poly trait ref.
     fn poly_trait_ref_binder_info(&mut self) -> (Vec<ty::BoundVariableKind>, BinderScopeType) {
         let mut scope = self.scope;
-        let mut supertrait_lifetimes = vec![];
+        let mut supertrait_bound_vars = vec![];
         loop {
             match scope {
                 Scope::Body { .. } | Scope::Root { .. } => {
@@ -301,14 +315,14 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
                     scope = s;
                 }
 
-                Scope::Supertrait { s, lifetimes } => {
-                    supertrait_lifetimes = lifetimes.clone();
+                Scope::Supertrait { s, bound_vars } => {
+                    supertrait_bound_vars = bound_vars.clone();
                     scope = s;
                 }
 
                 Scope::TraitRefBoundary { .. } => {
                     // We should only see super trait lifetimes if there is a `Binder` above
-                    assert!(supertrait_lifetimes.is_empty());
+                    assert!(supertrait_bound_vars.is_empty());
                     break (vec![], BinderScopeType::Normal);
                 }
 
@@ -316,14 +330,64 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
                     // Nested poly trait refs have the binders concatenated
                     let mut full_binders =
                         self.map.late_bound_vars.entry(*hir_id).or_default().clone();
-                    full_binders.extend(supertrait_lifetimes.into_iter());
+                    full_binders.extend(supertrait_bound_vars.into_iter());
                     break (full_binders, BinderScopeType::Concatenating);
                 }
             }
         }
     }
+
+    fn visit_poly_trait_ref_inner(
+        &mut self,
+        trait_ref: &'tcx hir::PolyTraitRef<'tcx>,
+        non_lifetime_binder_allowed: NonLifetimeBinderAllowed,
+    ) {
+        debug!("visit_poly_trait_ref(trait_ref={:?})", trait_ref);
+
+        let (mut binders, scope_type) = self.poly_trait_ref_binder_info();
+
+        let initial_bound_vars = binders.len() as u32;
+        let mut bound_vars: FxIndexMap<LocalDefId, ResolvedArg> = FxIndexMap::default();
+        let binders_iter =
+            trait_ref.bound_generic_params.iter().enumerate().map(|(late_bound_idx, param)| {
+                let pair = ResolvedArg::late(initial_bound_vars + late_bound_idx as u32, param);
+                let r = late_arg_as_bound_arg(self.tcx, &pair.1, param);
+                bound_vars.insert(pair.0, pair.1);
+                r
+            });
+        binders.extend(binders_iter);
+
+        if let NonLifetimeBinderAllowed::Deny(where_) = non_lifetime_binder_allowed {
+            deny_non_region_late_bound(self.tcx, &mut bound_vars, where_);
+        }
+
+        debug!(?binders);
+        self.record_late_bound_vars(trait_ref.trait_ref.hir_ref_id, binders);
+
+        // Always introduce a scope here, even if this is in a where clause and
+        // we introduced the binders around the bounded Ty. In that case, we
+        // just reuse the concatenation functionality also present in nested trait
+        // refs.
+        let scope = Scope::Binder {
+            hir_id: trait_ref.trait_ref.hir_ref_id,
+            bound_vars,
+            s: self.scope,
+            scope_type,
+            where_bound_origin: None,
+        };
+        self.with(scope, |this| {
+            walk_list!(this, visit_generic_param, trait_ref.bound_generic_params);
+            this.visit_trait_ref(&trait_ref.trait_ref);
+        });
+    }
 }
-impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
+
+enum NonLifetimeBinderAllowed {
+    Deny(&'static str),
+    Allow,
+}
+
+impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
     type NestedFilter = nested_filter::OnlyBodies;
 
     fn nested_visit_map(&mut self) -> Self::Map {
@@ -386,22 +450,23 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
                 }
             }
 
-            let (lifetimes, binders): (FxIndexMap<LocalDefId, Region>, Vec<_>) =
+            let (mut bound_vars, binders): (FxIndexMap<LocalDefId, ResolvedArg>, Vec<_>) =
                 bound_generic_params
                     .iter()
-                    .filter(|param| matches!(param.kind, GenericParamKind::Lifetime { .. }))
                     .enumerate()
                     .map(|(late_bound_idx, param)| {
-                        let pair = Region::late(late_bound_idx as u32, param);
-                        let r = late_region_as_bound_region(self.tcx, &pair.1);
+                        let pair = ResolvedArg::late(late_bound_idx as u32, param);
+                        let r = late_arg_as_bound_arg(self.tcx, &pair.1, param);
                         (pair, r)
                     })
                     .unzip();
 
+            deny_non_region_late_bound(self.tcx, &mut bound_vars, "closures");
+
             self.record_late_bound_vars(e.hir_id, binders);
             let scope = Scope::Binder {
                 hir_id: e.hir_id,
-                lifetimes,
+                bound_vars,
                 s: self.scope,
                 scope_type: BinderScopeType::Normal,
                 where_bound_origin: None,
@@ -461,7 +526,8 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
                 // conservatively add all resolved lifetimes. Otherwise we run into problems in
                 // cases like `type Foo<'a> = impl Bar<As = impl Baz + 'a>`.
                 let parent_item = self.tcx.hir().get_parent_item(item.hir_id());
-                let resolved_lifetimes: &ResolveLifetimes = self.tcx.resolve_lifetimes(parent_item);
+                let resolved_lifetimes: &ResolveBoundVars =
+                    self.tcx.resolve_bound_vars(parent_item);
                 // We need to add *all* deps, since opaque tys may want them from *us*
                 for (&owner, defs) in resolved_lifetimes.defs.iter() {
                     defs.iter().for_each(|(&local_id, region)| {
@@ -478,35 +544,33 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
                 }
             }
             hir::ItemKind::OpaqueTy(hir::OpaqueTy {
-                origin: hir::OpaqueTyOrigin::FnReturn(_) | hir::OpaqueTyOrigin::AsyncFn(_),
+                origin: hir::OpaqueTyOrigin::FnReturn(parent) | hir::OpaqueTyOrigin::AsyncFn(parent),
                 generics,
                 ..
             }) => {
                 // We want to start our early-bound indices at the end of the parent scope,
                 // not including any parent `impl Trait`s.
-                let mut lifetimes = FxIndexMap::default();
+                let mut bound_vars = FxIndexMap::default();
                 debug!(?generics.params);
                 for param in generics.params {
-                    match param.kind {
-                        GenericParamKind::Lifetime { .. } => {
-                            let (def_id, reg) = Region::early(&param);
-                            lifetimes.insert(def_id, reg);
-                        }
-                        GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => {}
-                    }
+                    let (def_id, reg) = ResolvedArg::early(&param);
+                    bound_vars.insert(def_id, reg);
                 }
 
-                let scope = Scope::Binder {
-                    hir_id: item.hir_id(),
-                    lifetimes,
-                    s: self.scope,
-                    scope_type: BinderScopeType::Normal,
-                    where_bound_origin: None,
-                };
+                let scope = Scope::Root { opt_parent_item: Some(parent) };
                 self.with(scope, |this| {
-                    let scope = Scope::TraitRefBoundary { s: this.scope };
-                    this.with(scope, |this| intravisit::walk_item(this, item))
-                });
+                    let scope = Scope::Binder {
+                        hir_id: item.hir_id(),
+                        bound_vars,
+                        s: this.scope,
+                        scope_type: BinderScopeType::Normal,
+                        where_bound_origin: None,
+                    };
+                    this.with(scope, |this| {
+                        let scope = Scope::TraitRefBoundary { s: this.scope };
+                        this.with(scope, |this| intravisit::walk_item(this, item))
+                    });
+                })
             }
             hir::ItemKind::TyAlias(_, generics)
             | hir::ItemKind::Enum(_, generics)
@@ -516,18 +580,11 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
             | hir::ItemKind::TraitAlias(generics, ..)
             | hir::ItemKind::Impl(&hir::Impl { generics, .. }) => {
                 // These kinds of items have only early-bound lifetime parameters.
-                let lifetimes = generics
-                    .params
-                    .iter()
-                    .filter_map(|param| match param.kind {
-                        GenericParamKind::Lifetime { .. } => Some(Region::early(param)),
-                        GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => None,
-                    })
-                    .collect();
+                let bound_vars = generics.params.iter().map(ResolvedArg::early).collect();
                 self.record_late_bound_vars(item.hir_id(), vec![]);
                 let scope = Scope::Binder {
                     hir_id: item.hir_id(),
-                    lifetimes,
+                    bound_vars,
                     scope_type: BinderScopeType::Normal,
                     s: self.scope,
                     where_bound_origin: None,
@@ -562,21 +619,23 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
     fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx>) {
         match ty.kind {
             hir::TyKind::BareFn(c) => {
-                let (lifetimes, binders): (FxIndexMap<LocalDefId, Region>, Vec<_>) = c
+                let (mut bound_vars, binders): (FxIndexMap<LocalDefId, ResolvedArg>, Vec<_>) = c
                     .generic_params
                     .iter()
-                    .filter(|param| matches!(param.kind, GenericParamKind::Lifetime { .. }))
                     .enumerate()
                     .map(|(late_bound_idx, param)| {
-                        let pair = Region::late(late_bound_idx as u32, param);
-                        let r = late_region_as_bound_region(self.tcx, &pair.1);
+                        let pair = ResolvedArg::late(late_bound_idx as u32, param);
+                        let r = late_arg_as_bound_arg(self.tcx, &pair.1, param);
                         (pair, r)
                     })
                     .unzip();
+
+                deny_non_region_late_bound(self.tcx, &mut bound_vars, "function pointer types");
+
                 self.record_late_bound_vars(ty.hir_id, binders);
                 let scope = Scope::Binder {
                     hir_id: ty.hir_id,
-                    lifetimes,
+                    bound_vars,
                     s: self.scope,
                     scope_type: BinderScopeType::Normal,
                     where_bound_origin: None,
@@ -592,7 +651,10 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
                 let scope = Scope::TraitRefBoundary { s: self.scope };
                 self.with(scope, |this| {
                     for bound in bounds {
-                        this.visit_poly_trait_ref(bound);
+                        this.visit_poly_trait_ref_inner(
+                            bound,
+                            NonLifetimeBinderAllowed::Deny("trait object types"),
+                        );
                     }
                 });
                 match lifetime.res {
@@ -674,7 +736,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
                     // well-supported at the moment, so this doesn't work.
                     // In the future, this should be fixed and this error should be removed.
                     let def = self.map.defs.get(&lifetime.hir_id).cloned();
-                    let Some(Region::LateBound(_, _, def_id)) = def else {
+                    let Some(ResolvedArg::LateBound(_, _, def_id)) = def else {
                         continue
                     };
                     let Some(def_id) = def_id.as_local() else {
@@ -722,18 +784,11 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
             }
             Type(bounds, ty) => {
                 let generics = &trait_item.generics;
-                let lifetimes = generics
-                    .params
-                    .iter()
-                    .filter_map(|param| match param.kind {
-                        GenericParamKind::Lifetime { .. } => Some(Region::early(param)),
-                        GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => None,
-                    })
-                    .collect();
+                let bound_vars = generics.params.iter().map(ResolvedArg::early).collect();
                 self.record_late_bound_vars(trait_item.hir_id(), vec![]);
                 let scope = Scope::Binder {
                     hir_id: trait_item.hir_id(),
-                    lifetimes,
+                    bound_vars,
                     s: self.scope,
                     scope_type: BinderScopeType::Normal,
                     where_bound_origin: None,
@@ -768,18 +823,12 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
             }),
             Type(ty) => {
                 let generics = &impl_item.generics;
-                let lifetimes: FxIndexMap<LocalDefId, Region> = generics
-                    .params
-                    .iter()
-                    .filter_map(|param| match param.kind {
-                        GenericParamKind::Lifetime { .. } => Some(Region::early(param)),
-                        GenericParamKind::Const { .. } | GenericParamKind::Type { .. } => None,
-                    })
-                    .collect();
+                let bound_vars: FxIndexMap<LocalDefId, ResolvedArg> =
+                    generics.params.iter().map(ResolvedArg::early).collect();
                 self.record_late_bound_vars(impl_item.hir_id(), vec![]);
                 let scope = Scope::Binder {
                     hir_id: impl_item.hir_id(),
-                    lifetimes,
+                    bound_vars,
                     s: self.scope,
                     scope_type: BinderScopeType::Normal,
                     where_bound_origin: None,
@@ -803,7 +852,9 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
     #[instrument(level = "debug", skip(self))]
     fn visit_lifetime(&mut self, lifetime_ref: &'tcx hir::Lifetime) {
         match lifetime_ref.res {
-            hir::LifetimeName::Static => self.insert_lifetime(lifetime_ref, Region::Static),
+            hir::LifetimeName::Static => {
+                self.insert_lifetime(lifetime_ref, ResolvedArg::StaticLifetime)
+            }
             hir::LifetimeName::Param(param_def_id) => {
                 self.resolve_lifetime_ref(param_def_id, lifetime_ref)
             }
@@ -814,13 +865,16 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
         }
     }
 
-    fn visit_path(&mut self, path: &hir::Path<'tcx>, _: hir::HirId) {
+    fn visit_path(&mut self, path: &hir::Path<'tcx>, hir_id: hir::HirId) {
         for (i, segment) in path.segments.iter().enumerate() {
             let depth = path.segments.len() - i - 1;
             if let Some(args) = segment.args {
                 self.visit_segment_args(path.res, depth, args);
             }
         }
+        if let Res::Def(DefKind::TyParam | DefKind::ConstParam, param_def_id) = path.res {
+            self.resolve_type_ref(param_def_id.expect_local(), hir_id);
+        }
     }
 
     fn visit_fn(
@@ -869,24 +923,17 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
                         origin,
                         ..
                     }) => {
-                        let lifetimes: FxIndexMap<LocalDefId, Region> =
+
+                        let (bound_vars, binders): (FxIndexMap<LocalDefId, ResolvedArg>, Vec<_>) =
                             bound_generic_params
-                                .iter()
-                                .filter(|param| {
-                                    matches!(param.kind, GenericParamKind::Lifetime { .. })
-                                })
-                                .enumerate()
-                                .map(|(late_bound_idx, param)| {
-                                        Region::late(late_bound_idx as u32, param)
-                                })
-                                .collect();
-                        let binders: Vec<_> =
-                            lifetimes
-                                .iter()
-                                .map(|(_, region)| {
-                                     late_region_as_bound_region(this.tcx, region)
-                                })
-                                .collect();
+                            .iter()
+                            .enumerate()
+                            .map(|(late_bound_idx, param)| {
+                                let pair = ResolvedArg::late(late_bound_idx as u32, param);
+                                let r = late_arg_as_bound_arg(this.tcx, &pair.1, param);
+                                (pair, r)
+                            })
+                            .unzip();
                         this.record_late_bound_vars(hir_id, binders.clone());
                         // Even if there are no lifetimes defined here, we still wrap it in a binder
                         // scope. If there happens to be a nested poly trait ref (an error), that
@@ -894,7 +941,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
                         // being wrong.
                         let scope = Scope::Binder {
                             hir_id,
-                            lifetimes,
+                            bound_vars,
                             s: this.scope,
                             scope_type: BinderScopeType::Normal,
                             where_bound_origin: Some(origin),
@@ -920,7 +967,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
                                 if lt.res != hir::LifetimeName::Static {
                                     continue;
                                 }
-                                this.insert_lifetime(lt, Region::Static);
+                                this.insert_lifetime(lt, ResolvedArg::StaticLifetime);
                                 this.tcx
                                     .sess
                                     .struct_span_warn(
@@ -964,7 +1011,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
                 self.record_late_bound_vars(*hir_id, binders);
                 let scope = Scope::Binder {
                     hir_id: *hir_id,
-                    lifetimes: FxIndexMap::default(),
+                    bound_vars: FxIndexMap::default(),
                     s: self.scope,
                     scope_type,
                     where_bound_origin: None,
@@ -978,43 +1025,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
     }
 
     fn visit_poly_trait_ref(&mut self, trait_ref: &'tcx hir::PolyTraitRef<'tcx>) {
-        debug!("visit_poly_trait_ref(trait_ref={:?})", trait_ref);
-
-        let (mut binders, scope_type) = self.poly_trait_ref_binder_info();
-
-        let initial_bound_vars = binders.len() as u32;
-        let mut lifetimes: FxIndexMap<LocalDefId, Region> = FxIndexMap::default();
-        let binders_iter = trait_ref
-            .bound_generic_params
-            .iter()
-            .filter(|param| matches!(param.kind, GenericParamKind::Lifetime { .. }))
-            .enumerate()
-            .map(|(late_bound_idx, param)| {
-                let pair = Region::late(initial_bound_vars + late_bound_idx as u32, param);
-                let r = late_region_as_bound_region(self.tcx, &pair.1);
-                lifetimes.insert(pair.0, pair.1);
-                r
-            });
-        binders.extend(binders_iter);
-
-        debug!(?binders);
-        self.record_late_bound_vars(trait_ref.trait_ref.hir_ref_id, binders);
-
-        // Always introduce a scope here, even if this is in a where clause and
-        // we introduced the binders around the bounded Ty. In that case, we
-        // just reuse the concatenation functionality also present in nested trait
-        // refs.
-        let scope = Scope::Binder {
-            hir_id: trait_ref.trait_ref.hir_ref_id,
-            lifetimes,
-            s: self.scope,
-            scope_type,
-            where_bound_origin: None,
-        };
-        self.with(scope, |this| {
-            walk_list!(this, visit_generic_param, trait_ref.bound_generic_params);
-            this.visit_trait_ref(&trait_ref.trait_ref);
-        });
+        self.visit_poly_trait_ref_inner(trait_ref, NonLifetimeBinderAllowed::Allow);
     }
 }
 
@@ -1063,13 +1074,13 @@ fn object_lifetime_default(tcx: TyCtxt<'_>, param_def_id: DefId) -> ObjectLifeti
     }
 }
 
-impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
+impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
     fn with<F>(&mut self, wrap_scope: Scope<'_>, f: F)
     where
-        F: for<'b> FnOnce(&mut LifetimeContext<'b, 'tcx>),
+        F: for<'b> FnOnce(&mut BoundVarContext<'b, 'tcx>),
     {
-        let LifetimeContext { tcx, map, .. } = self;
-        let mut this = LifetimeContext { tcx: *tcx, map, scope: &wrap_scope };
+        let BoundVarContext { tcx, map, .. } = self;
+        let mut this = BoundVarContext { tcx: *tcx, map, scope: &wrap_scope };
         let span = debug_span!("scope", scope = ?TruncatedScopeDebug(&this.scope));
         {
             let _enter = span.enter();
@@ -1110,23 +1121,25 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
         generics: &'tcx hir::Generics<'tcx>,
         walk: F,
     ) where
-        F: for<'b, 'c> FnOnce(&'b mut LifetimeContext<'c, 'tcx>),
+        F: for<'b, 'c> FnOnce(&'b mut BoundVarContext<'c, 'tcx>),
     {
         let mut named_late_bound_vars = 0;
-        let lifetimes: FxIndexMap<LocalDefId, Region> = generics
+        let bound_vars: FxIndexMap<LocalDefId, ResolvedArg> = generics
             .params
             .iter()
-            .filter_map(|param| match param.kind {
+            .map(|param| match param.kind {
                 GenericParamKind::Lifetime { .. } => {
                     if self.tcx.is_late_bound(param.hir_id) {
                         let late_bound_idx = named_late_bound_vars;
                         named_late_bound_vars += 1;
-                        Some(Region::late(late_bound_idx, param))
+                        ResolvedArg::late(late_bound_idx, param)
                     } else {
-                        Some(Region::early(param))
+                        ResolvedArg::early(param)
                     }
                 }
-                GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => None,
+                GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => {
+                    ResolvedArg::early(param)
+                }
             })
             .collect();
 
@@ -1139,14 +1152,14 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
             })
             .enumerate()
             .map(|(late_bound_idx, param)| {
-                let pair = Region::late(late_bound_idx as u32, param);
-                late_region_as_bound_region(self.tcx, &pair.1)
+                let pair = ResolvedArg::late(late_bound_idx as u32, param);
+                late_arg_as_bound_arg(self.tcx, &pair.1, param)
             })
             .collect();
         self.record_late_bound_vars(hir_id, binders);
         let scope = Scope::Binder {
             hir_id,
-            lifetimes,
+            bound_vars,
             s: self.scope,
             scope_type: BinderScopeType::Normal,
             where_bound_origin: None,
@@ -1177,15 +1190,15 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
                 Scope::Root { opt_parent_item } => {
                     if let Some(parent_item) = opt_parent_item
                         && let parent_generics = self.tcx.generics_of(parent_item)
-                        && parent_generics.param_def_id_to_index.contains_key(&region_def_id.to_def_id())
+                        && parent_generics.param_def_id_to_index(self.tcx, region_def_id.to_def_id()).is_some()
                     {
-                        break Some(Region::EarlyBound(region_def_id.to_def_id()));
+                        break Some(ResolvedArg::EarlyBound(region_def_id.to_def_id()));
                     }
                     break None;
                 }
 
-                Scope::Binder { ref lifetimes, scope_type, s, where_bound_origin, .. } => {
-                    if let Some(&def) = lifetimes.get(&region_def_id) {
+                Scope::Binder { ref bound_vars, scope_type, s, where_bound_origin, .. } => {
+                    if let Some(&def) = bound_vars.get(&region_def_id) {
                         break Some(def.shifted(late_depth));
                     }
                     match scope_type {
@@ -1259,7 +1272,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
         };
 
         if let Some(mut def) = result {
-            if let Region::EarlyBound(..) = def {
+            if let ResolvedArg::EarlyBound(..) = def {
                 // Do not free early-bound regions, only late-bound ones.
             } else if let Some(body_id) = outermost_body {
                 let fn_id = self.tcx.hir().body_owner(body_id);
@@ -1275,10 +1288,10 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
                         kind: hir::ImplItemKind::Fn(..),
                         ..
                     }) => {
-                        def = Region::Free(owner_id.to_def_id(), def.id().unwrap());
+                        def = ResolvedArg::Free(owner_id.to_def_id(), def.id().unwrap());
                     }
                     Node::Expr(hir::Expr { kind: hir::ExprKind::Closure(closure), .. }) => {
-                        def = Region::Free(closure.def_id.to_def_id(), def.id().unwrap());
+                        def = ResolvedArg::Free(closure.def_id.to_def_id(), def.id().unwrap());
                     }
                     _ => {}
                 }
@@ -1329,6 +1342,59 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
         );
     }
 
+    fn resolve_type_ref(&mut self, param_def_id: LocalDefId, hir_id: hir::HirId) {
+        // Walk up the scope chain, tracking the number of fn scopes
+        // that we pass through, until we find a lifetime with the
+        // given name or we run out of scopes.
+        // search.
+        let mut late_depth = 0;
+        let mut scope = self.scope;
+        let result = loop {
+            match *scope {
+                Scope::Body { s, .. } => {
+                    scope = s;
+                }
+
+                Scope::Root { opt_parent_item } => {
+                    if let Some(parent_item) = opt_parent_item
+                        && let parent_generics = self.tcx.generics_of(parent_item)
+                        && parent_generics.param_def_id_to_index(self.tcx, param_def_id.to_def_id()).is_some()
+                    {
+                        break Some(ResolvedArg::EarlyBound(param_def_id.to_def_id()));
+                    }
+                    break None;
+                }
+
+                Scope::Binder { ref bound_vars, scope_type, s, .. } => {
+                    if let Some(&def) = bound_vars.get(&param_def_id) {
+                        break Some(def.shifted(late_depth));
+                    }
+                    match scope_type {
+                        BinderScopeType::Normal => late_depth += 1,
+                        BinderScopeType::Concatenating => {}
+                    }
+                    scope = s;
+                }
+
+                Scope::Elision { s, .. }
+                | Scope::ObjectLifetimeDefault { s, .. }
+                | Scope::Supertrait { s, .. }
+                | Scope::TraitRefBoundary { s, .. } => {
+                    scope = s;
+                }
+            }
+        };
+
+        if let Some(def) = result {
+            self.map.defs.insert(hir_id, def);
+            return;
+        }
+
+        self.tcx
+            .sess
+            .delay_span_bug(self.tcx.hir().span(hir_id), "could not resolve {param_def_id:?}");
+    }
+
     #[instrument(level = "debug", skip(self))]
     fn visit_segment_args(
         &mut self,
@@ -1415,10 +1481,10 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
                     if in_body {
                         None
                     } else {
-                        Some(Region::Static)
+                        Some(ResolvedArg::StaticLifetime)
                     }
                 }
-                ObjectLifetimeDefault::Static => Some(Region::Static),
+                ObjectLifetimeDefault::Static => Some(ResolvedArg::StaticLifetime),
                 ObjectLifetimeDefault::Param(param_def_id) => {
                     // This index can be used with `generic_args` since `parent_count == 0`.
                     let index = generics.param_def_id_to_index[&param_def_id] as usize;
@@ -1507,18 +1573,19 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
         // in the trait ref `YY<...>` in `Item: YY<...>`.
         for binding in generic_args.bindings {
             let scope = Scope::ObjectLifetimeDefault {
-                lifetime: if has_lifetime_parameter { None } else { Some(Region::Static) },
+                lifetime: if has_lifetime_parameter {
+                    None
+                } else {
+                    Some(ResolvedArg::StaticLifetime)
+                },
                 s: self.scope,
             };
             if let Some(type_def_id) = type_def_id {
-                let lifetimes = LifetimeContext::supertrait_hrtb_lifetimes(
-                    self.tcx,
-                    type_def_id,
-                    binding.ident,
-                );
+                let bound_vars =
+                    BoundVarContext::supertrait_hrtb_vars(self.tcx, type_def_id, binding.ident);
                 self.with(scope, |this| {
                     let scope = Scope::Supertrait {
-                        lifetimes: lifetimes.unwrap_or_default(),
+                        bound_vars: bound_vars.unwrap_or_default(),
                         s: this.scope,
                     };
                     this.with(scope, |this| this.visit_assoc_type_binding(binding));
@@ -1541,7 +1608,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
     /// ```
     /// In this case, if we wanted to the supertrait HRTB lifetimes for `As` on
     /// the starting trait `Bar`, we would return `Some(['b, 'a])`.
-    fn supertrait_hrtb_lifetimes(
+    fn supertrait_hrtb_vars(
         tcx: TyCtxt<'tcx>,
         def_id: DefId,
         assoc_name: Ident,
@@ -1626,7 +1693,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
                     scope = s;
                 }
 
-                Scope::Root { .. } | Scope::Elision { .. } => break Region::Static,
+                Scope::Root { .. } | Scope::Elision { .. } => break ResolvedArg::StaticLifetime,
 
                 Scope::Body { .. } | Scope::ObjectLifetimeDefault { lifetime: None, .. } => return,
 
@@ -1641,7 +1708,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
     }
 
     #[instrument(level = "debug", skip(self))]
-    fn insert_lifetime(&mut self, lifetime_ref: &'tcx hir::Lifetime, def: Region) {
+    fn insert_lifetime(&mut self, lifetime_ref: &'tcx hir::Lifetime, def: ResolvedArg) {
         debug!(span = ?lifetime_ref.ident.span);
         self.map.defs.insert(lifetime_ref.hir_id, def);
     }
@@ -1649,7 +1716,11 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
     /// Sometimes we resolve a lifetime, but later find that it is an
     /// error (esp. around impl trait). In that case, we remove the
     /// entry into `map.defs` so as not to confuse later code.
-    fn uninsert_lifetime_on_error(&mut self, lifetime_ref: &'tcx hir::Lifetime, bad_def: Region) {
+    fn uninsert_lifetime_on_error(
+        &mut self,
+        lifetime_ref: &'tcx hir::Lifetime,
+        bad_def: ResolvedArg,
+    ) {
         let old_value = self.map.defs.remove(&lifetime_ref.hir_id);
         assert_eq!(old_value, Some(bad_def));
     }
@@ -1804,7 +1875,7 @@ fn is_late_bound_map(
                     let mut walker = ConstrainedCollectorPostAstConv {
                         arg_is_constrained: vec![false; generics.params.len()].into_boxed_slice(),
                     };
-                    walker.visit_ty(self.tcx.type_of(alias_def));
+                    walker.visit_ty(self.tcx.type_of(alias_def).subst_identity());
 
                     match segments.last() {
                         Some(hir::PathSegment { args: Some(args), .. }) => {
@@ -1872,3 +1943,37 @@ fn is_late_bound_map(
         }
     }
 }
+
+pub fn deny_non_region_late_bound(
+    tcx: TyCtxt<'_>,
+    bound_vars: &mut FxIndexMap<LocalDefId, ResolvedArg>,
+    where_: &str,
+) {
+    let mut first = true;
+
+    for (var, arg) in bound_vars {
+        let Node::GenericParam(param) = tcx.hir().get_by_def_id(*var) else {
+            bug!();
+        };
+
+        let what = match param.kind {
+            hir::GenericParamKind::Type { .. } => "type",
+            hir::GenericParamKind::Const { .. } => "const",
+            hir::GenericParamKind::Lifetime { .. } => continue,
+        };
+
+        let mut diag = tcx.sess.struct_span_err(
+            param.span,
+            format!("late-bound {what} parameter not allowed on {where_}"),
+        );
+
+        let guar = if tcx.features().non_lifetime_binders && first {
+            diag.emit()
+        } else {
+            diag.delay_as_bug()
+        };
+
+        first = false;
+        *arg = ResolvedArg::Error(guar);
+    }
+}
diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs
index 54fcccb0c11..a3bc0082ef2 100644
--- a/compiler/rustc_hir_analysis/src/collect/type_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs
@@ -243,7 +243,7 @@ fn get_path_containing_arg_in_pat<'hir>(
     arg_path
 }
 
-pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
+pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::EarlyBinder<Ty<'_>> {
     let def_id = def_id.expect_local();
     use rustc_hir::*;
 
@@ -251,7 +251,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
 
     let icx = ItemCtxt::new(tcx, def_id.to_def_id());
 
-    match tcx.hir().get(hir_id) {
+    let output = match tcx.hir().get(hir_id) {
         Node::TraitItem(item) => match item.kind {
             TraitItemKind::Fn(..) => {
                 let substs = InternalSubsts::identity_for_item(tcx, def_id.to_def_id());
@@ -259,13 +259,8 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
             }
             TraitItemKind::Const(ty, body_id) => body_id
                 .and_then(|body_id| {
-                    if is_suggestable_infer_ty(ty) {
-                        Some(infer_placeholder_type(
-                            tcx, def_id, body_id, ty.span, item.ident, "constant",
-                        ))
-                    } else {
-                        None
-                    }
+                    is_suggestable_infer_ty(ty)
+                        .then(|| infer_placeholder_type(tcx, def_id, body_id, ty.span, item.ident, "constant",))
                 })
                 .unwrap_or_else(|| icx.to_ty(ty)),
             TraitItemKind::Type(_, Some(ty)) => icx.to_ty(ty),
@@ -382,7 +377,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
 
         Node::Ctor(def) | Node::Variant(Variant { data: def, .. }) => match def {
             VariantData::Unit(..) | VariantData::Struct(..) => {
-                tcx.type_of(tcx.hir().get_parent_item(hir_id))
+                tcx.type_of(tcx.hir().get_parent_item(hir_id)).subst_identity()
             }
             VariantData::Tuple(..) => {
                 let substs = InternalSubsts::identity_for_item(tcx, def_id.to_def_id());
@@ -399,7 +394,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
         Node::AnonConst(_) if let Some(param) = tcx.opt_const_param_of(def_id) => {
             // We defer to `type_of` of the corresponding parameter
             // for generic arguments.
-            tcx.type_of(param)
+            tcx.type_of(param).subst_identity()
         }
 
         Node::AnonConst(_) => {
@@ -451,7 +446,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
                     && e.hir_id == hir_id =>
                 {
                     let Some(trait_def_id) = trait_ref.trait_def_id() else {
-                        return tcx.ty_error_with_message(DUMMY_SP, "Could not find trait");
+                        return ty::EarlyBinder(tcx.ty_error_with_message(DUMMY_SP, "Could not find trait"));
                     };
                     let assoc_items = tcx.associated_items(trait_def_id);
                     let assoc_item = assoc_items.find_by_name_and_kind(
@@ -461,7 +456,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
                         def_id.to_def_id(),
                     );
                     if let Some(assoc_item) = assoc_item {
-                        tcx.type_of(assoc_item.def_id)
+                        tcx.type_of(assoc_item.def_id).subst_identity()
                     } else {
                         // FIXME(associated_const_equality): add a useful error message here.
                         tcx.ty_error_with_message(
@@ -485,7 +480,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
                         }) =>
                 {
                     let Some(trait_def_id) = trait_ref.trait_def_id() else {
-                        return tcx.ty_error_with_message(DUMMY_SP, "Could not find trait");
+                        return ty::EarlyBinder(tcx.ty_error_with_message(DUMMY_SP, "Could not find trait"));
                     };
                     let assoc_items = tcx.associated_items(trait_def_id);
                     let assoc_item = assoc_items.find_by_name_and_kind(
@@ -506,7 +501,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
                     if let Some(param)
                         = assoc_item.map(|item| &tcx.generics_of(item.def_id).params[idx]).filter(|param| param.kind.is_ty_or_const())
                     {
-                        tcx.type_of(param.def_id)
+                        tcx.type_of(param.def_id).subst_identity()
                     } else {
                         // FIXME(associated_const_equality): add a useful error message here.
                         tcx.ty_error_with_message(
@@ -520,7 +515,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
                     def_id: param_def_id,
                     kind: GenericParamKind::Const { default: Some(ct), .. },
                     ..
-                }) if ct.hir_id == hir_id => tcx.type_of(param_def_id),
+                }) if ct.hir_id == hir_id => tcx.type_of(param_def_id).subst_identity(),
 
                 x => tcx.ty_error_with_message(
                     DUMMY_SP,
@@ -538,7 +533,8 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
         x => {
             bug!("unexpected sort of node in type_of(): {:?}", x);
         }
-    }
+    };
+    ty::EarlyBinder(output)
 }
 
 #[instrument(skip(tcx), level = "debug")]
diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check.rs b/compiler/rustc_hir_analysis/src/impl_wf_check.rs
index 4f30318412d..8ab9964d810 100644
--- a/compiler/rustc_hir_analysis/src/impl_wf_check.rs
+++ b/compiler/rustc_hir_analysis/src/impl_wf_check.rs
@@ -70,7 +70,7 @@ pub fn provide(providers: &mut Providers) {
 
 fn enforce_impl_params_are_constrained(tcx: TyCtxt<'_>, impl_def_id: LocalDefId) {
     // Every lifetime used in an associated type must be constrained.
-    let impl_self_ty = tcx.type_of(impl_def_id);
+    let impl_self_ty = tcx.type_of(impl_def_id).subst_identity();
     if impl_self_ty.references_error() {
         // Don't complain about unconstrained type params when self ty isn't known due to errors.
         // (#36836)
@@ -104,7 +104,7 @@ fn enforce_impl_params_are_constrained(tcx: TyCtxt<'_>, impl_def_id: LocalDefId)
             match item.kind {
                 ty::AssocKind::Type => {
                     if item.defaultness(tcx).has_value() {
-                        cgp::parameters_for(&tcx.type_of(def_id), true)
+                        cgp::parameters_for(&tcx.type_of(def_id).subst_identity(), true)
                     } else {
                         Vec::new()
                     }
diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs
index 02f77f9d6af..4741e4b095d 100644
--- a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs
+++ b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs
@@ -496,6 +496,16 @@ fn check_specialization_on<'tcx>(tcx: TyCtxt<'tcx>, predicate: ty::Predicate<'tc
                 )
                 .emit();
         }
+        ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..)) => {
+            // FIXME(min_specialization), FIXME(const_generics):
+            // It probably isn't right to allow _every_ `ConstArgHasType` but I am somewhat unsure
+            // about the actual rules that would be sound. Can't just always error here because otherwise
+            // std/core doesn't even compile as they have `const N: usize` in some specializing impls.
+            //
+            // While we do not support constructs like `<T, const N: T>` there is probably no risk of
+            // soundness bugs, but when we support generic const parameter types this will need to be
+            // revisited.
+        }
         _ => {
             tcx.sess
                 .struct_span_err(span, &format!("cannot specialize on predicate `{}`", predicate))
@@ -517,6 +527,7 @@ fn trait_predicate_kind<'tcx>(
         ty::PredicateKind::Clause(ty::Clause::RegionOutlives(_))
         | ty::PredicateKind::Clause(ty::Clause::TypeOutlives(_))
         | ty::PredicateKind::Clause(ty::Clause::Projection(_))
+        | ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..))
         | ty::PredicateKind::AliasEq(..)
         | ty::PredicateKind::WellFormed(_)
         | ty::PredicateKind::Subtype(_)
diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs
index c2fa46e563e..11240cf22e4 100644
--- a/compiler/rustc_hir_analysis/src/lib.rs
+++ b/compiler/rustc_hir_analysis/src/lib.rs
@@ -113,7 +113,6 @@ use rustc_target::spec::abi::Abi;
 use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _;
 use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode};
 
-use std::iter;
 use std::ops::Not;
 
 use astconv::AstConv;
@@ -187,7 +186,7 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) {
 
     fn main_fn_diagnostics_def_id(tcx: TyCtxt<'_>, def_id: DefId, sp: Span) -> LocalDefId {
         if let Some(local_def_id) = def_id.as_local() {
-            let hir_type = tcx.type_of(local_def_id);
+            let hir_type = tcx.type_of(local_def_id).subst_identity();
             if !matches!(hir_type.kind(), ty::FnDef(..)) {
                 span_bug!(sp, "main has a non-function type: found `{}`", hir_type);
             }
@@ -204,7 +203,7 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) {
         let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
         match tcx.hir().find(hir_id) {
             Some(Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, generics, _), .. })) => {
-                generics.params.is_empty().not().then(|| generics.span)
+                generics.params.is_empty().not().then_some(generics.span)
             }
             _ => {
                 span_bug!(tcx.def_span(def_id), "main has a non-function type");
@@ -348,7 +347,7 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) {
     }
 
     let se_ty = tcx.mk_fn_ptr(expected_return_type.map_bound(|expected_return_type| {
-        tcx.mk_fn_sig(iter::empty(), expected_return_type, false, hir::Unsafety::Normal, Abi::Rust)
+        tcx.mk_fn_sig([], expected_return_type, false, hir::Unsafety::Normal, Abi::Rust)
     }));
 
     require_same_types(
@@ -366,7 +365,7 @@ fn check_start_fn_ty(tcx: TyCtxt<'_>, start_def_id: DefId) {
     let start_def_id = start_def_id.expect_local();
     let start_id = tcx.hir().local_def_id_to_hir_id(start_def_id);
     let start_span = tcx.def_span(start_def_id);
-    let start_t = tcx.type_of(start_def_id);
+    let start_t = tcx.type_of(start_def_id).subst_identity();
     match start_t.kind() {
         ty::FnDef(..) => {
             if let Some(Node::Item(it)) = tcx.hir().find(start_id) {
@@ -434,7 +433,7 @@ fn check_start_fn_ty(tcx: TyCtxt<'_>, start_def_id: DefId) {
             }
 
             let se_ty = tcx.mk_fn_ptr(ty::Binder::dummy(tcx.mk_fn_sig(
-                [tcx.types.isize, tcx.mk_imm_ptr(tcx.mk_imm_ptr(tcx.types.u8))].iter().cloned(),
+                [tcx.types.isize, tcx.mk_imm_ptr(tcx.mk_imm_ptr(tcx.types.u8))],
                 tcx.types.isize,
                 false,
                 hir::Unsafety::Normal,
diff --git a/compiler/rustc_hir_analysis/src/outlives/explicit.rs b/compiler/rustc_hir_analysis/src/outlives/explicit.rs
index ecd6849426d..9ee6785970c 100644
--- a/compiler/rustc_hir_analysis/src/outlives/explicit.rs
+++ b/compiler/rustc_hir_analysis/src/outlives/explicit.rs
@@ -54,6 +54,7 @@ impl<'tcx> ExplicitPredicatesMap<'tcx> {
 
                     ty::PredicateKind::Clause(ty::Clause::Trait(..))
                     | ty::PredicateKind::Clause(ty::Clause::Projection(..))
+                    | ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..))
                     | ty::PredicateKind::WellFormed(..)
                     | ty::PredicateKind::AliasEq(..)
                     | ty::PredicateKind::ObjectSafe(..)
diff --git a/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs b/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs
index 925042436de..a8b33c74bc1 100644
--- a/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs
+++ b/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs
@@ -46,7 +46,7 @@ pub(super) fn infer_predicates(
                         // For field of type &'a T (reference) or Adt
                         // (struct/enum/union) there will be outlive
                         // requirements for adt_def.
-                        let field_ty = tcx.type_of(field_def.did);
+                        let field_ty = tcx.type_of(field_def.did).subst_identity();
                         let field_span = tcx.def_span(field_def.did);
                         insert_required_predicates_to_be_wf(
                             tcx,
diff --git a/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs b/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs
index 9133e6540d4..560ffc620e0 100644
--- a/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs
+++ b/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs
@@ -423,7 +423,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
 
     fn get_unbound_associated_types(&self) -> Vec<String> {
         if self.tcx.is_trait(self.def_id) {
-            let items: &AssocItems<'_> = self.tcx.associated_items(self.def_id);
+            let items: &AssocItems = self.tcx.associated_items(self.def_id);
             items
                 .in_definition_order()
                 .filter(|item| item.kind == AssocKind::Type)
diff --git a/compiler/rustc_hir_analysis/src/variance/constraints.rs b/compiler/rustc_hir_analysis/src/variance/constraints.rs
index b0cf0387f87..408bec71ee0 100644
--- a/compiler/rustc_hir_analysis/src/variance/constraints.rs
+++ b/compiler/rustc_hir_analysis/src/variance/constraints.rs
@@ -101,7 +101,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
 
         let inferred_start = self.terms_cx.inferred_starts[&def_id];
         let current_item = &CurrentItem { inferred_start };
-        match tcx.type_of(def_id).kind() {
+        match tcx.type_of(def_id).subst_identity().kind() {
             ty::Adt(def, _) => {
                 // Not entirely obvious: constraints on structs/enums do not
                 // affect the variance of their type parameters. See discussion
@@ -112,7 +112,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
                 for field in def.all_fields() {
                     self.add_constraints_from_ty(
                         current_item,
-                        tcx.type_of(field.did),
+                        tcx.type_of(field.did).subst_identity(),
                         self.covariant,
                     );
                 }
diff --git a/compiler/rustc_hir_analysis/src/variance/solve.rs b/compiler/rustc_hir_analysis/src/variance/solve.rs
index a17edb598ad..c27c176e35f 100644
--- a/compiler/rustc_hir_analysis/src/variance/solve.rs
+++ b/compiler/rustc_hir_analysis/src/variance/solve.rs
@@ -103,7 +103,7 @@ impl<'a, 'tcx> SolveContext<'a, 'tcx> {
                 self.enforce_const_invariance(generics, variances);
 
                 // Functions are permitted to have unused generic parameters: make those invariant.
-                if let ty::FnDef(..) = tcx.type_of(def_id).kind() {
+                if let ty::FnDef(..) = tcx.type_of(def_id).subst_identity().kind() {
                     for variance in variances.iter_mut() {
                         if *variance == ty::Bivariant {
                             *variance = ty::Invariant;
diff --git a/compiler/rustc_hir_typeck/src/check.rs b/compiler/rustc_hir_typeck/src/check.rs
index 05f6d8e6072..bf8259ff70f 100644
--- a/compiler/rustc_hir_typeck/src/check.rs
+++ b/compiler/rustc_hir_typeck/src/check.rs
@@ -74,15 +74,13 @@ pub(super) fn check_fn<'a, 'tcx>(
 
     // C-variadic fns also have a `VaList` input that's not listed in `fn_sig`
     // (as it's created inside the body itself, not passed in from outside).
-    let maybe_va_list = if fn_sig.c_variadic {
+    let maybe_va_list = fn_sig.c_variadic.then(|| {
         let span = body.params.last().unwrap().span;
         let va_list_did = tcx.require_lang_item(LangItem::VaList, Some(span));
         let region = fcx.next_region_var(RegionVariableOrigin::MiscVariable(span));
 
-        Some(tcx.bound_type_of(va_list_did).subst(tcx, &[region.into()]))
-    } else {
-        None
-    };
+        tcx.type_of(va_list_did).subst(tcx, &[region.into()])
+    });
 
     // Add formal parameters.
     let inputs_hir = hir.fn_decl_by_hir_id(fn_id).map(|decl| &decl.inputs);
@@ -266,7 +264,7 @@ fn check_lang_start_fn<'tcx>(
         let fn_generic = generics.param_at(0, tcx);
         let generic_ty = tcx.mk_ty_param(fn_generic.index, fn_generic.name);
         let expected_fn_sig =
-            tcx.mk_fn_sig([].iter(), &generic_ty, false, hir::Unsafety::Normal, Abi::Rust);
+            tcx.mk_fn_sig([], generic_ty, false, hir::Unsafety::Normal, Abi::Rust);
         let expected_ty = tcx.mk_fn_ptr(Binder::dummy(expected_fn_sig));
 
         // we emit the same error to suggest changing the arg no matter what's wrong with the arg
diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs
index b1268c5f792..cf296a7bf65 100644
--- a/compiler/rustc_hir_typeck/src/closure.rs
+++ b/compiler/rustc_hir_typeck/src/closure.rs
@@ -126,7 +126,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         // the `closures` table.
         let sig = bound_sig.map_bound(|sig| {
             self.tcx.mk_fn_sig(
-                iter::once(self.tcx.intern_tup(sig.inputs())),
+                [self.tcx.intern_tup(sig.inputs())],
                 sig.output(),
                 sig.c_variadic,
                 sig.unsafety,
@@ -326,7 +326,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         debug!(?ret_param_ty);
 
         let sig = projection.rebind(self.tcx.mk_fn_sig(
-            input_tys.iter(),
+            input_tys,
             ret_param_ty,
             false,
             hir::Unsafety::Normal,
diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs
index 7173239ba61..ba503bf47e7 100644
--- a/compiler/rustc_hir_typeck/src/coercion.rs
+++ b/compiler/rustc_hir_typeck/src/coercion.rs
@@ -1046,7 +1046,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     self.param_env,
                 )
                 .may_apply()
-                .then(|| deref_ty)
+                .then_some(deref_ty)
         })
     }
 
diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs
index 76e87a9e566..879a64fc0fb 100644
--- a/compiler/rustc_hir_typeck/src/demand.rs
+++ b/compiler/rustc_hir_typeck/src/demand.rs
@@ -1269,10 +1269,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 // ```
                 let ref_ty = match mutability {
                     hir::Mutability::Mut => {
-                        self.tcx.mk_mut_ref(self.tcx.mk_region(ty::ReStatic), checked_ty)
+                        self.tcx.mk_mut_ref(self.tcx.lifetimes.re_static, checked_ty)
                     }
                     hir::Mutability::Not => {
-                        self.tcx.mk_imm_ref(self.tcx.mk_region(ty::ReStatic), checked_ty)
+                        self.tcx.mk_imm_ref(self.tcx.lifetimes.re_static, checked_ty)
                     }
                 };
                 if self.can_coerce(ref_ty, expected) {
@@ -2037,7 +2037,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                                    args: &[hir::Expr<'_>],
                                    kind: CallableKind| {
             let arg_idx = args.iter().position(|a| a.hir_id == expr.hir_id).unwrap();
-            let fn_ty = self.tcx.bound_type_of(def_id).0;
+            let fn_ty = self.tcx.type_of(def_id).skip_binder();
             if !fn_ty.is_fn() {
                 return;
             }
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
index 52c2dabee29..5b641be062b 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
@@ -663,6 +663,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
                 ty::PredicateKind::Clause(ty::Clause::Trait(..))
                 | ty::PredicateKind::Clause(ty::Clause::Projection(..))
+                | ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..))
                 | ty::PredicateKind::Subtype(..)
                 | ty::PredicateKind::Coerce(..)
                 | ty::PredicateKind::Clause(ty::Clause::RegionOutlives(..))
@@ -776,9 +777,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let def_kind = self.tcx.def_kind(def_id);
 
         let item_ty = if let DefKind::Variant = def_kind {
-            self.tcx.bound_type_of(self.tcx.parent(def_id))
+            self.tcx.type_of(self.tcx.parent(def_id))
         } else {
-            self.tcx.bound_type_of(def_id)
+            self.tcx.type_of(def_id)
         };
         let substs = self.fresh_substs_for_item(span, def_id);
         let ty = item_ty.subst(self.tcx, substs);
@@ -1130,7 +1131,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             .unwrap_or(false);
 
         let (res, self_ctor_substs) = if let Res::SelfCtor(impl_def_id) = res {
-            let ty = self.handle_raw_ty(span, tcx.at(span).type_of(impl_def_id));
+            let ty = self.handle_raw_ty(span, tcx.at(span).type_of(impl_def_id).subst_identity());
             match ty.normalized.ty_adt_def() {
                 Some(adt_def) if adt_def.has_ctor() => {
                     let (ctor_kind, ctor_def_id) = adt_def.non_enum_variant().ctor.unwrap();
@@ -1226,7 +1227,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     }
                     (GenericParamDefKind::Const { .. }, GenericArg::Infer(inf)) => {
                         let tcx = self.fcx.tcx();
-                        self.fcx.ct_infer(tcx.type_of(param.def_id), Some(param), inf.span).into()
+                        self.fcx
+                            .ct_infer(
+                                tcx.type_of(param.def_id)
+                                    .no_bound_vars()
+                                    .expect("const parameter types cannot be generic"),
+                                Some(param),
+                                inf.span,
+                            )
+                            .into()
                     }
                     _ => unreachable!(),
                 }
@@ -1248,7 +1257,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             // If we have a default, then we it doesn't matter that we're not
                             // inferring the type arguments: we provide the default where any
                             // is missing.
-                            tcx.bound_type_of(param.def_id).subst(tcx, substs.unwrap()).into()
+                            tcx.type_of(param.def_id).subst(tcx, substs.unwrap()).into()
                         } else {
                             // If no type arguments were provided, we have to infer them.
                             // This case also occurs as a result of some malformed input, e.g.
@@ -1296,7 +1305,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         // Substitute the values for the type parameters into the type of
         // the referenced item.
-        let ty = tcx.bound_type_of(def_id);
+        let ty = tcx.type_of(def_id);
         assert!(!substs.has_escaping_bound_vars());
         assert!(!ty.0.has_escaping_bound_vars());
         let ty_substituted = self.normalize(span, ty.subst(tcx, substs));
@@ -1307,7 +1316,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             // type parameters, which we can infer by unifying the provided `Self`
             // with the substituted impl type.
             // This also occurs for an enum variant on a type alias.
-            let impl_ty = self.normalize(span, tcx.bound_type_of(impl_def_id).subst(tcx, substs));
+            let impl_ty = self.normalize(span, tcx.type_of(impl_def_id).subst(tcx, substs));
             let self_ty = self.normalize(span, self_ty);
             match self.at(&self.misc(span), self.param_env).eq(impl_ty, self_ty) {
                 Ok(ok) => self.register_infer_ok_obligations(ok),
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs
index f434fb92289..06d6a375697 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs
@@ -312,7 +312,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 // same rules that check_expr_struct uses for macro hygiene.
                 if self.tcx.adjust_ident(expr_field.ident, variant_def_id) == field.ident(self.tcx)
                 {
-                    return Some((expr_field.expr, self.tcx.type_of(field.did)));
+                    return Some((expr_field.expr, self.tcx.type_of(field.did).subst_identity()));
                 }
             }
         }
@@ -339,7 +339,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         receiver: Option<&'tcx hir::Expr<'tcx>>,
         args: &'tcx [hir::Expr<'tcx>],
     ) -> bool {
-        let ty = self.tcx.type_of(def_id);
+        let ty = self.tcx.type_of(def_id).subst_identity();
         if !ty.is_fn() {
             return false;
         }
@@ -477,19 +477,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         // This is the "trait" (meaning, the predicate "proved" by this `impl`) which provides the `Self` type we care about.
         // For the purposes of this function, we hope that it is a `struct` type, and that our current `expr` is a literal of
         // that struct type.
-        let impl_trait_self_ref: Option<ty::TraitRef<'tcx>> =
-            self.tcx.impl_trait_ref(obligation.impl_def_id).map(|impl_def| impl_def.skip_binder());
-
-        let Some(impl_trait_self_ref) = impl_trait_self_ref else {
-            // It is possible that this is absent. In this case, we make no progress.
-            return Err(expr);
+        let impl_trait_self_ref = if self.tcx.is_trait_alias(obligation.impl_or_alias_def_id) {
+            self.tcx.mk_trait_ref(
+                obligation.impl_or_alias_def_id,
+                ty::InternalSubsts::identity_for_item(self.tcx, obligation.impl_or_alias_def_id),
+            )
+        } else {
+            self.tcx
+                .impl_trait_ref(obligation.impl_or_alias_def_id)
+                .map(|impl_def| impl_def.skip_binder())
+                // It is possible that this is absent. In this case, we make no progress.
+                .ok_or(expr)?
         };
 
         // We only really care about the `Self` type itself, which we extract from the ref.
         let impl_self_ty: Ty<'tcx> = impl_trait_self_ref.self_ty();
 
         let impl_predicates: ty::GenericPredicates<'tcx> =
-            self.tcx.predicates_of(obligation.impl_def_id);
+            self.tcx.predicates_of(obligation.impl_or_alias_def_id);
         let Some(impl_predicate_index) = obligation.impl_def_predicate_index else {
             // We don't have the index, so we can only guess.
             return Err(expr);
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
index 9c7a84ce198..69a7235802b 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
@@ -755,15 +755,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         }
 
         errors.drain_filter(|error| {
-                let Error::Invalid(provided_idx, expected_idx, Compatibility::Incompatible(Some(e))) = error else { return false };
-                let (provided_ty, provided_span) = provided_arg_tys[*provided_idx];
-                let trace = mk_trace(provided_span, formal_and_expected_inputs[*expected_idx], provided_ty);
-                if !matches!(trace.cause.as_failure_code(*e), FailureCode::Error0308(_)) {
-                    self.err_ctxt().report_and_explain_type_error(trace, *e).emit();
-                    return true;
-                }
-                false
-            });
+            let Error::Invalid(
+                provided_idx,
+                expected_idx,
+                Compatibility::Incompatible(Some(e)),
+            ) = error else { return false };
+            let (provided_ty, provided_span) = provided_arg_tys[*provided_idx];
+            let trace =
+                mk_trace(provided_span, formal_and_expected_inputs[*expected_idx], provided_ty);
+            if !matches!(trace.cause.as_failure_code(*e), FailureCode::Error0308(_)) {
+                self.err_ctxt().report_and_explain_type_error(trace, *e).emit();
+                return true;
+            }
+            false
+        });
 
         // We're done if we found errors, but we already emitted them.
         if errors.is_empty() {
@@ -864,7 +869,27 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         }
         let mut suggestion_text = SuggestionText::None;
 
+        let ty_to_snippet = |ty: Ty<'tcx>, expected_idx: ExpectedIdx| {
+            if ty.is_unit() {
+                "()".to_string()
+            } else if ty.is_suggestable(tcx, false) {
+                format!("/* {} */", ty)
+            } else if let Some(fn_def_id) = fn_def_id
+                && self.tcx.def_kind(fn_def_id).is_fn_like()
+                && let self_implicit =
+                    matches!(call_expr.kind, hir::ExprKind::MethodCall(..)) as usize
+                && let Some(arg) = self.tcx.fn_arg_names(fn_def_id)
+                    .get(expected_idx.as_usize() + self_implicit)
+                && arg.name != kw::SelfLower
+            {
+                format!("/* {} */", arg.name)
+            } else {
+                "/* value */".to_string()
+            }
+        };
+
         let mut errors = errors.into_iter().peekable();
+        let mut suggestions = vec![];
         while let Some(error) = errors.next() {
             match error {
                 Error::Invalid(provided_idx, expected_idx, compatibility) => {
@@ -905,7 +930,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         "".to_string()
                     };
                     labels
-                        .push((provided_span, format!("argument{} unexpected", provided_ty_name)));
+                        .push((provided_span, format!("unexpected argument{}", provided_ty_name)));
+                    let mut span = provided_span;
+                    if arg_idx.index() > 0
+                        && let Some((_, prev)) = provided_arg_tys
+                            .get(ProvidedIdx::from_usize(arg_idx.index() - 1)
+                    ) {
+                        // Include previous comma
+                        span = span.with_lo(prev.hi());
+                    } else if let Some((_, next)) = provided_arg_tys.get(
+                        ProvidedIdx::from_usize(arg_idx.index() + 1),
+                    ) {
+                        // Include next comma
+                        span = span.until(*next);
+                    }
+                    suggestions.push((span, String::new()));
+
                     suggestion_text = match suggestion_text {
                         SuggestionText::None => SuggestionText::Remove(false),
                         SuggestionText::Remove(_) => SuggestionText::Remove(true),
@@ -1095,6 +1135,45 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             }
         }
 
+        // Incorporate the argument changes in the removal suggestion.
+        // When a type is *missing*, and the rest are additional, we want to suggest these with a
+        // multipart suggestion, but in order to do so we need to figure out *where* the arg that
+        // was provided but had the wrong type should go, because when looking at `expected_idx`
+        // that is the position in the argument list in the definition, while `provided_idx` will
+        // not be present. So we have to look at what the *last* provided position was, and point
+        // one after to suggest the replacement. FIXME(estebank): This is hacky, and there's
+        // probably a better more involved change we can make to make this work.
+        // For example, if we have
+        // ```
+        // fn foo(i32, &'static str) {}
+        // foo((), (), ());
+        // ```
+        // what should be suggested is
+        // ```
+        // foo(/* i32 */, /* &str */);
+        // ```
+        // which includes the replacement of the first two `()` for the correct type, and the
+        // removal of the last `()`.
+        let mut prev = -1;
+        for (expected_idx, provided_idx) in matched_inputs.iter_enumerated() {
+            // We want to point not at the *current* argument expression index, but rather at the
+            // index position where it *should have been*, which is *after* the previous one.
+            if let Some(provided_idx) = provided_idx {
+                prev = provided_idx.index() as i64;
+            }
+            let idx = ProvidedIdx::from_usize((prev + 1) as usize);
+            if let None = provided_idx
+                && let Some((_, arg_span)) = provided_arg_tys.get(idx)
+            {
+                // There is a type that was *not* found anywhere, so it isn't a move, but a
+                // replacement and we look at what type it should have been. This will allow us
+                // To suggest a multipart suggestion when encountering `foo(1, "")` where the def
+                // was `fn foo(())`.
+                let (_, expected_ty) = formal_and_expected_inputs[expected_idx];
+                suggestions.push((*arg_span, ty_to_snippet(expected_ty, expected_idx)));
+            }
+        }
+
         // If we have less than 5 things to say, it would be useful to call out exactly what's wrong
         if labels.len() <= 5 {
             for (span, label) in labels {
@@ -1112,7 +1191,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 Some(format!("provide the argument{}", if plural { "s" } else { "" }))
             }
             SuggestionText::Remove(plural) => {
-                Some(format!("remove the extra argument{}", if plural { "s" } else { "" }))
+                err.multipart_suggestion(
+                    &format!("remove the extra argument{}", if plural { "s" } else { "" }),
+                    suggestions,
+                    Applicability::HasPlaceholders,
+                );
+                None
             }
             SuggestionText::Swap => Some("swap these arguments".to_string()),
             SuggestionText::Reorder => Some("reorder these arguments".to_string()),
@@ -1151,20 +1235,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 } else {
                     // Propose a placeholder of the correct type
                     let (_, expected_ty) = formal_and_expected_inputs[expected_idx];
-                    if expected_ty.is_unit() {
-                        "()".to_string()
-                    } else if expected_ty.is_suggestable(tcx, false) {
-                        format!("/* {} */", expected_ty)
-                    } else if let Some(fn_def_id) = fn_def_id
-                        && self.tcx.def_kind(fn_def_id).is_fn_like()
-                        && let self_implicit = matches!(call_expr.kind, hir::ExprKind::MethodCall(..)) as usize
-                        && let Some(arg) = self.tcx.fn_arg_names(fn_def_id).get(expected_idx.as_usize() + self_implicit)
-                        && arg.name != kw::SelfLower
-                    {
-                        format!("/* {} */", arg.name)
-                    } else {
-                        "/* value */".to_string()
-                    }
+                    ty_to_snippet(expected_ty, expected_idx)
                 };
                 suggestion += &suggestion_text;
             }
@@ -1669,7 +1740,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         match *qpath {
             QPath::Resolved(ref maybe_qself, ref path) => {
                 let self_ty = maybe_qself.as_ref().map(|qself| self.to_ty(qself).raw);
-                let ty = self.astconv().res_to_ty(self_ty, path, true);
+                let ty = self.astconv().res_to_ty(self_ty, path, hir_id, true);
                 (path.res, self.handle_raw_ty(path_span, ty))
             }
             QPath::TypeRelative(ref qself, ref segment) => {
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
index 7ce721e94cb..3539202d1ca 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
@@ -1378,7 +1378,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             // Same item
             return false;
         }
-        let item_ty = self.tcx.type_of(item.def_id);
+        let item_ty = self.tcx.type_of(item.def_id).subst_identity();
         // FIXME(compiler-errors): This check is *so* rudimentary
         if item_ty.needs_subst() {
             return false;
diff --git a/compiler/rustc_hir_typeck/src/generator_interior/mod.rs b/compiler/rustc_hir_typeck/src/generator_interior/mod.rs
index 29ed9a24ecf..14e3ba83b10 100644
--- a/compiler/rustc_hir_typeck/src/generator_interior/mod.rs
+++ b/compiler/rustc_hir_typeck/src/generator_interior/mod.rs
@@ -271,15 +271,13 @@ pub fn resolve_interior<'a, 'tcx>(
                     },
                     _ => mk_bound_region(None),
                 };
-                let r = fcx.tcx.mk_region(ty::ReLateBound(current_depth, br));
+                let r = fcx.tcx.mk_re_late_bound(current_depth, br);
                 r
             });
-            if captured_tys.insert(ty) {
+            captured_tys.insert(ty).then(|| {
                 cause.ty = ty;
-                Some(cause)
-            } else {
-                None
-            }
+                cause
+            })
         })
         .collect();
 
@@ -302,7 +300,7 @@ pub fn resolve_interior<'a, 'tcx>(
                     let var = ty::BoundVar::from_usize(bound_vars.len());
                     bound_vars.push(ty::BoundVariableKind::Region(kind));
                     counter += 1;
-                    fcx.tcx.mk_region(ty::ReLateBound(ty::INNERMOST, ty::BoundRegion { var, kind }))
+                    fcx.tcx.mk_re_late_bound(ty::INNERMOST, ty::BoundRegion { var, kind })
                 },
                 types: &mut |b| bug!("unexpected bound ty in binder: {b:?}"),
                 consts: &mut |b, ty| bug!("unexpected bound ct in binder: {b:?} {ty}"),
@@ -314,7 +312,7 @@ pub fn resolve_interior<'a, 'tcx>(
 
     // Extract type components to build the witness type.
     let type_list = fcx.tcx.mk_type_list(type_causes.iter().map(|cause| cause.ty));
-    let bound_vars = fcx.tcx.mk_bound_variable_kinds(bound_vars.iter());
+    let bound_vars = fcx.tcx.intern_bound_variable_kinds(&bound_vars);
     let witness =
         fcx.tcx.mk_generator_witness(ty::Binder::bind_with_vars(type_list, bound_vars.clone()));
 
@@ -364,7 +362,7 @@ impl<'a, 'tcx> Visitor<'tcx> for InteriorVisitor<'a, 'tcx> {
                             let ty = tcx.mk_ref(
                                 // Use `ReErased` as `resolve_interior` is going to replace all the
                                 // regions anyway.
-                                tcx.mk_region(ty::ReErased),
+                                tcx.lifetimes.re_erased,
                                 ty::TypeAndMut { ty, mutbl: hir::Mutability::Not },
                             );
                             self.interior_visitor.record(
diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs
index 323bacf70ab..0204beb6fb8 100644
--- a/compiler/rustc_hir_typeck/src/lib.rs
+++ b/compiler/rustc_hir_typeck/src/lib.rs
@@ -154,7 +154,7 @@ fn typeck_const_arg<'tcx>(
     tcx: TyCtxt<'tcx>,
     (did, param_did): (LocalDefId, DefId),
 ) -> &ty::TypeckResults<'tcx> {
-    let fallback = move || tcx.type_of(param_did);
+    let fallback = move || tcx.type_of(param_did).subst_identity();
     typeck_with_fallback(tcx, did, fallback)
 }
 
@@ -162,7 +162,7 @@ fn typeck<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &ty::TypeckResults<'tc
     if let Some(param_did) = tcx.opt_const_param_of(def_id) {
         tcx.typeck_const_arg((def_id, param_did))
     } else {
-        let fallback = move || tcx.type_of(def_id.to_def_id());
+        let fallback = move || tcx.type_of(def_id.to_def_id()).subst_identity();
         typeck_with_fallback(tcx, def_id, fallback)
     }
 }
diff --git a/compiler/rustc_hir_typeck/src/method/confirm.rs b/compiler/rustc_hir_typeck/src/method/confirm.rs
index fa0dc4d8415..f7de55c989f 100644
--- a/compiler/rustc_hir_typeck/src/method/confirm.rs
+++ b/compiler/rustc_hir_typeck/src/method/confirm.rs
@@ -384,7 +384,15 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
                     }
                     (GenericParamDefKind::Const { .. }, GenericArg::Infer(inf)) => {
                         let tcx = self.cfcx.tcx();
-                        self.cfcx.ct_infer(tcx.type_of(param.def_id), Some(param), inf.span).into()
+                        self.cfcx
+                            .ct_infer(
+                                tcx.type_of(param.def_id)
+                                    .no_bound_vars()
+                                    .expect("const parameter types cannot be generic"),
+                                Some(param),
+                                inf.span,
+                            )
+                            .into()
                     }
                     _ => unreachable!(),
                 }
diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs
index a35fa008a95..0b9226802cf 100644
--- a/compiler/rustc_hir_typeck/src/method/probe.rs
+++ b/compiler/rustc_hir_typeck/src/method/probe.rs
@@ -735,7 +735,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
             debug!("impl_ty: {:?}", impl_ty);
 
             // Determine the receiver type that the method itself expects.
-            let (xform_self_ty, xform_ret_ty) = self.xform_self_ty(&item, impl_ty, impl_substs);
+            let (xform_self_ty, xform_ret_ty) = self.xform_self_ty(item, impl_ty, impl_substs);
             debug!("xform_self_ty: {:?}, xform_ret_ty: {:?}", xform_self_ty, xform_ret_ty);
 
             // We can't use normalize_associated_types_in as it will pollute the
@@ -796,7 +796,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
             let new_trait_ref = this.erase_late_bound_regions(new_trait_ref);
 
             let (xform_self_ty, xform_ret_ty) =
-                this.xform_self_ty(&item, new_trait_ref.self_ty(), new_trait_ref.substs);
+                this.xform_self_ty(item, new_trait_ref.self_ty(), new_trait_ref.substs);
             this.push_candidate(
                 Candidate {
                     xform_self_ty,
@@ -826,6 +826,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
                     }
                 }
                 ty::PredicateKind::Subtype(..)
+                | ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..))
                 | ty::PredicateKind::Coerce(..)
                 | ty::PredicateKind::Clause(ty::Clause::Projection(..))
                 | ty::PredicateKind::Clause(ty::Clause::RegionOutlives(..))
@@ -845,7 +846,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
             let trait_ref = this.erase_late_bound_regions(poly_trait_ref);
 
             let (xform_self_ty, xform_ret_ty) =
-                this.xform_self_ty(&item, trait_ref.self_ty(), trait_ref.substs);
+                this.xform_self_ty(item, trait_ref.self_ty(), trait_ref.substs);
 
             // Because this trait derives from a where-clause, it
             // should not contain any inference variables or other
@@ -916,7 +917,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
 
     fn matches_return_type(
         &self,
-        method: &ty::AssocItem,
+        method: ty::AssocItem,
         self_ty: Option<Ty<'tcx>>,
         expected: Ty<'tcx>,
     ) -> bool {
@@ -965,11 +966,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
                     } else {
                         let new_trait_ref = self.erase_late_bound_regions(bound_trait_ref);
 
-                        let (xform_self_ty, xform_ret_ty) = self.xform_self_ty(
-                            &item,
-                            new_trait_ref.self_ty(),
-                            new_trait_ref.substs,
-                        );
+                        let (xform_self_ty, xform_ret_ty) =
+                            self.xform_self_ty(item, new_trait_ref.self_ty(), new_trait_ref.substs);
                         self.push_candidate(
                             Candidate {
                                 xform_self_ty,
@@ -997,7 +995,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
                 }
 
                 let (xform_self_ty, xform_ret_ty) =
-                    self.xform_self_ty(&item, trait_ref.self_ty(), trait_substs);
+                    self.xform_self_ty(item, trait_ref.self_ty(), trait_substs);
                 self.push_candidate(
                     Candidate {
                         xform_self_ty,
@@ -1024,7 +1022,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
             .filter(|candidate| candidate_filter(&candidate.item))
             .filter(|candidate| {
                 if let Some(return_ty) = self.return_type {
-                    self.matches_return_type(&candidate.item, None, return_ty)
+                    self.matches_return_type(candidate.item, None, return_ty)
                 } else {
                     true
                 }
@@ -1576,7 +1574,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
                                 traits::ImplDerivedObligation(Box::new(
                                     traits::ImplDerivedObligationCause {
                                         derived,
-                                        impl_def_id,
+                                        impl_or_alias_def_id: impl_def_id,
                                         impl_def_predicate_index: None,
                                         span,
                                     },
@@ -1883,7 +1881,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
     #[instrument(level = "debug", skip(self))]
     fn xform_self_ty(
         &self,
-        item: &ty::AssocItem,
+        item: ty::AssocItem,
         impl_ty: Ty<'tcx>,
         substs: SubstsRef<'tcx>,
     ) -> (Ty<'tcx>, Option<Ty<'tcx>>) {
@@ -1940,7 +1938,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
         &self,
         impl_def_id: DefId,
     ) -> (ty::EarlyBinder<Ty<'tcx>>, SubstsRef<'tcx>) {
-        (self.tcx.bound_type_of(impl_def_id), self.fresh_item_substs(impl_def_id))
+        (self.tcx.type_of(impl_def_id), self.fresh_item_substs(impl_def_id))
     }
 
     fn fresh_item_substs(&self, def_id: DefId) -> SubstsRef<'tcx> {
@@ -1958,7 +1956,14 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
                     kind: ConstVariableOriginKind::SubstitutionPlaceholder,
                     span,
                 };
-                self.next_const_var(self.tcx.type_of(param.def_id), origin).into()
+                self.next_const_var(
+                    self.tcx
+                        .type_of(param.def_id)
+                        .no_bound_vars()
+                        .expect("const parameter types cannot be generic"),
+                    origin,
+                )
+                .into()
             }
         })
     }
diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs
index 54890489f8b..6a7b1f6646a 100644
--- a/compiler/rustc_hir_typeck/src/method/suggest.rs
+++ b/compiler/rustc_hir_typeck/src/method/suggest.rs
@@ -616,7 +616,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     ObligationCauseCode::ImplDerivedObligation(data)
                         if matches!(p.kind().skip_binder(), ty::PredicateKind::Clause(_)) =>
                     {
-                        Some((p, parent, data.impl_def_id, data))
+                        Some((p, parent, data.impl_or_alias_def_id, data))
                     }
                     _ => None,
                 })
@@ -714,7 +714,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         );
                     }
                     Some(Node::Item(hir::Item {
-                        ident, kind: hir::ItemKind::Trait(..), ..
+                        ident,
+                        kind: hir::ItemKind::Trait(..) | hir::ItemKind::TraitAlias(..),
+                        ..
                     })) => {
                         skip_list.insert(p);
                         let entry = spanned_predicates.entry(ident.span);
@@ -906,8 +908,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                                         // different from the received one
                                         // So we avoid suggestion method with Box<Self>
                                         // for instance
-                                        self.tcx.at(span).type_of(*def_id) != rcvr_ty
-                                            && self.tcx.at(span).type_of(*def_id) != rcvr_ty
+                                        self.tcx.at(span).type_of(*def_id).subst_identity()
+                                            != rcvr_ty
+                                            && self.tcx.at(span).type_of(*def_id).subst_identity()
+                                                != rcvr_ty
                                     }
                                     (Mode::Path, false, _) => true,
                                     _ => false,
@@ -927,7 +931,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             .iter()
                             .take(limit)
                             .map(|impl_item| {
-                                format!("- `{}`", self.tcx.at(span).type_of(*impl_item))
+                                format!(
+                                    "- `{}`",
+                                    self.tcx.at(span).type_of(*impl_item).subst_identity()
+                                )
                             })
                             .collect::<Vec<_>>()
                             .join("\n");
@@ -1104,7 +1111,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         None
                     };
 
-                    let impl_ty = self.tcx.at(span).type_of(impl_did);
+                    let impl_ty = self.tcx.at(span).type_of(impl_did).subst_identity();
 
                     let insertion = match self.tcx.impl_trait_ref(impl_did) {
                         None => String::new(),
@@ -1233,7 +1240,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             // When the "method" is resolved through dereferencing, we really want the
             // original type that has the associated function for accurate suggestions.
             // (#61411)
-            let impl_ty = self.tcx.type_of(*impl_did);
+            let impl_ty = self.tcx.type_of(*impl_did).subst_identity();
             let target_ty = self
                 .autoderef(sugg_span, rcvr_ty)
                 .find(|(rcvr_ty, _)| {
@@ -1453,8 +1460,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     }
 
                     let range_def_id = self.tcx.require_lang_item(lang_item.unwrap(), None);
-                    let range_ty =
-                        self.tcx.bound_type_of(range_def_id).subst(self.tcx, &[actual.into()]);
+                    let range_ty = self.tcx.type_of(range_def_id).subst(self.tcx, &[actual.into()]);
 
                     let pick = self.lookup_probe_for_diagnostic(
                         item_name,
diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs
index e12a575d5ac..7c8abb4186f 100644
--- a/compiler/rustc_hir_typeck/src/upvar.rs
+++ b/compiler/rustc_hir_typeck/src/upvar.rs
@@ -301,7 +301,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         // Build a tuple (U0..Un) of the final upvar types U0..Un
         // and unify the upvar tuple type in the closure with it:
-        let final_tupled_upvars_type = self.tcx.mk_tup(final_upvar_tys.iter());
+        let final_tupled_upvars_type = self.tcx.intern_tup(&final_upvar_tys);
         self.demand_suptype(span, substs.tupled_upvars_ty(), final_tupled_upvars_type);
 
         let fake_reads = delegate
@@ -315,8 +315,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             self.typeck_results.borrow_mut().closure_size_eval.insert(
                 closure_def_id,
                 ClosureSizeProfileData {
-                    before_feature_tys: self.tcx.mk_tup(before_feature_tys.into_iter()),
-                    after_feature_tys: self.tcx.mk_tup(after_feature_tys.into_iter()),
+                    before_feature_tys: self.tcx.intern_tup(&before_feature_tys),
+                    after_feature_tys: self.tcx.intern_tup(&after_feature_tys),
                 },
             );
         }
diff --git a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
index 6bfdeda3a24..2b33d31994f 100644
--- a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
+++ b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
@@ -363,7 +363,7 @@ impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'cx, 'tcx> {
                      opportunistically resolved to {:?}",
                     vid, resolved_vid
                 );
-                let r = self.tcx.reuse_or_mk_region(r, ty::ReVar(resolved_vid));
+                let r = self.tcx.mk_re_var(resolved_vid);
                 self.canonicalize_mode.canonicalize_free_region(self, r)
             }
 
@@ -737,8 +737,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
     ) -> ty::Region<'tcx> {
         let var = self.canonical_var(info, r.into());
         let br = ty::BoundRegion { var, kind: ty::BrAnon(var.as_u32(), None) };
-        let region = ty::ReLateBound(self.binder_index, br);
-        self.interner().mk_region(region)
+        self.interner().mk_re_late_bound(self.binder_index, br)
     }
 
     /// Given a type variable `ty_var` of the given kind, first check
diff --git a/compiler/rustc_infer/src/infer/canonical/mod.rs b/compiler/rustc_infer/src/infer/canonical/mod.rs
index d5cb3fb2498..4552256545b 100644
--- a/compiler/rustc_infer/src/infer/canonical/mod.rs
+++ b/compiler/rustc_infer/src/infer/canonical/mod.rs
@@ -137,7 +137,7 @@ impl<'tcx> InferCtxt<'tcx> {
             CanonicalVarKind::PlaceholderRegion(ty::PlaceholderRegion { universe, name }) => {
                 let universe_mapped = universe_map(universe);
                 let placeholder_mapped = ty::PlaceholderRegion { universe: universe_mapped, name };
-                self.tcx.mk_region(ty::RePlaceholder(placeholder_mapped)).into()
+                self.tcx.mk_re_placeholder(placeholder_mapped).into()
             }
 
             CanonicalVarKind::Const(ui, ty) => self
diff --git a/compiler/rustc_infer/src/infer/canonical/query_response.rs b/compiler/rustc_infer/src/infer/canonical/query_response.rs
index 0c97217bd6a..b9cb9732ca3 100644
--- a/compiler/rustc_infer/src/infer/canonical/query_response.rs
+++ b/compiler/rustc_infer/src/infer/canonical/query_response.rs
@@ -642,15 +642,14 @@ pub fn make_query_region_constraints<'tcx>(
             let constraint = match *k {
                 // Swap regions because we are going from sub (<=) to outlives
                 // (>=).
-                Constraint::VarSubVar(v1, v2) => ty::OutlivesPredicate(
-                    tcx.mk_region(ty::ReVar(v2)).into(),
-                    tcx.mk_region(ty::ReVar(v1)),
-                ),
+                Constraint::VarSubVar(v1, v2) => {
+                    ty::OutlivesPredicate(tcx.mk_re_var(v2).into(), tcx.mk_re_var(v1))
+                }
                 Constraint::VarSubReg(v1, r2) => {
-                    ty::OutlivesPredicate(r2.into(), tcx.mk_region(ty::ReVar(v1)))
+                    ty::OutlivesPredicate(r2.into(), tcx.mk_re_var(v1))
                 }
                 Constraint::RegSubVar(r1, v2) => {
-                    ty::OutlivesPredicate(tcx.mk_region(ty::ReVar(v2)).into(), r1)
+                    ty::OutlivesPredicate(tcx.mk_re_var(v2).into(), r1)
                 }
                 Constraint::RegSubReg(r1, r2) => ty::OutlivesPredicate(r2.into(), r1),
             };
@@ -690,7 +689,7 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for QueryTypeRelatingDelegate<'_, 'tcx> {
     }
 
     fn next_placeholder_region(&mut self, placeholder: ty::PlaceholderRegion) -> ty::Region<'tcx> {
-        self.infcx.tcx.mk_region(ty::RePlaceholder(placeholder))
+        self.infcx.tcx.mk_re_placeholder(placeholder)
     }
 
     fn generalize_existential(&mut self, universe: ty::UniverseIndex) -> ty::Region<'tcx> {
diff --git a/compiler/rustc_infer/src/infer/combine.rs b/compiler/rustc_infer/src/infer/combine.rs
index 964222307bc..f5504b05dc4 100644
--- a/compiler/rustc_infer/src/infer/combine.rs
+++ b/compiler/rustc_infer/src/infer/combine.rs
@@ -125,11 +125,11 @@ impl<'tcx> InferCtxt<'tcx> {
             }
 
             (ty::Alias(AliasKind::Projection, _), _) if self.tcx.trait_solver_next() => {
-                relation.register_type_equate_obligation(a.into(), b.into());
+                relation.register_type_equate_obligation(a, b);
                 Ok(b)
             }
             (_, ty::Alias(AliasKind::Projection, _)) if self.tcx.trait_solver_next() => {
-                relation.register_type_equate_obligation(b.into(), a.into());
+                relation.register_type_equate_obligation(b, a);
                 Ok(a)
             }
 
diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
index 2b5a19914a3..cf2f6ef33be 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
@@ -1062,7 +1062,7 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> {
 
                 let parent_def_id = generics.parent.unwrap();
                 if let DefKind::Impl { .. } = tcx.def_kind(parent_def_id) {
-                    let parent_ty = tcx.bound_type_of(parent_def_id).subst(tcx, substs);
+                    let parent_ty = tcx.type_of(parent_def_id).subst(tcx, substs);
                     match (parent_ty.kind(), &ty.kind) {
                         (
                             ty::Adt(def, substs),
diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs
index 39f4d502259..fec04af2313 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs
@@ -2,7 +2,7 @@ use rustc_hir as hir;
 use rustc_hir::intravisit::{self, Visitor};
 use rustc_middle::hir::map::Map;
 use rustc_middle::hir::nested_filter;
-use rustc_middle::middle::resolve_lifetime as rl;
+use rustc_middle::middle::resolve_bound_vars as rbv;
 use rustc_middle::ty::{self, Region, TyCtxt};
 
 /// This function calls the `visit_ty` method for the parameters
@@ -99,11 +99,11 @@ impl<'tcx> Visitor<'tcx> for FindNestedTypeVisitor<'tcx> {
             hir::TyKind::Ref(ref lifetime, _) => {
                 // the lifetime of the Ref
                 let hir_id = lifetime.hir_id;
-                match (self.tcx.named_region(hir_id), self.bound_region) {
+                match (self.tcx.named_bound_var(hir_id), self.bound_region) {
                     // Find the index of the named region that was part of the
                     // error. We will then search the function parameters for a bound
                     // region at the right depth with the same index
-                    (Some(rl::Region::EarlyBound(id)), ty::BrNamed(def_id, _)) => {
+                    (Some(rbv::ResolvedArg::EarlyBound(id)), ty::BrNamed(def_id, _)) => {
                         debug!("EarlyBound id={:?} def_id={:?}", id, def_id);
                         if id == def_id {
                             self.found_type = Some(arg);
@@ -115,7 +115,7 @@ impl<'tcx> Visitor<'tcx> for FindNestedTypeVisitor<'tcx> {
                     // error. We will then search the function parameters for a bound
                     // region at the right depth with the same index
                     (
-                        Some(rl::Region::LateBound(debruijn_index, _, id)),
+                        Some(rbv::ResolvedArg::LateBound(debruijn_index, _, id)),
                         ty::BrNamed(def_id, _),
                     ) => {
                         debug!(
@@ -131,10 +131,11 @@ impl<'tcx> Visitor<'tcx> for FindNestedTypeVisitor<'tcx> {
 
                     (
                         Some(
-                            rl::Region::Static
-                            | rl::Region::Free(_, _)
-                            | rl::Region::EarlyBound(_)
-                            | rl::Region::LateBound(_, _, _),
+                            rbv::ResolvedArg::StaticLifetime
+                            | rbv::ResolvedArg::Free(_, _)
+                            | rbv::ResolvedArg::EarlyBound(_)
+                            | rbv::ResolvedArg::LateBound(_, _, _)
+                            | rbv::ResolvedArg::Error(_),
                         )
                         | None,
                         _,
@@ -186,9 +187,9 @@ impl<'tcx> Visitor<'tcx> for TyPathVisitor<'tcx> {
     }
 
     fn visit_lifetime(&mut self, lifetime: &hir::Lifetime) {
-        match (self.tcx.named_region(lifetime.hir_id), self.bound_region) {
+        match (self.tcx.named_bound_var(lifetime.hir_id), self.bound_region) {
             // the lifetime of the TyPath!
-            (Some(rl::Region::EarlyBound(id)), ty::BrNamed(def_id, _)) => {
+            (Some(rbv::ResolvedArg::EarlyBound(id)), ty::BrNamed(def_id, _)) => {
                 debug!("EarlyBound id={:?} def_id={:?}", id, def_id);
                 if id == def_id {
                     self.found_it = true;
@@ -196,7 +197,7 @@ impl<'tcx> Visitor<'tcx> for TyPathVisitor<'tcx> {
                 }
             }
 
-            (Some(rl::Region::LateBound(debruijn_index, _, id)), ty::BrNamed(def_id, _)) => {
+            (Some(rbv::ResolvedArg::LateBound(debruijn_index, _, id)), ty::BrNamed(def_id, _)) => {
                 debug!("FindNestedTypeVisitor::visit_ty: LateBound depth = {:?}", debruijn_index,);
                 debug!("id={:?}", id);
                 debug!("def_id={:?}", def_id);
@@ -208,10 +209,11 @@ impl<'tcx> Visitor<'tcx> for TyPathVisitor<'tcx> {
 
             (
                 Some(
-                    rl::Region::Static
-                    | rl::Region::EarlyBound(_)
-                    | rl::Region::LateBound(_, _, _)
-                    | rl::Region::Free(_, _),
+                    rbv::ResolvedArg::StaticLifetime
+                    | rbv::ResolvedArg::EarlyBound(_)
+                    | rbv::ResolvedArg::LateBound(_, _, _)
+                    | rbv::ResolvedArg::Free(_, _)
+                    | rbv::ResolvedArg::Error(_),
                 )
                 | None,
                 _,
diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs
index 1067ccda20c..2c63a390410 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs
@@ -72,7 +72,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
             };
 
             // Next, let's figure out the set of trait objects with implicit static bounds
-            let ty = self.tcx().type_of(*impl_def_id);
+            let ty = self.tcx().type_of(*impl_def_id).subst_identity();
             let mut v = super::static_impl_trait::TraitObjectVisitor(FxIndexSet::default());
             v.visit_ty(ty);
             let mut traits = vec![];
diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs
index 99431567eda..c1ea0a0d95e 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs
@@ -14,7 +14,7 @@ use rustc_hir::def_id::DefId;
 use rustc_middle::ty::error::ExpectedFound;
 use rustc_middle::ty::print::{FmtPrinter, Print, RegionHighlightMode};
 use rustc_middle::ty::subst::SubstsRef;
-use rustc_middle::ty::{self, RePlaceholder, ReVar, Region, TyCtxt};
+use rustc_middle::ty::{self, RePlaceholder, Region, TyCtxt};
 
 use std::fmt;
 
@@ -79,7 +79,7 @@ impl<'tcx> NiceRegionError<'_, 'tcx> {
                 sup_placeholder @ Region(Interned(RePlaceholder(_), _)),
                 _,
             )) => self.try_report_trait_placeholder_mismatch(
-                Some(self.tcx().mk_region(ReVar(*vid))),
+                Some(self.tcx().mk_re_var(*vid)),
                 cause,
                 Some(*sub_placeholder),
                 Some(*sup_placeholder),
@@ -95,7 +95,7 @@ impl<'tcx> NiceRegionError<'_, 'tcx> {
                 _,
                 _,
             )) => self.try_report_trait_placeholder_mismatch(
-                Some(self.tcx().mk_region(ReVar(*vid))),
+                Some(self.tcx().mk_re_var(*vid)),
                 cause,
                 Some(*sub_placeholder),
                 None,
@@ -111,7 +111,7 @@ impl<'tcx> NiceRegionError<'_, 'tcx> {
                 sup_placeholder @ Region(Interned(RePlaceholder(_), _)),
                 _,
             )) => self.try_report_trait_placeholder_mismatch(
-                Some(self.tcx().mk_region(ReVar(*vid))),
+                Some(self.tcx().mk_re_var(*vid)),
                 cause,
                 None,
                 Some(*sup_placeholder),
@@ -127,7 +127,7 @@ impl<'tcx> NiceRegionError<'_, 'tcx> {
                 sup_placeholder @ Region(Interned(RePlaceholder(_), _)),
                 _,
             )) => self.try_report_trait_placeholder_mismatch(
-                Some(self.tcx().mk_region(ReVar(*vid))),
+                Some(self.tcx().mk_re_var(*vid)),
                 cause,
                 None,
                 Some(*sup_placeholder),
@@ -141,7 +141,7 @@ impl<'tcx> NiceRegionError<'_, 'tcx> {
                 SubregionOrigin::Subtype(box TypeTrace { cause, values }),
                 sup_placeholder @ Region(Interned(RePlaceholder(_), _)),
             )) => self.try_report_trait_placeholder_mismatch(
-                Some(self.tcx().mk_region(ReVar(*vid))),
+                Some(self.tcx().mk_re_var(*vid)),
                 cause,
                 None,
                 Some(*sup_placeholder),
diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs
index 4c0f457b46a..ac4de2cc842 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs
@@ -90,20 +90,18 @@ pub fn find_param_with_region<'tcx>(
                     r
                 }
             });
-            if found_anon_region {
+            found_anon_region.then(|| {
                 let ty_hir_id = fn_decl.inputs[index].hir_id;
                 let param_ty_span = hir.span(ty_hir_id);
                 let is_first = index == 0;
-                Some(AnonymousParamInfo {
+                AnonymousParamInfo {
                     param,
                     param_ty: new_param_ty,
                     param_ty_span,
                     bound_region,
                     is_first,
-                })
-            } else {
-                None
-            }
+                }
+            })
         })
 }
 
@@ -125,7 +123,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
         br: ty::BoundRegionKind,
         hir_sig: &hir::FnSig<'_>,
     ) -> Option<Span> {
-        let fn_ty = self.tcx().type_of(scope_def_id);
+        let fn_ty = self.tcx().type_of(scope_def_id).subst_identity();
         if let ty::FnDef(_, _) = fn_ty.kind() {
             let ret_ty = fn_ty.fn_sig(self.tcx()).output();
             let span = hir_sig.decl.output.span();
diff --git a/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs b/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs
index b6337d6853f..b33729d0be5 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs
@@ -326,7 +326,7 @@ impl<T> Trait<T> for X {
                         diag,
                         &trait_ref,
                         pred.bounds,
-                        &assoc,
+                        assoc,
                         assoc_substs,
                         ty,
                         msg,
@@ -577,7 +577,7 @@ fn foo(&self) -> Self::T { String::new() }
                             if let hir::Defaultness::Default { has_value: true } =
                                 tcx.impl_defaultness(item.id.owner_id)
                             {
-                                let assoc_ty = tcx.bound_type_of(item.id.owner_id).subst_identity();
+                                let assoc_ty = tcx.type_of(item.id.owner_id).subst_identity();
                                 if self.infcx.can_eq(param_env, assoc_ty, found) {
                                     diag.span_label(
                                         item.span,
@@ -598,7 +598,7 @@ fn foo(&self) -> Self::T { String::new() }
             })) => {
                 for item in &items[..] {
                     if let hir::AssocItemKind::Type = item.kind {
-                        let assoc_ty = tcx.bound_type_of(item.id.owner_id).subst_identity();
+                        let assoc_ty = tcx.type_of(item.id.owner_id).subst_identity();
 
                         if self.infcx.can_eq(param_env, assoc_ty, found) {
                             diag.span_label(item.span, "expected this associated type");
@@ -624,7 +624,7 @@ fn foo(&self) -> Self::T { String::new() }
         diag: &mut Diagnostic,
         trait_ref: &ty::TraitRef<'tcx>,
         bounds: hir::GenericBounds<'_>,
-        assoc: &ty::AssocItem,
+        assoc: ty::AssocItem,
         assoc_substs: &[ty::GenericArg<'tcx>],
         ty: Ty<'tcx>,
         msg: &str,
@@ -667,7 +667,7 @@ fn foo(&self) -> Self::T { String::new() }
         &self,
         diag: &mut Diagnostic,
         span: Span,
-        assoc: &ty::AssocItem,
+        assoc: ty::AssocItem,
         assoc_substs: &[ty::GenericArg<'tcx>],
         ty: Ty<'tcx>,
         msg: &str,
diff --git a/compiler/rustc_infer/src/infer/higher_ranked/mod.rs b/compiler/rustc_infer/src/infer/higher_ranked/mod.rs
index 39940f4592d..82a1bb1fd16 100644
--- a/compiler/rustc_infer/src/infer/higher_ranked/mod.rs
+++ b/compiler/rustc_infer/src/infer/higher_ranked/mod.rs
@@ -82,10 +82,10 @@ impl<'tcx> InferCtxt<'tcx> {
 
         let delegate = FnMutDelegate {
             regions: &mut |br: ty::BoundRegion| {
-                self.tcx.mk_region(ty::RePlaceholder(ty::PlaceholderRegion {
+                self.tcx.mk_re_placeholder(ty::PlaceholderRegion {
                     universe: next_universe,
                     name: br.kind,
-                }))
+                })
             },
             types: &mut |bound_ty: ty::BoundTy| {
                 self.tcx.mk_placeholder(ty::PlaceholderType {
diff --git a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs
index 4a2210bdb68..ac203c4eb0b 100644
--- a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs
+++ b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs
@@ -382,7 +382,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
                     // name the placeholder, then the placeholder is
                     // larger; otherwise, the only ancestor is `'static`.
                     Err(placeholder) if empty_ui.can_name(placeholder.universe) => {
-                        self.tcx().mk_region(RePlaceholder(placeholder))
+                        self.tcx().mk_re_placeholder(placeholder)
                     }
                     Err(_) => self.tcx().lifetimes.re_static,
                 };
@@ -1046,7 +1046,7 @@ impl<'tcx> LexicalRegionResolutions<'tcx> {
             ty::ReVar(rid) => match self.values[rid] {
                 VarValue::Empty(_) => r,
                 VarValue::Value(r) => r,
-                VarValue::ErrorValue => tcx.re_error_misc(),
+                VarValue::ErrorValue => tcx.mk_re_error_misc(),
             },
             _ => r,
         };
diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs
index 17e734f0700..aa316b2dadb 100644
--- a/compiler/rustc_infer/src/infer/mod.rs
+++ b/compiler/rustc_infer/src/infer/mod.rs
@@ -1093,7 +1093,7 @@ impl<'tcx> InferCtxt<'tcx> {
     ) -> ty::Region<'tcx> {
         let region_var =
             self.inner.borrow_mut().unwrap_region_constraints().new_region_var(universe, origin);
-        self.tcx.mk_region(ty::ReVar(region_var))
+        self.tcx.mk_re_var(region_var)
     }
 
     /// Return the universe that the region `r` was created in. For
@@ -1166,7 +1166,15 @@ impl<'tcx> InferCtxt<'tcx> {
                         origin,
                         val: ConstVariableValue::Unknown { universe: self.universe() },
                     });
-                self.tcx.mk_const(const_var_id, self.tcx.type_of(param.def_id)).into()
+                self.tcx
+                    .mk_const(
+                        const_var_id,
+                        self.tcx
+                            .type_of(param.def_id)
+                            .no_bound_vars()
+                            .expect("const parameter types cannot be generic"),
+                    )
+                    .into()
             }
         }
     }
diff --git a/compiler/rustc_infer/src/infer/outlives/mod.rs b/compiler/rustc_infer/src/infer/outlives/mod.rs
index a8e668d81ea..83f3d5a74fb 100644
--- a/compiler/rustc_infer/src/infer/outlives/mod.rs
+++ b/compiler/rustc_infer/src/infer/outlives/mod.rs
@@ -21,6 +21,7 @@ pub fn explicit_outlives_bounds<'tcx>(
         .filter_map(move |kind| match kind {
             ty::PredicateKind::Clause(ty::Clause::Projection(..))
             | ty::PredicateKind::Clause(ty::Clause::Trait(..))
+            | ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..))
             | ty::PredicateKind::AliasEq(..)
             | ty::PredicateKind::Coerce(..)
             | ty::PredicateKind::Subtype(..)
diff --git a/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs b/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs
index c46edc33ff4..e413b2bb570 100644
--- a/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs
+++ b/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs
@@ -280,7 +280,7 @@ impl<'me, 'tcx> LeakCheck<'me, 'tcx> {
         placeholder1: ty::PlaceholderRegion,
         placeholder2: ty::PlaceholderRegion,
     ) -> TypeError<'tcx> {
-        self.error(placeholder1, self.tcx.mk_region(ty::RePlaceholder(placeholder2)))
+        self.error(placeholder1, self.tcx.mk_re_placeholder(placeholder2))
     }
 
     fn error(
@@ -413,19 +413,19 @@ impl<'tcx> MiniGraph<'tcx> {
         for undo_entry in undo_log {
             match undo_entry {
                 &AddConstraint(Constraint::VarSubVar(a, b)) => {
-                    each_edge(tcx.mk_region(ReVar(a)), tcx.mk_region(ReVar(b)));
+                    each_edge(tcx.mk_re_var(a), tcx.mk_re_var(b));
                 }
                 &AddConstraint(Constraint::RegSubVar(a, b)) => {
-                    each_edge(a, tcx.mk_region(ReVar(b)));
+                    each_edge(a, tcx.mk_re_var(b));
                 }
                 &AddConstraint(Constraint::VarSubReg(a, b)) => {
-                    each_edge(tcx.mk_region(ReVar(a)), b);
+                    each_edge(tcx.mk_re_var(a), b);
                 }
                 &AddConstraint(Constraint::RegSubReg(a, b)) => {
                     each_edge(a, b);
                 }
                 &AddGiven(a, b) => {
-                    each_edge(a, tcx.mk_region(ReVar(b)));
+                    each_edge(a, tcx.mk_re_var(b));
                 }
                 &AddVerify(i) => span_bug!(
                     verifys[i].origin.span(),
diff --git a/compiler/rustc_infer/src/infer/region_constraints/mod.rs b/compiler/rustc_infer/src/infer/region_constraints/mod.rs
index cb24375c7a3..33514eedfc3 100644
--- a/compiler/rustc_infer/src/infer/region_constraints/mod.rs
+++ b/compiler/rustc_infer/src/infer/region_constraints/mod.rs
@@ -651,7 +651,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
                 let unified_region = self.unification_table().probe_value(rid);
                 unified_region.0.unwrap_or_else(|| {
                     let root = self.unification_table().find(rid).vid;
-                    tcx.reuse_or_mk_region(region, ty::ReVar(root))
+                    tcx.mk_re_var(root)
                 })
             }
             _ => region,
@@ -675,7 +675,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
     ) -> Region<'tcx> {
         let vars = TwoRegions { a, b };
         if let Some(&c) = self.combine_map(t).get(&vars) {
-            return tcx.mk_region(ReVar(c));
+            return tcx.mk_re_var(c);
         }
         let a_universe = self.universe(a);
         let b_universe = self.universe(b);
@@ -683,7 +683,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
         let c = self.new_region_var(c_universe, MiscVariable(origin.span()));
         self.combine_map(t).insert(vars, c);
         self.undo_log.push(AddCombination(t, vars));
-        let new_r = tcx.mk_region(ReVar(c));
+        let new_r = tcx.mk_re_var(c);
         for old_r in [a, b] {
             match t {
                 Glb => self.make_subregion(origin.clone(), new_r, old_r),
diff --git a/compiler/rustc_infer/src/infer/resolve.rs b/compiler/rustc_infer/src/infer/resolve.rs
index 008bf1e9c5d..2c246a5787c 100644
--- a/compiler/rustc_infer/src/infer/resolve.rs
+++ b/compiler/rustc_infer/src/infer/resolve.rs
@@ -95,7 +95,7 @@ impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for OpportunisticRegionResolver<'a, 'tcx
                     .borrow_mut()
                     .unwrap_region_constraints()
                     .opportunistic_resolve_var(rid);
-                TypeFolder::interner(self).reuse_or_mk_region(r, ty::ReVar(resolved))
+                TypeFolder::interner(self).mk_re_var(resolved)
             }
             _ => r,
         }
diff --git a/compiler/rustc_infer/src/traits/util.rs b/compiler/rustc_infer/src/traits/util.rs
index e617eb68d47..c1f0a6e9834 100644
--- a/compiler/rustc_infer/src/traits/util.rs
+++ b/compiler/rustc_infer/src/traits/util.rs
@@ -158,7 +158,7 @@ impl<'tcx> Elaborator<'tcx> {
                                 traits::ImplDerivedObligation(Box::new(
                                     traits::ImplDerivedObligationCause {
                                         derived,
-                                        impl_def_id: data.def_id(),
+                                        impl_or_alias_def_id: data.def_id(),
                                         impl_def_predicate_index: Some(index),
                                         span,
                                     },
@@ -297,6 +297,9 @@ impl<'tcx> Elaborator<'tcx> {
             ty::PredicateKind::AliasEq(..) => {
                 // No
             }
+            ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..)) => {
+                // Nothing to elaborate
+            }
         }
     }
 }
diff --git a/compiler/rustc_lexer/src/lib.rs b/compiler/rustc_lexer/src/lib.rs
index 6e815863d06..e6f04fe0aaa 100644
--- a/compiler/rustc_lexer/src/lib.rs
+++ b/compiler/rustc_lexer/src/lib.rs
@@ -95,7 +95,7 @@ pub enum TokenKind {
     Literal { kind: LiteralKind, suffix_start: u32 },
 
     /// "'a"
-    Lifetime { starts_with_number: bool },
+    Lifetime { starts_with_number: bool, contains_emoji: bool },
 
     // One-char tokens:
     /// ";"
@@ -630,7 +630,13 @@ impl Cursor<'_> {
             // If the first symbol is valid for identifier, it can be a lifetime.
             // Also check if it's a number for a better error reporting (so '0 will
             // be reported as invalid lifetime and not as unterminated char literal).
-            is_id_start(self.first()) || self.first().is_digit(10)
+            // We also have to account for potential `'🐱` emojis to avoid reporting
+            // it as an unterminated char literal.
+            is_id_start(self.first())
+                || self.first().is_digit(10)
+                // FIXME(#108019): `unic-emoji-char` seems to have data tables only up to Unicode
+                // 5.0, but Unicode is already newer than this.
+                || unic_emoji_char::is_emoji(self.first())
         };
 
         if !can_be_a_lifetime {
@@ -643,16 +649,33 @@ impl Cursor<'_> {
             return Literal { kind, suffix_start };
         }
 
-        // Either a lifetime or a character literal with
-        // length greater than 1.
+        // Either a lifetime or a character literal.
 
         let starts_with_number = self.first().is_digit(10);
+        let mut contains_emoji = false;
 
-        // Skip the literal contents.
-        // First symbol can be a number (which isn't a valid identifier start),
-        // so skip it without any checks.
-        self.bump();
-        self.eat_while(is_id_continue);
+        // FIXME(#108019): `unic-emoji-char` seems to have data tables only up to Unicode
+        // 5.0, but Unicode is already newer than this.
+        if unic_emoji_char::is_emoji(self.first()) {
+            contains_emoji = true;
+        } else {
+            // Skip the literal contents.
+            // First symbol can be a number (which isn't a valid identifier start),
+            // so skip it without any checks.
+            self.bump();
+        }
+        self.eat_while(|c| {
+            if is_id_continue(c) {
+                true
+            // FIXME(#108019): `unic-emoji-char` seems to have data tables only up to Unicode
+            // 5.0, but Unicode is already newer than this.
+            } else if unic_emoji_char::is_emoji(c) {
+                contains_emoji = true;
+                true
+            } else {
+                false
+            }
+        });
 
         // Check if after skipping literal contents we've met a closing
         // single quote (which means that user attempted to create a
@@ -662,7 +685,7 @@ impl Cursor<'_> {
             let kind = Char { terminated: true };
             Literal { kind, suffix_start: self.pos_within_token() }
         } else {
-            Lifetime { starts_with_number }
+            Lifetime { starts_with_number, contains_emoji }
         }
     }
 
diff --git a/compiler/rustc_lexer/src/tests.rs b/compiler/rustc_lexer/src/tests.rs
index e4c1787f2cc..670d64fb983 100644
--- a/compiler/rustc_lexer/src/tests.rs
+++ b/compiler/rustc_lexer/src/tests.rs
@@ -235,7 +235,7 @@ fn lifetime() {
     check_lexing(
         "'abc",
         expect![[r#"
-            Token { kind: Lifetime { starts_with_number: false }, len: 4 }
+            Token { kind: Lifetime { starts_with_number: false, contains_emoji: false }, len: 4 }
         "#]],
     );
 }
diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index f18c0aa377f..11fb1f80a11 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -183,7 +183,7 @@ impl<'tcx> LateLintPass<'tcx> for BoxPointers {
             | hir::ItemKind::Enum(..)
             | hir::ItemKind::Struct(..)
             | hir::ItemKind::Union(..) => {
-                self.check_heap_type(cx, it.span, cx.tcx.type_of(it.owner_id))
+                self.check_heap_type(cx, it.span, cx.tcx.type_of(it.owner_id).subst_identity())
             }
             _ => (),
         }
@@ -192,7 +192,11 @@ impl<'tcx> LateLintPass<'tcx> for BoxPointers {
         match it.kind {
             hir::ItemKind::Struct(ref struct_def, _) | hir::ItemKind::Union(ref struct_def, _) => {
                 for field in struct_def.fields() {
-                    self.check_heap_type(cx, field.span, cx.tcx.type_of(field.def_id));
+                    self.check_heap_type(
+                        cx,
+                        field.span,
+                        cx.tcx.type_of(field.def_id).subst_identity(),
+                    );
                 }
             }
             _ => (),
@@ -589,7 +593,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc {
             // If the method is an impl for an item with docs_hidden, don't doc.
             MethodLateContext::PlainImpl => {
                 let parent = cx.tcx.hir().get_parent_item(impl_item.hir_id());
-                let impl_ty = cx.tcx.type_of(parent);
+                let impl_ty = cx.tcx.type_of(parent).subst_identity();
                 let outerdef = match impl_ty.kind() {
                     ty::Adt(def, _) => Some(def.did()),
                     ty::Foreign(def_id) => Some(*def_id),
@@ -698,7 +702,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingCopyImplementations {
         // and recommending Copy might be a bad idea.
         for field in def.all_fields() {
             let did = field.did;
-            if cx.tcx.type_of(did).is_unsafe_ptr() {
+            if cx.tcx.type_of(did).subst_identity().is_unsafe_ptr() {
                 return;
             }
         }
@@ -798,7 +802,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDebugImplementations {
         if self.impling_types.is_none() {
             let mut impls = LocalDefIdSet::default();
             cx.tcx.for_each_impl(debug, |d| {
-                if let Some(ty_def) = cx.tcx.type_of(d).ty_adt_def() {
+                if let Some(ty_def) = cx.tcx.type_of(d).subst_identity().ty_adt_def() {
                     if let Some(def_id) = ty_def.did().as_local() {
                         impls.insert(def_id);
                     }
@@ -1591,6 +1595,8 @@ impl<'tcx> LateLintPass<'tcx> for TrivialConstraints {
                     Clause(Clause::TypeOutlives(..)) |
                     Clause(Clause::RegionOutlives(..)) => "lifetime",
 
+                    // `ConstArgHasType` is never global as `ct` is always a param
+                    Clause(Clause::ConstArgHasType(..)) |
                     // Ignore projections, as they can only be global
                     // if the trait bound is global
                     Clause(Clause::Projection(..)) |
@@ -2007,7 +2013,7 @@ impl ExplicitOutlivesRequirements {
         inferred_outlives: &[ty::Region<'tcx>],
         predicate_span: Span,
     ) -> Vec<(usize, Span)> {
-        use rustc_middle::middle::resolve_lifetime::Region;
+        use rustc_middle::middle::resolve_bound_vars::ResolvedArg;
 
         bounds
             .iter()
@@ -2017,8 +2023,8 @@ impl ExplicitOutlivesRequirements {
                     return None;
                 };
 
-                let is_inferred = match tcx.named_region(lifetime.hir_id) {
-                    Some(Region::EarlyBound(def_id)) => inferred_outlives
+                let is_inferred = match tcx.named_bound_var(lifetime.hir_id) {
+                    Some(ResolvedArg::EarlyBound(def_id)) => inferred_outlives
                         .iter()
                         .any(|r| matches!(**r, ty::ReEarlyBound(ebr) if { ebr.def_id == def_id })),
                     _ => false,
@@ -2097,7 +2103,7 @@ impl ExplicitOutlivesRequirements {
 
 impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements {
     fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) {
-        use rustc_middle::middle::resolve_lifetime::Region;
+        use rustc_middle::middle::resolve_bound_vars::ResolvedArg;
 
         let def_id = item.owner_id.def_id;
         if let hir::ItemKind::Struct(_, hir_generics)
@@ -2120,8 +2126,8 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements {
                 let (relevant_lifetimes, bounds, predicate_span, in_where_clause) =
                     match where_predicate {
                         hir::WherePredicate::RegionPredicate(predicate) => {
-                            if let Some(Region::EarlyBound(region_def_id)) =
-                                cx.tcx.named_region(predicate.lifetime.hir_id)
+                            if let Some(ResolvedArg::EarlyBound(region_def_id)) =
+                                cx.tcx.named_bound_var(predicate.lifetime.hir_id)
                             {
                                 (
                                     Self::lifetimes_outliving_lifetime(
@@ -2308,11 +2314,8 @@ impl EarlyLintPass for IncompleteFeatures {
             .for_each(|(&name, &span)| {
                 let note = rustc_feature::find_feature_issue(name, GateIssue::Language)
                     .map(|n| BuiltinIncompleteFeaturesNote { n });
-                let help = if HAS_MIN_FEATURES.contains(&name) {
-                    Some(BuiltinIncompleteFeaturesHelp)
-                } else {
-                    None
-                };
+                let help =
+                    HAS_MIN_FEATURES.contains(&name).then_some(BuiltinIncompleteFeaturesHelp);
                 cx.emit_spanned_lint(
                     INCOMPLETE_FEATURES,
                     span,
@@ -2855,8 +2858,8 @@ impl ClashingExternDeclarations {
                                     structurally_same_type_impl(
                                         seen_types,
                                         cx,
-                                        tcx.type_of(a_did),
-                                        tcx.type_of(b_did),
+                                        tcx.type_of(a_did).subst_identity(),
+                                        tcx.type_of(b_did).subst_identity(),
                                         ckind,
                                     )
                                 },
@@ -2956,8 +2959,8 @@ impl<'tcx> LateLintPass<'tcx> for ClashingExternDeclarations {
         if let ForeignItemKind::Fn(..) = this_fi.kind {
             let tcx = cx.tcx;
             if let Some(existing_did) = self.insert(tcx, this_fi) {
-                let existing_decl_ty = tcx.type_of(existing_did);
-                let this_decl_ty = tcx.type_of(this_fi.owner_id);
+                let existing_decl_ty = tcx.type_of(existing_did).skip_binder();
+                let this_decl_ty = tcx.type_of(this_fi.owner_id).subst_identity();
                 debug!(
                     "ClashingExternDeclarations: Comparing existing {:?}: {:?} to this {:?}: {:?}",
                     existing_did, existing_decl_ty, this_fi.owner_id, this_decl_ty
diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs
index 972240f42cf..9a9e2de7b5c 100644
--- a/compiler/rustc_lint/src/context.rs
+++ b/compiler/rustc_lint/src/context.rs
@@ -487,7 +487,7 @@ impl LintStore {
         let mut groups: Vec<_> = self
             .lint_groups
             .iter()
-            .filter_map(|(k, LintGroup { depr, .. })| if depr.is_none() { Some(k) } else { None })
+            .filter_map(|(k, LintGroup { depr, .. })| depr.is_none().then_some(k))
             .collect();
         groups.sort();
         let groups = groups.iter().map(|k| Symbol::intern(k));
@@ -1112,11 +1112,9 @@ impl<'tcx> LateContext<'tcx> {
                 .maybe_typeck_results()
                 .filter(|typeck_results| typeck_results.hir_owner == id.owner)
                 .or_else(|| {
-                    if self.tcx.has_typeck_results(id.owner.to_def_id()) {
-                        Some(self.tcx.typeck(id.owner.def_id))
-                    } else {
-                        None
-                    }
+                    self.tcx
+                        .has_typeck_results(id.owner.to_def_id())
+                        .then(|| self.tcx.typeck(id.owner.def_id))
                 })
                 .and_then(|typeck_results| typeck_results.type_dependent_def(id))
                 .map_or(Res::Err, |(kind, def_id)| Res::Def(kind, def_id)),
diff --git a/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs b/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs
index dff5a645c17..ccf95992a6e 100644
--- a/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs
+++ b/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs
@@ -59,7 +59,7 @@ impl<'tcx> LateLintPass<'tcx> for DerefIntoDynSupertrait {
         // `Deref` is being implemented for `t`
         if let hir::ItemKind::Impl(impl_) = item.kind
             && let Some(trait_) = &impl_.of_trait
-            && let t = cx.tcx.type_of(item.owner_id)
+            && let t = cx.tcx.type_of(item.owner_id).subst_identity()
             && let opt_did @ Some(did) = trait_.trait_def_id()
             && opt_did == cx.tcx.lang_items().deref_trait()
             // `t` is `dyn t_principal`
@@ -78,7 +78,7 @@ impl<'tcx> LateLintPass<'tcx> for DerefIntoDynSupertrait {
             });
             cx.emit_spanned_lint(DEREF_INTO_DYN_SUPERTRAIT, cx.tcx.def_span(item.owner_id.def_id), SupertraitAsDerefTarget {
                 t,
-                target_principal: target_principal.to_string(),
+                target_principal,
                 label,
             });
         }
diff --git a/compiler/rustc_lint/src/for_loops_over_fallibles.rs b/compiler/rustc_lint/src/for_loops_over_fallibles.rs
index 1add352e0c4..a3367ae4a9f 100644
--- a/compiler/rustc_lint/src/for_loops_over_fallibles.rs
+++ b/compiler/rustc_lint/src/for_loops_over_fallibles.rs
@@ -65,11 +65,8 @@ impl<'tcx> LateLintPass<'tcx> for ForLoopsOverFallibles {
             } else {
                 ForLoopsOverFalliblesLoopSub::UseWhileLet { start_span: expr.span.with_hi(pat.span.lo()), end_span: pat.span.between(arg.span), var }
             } ;
-        let question_mark = if suggest_question_mark(cx, adt, substs, expr.span) {
-            Some(ForLoopsOverFalliblesQuestionMark { suggestion: arg.span.shrink_to_hi() })
-        } else {
-            None
-        };
+        let question_mark = suggest_question_mark(cx, adt, substs, expr.span)
+            .then(|| ForLoopsOverFalliblesQuestionMark { suggestion: arg.span.shrink_to_hi() });
         let suggestion = ForLoopsOverFalliblesSuggestion {
             var,
             start_span: expr.span.with_hi(pat.span.lo()),
diff --git a/compiler/rustc_lint/src/internal.rs b/compiler/rustc_lint/src/internal.rs
index 6cefaea2bc7..2fd0ef3cda8 100644
--- a/compiler/rustc_lint/src/internal.rs
+++ b/compiler/rustc_lint/src/internal.rs
@@ -216,7 +216,7 @@ fn is_ty_or_ty_ctxt(cx: &LateContext<'_>, path: &Path<'_>) -> Option<String> {
         }
         // Only lint on `&Ty` and `&TyCtxt` if it is used outside of a trait.
         Res::SelfTyAlias { alias_to: did, is_trait_impl: false, .. } => {
-            if let ty::Adt(adt, substs) = cx.tcx.type_of(did).kind() {
+            if let ty::Adt(adt, substs) = cx.tcx.type_of(did).subst_identity().kind() {
                 if let Some(name @ (sym::Ty | sym::TyCtxt)) = cx.tcx.get_diagnostic_name(adt.did())
                 {
                     // NOTE: This path is currently unreachable as `Ty<'tcx>` is
diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs
index 2e447b900e1..94a43ab0c46 100644
--- a/compiler/rustc_lint/src/lints.rs
+++ b/compiler/rustc_lint/src/lints.rs
@@ -8,7 +8,7 @@ use rustc_errors::{
 };
 use rustc_hir::def_id::DefId;
 use rustc_macros::{LintDiagnostic, Subdiagnostic};
-use rustc_middle::ty::{Predicate, Ty, TyCtxt};
+use rustc_middle::ty::{PolyExistentialTraitRef, Predicate, Ty, TyCtxt};
 use rustc_session::parse::ParseSess;
 use rustc_span::{edition::Edition, sym, symbol::Ident, Span, Symbol};
 
@@ -556,8 +556,7 @@ pub struct BuiltinUnexpectedCliConfigValue {
 #[diag(lint_supertrait_as_deref_target)]
 pub struct SupertraitAsDerefTarget<'a> {
     pub t: Ty<'a>,
-    pub target_principal: String,
-    // pub target_principal: Binder<'a, ExistentialTraitRef<'b>>,
+    pub target_principal: PolyExistentialTraitRef<'a>,
     #[subdiagnostic]
     pub label: Option<SupertraitAsDerefTargetLabel>,
 }
diff --git a/compiler/rustc_lint/src/pass_by_value.rs b/compiler/rustc_lint/src/pass_by_value.rs
index 392e13f2fa9..2bb2a3aab55 100644
--- a/compiler/rustc_lint/src/pass_by_value.rs
+++ b/compiler/rustc_lint/src/pass_by_value.rs
@@ -50,7 +50,7 @@ fn path_for_pass_by_value(cx: &LateContext<'_>, ty: &hir::Ty<'_>) -> Option<Stri
                 return Some(format!("{}{}", name, gen_args(cx, path_segment)));
             }
             Res::SelfTyAlias { alias_to: did, is_trait_impl: false, .. } => {
-                if let ty::Adt(adt, substs) = cx.tcx.type_of(did).kind() {
+                if let ty::Adt(adt, substs) = cx.tcx.type_of(did).subst_identity().kind() {
                     if cx.tcx.has_attr(adt.did(), sym::rustc_pass_by_value) {
                         return Some(cx.tcx.def_path_str_with_substs(adt.did(), substs));
                     }
diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs
index 88c6ea7efb2..b7fd6a254d8 100644
--- a/compiler/rustc_lint/src/types.rs
+++ b/compiler/rustc_lint/src/types.rs
@@ -651,7 +651,7 @@ pub fn transparent_newtype_field<'a, 'tcx>(
 ) -> Option<&'a ty::FieldDef> {
     let param_env = tcx.param_env(variant.def_id);
     variant.fields.iter().find(|field| {
-        let field_ty = tcx.type_of(field.did);
+        let field_ty = tcx.type_of(field.did).subst_identity();
         let is_zst = tcx.layout_of(param_env.and(field_ty)).map_or(false, |layout| layout.is_zst());
         !is_zst
     })
@@ -1240,7 +1240,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
     }
 
     fn check_foreign_static(&mut self, id: hir::OwnerId, span: Span) {
-        let ty = self.cx.tcx.type_of(id);
+        let ty = self.cx.tcx.type_of(id).subst_identity();
         self.check_type_for_ffi_and_report_errors(span, ty, true, false);
     }
 
@@ -1301,7 +1301,7 @@ declare_lint_pass!(VariantSizeDifferences => [VARIANT_SIZE_DIFFERENCES]);
 impl<'tcx> LateLintPass<'tcx> for VariantSizeDifferences {
     fn check_item(&mut self, cx: &LateContext<'_>, it: &hir::Item<'_>) {
         if let hir::ItemKind::Enum(ref enum_definition, _) = it.kind {
-            let t = cx.tcx.type_of(it.owner_id);
+            let t = cx.tcx.type_of(it.owner_id).subst_identity();
             let ty = cx.tcx.erase_regions(t);
             let Ok(layout) = cx.layout_of(ty) else { return };
             let Variants::Multiple {
@@ -1421,7 +1421,7 @@ impl InvalidAtomicOrdering {
             && recognized_names.contains(&method_path.ident.name)
             && let Some(m_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id)
             && let Some(impl_did) = cx.tcx.impl_of_method(m_def_id)
-            && let Some(adt) = cx.tcx.type_of(impl_did).ty_adt_def()
+            && let Some(adt) = cx.tcx.type_of(impl_did).subst_identity().ty_adt_def()
             // skip extension traits, only lint functions from the standard library
             && cx.tcx.trait_id_of_impl(impl_did).is_none()
             && let parent = cx.tcx.parent(adt.did())
diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
index fbc1d8ef310..0a42265a6ba 100644
--- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
@@ -594,6 +594,8 @@ struct LLVMRustSanitizerOptions {
   bool SanitizeThread;
   bool SanitizeHWAddress;
   bool SanitizeHWAddressRecover;
+  bool SanitizeKernelAddress;
+  bool SanitizeKernelAddressRecover;
 };
 
 extern "C" LLVMRustResult
@@ -765,15 +767,17 @@ LLVMRustOptimize(
       );
     }
 
-    if (SanitizerOptions->SanitizeAddress) {
+    if (SanitizerOptions->SanitizeAddress || SanitizerOptions->SanitizeKernelAddress) {
       OptimizerLastEPCallbacks.push_back(
         [SanitizerOptions](ModulePassManager &MPM, OptimizationLevel Level) {
+          auto CompileKernel = SanitizerOptions->SanitizeKernelAddress;
 #if LLVM_VERSION_LT(15, 0)
           MPM.addPass(RequireAnalysisPass<ASanGlobalsMetadataAnalysis, Module>());
 #endif
           AddressSanitizerOptions opts = AddressSanitizerOptions{
-            /*CompileKernel=*/false,
-            SanitizerOptions->SanitizeAddressRecover,
+            CompileKernel,
+            SanitizerOptions->SanitizeAddressRecover
+              || SanitizerOptions->SanitizeKernelAddressRecover,
             /*UseAfterScope=*/true,
             AsanDetectStackUseAfterReturnMode::Runtime,
           };
diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs
index a8514c69d1c..d823989bb02 100644
--- a/compiler/rustc_metadata/src/native_libs.rs
+++ b/compiler/rustc_metadata/src/native_libs.rs
@@ -499,9 +499,10 @@ impl<'tcx> Collector<'tcx> {
         let argument_types: &List<Ty<'_>> = self.tcx.erase_late_bound_regions(
             self.tcx
                 .type_of(item.id.owner_id)
+                .subst_identity()
                 .fn_sig(self.tcx)
                 .inputs()
-                .map_bound(|slice| self.tcx.mk_type_list(slice.iter())),
+                .map_bound(|slice| self.tcx.intern_type_list(slice)),
         );
 
         argument_types
diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
index 8082a890320..0bacf51e911 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
@@ -114,7 +114,7 @@ macro_rules! provide_one {
         fn $name<'tcx>(
             $tcx: TyCtxt<'tcx>,
             def_id_arg: ty::query::query_keys::$name<'tcx>,
-        ) -> ty::query::query_values::$name<'tcx> {
+        ) -> ty::query::query_provided::$name<'tcx> {
             let _prof_timer =
                 $tcx.prof.generic_activity(concat!("metadata_decode_entry_", stringify!($name)));
 
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index 43047051f0f..e941dd45688 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -1541,8 +1541,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
                 self.tables.impl_defaultness.set_some(def_id.index, *defaultness);
                 self.tables.constness.set_some(def_id.index, *constness);
 
-                let trait_ref = self.tcx.impl_trait_ref(def_id).map(ty::EarlyBinder::skip_binder);
+                let trait_ref = self.tcx.impl_trait_ref(def_id);
                 if let Some(trait_ref) = trait_ref {
+                    let trait_ref = trait_ref.skip_binder();
                     let trait_def = self.tcx.trait_def(trait_ref.def_id);
                     if let Ok(mut an) = trait_def.ancestors(self.tcx, def_id) {
                         if let Some(specialization_graph::Node::Impl(parent)) = an.nth(1) {
diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs
index 9227609cc8b..01691398ad0 100644
--- a/compiler/rustc_metadata/src/rmeta/mod.rs
+++ b/compiler/rustc_metadata/src/rmeta/mod.rs
@@ -18,7 +18,7 @@ use rustc_index::vec::IndexVec;
 use rustc_middle::metadata::ModChild;
 use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;
 use rustc_middle::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo};
-use rustc_middle::middle::resolve_lifetime::ObjectLifetimeDefault;
+use rustc_middle::middle::resolve_bound_vars::ObjectLifetimeDefault;
 use rustc_middle::mir;
 use rustc_middle::ty::fast_reject::SimplifiedType;
 use rustc_middle::ty::query::Providers;
@@ -369,7 +369,7 @@ define_tables! {
     explicit_predicates_of: Table<DefIndex, LazyValue<ty::GenericPredicates<'static>>>,
     generics_of: Table<DefIndex, LazyValue<ty::Generics>>,
     super_predicates_of: Table<DefIndex, LazyValue<ty::GenericPredicates<'static>>>,
-    type_of: Table<DefIndex, LazyValue<Ty<'static>>>,
+    type_of: Table<DefIndex, LazyValue<ty::EarlyBinder<Ty<'static>>>>,
     variances_of: Table<DefIndex, LazyArray<ty::Variance>>,
     fn_sig: Table<DefIndex, LazyValue<ty::EarlyBinder<ty::PolyFnSig<'static>>>>,
     codegen_fn_attrs: Table<DefIndex, LazyValue<CodegenFnAttrs>>,
diff --git a/compiler/rustc_middle/src/dep_graph/mod.rs b/compiler/rustc_middle/src/dep_graph/mod.rs
index 2e82efba192..84510fe218c 100644
--- a/compiler/rustc_middle/src/dep_graph/mod.rs
+++ b/compiler/rustc_middle/src/dep_graph/mod.rs
@@ -74,8 +74,8 @@ impl<'tcx> DepContext for TyCtxt<'tcx> {
     type DepKind = DepKind;
 
     #[inline]
-    fn with_stable_hashing_context<R>(&self, f: impl FnOnce(StableHashingContext<'_>) -> R) -> R {
-        TyCtxt::with_stable_hashing_context(*self, f)
+    fn with_stable_hashing_context<R>(self, f: impl FnOnce(StableHashingContext<'_>) -> R) -> R {
+        TyCtxt::with_stable_hashing_context(self, f)
     }
 
     #[inline]
diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs
index ba93330d581..2eafc356dc3 100644
--- a/compiler/rustc_middle/src/hir/map/mod.rs
+++ b/compiler/rustc_middle/src/hir/map/mod.rs
@@ -1062,7 +1062,7 @@ impl<'hir> Map<'hir> {
     }
 
     pub fn span_if_local(self, id: DefId) -> Option<Span> {
-        if id.is_local() { Some(self.tcx.def_span(id)) } else { None }
+        id.is_local().then(|| self.tcx.def_span(id))
     }
 
     pub fn res_span(self, res: Res) -> Option<Span> {
diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs
index dedc65f4cbf..dc89f762b76 100644
--- a/compiler/rustc_middle/src/hir/mod.rs
+++ b/compiler/rustc_middle/src/hir/mod.rs
@@ -104,7 +104,7 @@ impl<'tcx> TyCtxt<'tcx> {
         self.impl_trait_ref(def_id)
             .map(|t| t.subst_identity())
             .map(ImplSubject::Trait)
-            .unwrap_or_else(|| ImplSubject::Inherent(self.type_of(def_id)))
+            .unwrap_or_else(|| ImplSubject::Inherent(self.type_of(def_id).subst_identity()))
     }
 }
 
diff --git a/compiler/rustc_middle/src/infer/canonical.rs b/compiler/rustc_middle/src/infer/canonical.rs
index ada516aa032..bb617e692cc 100644
--- a/compiler/rustc_middle/src/infer/canonical.rs
+++ b/compiler/rustc_middle/src/infer/canonical.rs
@@ -353,7 +353,7 @@ impl<'tcx> CanonicalVarValues<'tcx> {
                                 var: ty::BoundVar::from_usize(i),
                                 kind: ty::BrAnon(i as u32, None),
                             };
-                            tcx.mk_region(ty::ReLateBound(ty::INNERMOST, br)).into()
+                            tcx.mk_re_late_bound(ty::INNERMOST, br).into()
                         }
                         CanonicalVarKind::Const(_, ty)
                         | CanonicalVarKind::PlaceholderConst(_, ty) => tcx
diff --git a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs
index bea884c856a..c4601a1fb41 100644
--- a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs
+++ b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs
@@ -91,7 +91,8 @@ bitflags! {
         /// the MIR `InstrumentCoverage` pass and not added to the coverage map
         /// during codegen.
         const NO_COVERAGE               = 1 << 15;
-        /// `#[used(linker)]`: indicates that LLVM nor the linker can eliminate this function.
+        /// `#[used(linker)]`:
+        /// indicates that neither LLVM nor the linker will eliminate this function.
         const USED_LINKER               = 1 << 16;
         /// `#[rustc_deallocator]`: a hint to LLVM that the function only deallocates memory.
         const DEALLOCATOR               = 1 << 17;
diff --git a/compiler/rustc_middle/src/middle/mod.rs b/compiler/rustc_middle/src/middle/mod.rs
index 8dc68b1f5a8..0b6774f1b1f 100644
--- a/compiler/rustc_middle/src/middle/mod.rs
+++ b/compiler/rustc_middle/src/middle/mod.rs
@@ -29,7 +29,7 @@ pub mod lib_features {
 pub mod limits;
 pub mod privacy;
 pub mod region;
-pub mod resolve_lifetime;
+pub mod resolve_bound_vars;
 pub mod stability;
 
 pub fn provide(providers: &mut crate::ty::query::Providers) {
diff --git a/compiler/rustc_middle/src/middle/resolve_lifetime.rs b/compiler/rustc_middle/src/middle/resolve_bound_vars.rs
index c3bf1c717d9..c59704fc023 100644
--- a/compiler/rustc_middle/src/middle/resolve_lifetime.rs
+++ b/compiler/rustc_middle/src/middle/resolve_bound_vars.rs
@@ -1,18 +1,20 @@
-//! Name resolution for lifetimes: type declarations.
+//! Name resolution for lifetimes and late-bound type and const variables: type declarations.
 
 use crate::ty;
 
 use rustc_data_structures::fx::FxHashMap;
+use rustc_errors::ErrorGuaranteed;
 use rustc_hir::def_id::DefId;
 use rustc_hir::{ItemLocalId, OwnerId};
 use rustc_macros::HashStable;
 
 #[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable, Debug, HashStable)]
-pub enum Region {
-    Static,
-    EarlyBound(/* lifetime decl */ DefId),
-    LateBound(ty::DebruijnIndex, /* late-bound index */ u32, /* lifetime decl */ DefId),
+pub enum ResolvedArg {
+    StaticLifetime,
+    EarlyBound(/* decl */ DefId),
+    LateBound(ty::DebruijnIndex, /* late-bound index */ u32, /* decl */ DefId),
     Free(DefId, /* lifetime decl */ DefId),
+    Error(ErrorGuaranteed),
 }
 
 /// A set containing, at most, one known element.
@@ -46,10 +48,10 @@ pub enum ObjectLifetimeDefault {
 /// Maps the id of each lifetime reference to the lifetime decl
 /// that it corresponds to.
 #[derive(Default, HashStable, Debug)]
-pub struct ResolveLifetimes {
+pub struct ResolveBoundVars {
     /// Maps from every use of a named (not anonymous) lifetime to a
     /// `Region` describing how that region is bound
-    pub defs: FxHashMap<OwnerId, FxHashMap<ItemLocalId, Region>>,
+    pub defs: FxHashMap<OwnerId, FxHashMap<ItemLocalId, ResolvedArg>>,
 
     pub late_bound_vars: FxHashMap<OwnerId, FxHashMap<ItemLocalId, Vec<ty::BoundVariableKind>>>,
 }
diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs
index c596e91160c..46184cddd51 100644
--- a/compiler/rustc_middle/src/mir/mod.rs
+++ b/compiler/rustc_middle/src/mir/mod.rs
@@ -414,7 +414,7 @@ impl<'tcx> Body<'tcx> {
         (self.arg_count + 1..self.local_decls.len()).filter_map(move |index| {
             let local = Local::new(index);
             let decl = &self.local_decls[local];
-            (decl.is_user_variable() && decl.mutability.is_mut()).then(|| local)
+            (decl.is_user_variable() && decl.mutability.is_mut()).then_some(local)
         })
     }
 
@@ -2497,7 +2497,7 @@ impl<'tcx> ConstantKind<'tcx> {
         };
         debug!("expr.kind: {:?}", expr.kind);
 
-        let ty = tcx.type_of(def.def_id_for_type_of());
+        let ty = tcx.type_of(def.def_id_for_type_of()).subst_identity();
         debug!(?ty);
 
         // FIXME(const_generics): We currently have to special case parameters because `min_const_generics`
@@ -2525,14 +2525,12 @@ impl<'tcx> ConstantKind<'tcx> {
         }
 
         let hir_id = tcx.hir().local_def_id_to_hir_id(def.did);
-        let parent_substs = if let Some(parent_hir_id) = tcx.hir().opt_parent_id(hir_id) {
-            if let Some(parent_did) = parent_hir_id.as_owner() {
-                InternalSubsts::identity_for_item(tcx, parent_did.to_def_id())
-            } else {
-                tcx.mk_substs(Vec::<GenericArg<'tcx>>::new().into_iter())
-            }
+        let parent_substs = if let Some(parent_hir_id) = tcx.hir().opt_parent_id(hir_id)
+            && let Some(parent_did) = parent_hir_id.as_owner()
+        {
+            InternalSubsts::identity_for_item(tcx, parent_did.to_def_id())
         } else {
-            tcx.mk_substs(Vec::<GenericArg<'tcx>>::new().into_iter())
+            tcx.intern_substs(&[])
         };
         debug!(?parent_substs);
 
diff --git a/compiler/rustc_middle/src/mir/tcx.rs b/compiler/rustc_middle/src/mir/tcx.rs
index 97dc8a99f9b..aa9f170477b 100644
--- a/compiler/rustc_middle/src/mir/tcx.rs
+++ b/compiler/rustc_middle/src/mir/tcx.rs
@@ -165,7 +165,7 @@ impl<'tcx> Rvalue<'tcx> {
                 tcx.mk_array_with_const_len(operand.ty(local_decls, tcx), count)
             }
             Rvalue::ThreadLocalRef(did) => {
-                let static_ty = tcx.type_of(did);
+                let static_ty = tcx.type_of(did).subst_identity();
                 if tcx.is_mutable_static(did) {
                     tcx.mk_mut_ptr(static_ty)
                 } else if tcx.is_foreign_item(did) {
@@ -202,9 +202,7 @@ impl<'tcx> Rvalue<'tcx> {
             Rvalue::Aggregate(ref ak, ref ops) => match **ak {
                 AggregateKind::Array(ty) => tcx.mk_array(ty, ops.len() as u64),
                 AggregateKind::Tuple => tcx.mk_tup(ops.iter().map(|op| op.ty(local_decls, tcx))),
-                AggregateKind::Adt(did, _, substs, _, _) => {
-                    tcx.bound_type_of(did).subst(tcx, substs)
-                }
+                AggregateKind::Adt(did, _, substs, _, _) => tcx.type_of(did).subst(tcx, substs),
                 AggregateKind::Closure(did, substs) => tcx.mk_closure(did, substs),
                 AggregateKind::Generator(did, substs, movability) => {
                     tcx.mk_generator(did, substs, movability)
diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs
index 3ddac5e11fb..443c1b2d261 100644
--- a/compiler/rustc_middle/src/mir/visit.rs
+++ b/compiler/rustc_middle/src/mir/visit.rs
@@ -323,7 +323,7 @@ macro_rules! make_mir_visitor {
                     self.visit_source_scope($(& $mutability)? *parent_scope);
                 }
                 if let Some((callee, callsite_span)) = inlined {
-                    let location = START_BLOCK.start_location();
+                    let location = Location::START;
 
                     self.visit_span($(& $mutability)? *callsite_span);
 
@@ -837,7 +837,7 @@ macro_rules! make_mir_visitor {
                 } = var_debug_info;
 
                 self.visit_source_info(source_info);
-                let location = START_BLOCK.start_location();
+                let location = Location::START;
                 match value {
                     VarDebugInfoContents::Const(c) => self.visit_constant(c, location),
                     VarDebugInfoContents::Place(place) =>
@@ -1026,7 +1026,7 @@ macro_rules! super_body {
         $self.visit_span($(& $mutability)? $body.span);
 
         for const_ in &$($mutability)? $body.required_consts {
-            let location = START_BLOCK.start_location();
+            let location = Location::START;
             $self.visit_constant(const_, location);
         }
     }
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index 4b34f6b4881..cf4d9b4b005 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -152,7 +152,7 @@ rustc_queries! {
     /// to an alias, it will "skip" this alias to return the aliased type.
     ///
     /// [`DefId`]: rustc_hir::def_id::DefId
-    query type_of(key: DefId) -> Ty<'tcx> {
+    query type_of(key: DefId) -> ty::EarlyBinder<Ty<'tcx>> {
         desc { |tcx|
             "{action} `{path}`",
             action = {
@@ -729,15 +729,14 @@ rustc_queries! {
     }
 
     /// Maps from a trait item to the trait item "descriptor".
-    query associated_item(key: DefId) -> &'tcx ty::AssocItem {
+    query associated_item(key: DefId) -> ty::AssocItem {
         desc { |tcx| "computing associated item data for `{}`", tcx.def_path_str(key) }
-        arena_cache
         cache_on_disk_if { key.is_local() }
         separate_provide_extern
     }
 
     /// Collects the associated items defined on a trait or impl.
-    query associated_items(key: DefId) -> &'tcx ty::AssocItems<'tcx> {
+    query associated_items(key: DefId) -> &'tcx ty::AssocItems {
         arena_cache
         desc { |tcx| "collecting associated items of `{}`", tcx.def_path_str(key) }
     }
@@ -781,7 +780,7 @@ rustc_queries! {
         separate_provide_extern
     }
 
-    query issue33140_self_ty(key: DefId) -> Option<ty::Ty<'tcx>> {
+    query issue33140_self_ty(key: DefId) -> Option<ty::EarlyBinder<ty::Ty<'tcx>>> {
         desc { |tcx| "computing Self type wrt issue #33140 `{}`", tcx.def_path_str(key) }
     }
 
@@ -1641,12 +1640,12 @@ rustc_queries! {
     /// Does lifetime resolution on items. Importantly, we can't resolve
     /// lifetimes directly on things like trait methods, because of trait params.
     /// See `rustc_resolve::late::lifetimes for details.
-    query resolve_lifetimes(_: hir::OwnerId) -> &'tcx ResolveLifetimes {
+    query resolve_bound_vars(_: hir::OwnerId) -> &'tcx ResolveBoundVars {
         arena_cache
         desc { "resolving lifetimes" }
     }
-    query named_region_map(_: hir::OwnerId) ->
-        Option<&'tcx FxHashMap<ItemLocalId, Region>> {
+    query named_variable_map(_: hir::OwnerId) ->
+        Option<&'tcx FxHashMap<ItemLocalId, ResolvedArg>> {
         desc { "looking up a named region" }
     }
     query is_late_bound_map(_: hir::OwnerId) -> Option<&'tcx FxIndexSet<ItemLocalId>> {
diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs
index c528929e756..6231dd9b6f5 100644
--- a/compiler/rustc_middle/src/traits/mod.rs
+++ b/compiler/rustc_middle/src/traits/mod.rs
@@ -474,7 +474,11 @@ pub enum WellFormedLoc {
 #[derive(TypeVisitable, TypeFoldable)]
 pub struct ImplDerivedObligationCause<'tcx> {
     pub derived: DerivedObligationCause<'tcx>,
-    pub impl_def_id: DefId,
+    /// The `DefId` of the `impl` that gave rise to the `derived` obligation.
+    /// If the `derived` obligation arose from a trait alias, which conceptually has a synthetic impl,
+    /// then this will be the `DefId` of that trait alias. Care should therefore be taken to handle
+    /// that exceptional case where appropriate.
+    pub impl_or_alias_def_id: DefId,
     /// The index of the derived predicate in the parent impl's predicates.
     pub impl_def_predicate_index: Option<usize>,
     pub span: Span,
diff --git a/compiler/rustc_middle/src/traits/specialization_graph.rs b/compiler/rustc_middle/src/traits/specialization_graph.rs
index aad5b2fbe07..4019cf8ceee 100644
--- a/compiler/rustc_middle/src/traits/specialization_graph.rs
+++ b/compiler/rustc_middle/src/traits/specialization_graph.rs
@@ -133,11 +133,7 @@ impl Node {
     ///
     /// If this returns `None`, the item can potentially still be found in
     /// parents of this node.
-    pub fn item<'tcx>(
-        &self,
-        tcx: TyCtxt<'tcx>,
-        trait_item_def_id: DefId,
-    ) -> Option<&'tcx ty::AssocItem> {
+    pub fn item<'tcx>(&self, tcx: TyCtxt<'tcx>, trait_item_def_id: DefId) -> Option<ty::AssocItem> {
         match *self {
             Node::Trait(_) => Some(tcx.associated_item(trait_item_def_id)),
             Node::Impl(impl_def_id) => {
@@ -239,7 +235,7 @@ impl<'tcx> Ancestors<'tcx> {
                     }
                 }
 
-                Some(LeafDef { item: *item, defining_node: node, finalizing_node })
+                Some(LeafDef { item, defining_node: node, finalizing_node })
             } else {
                 // Item not mentioned. This "finalizes" any defaulted item provided by an ancestor.
                 finalizing_node = Some(node);
@@ -263,7 +259,7 @@ pub fn ancestors(
 
     if let Some(reported) = specialization_graph.has_errored {
         Err(reported)
-    } else if let Err(reported) = tcx.type_of(start_from_impl).error_reported() {
+    } else if let Err(reported) = tcx.type_of(start_from_impl).subst_identity().error_reported() {
         Err(reported)
     } else {
         Ok(Ancestors {
diff --git a/compiler/rustc_middle/src/ty/assoc.rs b/compiler/rustc_middle/src/ty/assoc.rs
index 71cecfb558f..f1a9e50a4f0 100644
--- a/compiler/rustc_middle/src/ty/assoc.rs
+++ b/compiler/rustc_middle/src/ty/assoc.rs
@@ -83,7 +83,7 @@ impl AssocItem {
             }
             ty::AssocKind::Type => format!("type {};", self.name),
             ty::AssocKind::Const => {
-                format!("const {}: {:?};", self.name, tcx.type_of(self.def_id))
+                format!("const {}: {:?};", self.name, tcx.type_of(self.def_id).subst_identity())
             }
         }
     }
@@ -129,13 +129,13 @@ impl std::fmt::Display for AssocKind {
 /// it is relatively expensive. Instead, items are indexed by `Symbol` and hygienic comparison is
 /// done only on items with the same name.
 #[derive(Debug, Clone, PartialEq, HashStable)]
-pub struct AssocItems<'tcx> {
-    items: SortedIndexMultiMap<u32, Symbol, &'tcx ty::AssocItem>,
+pub struct AssocItems {
+    items: SortedIndexMultiMap<u32, Symbol, ty::AssocItem>,
 }
 
-impl<'tcx> AssocItems<'tcx> {
+impl AssocItems {
     /// Constructs an `AssociatedItems` map from a series of `ty::AssocItem`s in definition order.
-    pub fn new(items_in_def_order: impl IntoIterator<Item = &'tcx ty::AssocItem>) -> Self {
+    pub fn new(items_in_def_order: impl IntoIterator<Item = ty::AssocItem>) -> Self {
         let items = items_in_def_order.into_iter().map(|item| (item.name, item)).collect();
         AssocItems { items }
     }
@@ -145,7 +145,7 @@ impl<'tcx> AssocItems<'tcx> {
     /// New code should avoid relying on definition order. If you need a particular associated item
     /// for a known trait, make that trait a lang item instead of indexing this array.
     pub fn in_definition_order(&self) -> impl '_ + Iterator<Item = &ty::AssocItem> {
-        self.items.iter().map(|(_, v)| *v)
+        self.items.iter().map(|(_, v)| v)
     }
 
     pub fn len(&self) -> usize {
@@ -157,7 +157,7 @@ impl<'tcx> AssocItems<'tcx> {
         &self,
         name: Symbol,
     ) -> impl '_ + Iterator<Item = &ty::AssocItem> {
-        self.items.get_by_key(name).copied()
+        self.items.get_by_key(name)
     }
 
     /// Returns the associated item with the given name and `AssocKind`, if one exists.
diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs
index 927f18f59b9..884ae7f5da2 100644
--- a/compiler/rustc_middle/src/ty/consts.rs
+++ b/compiler/rustc_middle/src/ty/consts.rs
@@ -1,7 +1,9 @@
+use crate::middle::resolve_bound_vars as rbv;
 use crate::mir::interpret::LitToConstInput;
 use crate::ty::{self, DefIdTree, InternalSubsts, ParamEnv, ParamEnvAnd, Ty, TyCtxt};
 use rustc_data_structures::intern::Interned;
 use rustc_hir as hir;
+use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_macros::HashStable;
 use std::fmt;
@@ -71,7 +73,10 @@ impl<'tcx> Const<'tcx> {
         let expr = &tcx.hir().body(body_id).value;
         debug!(?expr);
 
-        let ty = tcx.type_of(def.def_id_for_type_of());
+        let ty = tcx
+            .type_of(def.def_id_for_type_of())
+            .no_bound_vars()
+            .expect("const parameter types cannot be generic");
 
         match Self::try_eval_lit_or_param(tcx, ty, expr) {
             Some(v) => v,
@@ -125,16 +130,30 @@ impl<'tcx> Const<'tcx> {
             }
         }
 
-        use hir::{def::DefKind::ConstParam, def::Res, ExprKind, Path, QPath};
         match expr.kind {
-            ExprKind::Path(QPath::Resolved(_, &Path { res: Res::Def(ConstParam, def_id), .. })) => {
-                // 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);
-                Some(tcx.mk_const(ty::ParamConst::new(index, name), ty))
+            hir::ExprKind::Path(hir::QPath::Resolved(
+                _,
+                &hir::Path { res: Res::Def(DefKind::ConstParam, def_id), .. },
+            )) => {
+                match tcx.named_bound_var(expr.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);
+                        Some(tcx.mk_const(ty::ParamConst::new(index, name), ty))
+                    }
+                    Some(rbv::ResolvedArg::LateBound(debruijn, index, _)) => Some(tcx.mk_const(
+                        ty::ConstKind::Bound(debruijn, ty::BoundVar::from_u32(index)),
+                        ty,
+                    )),
+                    Some(rbv::ResolvedArg::Error(guar)) => {
+                        Some(tcx.const_error_with_guaranteed(ty, guar))
+                    }
+                    arg => bug!("unexpected bound var resolution for {:?}: {arg:?}", expr.hir_id),
+                }
             }
             _ => None,
         }
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 4aef071cd98..e2f32cdca3c 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -9,7 +9,7 @@ use crate::dep_graph::{DepGraph, DepKindStruct};
 use crate::infer::canonical::{CanonicalVarInfo, CanonicalVarInfos};
 use crate::lint::struct_lint_level;
 use crate::middle::codegen_fn_attrs::CodegenFnAttrs;
-use crate::middle::resolve_lifetime;
+use crate::middle::resolve_bound_vars;
 use crate::middle::stability;
 use crate::mir::interpret::{self, Allocation, ConstAllocation};
 use crate::mir::{
@@ -67,7 +67,7 @@ use rustc_target::abi::{Layout, LayoutS, TargetDataLayout, VariantIdx};
 use rustc_target::spec::abi;
 use rustc_type_ir::sty::TyKind::*;
 use rustc_type_ir::WithCachedTypeInfo;
-use rustc_type_ir::{DynKind, InternAs, InternIteratorElement, Interner, TypeFlags};
+use rustc_type_ir::{CollectAndApply, DynKind, Interner, TypeFlags};
 
 use std::any::Any;
 use std::borrow::Borrow;
@@ -243,11 +243,20 @@ impl<'tcx> CtxtInterners<'tcx> {
     }
 }
 
+// For these preinterned values, an alternative would be to have
+// variable-length vectors that grow as needed. But that turned out to be
+// slightly more complex and no faster.
+
 const NUM_PREINTERNED_TY_VARS: u32 = 100;
 const NUM_PREINTERNED_FRESH_TYS: u32 = 20;
 const NUM_PREINTERNED_FRESH_INT_TYS: u32 = 3;
 const NUM_PREINTERNED_FRESH_FLOAT_TYS: u32 = 3;
 
+// This number may seem high, but it is reached in all but the smallest crates.
+const NUM_PREINTERNED_RE_VARS: u32 = 500;
+const NUM_PREINTERNED_RE_LATE_BOUNDS_I: u32 = 2;
+const NUM_PREINTERNED_RE_LATE_BOUNDS_V: u32 = 20;
+
 pub struct CommonTypes<'tcx> {
     pub unit: Ty<'tcx>,
     pub bool: Ty<'tcx>,
@@ -295,6 +304,14 @@ pub struct CommonLifetimes<'tcx> {
 
     /// Erased region, used outside of type inference.
     pub re_erased: Region<'tcx>,
+
+    /// Pre-interned `ReVar(ty::RegionVar(n))` for small values of `n`.
+    pub re_vars: Vec<Region<'tcx>>,
+
+    /// Pre-interned values of the form:
+    /// `ReLateBound(DebruijnIndex(i), BoundRegion { var: v, kind: BrAnon(v, None) })
+    /// for small values of `i` and `v`.
+    pub re_late_bounds: Vec<Vec<Region<'tcx>>>,
 }
 
 pub struct CommonConsts<'tcx> {
@@ -358,7 +375,31 @@ impl<'tcx> CommonLifetimes<'tcx> {
             ))
         };
 
-        CommonLifetimes { re_static: mk(ty::ReStatic), re_erased: mk(ty::ReErased) }
+        let re_vars =
+            (0..NUM_PREINTERNED_RE_VARS).map(|n| mk(ty::ReVar(ty::RegionVid::from(n)))).collect();
+
+        let re_late_bounds = (0..NUM_PREINTERNED_RE_LATE_BOUNDS_I)
+            .map(|i| {
+                (0..NUM_PREINTERNED_RE_LATE_BOUNDS_V)
+                    .map(|v| {
+                        mk(ty::ReLateBound(
+                            ty::DebruijnIndex::from(i),
+                            ty::BoundRegion {
+                                var: ty::BoundVar::from(v),
+                                kind: ty::BrAnon(v, None),
+                            },
+                        ))
+                    })
+                    .collect()
+            })
+            .collect();
+
+        CommonLifetimes {
+            re_static: mk(ty::ReStatic),
+            re_erased: mk(ty::ReErased),
+            re_vars,
+            re_late_bounds,
+        }
     }
 }
 
@@ -479,7 +520,7 @@ pub struct GlobalCtxt<'tcx> {
     pub on_disk_cache: Option<&'tcx dyn OnDiskCache<'tcx>>,
 
     pub queries: &'tcx dyn query::QueryEngine<'tcx>,
-    pub query_caches: query::QueryCaches<'tcx>,
+    pub query_system: query::QuerySystem<'tcx>,
     pub(crate) query_kinds: &'tcx [DepKindStruct<'tcx>],
 
     // Internal caches for metadata decoding. No need to track deps on this.
@@ -664,7 +705,7 @@ impl<'tcx> TyCtxt<'tcx> {
             untracked,
             on_disk_cache,
             queries,
-            query_caches: query::QueryCaches::default(),
+            query_system: Default::default(),
             query_kinds,
             ty_rcache: Default::default(),
             pred_rcache: Default::default(),
@@ -697,15 +738,15 @@ impl<'tcx> TyCtxt<'tcx> {
 
     /// Constructs a `RegionKind::ReError` lifetime.
     #[track_caller]
-    pub fn re_error(self, reported: ErrorGuaranteed) -> Region<'tcx> {
-        self.mk_region(ty::ReError(reported))
+    pub fn mk_re_error(self, reported: ErrorGuaranteed) -> Region<'tcx> {
+        self.intern_region(ty::ReError(reported))
     }
 
     /// Constructs a `RegionKind::ReError` lifetime and registers a `delay_span_bug` to ensure it
     /// gets used.
     #[track_caller]
-    pub fn re_error_misc(self) -> Region<'tcx> {
-        self.re_error_with_message(
+    pub fn mk_re_error_misc(self) -> Region<'tcx> {
+        self.mk_re_error_with_message(
             DUMMY_SP,
             "RegionKind::ReError constructed but no error reported",
         )
@@ -714,9 +755,9 @@ impl<'tcx> TyCtxt<'tcx> {
     /// Constructs a `RegionKind::ReError` lifetime and registers a `delay_span_bug` with the given
     /// `msg` to ensure it gets used.
     #[track_caller]
-    pub fn re_error_with_message<S: Into<MultiSpan>>(self, span: S, msg: &str) -> Region<'tcx> {
+    pub fn mk_re_error_with_message<S: Into<MultiSpan>>(self, span: S, msg: &str) -> Region<'tcx> {
         let reported = self.sess.delay_span_bug(span, msg);
-        self.re_error(reported)
+        self.mk_re_error(reported)
     }
 
     /// Like [TyCtxt::ty_error] but for constants, with current `ErrorGuaranteed`
@@ -1108,18 +1149,16 @@ impl<'tcx> TyCtxt<'tcx> {
             _ => return None,
         }
 
-        let ret_ty = self.type_of(scope_def_id);
+        let ret_ty = self.type_of(scope_def_id).subst_identity();
         match ret_ty.kind() {
             ty::FnDef(_, _) => {
                 let sig = ret_ty.fn_sig(self);
                 let output = self.erase_late_bound_regions(sig.output());
-                if output.is_impl_trait() {
+                output.is_impl_trait().then(|| {
                     let hir_id = self.hir().local_def_id_to_hir_id(scope_def_id);
                     let fn_decl = self.hir().fn_decl_by_hir_id(hir_id).unwrap();
-                    Some((output, fn_decl.output.span()))
-                } else {
-                    None
-                }
+                    (output, fn_decl.output.span())
+                })
             }
             _ => None,
         }
@@ -1150,8 +1189,8 @@ impl<'tcx> TyCtxt<'tcx> {
     pub fn caller_location_ty(self) -> Ty<'tcx> {
         self.mk_imm_ref(
             self.lifetimes.re_static,
-            self.bound_type_of(self.require_lang_item(LangItem::PanicLocation, None))
-                .subst(self, self.mk_substs([self.lifetimes.re_static.into()].iter())),
+            self.type_of(self.require_lang_item(LangItem::PanicLocation, None))
+                .subst(self, self.intern_substs(&[self.lifetimes.re_static.into()])),
         )
     }
 
@@ -1225,13 +1264,12 @@ macro_rules! nop_lift {
         impl<'a, 'tcx> Lift<'tcx> for $ty {
             type Lifted = $lifted;
             fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
-                if tcx.interners.$set.contains_pointer_to(&InternedInSet(&*self.0.0)) {
+                tcx.interners
+                    .$set
+                    .contains_pointer_to(&InternedInSet(&*self.0.0))
                     // SAFETY: `self` is interned and therefore valid
                     // for the entire lifetime of the `TyCtxt`.
-                    Some(unsafe { mem::transmute(self) })
-                } else {
-                    None
-                }
+                    .then(|| unsafe { mem::transmute(self) })
             }
         }
     };
@@ -1246,13 +1284,13 @@ impl<'a, 'tcx> Lift<'tcx> for &'a List<Ty<'a>> {
         if self.is_empty() {
             return Some(List::empty());
         }
-        if tcx.interners.substs.contains_pointer_to(&InternedInSet(self.as_substs())) {
+
+        tcx.interners
+            .substs
+            .contains_pointer_to(&InternedInSet(self.as_substs()))
             // SAFETY: `self` is interned and therefore valid
             // for the entire lifetime of the `TyCtxt`.
-            Some(unsafe { mem::transmute::<&'a List<Ty<'a>>, &'tcx List<Ty<'tcx>>>(self) })
-        } else {
-            None
-        }
+            .then(|| unsafe { mem::transmute::<&'a List<Ty<'a>>, &'tcx List<Ty<'tcx>>>(self) })
     }
 }
 
@@ -1264,11 +1302,10 @@ macro_rules! nop_list_lift {
                 if self.is_empty() {
                     return Some(List::empty());
                 }
-                if tcx.interners.$set.contains_pointer_to(&InternedInSet(self)) {
-                    Some(unsafe { mem::transmute(self) })
-                } else {
-                    None
-                }
+                tcx.interners
+                    .$set
+                    .contains_pointer_to(&InternedInSet(self))
+                    .then(|| unsafe { mem::transmute(self) })
             }
         }
     };
@@ -1517,7 +1554,7 @@ macro_rules! direct_interners {
 }
 
 direct_interners! {
-    region: mk_region(RegionKind<'tcx>): Region -> Region<'tcx>,
+    region: intern_region(RegionKind<'tcx>): Region -> Region<'tcx>,
     const_: mk_const_internal(ConstData<'tcx>): Const -> Const<'tcx>,
     const_allocation: intern_const_alloc(Allocation): ConstAllocation -> ConstAllocation<'tcx>,
     layout: intern_layout(LayoutS): Layout -> Layout<'tcx>,
@@ -1623,21 +1660,14 @@ impl<'tcx> TyCtxt<'tcx> {
         unsafety: hir::Unsafety,
     ) -> PolyFnSig<'tcx> {
         sig.map_bound(|s| {
-            let params_iter = match s.inputs()[0].kind() {
-                ty::Tuple(params) => params.into_iter(),
+            let params = match s.inputs()[0].kind() {
+                ty::Tuple(params) => *params,
                 _ => bug!(),
             };
-            self.mk_fn_sig(params_iter, s.output(), s.c_variadic, unsafety, abi::Abi::Rust)
+            self.mk_fn_sig(params, s.output(), s.c_variadic, unsafety, abi::Abi::Rust)
         })
     }
 
-    /// Same a `self.mk_region(kind)`, but avoids accessing the interners if
-    /// `*r == kind`.
-    #[inline]
-    pub fn reuse_or_mk_region(self, r: Region<'tcx>, kind: RegionKind<'tcx>) -> Region<'tcx> {
-        if *r == kind { r } else { self.mk_region(kind) }
-    }
-
     // Avoid this in favour of more specific `mk_*` methods, where possible.
     #[allow(rustc::usage_of_ty_tykind)]
     #[inline]
@@ -1724,7 +1754,7 @@ impl<'tcx> TyCtxt<'tcx> {
                         ty_param.into()
                     } else {
                         assert!(has_default);
-                        self.bound_type_of(param.def_id).subst(self, substs).into()
+                        self.type_of(param.def_id).subst(self, substs).into()
                     }
                 }
             });
@@ -1805,8 +1835,12 @@ impl<'tcx> TyCtxt<'tcx> {
         if ts.is_empty() { self.types.unit } else { self.mk_ty(Tuple(self.intern_type_list(&ts))) }
     }
 
-    pub fn mk_tup<I: InternAs<Ty<'tcx>, Ty<'tcx>>>(self, iter: I) -> I::Output {
-        iter.intern_with(|ts| self.intern_tup(ts))
+    pub fn mk_tup<I, T>(self, iter: I) -> T::Output
+    where
+        I: Iterator<Item = T>,
+        T: CollectAndApply<Ty<'tcx>, Ty<'tcx>>,
+    {
+        T::collect_and_apply(iter, |ts| self.intern_tup(ts))
     }
 
     #[inline]
@@ -1966,13 +2000,15 @@ impl<'tcx> TyCtxt<'tcx> {
     pub fn mk_param_from_def(self, param: &ty::GenericParamDef) -> GenericArg<'tcx> {
         match param.kind {
             GenericParamDefKind::Lifetime => {
-                self.mk_region(ty::ReEarlyBound(param.to_early_bound_region_data())).into()
+                self.mk_re_early_bound(param.to_early_bound_region_data()).into()
             }
             GenericParamDefKind::Type { .. } => self.mk_ty_param(param.index, param.name).into(),
             GenericParamDefKind::Const { .. } => self
                 .mk_const(
                     ParamConst { index: param.index, name: param.name },
-                    self.type_of(param.def_id),
+                    self.type_of(param.def_id)
+                        .no_bound_vars()
+                        .expect("const parameter types cannot be generic"),
                 )
                 .into(),
         }
@@ -1998,6 +2034,66 @@ impl<'tcx> TyCtxt<'tcx> {
         self.mk_alias(ty::Opaque, self.mk_alias_ty(def_id, substs))
     }
 
+    #[inline]
+    pub fn mk_re_early_bound(self, early_bound_region: ty::EarlyBoundRegion) -> Region<'tcx> {
+        self.intern_region(ty::ReEarlyBound(early_bound_region))
+    }
+
+    #[inline]
+    pub fn mk_re_late_bound(
+        self,
+        debruijn: ty::DebruijnIndex,
+        bound_region: ty::BoundRegion,
+    ) -> Region<'tcx> {
+        // Use a pre-interned one when possible.
+        if let ty::BoundRegion { var, kind: ty::BrAnon(v, None) } = bound_region
+            && var.as_u32() == v
+            && let Some(inner) = self.lifetimes.re_late_bounds.get(debruijn.as_usize())
+            && let Some(re) = inner.get(v as usize).copied()
+        {
+            re
+        } else {
+            self.intern_region(ty::ReLateBound(debruijn, bound_region))
+        }
+    }
+
+    #[inline]
+    pub fn mk_re_free(self, scope: DefId, bound_region: ty::BoundRegionKind) -> Region<'tcx> {
+        self.intern_region(ty::ReFree(ty::FreeRegion { scope, bound_region }))
+    }
+
+    #[inline]
+    pub fn mk_re_var(self, v: ty::RegionVid) -> Region<'tcx> {
+        // Use a pre-interned one when possible.
+        self.lifetimes
+            .re_vars
+            .get(v.as_usize())
+            .copied()
+            .unwrap_or_else(|| self.intern_region(ty::ReVar(v)))
+    }
+
+    #[inline]
+    pub fn mk_re_placeholder(self, placeholder: ty::PlaceholderRegion) -> Region<'tcx> {
+        self.intern_region(ty::RePlaceholder(placeholder))
+    }
+
+    // Avoid this in favour of more specific `mk_re_*` methods, where possible,
+    // to avoid the cost of the `match`.
+    pub fn mk_region(self, kind: ty::RegionKind<'tcx>) -> Region<'tcx> {
+        match kind {
+            ty::ReEarlyBound(region) => self.mk_re_early_bound(region),
+            ty::ReLateBound(debruijn, region) => self.mk_re_late_bound(debruijn, region),
+            ty::ReFree(ty::FreeRegion { scope, bound_region }) => {
+                self.mk_re_free(scope, bound_region)
+            }
+            ty::ReStatic => self.lifetimes.re_static,
+            ty::ReVar(vid) => self.mk_re_var(vid),
+            ty::RePlaceholder(region) => self.mk_re_placeholder(region),
+            ty::ReErased => self.lifetimes.re_erased,
+            ty::ReError(reported) => self.mk_re_error(reported),
+        }
+    }
+
     pub fn mk_place_field(self, place: Place<'tcx>, f: Field, ty: Ty<'tcx>) -> Place<'tcx> {
         self.mk_place_elem(place, PlaceElem::Field(f, ty))
     }
@@ -2065,11 +2161,12 @@ impl<'tcx> TyCtxt<'tcx> {
         }
     }
 
-    pub fn mk_const_list<I: InternAs<ty::Const<'tcx>, &'tcx List<ty::Const<'tcx>>>>(
-        self,
-        iter: I,
-    ) -> I::Output {
-        iter.intern_with(|xs| self.intern_const_list(xs))
+    pub fn mk_const_list<I, T>(self, iter: I) -> T::Output
+    where
+        I: Iterator<Item = T>,
+        T: CollectAndApply<ty::Const<'tcx>, &'tcx List<ty::Const<'tcx>>>,
+    {
+        T::collect_and_apply(iter, |xs| self.intern_const_list(xs))
     }
 
     pub fn intern_const_list(self, cs: &[ty::Const<'tcx>]) -> &'tcx List<ty::Const<'tcx>> {
@@ -2118,18 +2215,24 @@ impl<'tcx> TyCtxt<'tcx> {
         if ts.is_empty() { List::empty() } else { self._intern_bound_variable_kinds(ts) }
     }
 
-    pub fn mk_fn_sig<I>(
+    // Unlike various other `mk_*` functions, this one uses `I: IntoIterator`
+    // instead of `I: Iterator`. Unlike those other functions, this one doesn't
+    // have a `intern_fn_sig` variant that can be used for cases where `I` is
+    // something like a `Vec`. That's because of the need to combine `inputs`
+    // and `output`.
+    pub fn mk_fn_sig<I, T>(
         self,
         inputs: I,
         output: I::Item,
         c_variadic: bool,
         unsafety: hir::Unsafety,
         abi: abi::Abi,
-    ) -> <I::Item as InternIteratorElement<Ty<'tcx>, ty::FnSig<'tcx>>>::Output
+    ) -> T::Output
     where
-        I: Iterator<Item: InternIteratorElement<Ty<'tcx>, ty::FnSig<'tcx>>>,
+        I: IntoIterator<Item = T>,
+        T: CollectAndApply<Ty<'tcx>, ty::FnSig<'tcx>>,
     {
-        inputs.chain(iter::once(output)).intern_with(|xs| ty::FnSig {
+        T::collect_and_apply(inputs.into_iter().chain(iter::once(output)), |xs| ty::FnSig {
             inputs_and_output: self.intern_type_list(xs),
             c_variadic,
             unsafety,
@@ -2137,38 +2240,47 @@ impl<'tcx> TyCtxt<'tcx> {
         })
     }
 
-    pub fn mk_poly_existential_predicates<
-        I: InternAs<PolyExistentialPredicate<'tcx>, &'tcx List<PolyExistentialPredicate<'tcx>>>,
-    >(
-        self,
-        iter: I,
-    ) -> I::Output {
-        iter.intern_with(|xs| self.intern_poly_existential_predicates(xs))
+    pub fn mk_poly_existential_predicates<I, T>(self, iter: I) -> T::Output
+    where
+        I: Iterator<Item = T>,
+        T: CollectAndApply<
+                PolyExistentialPredicate<'tcx>,
+                &'tcx List<PolyExistentialPredicate<'tcx>>,
+            >,
+    {
+        T::collect_and_apply(iter, |xs| self.intern_poly_existential_predicates(xs))
     }
 
-    pub fn mk_predicates<I: InternAs<Predicate<'tcx>, &'tcx List<Predicate<'tcx>>>>(
-        self,
-        iter: I,
-    ) -> I::Output {
-        iter.intern_with(|xs| self.intern_predicates(xs))
+    pub fn mk_predicates<I, T>(self, iter: I) -> T::Output
+    where
+        I: Iterator<Item = T>,
+        T: CollectAndApply<Predicate<'tcx>, &'tcx List<Predicate<'tcx>>>,
+    {
+        T::collect_and_apply(iter, |xs| self.intern_predicates(xs))
     }
 
-    pub fn mk_type_list<I: InternAs<Ty<'tcx>, &'tcx List<Ty<'tcx>>>>(self, iter: I) -> I::Output {
-        iter.intern_with(|xs| self.intern_type_list(xs))
+    pub fn mk_type_list<I, T>(self, iter: I) -> T::Output
+    where
+        I: Iterator<Item = T>,
+        T: CollectAndApply<Ty<'tcx>, &'tcx List<Ty<'tcx>>>,
+    {
+        T::collect_and_apply(iter, |xs| self.intern_type_list(xs))
     }
 
-    pub fn mk_substs<I: InternAs<GenericArg<'tcx>, &'tcx List<GenericArg<'tcx>>>>(
-        self,
-        iter: I,
-    ) -> I::Output {
-        iter.intern_with(|xs| self.intern_substs(xs))
+    pub fn mk_substs<I, T>(self, iter: I) -> T::Output
+    where
+        I: Iterator<Item = T>,
+        T: CollectAndApply<GenericArg<'tcx>, &'tcx List<GenericArg<'tcx>>>,
+    {
+        T::collect_and_apply(iter, |xs| self.intern_substs(xs))
     }
 
-    pub fn mk_place_elems<I: InternAs<PlaceElem<'tcx>, &'tcx List<PlaceElem<'tcx>>>>(
-        self,
-        iter: I,
-    ) -> I::Output {
-        iter.intern_with(|xs| self.intern_place_elems(xs))
+    pub fn mk_place_elems<I, T>(self, iter: I) -> T::Output
+    where
+        I: Iterator<Item = T>,
+        T: CollectAndApply<PlaceElem<'tcx>, &'tcx List<PlaceElem<'tcx>>>,
+    {
+        T::collect_and_apply(iter, |xs| self.intern_place_elems(xs))
     }
 
     pub fn mk_substs_trait(
@@ -2197,13 +2309,12 @@ impl<'tcx> TyCtxt<'tcx> {
         ty::AliasTy { def_id, substs, _use_mk_alias_ty_instead: () }
     }
 
-    pub fn mk_bound_variable_kinds<
-        I: InternAs<ty::BoundVariableKind, &'tcx List<ty::BoundVariableKind>>,
-    >(
-        self,
-        iter: I,
-    ) -> I::Output {
-        iter.intern_with(|xs| self.intern_bound_variable_kinds(xs))
+    pub fn mk_bound_variable_kinds<I, T>(self, iter: I) -> T::Output
+    where
+        I: Iterator<Item = T>,
+        T: CollectAndApply<ty::BoundVariableKind, &'tcx List<ty::BoundVariableKind>>,
+    {
+        T::collect_and_apply(iter, |xs| self.intern_bound_variable_kinds(xs))
     }
 
     /// Emit a lint at `span` from a lint struct (some type that implements `DecorateLint`,
@@ -2278,9 +2389,9 @@ impl<'tcx> TyCtxt<'tcx> {
         Some(&*candidates)
     }
 
-    pub fn named_region(self, id: HirId) -> Option<resolve_lifetime::Region> {
+    pub fn named_bound_var(self, id: HirId) -> Option<resolve_bound_vars::ResolvedArg> {
         debug!(?id, "named_region");
-        self.named_region_map(id.owner).and_then(|map| map.get(&id.local_id).cloned())
+        self.named_variable_map(id.owner).and_then(|map| map.get(&id.local_id).cloned())
     }
 
     pub fn is_late_bound(self, id: HirId) -> bool {
@@ -2288,13 +2399,13 @@ impl<'tcx> TyCtxt<'tcx> {
     }
 
     pub fn late_bound_vars(self, id: HirId) -> &'tcx List<ty::BoundVariableKind> {
-        self.mk_bound_variable_kinds(
-            self.late_bound_vars_map(id.owner)
+        self.intern_bound_variable_kinds(
+            &self
+                .late_bound_vars_map(id.owner)
                 .and_then(|map| map.get(&id.local_id).cloned())
                 .unwrap_or_else(|| {
                     bug!("No bound vars found for {}", self.hir().node_to_string(id))
-                })
-                .iter(),
+                }),
         )
     }
 
diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs
index fc529f5d1d0..a029c1b209d 100644
--- a/compiler/rustc_middle/src/ty/diagnostics.rs
+++ b/compiler/rustc_middle/src/ty/diagnostics.rs
@@ -481,8 +481,9 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for IsSuggestableVisitor<'tcx> {
 
             Alias(Opaque, AliasTy { def_id, .. }) => {
                 let parent = self.tcx.parent(def_id);
+                let parent_ty = self.tcx.type_of(parent).subst_identity();
                 if let DefKind::TyAlias | DefKind::AssocTy = self.tcx.def_kind(parent)
-                    && let Alias(Opaque, AliasTy { def_id: parent_opaque_def_id, .. }) = *self.tcx.type_of(parent).kind()
+                    && let Alias(Opaque, AliasTy { def_id: parent_opaque_def_id, .. }) = *parent_ty.kind()
                     && parent_opaque_def_id == def_id
                 {
                     // Okay
@@ -564,8 +565,9 @@ impl<'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for MakeSuggestableFolder<'tcx> {
 
             Alias(Opaque, AliasTy { def_id, .. }) => {
                 let parent = self.tcx.parent(def_id);
+                let parent_ty = self.tcx.type_of(parent).subst_identity();
                 if let hir::def::DefKind::TyAlias | hir::def::DefKind::AssocTy = self.tcx.def_kind(parent)
-                    && let Alias(Opaque, AliasTy { def_id: parent_opaque_def_id, .. }) = *self.tcx.type_of(parent).kind()
+                    && let Alias(Opaque, AliasTy { def_id: parent_opaque_def_id, .. }) = *parent_ty.kind()
                     && parent_opaque_def_id == def_id
                 {
                     t
diff --git a/compiler/rustc_middle/src/ty/fast_reject.rs b/compiler/rustc_middle/src/ty/fast_reject.rs
index 9afa37e9ef3..106ce9990e1 100644
--- a/compiler/rustc_middle/src/ty/fast_reject.rs
+++ b/compiler/rustc_middle/src/ty/fast_reject.rs
@@ -290,7 +290,7 @@ impl DeepRejectCtxt {
             // Impls cannot contain these types as these cannot be named directly.
             ty::FnDef(..) | ty::Closure(..) | ty::Generator(..) => false,
 
-            ty::Placeholder(..) => false,
+            ty::Placeholder(..) | ty::Bound(..) => false,
 
             // Depending on the value of `treat_obligation_params`, we either
             // treat generic parameters like placeholders or like inference variables.
@@ -310,7 +310,7 @@ impl DeepRejectCtxt {
 
             ty::Error(_) => true,
 
-            ty::GeneratorWitness(..) | ty::GeneratorWitnessMIR(..) | ty::Bound(..) => {
+            ty::GeneratorWitness(..) | ty::GeneratorWitnessMIR(..) => {
                 bug!("unexpected obligation type: {:?}", obligation_ty)
             }
         }
diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs
index c9aa0ec66d5..91241ff404f 100644
--- a/compiler/rustc_middle/src/ty/flags.rs
+++ b/compiler/rustc_middle/src/ty/flags.rs
@@ -251,6 +251,10 @@ impl FlagComputation {
                 self.add_ty(ty);
                 self.add_region(region);
             }
+            ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(ct, ty)) => {
+                self.add_const(ct);
+                self.add_ty(ty);
+            }
             ty::PredicateKind::Subtype(ty::SubtypePredicate { a_is_expected: _, a, b }) => {
                 self.add_ty(a);
                 self.add_ty(b);
diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs
index 352daa8fc29..ee36e60bff1 100644
--- a/compiler/rustc_middle/src/ty/fold.rs
+++ b/compiler/rustc_middle/src/ty/fold.rs
@@ -234,7 +234,7 @@ where
                     // debruijn index. Then we adjust it to the
                     // correct depth.
                     assert_eq!(debruijn1, ty::INNERMOST);
-                    self.tcx.reuse_or_mk_region(region, ty::ReLateBound(debruijn, br))
+                    self.tcx.mk_re_late_bound(debruijn, br)
                 } else {
                     region
                 }
@@ -349,10 +349,7 @@ impl<'tcx> TyCtxt<'tcx> {
         T: TypeFoldable<'tcx>,
     {
         self.replace_late_bound_regions_uncached(value, |br| {
-            self.mk_region(ty::ReFree(ty::FreeRegion {
-                scope: all_outlive_scope,
-                bound_region: br.kind,
-            }))
+            self.mk_re_free(all_outlive_scope, br.kind)
         })
     }
 
@@ -365,10 +362,10 @@ impl<'tcx> TyCtxt<'tcx> {
             value,
             FnMutDelegate {
                 regions: &mut |r: ty::BoundRegion| {
-                    self.mk_region(ty::ReLateBound(
+                    self.mk_re_late_bound(
                         ty::INNERMOST,
                         ty::BoundRegion { var: shift_bv(r.var), kind: r.kind },
-                    ))
+                    )
                 },
                 types: &mut |t: ty::BoundTy| {
                     self.mk_bound(ty::INNERMOST, ty::BoundTy { var: shift_bv(t.var), kind: t.kind })
@@ -409,7 +406,7 @@ impl<'tcx> TyCtxt<'tcx> {
                     })
                     .expect_region();
                 let br = ty::BoundRegion { var, kind };
-                self.tcx.mk_region(ty::ReLateBound(ty::INNERMOST, br))
+                self.tcx.mk_re_late_bound(ty::INNERMOST, br)
             }
             fn replace_ty(&mut self, bt: ty::BoundTy) -> Ty<'tcx> {
                 let entry = self.map.entry(bt.var);
@@ -479,8 +476,7 @@ impl<'tcx> ir::TypeFolder<TyCtxt<'tcx>> for Shifter<'tcx> {
         match *r {
             ty::ReLateBound(debruijn, br) if debruijn >= self.current_index => {
                 let debruijn = debruijn.shifted_in(self.amount);
-                let shifted = ty::ReLateBound(debruijn, br);
-                self.tcx.mk_region(shifted)
+                self.tcx.mk_re_late_bound(debruijn, br)
             }
             _ => r,
         }
@@ -521,7 +517,7 @@ pub fn shift_region<'tcx>(
 ) -> ty::Region<'tcx> {
     match *region {
         ty::ReLateBound(debruijn, br) if amount > 0 => {
-            tcx.mk_region(ty::ReLateBound(debruijn.shifted_in(amount), br))
+            tcx.mk_re_late_bound(debruijn.shifted_in(amount), br)
         }
         _ => region,
     }
diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs
index ea95a38f272..35c036fef2d 100644
--- a/compiler/rustc_middle/src/ty/generics.rs
+++ b/compiler/rustc_middle/src/ty/generics.rs
@@ -85,7 +85,7 @@ impl GenericParamDef {
     ) -> Option<EarlyBinder<ty::GenericArg<'tcx>>> {
         match self.kind {
             GenericParamDefKind::Type { has_default, .. } if has_default => {
-                Some(tcx.bound_type_of(self.def_id).map_bound(|t| t.into()))
+                Some(tcx.type_of(self.def_id).map_bound(|t| t.into()))
             }
             GenericParamDefKind::Const { has_default } if has_default => {
                 Some(tcx.const_param_default(self.def_id).map_bound(|c| c.into()))
@@ -100,10 +100,10 @@ impl GenericParamDef {
         preceding_substs: &[ty::GenericArg<'tcx>],
     ) -> ty::GenericArg<'tcx> {
         match &self.kind {
-            ty::GenericParamDefKind::Lifetime => tcx.re_error_misc().into(),
+            ty::GenericParamDefKind::Lifetime => tcx.mk_re_error_misc().into(),
             ty::GenericParamDefKind::Type { .. } => tcx.ty_error().into(),
             ty::GenericParamDefKind::Const { .. } => {
-                tcx.const_error(tcx.bound_type_of(self.def_id).subst(tcx, preceding_substs)).into()
+                tcx.const_error(tcx.type_of(self.def_id).subst(tcx, preceding_substs)).into()
             }
         }
     }
diff --git a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs
index 690c0d58e01..355b8d8b431 100644
--- a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs
+++ b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs
@@ -87,7 +87,7 @@ impl<'tcx> VariantDef {
         InhabitedPredicate::all(
             tcx,
             self.fields.iter().map(|field| {
-                let pred = tcx.type_of(field.did).inhabited_predicate(tcx);
+                let pred = tcx.type_of(field.did).subst_identity().inhabited_predicate(tcx);
                 if adt.is_enum() {
                     return pred;
                 }
diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs
index 55f2395e531..c68a344e92c 100644
--- a/compiler/rustc_middle/src/ty/instance.rs
+++ b/compiler/rustc_middle/src/ty/instance.rs
@@ -103,7 +103,7 @@ impl<'tcx> Instance<'tcx> {
     /// 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> {
         let ty = tcx.type_of(self.def.def_id());
-        tcx.subst_and_normalize_erasing_regions(self.substs, param_env, ty)
+        tcx.subst_and_normalize_erasing_regions(self.substs, param_env, ty.skip_binder())
     }
 
     /// Finds a crate that contains a monomorphization of this instance that
@@ -584,7 +584,7 @@ impl<'tcx> Instance<'tcx> {
     /// this function returns `None`, then the MIR body does not require substitution during
     /// codegen.
     fn substs_for_mir_body(&self) -> Option<SubstsRef<'tcx>> {
-        if self.def.has_polymorphic_mir_body() { Some(self.substs) } else { None }
+        self.def.has_polymorphic_mir_body().then_some(self.substs)
     }
 
     pub fn subst_mir<T>(&self, tcx: TyCtxt<'tcx>, v: &T) -> T
@@ -662,7 +662,7 @@ fn polymorphize<'tcx>(
     let def_id = instance.def_id();
     let upvars_ty = if tcx.is_closure(def_id) {
         Some(substs.as_closure().tupled_upvars_ty())
-    } else if tcx.type_of(def_id).is_generator() {
+    } else if tcx.type_of(def_id).skip_binder().is_generator() {
         Some(substs.as_generator().tupled_upvars_ty())
     } else {
         None
diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs
index 1d76f435e26..3d0f9a5053c 100644
--- a/compiler/rustc_middle/src/ty/layout.rs
+++ b/compiler/rustc_middle/src/ty/layout.rs
@@ -686,7 +686,7 @@ where
                         Increase this counter if you tried to implement this but
                         failed to do it without duplicating a lot of code from
                         other places in the compiler: 2
-                        tcx.mk_tup(&[
+                        tcx.intern_tup(&[
                             tcx.mk_array(tcx.types.usize, 3),
                             tcx.mk_array(Option<fn()>),
                         ])
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index a1b5eaed2f1..1dc27ce8dae 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -552,6 +552,7 @@ impl<'tcx> Predicate<'tcx> {
             | PredicateKind::Clause(Clause::RegionOutlives(_))
             | PredicateKind::Clause(Clause::TypeOutlives(_))
             | PredicateKind::Clause(Clause::Projection(_))
+            | PredicateKind::Clause(Clause::ConstArgHasType(..))
             | PredicateKind::AliasEq(..)
             | PredicateKind::ObjectSafe(_)
             | PredicateKind::ClosureKind(_, _, _)
@@ -590,6 +591,10 @@ pub enum Clause<'tcx> {
     /// `where <T as TraitRef>::Name == X`, approximately.
     /// See the `ProjectionPredicate` struct for details.
     Projection(ProjectionPredicate<'tcx>),
+
+    /// Ensures that a const generic argument to a parameter `const N: u8`
+    /// is of type `u8`.
+    ConstArgHasType(Const<'tcx>, Ty<'tcx>),
 }
 
 #[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
@@ -1193,6 +1198,7 @@ impl<'tcx> Predicate<'tcx> {
         match predicate.skip_binder() {
             PredicateKind::Clause(Clause::Trait(t)) => Some(predicate.rebind(t)),
             PredicateKind::Clause(Clause::Projection(..))
+            | PredicateKind::Clause(Clause::ConstArgHasType(..))
             | PredicateKind::AliasEq(..)
             | PredicateKind::Subtype(..)
             | PredicateKind::Coerce(..)
@@ -1213,6 +1219,7 @@ impl<'tcx> Predicate<'tcx> {
         match predicate.skip_binder() {
             PredicateKind::Clause(Clause::Projection(t)) => Some(predicate.rebind(t)),
             PredicateKind::Clause(Clause::Trait(..))
+            | PredicateKind::Clause(Clause::ConstArgHasType(..))
             | PredicateKind::AliasEq(..)
             | PredicateKind::Subtype(..)
             | PredicateKind::Coerce(..)
@@ -1233,6 +1240,7 @@ impl<'tcx> Predicate<'tcx> {
         match predicate.skip_binder() {
             PredicateKind::Clause(Clause::TypeOutlives(data)) => Some(predicate.rebind(data)),
             PredicateKind::Clause(Clause::Trait(..))
+            | PredicateKind::Clause(Clause::ConstArgHasType(..))
             | PredicateKind::Clause(Clause::Projection(..))
             | PredicateKind::AliasEq(..)
             | PredicateKind::Subtype(..)
@@ -2017,7 +2025,7 @@ impl<'tcx> FieldDef {
     /// Returns the type of this field. The resulting type is not normalized. The `subst` is
     /// typically obtained via the second field of [`TyKind::Adt`].
     pub fn ty(&self, tcx: TyCtxt<'tcx>, subst: SubstsRef<'tcx>) -> Ty<'tcx> {
-        tcx.bound_type_of(self.did).subst(tcx, subst)
+        tcx.type_of(self.did).subst(tcx, subst)
     }
 
     /// Computes the `Ident` of this variant by looking up the `Span`
@@ -2198,7 +2206,7 @@ impl<'tcx> TyCtxt<'tcx> {
         Some(Ident::new(def, span))
     }
 
-    pub fn opt_associated_item(self, def_id: DefId) -> Option<&'tcx AssocItem> {
+    pub fn opt_associated_item(self, def_id: DefId) -> Option<AssocItem> {
         if let DefKind::AssocConst | DefKind::AssocFn | DefKind::AssocTy = self.def_kind(def_id) {
             Some(self.associated_item(def_id))
         } else {
diff --git a/compiler/rustc_middle/src/ty/opaque_types.rs b/compiler/rustc_middle/src/ty/opaque_types.rs
index 66c878c8b63..8aeef4684b3 100644
--- a/compiler/rustc_middle/src/ty/opaque_types.rs
+++ b/compiler/rustc_middle/src/ty/opaque_types.rs
@@ -143,7 +143,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ReverseMapper<'tcx> {
                     )
                     .emit();
 
-                self.interner().re_error(e)
+                self.interner().mk_re_error(e)
             }
         }
     }
diff --git a/compiler/rustc_middle/src/ty/parameterized.rs b/compiler/rustc_middle/src/ty/parameterized.rs
index 303675d3ca5..8849e7eab33 100644
--- a/compiler/rustc_middle/src/ty/parameterized.rs
+++ b/compiler/rustc_middle/src/ty/parameterized.rs
@@ -57,7 +57,7 @@ trivially_parameterized_over_tcx! {
     crate::metadata::ModChild,
     crate::middle::codegen_fn_attrs::CodegenFnAttrs,
     crate::middle::exported_symbols::SymbolExportInfo,
-    crate::middle::resolve_lifetime::ObjectLifetimeDefault,
+    crate::middle::resolve_bound_vars::ObjectLifetimeDefault,
     crate::mir::ConstQualifs,
     ty::AssocItemContainer,
     ty::DeducedParamAttrs,
diff --git a/compiler/rustc_middle/src/ty/print/mod.rs b/compiler/rustc_middle/src/ty/print/mod.rs
index 90bf3288ccf..021c20b5854 100644
--- a/compiler/rustc_middle/src/ty/print/mod.rs
+++ b/compiler/rustc_middle/src/ty/print/mod.rs
@@ -115,7 +115,7 @@ pub trait Printer<'tcx>: Sized {
 
             DefPathData::Impl => {
                 let generics = self.tcx().generics_of(def_id);
-                let self_ty = self.tcx().bound_type_of(def_id);
+                let self_ty = self.tcx().type_of(def_id);
                 let impl_trait_ref = self.tcx().impl_trait_ref(def_id);
                 let (self_ty, impl_trait_ref) = if substs.len() >= generics.count() {
                     (
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index f50a5d89d3d..1e59983583b 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -182,7 +182,7 @@ impl<'tcx> RegionHighlightMode<'tcx> {
 
     /// Convenience wrapper for `highlighting_region`.
     pub fn highlighting_region_vid(&mut self, vid: ty::RegionVid, number: usize) {
-        self.highlighting_region(self.tcx.mk_region(ty::ReVar(vid)), number)
+        self.highlighting_region(self.tcx.mk_re_var(vid), number)
     }
 
     /// Returns `Some(n)` with the number to use for the given region, if any.
@@ -754,7 +754,7 @@ pub trait PrettyPrinter<'tcx>:
                         // NOTE: I know we should check for NO_QUERIES here, but it's alright.
                         // `type_of` on a type alias or assoc type should never cause a cycle.
                         if let ty::Alias(ty::Opaque, ty::AliasTy { def_id: d, .. }) =
-                            *self.tcx().type_of(parent).kind()
+                            *self.tcx().type_of(parent).subst_identity().kind()
                         {
                             if d == def_id {
                                 // If the type alias directly starts with the `impl` of the
@@ -2271,7 +2271,7 @@ impl<'a, 'tcx> ty::ir::TypeFolder<TyCtxt<'tcx>> for RegionFolder<'a, 'tcx> {
         };
         if let ty::ReLateBound(debruijn1, br) = *region {
             assert_eq!(debruijn1, ty::INNERMOST);
-            self.tcx.mk_region(ty::ReLateBound(self.current_index, br))
+            self.tcx.mk_re_late_bound(self.current_index, br)
         } else {
             region
         }
@@ -2383,10 +2383,10 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
                         if let Some(lt_idx) = lifetime_idx {
                             if lt_idx > binder_level_idx {
                                 let kind = ty::BrNamed(CRATE_DEF_ID.to_def_id(), name);
-                                return tcx.mk_region(ty::ReLateBound(
+                                return tcx.mk_re_late_bound(
                                     ty::INNERMOST,
                                     ty::BoundRegion { var: br.var, kind },
-                                ));
+                                );
                             }
                         }
 
@@ -2398,10 +2398,10 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
                         if let Some(lt_idx) = lifetime_idx {
                             if lt_idx > binder_level_idx {
                                 let kind = ty::BrNamed(def_id, name);
-                                return tcx.mk_region(ty::ReLateBound(
+                                return tcx.mk_re_late_bound(
                                     ty::INNERMOST,
                                     ty::BoundRegion { var: br.var, kind },
-                                ));
+                                );
                             }
                         }
 
@@ -2411,10 +2411,10 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
                         if let Some(lt_idx) = lifetime_idx {
                             if lt_idx > binder_level_idx {
                                 let kind = br.kind;
-                                return tcx.mk_region(ty::ReLateBound(
+                                return tcx.mk_re_late_bound(
                                     ty::INNERMOST,
                                     ty::BoundRegion { var: br.var, kind },
-                                ));
+                                );
                             }
                         }
 
@@ -2426,7 +2426,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
                     start_or_continue(&mut self, "for<", ", ");
                     do_continue(&mut self, name);
                 }
-                tcx.mk_region(ty::ReLateBound(ty::INNERMOST, ty::BoundRegion { var: br.var, kind }))
+                tcx.mk_re_late_bound(ty::INNERMOST, ty::BoundRegion { var: br.var, kind })
             };
             let mut folder = RegionFolder {
                 tcx,
@@ -2822,15 +2822,18 @@ define_print_and_forward_display! {
             ty::PredicateKind::Clause(ty::Clause::RegionOutlives(predicate)) => p!(print(predicate)),
             ty::PredicateKind::Clause(ty::Clause::TypeOutlives(predicate)) => p!(print(predicate)),
             ty::PredicateKind::Clause(ty::Clause::Projection(predicate)) => p!(print(predicate)),
+            ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(ct, ty)) => {
+                p!("the constant `", print(ct), "` has type `", print(ty), "`")
+            },
             ty::PredicateKind::WellFormed(arg) => p!(print(arg), " well-formed"),
             ty::PredicateKind::ObjectSafe(trait_def_id) => {
                 p!("the trait `", print_def_path(trait_def_id, &[]), "` is object-safe")
             }
-            ty::PredicateKind::ClosureKind(closure_def_id, _closure_substs, kind) => {
-                p!("the closure `",
+            ty::PredicateKind::ClosureKind(closure_def_id, _closure_substs, kind) => p!(
+                "the closure `",
                 print_value_path(closure_def_id, &[]),
-                write("` implements the trait `{}`", kind))
-            }
+                write("` implements the trait `{}`", kind)
+            ),
             ty::PredicateKind::ConstEvaluatable(ct) => {
                 p!("the constant `", print(ct), "` can be evaluated")
             }
diff --git a/compiler/rustc_middle/src/ty/query.rs b/compiler/rustc_middle/src/ty/query.rs
index ed54aa96f5b..5b3f3870429 100644
--- a/compiler/rustc_middle/src/ty/query.rs
+++ b/compiler/rustc_middle/src/ty/query.rs
@@ -1,3 +1,5 @@
+#![allow(unused_parens)]
+
 use crate::dep_graph;
 use crate::infer::canonical::{self, Canonical};
 use crate::lint::LintExpectation;
@@ -6,7 +8,7 @@ use crate::middle::codegen_fn_attrs::CodegenFnAttrs;
 use crate::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo};
 use crate::middle::lib_features::LibFeatures;
 use crate::middle::privacy::EffectiveVisibilities;
-use crate::middle::resolve_lifetime::{ObjectLifetimeDefault, Region, ResolveLifetimes};
+use crate::middle::resolve_bound_vars::{ObjectLifetimeDefault, ResolveBoundVars, ResolvedArg};
 use crate::middle::stability::{self, DeprecationEntry};
 use crate::mir;
 use crate::mir::interpret::GlobalId;
@@ -34,6 +36,7 @@ use crate::ty::subst::{GenericArg, SubstsRef};
 use crate::ty::util::AlwaysRequiresDrop;
 use crate::ty::GeneratorDiagnosticData;
 use crate::ty::{self, CrateInherentImpls, ParamEnvAnd, Ty, TyCtxt, UnusedGenericParams};
+use rustc_arena::TypedArena;
 use rustc_ast as ast;
 use rustc_ast::expand::allocator::AllocatorKind;
 use rustc_attr as attr;
@@ -41,6 +44,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet};
 use rustc_data_structures::steal::Steal;
 use rustc_data_structures::svh::Svh;
 use rustc_data_structures::sync::Lrc;
+use rustc_data_structures::sync::WorkerLocal;
 use rustc_data_structures::unord::UnordSet;
 use rustc_errors::ErrorGuaranteed;
 use rustc_hir as hir;
@@ -59,6 +63,7 @@ use rustc_span::symbol::Symbol;
 use rustc_span::{Span, DUMMY_SP};
 use rustc_target::abi;
 use rustc_target::spec::PanicStrategy;
+use std::mem;
 use std::ops::Deref;
 use std::path::PathBuf;
 use std::sync::Arc;
@@ -66,6 +71,12 @@ use std::sync::Arc;
 pub(crate) use rustc_query_system::query::QueryJobId;
 use rustc_query_system::query::*;
 
+#[derive(Default)]
+pub struct QuerySystem<'tcx> {
+    pub arenas: QueryArenas<'tcx>,
+    pub caches: QueryCaches<'tcx>,
+}
+
 #[derive(Copy, Clone)]
 pub struct TyCtxtAt<'tcx> {
     pub tcx: TyCtxt<'tcx>,
@@ -112,10 +123,10 @@ macro_rules! query_helper_param_ty {
 }
 
 macro_rules! query_if_arena {
-    ([] $arena:ty, $no_arena:ty) => {
+    ([] $arena:tt $no_arena:tt) => {
         $no_arena
     };
-    ([(arena_cache) $($rest:tt)*] $arena:ty, $no_arena:ty) => {
+    ([(arena_cache) $($rest:tt)*] $arena:tt $no_arena:tt) => {
         $arena
     };
     ([$other:tt $($modifiers:tt)*]$($args:tt)*) => {
@@ -131,7 +142,7 @@ macro_rules! separate_provide_extern_decl {
         for<'tcx> fn(
             TyCtxt<'tcx>,
             query_keys::$name<'tcx>,
-        ) -> query_values::$name<'tcx>
+        ) -> query_provided::$name<'tcx>
     };
     ([$other:tt $($modifiers:tt)*][$($args:tt)*]) => {
         separate_provide_extern_decl!([$($modifiers)*][$($args)*])
@@ -183,30 +194,77 @@ macro_rules! define_callbacks {
 
             $(pub type $name<'tcx> = $($K)*;)*
         }
-        #[allow(nonstandard_style, unused_lifetimes, unused_parens)]
+        #[allow(nonstandard_style, unused_lifetimes)]
         pub mod query_values {
             use super::*;
 
-            $(pub type $name<'tcx> = query_if_arena!([$($modifiers)*] <$V as Deref>::Target, $V);)*
+            $(pub type $name<'tcx> = $V;)*
         }
-        #[allow(nonstandard_style, unused_lifetimes, unused_parens)]
-        pub mod query_storage {
+
+        /// This module specifies the type returned from query providers and the type used for
+        /// decoding. For regular queries this is the declared returned type `V`, but
+        /// `arena_cache` will use `<V as Deref>::Target` instead.
+        #[allow(nonstandard_style, unused_lifetimes)]
+        pub mod query_provided {
             use super::*;
 
             $(
-                pub type $name<'tcx> = query_if_arena!([$($modifiers)*]
-                    <<$($K)* as Key>::CacheSelector
-                        as CacheSelector<'tcx, <$V as Deref>::Target>>::ArenaCache,
-                    <<$($K)* as Key>::CacheSelector as CacheSelector<'tcx, $V>>::Cache
-                );
+                pub type $name<'tcx> = query_if_arena!([$($modifiers)*] (<$V as Deref>::Target) ($V));
             )*
         }
 
+        /// This module has a function per query which takes a `query_provided` value and coverts
+        /// it to a regular `V` value by allocating it on an arena if the query has the
+        /// `arena_cache` modifier. This will happen when computing the query using a provider or
+        /// decoding a stored result.
         #[allow(nonstandard_style, unused_lifetimes)]
-        pub mod query_stored {
+        pub mod query_provided_to_value {
             use super::*;
 
-            $(pub type $name<'tcx> = $V;)*
+            $(
+                #[inline(always)]
+                pub fn $name<'tcx>(
+                    _tcx: TyCtxt<'tcx>,
+                    value: query_provided::$name<'tcx>,
+                ) -> query_values::$name<'tcx> {
+                    query_if_arena!([$($modifiers)*]
+                        {
+                            if mem::needs_drop::<query_provided::$name<'tcx>>() {
+                                &*_tcx.query_system.arenas.$name.alloc(value)
+                            } else {
+                                &*_tcx.arena.dropless.alloc(value)
+                            }
+                        }
+                        (value)
+                    )
+                }
+            )*
+        }
+        #[allow(nonstandard_style, unused_lifetimes)]
+        pub mod query_storage {
+            use super::*;
+
+            $(
+                pub type $name<'tcx> = <<$($K)* as Key>::CacheSelector as CacheSelector<'tcx, $V>>::Cache;
+            )*
+        }
+
+        pub struct QueryArenas<'tcx> {
+            $($(#[$attr])* pub $name: query_if_arena!([$($modifiers)*]
+                (WorkerLocal<TypedArena<<$V as Deref>::Target>>)
+                ()
+            ),)*
+        }
+
+        impl Default for QueryArenas<'_> {
+            fn default() -> Self {
+                Self {
+                    $($name: query_if_arena!([$($modifiers)*]
+                        (WorkerLocal::new(|_| Default::default()))
+                        ()
+                    ),)*
+                }
+            }
         }
 
         #[derive(Default)]
@@ -221,7 +279,7 @@ macro_rules! define_callbacks {
                 let key = key.into_query_param();
                 opt_remap_env_constness!([$($modifiers)*][key]);
 
-                match try_get_cached(self.tcx, &self.tcx.query_caches.$name, &key) {
+                match try_get_cached(self.tcx, &self.tcx.query_system.caches.$name, &key) {
                     Some(_) => return,
                     None => self.tcx.queries.$name(self.tcx, DUMMY_SP, key, QueryMode::Ensure),
                 };
@@ -246,7 +304,7 @@ macro_rules! define_callbacks {
                 let key = key.into_query_param();
                 opt_remap_env_constness!([$($modifiers)*][key]);
 
-                match try_get_cached(self.tcx, &self.tcx.query_caches.$name, &key) {
+                match try_get_cached(self.tcx, &self.tcx.query_system.caches.$name, &key) {
                     Some(value) => value,
                     None => self.tcx.queries.$name(self.tcx, self.span, key, QueryMode::Get).unwrap(),
                 }
@@ -257,7 +315,7 @@ macro_rules! define_callbacks {
             $(pub $name: for<'tcx> fn(
                 TyCtxt<'tcx>,
                 query_keys::$name<'tcx>,
-            ) -> query_values::$name<'tcx>,)*
+            ) -> query_provided::$name<'tcx>,)*
         }
 
         pub struct ExternProviders {
@@ -334,12 +392,13 @@ macro_rules! define_feedable {
         $(impl<'tcx, K: IntoQueryParam<$($K)*> + Copy> TyCtxtFeed<'tcx, K> {
             $(#[$attr])*
             #[inline(always)]
-            pub fn $name(self, value: query_values::$name<'tcx>) -> $V {
+            pub fn $name(self, value: query_provided::$name<'tcx>) -> $V {
                 let key = self.key().into_query_param();
                 opt_remap_env_constness!([$($modifiers)*][key]);
 
                 let tcx = self.tcx;
-                let cache = &tcx.query_caches.$name;
+                let value = query_provided_to_value::$name(tcx, value);
+                let cache = &tcx.query_system.caches.$name;
 
                 match try_get_cached(tcx, cache, &key) {
                     Some(old) => {
@@ -357,7 +416,8 @@ macro_rules! define_feedable {
                             &value,
                             hash_result!([$($modifiers)*]),
                         );
-                        cache.complete(key, value, dep_node_index)
+                        cache.complete(key, value, dep_node_index);
+                        value
                     }
                 }
             }
@@ -435,10 +495,6 @@ impl<'tcx> TyCtxt<'tcx> {
         self.opt_def_kind(def_id)
             .unwrap_or_else(|| bug!("def_kind: unsupported node: {:?}", def_id))
     }
-
-    pub fn bound_type_of(self, def_id: impl IntoQueryParam<DefId>) -> ty::EarlyBinder<Ty<'tcx>> {
-        ty::EarlyBinder(self.type_of(def_id))
-    }
 }
 
 impl<'tcx> TyCtxtAt<'tcx> {
@@ -447,8 +503,4 @@ impl<'tcx> TyCtxtAt<'tcx> {
         self.opt_def_kind(def_id)
             .unwrap_or_else(|| bug!("def_kind: unsupported node: {:?}", def_id))
     }
-
-    pub fn bound_type_of(self, def_id: impl IntoQueryParam<DefId>) -> ty::EarlyBinder<Ty<'tcx>> {
-        ty::EarlyBinder(self.type_of(def_id))
-    }
 }
diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs
index 33b509ec490..2ba25e8bfad 100644
--- a/compiler/rustc_middle/src/ty/relate.rs
+++ b/compiler/rustc_middle/src/ty/relate.rs
@@ -163,8 +163,7 @@ pub fn relate_substs_with_variances<'tcx, R: TypeRelation<'tcx>>(
     let params = iter::zip(a_subst, b_subst).enumerate().map(|(i, (a, b))| {
         let variance = variances[i];
         let variance_info = if variance == ty::Invariant && fetch_ty_for_diag {
-            let ty =
-                *cached_ty.get_or_insert_with(|| tcx.bound_type_of(ty_def_id).subst(tcx, a_subst));
+            let ty = *cached_ty.get_or_insert_with(|| tcx.type_of(ty_def_id).subst(tcx, a_subst));
             ty::VarianceDiagInfo::Invariant { ty, param_index: i.try_into().unwrap() }
         } else {
             ty::VarianceDiagInfo::default()
@@ -674,7 +673,7 @@ pub fn super_relate_consts<'tcx, R: TypeRelation<'tcx>>(
                     for (a_arg, b_arg) in aa.iter().zip(ba.iter()) {
                         related_args.push(r.consts(a_arg, b_arg)?);
                     }
-                    let related_args = tcx.mk_const_list(related_args.iter());
+                    let related_args = tcx.intern_const_list(&related_args);
                     Expr::FunctionCall(func, related_args)
                 }
                 _ => return Err(TypeError::ConstMismatch(expected_found(r, a, b))),
diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs
index 97ee2b1fc5d..573105fd8c0 100644
--- a/compiler/rustc_middle/src/ty/structural_impls.rs
+++ b/compiler/rustc_middle/src/ty/structural_impls.rs
@@ -147,6 +147,7 @@ impl<'tcx> fmt::Debug for ty::Predicate<'tcx> {
 impl<'tcx> fmt::Debug for ty::Clause<'tcx> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match *self {
+            ty::Clause::ConstArgHasType(ct, ty) => write!(f, "ConstArgHasType({ct:?}, {ty:?})"),
             ty::Clause::Trait(ref a) => a.fmt(f),
             ty::Clause::RegionOutlives(ref pair) => pair.fmt(f),
             ty::Clause::TypeOutlives(ref pair) => pair.fmt(f),
@@ -418,7 +419,7 @@ impl<'tcx> ir::TypeFoldable<TyCtxt<'tcx>> for &'tcx ty::List<ty::PolyExistential
 
 impl<'tcx> ir::TypeFoldable<TyCtxt<'tcx>> for &'tcx ty::List<ty::Const<'tcx>> {
     fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
-        ty::util::fold_list(self, folder, |tcx, v| tcx.mk_const_list(v.iter()))
+        ty::util::fold_list(self, folder, |tcx, v| tcx.intern_const_list(v))
     }
 }
 
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index c613b3627f2..f8d17433cf7 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -933,6 +933,12 @@ impl<'tcx> PolyExistentialTraitRef<'tcx> {
     }
 }
 
+impl rustc_errors::IntoDiagnosticArg for PolyExistentialTraitRef<'_> {
+    fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> {
+        self.to_string().into_diagnostic_arg()
+    }
+}
+
 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)]
 #[derive(HashStable)]
 pub enum BoundVariableKind {
@@ -1187,7 +1193,7 @@ impl<'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for SkipBindersAt<'tcx> {
             if index == self.index {
                 Err(())
             } else {
-                Ok(self.interner().mk_region(ty::ReLateBound(index.shifted_out(1), bv)))
+                Ok(self.interner().mk_re_late_bound(index.shifted_out(1), bv))
             }
         } else {
             r.try_super_fold_with(self)
@@ -2268,7 +2274,7 @@ impl<'tcx> Ty<'tcx> {
             ty::Str | ty::Slice(_) => (tcx.types.usize, false),
             ty::Dynamic(..) => {
                 let dyn_metadata = tcx.require_lang_item(LangItem::DynMetadata, None);
-                (tcx.bound_type_of(dyn_metadata).subst(tcx, &[tail.into()]), false)
+                (tcx.type_of(dyn_metadata).subst(tcx, &[tail.into()]), false)
             },
 
             // type parameters only have unit metadata if they're sized, so return true
diff --git a/compiler/rustc_middle/src/ty/subst.rs b/compiler/rustc_middle/src/ty/subst.rs
index a6ab7440c8e..6b4a6a17aef 100644
--- a/compiler/rustc_middle/src/ty/subst.rs
+++ b/compiler/rustc_middle/src/ty/subst.rs
@@ -267,13 +267,11 @@ pub type SubstsRef<'tcx> = &'tcx InternalSubsts<'tcx>;
 impl<'tcx> InternalSubsts<'tcx> {
     /// Checks whether all elements of this list are types, if so, transmute.
     pub fn try_as_type_list(&'tcx self) -> Option<&'tcx List<Ty<'tcx>>> {
-        if self.iter().all(|arg| matches!(arg.unpack(), GenericArgKind::Type(_))) {
+        self.iter().all(|arg| matches!(arg.unpack(), GenericArgKind::Type(_))).then(|| {
             assert_eq!(TYPE_TAG, 0);
             // SAFETY: All elements are types, see `List<Ty<'tcx>>::as_substs`.
-            Some(unsafe { &*(self as *const List<GenericArg<'tcx>> as *const List<Ty<'tcx>>) })
-        } else {
-            None
-        }
+            unsafe { &*(self as *const List<GenericArg<'tcx>> as *const List<Ty<'tcx>>) }
+        })
     }
 
     /// Interpret these substitutions as the substitutions of a closure type.
diff --git a/compiler/rustc_middle/src/ty/trait_def.rs b/compiler/rustc_middle/src/ty/trait_def.rs
index 71353acaaa7..a4a82bf247d 100644
--- a/compiler/rustc_middle/src/ty/trait_def.rs
+++ b/compiler/rustc_middle/src/ty/trait_def.rs
@@ -225,7 +225,7 @@ pub(super) fn trait_impls_of_provider(tcx: TyCtxt<'_>, trait_id: DefId) -> Trait
     for &impl_def_id in tcx.hir().trait_impls(trait_id) {
         let impl_def_id = impl_def_id.to_def_id();
 
-        let impl_self_ty = tcx.type_of(impl_def_id);
+        let impl_self_ty = tcx.type_of(impl_def_id).subst_identity();
         if impl_self_ty.references_error() {
             continue;
         }
diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs
index 35831ff8706..a34ee1a99a1 100644
--- a/compiler/rustc_middle/src/ty/util.rs
+++ b/compiler/rustc_middle/src/ty/util.rs
@@ -362,7 +362,7 @@ impl<'tcx> TyCtxt<'tcx> {
         let drop_trait = self.lang_items().drop_trait()?;
         self.ensure().coherent_trait(drop_trait);
 
-        let ty = self.type_of(adt_did);
+        let ty = self.type_of(adt_did).subst_identity();
         let (did, constness) = self.find_map_relevant_impl(drop_trait, ty, |impl_did| {
             if let Some(item_id) = self.associated_item_def_ids(impl_did).first() {
                 if validate(self, impl_did).is_ok() {
@@ -415,12 +415,12 @@ impl<'tcx> TyCtxt<'tcx> {
         // <P1, P2, P0>, and then look up which of the impl substs refer to
         // parameters marked as pure.
 
-        let impl_substs = match *self.type_of(impl_def_id).kind() {
+        let impl_substs = match *self.type_of(impl_def_id).subst_identity().kind() {
             ty::Adt(def_, substs) if def_ == def => substs,
             _ => bug!(),
         };
 
-        let item_substs = match *self.type_of(def.did()).kind() {
+        let item_substs = match *self.type_of(def.did()).subst_identity().kind() {
             ty::Adt(def_, substs) if def_ == def => substs,
             _ => bug!(),
         };
@@ -564,14 +564,14 @@ impl<'tcx> TyCtxt<'tcx> {
         self,
         closure_def_id: DefId,
         closure_substs: SubstsRef<'tcx>,
-        env_region: ty::RegionKind<'tcx>,
+        env_region: ty::Region<'tcx>,
     ) -> Option<Ty<'tcx>> {
         let closure_ty = self.mk_closure(closure_def_id, closure_substs);
         let closure_kind_ty = closure_substs.as_closure().kind_ty();
         let closure_kind = closure_kind_ty.to_opt_closure_kind()?;
         let env_ty = match closure_kind {
-            ty::ClosureKind::Fn => self.mk_imm_ref(self.mk_region(env_region), closure_ty),
-            ty::ClosureKind::FnMut => self.mk_mut_ref(self.mk_region(env_region), closure_ty),
+            ty::ClosureKind::Fn => self.mk_imm_ref(env_region, closure_ty),
+            ty::ClosureKind::FnMut => self.mk_mut_ref(env_region, closure_ty),
             ty::ClosureKind::FnOnce => closure_ty,
         };
         Some(env_ty)
@@ -602,7 +602,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> {
         // 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));
+        let static_ty = self.normalize_erasing_regions(
+            ty::ParamEnv::empty(),
+            self.type_of(def_id).subst_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`.
@@ -790,7 +793,7 @@ impl<'tcx> OpaqueTypeExpander<'tcx> {
             let expanded_ty = match self.expanded_cache.get(&(def_id, substs)) {
                 Some(expanded_ty) => *expanded_ty,
                 None => {
-                    let generic_ty = self.tcx.bound_type_of(def_id);
+                    let generic_ty = self.tcx.type_of(def_id);
                     let concrete_ty = generic_ty.subst(self.tcx, substs);
                     let expanded_ty = self.fold_ty(concrete_ty);
                     self.expanded_cache.insert((def_id, substs), expanded_ty);
diff --git a/compiler/rustc_mir_build/src/build/expr/into.rs b/compiler/rustc_mir_build/src/build/expr/into.rs
index 38b1fa91d0a..dac9bf0a883 100644
--- a/compiler/rustc_mir_build/src/build/expr/into.rs
+++ b/compiler/rustc_mir_build/src/build/expr/into.rs
@@ -319,7 +319,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 // See the notes for `ExprKind::Array` in `as_rvalue` and for
                 // `ExprKind::Borrow` above.
                 let is_union = adt_def.is_union();
-                let active_field_index = if is_union { Some(fields[0].name.index()) } else { None };
+                let active_field_index = is_union.then(|| fields[0].name.index());
 
                 let scope = this.local_scope();
 
diff --git a/compiler/rustc_mir_build/src/build/matches/test.rs b/compiler/rustc_mir_build/src/build/matches/test.rs
index ad7a568a231..8859f5002e4 100644
--- a/compiler/rustc_mir_build/src/build/matches/test.rs
+++ b/compiler/rustc_mir_build/src/build/matches/test.rs
@@ -563,14 +563,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 let not_contained =
                     self.values_not_contained_in_range(&*range, options).unwrap_or(false);
 
-                if not_contained {
+                not_contained.then(|| {
                     // No switch values are contained in the pattern range,
                     // so the pattern can be matched only if this test fails.
-                    let otherwise = options.len();
-                    Some(otherwise)
-                } else {
-                    None
-                }
+                    options.len()
+                })
             }
 
             (&TestKind::SwitchInt { .. }, _) => None,
diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs
index 1655e224ddb..933b1158fa6 100644
--- a/compiler/rustc_mir_build/src/build/mod.rs
+++ b/compiler/rustc_mir_build/src/build/mod.rs
@@ -643,7 +643,7 @@ fn construct_error(
     let num_params = match body_owner_kind {
         hir::BodyOwnerKind::Fn => tcx.fn_sig(def).skip_binder().inputs().skip_binder().len(),
         hir::BodyOwnerKind::Closure => {
-            let ty = tcx.type_of(def);
+            let ty = tcx.type_of(def).subst_identity();
             match ty.kind() {
                 ty::Closure(_, substs) => {
                     1 + substs.as_closure().sig().inputs().skip_binder().len()
diff --git a/compiler/rustc_mir_build/src/thir/cx/mod.rs b/compiler/rustc_mir_build/src/thir/cx/mod.rs
index 10df4b22952..74c35ef0fc2 100644
--- a/compiler/rustc_mir_build/src/thir/cx/mod.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/mod.rs
@@ -133,14 +133,14 @@ impl<'tcx> Cx<'tcx> {
                     bug!("closure expr does not have closure type: {:?}", closure_ty);
                 };
 
-                let bound_vars = self.tcx.mk_bound_variable_kinds(std::iter::once(
-                    ty::BoundVariableKind::Region(ty::BrEnv),
-                ));
+                let bound_vars = self
+                    .tcx
+                    .intern_bound_variable_kinds(&[ty::BoundVariableKind::Region(ty::BrEnv)]);
                 let br = ty::BoundRegion {
                     var: ty::BoundVar::from_usize(bound_vars.len() - 1),
                     kind: ty::BrEnv,
                 };
-                let env_region = ty::ReLateBound(ty::INNERMOST, br);
+                let env_region = self.tcx.mk_re_late_bound(ty::INNERMOST, br);
                 let closure_env_ty =
                     self.tcx.closure_env_ty(closure_def_id, closure_substs, env_region).unwrap();
                 let liberated_closure_env_ty = self.tcx.erase_late_bound_regions(
@@ -193,7 +193,7 @@ impl<'tcx> Cx<'tcx> {
                 let va_list_did = self.tcx.require_lang_item(LangItem::VaList, Some(param.span));
 
                 self.tcx
-                    .bound_type_of(va_list_did)
+                    .type_of(va_list_did)
                     .subst(self.tcx, &[self.tcx.lifetimes.re_erased.into()])
             } else {
                 fn_sig.inputs()[index]
diff --git a/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs
index 977c4b4ae6c..e5b7d685c49 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs
@@ -172,7 +172,7 @@ impl IntRange {
         ty: Ty<'tcx>,
         end: &RangeEnd,
     ) -> Option<IntRange> {
-        if Self::is_integral(ty) {
+        Self::is_integral(ty).then(|| {
             // Perform a shift if the underlying types are signed,
             // which makes the interval arithmetic simpler.
             let bias = IntRange::signed_bias(tcx, ty);
@@ -182,10 +182,8 @@ impl IntRange {
                 // This should have been caught earlier by E0030.
                 bug!("malformed range pattern: {}..={}", lo, (hi - offset));
             }
-            Some(IntRange { range: lo..=(hi - offset), bias })
-        } else {
-            None
-        }
+            IntRange { range: lo..=(hi - offset), bias }
+        })
     }
 
     // The return value of `signed_bias` should be XORed with an endpoint to encode/decode it.
diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
index 47ca0a87fcc..41306dd80fb 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
@@ -203,11 +203,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
                 if !lower_overflow && !higher_overflow {
                     self.tcx.sess.emit_err(LowerRangeBoundMustBeLessThanOrEqualToUpper {
                         span,
-                        teach: if self.tcx.sess.teach(&error_code!(E0030)) {
-                            Some(())
-                        } else {
-                            None
-                        },
+                        teach: self.tcx.sess.teach(&error_code!(E0030)).then_some(()),
                     });
                 }
                 PatKind::Wild
diff --git a/compiler/rustc_mir_dataflow/src/impls/liveness.rs b/compiler/rustc_mir_dataflow/src/impls/liveness.rs
index 2890fa32cc9..633a5674f1f 100644
--- a/compiler/rustc_mir_dataflow/src/impls/liveness.rs
+++ b/compiler/rustc_mir_dataflow/src/impls/liveness.rs
@@ -254,13 +254,7 @@ impl<'a, 'tcx> Analysis<'tcx> for MaybeTransitiveLiveLocals<'a> {
     ) {
         // Compute the place that we are storing to, if any
         let destination = match &statement.kind {
-            StatementKind::Assign(assign) => {
-                if assign.1.is_safe_to_remove() {
-                    Some(assign.0)
-                } else {
-                    None
-                }
-            }
+            StatementKind::Assign(assign) => assign.1.is_safe_to_remove().then_some(assign.0),
             StatementKind::SetDiscriminant { place, .. } | StatementKind::Deinit(place) => {
                 Some(**place)
             }
diff --git a/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs b/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs
index d8f85d2e379..9b4b720702b 100644
--- a/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs
+++ b/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs
@@ -41,7 +41,7 @@ impl<'tcx> MirPass<'tcx> for AbortUnwindingCalls {
         //
         // Here we test for this function itself whether its ABI allows
         // unwinding or not.
-        let body_ty = tcx.type_of(def_id);
+        let body_ty = tcx.type_of(def_id).skip_binder();
         let body_abi = match body_ty.kind() {
             ty::FnDef(..) => body_ty.fn_sig(tcx).abi(),
             ty::Closure(..) => Abi::RustCall,
diff --git a/compiler/rustc_mir_transform/src/const_prop.rs b/compiler/rustc_mir_transform/src/const_prop.rs
index feb054392bc..13f064aa72e 100644
--- a/compiler/rustc_mir_transform/src/const_prop.rs
+++ b/compiler/rustc_mir_transform/src/const_prop.rs
@@ -82,7 +82,7 @@ impl<'tcx> MirPass<'tcx> for ConstProp {
             return;
         }
 
-        let is_generator = tcx.type_of(def_id.to_def_id()).is_generator();
+        let is_generator = tcx.type_of(def_id.to_def_id()).subst_identity().is_generator();
         // FIXME(welseywiser) const prop doesn't work on generators because of query cycles
         // computing their layout.
         if is_generator {
diff --git a/compiler/rustc_mir_transform/src/const_prop_lint.rs b/compiler/rustc_mir_transform/src/const_prop_lint.rs
index c4b10218c23..be41d611fe4 100644
--- a/compiler/rustc_mir_transform/src/const_prop_lint.rs
+++ b/compiler/rustc_mir_transform/src/const_prop_lint.rs
@@ -57,7 +57,7 @@ impl<'tcx> MirLint<'tcx> for ConstProp {
             return;
         }
 
-        let is_generator = tcx.type_of(def_id.to_def_id()).is_generator();
+        let is_generator = tcx.type_of(def_id.to_def_id()).subst_identity().is_generator();
         // FIXME(welseywiser) const prop doesn't work on generators because of query cycles
         // computing their layout.
         if is_generator {
diff --git a/compiler/rustc_mir_transform/src/ctfe_limit.rs b/compiler/rustc_mir_transform/src/ctfe_limit.rs
index 7d127032179..1b3ac78fbc6 100644
--- a/compiler/rustc_mir_transform/src/ctfe_limit.rs
+++ b/compiler/rustc_mir_transform/src/ctfe_limit.rs
@@ -47,8 +47,7 @@ fn has_back_edge(
         return false;
     }
     // Check if any of the dominators of the node are also the node's successor.
-    doms.dominators(node)
-        .any(|dom| node_data.terminator().successors().into_iter().any(|succ| succ == dom))
+    doms.dominators(node).any(|dom| node_data.terminator().successors().any(|succ| succ == dom))
 }
 
 fn insert_counter(basic_block_data: &mut BasicBlockData<'_>) {
diff --git a/compiler/rustc_mir_transform/src/deduce_param_attrs.rs b/compiler/rustc_mir_transform/src/deduce_param_attrs.rs
index ddab7bbb2e3..89ca04a1582 100644
--- a/compiler/rustc_mir_transform/src/deduce_param_attrs.rs
+++ b/compiler/rustc_mir_transform/src/deduce_param_attrs.rs
@@ -163,7 +163,7 @@ pub fn deduced_param_attrs<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx [Ded
 
     // Codegen won't use this information for anything if all the function parameters are passed
     // directly. Detect that and bail, for compilation speed.
-    let fn_ty = tcx.type_of(def_id);
+    let fn_ty = tcx.type_of(def_id).subst_identity();
     if matches!(fn_ty.kind(), ty::FnDef(..)) {
         if fn_ty
             .fn_sig(tcx)
diff --git a/compiler/rustc_mir_transform/src/dest_prop.rs b/compiler/rustc_mir_transform/src/dest_prop.rs
index 5c5baa68e58..2e481b97278 100644
--- a/compiler/rustc_mir_transform/src/dest_prop.rs
+++ b/compiler/rustc_mir_transform/src/dest_prop.rs
@@ -136,8 +136,8 @@ use rustc_index::bit_set::BitSet;
 use rustc_middle::mir::visit::{MutVisitor, PlaceContext, Visitor};
 use rustc_middle::mir::{dump_mir, PassWhere};
 use rustc_middle::mir::{
-    traversal, BasicBlock, Body, InlineAsmOperand, Local, LocalKind, Location, Operand, Place,
-    Rvalue, Statement, StatementKind, TerminatorKind,
+    traversal, Body, InlineAsmOperand, Local, LocalKind, Location, Operand, Place, Rvalue,
+    Statement, StatementKind, TerminatorKind,
 };
 use rustc_middle::ty::TyCtxt;
 use rustc_mir_dataflow::impls::MaybeLiveLocals;
@@ -468,7 +468,7 @@ impl<'a, 'body, 'alloc, 'tcx> FilterInformation<'a, 'body, 'alloc, 'tcx> {
             // to reuse the allocation.
             write_info: write_info_alloc,
             // Doesn't matter what we put here, will be overwritten before being used
-            at: Location { block: BasicBlock::from_u32(0), statement_index: 0 },
+            at: Location::START,
         };
         this.internal_filter_liveness();
     }
diff --git a/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs b/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs
index 932134bd631..dc583471c89 100644
--- a/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs
+++ b/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs
@@ -18,8 +18,8 @@ pub fn build_ptr_tys<'tcx>(
     nonnull_did: DefId,
 ) -> (Ty<'tcx>, Ty<'tcx>, Ty<'tcx>) {
     let substs = tcx.intern_substs(&[pointee.into()]);
-    let unique_ty = tcx.bound_type_of(unique_did).subst(tcx, substs);
-    let nonnull_ty = tcx.bound_type_of(nonnull_did).subst(tcx, substs);
+    let unique_ty = tcx.type_of(unique_did).subst(tcx, substs);
+    let nonnull_ty = tcx.type_of(nonnull_did).subst(tcx, substs);
     let ptr_ty = tcx.mk_imm_ptr(pointee);
 
     (unique_ty, nonnull_ty, ptr_ty)
@@ -93,7 +93,7 @@ impl<'tcx> MirPass<'tcx> for ElaborateBoxDerefs {
         if let Some(def_id) = tcx.lang_items().owned_box() {
             let unique_did = tcx.adt_def(def_id).non_enum_variant().fields[0].did;
 
-            let Some(nonnull_def) = tcx.type_of(unique_did).ty_adt_def() else {
+            let Some(nonnull_def) = tcx.type_of(unique_did).subst_identity().ty_adt_def() else {
                 span_bug!(tcx.def_span(unique_did), "expected Box to contain Unique")
             };
 
diff --git a/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs b/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs
index 1244c18020d..e6546911a2d 100644
--- a/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs
+++ b/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs
@@ -49,7 +49,7 @@ fn has_ffi_unwind_calls(tcx: TyCtxt<'_>, local_def_id: LocalDefId) -> bool {
 
     let body = &*tcx.mir_built(ty::WithOptConstParam::unknown(local_def_id)).borrow();
 
-    let body_ty = tcx.type_of(def_id);
+    let body_ty = tcx.type_of(def_id).skip_binder();
     let body_abi = match body_ty.kind() {
         ty::FnDef(..) => body_ty.fn_sig(tcx).abi(),
         ty::Closure(..) => Abi::RustCall,
diff --git a/compiler/rustc_mir_transform/src/function_item_references.rs b/compiler/rustc_mir_transform/src/function_item_references.rs
index aa19b1fdb5e..66d32b954e4 100644
--- a/compiler/rustc_mir_transform/src/function_item_references.rs
+++ b/compiler/rustc_mir_transform/src/function_item_references.rs
@@ -111,11 +111,9 @@ impl<'tcx> FunctionItemRefChecker<'_, 'tcx> {
     /// If the given predicate is the trait `fmt::Pointer`, returns the bound parameter type.
     fn is_pointer_trait(&self, bound: &PredicateKind<'tcx>) -> Option<Ty<'tcx>> {
         if let ty::PredicateKind::Clause(ty::Clause::Trait(predicate)) = bound {
-            if self.tcx.is_diagnostic_item(sym::Pointer, predicate.def_id()) {
-                Some(predicate.trait_ref.self_ty())
-            } else {
-                None
-            }
+            self.tcx
+                .is_diagnostic_item(sym::Pointer, predicate.def_id())
+                .then(|| predicate.trait_ref.self_ty())
         } else {
             None
         }
diff --git a/compiler/rustc_mir_transform/src/generator.rs b/compiler/rustc_mir_transform/src/generator.rs
index 35c6037fa29..dc5f88f24f8 100644
--- a/compiler/rustc_mir_transform/src/generator.rs
+++ b/compiler/rustc_mir_transform/src/generator.rs
@@ -487,7 +487,7 @@ fn transform_async_context<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
 
     let get_context_def_id = tcx.require_lang_item(LangItem::GetContext, None);
 
-    for bb in BasicBlock::new(0)..body.basic_blocks.next_index() {
+    for bb in START_BLOCK..body.basic_blocks.next_index() {
         let bb_data = &body[bb];
         if bb_data.is_cleanup {
             continue;
@@ -1255,7 +1255,7 @@ fn create_generator_resume_function<'tcx>(
     use rustc_middle::mir::AssertKind::{ResumedAfterPanic, ResumedAfterReturn};
 
     // Jump to the entry point on the unresumed
-    cases.insert(0, (UNRESUMED, BasicBlock::new(0)));
+    cases.insert(0, (UNRESUMED, START_BLOCK));
 
     // Panic when resumed on the returned or poisoned state
     let generator_kind = body.generator_kind().unwrap();
@@ -1481,7 +1481,7 @@ impl<'tcx> MirPass<'tcx> for StateTransform {
 
         // When first entering the generator, move the resume argument into its new local.
         let source_info = SourceInfo::outermost(body.span);
-        let stmts = &mut body.basic_blocks_mut()[BasicBlock::new(0)].statements;
+        let stmts = &mut body.basic_blocks_mut()[START_BLOCK].statements;
         stmts.insert(
             0,
             Statement {
diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs
index 84640b703c8..8c6b0463a73 100644
--- a/compiler/rustc_mir_transform/src/inline.rs
+++ b/compiler/rustc_mir_transform/src/inline.rs
@@ -96,7 +96,7 @@ fn inline<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) -> bool {
         history: Vec::new(),
         changed: false,
     };
-    let blocks = BasicBlock::new(0)..body.basic_blocks.next_index();
+    let blocks = START_BLOCK..body.basic_blocks.next_index();
     this.process_blocks(body, blocks);
     this.changed
 }
@@ -900,7 +900,7 @@ impl<'tcx> Visitor<'tcx> for CostChecker<'_, 'tcx> {
 
             let kind = match parent_ty.ty.kind() {
                 &ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
-                    self.tcx.bound_type_of(def_id).subst(self.tcx, substs).kind()
+                    self.tcx.type_of(def_id).subst(self.tcx, substs).kind()
                 }
                 kind => kind,
             };
diff --git a/compiler/rustc_mir_transform/src/instcombine.rs b/compiler/rustc_mir_transform/src/instcombine.rs
index 1079377fbac..0534e688703 100644
--- a/compiler/rustc_mir_transform/src/instcombine.rs
+++ b/compiler/rustc_mir_transform/src/instcombine.rs
@@ -110,11 +110,7 @@ impl<'tcx> InstCombineContext<'tcx, '_> {
     fn combine_ref_deref(&self, source_info: &SourceInfo, rvalue: &mut Rvalue<'tcx>) {
         if let Rvalue::Ref(_, _, place) = rvalue {
             if let Some((base, ProjectionElem::Deref)) = place.as_ref().last_projection() {
-                if let ty::Ref(_, _, Mutability::Not) =
-                    base.ty(self.local_decls, self.tcx).ty.kind()
-                {
-                    // The dereferenced place must have type `&_`, so that we don't copy `&mut _`.
-                } else {
+                if rvalue.ty(self.local_decls, self.tcx) != base.ty(self.local_decls, self.tcx).ty {
                     return;
                 }
 
diff --git a/compiler/rustc_mir_transform/src/large_enums.rs b/compiler/rustc_mir_transform/src/large_enums.rs
index 194c41c6ba1..2ca33a624e2 100644
--- a/compiler/rustc_mir_transform/src/large_enums.rs
+++ b/compiler/rustc_mir_transform/src/large_enums.rs
@@ -3,7 +3,7 @@ use crate::MirPass;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_middle::mir::interpret::AllocId;
 use rustc_middle::mir::*;
-use rustc_middle::ty::{self, AdtDef, Const, ParamEnv, Ty, TyCtxt};
+use rustc_middle::ty::{self, AdtDef, ParamEnv, Ty, TyCtxt};
 use rustc_session::Session;
 use rustc_target::abi::{HasDataLayout, Size, TagEncoding, Variants};
 
@@ -141,10 +141,7 @@ impl EnumSizeOpt {
                         self.candidate(tcx, param_env, ty, &mut alloc_cache)?;
                     let alloc = tcx.global_alloc(alloc_id).unwrap_memory();
 
-                    let tmp_ty = tcx.mk_ty(ty::Array(
-                        tcx.types.usize,
-                        Const::from_target_usize(tcx, num_variants as u64),
-                    ));
+                    let tmp_ty = tcx.mk_array(tcx.types.usize, num_variants as u64);
 
                     let size_array_local = local_decls.push(LocalDecl::new(tmp_ty, span));
                     let store_live = Statement {
diff --git a/compiler/rustc_mir_transform/src/remove_zsts.rs b/compiler/rustc_mir_transform/src/remove_zsts.rs
index 6cabef92d8c..1becfddb23b 100644
--- a/compiler/rustc_mir_transform/src/remove_zsts.rs
+++ b/compiler/rustc_mir_transform/src/remove_zsts.rs
@@ -13,7 +13,7 @@ impl<'tcx> MirPass<'tcx> for RemoveZsts {
 
     fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
         // Avoid query cycles (generators require optimized MIR for layout).
-        if tcx.type_of(body.source.def_id()).is_generator() {
+        if tcx.type_of(body.source.def_id()).subst_identity().is_generator() {
             return;
         }
         let param_env = tcx.param_env(body.source.def_id());
diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs
index 551422386f6..682ad081f5c 100644
--- a/compiler/rustc_mir_transform/src/shim.rs
+++ b/compiler/rustc_mir_transform/src/shim.rs
@@ -597,7 +597,7 @@ fn build_call_shim<'tcx>(
         let untuple_args = sig.inputs();
 
         // Create substitutions for the `Self` and `Args` generic parameters of the shim body.
-        let arg_tup = tcx.mk_tup(untuple_args.iter());
+        let arg_tup = tcx.intern_tup(untuple_args);
 
         (Some([ty.into(), arg_tup.into()]), Some(untuple_args))
     } else {
@@ -692,7 +692,7 @@ fn build_call_shim<'tcx>(
 
         // `FnDef` call with optional receiver.
         CallKind::Direct(def_id) => {
-            let ty = tcx.type_of(def_id);
+            let ty = tcx.type_of(def_id).subst_identity();
             (
                 Operand::Constant(Box::new(Constant {
                     span,
diff --git a/compiler/rustc_mir_transform/src/simplify.rs b/compiler/rustc_mir_transform/src/simplify.rs
index ced97b2c788..9ef55c558c6 100644
--- a/compiler/rustc_mir_transform/src/simplify.rs
+++ b/compiler/rustc_mir_transform/src/simplify.rs
@@ -496,7 +496,7 @@ impl UsedLocals {
         self.increment = false;
 
         // The location of the statement is irrelevant.
-        let location = Location { block: START_BLOCK, statement_index: 0 };
+        let location = Location::START;
         self.visit_statement(statement, location);
     }
 
diff --git a/compiler/rustc_mir_transform/src/ssa.rs b/compiler/rustc_mir_transform/src/ssa.rs
index 65c15d9c674..c1e7f62dea5 100644
--- a/compiler/rustc_mir_transform/src/ssa.rs
+++ b/compiler/rustc_mir_transform/src/ssa.rs
@@ -2,7 +2,7 @@ use either::Either;
 use rustc_data_structures::graph::dominators::Dominators;
 use rustc_index::bit_set::BitSet;
 use rustc_index::vec::IndexVec;
-use rustc_middle::middle::resolve_lifetime::Set1;
+use rustc_middle::middle::resolve_bound_vars::Set1;
 use rustc_middle::mir::visit::*;
 use rustc_middle::mir::*;
 use rustc_middle::ty::{ParamEnv, TyCtxt};
diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs
index bbe4e67977c..55a9f912e08 100644
--- a/compiler/rustc_monomorphize/src/collector.rs
+++ b/compiler/rustc_monomorphize/src/collector.rs
@@ -1196,8 +1196,7 @@ impl<'v> RootCollector<'_, 'v> {
                 {
                     debug!("RootCollector: ADT drop-glue for `{id:?}`",);
 
-                    let ty =
-                        self.tcx.bound_type_of(id.owner_id.to_def_id()).no_bound_vars().unwrap();
+                    let ty = self.tcx.type_of(id.owner_id.to_def_id()).no_bound_vars().unwrap();
                     visit_drop_use(self.tcx, ty, true, DUMMY_SP, self.output);
                 }
             }
diff --git a/compiler/rustc_monomorphize/src/partitioning/default.rs b/compiler/rustc_monomorphize/src/partitioning/default.rs
index 29009c48050..62bafb981e7 100644
--- a/compiler/rustc_monomorphize/src/partitioning/default.rs
+++ b/compiler/rustc_monomorphize/src/partitioning/default.rs
@@ -308,7 +308,7 @@ fn characteristic_def_id_of_mono_item<'tcx>(
                     let impl_self_ty = tcx.subst_and_normalize_erasing_regions(
                         instance.substs,
                         ty::ParamEnv::reveal_all(),
-                        tcx.type_of(impl_def_id),
+                        tcx.type_of(impl_def_id).skip_binder(),
                     );
                     if let Some(def_id) = characteristic_def_id_of_type(impl_self_ty) {
                         return Some(def_id);
diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs
index bd998ed91d9..37449aaabed 100644
--- a/compiler/rustc_parse/src/lexer/mod.rs
+++ b/compiler/rustc_parse/src/lexer/mod.rs
@@ -200,16 +200,21 @@ impl<'a> StringReader<'a> {
                     };
                     token::Literal(token::Lit { kind, symbol, suffix })
                 }
-                rustc_lexer::TokenKind::Lifetime { starts_with_number } => {
+                rustc_lexer::TokenKind::Lifetime { starts_with_number, contains_emoji } => {
                     // Include the leading `'` in the real identifier, for macro
                     // expansion purposes. See #12512 for the gory details of why
                     // this is necessary.
                     let lifetime_name = self.str_from(start);
                     if starts_with_number {
                         let span = self.mk_sp(start, self.pos);
-                        let mut diag = self.sess.struct_err("lifetimes cannot start with a number");
+                        let mut diag = self.sess.struct_err("lifetimes or labels cannot start with a number");
                         diag.set_span(span);
                         diag.stash(span, StashKey::LifetimeIsChar);
+                    } else if contains_emoji {
+                        let span = self.mk_sp(start, self.pos);
+                        let mut diag = self.sess.struct_err("lifetimes or labels cannot contain emojis");
+                        diag.set_span(span);
+                        diag.stash(span, StashKey::LifetimeContainsEmoji);
                     }
                     let ident = Symbol::intern(lifetime_name);
                     token::Lifetime(ident)
diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs
index 0cb88f3c3a9..a74f408d774 100644
--- a/compiler/rustc_parse/src/parser/mod.rs
+++ b/compiler/rustc_parse/src/parser/mod.rs
@@ -1283,22 +1283,16 @@ impl<'a> Parser<'a> {
     }
 
     fn parse_delim_args_inner(&mut self) -> Option<DelimArgs> {
-        if self.check(&token::OpenDelim(Delimiter::Parenthesis))
+        let delimited = self.check(&token::OpenDelim(Delimiter::Parenthesis))
             || self.check(&token::OpenDelim(Delimiter::Bracket))
-            || self.check(&token::OpenDelim(Delimiter::Brace))
-        {
-            match self.parse_token_tree() {
-                // We've confirmed above that there is a delimiter so unwrapping is OK.
-                TokenTree::Delimited(dspan, delim, tokens) => Some(DelimArgs {
-                    dspan,
-                    delim: MacDelimiter::from_token(delim).unwrap(),
-                    tokens,
-                }),
-                _ => unreachable!(),
-            }
-        } else {
-            None
-        }
+            || self.check(&token::OpenDelim(Delimiter::Brace));
+
+        delimited.then(|| {
+            // We've confirmed above that there is a delimiter so unwrapping is OK.
+            let TokenTree::Delimited(dspan, delim, tokens) = self.parse_token_tree() else { unreachable!() };
+
+            DelimArgs { dspan, delim: MacDelimiter::from_token(delim).unwrap(), tokens }
+        })
     }
 
     fn parse_or_use_outer_attributes(
diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs
index 2e706a00cf7..49959a8981c 100644
--- a/compiler/rustc_parse/src/parser/path.rs
+++ b/compiler/rustc_parse/src/parser/path.rs
@@ -404,7 +404,7 @@ impl<'a> Parser<'a> {
 
         let is_first_invocation = style == PathStyle::Expr;
         // Take a snapshot before attempting to parse - we can restore this later.
-        let snapshot = if is_first_invocation { Some(self.clone()) } else { None };
+        let snapshot = is_first_invocation.then(|| self.clone());
 
         debug!("parse_generic_args_with_leading_angle_bracket_recovery: (snapshotting)");
         match self.parse_angle_args(ty_generics) {
diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs
index 5b92563fc35..4f4252b532e 100644
--- a/compiler/rustc_parse/src/parser/ty.rs
+++ b/compiler/rustc_parse/src/parser/ty.rs
@@ -450,8 +450,7 @@ impl<'a> Parser<'a> {
 
     fn parse_borrowed_pointee(&mut self) -> PResult<'a, TyKind> {
         let and_span = self.prev_token.span;
-        let mut opt_lifetime =
-            if self.check_lifetime() { Some(self.expect_lifetime()) } else { None };
+        let mut opt_lifetime = self.check_lifetime().then(|| self.expect_lifetime());
         let mut mutbl = self.parse_mutability();
         if self.token.is_lifetime() && mutbl == Mutability::Mut && opt_lifetime.is_none() {
             // A lifetime is invalid here: it would be part of a bare trait bound, which requires
@@ -871,7 +870,7 @@ impl<'a> Parser<'a> {
             None
         };
 
-        let maybe = if self.eat(&token::Question) { Some(self.prev_token.span) } else { None };
+        let maybe = self.eat(&token::Question).then_some(self.prev_token.span);
 
         Ok(BoundModifiers { maybe, maybe_const })
     }
diff --git a/compiler/rustc_parse_format/src/lib.rs b/compiler/rustc_parse_format/src/lib.rs
index 34a4fd02ea6..8a3cedfee79 100644
--- a/compiler/rustc_parse_format/src/lib.rs
+++ b/compiler/rustc_parse_format/src/lib.rs
@@ -835,7 +835,7 @@ impl<'a> Parser<'a> {
             );
         }
 
-        if found { Some(cur) } else { None }
+        found.then_some(cur)
     }
 
     fn suggest_format(&mut self) {
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index 225095948af..8ad4a5ef958 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -18,7 +18,7 @@ use rustc_hir::{
 };
 use rustc_hir::{MethodKind, Target, Unsafety};
 use rustc_middle::hir::nested_filter;
-use rustc_middle::middle::resolve_lifetime::ObjectLifetimeDefault;
+use rustc_middle::middle::resolve_bound_vars::ObjectLifetimeDefault;
 use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams};
 use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::{ParamEnv, TyCtxt};
@@ -2174,7 +2174,7 @@ impl CheckAttrVisitor<'_> {
         let tcx = self.tcx;
         if target == Target::Fn {
             let Some(tokenstream) = tcx.get_diagnostic_item(sym::TokenStream) else {return};
-            let tokenstream = tcx.type_of(tokenstream);
+            let tokenstream = tcx.type_of(tokenstream).subst_identity();
 
             let id = hir_id.expect_owner();
             let hir_sig = tcx.hir().fn_sig_by_hir_id(hir_id).unwrap();
diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs
index 7cfffe390d3..668c159f3cc 100644
--- a/compiler/rustc_passes/src/dead.rs
+++ b/compiler/rustc_passes/src/dead.rs
@@ -315,7 +315,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
                     //// This is done to handle the case where, for example, the static
                     //// method of a private type is used, but the type itself is never
                     //// called directly.
-                    let self_ty = self.tcx.type_of(item);
+                    let self_ty = self.tcx.type_of(item).subst_identity();
                     match *self_ty.kind() {
                         ty::Adt(def, _) => self.check_def_id(def.did()),
                         ty::Foreign(did) => self.check_def_id(did),
@@ -654,7 +654,7 @@ impl<'tcx> DeadVisitor<'tcx> {
         if self.live_symbols.contains(&field.did.expect_local()) {
             return ShouldWarnAboutField::No;
         }
-        let field_type = self.tcx.type_of(field.did);
+        let field_type = self.tcx.type_of(field.did).subst_identity();
         if field_type.is_phantom_data() {
             return ShouldWarnAboutField::No;
         }
diff --git a/compiler/rustc_passes/src/diagnostic_items.rs b/compiler/rustc_passes/src/diagnostic_items.rs
index 10ffa87efe3..0ae7096642c 100644
--- a/compiler/rustc_passes/src/diagnostic_items.rs
+++ b/compiler/rustc_passes/src/diagnostic_items.rs
@@ -32,11 +32,8 @@ fn collect_item(tcx: TyCtxt<'_>, items: &mut DiagnosticItems, name: Symbol, item
     if let Some(original_def_id) = items.name_to_id.insert(name, item_def_id) {
         if original_def_id != item_def_id {
             let orig_span = tcx.hir().span_if_local(original_def_id);
-            let orig_crate_name = if orig_span.is_some() {
-                None
-            } else {
-                Some(tcx.crate_name(original_def_id.krate))
-            };
+            let orig_crate_name =
+                orig_span.is_none().then(|| tcx.crate_name(original_def_id.krate));
             match tcx.hir().span_if_local(item_def_id) {
                 Some(span) => tcx.sess.emit_err(DuplicateDiagnosticItem { span, name }),
                 None => tcx.sess.emit_err(DuplicateDiagnosticItemInCrate {
diff --git a/compiler/rustc_passes/src/layout_test.rs b/compiler/rustc_passes/src/layout_test.rs
index 827d86780aa..047b9b525e8 100644
--- a/compiler/rustc_passes/src/layout_test.rs
+++ b/compiler/rustc_passes/src/layout_test.rs
@@ -29,7 +29,7 @@ pub fn test_layout(tcx: TyCtxt<'_>) {
 fn dump_layout_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribute) {
     let tcx = tcx;
     let param_env = tcx.param_env(item_def_id);
-    let ty = tcx.type_of(item_def_id);
+    let ty = tcx.type_of(item_def_id).subst_identity();
     match tcx.layout_of(param_env.and(ty)) {
         Ok(ty_layout) => {
             // Check out the `#[rustc_layout(..)]` attribute to tell what to dump.
diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs
index 873c40e8cb6..2e736039fb5 100644
--- a/compiler/rustc_passes/src/stability.rs
+++ b/compiler/rustc_passes/src/stability.rs
@@ -281,7 +281,7 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
         self.recurse_with_stability_attrs(
             depr.map(|(d, _)| DeprecationEntry::local(d, def_id)),
             stab,
-            if inherit_const_stability.yes() { const_stab } else { None },
+            inherit_const_stability.yes().then_some(const_stab).flatten(),
             visit_children,
         );
     }
diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs
index 4675bd79c46..58dfca75c65 100644
--- a/compiler/rustc_privacy/src/lib.rs
+++ b/compiler/rustc_privacy/src/lib.rs
@@ -159,9 +159,21 @@ where
                 _region,
             ))) => ty.visit_with(self),
             ty::PredicateKind::Clause(ty::Clause::RegionOutlives(..)) => ControlFlow::Continue(()),
+            ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(ct, ty)) => {
+                ct.visit_with(self)?;
+                ty.visit_with(self)
+            }
             ty::PredicateKind::ConstEvaluatable(ct) => ct.visit_with(self),
             ty::PredicateKind::WellFormed(arg) => arg.visit_with(self),
-            _ => bug!("unexpected predicate: {:?}", predicate),
+
+            ty::PredicateKind::ObjectSafe(_)
+            | ty::PredicateKind::ClosureKind(_, _, _)
+            | ty::PredicateKind::Subtype(_)
+            | ty::PredicateKind::Coerce(_)
+            | ty::PredicateKind::ConstEquate(_, _)
+            | ty::PredicateKind::TypeWellFormedFromEnv(_)
+            | ty::PredicateKind::Ambiguous
+            | ty::PredicateKind::AliasEq(_, _) => bug!("unexpected predicate: {:?}", predicate),
         }
     }
 
@@ -207,7 +219,7 @@ where
                 // so we need to visit the self type additionally.
                 if let Some(assoc_item) = tcx.opt_associated_item(def_id) {
                     if let Some(impl_def_id) = assoc_item.impl_container(tcx) {
-                        tcx.type_of(impl_def_id).visit_with(self)?;
+                        tcx.type_of(impl_def_id).subst_identity().visit_with(self)?;
                     }
                 }
             }
@@ -270,10 +282,11 @@ where
             | ty::Ref(..)
             | ty::FnPtr(..)
             | ty::Param(..)
+            | ty::Bound(..)
             | ty::Error(_)
             | ty::GeneratorWitness(..)
             | ty::GeneratorWitnessMIR(..) => {}
-            ty::Bound(..) | ty::Placeholder(..) | ty::Infer(..) => {
+            ty::Placeholder(..) | ty::Infer(..) => {
                 bug!("unexpected type: {:?}", ty)
             }
         }
@@ -341,7 +354,7 @@ trait VisibilityLike: Sized {
         effective_visibilities: &EffectiveVisibilities,
     ) -> Self {
         let mut find = FindMin { tcx, effective_visibilities, min: Self::MAX };
-        find.visit(tcx.type_of(def_id));
+        find.visit(tcx.type_of(def_id).subst_identity());
         if let Some(trait_ref) = tcx.impl_trait_ref(def_id) {
             find.visit_trait(trait_ref.subst_identity());
         }
@@ -837,11 +850,11 @@ impl ReachEverythingInTheInterfaceVisitor<'_, '_> {
                 GenericParamDefKind::Lifetime => {}
                 GenericParamDefKind::Type { has_default, .. } => {
                     if has_default {
-                        self.visit(self.ev.tcx.type_of(param.def_id));
+                        self.visit(self.ev.tcx.type_of(param.def_id).subst_identity());
                     }
                 }
                 GenericParamDefKind::Const { has_default } => {
-                    self.visit(self.ev.tcx.type_of(param.def_id));
+                    self.visit(self.ev.tcx.type_of(param.def_id).subst_identity());
                     if has_default {
                         self.visit(self.ev.tcx.const_param_default(param.def_id).subst_identity());
                     }
@@ -857,7 +870,7 @@ impl ReachEverythingInTheInterfaceVisitor<'_, '_> {
     }
 
     fn ty(&mut self) -> &mut Self {
-        self.visit(self.ev.tcx.type_of(self.item_def_id));
+        self.visit(self.ev.tcx.type_of(self.item_def_id).subst_identity());
         self
     }
 
@@ -1268,7 +1281,7 @@ impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> {
                 // Method calls have to be checked specially.
                 self.span = segment.ident.span;
                 if let Some(def_id) = self.typeck_results().type_dependent_def_id(expr.hir_id) {
-                    if self.visit(self.tcx.type_of(def_id)).is_break() {
+                    if self.visit(self.tcx.type_of(def_id).subst_identity()).is_break() {
                         return;
                     }
                 } else {
@@ -1742,12 +1755,12 @@ impl SearchInterfaceForPrivateItemsVisitor<'_> {
                 GenericParamDefKind::Lifetime => {}
                 GenericParamDefKind::Type { has_default, .. } => {
                     if has_default {
-                        self.visit(self.tcx.type_of(param.def_id));
+                        self.visit(self.tcx.type_of(param.def_id).subst_identity());
                     }
                 }
                 // FIXME(generic_const_exprs): May want to look inside const here
                 GenericParamDefKind::Const { .. } => {
-                    self.visit(self.tcx.type_of(param.def_id));
+                    self.visit(self.tcx.type_of(param.def_id).subst_identity());
                 }
             }
         }
@@ -1774,7 +1787,7 @@ impl SearchInterfaceForPrivateItemsVisitor<'_> {
     }
 
     fn ty(&mut self) -> &mut Self {
-        self.visit(self.tcx.type_of(self.item_def_id));
+        self.visit(self.tcx.type_of(self.item_def_id).subst_identity());
         self
     }
 
diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs
index 2d243e13cc2..d7708a3bc3f 100644
--- a/compiler/rustc_query_impl/src/lib.rs
+++ b/compiler/rustc_query_impl/src/lib.rs
@@ -21,7 +21,9 @@ use rustc_data_structures::sync::AtomicU64;
 use rustc_middle::arena::Arena;
 use rustc_middle::dep_graph::{self, DepKindStruct};
 use rustc_middle::query::Key;
-use rustc_middle::ty::query::{query_keys, query_storage, query_stored, query_values};
+use rustc_middle::ty::query::{
+    query_keys, query_provided, query_provided_to_value, query_storage, query_values,
+};
 use rustc_middle::ty::query::{ExternProviders, Providers, QueryEngine};
 use rustc_middle::ty::TyCtxt;
 use rustc_span::Span;
diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs
index 49309db564e..e2884f2026e 100644
--- a/compiler/rustc_query_impl/src/plumbing.rs
+++ b/compiler/rustc_query_impl/src/plumbing.rs
@@ -53,7 +53,7 @@ impl<'tcx> HasDepContext for QueryCtxt<'tcx> {
 }
 
 impl QueryContext for QueryCtxt<'_> {
-    fn next_job_id(&self) -> QueryJobId {
+    fn next_job_id(self) -> QueryJobId {
         QueryJobId(
             NonZeroU64::new(
                 self.queries.jobs.fetch_add(1, rustc_data_structures::sync::Ordering::Relaxed),
@@ -62,31 +62,31 @@ impl QueryContext for QueryCtxt<'_> {
         )
     }
 
-    fn current_query_job(&self) -> Option<QueryJobId> {
-        tls::with_related_context(**self, |icx| icx.query)
+    fn current_query_job(self) -> Option<QueryJobId> {
+        tls::with_related_context(*self, |icx| icx.query)
     }
 
-    fn try_collect_active_jobs(&self) -> Option<QueryMap<DepKind>> {
-        self.queries.try_collect_active_jobs(**self)
+    fn try_collect_active_jobs(self) -> Option<QueryMap<DepKind>> {
+        self.queries.try_collect_active_jobs(*self)
     }
 
     // Interactions with on_disk_cache
-    fn load_side_effects(&self, prev_dep_node_index: SerializedDepNodeIndex) -> QuerySideEffects {
+    fn load_side_effects(self, prev_dep_node_index: SerializedDepNodeIndex) -> QuerySideEffects {
         self.queries
             .on_disk_cache
             .as_ref()
-            .map(|c| c.load_side_effects(**self, prev_dep_node_index))
+            .map(|c| c.load_side_effects(*self, prev_dep_node_index))
             .unwrap_or_default()
     }
 
-    fn store_side_effects(&self, dep_node_index: DepNodeIndex, side_effects: QuerySideEffects) {
+    fn store_side_effects(self, dep_node_index: DepNodeIndex, side_effects: QuerySideEffects) {
         if let Some(c) = self.queries.on_disk_cache.as_ref() {
             c.store_side_effects(dep_node_index, side_effects)
         }
     }
 
     fn store_side_effects_for_anon_node(
-        &self,
+        self,
         dep_node_index: DepNodeIndex,
         side_effects: QuerySideEffects,
     ) {
@@ -100,7 +100,7 @@ impl QueryContext for QueryCtxt<'_> {
     /// captured during execution and the actual result.
     #[inline(always)]
     fn start_query<R>(
-        &self,
+        self,
         token: QueryJobId,
         depth_limit: bool,
         diagnostics: Option<&Lock<ThinVec<Diagnostic>>>,
@@ -109,14 +109,14 @@ impl QueryContext for QueryCtxt<'_> {
         // The `TyCtxt` stored in TLS has the same global interner lifetime
         // as `self`, so we use `with_related_context` to relate the 'tcx lifetimes
         // when accessing the `ImplicitCtxt`.
-        tls::with_related_context(**self, move |current_icx| {
+        tls::with_related_context(*self, move |current_icx| {
             if depth_limit && !self.recursion_limit().value_within_limit(current_icx.query_depth) {
                 self.depth_limit_error(token);
             }
 
             // Update the `ImplicitCtxt` to point to our new query job.
             let new_icx = ImplicitCtxt {
-                tcx: **self,
+                tcx: *self,
                 query: Some(token),
                 diagnostics,
                 query_depth: current_icx.query_depth + depth_limit as usize,
@@ -130,7 +130,7 @@ impl QueryContext for QueryCtxt<'_> {
         })
     }
 
-    fn depth_limit_error(&self, job: QueryJobId) {
+    fn depth_limit_error(self, job: QueryJobId) {
         let mut span = None;
         let mut layout_of_depth = None;
         if let Some(map) = self.try_collect_active_jobs() {
@@ -293,14 +293,14 @@ macro_rules! get_provider {
 }
 
 macro_rules! should_ever_cache_on_disk {
-    ([]) => {{
-        None
+    ([]$yes:tt $no:tt) => {{
+        $no
     }};
-    ([(cache) $($rest:tt)*]) => {{
-        Some($crate::plumbing::try_load_from_disk::<Self::Value>)
+    ([(cache) $($rest:tt)*]$yes:tt $no:tt) => {{
+        $yes
     }};
-    ([$other:tt $($modifiers:tt)*]) => {
-        should_ever_cache_on_disk!([$($modifiers)*])
+    ([$other:tt $($modifiers:tt)*]$yes:tt $no:tt) => {
+        should_ever_cache_on_disk!([$($modifiers)*]$yes $no)
     };
 }
 
@@ -472,7 +472,6 @@ macro_rules! define_queries {
         $(impl<'tcx> QueryConfig<QueryCtxt<'tcx>> for queries::$name<'tcx> {
             type Key = query_keys::$name<'tcx>;
             type Value = query_values::$name<'tcx>;
-            type Stored = query_stored::$name<'tcx>;
             const NAME: &'static str = stringify!($name);
 
             #[inline]
@@ -493,24 +492,39 @@ macro_rules! define_queries {
             fn query_cache<'a>(tcx: QueryCtxt<'tcx>) -> &'a Self::Cache
                 where 'tcx:'a
             {
-                &tcx.query_caches.$name
+                &tcx.query_system.caches.$name
             }
 
-            fn execute_query(tcx: TyCtxt<'tcx>, key: Self::Key) -> Self::Stored {
+            fn execute_query(tcx: TyCtxt<'tcx>, key: Self::Key) -> Self::Value {
                 tcx.$name(key)
             }
 
             #[inline]
-            // key is only sometimes used
             #[allow(unused_variables)]
-            fn compute(qcx: QueryCtxt<'tcx>, key: &Self::Key) -> fn(TyCtxt<'tcx>, Self::Key) -> Self::Value {
-                get_provider!([$($modifiers)*][qcx, $name, key])
+            fn compute(qcx: QueryCtxt<'tcx>, key: Self::Key) -> Self::Value {
+                query_provided_to_value::$name(
+                    qcx.tcx,
+                    get_provider!([$($modifiers)*][qcx, $name, key])(qcx.tcx, key)
+                )
             }
 
             #[inline]
-            fn try_load_from_disk(qcx: QueryCtxt<'tcx>, key: &Self::Key) -> rustc_query_system::query::TryLoadFromDisk<QueryCtxt<'tcx>, Self> {
-                let cache_on_disk = Self::cache_on_disk(qcx.tcx, key);
-                if cache_on_disk { should_ever_cache_on_disk!([$($modifiers)*]) } else { None }
+            fn try_load_from_disk(_qcx: QueryCtxt<'tcx>, _key: &Self::Key) -> rustc_query_system::query::TryLoadFromDisk<QueryCtxt<'tcx>, Self> {
+                should_ever_cache_on_disk!([$($modifiers)*] {
+                    if Self::cache_on_disk(_qcx.tcx, _key) {
+                        Some(|qcx: QueryCtxt<'tcx>, dep_node| {
+                            let value = $crate::plumbing::try_load_from_disk::<query_provided::$name<'tcx>>(
+                                qcx,
+                                dep_node
+                            );
+                            value.map(|value| query_provided_to_value::$name(qcx.tcx, value))
+                        })
+                    } else {
+                        None
+                    }
+                } {
+                    None
+                })
             }
 
             const ANON: bool = is_anon!([$($modifiers)*]);
@@ -633,7 +647,7 @@ macro_rules! define_queries {
                     $crate::profiling_support::alloc_self_profile_query_strings_for_query_cache(
                         tcx,
                         stringify!($name),
-                        &tcx.query_caches.$name,
+                        &tcx.query_system.caches.$name,
                         string_cache,
                     )
                 },
@@ -725,7 +739,7 @@ macro_rules! define_queries_struct {
                 span: Span,
                 key: <queries::$name<'tcx> as QueryConfig<QueryCtxt<'tcx>>>::Key,
                 mode: QueryMode,
-            ) -> Option<query_stored::$name<'tcx>> {
+            ) -> Option<query_values::$name<'tcx>> {
                 let qcx = QueryCtxt { tcx, queries: self };
                 get_query::<queries::$name<'tcx>, _, rustc_middle::dep_graph::DepKind>(qcx, span, key, mode)
             })*
diff --git a/compiler/rustc_query_system/src/dep_graph/mod.rs b/compiler/rustc_query_system/src/dep_graph/mod.rs
index e370c6990a4..6969f2dbef8 100644
--- a/compiler/rustc_query_system/src/dep_graph/mod.rs
+++ b/compiler/rustc_query_system/src/dep_graph/mod.rs
@@ -23,7 +23,7 @@ pub trait DepContext: Copy {
     type DepKind: self::DepKind;
 
     /// Create a hashing context for hashing new results.
-    fn with_stable_hashing_context<R>(&self, f: impl FnOnce(StableHashingContext<'_>) -> R) -> R;
+    fn with_stable_hashing_context<R>(self, f: impl FnOnce(StableHashingContext<'_>) -> R) -> R;
 
     /// Access the DepGraph.
     fn dep_graph(&self) -> &DepGraph<Self::DepKind>;
@@ -37,7 +37,7 @@ pub trait DepContext: Copy {
     fn dep_kind_info(&self, dep_node: Self::DepKind) -> &DepKindStruct<Self>;
 
     #[inline(always)]
-    fn fingerprint_style(&self, kind: Self::DepKind) -> FingerprintStyle {
+    fn fingerprint_style(self, kind: Self::DepKind) -> FingerprintStyle {
         let data = self.dep_kind_info(kind);
         if data.is_anon {
             return FingerprintStyle::Opaque;
@@ -47,7 +47,7 @@ pub trait DepContext: Copy {
 
     #[inline(always)]
     /// Return whether this kind always require evaluation.
-    fn is_eval_always(&self, kind: Self::DepKind) -> bool {
+    fn is_eval_always(self, kind: Self::DepKind) -> bool {
         self.dep_kind_info(kind).is_eval_always
     }
 
diff --git a/compiler/rustc_query_system/src/dep_graph/serialized.rs b/compiler/rustc_query_system/src/dep_graph/serialized.rs
index a81595b2420..29513df460f 100644
--- a/compiler/rustc_query_system/src/dep_graph/serialized.rs
+++ b/compiler/rustc_query_system/src/dep_graph/serialized.rs
@@ -242,8 +242,7 @@ impl<K: DepKind + Encodable<FileEncoder>> GraphEncoder<K> {
         record_graph: bool,
         record_stats: bool,
     ) -> Self {
-        let record_graph =
-            if record_graph { Some(Lock::new(DepGraphQuery::new(prev_node_count))) } else { None };
+        let record_graph = record_graph.then(|| Lock::new(DepGraphQuery::new(prev_node_count)));
         let status = Lock::new(EncoderState::new(encoder, record_stats));
         GraphEncoder { status, record_graph }
     }
diff --git a/compiler/rustc_query_system/src/query/caches.rs b/compiler/rustc_query_system/src/query/caches.rs
index 81c7e4673d4..e840108bdd8 100644
--- a/compiler/rustc_query_system/src/query/caches.rs
+++ b/compiler/rustc_query_system/src/query/caches.rs
@@ -1,12 +1,10 @@
 use crate::dep_graph::DepNodeIndex;
 
-use rustc_arena::TypedArena;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::sharded;
 #[cfg(parallel_compiler)]
 use rustc_data_structures::sharded::Sharded;
 use rustc_data_structures::sync::Lock;
-use rustc_data_structures::sync::WorkerLocal;
 use rustc_index::vec::{Idx, IndexVec};
 use std::fmt::Debug;
 use std::hash::Hash;
@@ -16,12 +14,10 @@ pub trait CacheSelector<'tcx, V> {
     type Cache
     where
         V: Copy;
-    type ArenaCache;
 }
 
 pub trait QueryStorage {
-    type Value: Debug;
-    type Stored: Copy;
+    type Value: Copy;
 }
 
 pub trait QueryCache: QueryStorage + Sized {
@@ -31,9 +27,9 @@ pub trait QueryCache: QueryStorage + Sized {
     /// It returns the shard index and a lock guard to the shard,
     /// which will be used if the query is not in the cache and we need
     /// to compute it.
-    fn lookup(&self, key: &Self::Key) -> Option<(Self::Stored, DepNodeIndex)>;
+    fn lookup(&self, key: &Self::Key) -> Option<(Self::Value, DepNodeIndex)>;
 
-    fn complete(&self, key: Self::Key, value: Self::Value, index: DepNodeIndex) -> Self::Stored;
+    fn complete(&self, key: Self::Key, value: Self::Value, index: DepNodeIndex);
 
     fn iter(&self, f: &mut dyn FnMut(&Self::Key, &Self::Value, DepNodeIndex));
 }
@@ -44,7 +40,6 @@ impl<'tcx, K: Eq + Hash, V: 'tcx> CacheSelector<'tcx, V> for DefaultCacheSelecto
     type Cache = DefaultCache<K, V>
     where
         V: Copy;
-    type ArenaCache = ArenaCache<'tcx, K, V>;
 }
 
 pub struct DefaultCache<K, V> {
@@ -62,7 +57,6 @@ impl<K, V> Default for DefaultCache<K, V> {
 
 impl<K: Eq + Hash, V: Copy + Debug> QueryStorage for DefaultCache<K, V> {
     type Value = V;
-    type Stored = V;
 }
 
 impl<K, V> QueryCache for DefaultCache<K, V>
@@ -85,7 +79,7 @@ where
     }
 
     #[inline]
-    fn complete(&self, key: K, value: V, index: DepNodeIndex) -> Self::Stored {
+    fn complete(&self, key: K, value: V, index: DepNodeIndex) {
         #[cfg(parallel_compiler)]
         let mut lock = self.cache.get_shard_by_value(&key).lock();
         #[cfg(not(parallel_compiler))]
@@ -93,7 +87,6 @@ where
         // We may be overwriting another value. This is all right, since the dep-graph
         // will check that the fingerprint matches.
         lock.insert(key, (value, index));
-        value
     }
 
     fn iter(&self, f: &mut dyn FnMut(&Self::Key, &Self::Value, DepNodeIndex)) {
@@ -122,7 +115,6 @@ impl<'tcx, V: 'tcx> CacheSelector<'tcx, V> for SingleCacheSelector {
     type Cache = SingleCache<V>
     where
         V: Copy;
-    type ArenaCache = ArenaCache<'tcx, (), V>;
 }
 
 pub struct SingleCache<V> {
@@ -137,7 +129,6 @@ impl<V> Default for SingleCache<V> {
 
 impl<V: Copy + Debug> QueryStorage for SingleCache<V> {
     type Value = V;
-    type Stored = V;
 }
 
 impl<V> QueryCache for SingleCache<V>
@@ -152,9 +143,8 @@ where
     }
 
     #[inline]
-    fn complete(&self, _key: (), value: V, index: DepNodeIndex) -> Self::Stored {
+    fn complete(&self, _key: (), value: V, index: DepNodeIndex) {
         *self.cache.lock() = Some((value, index));
-        value
     }
 
     fn iter(&self, f: &mut dyn FnMut(&Self::Key, &Self::Value, DepNodeIndex)) {
@@ -162,85 +152,12 @@ where
     }
 }
 
-pub struct ArenaCache<'tcx, K, V> {
-    arena: WorkerLocal<TypedArena<(V, DepNodeIndex)>>,
-    #[cfg(parallel_compiler)]
-    cache: Sharded<FxHashMap<K, &'tcx (V, DepNodeIndex)>>,
-    #[cfg(not(parallel_compiler))]
-    cache: Lock<FxHashMap<K, &'tcx (V, DepNodeIndex)>>,
-}
-
-impl<'tcx, K, V> Default for ArenaCache<'tcx, K, V> {
-    fn default() -> Self {
-        ArenaCache { arena: WorkerLocal::new(|_| TypedArena::default()), cache: Default::default() }
-    }
-}
-
-impl<'tcx, K: Eq + Hash, V: Debug + 'tcx> QueryStorage for ArenaCache<'tcx, K, V> {
-    type Value = V;
-    type Stored = &'tcx V;
-}
-
-impl<'tcx, K, V: 'tcx> QueryCache for ArenaCache<'tcx, K, V>
-where
-    K: Eq + Hash + Clone + Debug,
-    V: Debug,
-{
-    type Key = K;
-
-    #[inline(always)]
-    fn lookup(&self, key: &K) -> Option<(&'tcx V, DepNodeIndex)> {
-        let key_hash = sharded::make_hash(key);
-        #[cfg(parallel_compiler)]
-        let lock = self.cache.get_shard_by_hash(key_hash).lock();
-        #[cfg(not(parallel_compiler))]
-        let lock = self.cache.lock();
-        let result = lock.raw_entry().from_key_hashed_nocheck(key_hash, key);
-
-        if let Some((_, value)) = result { Some((&value.0, value.1)) } else { None }
-    }
-
-    #[inline]
-    fn complete(&self, key: K, value: V, index: DepNodeIndex) -> Self::Stored {
-        let value = self.arena.alloc((value, index));
-        let value = unsafe { &*(value as *const _) };
-        #[cfg(parallel_compiler)]
-        let mut lock = self.cache.get_shard_by_value(&key).lock();
-        #[cfg(not(parallel_compiler))]
-        let mut lock = self.cache.lock();
-        // We may be overwriting another value. This is all right, since the dep-graph
-        // will check that the fingerprint matches.
-        lock.insert(key, value);
-        &value.0
-    }
-
-    fn iter(&self, f: &mut dyn FnMut(&Self::Key, &Self::Value, DepNodeIndex)) {
-        #[cfg(parallel_compiler)]
-        {
-            let shards = self.cache.lock_shards();
-            for shard in shards.iter() {
-                for (k, v) in shard.iter() {
-                    f(k, &v.0, v.1);
-                }
-            }
-        }
-        #[cfg(not(parallel_compiler))]
-        {
-            let map = self.cache.lock();
-            for (k, v) in map.iter() {
-                f(k, &v.0, v.1);
-            }
-        }
-    }
-}
-
 pub struct VecCacheSelector<K>(PhantomData<K>);
 
 impl<'tcx, K: Idx, V: 'tcx> CacheSelector<'tcx, V> for VecCacheSelector<K> {
     type Cache = VecCache<K, V>
     where
         V: Copy;
-    type ArenaCache = VecArenaCache<'tcx, K, V>;
 }
 
 pub struct VecCache<K: Idx, V> {
@@ -258,7 +175,6 @@ impl<K: Idx, V> Default for VecCache<K, V> {
 
 impl<K: Eq + Idx, V: Copy + Debug> QueryStorage for VecCache<K, V> {
     type Value = V;
-    type Stored = V;
 }
 
 impl<K, V> QueryCache for VecCache<K, V>
@@ -278,87 +194,12 @@ where
     }
 
     #[inline]
-    fn complete(&self, key: K, value: V, index: DepNodeIndex) -> Self::Stored {
+    fn complete(&self, key: K, value: V, index: DepNodeIndex) {
         #[cfg(parallel_compiler)]
         let mut lock = self.cache.get_shard_by_hash(key.index() as u64).lock();
         #[cfg(not(parallel_compiler))]
         let mut lock = self.cache.lock();
         lock.insert(key, (value, index));
-        value
-    }
-
-    fn iter(&self, f: &mut dyn FnMut(&Self::Key, &Self::Value, DepNodeIndex)) {
-        #[cfg(parallel_compiler)]
-        {
-            let shards = self.cache.lock_shards();
-            for shard in shards.iter() {
-                for (k, v) in shard.iter_enumerated() {
-                    if let Some(v) = v {
-                        f(&k, &v.0, v.1);
-                    }
-                }
-            }
-        }
-        #[cfg(not(parallel_compiler))]
-        {
-            let map = self.cache.lock();
-            for (k, v) in map.iter_enumerated() {
-                if let Some(v) = v {
-                    f(&k, &v.0, v.1);
-                }
-            }
-        }
-    }
-}
-
-pub struct VecArenaCache<'tcx, K: Idx, V> {
-    arena: WorkerLocal<TypedArena<(V, DepNodeIndex)>>,
-    #[cfg(parallel_compiler)]
-    cache: Sharded<IndexVec<K, Option<&'tcx (V, DepNodeIndex)>>>,
-    #[cfg(not(parallel_compiler))]
-    cache: Lock<IndexVec<K, Option<&'tcx (V, DepNodeIndex)>>>,
-}
-
-impl<'tcx, K: Idx, V> Default for VecArenaCache<'tcx, K, V> {
-    fn default() -> Self {
-        VecArenaCache {
-            arena: WorkerLocal::new(|_| TypedArena::default()),
-            cache: Default::default(),
-        }
-    }
-}
-
-impl<'tcx, K: Eq + Idx, V: Debug + 'tcx> QueryStorage for VecArenaCache<'tcx, K, V> {
-    type Value = V;
-    type Stored = &'tcx V;
-}
-
-impl<'tcx, K, V: 'tcx> QueryCache for VecArenaCache<'tcx, K, V>
-where
-    K: Eq + Idx + Clone + Debug,
-    V: Debug,
-{
-    type Key = K;
-
-    #[inline(always)]
-    fn lookup(&self, key: &K) -> Option<(&'tcx V, DepNodeIndex)> {
-        #[cfg(parallel_compiler)]
-        let lock = self.cache.get_shard_by_hash(key.index() as u64).lock();
-        #[cfg(not(parallel_compiler))]
-        let lock = self.cache.lock();
-        if let Some(Some(value)) = lock.get(*key) { Some((&value.0, value.1)) } else { None }
-    }
-
-    #[inline]
-    fn complete(&self, key: K, value: V, index: DepNodeIndex) -> Self::Stored {
-        let value = self.arena.alloc((value, index));
-        let value = unsafe { &*(value as *const _) };
-        #[cfg(parallel_compiler)]
-        let mut lock = self.cache.get_shard_by_hash(key.index() as u64).lock();
-        #[cfg(not(parallel_compiler))]
-        let mut lock = self.cache.lock();
-        lock.insert(key, value);
-        &value.0
     }
 
     fn iter(&self, f: &mut dyn FnMut(&Self::Key, &Self::Value, DepNodeIndex)) {
diff --git a/compiler/rustc_query_system/src/query/config.rs b/compiler/rustc_query_system/src/query/config.rs
index a28e45a5c08..56247e827a2 100644
--- a/compiler/rustc_query_system/src/query/config.rs
+++ b/compiler/rustc_query_system/src/query/config.rs
@@ -20,10 +20,9 @@ pub trait QueryConfig<Qcx: QueryContext> {
     const NAME: &'static str;
 
     type Key: DepNodeParams<Qcx::DepContext> + Eq + Hash + Clone + Debug;
-    type Value: Debug;
-    type Stored: Debug + Copy + std::borrow::Borrow<Self::Value>;
+    type Value: Debug + Copy;
 
-    type Cache: QueryCache<Key = Self::Key, Stored = Self::Stored, Value = Self::Value>;
+    type Cache: QueryCache<Key = Self::Key, Value = Self::Value>;
 
     // Don't use this method to access query results, instead use the methods on TyCtxt
     fn query_state<'a>(tcx: Qcx) -> &'a QueryState<Self::Key, Qcx::DepKind>
@@ -38,9 +37,9 @@ pub trait QueryConfig<Qcx: QueryContext> {
     fn cache_on_disk(tcx: Qcx::DepContext, key: &Self::Key) -> bool;
 
     // Don't use this method to compute query results, instead use the methods on TyCtxt
-    fn execute_query(tcx: Qcx::DepContext, k: Self::Key) -> Self::Stored;
+    fn execute_query(tcx: Qcx::DepContext, k: Self::Key) -> Self::Value;
 
-    fn compute(tcx: Qcx, key: &Self::Key) -> fn(Qcx::DepContext, Self::Key) -> Self::Value;
+    fn compute(tcx: Qcx, key: Self::Key) -> Self::Value;
 
     fn try_load_from_disk(qcx: Qcx, idx: &Self::Key) -> TryLoadFromDisk<Qcx, Self>;
 
diff --git a/compiler/rustc_query_system/src/query/mod.rs b/compiler/rustc_query_system/src/query/mod.rs
index 6c0ee2bc2f6..383c63cd2f8 100644
--- a/compiler/rustc_query_system/src/query/mod.rs
+++ b/compiler/rustc_query_system/src/query/mod.rs
@@ -101,22 +101,22 @@ impl QuerySideEffects {
 }
 
 pub trait QueryContext: HasDepContext {
-    fn next_job_id(&self) -> QueryJobId;
+    fn next_job_id(self) -> QueryJobId;
 
     /// Get the query information from the TLS context.
-    fn current_query_job(&self) -> Option<QueryJobId>;
+    fn current_query_job(self) -> Option<QueryJobId>;
 
-    fn try_collect_active_jobs(&self) -> Option<QueryMap<Self::DepKind>>;
+    fn try_collect_active_jobs(self) -> Option<QueryMap<Self::DepKind>>;
 
     /// Load side effects associated to the node in the previous session.
-    fn load_side_effects(&self, prev_dep_node_index: SerializedDepNodeIndex) -> QuerySideEffects;
+    fn load_side_effects(self, prev_dep_node_index: SerializedDepNodeIndex) -> QuerySideEffects;
 
     /// Register diagnostics for the given node, for use in next session.
-    fn store_side_effects(&self, dep_node_index: DepNodeIndex, side_effects: QuerySideEffects);
+    fn store_side_effects(self, dep_node_index: DepNodeIndex, side_effects: QuerySideEffects);
 
     /// Register diagnostics for the given node, for use in next session.
     fn store_side_effects_for_anon_node(
-        &self,
+        self,
         dep_node_index: DepNodeIndex,
         side_effects: QuerySideEffects,
     );
@@ -125,12 +125,12 @@ pub trait QueryContext: HasDepContext {
     /// new query job while it executes. It returns the diagnostics
     /// captured during execution and the actual result.
     fn start_query<R>(
-        &self,
+        self,
         token: QueryJobId,
         depth_limit: bool,
         diagnostics: Option<&Lock<ThinVec<Diagnostic>>>,
         compute: impl FnOnce() -> R,
     ) -> R;
 
-    fn depth_limit_error(&self, job: QueryJobId);
+    fn depth_limit_error(self, job: QueryJobId);
 }
diff --git a/compiler/rustc_query_system/src/query/plumbing.rs b/compiler/rustc_query_system/src/query/plumbing.rs
index ed66d1929c5..53e04bcc132 100644
--- a/compiler/rustc_query_system/src/query/plumbing.rs
+++ b/compiler/rustc_query_system/src/query/plumbing.rs
@@ -19,7 +19,6 @@ use rustc_data_structures::sync::Lock;
 use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed, FatalError};
 use rustc_session::Session;
 use rustc_span::{Span, DUMMY_SP};
-use std::borrow::Borrow;
 use std::cell::Cell;
 use std::collections::hash_map::Entry;
 use std::fmt::Debug;
@@ -246,7 +245,7 @@ where
 
     /// Completes the query by updating the query cache with the `result`,
     /// signals the waiter and forgets the JobOwner, so it won't poison the query
-    fn complete<C>(self, cache: &C, result: C::Value, dep_node_index: DepNodeIndex) -> C::Stored
+    fn complete<C>(self, cache: &C, result: C::Value, dep_node_index: DepNodeIndex)
     where
         C: QueryCache<Key = K>,
     {
@@ -257,23 +256,19 @@ where
         // Forget ourself so our destructor won't poison the query
         mem::forget(self);
 
-        let (job, result) = {
-            let job = {
-                #[cfg(parallel_compiler)]
-                let mut lock = state.active.get_shard_by_value(&key).lock();
-                #[cfg(not(parallel_compiler))]
-                let mut lock = state.active.lock();
-                match lock.remove(&key).unwrap() {
-                    QueryResult::Started(job) => job,
-                    QueryResult::Poisoned => panic!(),
-                }
-            };
-            let result = cache.complete(key, result, dep_node_index);
-            (job, result)
+        let job = {
+            #[cfg(parallel_compiler)]
+            let mut lock = state.active.get_shard_by_value(&key).lock();
+            #[cfg(not(parallel_compiler))]
+            let mut lock = state.active.lock();
+            match lock.remove(&key).unwrap() {
+                QueryResult::Started(job) => job,
+                QueryResult::Poisoned => panic!(),
+            }
         };
+        cache.complete(key, result, dep_node_index);
 
         job.signal_complete();
-        result
     }
 }
 
@@ -336,7 +331,7 @@ where
 /// which will be used if the query is not in the cache and we need
 /// to compute it.
 #[inline]
-pub fn try_get_cached<Tcx, C>(tcx: Tcx, cache: &C, key: &C::Key) -> Option<C::Stored>
+pub fn try_get_cached<Tcx, C>(tcx: Tcx, cache: &C, key: &C::Key) -> Option<C::Value>
 where
     C: QueryCache,
     Tcx: DepContext,
@@ -358,7 +353,7 @@ fn try_execute_query<Q, Qcx>(
     span: Span,
     key: Q::Key,
     dep_node: Option<DepNode<Qcx::DepKind>>,
-) -> (Q::Stored, Option<DepNodeIndex>)
+) -> (Q::Value, Option<DepNodeIndex>)
 where
     Q: QueryConfig<Qcx>,
     Qcx: QueryContext,
@@ -368,29 +363,17 @@ where
             let (result, dep_node_index) =
                 execute_job::<Q, Qcx>(qcx, key.clone(), dep_node, job.id);
             if Q::FEEDABLE {
-                // We may have put a value inside the cache from inside the execution.
-                // Verify that it has the same hash as what we have now, to ensure consistency.
+                // We should not compute queries that also got a value via feeding.
+                // This can't happen, as query feeding adds the very dependencies to the fed query
+                // as its feeding query had. So if the fed query is red, so is its feeder, which will
+                // get evaluated first, and re-feed the query.
                 if let Some((cached_result, _)) = cache.lookup(&key) {
-                    let hasher = Q::HASH_RESULT.expect("feedable forbids no_hash");
-
-                    let old_hash = qcx.dep_context().with_stable_hashing_context(|mut hcx| {
-                        hasher(&mut hcx, cached_result.borrow())
-                    });
-                    let new_hash = qcx
-                        .dep_context()
-                        .with_stable_hashing_context(|mut hcx| hasher(&mut hcx, &result));
-                    debug_assert_eq!(
-                        old_hash,
-                        new_hash,
-                        "Computed query value for {:?}({:?}) is inconsistent with fed value,\ncomputed={:#?}\nfed={:#?}",
-                        Q::DEP_KIND,
-                        key,
-                        result,
-                        cached_result,
+                    panic!(
+                        "fed query later has its value computed. The already cached value: {cached_result:?}"
                     );
                 }
             }
-            let result = job.complete(cache, result, dep_node_index);
+            job.complete(cache, result, dep_node_index);
             (result, Some(dep_node_index))
         }
         TryGetJob::Cycle(error) => {
@@ -426,9 +409,7 @@ where
     // Fast path for when incr. comp. is off.
     if !dep_graph.is_fully_enabled() {
         let prof_timer = qcx.dep_context().profiler().query_provider();
-        let result = qcx.start_query(job_id, Q::DEPTH_LIMIT, None, || {
-            Q::compute(qcx, &key)(*qcx.dep_context(), key)
-        });
+        let result = qcx.start_query(job_id, Q::DEPTH_LIMIT, None, || Q::compute(qcx, key));
         let dep_node_index = dep_graph.next_virtual_depnode_index();
         prof_timer.finish_with_query_invocation_id(dep_node_index.into());
         return (result, dep_node_index);
@@ -454,17 +435,15 @@ where
     let (result, dep_node_index) =
         qcx.start_query(job_id, Q::DEPTH_LIMIT, Some(&diagnostics), || {
             if Q::ANON {
-                return dep_graph.with_anon_task(*qcx.dep_context(), Q::DEP_KIND, || {
-                    Q::compute(qcx, &key)(*qcx.dep_context(), key)
-                });
+                return dep_graph
+                    .with_anon_task(*qcx.dep_context(), Q::DEP_KIND, || Q::compute(qcx, key));
             }
 
             // `to_dep_node` is expensive for some `DepKind`s.
             let dep_node =
                 dep_node_opt.unwrap_or_else(|| Q::construct_dep_node(*qcx.dep_context(), &key));
 
-            let task = Q::compute(qcx, &key);
-            dep_graph.with_task(dep_node, *qcx.dep_context(), key, task, Q::HASH_RESULT)
+            dep_graph.with_task(dep_node, qcx, key, Q::compute, Q::HASH_RESULT)
         });
 
     prof_timer.finish_with_query_invocation_id(dep_node_index.into());
@@ -555,7 +534,7 @@ where
     let prof_timer = qcx.dep_context().profiler().query_provider();
 
     // The dep-graph for this computation is already in-place.
-    let result = dep_graph.with_ignore(|| Q::compute(qcx, key)(*qcx.dep_context(), key.clone()));
+    let result = dep_graph.with_ignore(|| Q::compute(qcx, key.clone()));
 
     prof_timer.finish_with_query_invocation_id(dep_node_index.into());
 
@@ -727,7 +706,7 @@ pub enum QueryMode {
     Ensure,
 }
 
-pub fn get_query<Q, Qcx, D>(qcx: Qcx, span: Span, key: Q::Key, mode: QueryMode) -> Option<Q::Stored>
+pub fn get_query<Q, Qcx, D>(qcx: Qcx, span: Span, key: Q::Key, mode: QueryMode) -> Option<Q::Value>
 where
     D: DepKind,
     Q: QueryConfig<Qcx>,
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index d3bcbbabf55..324de7461cd 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -21,7 +21,7 @@ use rustc_hir::def::Namespace::{self, *};
 use rustc_hir::def::{self, CtorKind, DefKind, LifetimeRes, PartialRes, PerNS};
 use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID, LOCAL_CRATE};
 use rustc_hir::{BindingAnnotation, PrimTy, TraitCandidate};
-use rustc_middle::middle::resolve_lifetime::Set1;
+use rustc_middle::middle::resolve_bound_vars::Set1;
 use rustc_middle::ty::DefIdTree;
 use rustc_middle::{bug, span_bug};
 use rustc_session::config::{CrateType, ResolveDocLinks};
@@ -2505,7 +2505,13 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
 
             let res = match kind {
                 ItemRibKind(..) | AssocItemRibKind => Res::Def(def_kind, def_id.to_def_id()),
-                NormalRibKind => Res::Err,
+                NormalRibKind => {
+                    if self.r.session.features_untracked().non_lifetime_binders {
+                        Res::Def(def_kind, def_id.to_def_id())
+                    } else {
+                        Res::Err
+                    }
+                }
                 _ => span_bug!(param.ident.span, "Unexpected rib kind {:?}", kind),
             };
             self.r.record_partial_res(param.id, PartialRes::new(res));
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index a3195a64366..5205d055cf9 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -1700,11 +1700,9 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
                                         let crate_mod =
                                             Res::Def(DefKind::Mod, crate_id.as_def_id());
 
-                                        if filter_fn(crate_mod) {
-                                            Some(TypoSuggestion::typo_from_ident(*ident, crate_mod))
-                                        } else {
-                                            None
-                                        }
+                                        filter_fn(crate_mod).then(|| {
+                                            TypoSuggestion::typo_from_ident(*ident, crate_mod)
+                                        })
                                     })
                             }));
 
diff --git a/compiler/rustc_resolve/src/rustdoc.rs b/compiler/rustc_resolve/src/rustdoc.rs
index a967f4b940c..3425e24585c 100644
--- a/compiler/rustc_resolve/src/rustdoc.rs
+++ b/compiler/rustc_resolve/src/rustdoc.rs
@@ -344,7 +344,7 @@ fn preprocess_link(link: &str) -> String {
     let link = link.strip_suffix("()").unwrap_or(link);
     let link = link.strip_suffix("{}").unwrap_or(link);
     let link = link.strip_suffix("[]").unwrap_or(link);
-    let link = if link != "!" { link.strip_suffix("!").unwrap_or(link) } else { link };
+    let link = if link != "!" { link.strip_suffix('!').unwrap_or(link) } else { link };
     strip_generics_from_path(link).unwrap_or_else(|_| link.to_string())
 }
 
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index e8bc19f88e3..295e93f6103 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -1022,7 +1022,13 @@ fn default_configuration(sess: &Session) -> CrateConfig {
     let panic_strategy = sess.panic_strategy();
     ret.insert((sym::panic, Some(panic_strategy.desc_symbol())));
 
-    for s in sess.opts.unstable_opts.sanitizer {
+    for mut s in sess.opts.unstable_opts.sanitizer {
+        // KASAN should use the same attribute name as ASAN, as it's still ASAN
+        // under the hood
+        if s == SanitizerSet::KERNELADDRESS {
+            s = SanitizerSet::ADDRESS;
+        }
+
         let symbol = Symbol::intern(&s.to_string());
         ret.insert((sym::sanitize, Some(symbol)));
     }
@@ -2544,7 +2550,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
         }
 
         // Only use this directory if it has a file we can expect to always find.
-        if candidate.join("library/std/src/lib.rs").is_file() { Some(candidate) } else { None }
+        candidate.join("library/std/src/lib.rs").is_file().then_some(candidate)
     };
 
     let working_dir = std::env::current_dir().unwrap_or_else(|e| {
diff --git a/compiler/rustc_session/src/errors.rs b/compiler/rustc_session/src/errors.rs
index c851145440b..bd32adbbdbb 100644
--- a/compiler/rustc_session/src/errors.rs
+++ b/compiler/rustc_session/src/errors.rs
@@ -4,7 +4,7 @@ use crate::cgu_reuse_tracker::CguReuse;
 use crate::parse::ParseSess;
 use rustc_ast::token;
 use rustc_ast::util::literal::LitError;
-use rustc_errors::MultiSpan;
+use rustc_errors::{error_code, DiagnosticMessage, EmissionGuarantee, IntoDiagnostic, MultiSpan};
 use rustc_macros::Diagnostic;
 use rustc_span::{Span, Symbol};
 use rustc_target::spec::{SplitDebuginfo, StackProtector, TargetTriple};
@@ -27,12 +27,22 @@ pub struct CguNotRecorded<'a> {
     pub cgu_name: &'a str,
 }
 
-#[derive(Diagnostic)]
-#[diag(session_feature_gate_error, code = "E0658")]
-pub struct FeatureGateError<'a> {
-    #[primary_span]
+pub struct FeatureGateError {
     pub span: MultiSpan,
-    pub explain: &'a str,
+    pub explain: DiagnosticMessage,
+}
+
+impl<'a, T: EmissionGuarantee> IntoDiagnostic<'a, T> for FeatureGateError {
+    #[track_caller]
+    fn into_diagnostic(
+        self,
+        handler: &'a rustc_errors::Handler,
+    ) -> rustc_errors::DiagnosticBuilder<'a, T> {
+        let mut diag = handler.struct_diagnostic(self.explain);
+        diag.set_span(self.span);
+        diag.code(error_code!(E0658));
+        diag
+    }
 }
 
 #[derive(Subdiagnostic)]
@@ -322,11 +332,7 @@ pub fn report_lit_error(sess: &ParseSess, err: LitError, lit: token::Lit, span:
                 .take_while(|c| *c != 'i' && *c != 'u')
                 .all(|c| c.to_digit(base).is_some());
 
-        if valid {
-            Some(format!("0{}{}", base_char.to_ascii_lowercase(), &suffix[1..]))
-        } else {
-            None
-        }
+        valid.then(|| format!("0{}{}", base_char.to_ascii_lowercase(), &suffix[1..]))
     }
 
     let token::Lit { kind, symbol, suffix, .. } = lit;
diff --git a/compiler/rustc_session/src/filesearch.rs b/compiler/rustc_session/src/filesearch.rs
index b6a328908ce..2075ed57a94 100644
--- a/compiler/rustc_session/src/filesearch.rs
+++ b/compiler/rustc_session/src/filesearch.rs
@@ -217,7 +217,7 @@ pub fn get_or_default_sysroot() -> Result<PathBuf, String> {
                 // Look for the target rustlib directory in the suspected sysroot.
                 let mut rustlib_path = rustc_target::target_rustlib_path(&p, "dummy");
                 rustlib_path.pop(); // pop off the dummy target.
-                if rustlib_path.exists() { Some(p) } else { None }
+                rustlib_path.exists().then_some(p)
             }
             None => None,
         }
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index d9e68320f8f..0d5818bd39c 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -370,7 +370,7 @@ mod desc {
     pub const parse_opt_panic_strategy: &str = parse_panic_strategy;
     pub const parse_oom_strategy: &str = "either `panic` or `abort`";
     pub const parse_relro_level: &str = "one of: `full`, `partial`, or `off`";
-    pub const parse_sanitizers: &str = "comma separated list of sanitizers: `address`, `cfi`, `hwaddress`, `kcfi`, `leak`, `memory`, `memtag`, `shadow-call-stack`, or `thread`";
+    pub const parse_sanitizers: &str = "comma separated list of sanitizers: `address`, `cfi`, `hwaddress`, `kcfi`, `kernel-address`, `leak`, `memory`, `memtag`, `shadow-call-stack`, or `thread`";
     pub const parse_sanitizer_memory_track_origins: &str = "0, 1, or 2";
     pub const parse_cfguard: &str =
         "either a boolean (`yes`, `no`, `on`, `off`, etc), `checks`, or `nochecks`";
@@ -684,6 +684,7 @@ mod parse {
                     "address" => SanitizerSet::ADDRESS,
                     "cfi" => SanitizerSet::CFI,
                     "kcfi" => SanitizerSet::KCFI,
+                    "kernel-address" => SanitizerSet::KERNELADDRESS,
                     "leak" => SanitizerSet::LEAK,
                     "memory" => SanitizerSet::MEMORY,
                     "memtag" => SanitizerSet::MEMTAG,
@@ -809,7 +810,7 @@ mod parse {
         if v.is_some() {
             let mut bool_arg = None;
             if parse_opt_bool(&mut bool_arg, v) {
-                *slot = if bool_arg.unwrap() { Some(MirSpanview::Statement) } else { None };
+                *slot = bool_arg.unwrap().then_some(MirSpanview::Statement);
                 return true;
             }
         }
@@ -850,7 +851,7 @@ mod parse {
         if v.is_some() {
             let mut bool_arg = None;
             if parse_opt_bool(&mut bool_arg, v) {
-                *slot = if bool_arg.unwrap() { Some(InstrumentCoverage::All) } else { None };
+                *slot = bool_arg.unwrap().then_some(InstrumentCoverage::All);
                 return true;
             }
         }
diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs
index 2aa8ca9e4a9..cbdcc5581e5 100644
--- a/compiler/rustc_session/src/parse.rs
+++ b/compiler/rustc_session/src/parse.rs
@@ -88,7 +88,7 @@ pub fn feature_err<'a>(
     sess: &'a ParseSess,
     feature: Symbol,
     span: impl Into<MultiSpan>,
-    explain: &str,
+    explain: impl Into<DiagnosticMessage>,
 ) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
     feature_err_issue(sess, feature, span, GateIssue::Language, explain)
 }
@@ -103,7 +103,7 @@ pub fn feature_err_issue<'a>(
     feature: Symbol,
     span: impl Into<MultiSpan>,
     issue: GateIssue,
-    explain: &str,
+    explain: impl Into<DiagnosticMessage>,
 ) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
     let span = span.into();
 
@@ -114,7 +114,7 @@ pub fn feature_err_issue<'a>(
             .map(|err| err.cancel());
     }
 
-    let mut err = sess.create_err(FeatureGateError { span, explain });
+    let mut err = sess.create_err(FeatureGateError { span, explain: explain.into() });
     add_feature_diagnostics_for_issue(&mut err, sess, feature, issue);
     err
 }
diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs
index e608b9fe0b3..3dc09854b3c 100644
--- a/compiler/rustc_session/src/session.rs
+++ b/compiler/rustc_session/src/session.rs
@@ -954,10 +954,10 @@ impl Session {
     /// Checks if LLVM lifetime markers should be emitted.
     pub fn emit_lifetime_markers(&self) -> bool {
         self.opts.optimize != config::OptLevel::No
-        // AddressSanitizer uses lifetimes to detect use after scope bugs.
+        // AddressSanitizer and KernelAddressSanitizer uses lifetimes to detect use after scope bugs.
         // MemorySanitizer uses lifetimes to detect use of uninitialized stack variables.
         // HWAddressSanitizer will use lifetimes to detect use after scope bugs in the future.
-        || self.opts.unstable_opts.sanitizer.intersects(SanitizerSet::ADDRESS | SanitizerSet::MEMORY | SanitizerSet::HWADDRESS)
+        || self.opts.unstable_opts.sanitizer.intersects(SanitizerSet::ADDRESS | SanitizerSet::KERNELADDRESS | SanitizerSet::MEMORY | SanitizerSet::HWADDRESS)
     }
 
     pub fn is_proc_macro_attr(&self, attr: &Attribute) -> bool {
diff --git a/compiler/rustc_span/src/def_id.rs b/compiler/rustc_span/src/def_id.rs
index cdda052f529..2340d501d5a 100644
--- a/compiler/rustc_span/src/def_id.rs
+++ b/compiler/rustc_span/src/def_id.rs
@@ -299,7 +299,7 @@ impl DefId {
 
     #[inline]
     pub fn as_local(self) -> Option<LocalDefId> {
-        if self.is_local() { Some(LocalDefId { local_def_index: self.index }) } else { None }
+        self.is_local().then(|| LocalDefId { local_def_index: self.index })
     }
 
     #[inline]
@@ -320,7 +320,7 @@ impl DefId {
 
     #[inline]
     pub fn as_crate_root(self) -> Option<CrateNum> {
-        if self.is_crate_root() { Some(self.krate) } else { None }
+        self.is_crate_root().then_some(self.krate)
     }
 
     #[inline]
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 56835a2466a..37d2aea42ad 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -1016,6 +1016,7 @@ symbols! {
         non_ascii_idents,
         non_exhaustive,
         non_exhaustive_omitted_patterns_lint,
+        non_lifetime_binders,
         non_modrs_mods,
         nontemporal_store,
         noop_method_borrow,
diff --git a/compiler/rustc_symbol_mangling/src/legacy.rs b/compiler/rustc_symbol_mangling/src/legacy.rs
index 23ff6b333f0..744e8a4320e 100644
--- a/compiler/rustc_symbol_mangling/src/legacy.rs
+++ b/compiler/rustc_symbol_mangling/src/legacy.rs
@@ -26,7 +26,7 @@ pub(super) fn mangle<'tcx>(
         let key = tcx.def_key(ty_def_id);
         match key.disambiguated_data.data {
             DefPathData::TypeNs(_) | DefPathData::ValueNs(_) => {
-                instance_ty = tcx.type_of(ty_def_id);
+                instance_ty = tcx.type_of(ty_def_id).subst_identity();
                 debug!(?instance_ty);
                 break;
             }
diff --git a/compiler/rustc_symbol_mangling/src/lib.rs b/compiler/rustc_symbol_mangling/src/lib.rs
index 547a5907660..d81722e59a6 100644
--- a/compiler/rustc_symbol_mangling/src/lib.rs
+++ b/compiler/rustc_symbol_mangling/src/lib.rs
@@ -244,8 +244,7 @@ fn compute_symbol_name<'tcx>(
     // project.
     let avoid_cross_crate_conflicts = is_generic(substs) || is_globally_shared_function;
 
-    let instantiating_crate =
-        if avoid_cross_crate_conflicts { Some(compute_instantiating_crate()) } else { None };
+    let instantiating_crate = avoid_cross_crate_conflicts.then(compute_instantiating_crate);
 
     // Pick the crate responsible for the symbol mangling version, which has to:
     // 1. be stable for each instance, whether it's being defined or imported
diff --git a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs
index 710f3826403..59a2227cd36 100644
--- a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs
+++ b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs
@@ -696,13 +696,13 @@ fn transform_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, options: TransformTyOptio
                 let variant = adt_def.non_enum_variant();
                 let param_env = tcx.param_env(variant.def_id);
                 let field = variant.fields.iter().find(|field| {
-                    let ty = tcx.type_of(field.did);
+                    let ty = tcx.type_of(field.did).subst_identity();
                     let is_zst =
                         tcx.layout_of(param_env.and(ty)).map_or(false, |layout| layout.is_zst());
                     !is_zst
                 });
                 if let Some(field) = field {
-                    let ty0 = tcx.bound_type_of(field.did).subst(tcx, substs);
+                    let ty0 = tcx.type_of(field.did).subst(tcx, substs);
                     // Generalize any repr(transparent) user-defined type that is either a pointer
                     // or reference, and either references itself or any other type that contains or
                     // references itself, to avoid a reference cycle.
@@ -781,8 +781,8 @@ fn transform_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, options: TransformTyOptio
                 let output = transform_ty(tcx, fn_sig.skip_binder().output(), options);
                 ty = tcx.mk_fn_ptr(ty::Binder::bind_with_vars(
                     tcx.mk_fn_sig(
-                        parameters.iter(),
-                        &output,
+                        parameters,
+                        output,
                         fn_sig.c_variadic(),
                         fn_sig.unsafety(),
                         fn_sig.abi(),
@@ -813,21 +813,18 @@ fn transform_substs<'tcx>(
     substs: SubstsRef<'tcx>,
     options: TransformTyOptions,
 ) -> SubstsRef<'tcx> {
-    let substs: Vec<GenericArg<'tcx>> = substs
-        .iter()
-        .map(|subst| {
-            if let GenericArgKind::Type(ty) = subst.unpack() {
-                if is_c_void_ty(tcx, ty) {
-                    tcx.mk_unit().into()
-                } else {
-                    transform_ty(tcx, ty, options).into()
-                }
+    let substs = substs.iter().map(|subst| {
+        if let GenericArgKind::Type(ty) = subst.unpack() {
+            if is_c_void_ty(tcx, ty) {
+                tcx.mk_unit().into()
             } else {
-                subst
+                transform_ty(tcx, ty, options).into()
             }
-        })
-        .collect();
-    tcx.mk_substs(substs.iter())
+        } else {
+            subst
+        }
+    });
+    tcx.mk_substs(substs)
 }
 
 /// Returns a type metadata identifier for the specified FnAbi using the Itanium C++ ABI with vendor
diff --git a/compiler/rustc_target/src/spec/aarch64_apple_ios.rs b/compiler/rustc_target/src/spec/aarch64_apple_ios.rs
index b5f9eb1259d..e9edfd2877b 100644
--- a/compiler/rustc_target/src/spec/aarch64_apple_ios.rs
+++ b/compiler/rustc_target/src/spec/aarch64_apple_ios.rs
@@ -1,8 +1,11 @@
 use super::apple_base::{ios_llvm_target, opts, Arch};
-use crate::spec::{FramePointer, Target, TargetOptions};
+use crate::spec::{FramePointer, SanitizerSet, Target, TargetOptions};
 
 pub fn target() -> Target {
     let arch = Arch::Arm64;
+    let mut base = opts("ios", arch);
+    base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::THREAD;
+
     Target {
         // Clang automatically chooses a more specific target based on
         // IPHONEOS_DEPLOYMENT_TARGET.
@@ -28,7 +31,7 @@ pub fn target() -> Target {
                 darwinpcs\0\
                 -Os\0"
                 .into(),
-            ..opts("ios", arch)
+            ..base
         },
     }
 }
diff --git a/compiler/rustc_target/src/spec/aarch64_apple_ios_sim.rs b/compiler/rustc_target/src/spec/aarch64_apple_ios_sim.rs
index 3374755e2dd..6e2d62b6e08 100644
--- a/compiler/rustc_target/src/spec/aarch64_apple_ios_sim.rs
+++ b/compiler/rustc_target/src/spec/aarch64_apple_ios_sim.rs
@@ -1,8 +1,11 @@
 use super::apple_base::{ios_sim_llvm_target, opts, Arch};
-use crate::spec::{FramePointer, Target, TargetOptions};
+use crate::spec::{FramePointer, SanitizerSet, Target, TargetOptions};
 
 pub fn target() -> Target {
     let arch = Arch::Arm64_sim;
+    let mut base = opts("ios", arch);
+    base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::THREAD;
+
     Target {
         // Clang automatically chooses a more specific target based on
         // IPHONEOS_DEPLOYMENT_TARGET.
@@ -28,7 +31,7 @@ pub fn target() -> Target {
                 darwinpcs\0\
                 -Os\0"
                 .into(),
-            ..opts("ios", arch)
+            ..base
         },
     }
 }
diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_none.rs b/compiler/rustc_target/src/spec/aarch64_unknown_none.rs
index 30fbe6f3c15..be27302f7f5 100644
--- a/compiler/rustc_target/src/spec/aarch64_unknown_none.rs
+++ b/compiler/rustc_target/src/spec/aarch64_unknown_none.rs
@@ -15,7 +15,7 @@ pub fn target() -> Target {
         linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes),
         linker: Some("rust-lld".into()),
         features: "+v8a,+strict-align,+neon,+fp-armv8".into(),
-        supported_sanitizers: SanitizerSet::KCFI,
+        supported_sanitizers: SanitizerSet::KCFI | SanitizerSet::KERNELADDRESS,
         relocation_model: RelocModel::Static,
         disable_redzone: true,
         max_atomic_width: Some(128),
diff --git a/compiler/rustc_target/src/spec/armebv7r_none_eabi.rs b/compiler/rustc_target/src/spec/armebv7r_none_eabi.rs
index 8c65d6afcc1..f6f46aac4c3 100644
--- a/compiler/rustc_target/src/spec/armebv7r_none_eabi.rs
+++ b/compiler/rustc_target/src/spec/armebv7r_none_eabi.rs
@@ -19,7 +19,7 @@ pub fn target() -> Target {
             max_atomic_width: Some(32),
             emit_debug_gdb_scripts: false,
             // GCC and Clang default to 8 for arm-none here
-            c_enum_min_bits: 8,
+            c_enum_min_bits: Some(8),
             ..Default::default()
         },
     }
diff --git a/compiler/rustc_target/src/spec/armebv7r_none_eabihf.rs b/compiler/rustc_target/src/spec/armebv7r_none_eabihf.rs
index 7013bc60d16..9608efe8bcf 100644
--- a/compiler/rustc_target/src/spec/armebv7r_none_eabihf.rs
+++ b/compiler/rustc_target/src/spec/armebv7r_none_eabihf.rs
@@ -20,7 +20,7 @@ pub fn target() -> Target {
             max_atomic_width: Some(32),
             emit_debug_gdb_scripts: false,
             // GCC and Clang default to 8 for arm-none here
-            c_enum_min_bits: 8,
+            c_enum_min_bits: Some(8),
             ..Default::default()
         },
     }
diff --git a/compiler/rustc_target/src/spec/armv4t_none_eabi.rs b/compiler/rustc_target/src/spec/armv4t_none_eabi.rs
index 7ac1aab3b43..28b109889e9 100644
--- a/compiler/rustc_target/src/spec/armv4t_none_eabi.rs
+++ b/compiler/rustc_target/src/spec/armv4t_none_eabi.rs
@@ -49,7 +49,7 @@ pub fn target() -> Target {
             // from thumb_base, rust-lang/rust#44993.
             emit_debug_gdb_scripts: false,
             // from thumb_base, apparently gcc/clang give enums a minimum of 8 bits on no-os targets
-            c_enum_min_bits: 8,
+            c_enum_min_bits: Some(8),
             ..Default::default()
         },
     }
diff --git a/compiler/rustc_target/src/spec/armv7a_none_eabi.rs b/compiler/rustc_target/src/spec/armv7a_none_eabi.rs
index 4e20fb32569..d59de86a230 100644
--- a/compiler/rustc_target/src/spec/armv7a_none_eabi.rs
+++ b/compiler/rustc_target/src/spec/armv7a_none_eabi.rs
@@ -27,7 +27,7 @@ pub fn target() -> Target {
         max_atomic_width: Some(64),
         panic_strategy: PanicStrategy::Abort,
         emit_debug_gdb_scripts: false,
-        c_enum_min_bits: 8,
+        c_enum_min_bits: Some(8),
         ..Default::default()
     };
     Target {
diff --git a/compiler/rustc_target/src/spec/armv7a_none_eabihf.rs b/compiler/rustc_target/src/spec/armv7a_none_eabihf.rs
index ae70129ae51..8cdf3c36ba2 100644
--- a/compiler/rustc_target/src/spec/armv7a_none_eabihf.rs
+++ b/compiler/rustc_target/src/spec/armv7a_none_eabihf.rs
@@ -19,7 +19,7 @@ pub fn target() -> Target {
         panic_strategy: PanicStrategy::Abort,
         emit_debug_gdb_scripts: false,
         // GCC and Clang default to 8 for arm-none here
-        c_enum_min_bits: 8,
+        c_enum_min_bits: Some(8),
         ..Default::default()
     };
     Target {
diff --git a/compiler/rustc_target/src/spec/armv7r_none_eabi.rs b/compiler/rustc_target/src/spec/armv7r_none_eabi.rs
index 25f301ccce7..5225abf44fc 100644
--- a/compiler/rustc_target/src/spec/armv7r_none_eabi.rs
+++ b/compiler/rustc_target/src/spec/armv7r_none_eabi.rs
@@ -18,7 +18,7 @@ pub fn target() -> Target {
             max_atomic_width: Some(32),
             emit_debug_gdb_scripts: false,
             // GCC and Clang default to 8 for arm-none here
-            c_enum_min_bits: 8,
+            c_enum_min_bits: Some(8),
             ..Default::default()
         },
     }
diff --git a/compiler/rustc_target/src/spec/armv7r_none_eabihf.rs b/compiler/rustc_target/src/spec/armv7r_none_eabihf.rs
index 40449759dd3..9a35e04617f 100644
--- a/compiler/rustc_target/src/spec/armv7r_none_eabihf.rs
+++ b/compiler/rustc_target/src/spec/armv7r_none_eabihf.rs
@@ -19,7 +19,7 @@ pub fn target() -> Target {
             max_atomic_width: Some(32),
             emit_debug_gdb_scripts: false,
             // GCC and Clang default to 8 for arm-none here
-            c_enum_min_bits: 8,
+            c_enum_min_bits: Some(8),
             ..Default::default()
         },
     }
diff --git a/compiler/rustc_target/src/spec/hexagon_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/hexagon_unknown_linux_musl.rs
index 3aad05eb271..4c6ab5f5ae4 100644
--- a/compiler/rustc_target/src/spec/hexagon_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/hexagon_unknown_linux_musl.rs
@@ -11,7 +11,7 @@ pub fn target() -> Target {
     base.has_rpath = true;
     base.linker_flavor = LinkerFlavor::Unix(Cc::Yes);
 
-    base.c_enum_min_bits = 8;
+    base.c_enum_min_bits = Some(8);
 
     Target {
         llvm_target: "hexagon-unknown-linux-musl".into(),
diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs
index bc1920e3424..0d86a3032a6 100644
--- a/compiler/rustc_target/src/spec/mod.rs
+++ b/compiler/rustc_target/src/spec/mod.rs
@@ -812,6 +812,7 @@ bitflags::bitflags! {
         const MEMTAG  = 1 << 6;
         const SHADOWCALLSTACK = 1 << 7;
         const KCFI    = 1 << 8;
+        const KERNELADDRESS = 1 << 9;
     }
 }
 
@@ -824,6 +825,7 @@ impl SanitizerSet {
             SanitizerSet::ADDRESS => "address",
             SanitizerSet::CFI => "cfi",
             SanitizerSet::KCFI => "kcfi",
+            SanitizerSet::KERNELADDRESS => "kernel-address",
             SanitizerSet::LEAK => "leak",
             SanitizerSet::MEMORY => "memory",
             SanitizerSet::MEMTAG => "memtag",
@@ -866,6 +868,7 @@ impl IntoIterator for SanitizerSet {
             SanitizerSet::SHADOWCALLSTACK,
             SanitizerSet::THREAD,
             SanitizerSet::HWADDRESS,
+            SanitizerSet::KERNELADDRESS,
         ]
         .iter()
         .copied()
@@ -1344,10 +1347,18 @@ impl Target {
             });
         }
 
-        dl.c_enum_min_size = match Integer::from_size(Size::from_bits(self.c_enum_min_bits)) {
-            Ok(bits) => bits,
-            Err(err) => return Err(TargetDataLayoutErrors::InvalidBitsSize { err }),
-        };
+        dl.c_enum_min_size = self
+            .c_enum_min_bits
+            .map_or_else(
+                || {
+                    self.c_int_width
+                        .parse()
+                        .map_err(|_| String::from("failed to parse c_int_width"))
+                },
+                Ok,
+            )
+            .and_then(|i| Integer::from_size(Size::from_bits(i)))
+            .map_err(|err| TargetDataLayoutErrors::InvalidBitsSize { err })?;
 
         Ok(dl)
     }
@@ -1701,8 +1712,8 @@ pub struct TargetOptions {
     /// If present it's a default value to use for adjusting the C ABI.
     pub default_adjusted_cabi: Option<Abi>,
 
-    /// Minimum number of bits in #[repr(C)] enum. Defaults to 32.
-    pub c_enum_min_bits: u64,
+    /// Minimum number of bits in #[repr(C)] enum. Defaults to the size of c_int
+    pub c_enum_min_bits: Option<u64>,
 
     /// Whether or not the DWARF `.debug_aranges` section should be generated.
     pub generate_arange_section: bool,
@@ -1935,7 +1946,7 @@ impl Default for TargetOptions {
             supported_split_debuginfo: Cow::Borrowed(&[SplitDebuginfo::Off]),
             supported_sanitizers: SanitizerSet::empty(),
             default_adjusted_cabi: None,
-            c_enum_min_bits: 32,
+            c_enum_min_bits: None,
             generate_arange_section: true,
             supports_stack_protector: true,
             entry_name: "main".into(),
@@ -2122,12 +2133,6 @@ impl Target {
                     base.$key_name = s;
                 }
             } );
-            ($key_name:ident, u64) => ( {
-                let name = (stringify!($key_name)).replace("_", "-");
-                if let Some(s) = obj.remove(&name).and_then(|j| Json::as_u64(&j)) {
-                    base.$key_name = s;
-                }
-            } );
             ($key_name:ident, u32) => ( {
                 let name = (stringify!($key_name)).replace("_", "-");
                 if let Some(s) = obj.remove(&name).and_then(|b| b.as_u64()) {
@@ -2339,6 +2344,7 @@ impl Target {
                                 Some("address") => SanitizerSet::ADDRESS,
                                 Some("cfi") => SanitizerSet::CFI,
                                 Some("kcfi") => SanitizerSet::KCFI,
+                                Some("kernel-address") => SanitizerSet::KERNELADDRESS,
                                 Some("leak") => SanitizerSet::LEAK,
                                 Some("memory") => SanitizerSet::MEMORY,
                                 Some("memtag") => SanitizerSet::MEMTAG,
@@ -2496,6 +2502,7 @@ impl Target {
 
         key!(is_builtin, bool);
         key!(c_int_width = "target-c-int-width");
+        key!(c_enum_min_bits, Option<u64>); // if None, matches c_int_width
         key!(os);
         key!(env);
         key!(abi);
@@ -2591,7 +2598,6 @@ impl Target {
         key!(supported_split_debuginfo, falliable_list)?;
         key!(supported_sanitizers, SanitizerSet)?;
         key!(default_adjusted_cabi, Option<Abi>)?;
-        key!(c_enum_min_bits, u64);
         key!(generate_arange_section, bool);
         key!(supports_stack_protector, bool);
         key!(entry_name);
diff --git a/compiler/rustc_target/src/spec/riscv64gc_unknown_none_elf.rs b/compiler/rustc_target/src/spec/riscv64gc_unknown_none_elf.rs
index 409b0b26961..ab3c14e3fe7 100644
--- a/compiler/rustc_target/src/spec/riscv64gc_unknown_none_elf.rs
+++ b/compiler/rustc_target/src/spec/riscv64gc_unknown_none_elf.rs
@@ -1,6 +1,8 @@
 use crate::spec::{Cc, CodeModel, LinkerFlavor, Lld, PanicStrategy};
 use crate::spec::{RelocModel, Target, TargetOptions};
 
+use super::SanitizerSet;
+
 pub fn target() -> Target {
     Target {
         data_layout: "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128".into(),
@@ -20,6 +22,7 @@ pub fn target() -> Target {
             code_model: Some(CodeModel::Medium),
             emit_debug_gdb_scripts: false,
             eh_frame_header: false,
+            supported_sanitizers: SanitizerSet::KERNELADDRESS,
             ..Default::default()
         },
     }
diff --git a/compiler/rustc_target/src/spec/riscv64imac_unknown_none_elf.rs b/compiler/rustc_target/src/spec/riscv64imac_unknown_none_elf.rs
index 87aba9171b4..0f1821c9985 100644
--- a/compiler/rustc_target/src/spec/riscv64imac_unknown_none_elf.rs
+++ b/compiler/rustc_target/src/spec/riscv64imac_unknown_none_elf.rs
@@ -1,5 +1,5 @@
 use crate::spec::{Cc, CodeModel, LinkerFlavor, Lld, PanicStrategy};
-use crate::spec::{RelocModel, Target, TargetOptions};
+use crate::spec::{RelocModel, SanitizerSet, Target, TargetOptions};
 
 pub fn target() -> Target {
     Target {
@@ -19,6 +19,7 @@ pub fn target() -> Target {
             code_model: Some(CodeModel::Medium),
             emit_debug_gdb_scripts: false,
             eh_frame_header: false,
+            supported_sanitizers: SanitizerSet::KERNELADDRESS,
             ..Default::default()
         },
     }
diff --git a/compiler/rustc_target/src/spec/thumb_base.rs b/compiler/rustc_target/src/spec/thumb_base.rs
index 000766c57ce..4dcf47fe465 100644
--- a/compiler/rustc_target/src/spec/thumb_base.rs
+++ b/compiler/rustc_target/src/spec/thumb_base.rs
@@ -53,7 +53,7 @@ pub fn opts() -> TargetOptions {
         frame_pointer: FramePointer::Always,
         // ARM supports multiple ABIs for enums, the linux one matches the default of 32 here
         // but any arm-none or thumb-none target will be defaulted to 8 on GCC and clang
-        c_enum_min_bits: 8,
+        c_enum_min_bits: Some(8),
         ..Default::default()
     }
 }
diff --git a/compiler/rustc_target/src/spec/thumbv4t_none_eabi.rs b/compiler/rustc_target/src/spec/thumbv4t_none_eabi.rs
index 5a3e4c88d3a..e3734932f88 100644
--- a/compiler/rustc_target/src/spec/thumbv4t_none_eabi.rs
+++ b/compiler/rustc_target/src/spec/thumbv4t_none_eabi.rs
@@ -55,7 +55,7 @@ pub fn target() -> Target {
             // suggested from thumb_base, rust-lang/rust#44993.
             emit_debug_gdb_scripts: false,
             // suggested from thumb_base, with no-os gcc/clang use 8-bit enums
-            c_enum_min_bits: 8,
+            c_enum_min_bits: Some(8),
             frame_pointer: FramePointer::MayOmit,
 
             main_needs_argc_argv: false,
diff --git a/compiler/rustc_target/src/spec/x86_64_apple_ios.rs b/compiler/rustc_target/src/spec/x86_64_apple_ios.rs
index fbd3ebd4d04..1dcb47056a4 100644
--- a/compiler/rustc_target/src/spec/x86_64_apple_ios.rs
+++ b/compiler/rustc_target/src/spec/x86_64_apple_ios.rs
@@ -1,8 +1,11 @@
 use super::apple_base::{ios_sim_llvm_target, opts, Arch};
-use crate::spec::{StackProbeType, Target, TargetOptions};
+use crate::spec::{SanitizerSet, StackProbeType, Target, TargetOptions};
 
 pub fn target() -> Target {
     let arch = Arch::X86_64_sim;
+    let mut base = opts("ios", arch);
+    base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::THREAD;
+
     Target {
         llvm_target: ios_sim_llvm_target(arch).into(),
         pointer_width: 64,
@@ -12,7 +15,7 @@ pub fn target() -> Target {
         options: TargetOptions {
             max_atomic_width: Some(64),
             stack_probes: StackProbeType::X86,
-            ..opts("ios", arch)
+            ..base
         },
     }
 }
diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_none.rs b/compiler/rustc_target/src/spec/x86_64_unknown_none.rs
index 32060c35c11..43c5ce78ce3 100644
--- a/compiler/rustc_target/src/spec/x86_64_unknown_none.rs
+++ b/compiler/rustc_target/src/spec/x86_64_unknown_none.rs
@@ -20,7 +20,7 @@ pub fn target() -> Target {
         features:
             "-mmx,-sse,-sse2,-sse3,-ssse3,-sse4.1,-sse4.2,-3dnow,-3dnowa,-avx,-avx2,+soft-float"
                 .into(),
-        supported_sanitizers: SanitizerSet::KCFI,
+        supported_sanitizers: SanitizerSet::KCFI | SanitizerSet::KERNELADDRESS,
         disable_redzone: true,
         panic_strategy: PanicStrategy::Abort,
         code_model: Some(CodeModel::Kernel),
diff --git a/compiler/rustc_trait_selection/src/solve/mod.rs b/compiler/rustc_trait_selection/src/solve/mod.rs
index 28aa3d52705..6890811fd04 100644
--- a/compiler/rustc_trait_selection/src/solve/mod.rs
+++ b/compiler/rustc_trait_selection/src/solve/mod.rs
@@ -25,7 +25,7 @@ use rustc_infer::traits::query::NoSolution;
 use rustc_infer::traits::Obligation;
 use rustc_middle::infer::canonical::Certainty as OldCertainty;
 use rustc_middle::traits::solve::{ExternalConstraints, ExternalConstraintsData};
-use rustc_middle::ty::{self, TyCtxt};
+use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_middle::ty::{
     CoercePredicate, RegionOutlivesPredicate, SubtypePredicate, ToPredicate, TypeOutlivesPredicate,
 };
@@ -290,6 +290,9 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
                 ty::PredicateKind::Clause(ty::Clause::RegionOutlives(predicate)) => {
                     self.compute_region_outlives_goal(Goal { param_env, predicate })
                 }
+                ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(ct, ty)) => {
+                    self.compute_const_arg_has_type_goal(Goal { param_env, predicate: (ct, ty) })
+                }
                 ty::PredicateKind::Subtype(predicate) => {
                     self.compute_subtype_goal(Goal { param_env, predicate })
                 }
@@ -471,6 +474,16 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
             }
         }
     }
+
+    #[instrument(level = "debug", skip(self), ret)]
+    fn compute_const_arg_has_type_goal(
+        &mut self,
+        goal: Goal<'tcx, (ty::Const<'tcx>, Ty<'tcx>)>,
+    ) -> QueryResult<'tcx> {
+        let (ct, ty) = goal.predicate;
+        let nested_goals = self.infcx.eq(goal.param_env, ct.ty(), ty)?;
+        self.evaluate_all_and_make_canonical_response(nested_goals)
+    }
 }
 
 impl<'tcx> EvalCtxt<'_, 'tcx> {
diff --git a/compiler/rustc_trait_selection/src/solve/project_goals.rs b/compiler/rustc_trait_selection/src/solve/project_goals.rs
index b52200e066f..883342148f4 100644
--- a/compiler/rustc_trait_selection/src/solve/project_goals.rs
+++ b/compiler/rustc_trait_selection/src/solve/project_goals.rs
@@ -244,7 +244,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
 
             // Finally we construct the actual value of the associated type.
             let is_const = matches!(tcx.def_kind(assoc_def.item.def_id), DefKind::AssocConst);
-            let ty = tcx.bound_type_of(assoc_def.item.def_id);
+            let ty = tcx.type_of(assoc_def.item.def_id);
             let term: ty::EarlyBinder<ty::Term<'tcx>> = if is_const {
                 let identity_substs =
                     ty::InternalSubsts::identity_for_item(tcx, assoc_def.item.def_id);
@@ -388,7 +388,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
 
                 ty::Dynamic(_, _, _) => {
                     let dyn_metadata = tcx.require_lang_item(LangItem::DynMetadata, None);
-                    tcx.bound_type_of(dyn_metadata)
+                    tcx.type_of(dyn_metadata)
                         .subst(tcx, &[ty::GenericArg::from(goal.predicate.self_ty())])
                 }
 
diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals.rs b/compiler/rustc_trait_selection/src/solve/trait_goals.rs
index 6554c739b3f..d12e5f797fb 100644
--- a/compiler/rustc_trait_selection/src/solve/trait_goals.rs
+++ b/compiler/rustc_trait_selection/src/solve/trait_goals.rs
@@ -326,7 +326,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
                         .fields
                         .last()
                         .expect("expected unsized ADT to have a tail field");
-                    let tail_field_ty = tcx.bound_type_of(tail_field.did);
+                    let tail_field_ty = tcx.type_of(tail_field.did);
 
                     let a_tail_ty = tail_field_ty.subst(tcx, a_substs);
                     let b_tail_ty = tail_field_ty.subst(tcx, b_substs);
@@ -359,7 +359,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
                     let b_last_ty = b_tys.last().unwrap();
 
                     // Substitute just the tail field of B., and require that they're equal.
-                    let unsized_a_ty = tcx.mk_tup(a_rest_tys.iter().chain([b_last_ty]));
+                    let unsized_a_ty = tcx.mk_tup(a_rest_tys.iter().chain([b_last_ty]).copied());
                     let mut nested_goals = ecx.infcx.eq(goal.param_env, unsized_a_ty, b_ty)?;
 
                     // Similar to ADTs, require that the rest of the fields are equal.
diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals/structural_traits.rs b/compiler/rustc_trait_selection/src/solve/trait_goals/structural_traits.rs
index 1ee35a86e62..3662463178f 100644
--- a/compiler/rustc_trait_selection/src/solve/trait_goals/structural_traits.rs
+++ b/compiler/rustc_trait_selection/src/solve/trait_goals/structural_traits.rs
@@ -68,7 +68,7 @@ pub(super) fn instantiate_constituent_tys_for_auto_trait<'tcx>(
             // We can resolve the `impl Trait` to its concrete type,
             // which enforces a DAG between the functions requiring
             // the auto trait bounds in question.
-            Ok(vec![tcx.bound_type_of(def_id).subst(tcx, substs)])
+            Ok(vec![tcx.type_of(def_id).subst(tcx, substs)])
         }
     }
 }
@@ -191,10 +191,10 @@ pub(crate) fn extract_tupled_inputs_and_output_from_callable<'tcx>(
         ty::FnDef(def_id, substs) => Ok(Some(
             tcx.fn_sig(def_id)
                 .subst(tcx, substs)
-                .map_bound(|sig| (tcx.mk_tup(sig.inputs().iter()), sig.output())),
+                .map_bound(|sig| (tcx.intern_tup(sig.inputs()), sig.output())),
         )),
         ty::FnPtr(sig) => {
-            Ok(Some(sig.map_bound(|sig| (tcx.mk_tup(sig.inputs().iter()), sig.output()))))
+            Ok(Some(sig.map_bound(|sig| (tcx.intern_tup(sig.inputs()), sig.output()))))
         }
         ty::Closure(_, substs) => {
             let closure_substs = substs.as_closure();
diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs
index 3adb15cb441..9776cc57af8 100644
--- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs
+++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs
@@ -830,6 +830,7 @@ impl<'tcx> AutoTraitFinder<'tcx> {
                 // and these don't correspond to adding any new bounds to
                 // the `ParamEnv`.
                 ty::PredicateKind::WellFormed(..)
+                | ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..))
                 | ty::PredicateKind::AliasEq(..)
                 | ty::PredicateKind::ObjectSafe(..)
                 | ty::PredicateKind::ClosureKind(..)
diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs
index a95694e5144..599238e405d 100644
--- a/compiler/rustc_trait_selection/src/traits/coherence.rs
+++ b/compiler/rustc_trait_selection/src/traits/coherence.rs
@@ -82,8 +82,8 @@ pub fn overlapping_impls(
         (Some(a), Some(b)) => iter::zip(a.skip_binder().substs, b.skip_binder().substs)
             .all(|(arg1, arg2)| drcx.generic_args_may_unify(arg1, arg2)),
         (None, None) => {
-            let self_ty1 = tcx.type_of(impl1_def_id);
-            let self_ty2 = tcx.type_of(impl2_def_id);
+            let self_ty1 = tcx.type_of(impl1_def_id).skip_binder();
+            let self_ty2 = tcx.type_of(impl2_def_id).skip_binder();
             drcx.types_may_unify(self_ty1, self_ty2)
         }
         _ => bug!("unexpected impls: {impl1_def_id:?} {impl2_def_id:?}"),
@@ -124,7 +124,7 @@ fn with_fresh_ty_vars<'cx, 'tcx>(
 
     let header = ty::ImplHeader {
         impl_def_id,
-        self_ty: tcx.bound_type_of(impl_def_id).subst(tcx, impl_substs),
+        self_ty: tcx.type_of(impl_def_id).subst(tcx, impl_substs),
         trait_ref: tcx.impl_trait_ref(impl_def_id).map(|i| i.subst(tcx, impl_substs)),
         predicates: tcx.predicates_of(impl_def_id).instantiate(tcx, impl_substs).predicates,
     };
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
index edb36b4ac81..a32ab16263a 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
@@ -1282,6 +1282,13 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                         span,
                         "AliasEq predicate should never be the predicate cause of a SelectionError"
                     ),
+
+                    ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(ct, ty)) => {
+                        self.tcx.sess.struct_span_err(
+                            span,
+                            &format!("the constant `{}` is not of type `{}`", ct, ty),
+                        )
+                    }
                 }
             }
 
@@ -2432,7 +2439,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                             };
                             let mut suggestions = vec![(
                                 path.span.shrink_to_lo(),
-                                format!("<{} as ", self.tcx.type_of(impl_def_id))
+                                format!("<{} as ", self.tcx.type_of(impl_def_id).subst_identity())
                             )];
                             if let Some(generic_arg) = trait_path_segment.args {
                                 let between_span = trait_path_segment.ident.span.between(generic_arg.span_ext);
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs
index 52ed64868c0..b3bf9ad599a 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs
@@ -60,7 +60,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
     ) -> Option<(DefId, SubstsRef<'tcx>)> {
         let tcx = self.tcx;
         let param_env = obligation.param_env;
-        let trait_ref = tcx.erase_late_bound_regions(trait_ref);
+        let trait_ref = self.instantiate_binder_with_placeholders(trait_ref);
         let trait_self_ty = trait_ref.self_ty();
 
         let mut self_match_impls = vec![];
@@ -200,7 +200,10 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
             if let Some(def) = self_ty.ty_adt_def() {
                 // We also want to be able to select self's original
                 // signature with no type arguments resolved
-                flags.push((sym::_Self, Some(self.tcx.type_of(def.did()).to_string())));
+                flags.push((
+                    sym::_Self,
+                    Some(self.tcx.type_of(def.did()).subst_identity().to_string()),
+                ));
             }
 
             for param in generics.params.iter() {
@@ -218,7 +221,10 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                     if let Some(def) = param_ty.ty_adt_def() {
                         // We also want to be able to select the parameter's
                         // original signature with no type arguments resolved
-                        flags.push((name, Some(self.tcx.type_of(def.did()).to_string())));
+                        flags.push((
+                            name,
+                            Some(self.tcx.type_of(def.did()).subst_identity().to_string()),
+                        ));
                     }
                 }
             }
@@ -251,7 +257,10 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                 if let Some(def) = aty.ty_adt_def() {
                     // We also want to be able to select the slice's type's original
                     // signature with no type arguments resolved
-                    flags.push((sym::_Self, Some(format!("[{}]", self.tcx.type_of(def.did())))));
+                    flags.push((
+                        sym::_Self,
+                        Some(format!("[{}]", self.tcx.type_of(def.did()).subst_identity())),
+                    ));
                 }
                 if aty.is_integral() {
                     flags.push((sym::_Self, Some("[{integral}]".to_string())));
@@ -269,7 +278,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                 if let Some(def) = aty.ty_adt_def() {
                     // We also want to be able to select the array's type's original
                     // signature with no type arguments resolved
-                    let def_ty = self.tcx.type_of(def.did());
+                    let def_ty = self.tcx.type_of(def.did()).subst_identity();
                     flags.push((sym::_Self, Some(format!("[{def_ty}; _]"))));
                     if let Some(n) = len {
                         flags.push((sym::_Self, Some(format!("[{def_ty}; {n}]"))));
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
index 135232d1b20..91b463800a8 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -82,11 +82,8 @@ impl<'tcx, 'a> GeneratorData<'tcx, 'a> {
                     upvars.iter().find_map(|(upvar_id, upvar)| {
                         let upvar_ty = typeck_results.node_type(*upvar_id);
                         let upvar_ty = infer_context.resolve_vars_if_possible(upvar_ty);
-                        if ty_matches(ty::Binder::dummy(upvar_ty)) {
-                            Some(GeneratorInteriorOrUpvar::Upvar(upvar.span))
-                        } else {
-                            None
-                        }
+                        ty_matches(ty::Binder::dummy(upvar_ty))
+                            .then(|| GeneratorInteriorOrUpvar::Upvar(upvar.span))
                     })
                 })
             }
@@ -770,15 +767,13 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                             obligation.param_env,
                             real_trait_pred_and_ty,
                         );
-                        if obligations
+                        let may_hold = obligations
                             .iter()
                             .chain([&obligation])
                             .all(|obligation| self.predicate_may_hold(obligation))
-                        {
-                            Some(steps)
-                        } else {
-                            None
-                        }
+                            .then_some(steps);
+
+                        may_hold
                     })
                 {
                     if steps > 0 {
@@ -1061,7 +1056,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
         trait_pred: ty::PolyTraitPredicate<'tcx>,
     ) -> bool {
         let self_ty = self.resolve_vars_if_possible(trait_pred.self_ty());
-        let ty = self.tcx.erase_late_bound_regions(self_ty);
+        let ty = self.instantiate_binder_with_placeholders(self_ty);
         let Some(generics) = self.tcx.hir().get_generics(obligation.cause.body_id) else { return false };
         let ty::Ref(_, inner_ty, hir::Mutability::Not) = ty.kind() else { return false };
         let ty::Param(param) = inner_ty.kind() else { return false };
@@ -2017,7 +2012,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
             let sig = match inputs.kind() {
                 ty::Tuple(inputs) if infcx.tcx.is_fn_trait(trait_ref.def_id()) => {
                     infcx.tcx.mk_fn_sig(
-                        inputs.iter(),
+                        *inputs,
                         infcx.next_ty_var(TypeVariableOrigin {
                             span: DUMMY_SP,
                             kind: TypeVariableOriginKind::MiscVariable,
@@ -2028,7 +2023,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                     )
                 }
                 _ => infcx.tcx.mk_fn_sig(
-                    std::iter::once(inputs),
+                    [inputs],
                     infcx.next_ty_var(TypeVariableOrigin {
                         span: DUMMY_SP,
                         kind: TypeVariableOriginKind::MiscVariable,
@@ -3148,7 +3143,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                     parent_trait_pred.print_modifiers_and_trait_path()
                 );
                 let mut is_auto_trait = false;
-                match self.tcx.hir().get_if_local(data.impl_def_id) {
+                match self.tcx.hir().get_if_local(data.impl_or_alias_def_id) {
                     Some(Node::Item(hir::Item {
                         kind: hir::ItemKind::Trait(is_auto, ..),
                         ident,
diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs
index 19d47d33f67..deeed930e50 100644
--- a/compiler/rustc_trait_selection/src/traits/fulfill.rs
+++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs
@@ -313,6 +313,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
                 }
                 ty::PredicateKind::Clause(ty::Clause::RegionOutlives(_))
                 | ty::PredicateKind::Clause(ty::Clause::TypeOutlives(_))
+                | ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..))
                 | ty::PredicateKind::WellFormed(_)
                 | ty::PredicateKind::ObjectSafe(_)
                 | ty::PredicateKind::ClosureKind(..)
@@ -600,6 +601,19 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
                 ty::PredicateKind::AliasEq(..) => {
                     bug!("AliasEq is only used for new solver")
                 }
+                ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(ct, ty)) => {
+                    match self
+                        .selcx
+                        .infcx
+                        .at(&obligation.cause, obligation.param_env)
+                        .eq(ct.ty(), ty)
+                    {
+                        Ok(inf_ok) => ProcessResult::Changed(mk_pending(inf_ok.into_obligations())),
+                        Err(_) => ProcessResult::Error(FulfillmentErrorCode::CodeSelectionError(
+                            SelectionError::Unimplemented,
+                        )),
+                    }
+                }
             },
         }
     }
diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs
index 41ee8cd9d3f..2d299486ee6 100644
--- a/compiler/rustc_trait_selection/src/traits/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/mod.rs
@@ -523,16 +523,14 @@ fn is_impossible_method(tcx: TyCtxt<'_>, (impl_def_id, trait_item_def_id): (DefI
 
     let mut visitor = ReferencesOnlyParentGenerics { tcx, generics, trait_item_def_id };
     let predicates_for_trait = predicates.predicates.iter().filter_map(|(pred, span)| {
-        if pred.visit_with(&mut visitor).is_continue() {
-            Some(Obligation::new(
+        pred.visit_with(&mut visitor).is_continue().then(|| {
+            Obligation::new(
                 tcx,
                 ObligationCause::dummy_with_span(*span),
                 param_env,
                 ty::EarlyBinder(*pred).subst(tcx, impl_trait_ref.substs),
-            ))
-        } else {
-            None
-        }
+            )
+        })
     });
 
     let infcx = tcx.infer_ctxt().ignoring_regions().build();
diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs
index 7ef39b20107..df1aeed941d 100644
--- a/compiler/rustc_trait_selection/src/traits/object_safety.rs
+++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs
@@ -97,7 +97,7 @@ fn check_is_object_safe(tcx: TyCtxt<'_>, trait_def_id: DefId) -> bool {
 /// object. Note that object-safe traits can have some
 /// non-vtable-safe methods, so long as they require `Self: Sized` or
 /// otherwise ensure that they cannot be used when `Self = Trait`.
-pub fn is_vtable_safe_method(tcx: TyCtxt<'_>, trait_def_id: DefId, method: &ty::AssocItem) -> bool {
+pub fn is_vtable_safe_method(tcx: TyCtxt<'_>, trait_def_id: DefId, method: ty::AssocItem) -> bool {
     debug_assert!(tcx.generics_of(trait_def_id).has_self);
     debug!("is_vtable_safe_method({:?}, {:?})", trait_def_id, method);
     // Any method that has a `Self: Sized` bound cannot be called.
@@ -120,8 +120,8 @@ fn object_safety_violations_for_trait(
         .associated_items(trait_def_id)
         .in_definition_order()
         .filter(|item| item.kind == ty::AssocKind::Fn)
-        .filter_map(|item| {
-            object_safety_violation_for_method(tcx, trait_def_id, &item)
+        .filter_map(|&item| {
+            object_safety_violation_for_method(tcx, trait_def_id, item)
                 .map(|(code, span)| ObjectSafetyViolation::Method(item.name, code, span))
         })
         .collect();
@@ -307,7 +307,7 @@ fn predicate_references_self<'tcx>(
     match predicate.kind().skip_binder() {
         ty::PredicateKind::Clause(ty::Clause::Trait(ref data)) => {
             // In the case of a trait predicate, we can skip the "self" type.
-            if data.trait_ref.substs[1..].iter().any(has_self_ty) { Some(sp) } else { None }
+            data.trait_ref.substs[1..].iter().any(has_self_ty).then_some(sp)
         }
         ty::PredicateKind::Clause(ty::Clause::Projection(ref data)) => {
             // And similarly for projections. This should be redundant with
@@ -325,8 +325,12 @@ fn predicate_references_self<'tcx>(
             //
             // This is ALT2 in issue #56288, see that for discussion of the
             // possible alternatives.
-            if data.projection_ty.substs[1..].iter().any(has_self_ty) { Some(sp) } else { None }
+            data.projection_ty.substs[1..].iter().any(has_self_ty).then_some(sp)
         }
+        ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(_ct, ty)) => {
+            has_self_ty(&ty.into()).then_some(sp)
+        }
+
         ty::PredicateKind::AliasEq(..) => bug!("`AliasEq` not allowed as assumption"),
 
         ty::PredicateKind::WellFormed(..)
@@ -362,6 +366,7 @@ fn generics_require_sized_self(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
                 trait_pred.def_id() == sized_def_id && trait_pred.self_ty().is_param(0)
             }
             ty::PredicateKind::Clause(ty::Clause::Projection(..))
+            | ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..))
             | ty::PredicateKind::Subtype(..)
             | ty::PredicateKind::Coerce(..)
             | ty::PredicateKind::Clause(ty::Clause::RegionOutlives(..))
@@ -382,7 +387,7 @@ fn generics_require_sized_self(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
 fn object_safety_violation_for_method(
     tcx: TyCtxt<'_>,
     trait_def_id: DefId,
-    method: &ty::AssocItem,
+    method: ty::AssocItem,
 ) -> Option<(MethodViolationCode, Span)> {
     debug!("object_safety_violation_for_method({:?}, {:?})", trait_def_id, method);
     // Any method that has a `Self : Sized` requisite is otherwise
@@ -415,7 +420,7 @@ fn object_safety_violation_for_method(
 fn virtual_call_violation_for_method<'tcx>(
     tcx: TyCtxt<'tcx>,
     trait_def_id: DefId,
-    method: &ty::AssocItem,
+    method: ty::AssocItem,
 ) -> Option<MethodViolationCode> {
     let sig = tcx.fn_sig(method.def_id).subst_identity();
 
@@ -527,8 +532,7 @@ fn virtual_call_violation_for_method<'tcx>(
                 }
             }
 
-            let trait_object_ty =
-                object_ty_for_trait(tcx, trait_def_id, tcx.mk_region(ty::ReStatic));
+            let trait_object_ty = object_ty_for_trait(tcx, trait_def_id, tcx.lifetimes.re_static);
 
             // e.g., `Rc<dyn Trait>`
             let trait_object_receiver =
@@ -718,7 +722,7 @@ fn object_ty_for_trait<'tcx>(
 #[allow(dead_code)]
 fn receiver_is_dispatchable<'tcx>(
     tcx: TyCtxt<'tcx>,
-    method: &ty::AssocItem,
+    method: ty::AssocItem,
     receiver_ty: Ty<'tcx>,
 ) -> bool {
     debug!("receiver_is_dispatchable: method = {:?}, receiver_ty = {:?}", method, receiver_ty);
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index a380d4697ea..9b3249e58e8 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -514,7 +514,7 @@ impl<'a, 'b, 'tcx> TypeFolder<TyCtxt<'tcx>> for AssocTypeNormalizer<'a, 'b, 'tcx
                         }
 
                         let substs = substs.fold_with(self);
-                        let generic_ty = self.interner().bound_type_of(def_id);
+                        let generic_ty = self.interner().type_of(def_id);
                         let concrete_ty = generic_ty.subst(self.interner(), substs);
                         self.depth += 1;
                         let folded_ty = self.fold_ty(concrete_ty);
@@ -767,7 +767,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for BoundVarReplacer<'_, 'tcx> {
                 let universe = self.universe_for(debruijn);
                 let p = ty::PlaceholderRegion { universe, name: br.kind };
                 self.mapped_regions.insert(p, br);
-                self.infcx.tcx.mk_region(ty::RePlaceholder(p))
+                self.infcx.tcx.mk_re_placeholder(p)
             }
             _ => r,
         }
@@ -888,7 +888,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for PlaceholderReplacer<'_, 'tcx> {
                         let db = ty::DebruijnIndex::from_usize(
                             self.universe_indices.len() - index + self.current_index.as_usize() - 1,
                         );
-                        self.interner().mk_region(ty::ReLateBound(db, *replace_var))
+                        self.interner().mk_re_late_bound(db, *replace_var)
                     }
                     None => r1,
                 }
@@ -1923,7 +1923,7 @@ fn confirm_builtin_candidate<'cx, 'tcx>(
 ) -> Progress<'tcx> {
     let tcx = selcx.tcx();
     let self_ty = obligation.predicate.self_ty();
-    let substs = tcx.mk_substs([self_ty.into()].iter());
+    let substs = tcx.intern_substs(&[self_ty.into()]);
     let lang_items = tcx.lang_items();
     let item_def_id = obligation.predicate.def_id;
     let trait_def_id = tcx.trait_of_item(item_def_id).unwrap();
@@ -2138,7 +2138,7 @@ fn confirm_impl_candidate<'cx, 'tcx>(
     let substs = obligation.predicate.substs.rebase_onto(tcx, trait_def_id, substs);
     let substs =
         translate_substs(selcx.infcx, param_env, impl_def_id, substs, assoc_ty.defining_node);
-    let ty = tcx.bound_type_of(assoc_ty.item.def_id);
+    let ty = tcx.type_of(assoc_ty.item.def_id);
     let is_const = matches!(tcx.def_kind(assoc_ty.item.def_id), DefKind::AssocConst);
     let term: ty::EarlyBinder<ty::Term<'tcx>> = if is_const {
         let identity_substs =
@@ -2149,7 +2149,7 @@ fn confirm_impl_candidate<'cx, 'tcx>(
     } else {
         ty.map_bound(|ty| ty.into())
     };
-    if !check_substs_compatible(tcx, &assoc_ty.item, substs) {
+    if !check_substs_compatible(tcx, assoc_ty.item, substs) {
         let err = tcx.ty_error_with_message(
             obligation.cause.span,
             "impl item and trait item have different parameters",
@@ -2164,7 +2164,7 @@ fn confirm_impl_candidate<'cx, 'tcx>(
 // Verify that the trait item and its implementation have compatible substs lists
 fn check_substs_compatible<'tcx>(
     tcx: TyCtxt<'tcx>,
-    assoc_item: &ty::AssocItem,
+    assoc_item: ty::AssocItem,
     substs: ty::SubstsRef<'tcx>,
 ) -> bool {
     fn check_substs_compatible_inner<'tcx>(
@@ -2238,7 +2238,7 @@ fn confirm_impl_trait_in_trait_candidate<'tcx>(
         leaf_def.defining_node,
     );
 
-    if !check_substs_compatible(tcx, &leaf_def.item, impl_fn_substs) {
+    if !check_substs_compatible(tcx, leaf_def.item, impl_fn_substs) {
         let err = tcx.ty_error_with_message(
             obligation.cause.span,
             "impl method and trait method have different parameters",
diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs
index e7282a450f6..a266013b8fd 100644
--- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs
@@ -228,7 +228,7 @@ impl<'cx, 'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for QueryNormalizer<'cx, 'tcx>
                             return ty.try_super_fold_with(self);
                         }
 
-                        let generic_ty = self.interner().bound_type_of(def_id);
+                        let generic_ty = self.interner().type_of(def_id);
                         let concrete_ty = generic_ty.subst(self.interner(), substs);
                         self.anon_depth += 1;
                         if concrete_ty == ty {
diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/outlives.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/outlives.rs
index 0d42cd8250a..21ef4e24fdb 100644
--- a/compiler/rustc_trait_selection/src/traits/query/type_op/outlives.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/type_op/outlives.rs
@@ -21,11 +21,7 @@ impl<'tcx> super::QueryTypeOp<'tcx> for DropckOutlives<'tcx> {
         tcx: TyCtxt<'tcx>,
         key: &ParamEnvAnd<'tcx, Self>,
     ) -> Option<Self::QueryResponse> {
-        if trivial_dropck_outlives(tcx, key.value.dropped_ty) {
-            Some(DropckOutlivesResult::default())
-        } else {
-            None
-        }
+        trivial_dropck_outlives(tcx, key.value.dropped_ty).then(DropckOutlivesResult::default)
     }
 
     fn perform_query(
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 e9f7c3bc4cc..dae602908a3 100644
--- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
@@ -396,7 +396,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                     // still be provided by a manual implementation for
                     // this trait and type.
                 }
-                ty::Param(..) | ty::Alias(ty::Projection, ..) => {
+                ty::Param(..)
+                | ty::Alias(ty::Projection, ..)
+                | ty::Placeholder(..)
+                | ty::Bound(..) => {
                     // In these cases, we don't know what the actual
                     // type is. Therefore, we cannot break it down
                     // into its constituent types. So we don't
@@ -448,6 +451,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         );
 
         self.infcx.probe(|_snapshot| {
+            if obligation.has_non_region_late_bound() {
+                return;
+            }
+
             // The code below doesn't care about regions, and the
             // self-ty here doesn't escape this probe, so just erase
             // any LBR.
diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
index dc5bcb48cad..e4a832e4728 100644
--- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
@@ -540,13 +540,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                                 let kind = ty::BoundRegionKind::BrNamed(param.def_id, param.name);
                                 let bound_var = ty::BoundVariableKind::Region(kind);
                                 bound_vars.push(bound_var);
-                                tcx.mk_region(ty::ReLateBound(
+                                tcx.mk_re_late_bound(
                                     ty::INNERMOST,
                                     ty::BoundRegion {
                                         var: ty::BoundVar::from_usize(bound_vars.len() - 1),
                                         kind,
                                     },
-                                ))
+                                )
                                 .into()
                             }
                             GenericParamDefKind::Const { .. } => {
@@ -557,15 +557,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                                         ty::INNERMOST,
                                         ty::BoundVar::from_usize(bound_vars.len() - 1),
                                     ),
-                                    tcx.type_of(param.def_id),
+                                    tcx.type_of(param.def_id)
+                                        .no_bound_vars()
+                                        .expect("const parameter types cannot be generic"),
                                 )
                                 .into()
                             }
                         });
-                        let bound_vars = tcx.mk_bound_variable_kinds(bound_vars.into_iter());
+                        let bound_vars = tcx.intern_bound_variable_kinds(&bound_vars);
                         let assoc_ty_substs = tcx.intern_substs(&substs);
-
-                        let bound_vars = tcx.mk_bound_variable_kinds(bound_vars.into_iter());
                         let bound =
                             bound.map_bound(|b| b.kind().skip_binder()).subst(tcx, assoc_ty_substs);
                         tcx.mk_predicate(ty::Binder::bind_with_vars(bound, bound_vars))
@@ -1073,7 +1073,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                     .fields
                     .last()
                     .expect("expected unsized ADT to have a tail field");
-                let tail_field_ty = tcx.bound_type_of(tail_field.did);
+                let tail_field_ty = tcx.type_of(tail_field.did);
 
                 // Extract `TailField<T>` and `TailField<U>` from `Struct<T>` and `Struct<U>`,
                 // normalizing in the process, since `type_of` returns something directly from
@@ -1189,7 +1189,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             let cause = obligation.derived_cause(|derived| {
                 ImplDerivedObligation(Box::new(ImplDerivedObligationCause {
                     derived,
-                    impl_def_id,
+                    impl_or_alias_def_id: impl_def_id,
                     impl_def_predicate_index: None,
                     span: obligation.cause.span,
                 }))
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index fc9678233c3..e6fc9bb9239 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -378,11 +378,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                             let self_ty = trait_ref.self_ty();
                             let (trait_desc, self_desc) = with_no_trimmed_paths!({
                                 let trait_desc = trait_ref.print_only_trait_path().to_string();
-                                let self_desc = if self_ty.has_concrete_skeleton() {
-                                    Some(self_ty.to_string())
-                                } else {
-                                    None
-                                };
+                                let self_desc =
+                                    self_ty.has_concrete_skeleton().then(|| self_ty.to_string());
                                 (trait_desc, self_desc)
                             });
                             let cause = if let Conflict::Upstream = conflict {
@@ -996,6 +993,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                     bug!("AliasEq is only used for new solver")
                 }
                 ty::PredicateKind::Ambiguous => Ok(EvaluatedToAmbig),
+                ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(ct, ty)) => {
+                    match self.infcx.at(&obligation.cause, obligation.param_env).eq(ct.ty(), ty) {
+                        Ok(inf_ok) => self.evaluate_predicates_recursively(
+                            previous_stack,
+                            inf_ok.into_obligations(),
+                        ),
+                        Err(_) => Ok(EvaluatedToErr),
+                    }
+                }
             }
         })
     }
@@ -2353,7 +2359,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 // We can resolve the `impl Trait` to its concrete type,
                 // which enforces a DAG between the functions requiring
                 // the auto trait bounds in question.
-                t.rebind(vec![self.tcx().bound_type_of(def_id).subst(self.tcx(), substs)])
+                t.rebind(vec![self.tcx().type_of(def_id).subst(self.tcx(), substs)])
             }
         }
     }
@@ -2660,7 +2666,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             let cause = cause.clone().derived_cause(parent_trait_pred, |derived| {
                 ImplDerivedObligation(Box::new(ImplDerivedObligationCause {
                     derived,
-                    impl_def_id: def_id,
+                    impl_or_alias_def_id: def_id,
                     impl_def_predicate_index: Some(index),
                     span,
                 }))
@@ -3023,7 +3029,7 @@ fn bind_generator_hidden_types_above<'tcx>(
                             kind: ty::BrAnon(counter, None),
                         };
                         counter += 1;
-                        r = tcx.mk_region(ty::ReLateBound(current_depth, br));
+                        r = tcx.mk_re_late_bound(current_depth, br);
                     }
                     r
                 })
diff --git a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
index 3b796c623c0..d1d6a7a90cf 100644
--- a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
@@ -455,7 +455,13 @@ pub(crate) fn to_pretty_impl_header(tcx: TyCtxt<'_>, impl_def_id: DefId) -> Opti
         w.push('>');
     }
 
-    write!(w, " {} for {}", trait_ref.print_only_trait_path(), tcx.type_of(impl_def_id)).unwrap();
+    write!(
+        w,
+        " {} for {}",
+        trait_ref.print_only_trait_path(),
+        tcx.type_of(impl_def_id).subst_identity()
+    )
+    .unwrap();
 
     // The predicates will contain default bounds like `T: Sized`. We need to
     // remove these bounds, and add `T: ?Sized` to any untouched type parameters.
diff --git a/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs b/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs
index 0f9196de4fb..2e4a5cfe4bc 100644
--- a/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs
+++ b/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs
@@ -113,7 +113,7 @@ impl<'tcx> ChildrenExt<'tcx> for Children {
                     // Only report the `Self` type if it has at least
                     // some outer concrete shell; otherwise, it's
                     // not adding much information.
-                    self_ty: if self_ty.has_concrete_skeleton() { Some(self_ty) } else { None },
+                    self_ty: self_ty.has_concrete_skeleton().then_some(self_ty),
                     intercrate_ambiguity_causes: overlap.intercrate_ambiguity_causes,
                     involves_placeholder: overlap.involves_placeholder,
                 }
@@ -399,7 +399,7 @@ pub(crate) fn assoc_def(
     // If there is no such item in that impl, this function will fail with a
     // cycle error if the specialization graph is currently being built.
     if let Some(&impl_item_id) = tcx.impl_item_implementor_ids(impl_def_id).get(&assoc_def_id) {
-        let &item = tcx.associated_item(impl_item_id);
+        let item = tcx.associated_item(impl_item_id);
         let impl_node = Node::Impl(impl_def_id);
         return Ok(LeafDef {
             item,
diff --git a/compiler/rustc_trait_selection/src/traits/vtable.rs b/compiler/rustc_trait_selection/src/traits/vtable.rs
index 64daca714c3..9f5c5bbeac8 100644
--- a/compiler/rustc_trait_selection/src/traits/vtable.rs
+++ b/compiler/rustc_trait_selection/src/traits/vtable.rs
@@ -197,12 +197,12 @@ fn own_existential_vtable_entries(tcx: TyCtxt<'_>, trait_def_id: DefId) -> &[Def
         .in_definition_order()
         .filter(|item| item.kind == ty::AssocKind::Fn);
     // Now list each method's DefId (for within its trait).
-    let own_entries = trait_methods.filter_map(move |trait_method| {
+    let own_entries = trait_methods.filter_map(move |&trait_method| {
         debug!("own_existential_vtable_entry: trait_method={:?}", trait_method);
         let def_id = trait_method.def_id;
 
         // Some methods cannot be called on an object; skip those.
-        if !is_vtable_safe_method(tcx, trait_def_id, &trait_method) {
+        if !is_vtable_safe_method(tcx, trait_def_id, trait_method) {
             debug!("own_existential_vtable_entry: not vtable safe");
             return None;
         }
diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs
index 5cfb6cf332e..6a881c233db 100644
--- a/compiler/rustc_trait_selection/src/traits/wf.rs
+++ b/compiler/rustc_trait_selection/src/traits/wf.rs
@@ -163,6 +163,10 @@ pub fn predicate_obligations<'tcx>(
                 ty::TermKind::Const(c) => c.into(),
             })
         }
+        ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(ct, ty)) => {
+            wf.compute(ct.into());
+            wf.compute(ty.into());
+        }
         ty::PredicateKind::WellFormed(arg) => {
             wf.compute(arg);
         }
@@ -922,6 +926,7 @@ pub(crate) fn required_region_bounds<'tcx>(
             match obligation.predicate.kind().skip_binder() {
                 ty::PredicateKind::Clause(ty::Clause::Projection(..))
                 | ty::PredicateKind::Clause(ty::Clause::Trait(..))
+                | ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..))
                 | ty::PredicateKind::Subtype(..)
                 | ty::PredicateKind::Coerce(..)
                 | ty::PredicateKind::WellFormed(..)
diff --git a/compiler/rustc_traits/src/chalk/db.rs b/compiler/rustc_traits/src/chalk/db.rs
index 20725c656de..e2b5d17e073 100644
--- a/compiler/rustc_traits/src/chalk/db.rs
+++ b/compiler/rustc_traits/src/chalk/db.rs
@@ -246,7 +246,7 @@ impl<'tcx> chalk_solve::RustIrDatabase<RustInterner<'tcx>> for RustIrDatabase<'t
 
         // Grab the ADT and the param we might need to calculate its layout
         let param_env = tcx.param_env(did);
-        let adt_ty = tcx.type_of(did);
+        let adt_ty = tcx.type_of(did).subst_identity();
 
         // The ADT is a 1-zst if it's a ZST and its alignment is 1.
         // Mark the ADT as _not_ a 1-zst if there was a layout error.
@@ -468,7 +468,7 @@ impl<'tcx> chalk_solve::RustIrDatabase<RustInterner<'tcx>> for RustIrDatabase<'t
         let ty = self
             .interner
             .tcx
-            .bound_type_of(def_id)
+            .type_of(def_id)
             .subst(self.interner.tcx, bound_vars)
             .lower_into(self.interner);
 
@@ -732,13 +732,13 @@ fn bound_vars_for_item(tcx: TyCtxt<'_>, def_id: DefId) -> SubstsRef<'_> {
                 var: ty::BoundVar::from_usize(substs.len()),
                 kind: ty::BrAnon(substs.len() as u32, None),
             };
-            tcx.mk_region(ty::ReLateBound(ty::INNERMOST, br)).into()
+            tcx.mk_re_late_bound(ty::INNERMOST, br).into()
         }
 
         ty::GenericParamDefKind::Const { .. } => tcx
             .mk_const(
                 ty::ConstKind::Bound(ty::INNERMOST, ty::BoundVar::from(param.index)),
-                tcx.type_of(param.def_id),
+                tcx.type_of(param.def_id).subst_identity(),
             )
             .into(),
     })
diff --git a/compiler/rustc_traits/src/chalk/lowering.rs b/compiler/rustc_traits/src/chalk/lowering.rs
index 2978fc4ed8c..7635f4bfec3 100644
--- a/compiler/rustc_traits/src/chalk/lowering.rs
+++ b/compiler/rustc_traits/src/chalk/lowering.rs
@@ -117,6 +117,7 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::InEnvironment<chalk_ir::Goal<RustInterner<'
                     )),
                 },
                 ty::PredicateKind::ObjectSafe(..)
+                | ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..))
                 | ty::PredicateKind::AliasEq(..)
                 | ty::PredicateKind::ClosureKind(..)
                 | ty::PredicateKind::Subtype(..)
@@ -212,6 +213,7 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::GoalData<RustInterner<'tcx>>> for ty::Predi
             // We can defer this, but ultimately we'll want to express
             // some of these in terms of chalk operations.
             ty::PredicateKind::ClosureKind(..)
+            | ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..))
             | ty::PredicateKind::AliasEq(..)
             | ty::PredicateKind::Coerce(..)
             | ty::PredicateKind::ConstEvaluatable(..)
@@ -521,8 +523,9 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::Lifetime<RustInterner<'tcx>>> for Region<'t
 
 impl<'tcx> LowerInto<'tcx, Region<'tcx>> for &chalk_ir::Lifetime<RustInterner<'tcx>> {
     fn lower_into(self, interner: RustInterner<'tcx>) -> Region<'tcx> {
-        let kind = match self.data(interner) {
-            chalk_ir::LifetimeData::BoundVar(var) => ty::ReLateBound(
+        let tcx = interner.tcx;
+        match self.data(interner) {
+            chalk_ir::LifetimeData::BoundVar(var) => tcx.mk_re_late_bound(
                 ty::DebruijnIndex::from_u32(var.debruijn.depth()),
                 ty::BoundRegion {
                     var: ty::BoundVar::from_usize(var.index),
@@ -530,15 +533,14 @@ impl<'tcx> LowerInto<'tcx, Region<'tcx>> for &chalk_ir::Lifetime<RustInterner<'t
                 },
             ),
             chalk_ir::LifetimeData::InferenceVar(_var) => unimplemented!(),
-            chalk_ir::LifetimeData::Placeholder(p) => ty::RePlaceholder(ty::Placeholder {
+            chalk_ir::LifetimeData::Placeholder(p) => tcx.mk_re_placeholder(ty::Placeholder {
                 universe: ty::UniverseIndex::from_usize(p.ui.counter),
                 name: ty::BoundRegionKind::BrAnon(p.idx as u32, None),
             }),
-            chalk_ir::LifetimeData::Static => return interner.tcx.lifetimes.re_static,
-            chalk_ir::LifetimeData::Erased => return interner.tcx.lifetimes.re_erased,
+            chalk_ir::LifetimeData::Static => tcx.lifetimes.re_static,
+            chalk_ir::LifetimeData::Erased => tcx.lifetimes.re_erased,
             chalk_ir::LifetimeData::Phantom(void, _) => match *void {},
-        };
-        interner.tcx.mk_region(kind)
+        }
     }
 }
 
@@ -646,6 +648,7 @@ impl<'tcx> LowerInto<'tcx, Option<chalk_ir::QuantifiedWhereClause<RustInterner<'
                 Some(chalk_ir::WhereClause::AliasEq(predicate.lower_into(interner)))
             }
             ty::PredicateKind::WellFormed(_ty) => None,
+            ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..)) => None,
 
             ty::PredicateKind::ObjectSafe(..)
             | ty::PredicateKind::AliasEq(..)
@@ -780,6 +783,7 @@ impl<'tcx> LowerInto<'tcx, Option<chalk_solve::rust_ir::QuantifiedInlineBound<Ru
             }
             ty::PredicateKind::Clause(ty::Clause::TypeOutlives(_predicate)) => None,
             ty::PredicateKind::WellFormed(_ty) => None,
+            ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..)) => None,
 
             ty::PredicateKind::Clause(ty::Clause::RegionOutlives(..))
             | ty::PredicateKind::AliasEq(..)
@@ -1025,7 +1029,7 @@ impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for NamedBoundVarSubstitutor<'a, 'tcx> {
                 ty::BrNamed(def_id, _name) => match self.named_parameters.get(&def_id) {
                     Some(idx) => {
                         let new_br = ty::BoundRegion { var: br.var, kind: ty::BrAnon(*idx, None) };
-                        return self.tcx.mk_region(ty::ReLateBound(index, new_br));
+                        return self.tcx.mk_re_late_bound(index, new_br);
                     }
                     None => panic!("Missing `BrNamed`."),
                 },
@@ -1107,7 +1111,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ParamsSubstitutor<'tcx> {
                         var: ty::BoundVar::from_u32(*idx),
                         kind: ty::BrAnon(*idx, None),
                     };
-                    self.tcx.mk_region(ty::ReLateBound(self.binder_index, br))
+                    self.tcx.mk_re_late_bound(self.binder_index, br)
                 }
                 None => {
                     let idx = self.named_regions.len() as u32;
@@ -1116,7 +1120,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ParamsSubstitutor<'tcx> {
                         kind: ty::BrAnon(idx, None),
                     };
                     self.named_regions.insert(_re.def_id, idx);
-                    self.tcx.mk_region(ty::ReLateBound(self.binder_index, br))
+                    self.tcx.mk_re_late_bound(self.binder_index, br)
                 }
             },
 
diff --git a/compiler/rustc_traits/src/dropck_outlives.rs b/compiler/rustc_traits/src/dropck_outlives.rs
index 8b7f8033bfa..b5924e94914 100644
--- a/compiler/rustc_traits/src/dropck_outlives.rs
+++ b/compiler/rustc_traits/src/dropck_outlives.rs
@@ -308,7 +308,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);
+        let fty = tcx.type_of(field.did).subst_identity();
         dtorck_constraint_for_ty(tcx, span, fty, 0, fty, &mut result)?;
     }
     result.outlives.extend(tcx.destructor_constraints(def));
diff --git a/compiler/rustc_traits/src/implied_outlives_bounds.rs b/compiler/rustc_traits/src/implied_outlives_bounds.rs
index 93f9b66e0f8..abf0c1c5f3e 100644
--- a/compiler/rustc_traits/src/implied_outlives_bounds.rs
+++ b/compiler/rustc_traits/src/implied_outlives_bounds.rs
@@ -99,6 +99,9 @@ fn compute_implied_outlives_bounds<'tcx>(
             };
             match pred {
                 ty::PredicateKind::Clause(ty::Clause::Trait(..))
+                // FIXME(const_generics): Make sure that `<'a, 'b, const N: &'a &'b u32>` is sound
+                // if we ever support that
+                | ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..))
                 | ty::PredicateKind::Subtype(..)
                 | ty::PredicateKind::Coerce(..)
                 | ty::PredicateKind::Clause(ty::Clause::Projection(..))
diff --git a/compiler/rustc_traits/src/normalize_erasing_regions.rs b/compiler/rustc_traits/src/normalize_erasing_regions.rs
index 07e716cda42..2c18a034050 100644
--- a/compiler/rustc_traits/src/normalize_erasing_regions.rs
+++ b/compiler/rustc_traits/src/normalize_erasing_regions.rs
@@ -60,6 +60,7 @@ fn not_outlives_predicate(p: ty::Predicate<'_>) -> bool {
         | ty::PredicateKind::Clause(ty::Clause::TypeOutlives(..)) => false,
         ty::PredicateKind::Clause(ty::Clause::Trait(..))
         | ty::PredicateKind::Clause(ty::Clause::Projection(..))
+        | ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..))
         | ty::PredicateKind::AliasEq(..)
         | ty::PredicateKind::WellFormed(..)
         | ty::PredicateKind::ObjectSafe(..)
diff --git a/compiler/rustc_traits/src/type_op.rs b/compiler/rustc_traits/src/type_op.rs
index 27dc1625992..d34fce64dd7 100644
--- a/compiler/rustc_traits/src/type_op.rs
+++ b/compiler/rustc_traits/src/type_op.rs
@@ -93,7 +93,7 @@ fn relate_mir_and_user_substs<'tcx>(
     let tcx = ocx.infcx.tcx;
     let cause = ObligationCause::dummy_with_span(span);
 
-    let ty = tcx.bound_type_of(def_id).subst(tcx, substs);
+    let ty = tcx.type_of(def_id).subst(tcx, substs);
     let ty = ocx.normalize(&cause, param_env, ty);
     debug!("relate_type_and_user_type: ty of def-id is {:?}", ty);
 
@@ -122,7 +122,7 @@ fn relate_mir_and_user_substs<'tcx>(
 
     if let Some(UserSelfTy { impl_def_id, self_ty }) = user_self_ty {
         let self_ty = ocx.normalize(&cause, param_env, self_ty);
-        let impl_self_ty = tcx.bound_type_of(impl_def_id).subst(tcx, substs);
+        let impl_self_ty = tcx.type_of(impl_def_id).subst(tcx, substs);
         let impl_self_ty = ocx.normalize(&cause, param_env, impl_self_ty);
 
         ocx.eq(&cause, param_env, self_ty, impl_self_ty)?;
diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs
index ad5527f5a77..41924dc2a6d 100644
--- a/compiler/rustc_ty_utils/src/abi.rs
+++ b/compiler/rustc_ty_utils/src/abi.rs
@@ -70,7 +70,7 @@ fn fn_sig_for_fn_abi<'tcx>(
                 var: ty::BoundVar::from_usize(bound_vars.len() - 1),
                 kind: ty::BoundRegionKind::BrEnv,
             };
-            let env_region = ty::ReLateBound(ty::INNERMOST, br);
+            let env_region = tcx.mk_re_late_bound(ty::INNERMOST, br);
             let env_ty = tcx.closure_env_ty(def_id, substs, env_region).unwrap();
 
             let sig = sig.skip_binder();
@@ -95,8 +95,7 @@ fn fn_sig_for_fn_abi<'tcx>(
                 var: ty::BoundVar::from_usize(bound_vars.len() - 1),
                 kind: ty::BoundRegionKind::BrEnv,
             };
-            let env_region = ty::ReLateBound(ty::INNERMOST, br);
-            let env_ty = tcx.mk_mut_ref(tcx.mk_region(env_region), ty);
+            let env_ty = tcx.mk_mut_ref(tcx.mk_re_late_bound(ty::INNERMOST, br), ty);
 
             let pin_did = tcx.require_lang_item(LangItem::Pin, None);
             let pin_adt_ref = tcx.adt_def(pin_did);
@@ -142,8 +141,8 @@ fn fn_sig_for_fn_abi<'tcx>(
 
             ty::Binder::bind_with_vars(
                 tcx.mk_fn_sig(
-                    [env_ty, resume_ty].iter(),
-                    &ret_ty,
+                    [env_ty, resume_ty],
+                    ret_ty,
                     false,
                     hir::Unsafety::Normal,
                     rustc_target::spec::abi::Abi::Rust,
@@ -207,11 +206,8 @@ fn fn_abi_of_instance<'tcx>(
 
     let sig = fn_sig_for_fn_abi(tcx, instance, param_env);
 
-    let caller_location = if instance.def.requires_caller_location(tcx) {
-        Some(tcx.caller_location_ty())
-    } else {
-        None
-    };
+    let caller_location =
+        instance.def.requires_caller_location(tcx).then(|| tcx.caller_location_ty());
 
     fn_abi_new_uncached(
         &LayoutCx { tcx, param_env },
diff --git a/compiler/rustc_ty_utils/src/assoc.rs b/compiler/rustc_ty_utils/src/assoc.rs
index a6e0f13f698..164cac6a010 100644
--- a/compiler/rustc_ty_utils/src/assoc.rs
+++ b/compiler/rustc_ty_utils/src/assoc.rs
@@ -26,7 +26,7 @@ fn associated_item_def_ids(tcx: TyCtxt<'_>, def_id: DefId) -> &[DefId] {
     }
 }
 
-fn associated_items(tcx: TyCtxt<'_>, def_id: DefId) -> ty::AssocItems<'_> {
+fn associated_items(tcx: TyCtxt<'_>, def_id: DefId) -> ty::AssocItems {
     if tcx.is_trait_alias(def_id) {
         ty::AssocItems::new(Vec::new())
     } else {
diff --git a/compiler/rustc_ty_utils/src/consts.rs b/compiler/rustc_ty_utils/src/consts.rs
index a9fbad55dac..852156c24f4 100644
--- a/compiler/rustc_ty_utils/src/consts.rs
+++ b/compiler/rustc_ty_utils/src/consts.rs
@@ -144,7 +144,7 @@ fn recurse_build<'tcx>(
             for &id in args.iter() {
                 new_args.push(recurse_build(tcx, body, id, root_span)?);
             }
-            let new_args = tcx.mk_const_list(new_args.iter());
+            let new_args = tcx.intern_const_list(&new_args);
             tcx.mk_const(Expr::FunctionCall(fun, new_args), node.ty)
         }
         &ExprKind::Binary { op, lhs, rhs } if check_binop(op) => {
diff --git a/compiler/rustc_ty_utils/src/implied_bounds.rs b/compiler/rustc_ty_utils/src/implied_bounds.rs
index 2fe9d135fa5..eb307e66e34 100644
--- a/compiler/rustc_ty_utils/src/implied_bounds.rs
+++ b/compiler/rustc_ty_utils/src/implied_bounds.rs
@@ -28,7 +28,7 @@ fn assumed_wf_types(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::List<Ty<'_>> {
                     tcx.intern_type_list(&types)
                 }
                 // Only the impl self type
-                None => tcx.intern_type_list(&[tcx.type_of(def_id)]),
+                None => tcx.intern_type_list(&[tcx.type_of(def_id).subst_identity()]),
             }
         }
         DefKind::AssocConst | DefKind::AssocTy => tcx.assumed_wf_types(tcx.parent(def_id)),
diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs
index 8d46ba320fc..de7230b0cfa 100644
--- a/compiler/rustc_ty_utils/src/instance.rs
+++ b/compiler/rustc_ty_utils/src/instance.rs
@@ -53,7 +53,8 @@ fn inner_resolve_instance<'tcx>(
         )
     } else {
         let ty = tcx.type_of(def.def_id_for_type_of());
-        let item_type = tcx.subst_and_normalize_erasing_regions(substs, param_env, ty);
+        let item_type =
+            tcx.subst_and_normalize_erasing_regions(substs, param_env, ty.skip_binder());
 
         let def = match *item_type.kind() {
             ty::FnDef(def_id, ..) if tcx.is_intrinsic(def_id) => {
diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs
index 2df4a5eab21..b860fb6c918 100644
--- a/compiler/rustc_ty_utils/src/layout.rs
+++ b/compiler/rustc_ty_utils/src/layout.rs
@@ -453,9 +453,10 @@ fn layout_of_uncached<'tcx>(
                         let param_env = tcx.param_env(def.did());
                         def.is_struct()
                             && match def.variants().iter().next().and_then(|x| x.fields.last()) {
-                                Some(last_field) => {
-                                    tcx.type_of(last_field.did).is_sized(tcx, param_env)
-                                }
+                                Some(last_field) => tcx
+                                    .type_of(last_field.did)
+                                    .subst_identity()
+                                    .is_sized(tcx, param_env),
                                 None => false,
                             }
                     },
diff --git a/compiler/rustc_ty_utils/src/needs_drop.rs b/compiler/rustc_ty_utils/src/needs_drop.rs
index cd1475391a4..c177d60bb59 100644
--- a/compiler/rustc_ty_utils/src/needs_drop.rs
+++ b/compiler/rustc_ty_utils/src/needs_drop.rs
@@ -242,7 +242,7 @@ fn drop_tys_helper<'tcx>(
             Ok(Vec::new())
         } else {
             let field_tys = adt_def.all_fields().map(|field| {
-                let r = tcx.bound_type_of(field.did).subst(tcx, substs);
+                let r = tcx.type_of(field.did).subst(tcx, substs);
                 debug!("drop_tys_helper: Subst into {:?} with {:?} gettng {:?}", field, substs, r);
                 r
             });
@@ -295,9 +295,15 @@ fn adt_drop_tys<'tcx>(
     let adt_has_dtor =
         |adt_def: ty::AdtDef<'tcx>| adt_def.destructor(tcx).map(|_| DtorType::Significant);
     // `tcx.type_of(def_id)` identical to `tcx.make_adt(def, identity_substs)`
-    drop_tys_helper(tcx, tcx.type_of(def_id), tcx.param_env(def_id), adt_has_dtor, false)
-        .collect::<Result<Vec<_>, _>>()
-        .map(|components| tcx.intern_type_list(&components))
+    drop_tys_helper(
+        tcx,
+        tcx.type_of(def_id).subst_identity(),
+        tcx.param_env(def_id),
+        adt_has_dtor,
+        false,
+    )
+    .collect::<Result<Vec<_>, _>>()
+    .map(|components| tcx.intern_type_list(&components))
 }
 // If `def_id` refers to a generic ADT, the queries above and below act as if they had been handed
 // a `tcx.make_ty(def, identity_substs)` and as such it is legal to substitute the generic parameters
@@ -308,7 +314,7 @@ fn adt_significant_drop_tys(
 ) -> Result<&ty::List<Ty<'_>>, AlwaysRequiresDrop> {
     drop_tys_helper(
         tcx,
-        tcx.type_of(def_id), // identical to `tcx.make_adt(def, identity_substs)`
+        tcx.type_of(def_id).subst_identity(), // identical to `tcx.make_adt(def, identity_substs)`
         tcx.param_env(def_id),
         adt_consider_insignificant_dtor(tcx),
         true,
diff --git a/compiler/rustc_ty_utils/src/representability.rs b/compiler/rustc_ty_utils/src/representability.rs
index 7f48fb80417..591017eecd2 100644
--- a/compiler/rustc_ty_utils/src/representability.rs
+++ b/compiler/rustc_ty_utils/src/representability.rs
@@ -31,7 +31,7 @@ fn representability(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Representability {
             }
             Representability::Representable
         }
-        DefKind::Field => representability_ty(tcx, tcx.type_of(def_id)),
+        DefKind::Field => representability_ty(tcx, tcx.type_of(def_id).subst_identity()),
         def_kind => bug!("unexpected {def_kind:?}"),
     }
 }
@@ -91,7 +91,7 @@ fn params_in_repr(tcx: TyCtxt<'_>, def_id: DefId) -> BitSet<u32> {
     let mut params_in_repr = BitSet::new_empty(generics.params.len());
     for variant in adt_def.variants() {
         for field in variant.fields.iter() {
-            params_in_repr_ty(tcx, tcx.type_of(field.did), &mut params_in_repr);
+            params_in_repr_ty(tcx, tcx.type_of(field.did).subst_identity(), &mut params_in_repr);
         }
     }
     params_in_repr
diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs
index 41e837e8b75..2c50b766d21 100644
--- a/compiler/rustc_ty_utils/src/ty.rs
+++ b/compiler/rustc_ty_utils/src/ty.rs
@@ -1,7 +1,9 @@
 use rustc_data_structures::fx::FxIndexSet;
 use rustc_hir as hir;
 use rustc_index::bit_set::BitSet;
-use rustc_middle::ty::{self, Binder, Predicate, PredicateKind, ToPredicate, Ty, TyCtxt};
+use rustc_middle::ty::{
+    self, Binder, EarlyBinder, Predicate, PredicateKind, ToPredicate, Ty, TyCtxt,
+};
 use rustc_session::config::TraitSolver;
 use rustc_span::def_id::{DefId, CRATE_DEF_ID};
 use rustc_trait_selection::traits;
@@ -103,7 +105,7 @@ fn adt_sized_constraint(tcx: TyCtxt<'_>, def_id: DefId) -> &[Ty<'_>] {
         def.variants()
             .iter()
             .flat_map(|v| v.fields.last())
-            .flat_map(|f| sized_constraint_for_ty(tcx, def, tcx.type_of(f.did))),
+            .flat_map(|f| sized_constraint_for_ty(tcx, def, tcx.type_of(f.did).subst_identity())),
     );
 
     debug!("adt_sized_constraint: {:?} => {:?}", def, result);
@@ -299,7 +301,7 @@ fn well_formed_types_in_env(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::List<Predica
         // In an inherent impl, we assume that the receiver type and all its
         // constituents are well-formed.
         NodeKind::InherentImpl => {
-            let self_ty = tcx.type_of(def_id);
+            let self_ty = tcx.type_of(def_id).subst_identity();
             inputs.extend(self_ty.walk());
         }
 
@@ -355,7 +357,7 @@ fn instance_def_size_estimate<'tcx>(
 /// If `def_id` is an issue 33140 hack impl, returns its self type; otherwise, returns `None`.
 ///
 /// See [`ty::ImplOverlapKind::Issue33140`] for more details.
-fn issue33140_self_ty(tcx: TyCtxt<'_>, def_id: DefId) -> Option<Ty<'_>> {
+fn issue33140_self_ty(tcx: TyCtxt<'_>, def_id: DefId) -> Option<EarlyBinder<Ty<'_>>> {
     debug!("issue33140_self_ty({:?})", def_id);
 
     let trait_ref = tcx
@@ -394,7 +396,7 @@ fn issue33140_self_ty(tcx: TyCtxt<'_>, def_id: DefId) -> Option<Ty<'_>> {
 
     if self_ty_matches {
         debug!("issue33140_self_ty - MATCHES!");
-        Some(self_ty)
+        Some(EarlyBinder(self_ty))
     } else {
         debug!("issue33140_self_ty - non-matching self type");
         None
@@ -434,7 +436,7 @@ fn unsizing_params_for_adt<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> BitSet<u32
     };
 
     let mut unsizing_params = BitSet::new_empty(num_params);
-    for arg in tcx.bound_type_of(tail_field.did).subst_identity().walk() {
+    for arg in tcx.type_of(tail_field.did).subst_identity().walk() {
         if let Some(i) = maybe_unsizing_param_idx(arg) {
             unsizing_params.insert(i);
         }
@@ -443,7 +445,7 @@ fn unsizing_params_for_adt<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> BitSet<u32
     // Ensure none of the other fields mention the parameters used
     // in unsizing.
     for field in prefix_fields {
-        for arg in tcx.bound_type_of(field.did).subst_identity().walk() {
+        for arg in tcx.type_of(field.did).subst_identity().walk() {
             if let Some(i) = maybe_unsizing_param_idx(arg) {
                 unsizing_params.remove(i);
             }
diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs
index cb28731681b..5a991e03dee 100644
--- a/compiler/rustc_type_ir/src/lib.rs
+++ b/compiler/rustc_type_ir/src/lib.rs
@@ -69,38 +69,37 @@ pub trait Interner: Sized {
     type PlaceholderRegion: Clone + Debug + Hash + Ord;
 }
 
-pub trait InternAs<T: ?Sized, R> {
+/// Imagine you have a function `F: FnOnce(&[T]) -> R`, plus an iterator `iter`
+/// that produces `T` items. You could combine them with
+/// `f(&iter.collect::<Vec<_>>())`, but this requires allocating memory for the
+/// `Vec`.
+///
+/// This trait allows for faster implementations, intended for cases where the
+/// number of items produced by the iterator is small. There is a blanket impl
+/// for `T` items, but there is also a fallible impl for `Result<T, E>` items.
+pub trait CollectAndApply<T, R>: Sized {
     type Output;
-    fn intern_with<F>(self, f: F) -> Self::Output
+
+    /// Produce a result of type `Self::Output` from `iter`. The result will
+    /// typically be produced by applying `f` on the elements produced by
+    /// `iter`, though this may not happen in some impls, e.g. if an error
+    /// occured during iteration.
+    fn collect_and_apply<I, F>(iter: I, f: F) -> Self::Output
     where
+        I: Iterator<Item = Self>,
         F: FnOnce(&[T]) -> R;
 }
 
-impl<I, T, R, E> InternAs<T, R> for I
-where
-    E: InternIteratorElement<T, R>,
-    I: Iterator<Item = E>,
-{
-    type Output = E::Output;
-    fn intern_with<F>(self, f: F) -> Self::Output
+/// The blanket impl that always collects all elements and applies `f`.
+impl<T, R> CollectAndApply<T, R> for T {
+    type Output = R;
+
+    /// Equivalent to `f(&iter.collect::<Vec<_>>())`.
+    fn collect_and_apply<I, F>(mut iter: I, f: F) -> R
     where
+        I: Iterator<Item = T>,
         F: FnOnce(&[T]) -> R,
     {
-        E::intern_with(self, f)
-    }
-}
-
-pub trait InternIteratorElement<T, R>: Sized {
-    type Output;
-    fn intern_with<I: Iterator<Item = Self>, F: FnOnce(&[T]) -> R>(iter: I, f: F) -> Self::Output;
-}
-
-impl<T, R> InternIteratorElement<T, R> for T {
-    type Output = R;
-    fn intern_with<I: Iterator<Item = Self>, F: FnOnce(&[T]) -> R>(
-        mut iter: I,
-        f: F,
-    ) -> Self::Output {
         // This code is hot enough that it's worth specializing for the most
         // common length lists, to avoid the overhead of `SmallVec` creation.
         // Lengths 0, 1, and 2 typically account for ~95% of cases. If
@@ -127,23 +126,17 @@ impl<T, R> InternIteratorElement<T, R> for T {
     }
 }
 
-impl<'a, T, R> InternIteratorElement<T, R> for &'a T
-where
-    T: Clone + 'a,
-{
-    type Output = R;
-    fn intern_with<I: Iterator<Item = Self>, F: FnOnce(&[T]) -> R>(iter: I, f: F) -> Self::Output {
-        // This code isn't hot.
-        f(&iter.cloned().collect::<SmallVec<[_; 8]>>())
-    }
-}
-
-impl<T, R, E> InternIteratorElement<T, R> for Result<T, E> {
+/// A fallible impl that will fail, without calling `f`, if there are any
+/// errors during collection.
+impl<T, R, E> CollectAndApply<T, R> for Result<T, E> {
     type Output = Result<R, E>;
-    fn intern_with<I: Iterator<Item = Self>, F: FnOnce(&[T]) -> R>(
-        mut iter: I,
-        f: F,
-    ) -> Self::Output {
+
+    /// Equivalent to `Ok(f(&iter.collect::<Result<Vec<_>>>()?))`.
+    fn collect_and_apply<I, F>(mut iter: I, f: F) -> Result<R, E>
+    where
+        I: Iterator<Item = Result<T, E>>,
+        F: FnOnce(&[T]) -> R,
+    {
         // This code is hot enough that it's worth specializing for the most
         // common length lists, to avoid the overhead of `SmallVec` creation.
         // Lengths 0, 1, and 2 typically account for ~95% of cases. If
diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs
index 5a0b8594104..9e3e13e7004 100644
--- a/library/core/src/iter/traits/iterator.rs
+++ b/library/core/src/iter/traits/iterator.rs
@@ -3502,8 +3502,10 @@ pub trait Iterator {
         }
     }
 
-    /// [Lexicographically](Ord#lexicographical-comparison) compares the elements of this [`Iterator`] with those
-    /// of another.
+    /// [Lexicographically](Ord#lexicographical-comparison) compares the [`PartialOrd`] elements of
+    /// this [`Iterator`] with those of another. The comparison works like short-circuit
+    /// evaluation, returning a result without comparing the remaining elements.
+    /// As soon as an order can be determined, the evaluation stops and a result is returned.
     ///
     /// # Examples
     ///
@@ -3513,9 +3515,25 @@ pub trait Iterator {
     /// assert_eq!([1.].iter().partial_cmp([1.].iter()), Some(Ordering::Equal));
     /// assert_eq!([1.].iter().partial_cmp([1., 2.].iter()), Some(Ordering::Less));
     /// assert_eq!([1., 2.].iter().partial_cmp([1.].iter()), Some(Ordering::Greater));
+    /// ```
     ///
+    /// For floating-point numbers, NaN does not have a total order and will result
+    /// in `None` when compared:
+    ///
+    /// ```
     /// assert_eq!([f64::NAN].iter().partial_cmp([1.].iter()), None);
     /// ```
+    ///
+    /// The results are determined by the order of evaluation.
+    ///
+    /// ```
+    /// use std::cmp::Ordering;
+    ///
+    /// assert_eq!([1.0, f64::NAN].iter().partial_cmp([2.0, f64::NAN].iter()), Some(Ordering::Less));
+    /// assert_eq!([2.0, f64::NAN].iter().partial_cmp([1.0, f64::NAN].iter()), Some(Ordering::Greater));
+    /// assert_eq!([f64::NAN, 1.0].iter().partial_cmp([f64::NAN, 2.0].iter()), None);
+    /// ```
+    ///
     #[stable(feature = "iter_order", since = "1.5.0")]
     fn partial_cmp<I>(self, other: I) -> Option<Ordering>
     where
diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs
index 1675ed158c9..ff7821fb9ff 100644
--- a/src/bootstrap/check.rs
+++ b/src/bootstrap/check.rs
@@ -58,9 +58,10 @@ fn args(builder: &Builder<'_>) -> Vec<String> {
         clippy_lint_warn.iter().for_each(|v| clippy_lint_levels.push(format!("-W{}", v)));
         clippy_lint_forbid.iter().for_each(|v| clippy_lint_levels.push(format!("-F{}", v)));
         args.extend(clippy_lint_levels);
+        args.extend(builder.config.free_args.clone());
         args
     } else {
-        vec![]
+        builder.config.free_args.clone()
     }
 }
 
diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs
index 07c0d2233ca..e7d7215166b 100644
--- a/src/bootstrap/compile.rs
+++ b/src/bootstrap/compile.rs
@@ -445,6 +445,72 @@ impl Step for StdLink {
         let libdir = builder.sysroot_libdir(target_compiler, target);
         let hostdir = builder.sysroot_libdir(target_compiler, compiler.host);
         add_to_sysroot(builder, &libdir, &hostdir, &libstd_stamp(builder, compiler, target));
+
+        if compiler.stage == 0 {
+            // special handling for stage0, to make `rustup toolchain link` and `x dist --stage 0`
+            // work for stage0-sysroot
+            let sysroot = builder.out.join(&compiler.host.triple).join("stage0-sysroot");
+
+            let host_lib_dir = builder.initial_rustc.ancestors().nth(2).unwrap().join("lib");
+            let host_bin_dir = builder.out.join(&builder.initial_rustc.parent().unwrap());
+            let host_codegen_backends =
+                host_lib_dir.join("rustlib").join(&compiler.host.triple).join("codegen-backends");
+            let sysroot_bin_dir = sysroot.join("bin");
+            let sysroot_lib_dir = sysroot.join("lib");
+            let sysroot_codegen_backends = builder.sysroot_codegen_backends(compiler);
+
+            // Create the `bin` directory in stage0-sysroot
+            t!(fs::create_dir_all(&sysroot_bin_dir));
+
+            // copy bin files from `builder.initial_rustc/./` to `stage0-sysroot/bin`
+            if let Ok(files) = fs::read_dir(&host_bin_dir) {
+                for file in files {
+                    let file = t!(file);
+                    if file.file_name() == "rustfmt" {
+                        // This is when `rustc` and `cargo` are set in `config.toml`
+                        if !file.path().starts_with(&builder.out) {
+                            builder.copy(
+                                &file.path().into_boxed_path(),
+                                &sysroot_bin_dir.join(file.file_name()),
+                            );
+                        } else {
+                            builder.copy(
+                                &builder
+                                    .out
+                                    .join(&compiler.host.triple)
+                                    .join("rustfmt/bin/rustfmt"),
+                                &sysroot_bin_dir.join(file.file_name()),
+                            );
+                        }
+                    } else {
+                        builder.copy(
+                            &file.path().into_boxed_path(),
+                            &sysroot_bin_dir.join(file.file_name()),
+                        );
+                    }
+                }
+            }
+
+            // copy dylib files from `builder.initial_rustc/../lib/*` while excluding the `rustlib` directory to `stage0-sysroot/lib`
+            if let Ok(files) = fs::read_dir(&host_lib_dir) {
+                for file in files {
+                    let file = t!(file);
+                    let path = file.path();
+                    if path.is_file()
+                        && is_dylib(&file.file_name().into_string().unwrap())
+                        && !path.starts_with(sysroot_lib_dir.join("rustlib").into_boxed_path())
+                    {
+                        builder.copy(&path, &sysroot_lib_dir.join(path.file_name().unwrap()));
+                    }
+                }
+            }
+
+            t!(fs::create_dir_all(&sysroot_codegen_backends));
+            // copy `codegen-backends` from `host_lib_dir/rustlib/codegen_backends` to `stage0-sysroot/lib/rustlib/host-triple/codegen-backends` if it exists.
+            if host_codegen_backends.exists() {
+                builder.cp_r(&host_codegen_backends, &sysroot_codegen_backends);
+            }
+        }
     }
 }
 
@@ -467,7 +533,12 @@ fn copy_sanitizers(
         let dst = libdir.join(&runtime.name);
         builder.copy(&runtime.path, &dst);
 
-        if target == "x86_64-apple-darwin" || target == "aarch64-apple-darwin" {
+        if target == "x86_64-apple-darwin"
+            || target == "aarch64-apple-darwin"
+            || target == "aarch64-apple-ios"
+            || target == "aarch64-apple-ios-sim"
+            || target == "x86_64-apple-ios"
+        {
             // Update the library’s install name to reflect that it has been renamed.
             apple_darwin_update_library_name(&dst, &format!("@rpath/{}", &runtime.name));
             // Upon renaming the install name, the code signature of the file will invalidate,
diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs
index e5fad538969..cd027a4abb7 100644
--- a/src/bootstrap/config.rs
+++ b/src/bootstrap/config.rs
@@ -97,6 +97,10 @@ pub struct Config {
     pub cmd: Subcommand,
     pub incremental: bool,
     pub dry_run: DryRun,
+    /// Arguments appearing after `--` to be forwarded to tools,
+    /// e.g. `--fix-broken` or test arguments.
+    pub free_args: Vec<String>,
+
     /// `None` if we shouldn't download CI compiler artifacts, or the commit to download if we should.
     #[cfg(not(test))]
     download_rustc_commit: Option<String>,
@@ -866,6 +870,7 @@ impl Config {
         config.keep_stage = flags.keep_stage;
         config.keep_stage_std = flags.keep_stage_std;
         config.color = flags.color;
+        config.free_args = flags.free_args.clone().unwrap_or_default();
         if let Some(value) = flags.deny_warnings {
             config.deny_warnings = value;
         }
diff --git a/src/bootstrap/configure.py b/src/bootstrap/configure.py
index 0af329e7007..04e798e3949 100755
--- a/src/bootstrap/configure.py
+++ b/src/bootstrap/configure.py
@@ -379,8 +379,14 @@ cur_section = None
 sections[None] = []
 section_order = [None]
 targets = {}
+top_level_keys = []
 
 for line in open(rust_dir + '/config.toml.example').read().split("\n"):
+    if cur_section == None:
+        if line.count('=') == 1:
+            top_level_key = line.split('=')[0]
+            top_level_key = top_level_key.strip(' #')
+            top_level_keys.append(top_level_key)
     if line.startswith('['):
         cur_section = line[1:-1]
         if cur_section.startswith('target'):
@@ -459,12 +465,22 @@ def configure_section(lines, config):
                 raise RuntimeError("failed to find config line for {}".format(key))
 
 
-for section_key in config:
-    section_config = config[section_key]
-    if section_key not in sections:
-        raise RuntimeError("config key {} not in sections".format(section_key))
+def configure_top_level_key(lines, top_level_key, value):
+    for i, line in enumerate(lines):
+        if line.startswith('#' + top_level_key + ' = ') or line.startswith(top_level_key + ' = '):
+            lines[i] = "{} = {}".format(top_level_key, value)
+            return
 
-    if section_key == 'target':
+    raise RuntimeError("failed to find config line for {}".format(top_level_key))
+
+
+for section_key, section_config in config.items():
+    if section_key not in sections and section_key not in top_level_keys:
+        raise RuntimeError("config key {} not in sections or top_level_keys".format(section_key))
+    if section_key in top_level_keys:
+        configure_top_level_key(sections[None], section_key, section_config)
+
+    elif  section_key == 'target':
         for target in section_config:
             configure_section(targets[target], section_config[target])
     else:
diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs
index ff927ed561b..f07e710a9e6 100644
--- a/src/bootstrap/flags.rs
+++ b/src/bootstrap/flags.rs
@@ -80,6 +80,10 @@ pub struct Flags {
     pub llvm_profile_generate: bool,
     pub llvm_bolt_profile_generate: bool,
     pub llvm_bolt_profile_use: Option<String>,
+
+    /// Arguments appearing after `--` to be forwarded to tools,
+    /// e.g. `--fix-broken` or test arguments.
+    pub free_args: Option<Vec<String>>,
 }
 
 #[derive(Debug)]
@@ -157,6 +161,12 @@ impl Default for Subcommand {
 
 impl Flags {
     pub fn parse(args: &[String]) -> Flags {
+        let (args, free_args) = if let Some(pos) = args.iter().position(|s| s == "--") {
+            let (args, free) = args.split_at(pos);
+            (args, Some(free[1..].to_vec()))
+        } else {
+            (args, None)
+        };
         let mut subcommand_help = String::from(
             "\
 Usage: x.py <subcommand> [options] [<paths>...]
@@ -709,6 +719,7 @@ Arguments:
             llvm_profile_generate: matches.opt_present("llvm-profile-generate"),
             llvm_bolt_profile_generate: matches.opt_present("llvm-bolt-profile-generate"),
             llvm_bolt_profile_use: matches.opt_str("llvm-bolt-profile-use"),
+            free_args,
         }
     }
 }
diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs
index 9235de75ec6..d6e63fb937e 100644
--- a/src/bootstrap/native.rs
+++ b/src/bootstrap/native.rs
@@ -483,7 +483,7 @@ impl Step for Llvm {
             cfg.define("LLVM_VERSION_SUFFIX", suffix);
         }
 
-        configure_cmake(builder, target, &mut cfg, true, ldflags);
+        configure_cmake(builder, target, &mut cfg, true, ldflags, &[]);
         configure_llvm(builder, target, &mut cfg);
 
         for (key, val) in &builder.config.llvm_build_config {
@@ -574,6 +574,7 @@ fn configure_cmake(
     cfg: &mut cmake::Config,
     use_compiler_launcher: bool,
     mut ldflags: LdFlags,
+    extra_compiler_flags: &[&str],
 ) {
     // Do not print installation messages for up-to-date files.
     // LLVM and LLD builds can produce a lot of those and hit CI limits on log size.
@@ -714,6 +715,9 @@ fn configure_cmake(
     if builder.config.llvm_clang_cl.is_some() {
         cflags.push(&format!(" --target={}", target));
     }
+    for flag in extra_compiler_flags {
+        cflags.push(&format!(" {}", flag));
+    }
     cfg.define("CMAKE_C_FLAGS", cflags);
     let mut cxxflags: OsString = builder.cflags(target, GitRepo::Llvm, CLang::Cxx).join(" ").into();
     if let Some(ref s) = builder.config.llvm_cxxflags {
@@ -723,6 +727,9 @@ fn configure_cmake(
     if builder.config.llvm_clang_cl.is_some() {
         cxxflags.push(&format!(" --target={}", target));
     }
+    for flag in extra_compiler_flags {
+        cxxflags.push(&format!(" {}", flag));
+    }
     cfg.define("CMAKE_CXX_FLAGS", cxxflags);
     if let Some(ar) = builder.ar(target) {
         if ar.is_absolute() {
@@ -864,7 +871,7 @@ impl Step for Lld {
             }
         }
 
-        configure_cmake(builder, target, &mut cfg, true, ldflags);
+        configure_cmake(builder, target, &mut cfg, true, ldflags, &[]);
         configure_llvm(builder, target, &mut cfg);
 
         // Re-use the same flags as llvm to control the level of debug information
@@ -1028,7 +1035,16 @@ impl Step for Sanitizers {
         // Unfortunately sccache currently lacks support to build them successfully.
         // Disable compiler launcher on Darwin targets to avoid potential issues.
         let use_compiler_launcher = !self.target.contains("apple-darwin");
-        configure_cmake(builder, self.target, &mut cfg, use_compiler_launcher, LdFlags::default());
+        let extra_compiler_flags: &[&str] =
+            if self.target.contains("apple") { &["-fembed-bitcode=off"] } else { &[] };
+        configure_cmake(
+            builder,
+            self.target,
+            &mut cfg,
+            use_compiler_launcher,
+            LdFlags::default(),
+            extra_compiler_flags,
+        );
 
         t!(fs::create_dir_all(&out_dir));
         cfg.out_dir(out_dir);
@@ -1084,12 +1100,15 @@ fn supported_sanitizers(
 
     match &*target.triple {
         "aarch64-apple-darwin" => darwin_libs("osx", &["asan", "lsan", "tsan"]),
+        "aarch64-apple-ios" => darwin_libs("ios", &["asan", "tsan"]),
+        "aarch64-apple-ios-sim" => darwin_libs("iossim", &["asan", "tsan"]),
         "aarch64-unknown-fuchsia" => common_libs("fuchsia", "aarch64", &["asan"]),
         "aarch64-unknown-linux-gnu" => {
             common_libs("linux", "aarch64", &["asan", "lsan", "msan", "tsan", "hwasan"])
         }
         "x86_64-apple-darwin" => darwin_libs("osx", &["asan", "lsan", "tsan"]),
         "x86_64-unknown-fuchsia" => common_libs("fuchsia", "x86_64", &["asan"]),
+        "x86_64-apple-ios" => darwin_libs("iossim", &["asan", "tsan"]),
         "x86_64-unknown-freebsd" => common_libs("freebsd", "x86_64", &["asan", "msan", "tsan"]),
         "x86_64-unknown-netbsd" => {
             common_libs("netbsd", "x86_64", &["asan", "lsan", "msan", "tsan"])
diff --git a/src/bootstrap/run.rs b/src/bootstrap/run.rs
index e0280854541..e14440f57a8 100644
--- a/src/bootstrap/run.rs
+++ b/src/bootstrap/run.rs
@@ -183,6 +183,7 @@ impl Step for Miri {
         // Forward arguments.
         miri.arg("--").arg("--target").arg(target.rustc_target_arg());
         miri.args(builder.config.cmd.args());
+        miri.args(&builder.config.free_args);
 
         // miri tests need to know about the stage sysroot
         miri.env("MIRI_SYSROOT", &miri_sysroot);
diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs
index f8835fe11a8..9cd6107b43a 100644
--- a/src/bootstrap/test.rs
+++ b/src/bootstrap/test.rs
@@ -1588,6 +1588,7 @@ note: if you're sure you want to do this, please open an issue as to why. In the
             .collect();
 
         test_args.append(&mut builder.config.cmd.test_args());
+        test_args.extend(builder.config.free_args.iter().map(|s| s.as_str()));
 
         // On Windows, replace forward slashes in test-args by backslashes
         // so the correct filters are passed to libtest
diff --git a/src/doc/unstable-book/src/compiler-flags/sanitizer.md b/src/doc/unstable-book/src/compiler-flags/sanitizer.md
index 70c3a445b86..262cef3454a 100644
--- a/src/doc/unstable-book/src/compiler-flags/sanitizer.md
+++ b/src/doc/unstable-book/src/compiler-flags/sanitizer.md
@@ -531,6 +531,24 @@ LLVM KCFI is supported on the following targets:
 See the [Clang KernelControlFlowIntegrity documentation][clang-kcfi] for more
 details.
 
+# KernelAddressSanitizer
+
+KernelAddressSanitizer (KASAN) is a freestanding version of AddressSanitizer
+which is suitable for detecting memory errors in programs which do not have a
+runtime environment, such as operating system kernels. KernelAddressSanitizer
+requires manual implementation of the underlying functions used for tracking
+KernelAddressSanitizer state.
+
+KernelAddressSanitizer is supported on the following targets:
+
+* `aarch64-unknown-none`
+* `riscv64gc-unknown-none-elf`
+* `riscv64imac-unknown-none-elf`
+* `x86_64-unknown-none`
+
+See the [Linux Kernel's KernelAddressSanitizer documentation][linux-kasan] for
+more details.
+
 # LeakSanitizer
 
 LeakSanitizer is run-time memory leak detector.
@@ -714,6 +732,7 @@ Sanitizers produce symbolized stacktraces when llvm-symbolizer binary is in `PAT
 * [AddressSanitizer in Clang][clang-asan]
 * [ControlFlowIntegrity in Clang][clang-cfi]
 * [HWAddressSanitizer in Clang][clang-hwasan]
+* [Linux Kernel's KernelAddressSanitizer documentation][linux-kasan]
 * [LeakSanitizer in Clang][clang-lsan]
 * [MemorySanitizer in Clang][clang-msan]
 * [MemTagSanitizer in LLVM][llvm-memtag]
@@ -727,4 +746,5 @@ Sanitizers produce symbolized stacktraces when llvm-symbolizer binary is in `PAT
 [clang-msan]: https://clang.llvm.org/docs/MemorySanitizer.html
 [clang-scs]: https://clang.llvm.org/docs/ShadowCallStack.html
 [clang-tsan]: https://clang.llvm.org/docs/ThreadSanitizer.html
+[linux-kasan]: https://www.kernel.org/doc/html/latest/dev-tools/kasan.html
 [llvm-memtag]: https://llvm.org/docs/MemTagSanitizer.html
diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs
index 6c15eac2c19..9479b3ee036 100644
--- a/src/librustdoc/clean/auto_trait.rs
+++ b/src/librustdoc/clean/auto_trait.rs
@@ -137,7 +137,7 @@ where
     pub(crate) fn get_auto_trait_impls(&mut self, item_def_id: DefId) -> Vec<Item> {
         let tcx = self.cx.tcx;
         let param_env = tcx.param_env(item_def_id);
-        let ty = tcx.type_of(item_def_id);
+        let ty = tcx.type_of(item_def_id).subst_identity();
         let f = auto_trait::AutoTraitFinder::new(tcx);
 
         debug!("get_auto_trait_impls({:?})", ty);
diff --git a/src/librustdoc/clean/blanket_impl.rs b/src/librustdoc/clean/blanket_impl.rs
index e6b2b234945..bcdbbcacc4b 100644
--- a/src/librustdoc/clean/blanket_impl.rs
+++ b/src/librustdoc/clean/blanket_impl.rs
@@ -15,7 +15,7 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> {
     pub(crate) fn get_blanket_impls(&mut self, item_def_id: DefId) -> Vec<Item> {
         let cx = &mut self.cx;
         let param_env = cx.tcx.param_env(item_def_id);
-        let ty = cx.tcx.bound_type_of(item_def_id);
+        let ty = cx.tcx.type_of(item_def_id);
 
         trace!("get_blanket_impls({:?})", ty);
         let mut impls = Vec::new();
diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index 8bb8f122e22..148243683cb 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -303,7 +303,8 @@ fn build_union(cx: &mut DocContext<'_>, did: DefId) -> clean::Union {
 
 fn build_type_alias(cx: &mut DocContext<'_>, did: DefId) -> Box<clean::Typedef> {
     let predicates = cx.tcx.explicit_predicates_of(did);
-    let type_ = clean_middle_ty(ty::Binder::dummy(cx.tcx.type_of(did)), cx, Some(did));
+    let type_ =
+        clean_middle_ty(ty::Binder::dummy(cx.tcx.type_of(did).subst_identity()), cx, Some(did));
 
     Box::new(clean::Typedef {
         type_,
@@ -414,7 +415,9 @@ pub(crate) fn build_impl(
 
     let for_ = match &impl_item {
         Some(impl_) => clean_ty(impl_.self_ty, cx),
-        None => clean_middle_ty(ty::Binder::dummy(tcx.type_of(did)), cx, Some(did)),
+        None => {
+            clean_middle_ty(ty::Binder::dummy(tcx.type_of(did).subst_identity()), cx, Some(did))
+        }
     };
 
     // Only inline impl if the implementing type is
@@ -652,14 +655,22 @@ pub(crate) fn print_inlined_const(tcx: TyCtxt<'_>, did: DefId) -> String {
 
 fn build_const(cx: &mut DocContext<'_>, def_id: DefId) -> clean::Constant {
     clean::Constant {
-        type_: clean_middle_ty(ty::Binder::dummy(cx.tcx.type_of(def_id)), cx, Some(def_id)),
+        type_: clean_middle_ty(
+            ty::Binder::dummy(cx.tcx.type_of(def_id).subst_identity()),
+            cx,
+            Some(def_id),
+        ),
         kind: clean::ConstantKind::Extern { def_id },
     }
 }
 
 fn build_static(cx: &mut DocContext<'_>, did: DefId, mutable: bool) -> clean::Static {
     clean::Static {
-        type_: clean_middle_ty(ty::Binder::dummy(cx.tcx.type_of(did)), cx, Some(did)),
+        type_: clean_middle_ty(
+            ty::Binder::dummy(cx.tcx.type_of(did).subst_identity()),
+            cx,
+            Some(did),
+        ),
         mutability: if mutable { Mutability::Mut } else { Mutability::Not },
         expr: None,
     }
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 65736bb16fc..0c70d31ed60 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -11,6 +11,8 @@ pub(crate) mod types;
 pub(crate) mod utils;
 
 use rustc_ast as ast;
+use rustc_ast::token::{Token, TokenKind};
+use rustc_ast::tokenstream::{TokenStream, TokenTree};
 use rustc_attr as attr;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet, IndexEntry};
 use rustc_hir as hir;
@@ -19,7 +21,7 @@ use rustc_hir::def_id::{DefId, DefIdMap, DefIdSet, LocalDefId, LOCAL_CRATE};
 use rustc_hir::PredicateOrigin;
 use rustc_hir_analysis::hir_ty_to_ty;
 use rustc_infer::infer::region_constraints::{Constraint, RegionConstraintData};
-use rustc_middle::middle::resolve_lifetime as rl;
+use rustc_middle::middle::resolve_bound_vars as rbv;
 use rustc_middle::ty::fold::ir::TypeFolder;
 use rustc_middle::ty::InternalSubsts;
 use rustc_middle::ty::TypeVisitable;
@@ -198,11 +200,11 @@ fn clean_poly_trait_ref_with_bindings<'tcx>(
 }
 
 fn clean_lifetime<'tcx>(lifetime: &hir::Lifetime, cx: &mut DocContext<'tcx>) -> Lifetime {
-    let def = cx.tcx.named_region(lifetime.hir_id);
+    let def = cx.tcx.named_bound_var(lifetime.hir_id);
     if let Some(
-        rl::Region::EarlyBound(node_id)
-        | rl::Region::LateBound(_, _, node_id)
-        | rl::Region::Free(_, node_id),
+        rbv::ResolvedArg::EarlyBound(node_id)
+        | rbv::ResolvedArg::LateBound(_, _, node_id)
+        | rbv::ResolvedArg::Free(_, node_id),
     ) = def
     {
         if let Some(lt) = cx.substs.get(&node_id).and_then(|p| p.as_lt()).cloned() {
@@ -215,7 +217,11 @@ fn clean_lifetime<'tcx>(lifetime: &hir::Lifetime, cx: &mut DocContext<'tcx>) ->
 pub(crate) fn clean_const<'tcx>(constant: &hir::ConstArg, cx: &mut DocContext<'tcx>) -> Constant {
     let def_id = cx.tcx.hir().body_owner_def_id(constant.value.body).to_def_id();
     Constant {
-        type_: clean_middle_ty(ty::Binder::dummy(cx.tcx.type_of(def_id)), cx, Some(def_id)),
+        type_: clean_middle_ty(
+            ty::Binder::dummy(cx.tcx.type_of(def_id).subst_identity()),
+            cx,
+            Some(def_id),
+        ),
         kind: ConstantKind::Anonymous { body: constant.value.body },
     }
 }
@@ -314,6 +320,7 @@ pub(crate) fn clean_predicate<'tcx>(
         // FIXME(generic_const_exprs): should this do something?
         ty::PredicateKind::ConstEvaluatable(..) => None,
         ty::PredicateKind::WellFormed(..) => None,
+        ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..)) => None,
 
         ty::PredicateKind::Subtype(..)
         | ty::PredicateKind::AliasEq(..)
@@ -480,7 +487,7 @@ fn clean_generic_param_def<'tcx>(
         ty::GenericParamDefKind::Type { has_default, synthetic, .. } => {
             let default = if has_default {
                 Some(clean_middle_ty(
-                    ty::Binder::dummy(cx.tcx.type_of(def.def_id)),
+                    ty::Binder::dummy(cx.tcx.type_of(def.def_id).subst_identity()),
                     cx,
                     Some(def.def_id),
                 ))
@@ -502,7 +509,12 @@ fn clean_generic_param_def<'tcx>(
             GenericParamDefKind::Const {
                 did: def.def_id,
                 ty: Box::new(clean_middle_ty(
-                    ty::Binder::dummy(cx.tcx.type_of(def.def_id)),
+                    ty::Binder::dummy(
+                        cx.tcx
+                            .type_of(def.def_id)
+                            .no_bound_vars()
+                            .expect("const parameter types cannot be generic"),
+                    ),
                     cx,
                     Some(def.def_id),
                 )),
@@ -1212,7 +1224,7 @@ pub(crate) fn clean_middle_assoc_item<'tcx>(
     let kind = match assoc_item.kind {
         ty::AssocKind::Const => {
             let ty = clean_middle_ty(
-                ty::Binder::dummy(tcx.type_of(assoc_item.def_id)),
+                ty::Binder::dummy(tcx.type_of(assoc_item.def_id).subst_identity()),
                 cx,
                 Some(assoc_item.def_id),
             );
@@ -1251,7 +1263,7 @@ pub(crate) fn clean_middle_assoc_item<'tcx>(
 
             if assoc_item.fn_has_self_parameter {
                 let self_ty = match assoc_item.container {
-                    ty::ImplContainer => tcx.type_of(assoc_item.container_id(tcx)),
+                    ty::ImplContainer => tcx.type_of(assoc_item.container_id(tcx)).subst_identity(),
                     ty::TraitContainer => tcx.types.self_param,
                 };
                 let self_arg_ty = sig.input(0).skip_binder();
@@ -1398,7 +1410,7 @@ pub(crate) fn clean_middle_assoc_item<'tcx>(
                     AssocTypeItem(
                         Box::new(Typedef {
                             type_: clean_middle_ty(
-                                ty::Binder::dummy(tcx.type_of(assoc_item.def_id)),
+                                ty::Binder::dummy(tcx.type_of(assoc_item.def_id).subst_identity()),
                                 cx,
                                 Some(assoc_item.def_id),
                             ),
@@ -1416,7 +1428,7 @@ pub(crate) fn clean_middle_assoc_item<'tcx>(
                 AssocTypeItem(
                     Box::new(Typedef {
                         type_: clean_middle_ty(
-                            ty::Binder::dummy(tcx.type_of(assoc_item.def_id)),
+                            ty::Binder::dummy(tcx.type_of(assoc_item.def_id).subst_identity()),
                             cx,
                             Some(assoc_item.def_id),
                         ),
@@ -1926,7 +1938,11 @@ pub(crate) fn clean_middle_field<'tcx>(field: &ty::FieldDef, cx: &mut DocContext
     clean_field_with_def_id(
         field.did,
         field.name,
-        clean_middle_ty(ty::Binder::dummy(cx.tcx.type_of(field.did)), cx, Some(field.did)),
+        clean_middle_ty(
+            ty::Binder::dummy(cx.tcx.type_of(field.did).subst_identity()),
+            cx,
+            Some(field.did),
+        ),
         cx,
     )
 }
@@ -2079,8 +2095,8 @@ impl<'hir> hir::intravisit::Visitor<'hir> for OneLevelVisitor<'hir> {
     fn visit_item(&mut self, item: &'hir hir::Item<'hir>) {
         if self.item.is_none()
             && item.ident == self.looking_for
-            && matches!(item.kind, hir::ItemKind::Use(_, _))
-            || item.owner_id.def_id == self.target_def_id
+            && (matches!(item.kind, hir::ItemKind::Use(_, _))
+                || item.owner_id.def_id == self.target_def_id)
         {
             self.item = Some(item);
         }
@@ -2096,34 +2112,149 @@ fn get_all_import_attributes<'hir>(
     tcx: TyCtxt<'hir>,
     target_def_id: LocalDefId,
     attributes: &mut Vec<ast::Attribute>,
+    is_inline: bool,
 ) {
     let hir_map = tcx.hir();
     let mut visitor = OneLevelVisitor::new(hir_map, target_def_id);
     let mut visited = FxHashSet::default();
     // If the item is an import and has at least a path with two parts, we go into it.
-    while let hir::ItemKind::Use(path, _) = item.kind &&
-        path.segments.len() > 1 &&
-        let hir::def::Res::Def(_, def_id) = path.segments[path.segments.len() - 2].res &&
-        visited.insert(def_id)
-    {
-        if let Some(hir::Node::Item(parent_item)) = hir_map.get_if_local(def_id) {
-            // We add the attributes from this import into the list.
-            attributes.extend_from_slice(hir_map.attrs(item.hir_id()));
-            // We get the `Ident` we will be looking for into `item`.
-            let looking_for = path.segments[path.segments.len() - 1].ident;
-            visitor.reset(looking_for);
-            hir::intravisit::walk_item(&mut visitor, parent_item);
-            if let Some(i) = visitor.item {
-                item = i;
-            } else {
-                break;
+    while let hir::ItemKind::Use(path, _) = item.kind && visited.insert(item.hir_id()) {
+        // We add the attributes from this import into the list.
+        add_without_unwanted_attributes(attributes, hir_map.attrs(item.hir_id()), is_inline);
+
+        let def_id = if path.segments.len() > 1 {
+            match path.segments[path.segments.len() - 2].res {
+                hir::def::Res::Def(_, def_id) => def_id,
+                _ => break,
+            }
+        } else {
+            // If the path doesn't have a parent, then the parent is the current module.
+            tcx.parent(item.owner_id.def_id.to_def_id())
+        };
+
+        let Some(parent) = hir_map.get_if_local(def_id) else { break };
+
+        // We get the `Ident` we will be looking for into `item`.
+        let looking_for = path.segments[path.segments.len() - 1].ident;
+        visitor.reset(looking_for);
+
+        match parent {
+            hir::Node::Item(parent_item) => {
+                hir::intravisit::walk_item(&mut visitor, parent_item);
+            }
+            hir::Node::Crate(m) => {
+                hir::intravisit::walk_mod(
+                    &mut visitor,
+                    m,
+                    tcx.local_def_id_to_hir_id(def_id.as_local().unwrap()),
+                );
             }
+            _ => break,
+        }
+        if let Some(i) = visitor.item {
+            item = i;
         } else {
             break;
         }
     }
 }
 
+fn filter_tokens_from_list(
+    args_tokens: TokenStream,
+    should_retain: impl Fn(&TokenTree) -> bool,
+) -> Vec<TokenTree> {
+    let mut tokens = Vec::with_capacity(args_tokens.len());
+    let mut skip_next_comma = false;
+    for token in args_tokens.into_trees() {
+        match token {
+            TokenTree::Token(Token { kind: TokenKind::Comma, .. }, _) if skip_next_comma => {
+                skip_next_comma = false;
+            }
+            token if should_retain(&token) => {
+                skip_next_comma = false;
+                tokens.push(token);
+            }
+            _ => {
+                skip_next_comma = true;
+            }
+        }
+    }
+    tokens
+}
+
+/// When inlining items, we merge its attributes (and all the reexports attributes too) with the
+/// final reexport. For example:
+///
+/// ```ignore (just an example)
+/// #[doc(hidden, cfg(feature = "foo"))]
+/// pub struct Foo;
+///
+/// #[doc(cfg(feature = "bar"))]
+/// #[doc(hidden, no_inline)]
+/// pub use Foo as Foo1;
+///
+/// #[doc(inline)]
+/// pub use Foo2 as Bar;
+/// ```
+///
+/// So `Bar` at the end will have both `cfg(feature = "...")`. However, we don't want to merge all
+/// attributes so we filter out the following ones:
+/// * `doc(inline)`
+/// * `doc(no_inline)`
+/// * `doc(hidden)`
+fn add_without_unwanted_attributes(
+    attrs: &mut Vec<ast::Attribute>,
+    new_attrs: &[ast::Attribute],
+    is_inline: bool,
+) {
+    // If it's `#[doc(inline)]`, we don't want all attributes, otherwise we keep everything.
+    if !is_inline {
+        attrs.extend_from_slice(new_attrs);
+        return;
+    }
+    for attr in new_attrs {
+        let mut attr = attr.clone();
+        match attr.kind {
+            ast::AttrKind::Normal(ref mut normal) => {
+                if let [ident] = &*normal.item.path.segments &&
+                    let ident = ident.ident.name &&
+                    ident == sym::doc
+                {
+                    match normal.item.args {
+                        ast::AttrArgs::Delimited(ref mut args) => {
+                            let tokens =
+                                filter_tokens_from_list(args.tokens.clone(), |token| {
+                                    !matches!(
+                                        token,
+                                        TokenTree::Token(
+                                            Token {
+                                                kind: TokenKind::Ident(
+                                                    sym::hidden | sym::inline | sym::no_inline,
+                                                    _,
+                                                ),
+                                                ..
+                                            },
+                                            _,
+                                        ),
+                                    )
+                                });
+                            args.tokens = TokenStream::new(tokens);
+                            attrs.push(attr);
+                        }
+                        ast::AttrArgs::Empty | ast::AttrArgs::Eq(..) => {
+                            attrs.push(attr);
+                            continue;
+                        }
+                    }
+                }
+            }
+            ast::AttrKind::DocComment(..) => {
+                attrs.push(attr);
+            }
+        }
+    }
+}
+
 fn clean_maybe_renamed_item<'tcx>(
     cx: &mut DocContext<'tcx>,
     item: &hir::Item<'tcx>,
@@ -2212,19 +2343,20 @@ fn clean_maybe_renamed_item<'tcx>(
         {
             // First, we add the attributes from the current import.
             extra_attrs.extend_from_slice(inline::load_attrs(cx, import_id.to_def_id()));
+            let is_inline = extra_attrs.lists(sym::doc).get_word_attr(sym::inline).is_some();
             // Then we get all the various imports' attributes.
-            get_all_import_attributes(use_node, cx.tcx, item.owner_id.def_id, &mut extra_attrs);
+            get_all_import_attributes(use_node, cx.tcx, item.owner_id.def_id, &mut extra_attrs, is_inline);
+            add_without_unwanted_attributes(&mut extra_attrs, inline::load_attrs(cx, def_id), is_inline);
+        } else {
+            // We only keep the item's attributes.
+            extra_attrs.extend_from_slice(inline::load_attrs(cx, def_id));
         }
 
-        let mut item = if !extra_attrs.is_empty() {
-            extra_attrs.extend_from_slice(inline::load_attrs(cx, def_id));
-            let attrs = Attributes::from_ast(&extra_attrs);
-            let cfg = extra_attrs.cfg(cx.tcx, &cx.cache.hidden_cfg);
+        let attrs = Attributes::from_ast(&extra_attrs);
+        let cfg = extra_attrs.cfg(cx.tcx, &cx.cache.hidden_cfg);
 
-            Item::from_def_id_and_attrs_and_parts(def_id, Some(name), kind, Box::new(attrs), cfg)
-        } else {
-            Item::from_def_id_and_parts(def_id, Some(name), kind, cx)
-        };
+        let mut item =
+            Item::from_def_id_and_attrs_and_parts(def_id, Some(name), kind, Box::new(attrs), cfg);
         item.inline_stmt_id = import_id.map(|def_id| def_id.to_def_id());
         vec![item]
     })
@@ -2257,9 +2389,11 @@ fn clean_impl<'tcx>(
 
     let for_ = clean_ty(impl_.self_ty, cx);
     let type_alias = for_.def_id(&cx.cache).and_then(|did| match tcx.def_kind(did) {
-        DefKind::TyAlias => {
-            Some(clean_middle_ty(ty::Binder::dummy(tcx.type_of(did)), cx, Some(did)))
-        }
+        DefKind::TyAlias => Some(clean_middle_ty(
+            ty::Binder::dummy(tcx.type_of(did).subst_identity()),
+            cx,
+            Some(did),
+        )),
         _ => None,
     });
     let mut make_item = |trait_: Option<Path>, for_: Type, items: Vec<Item>| {
diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs
index 4d8ce54dc5c..5a564c2ac1c 100644
--- a/src/librustdoc/clean/utils.rs
+++ b/src/librustdoc/clean/utils.rs
@@ -129,7 +129,7 @@ fn external_generic_args<'tcx>(
         });
         GenericArgs::Parenthesized { inputs, output }
     } else {
-        GenericArgs::AngleBracketed { args: args.into(), bindings: bindings.into() }
+        GenericArgs::AngleBracketed { args: args.into(), bindings }
     }
 }
 
@@ -266,7 +266,7 @@ pub(crate) fn print_evaluated_const(
     underscores_and_type: bool,
 ) -> Option<String> {
     tcx.const_eval_poly(def_id).ok().and_then(|val| {
-        let ty = tcx.type_of(def_id);
+        let ty = tcx.type_of(def_id).subst_identity();
         match (val, ty.kind()) {
             (_, &ty::Ref(..)) => None,
             (ConstValue::Scalar(_), &ty::Adt(_, _)) => None,
diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs
index b1db16cfe3c..68bdd2bc531 100644
--- a/src/librustdoc/formats/cache.rs
+++ b/src/librustdoc/formats/cache.rs
@@ -453,7 +453,7 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> {
                 | clean::BorrowedRef { type_: box clean::Type::Path { ref path }, .. } => {
                     dids.insert(path.def_id());
                     if let Some(generics) = path.generics() &&
-                        let ty::Adt(adt, _) = self.tcx.type_of(path.def_id()).kind() &&
+                        let ty::Adt(adt, _) = self.tcx.type_of(path.def_id()).subst_identity().kind() &&
                         adt.is_fundamental() {
                         for ty in generics {
                             if let Some(did) = ty.def_id(self.cache) {
diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs
index 1ed0b0bc2d5..aa406f30cbe 100644
--- a/src/librustdoc/html/format.rs
+++ b/src/librustdoc/html/format.rs
@@ -361,7 +361,7 @@ pub(crate) fn print_where_clause<'a, 'tcx: 'a>(
             for _ in 0..padding_amout {
                 br_with_padding.push_str(" ");
             }
-            let where_preds = where_preds.to_string().replace("\n", &br_with_padding);
+            let where_preds = where_preds.to_string().replace('\n', &br_with_padding);
 
             if ending == Ending::Newline {
                 let mut clause = " ".repeat(indent.saturating_sub(1));
@@ -1419,12 +1419,12 @@ impl clean::FnDecl {
             format!(
                 "({pad}{args}{close}){arrow}",
                 pad = if self.inputs.values.is_empty() { "" } else { &full_pad },
-                args = args.replace("\n", &full_pad),
+                args = args.replace('\n', &full_pad),
                 close = close_pad,
                 arrow = arrow
             )
         } else {
-            format!("({args}){arrow}", args = args.replace("\n", " "), arrow = arrow)
+            format!("({args}){arrow}", args = args.replace('\n', " "), arrow = arrow)
         };
 
         write!(f, "{}", output)
diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs
index 4ff1c93dc5d..387984a2b3b 100644
--- a/src/librustdoc/html/render/print_item.rs
+++ b/src/librustdoc/html/render/print_item.rs
@@ -1855,7 +1855,7 @@ fn document_type_layout(w: &mut Buffer, cx: &Context<'_>, ty_def_id: DefId) {
 
     let tcx = cx.tcx();
     let param_env = tcx.param_env(ty_def_id);
-    let ty = tcx.type_of(ty_def_id);
+    let ty = tcx.type_of(ty_def_id).subst_identity();
     match tcx.layout_of(param_env.and(ty)) {
         Ok(ty_layout) => {
             writeln!(
diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs
index b2208da9060..d2c6e7ab024 100644
--- a/src/librustdoc/passes/collect_intra_doc_links.rs
+++ b/src/librustdoc/passes/collect_intra_doc_links.rs
@@ -293,7 +293,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
         let ty_res = self.resolve_path(&path, TypeNS, item_id, module_id).ok_or_else(no_res)?;
 
         match ty_res {
-            Res::Def(DefKind::Enum, did) => match tcx.type_of(did).kind() {
+            Res::Def(DefKind::Enum, did) => match tcx.type_of(did).subst_identity().kind() {
                 ty::Adt(def, _) if def.is_enum() => {
                     if let Some(variant) = def.variants().iter().find(|v| v.name == variant_name)
                         && let Some(field) = variant.fields.iter().find(|f| f.name == variant_field_name) {
@@ -471,7 +471,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
     /// This is used for resolving type aliases.
     fn def_id_to_res(&self, ty_id: DefId) -> Option<Res> {
         use PrimitiveType::*;
-        Some(match *self.cx.tcx.type_of(ty_id).kind() {
+        Some(match *self.cx.tcx.type_of(ty_id).subst_identity().kind() {
             ty::Bool => Res::Primitive(Bool),
             ty::Char => Res::Primitive(Char),
             ty::Int(ity) => Res::Primitive(ity.into()),
@@ -572,7 +572,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
                 debug!("looking for associated item named {} for item {:?}", item_name, did);
                 // Checks if item_name is a variant of the `SomeItem` enum
                 if ns == TypeNS && def_kind == DefKind::Enum {
-                    match tcx.type_of(did).kind() {
+                    match tcx.type_of(did).subst_identity().kind() {
                         ty::Adt(adt_def, _) => {
                             for variant in adt_def.variants() {
                                 if variant.name == item_name {
@@ -606,7 +606,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
                     // something like [`ambi_fn`](<SomeStruct as SomeTrait>::ambi_fn)
                     .or_else(|| {
                         resolve_associated_trait_item(
-                            tcx.type_of(did),
+                            tcx.type_of(did).subst_identity(),
                             module_id,
                             item_name,
                             ns,
@@ -639,7 +639,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
                 // they also look like associated items (`module::Type::Variant`),
                 // because they are real Rust syntax (unlike the intra-doc links
                 // field syntax) and are handled by the compiler's resolver.
-                let def = match tcx.type_of(did).kind() {
+                let def = match tcx.type_of(did).subst_identity().kind() {
                     ty::Adt(def, _) if !def.is_enum() => def,
                     _ => return None,
                 };
@@ -689,12 +689,12 @@ fn resolve_associated_trait_item<'a>(
             .find_by_name_and_namespace(cx.tcx, Ident::with_dummy_span(item_name), ns, trait_)
             .map(|trait_assoc| {
                 trait_assoc_to_impl_assoc_item(cx.tcx, impl_, trait_assoc.def_id)
-                    .unwrap_or(trait_assoc)
+                    .unwrap_or(*trait_assoc)
             })
     });
     // FIXME(#74563): warn about ambiguity
     debug!("the candidates were {:?}", candidates.clone().collect::<Vec<_>>());
-    candidates.next().copied()
+    candidates.next()
 }
 
 /// Find the associated item in the impl `impl_id` that corresponds to the
@@ -711,7 +711,7 @@ fn trait_assoc_to_impl_assoc_item<'tcx>(
     tcx: TyCtxt<'tcx>,
     impl_id: DefId,
     trait_assoc_id: DefId,
-) -> Option<&'tcx ty::AssocItem> {
+) -> Option<ty::AssocItem> {
     let trait_to_impl_assoc_map = tcx.impl_item_implementor_ids(impl_id);
     debug!(?trait_to_impl_assoc_map);
     let impl_assoc_id = *trait_to_impl_assoc_map.get(&trait_assoc_id)?;
@@ -1710,7 +1710,7 @@ fn resolution_failure(
                         Res::Primitive(_) => None,
                     };
                     let is_struct_variant = |did| {
-                        if let ty::Adt(def, _) = tcx.type_of(did).kind()
+                        if let ty::Adt(def, _) = tcx.type_of(did).subst_identity().kind()
                         && def.is_enum()
                         && let Some(variant) = def.variants().iter().find(|v| v.name == res.name(tcx)) {
                             // ctor is `None` if variant is a struct
diff --git a/src/librustdoc/passes/collect_trait_impls.rs b/src/librustdoc/passes/collect_trait_impls.rs
index 189b37b69d1..01ed4a60b3b 100644
--- a/src/librustdoc/passes/collect_trait_impls.rs
+++ b/src/librustdoc/passes/collect_trait_impls.rs
@@ -109,7 +109,7 @@ pub(crate) fn collect_trait_impls(mut krate: Crate, cx: &mut DocContext<'_>) ->
                     // `Generics`. To avoid relying on the `impl` block, these
                     // things would need to be created from wholecloth, in a
                     // form that is valid for use in type inference.
-                    let ty = tcx.type_of(def_id);
+                    let ty = tcx.type_of(def_id).subst_identity();
                     match ty.kind() {
                         ty::Slice(ty)
                         | ty::Ref(_, ty, _)
diff --git a/src/librustdoc/scrape_examples.rs b/src/librustdoc/scrape_examples.rs
index f2ee99cd9d4..f28c164d61d 100644
--- a/src/librustdoc/scrape_examples.rs
+++ b/src/librustdoc/scrape_examples.rs
@@ -169,7 +169,7 @@ where
                 };
 
                 let ident_span = path.ident.span;
-                (tcx.type_of(def_id), call_span, ident_span)
+                (tcx.type_of(def_id).subst_identity(), call_span, ident_span)
             }
             _ => {
                 return;
diff --git a/src/tools/cargo b/src/tools/cargo
-Subproject 39c13e67a5962466cc7253d41bc1099bbcb224c
+Subproject 17b3d0de0897e1c6b8ca347bd39f850bb0a5b9f
diff --git a/src/tools/clippy/clippy_lints/src/casts/cast_ptr_alignment.rs b/src/tools/clippy/clippy_lints/src/casts/cast_ptr_alignment.rs
index 97054a0d101..6c8ee296c75 100644
--- a/src/tools/clippy/clippy_lints/src/casts/cast_ptr_alignment.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/cast_ptr_alignment.rs
@@ -66,7 +66,7 @@ fn is_used_as_unaligned(cx: &LateContext<'_>, e: &Expr<'_>) -> bool {
             if matches!(name.ident.as_str(), "read_unaligned" | "write_unaligned")
                 && let Some(def_id) = cx.typeck_results().type_dependent_def_id(parent.hir_id)
                 && let Some(def_id) = cx.tcx.impl_of_method(def_id)
-                && cx.tcx.type_of(def_id).is_unsafe_ptr()
+                && cx.tcx.type_of(def_id).subst_identity().is_unsafe_ptr()
             {
                 true
             } else {
diff --git a/src/tools/clippy/clippy_lints/src/copy_iterator.rs b/src/tools/clippy/clippy_lints/src/copy_iterator.rs
index e38f7726853..0fc11523298 100644
--- a/src/tools/clippy/clippy_lints/src/copy_iterator.rs
+++ b/src/tools/clippy/clippy_lints/src/copy_iterator.rs
@@ -43,7 +43,7 @@ impl<'tcx> LateLintPass<'tcx> for CopyIterator {
                 of_trait: Some(ref trait_ref),
                 ..
             }) = item.kind;
-            let ty = cx.tcx.type_of(item.owner_id);
+            let ty = cx.tcx.type_of(item.owner_id).subst_identity();
             if is_copy(cx, ty);
             if let Some(trait_id) = trait_ref.trait_def_id();
             if cx.tcx.is_diagnostic_item(sym::Iterator, trait_id);
diff --git a/src/tools/clippy/clippy_lints/src/default.rs b/src/tools/clippy/clippy_lints/src/default.rs
index a04693f4637..080d44e6398 100644
--- a/src/tools/clippy/clippy_lints/src/default.rs
+++ b/src/tools/clippy/clippy_lints/src/default.rs
@@ -150,7 +150,7 @@ impl<'tcx> LateLintPass<'tcx> for Default {
                     .fields
                     .iter()
                     .all(|field| {
-                        is_copy(cx, cx.tcx.type_of(field.did))
+                        is_copy(cx, cx.tcx.type_of(field.did).subst_identity())
                     });
                 if !has_drop(cx, binding_type) || all_fields_are_copy;
                 then {
diff --git a/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs b/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs
index f806ba238c7..4e1a6cd4d73 100644
--- a/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs
+++ b/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs
@@ -167,7 +167,7 @@ impl<'a, 'tcx> Visitor<'tcx> for NumericFallbackVisitor<'a, 'tcx> {
                                     .iter()
                                     .find_map(|f_def| {
                                         if f_def.ident(self.cx.tcx) == field.ident
-                                            { Some(self.cx.tcx.type_of(f_def.did)) }
+                                            { Some(self.cx.tcx.type_of(f_def.did).subst_identity()) }
                                         else { None }
                                     });
                             self.ty_bounds.push(bound.into());
diff --git a/src/tools/clippy/clippy_lints/src/dereference.rs b/src/tools/clippy/clippy_lints/src/dereference.rs
index 6c333afacc6..b4543aa2544 100644
--- a/src/tools/clippy/clippy_lints/src/dereference.rs
+++ b/src/tools/clippy/clippy_lints/src/dereference.rs
@@ -735,7 +735,7 @@ fn walk_parents<'tcx>(
                 span,
                 ..
             }) if span.ctxt() == ctxt => {
-                let ty = cx.tcx.type_of(owner_id.def_id);
+                let ty = cx.tcx.type_of(owner_id.def_id).subst_identity();
                 Some(ty_auto_deref_stability(cx, ty, precedence).position_for_result(cx))
             },
 
@@ -771,7 +771,7 @@ fn walk_parents<'tcx>(
                 }) => variant_of_res(cx, cx.qpath_res(path, *hir_id))
                     .and_then(|variant| variant.fields.iter().find(|f| f.name == field.ident.name))
                     .map(|field_def| {
-                        ty_auto_deref_stability(cx, cx.tcx.type_of(field_def.did), precedence).position_for_arg()
+                        ty_auto_deref_stability(cx, cx.tcx.type_of(field_def.did).subst_identity(), precedence).position_for_arg()
                     }),
                 _ => None,
             },
diff --git a/src/tools/clippy/clippy_lints/src/derivable_impls.rs b/src/tools/clippy/clippy_lints/src/derivable_impls.rs
index bc18e2e5ed5..f95b8ccf067 100644
--- a/src/tools/clippy/clippy_lints/src/derivable_impls.rs
+++ b/src/tools/clippy/clippy_lints/src/derivable_impls.rs
@@ -184,7 +184,7 @@ impl<'tcx> LateLintPass<'tcx> for DerivableImpls {
             if let Some(Node::ImplItem(impl_item)) = cx.tcx.hir().find(impl_item_hir);
             if let ImplItemKind::Fn(_, b) = &impl_item.kind;
             if let Body { value: func_expr, .. } = cx.tcx.hir().body(*b);
-            if let Some(adt_def) = cx.tcx.type_of(item.owner_id).ty_adt_def();
+            if let Some(adt_def) = cx.tcx.type_of(item.owner_id).subst_identity().ty_adt_def();
             if let attrs = cx.tcx.hir().attrs(item.hir_id());
             if !attrs.iter().any(|attr| attr.doc_str().is_some());
             if let child_attrs = cx.tcx.hir().attrs(impl_item_hir);
diff --git a/src/tools/clippy/clippy_lints/src/derive.rs b/src/tools/clippy/clippy_lints/src/derive.rs
index f8fc726d603..1cdcccd5f14 100644
--- a/src/tools/clippy/clippy_lints/src/derive.rs
+++ b/src/tools/clippy/clippy_lints/src/derive.rs
@@ -211,7 +211,7 @@ impl<'tcx> LateLintPass<'tcx> for Derive {
             ..
         }) = item.kind
         {
-            let ty = cx.tcx.type_of(item.owner_id);
+            let ty = cx.tcx.type_of(item.owner_id).subst_identity();
             let is_automatically_derived = cx.tcx.has_attr(item.owner_id.to_def_id(), sym::automatically_derived);
 
             check_hash_peq(cx, item.span, trait_ref, ty, is_automatically_derived);
@@ -347,7 +347,7 @@ fn check_copy_clone<'tcx>(cx: &LateContext<'tcx>, item: &Item<'_>, trait_ref: &h
             let has_copy_impl = cx.tcx.all_local_trait_impls(()).get(&copy_id).map_or(false, |impls| {
                 impls
                     .iter()
-                    .any(|&id| matches!(cx.tcx.type_of(id).kind(), ty::Adt(adt, _) if ty_adt.did() == adt.did()))
+                    .any(|&id| matches!(cx.tcx.type_of(id).subst_identity().kind(), ty::Adt(adt, _) if ty_adt.did() == adt.did()))
             });
             if !has_copy_impl {
                 return;
diff --git a/src/tools/clippy/clippy_lints/src/empty_enum.rs b/src/tools/clippy/clippy_lints/src/empty_enum.rs
index 0570c2a1013..d94664daa56 100644
--- a/src/tools/clippy/clippy_lints/src/empty_enum.rs
+++ b/src/tools/clippy/clippy_lints/src/empty_enum.rs
@@ -49,7 +49,7 @@ impl<'tcx> LateLintPass<'tcx> for EmptyEnum {
         }
 
         if let ItemKind::Enum(..) = item.kind {
-            let ty = cx.tcx.type_of(item.owner_id);
+            let ty = cx.tcx.type_of(item.owner_id).subst_identity();
             let adt = ty.ty_adt_def().expect("already checked whether this is an enum");
             if adt.variants().is_empty() {
                 span_lint_and_help(
diff --git a/src/tools/clippy/clippy_lints/src/enum_clike.rs b/src/tools/clippy/clippy_lints/src/enum_clike.rs
index da67888827d..e275efaba25 100644
--- a/src/tools/clippy/clippy_lints/src/enum_clike.rs
+++ b/src/tools/clippy/clippy_lints/src/enum_clike.rs
@@ -45,7 +45,7 @@ impl<'tcx> LateLintPass<'tcx> for UnportableVariant {
             for var in def.variants {
                 if let Some(anon_const) = &var.disr_expr {
                     let def_id = cx.tcx.hir().body_owner_def_id(anon_const.body);
-                    let mut ty = cx.tcx.type_of(def_id.to_def_id());
+                    let mut ty = cx.tcx.type_of(def_id.to_def_id()).subst_identity();
                     let constant = cx
                         .tcx
                         .const_eval_poly(def_id.to_def_id())
diff --git a/src/tools/clippy/clippy_lints/src/eta_reduction.rs b/src/tools/clippy/clippy_lints/src/eta_reduction.rs
index 3543910c3b5..ddade65c515 100644
--- a/src/tools/clippy/clippy_lints/src/eta_reduction.rs
+++ b/src/tools/clippy/clippy_lints/src/eta_reduction.rs
@@ -108,7 +108,7 @@ impl<'tcx> LateLintPass<'tcx> for EtaReduction {
             if check_inputs(cx, body.params, None, args);
             let callee_ty = cx.typeck_results().expr_ty_adjusted(callee);
             let call_ty = cx.typeck_results().type_dependent_def_id(body.value.hir_id)
-                .map_or(callee_ty, |id| cx.tcx.type_of(id));
+                .map_or(callee_ty, |id| cx.tcx.type_of(id).subst_identity());
             if check_sig(cx, closure_ty, call_ty);
             let substs = cx.typeck_results().node_substs(callee.hir_id);
             // This fixes some false positives that I don't entirely understand
@@ -153,7 +153,7 @@ impl<'tcx> LateLintPass<'tcx> for EtaReduction {
             if check_inputs(cx, body.params, Some(receiver), args);
             let method_def_id = cx.typeck_results().type_dependent_def_id(body.value.hir_id).unwrap();
             let substs = cx.typeck_results().node_substs(body.value.hir_id);
-            let call_ty = cx.tcx.bound_type_of(method_def_id).subst(cx.tcx, substs);
+            let call_ty = cx.tcx.type_of(method_def_id).subst(cx.tcx, substs);
             if check_sig(cx, closure_ty, call_ty);
             then {
                 span_lint_and_then(cx, REDUNDANT_CLOSURE_FOR_METHOD_CALLS, expr.span, "redundant closure", |diag| {
@@ -233,7 +233,7 @@ fn get_ufcs_type_name<'tcx>(cx: &LateContext<'tcx>, method_def_id: DefId, substs
     match assoc_item.container {
         ty::TraitContainer => cx.tcx.def_path_str(def_id),
         ty::ImplContainer => {
-            let ty = cx.tcx.type_of(def_id);
+            let ty = cx.tcx.type_of(def_id).skip_binder();
             match ty.kind() {
                 ty::Adt(adt, _) => cx.tcx.def_path_str(adt.did()),
                 ty::Array(..)
diff --git a/src/tools/clippy/clippy_lints/src/implicit_saturating_sub.rs b/src/tools/clippy/clippy_lints/src/implicit_saturating_sub.rs
index 29d59c26d92..0c7aea6da8f 100644
--- a/src/tools/clippy/clippy_lints/src/implicit_saturating_sub.rs
+++ b/src/tools/clippy/clippy_lints/src/implicit_saturating_sub.rs
@@ -102,7 +102,7 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitSaturatingSub {
                             if let Some(const_id) = cx.typeck_results().type_dependent_def_id(cond_num_val.hir_id);
                             if let Some(impl_id) = cx.tcx.impl_of_method(const_id);
                             if let None = cx.tcx.impl_trait_ref(impl_id); // An inherent impl
-                            if cx.tcx.type_of(impl_id).is_integral();
+                            if cx.tcx.type_of(impl_id).subst_identity().is_integral();
                             then {
                                 print_lint_and_sugg(cx, var_name, expr)
                             }
@@ -115,7 +115,7 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitSaturatingSub {
                             if let Some(func_id) = cx.typeck_results().type_dependent_def_id(func.hir_id);
                             if let Some(impl_id) = cx.tcx.impl_of_method(func_id);
                             if let None = cx.tcx.impl_trait_ref(impl_id); // An inherent impl
-                            if cx.tcx.type_of(impl_id).is_integral();
+                            if cx.tcx.type_of(impl_id).subst_identity().is_integral();
                             then {
                                 print_lint_and_sugg(cx, var_name, expr)
                             }
diff --git a/src/tools/clippy/clippy_lints/src/inherent_impl.rs b/src/tools/clippy/clippy_lints/src/inherent_impl.rs
index e9b2e31a769..7c41699f307 100644
--- a/src/tools/clippy/clippy_lints/src/inherent_impl.rs
+++ b/src/tools/clippy/clippy_lints/src/inherent_impl.rs
@@ -66,7 +66,8 @@ impl<'tcx> LateLintPass<'tcx> for MultipleInherentImpl {
             )
         }) {
             for impl_id in impl_ids.iter().map(|id| id.expect_local()) {
-                match type_map.entry(cx.tcx.type_of(impl_id)) {
+                let impl_ty = cx.tcx.type_of(impl_id).subst_identity();
+                match type_map.entry(impl_ty) {
                     Entry::Vacant(e) => {
                         // Store the id for the first impl block of this type. The span is retrieved lazily.
                         e.insert(IdOrSpan::Id(impl_id));
diff --git a/src/tools/clippy/clippy_lints/src/large_enum_variant.rs b/src/tools/clippy/clippy_lints/src/large_enum_variant.rs
index b8d4abdbb78..1c99bd2f3d0 100644
--- a/src/tools/clippy/clippy_lints/src/large_enum_variant.rs
+++ b/src/tools/clippy/clippy_lints/src/large_enum_variant.rs
@@ -83,7 +83,7 @@ impl<'tcx> LateLintPass<'tcx> for LargeEnumVariant {
             return;
         }
         if let ItemKind::Enum(ref def, _) = item.kind {
-            let ty = cx.tcx.type_of(item.owner_id);
+            let ty = cx.tcx.type_of(item.owner_id).subst_identity();
             let Adt(adt, subst) = ty.kind() else {
                 panic!("already checked whether this is an enum")
             };
diff --git a/src/tools/clippy/clippy_lints/src/matches/rest_pat_in_fully_bound_struct.rs b/src/tools/clippy/clippy_lints/src/matches/rest_pat_in_fully_bound_struct.rs
index 0aadb482acd..d06bcdaa27f 100644
--- a/src/tools/clippy/clippy_lints/src/matches/rest_pat_in_fully_bound_struct.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/rest_pat_in_fully_bound_struct.rs
@@ -10,7 +10,7 @@ pub(crate) fn check(cx: &LateContext<'_>, pat: &Pat<'_>) {
         if !pat.span.from_expansion();
         if let PatKind::Struct(QPath::Resolved(_, path), fields, true) = pat.kind;
         if let Some(def_id) = path.res.opt_def_id();
-        let ty = cx.tcx.type_of(def_id);
+        let ty = cx.tcx.type_of(def_id).subst_identity();
         if let ty::Adt(def, _) = ty.kind();
         if def.is_struct() || def.is_union();
         if fields.len() == def.non_enum_variant().fields.len();
diff --git a/src/tools/clippy/clippy_lints/src/methods/bytes_count_to_len.rs b/src/tools/clippy/clippy_lints/src/methods/bytes_count_to_len.rs
index 89aaad359d4..46a20ad412b 100644
--- a/src/tools/clippy/clippy_lints/src/methods/bytes_count_to_len.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/bytes_count_to_len.rs
@@ -17,7 +17,7 @@ pub(super) fn check<'tcx>(
     if_chain! {
         if let Some(bytes_id) = cx.typeck_results().type_dependent_def_id(count_recv.hir_id);
         if let Some(impl_id) = cx.tcx.impl_of_method(bytes_id);
-        if cx.tcx.type_of(impl_id).is_str();
+        if cx.tcx.type_of(impl_id).subst_identity().is_str();
         let ty = cx.typeck_results().expr_ty(bytes_recv).peel_refs();
         if ty.is_str() || is_type_lang_item(cx, ty, hir::LangItem::String);
         then {
diff --git a/src/tools/clippy/clippy_lints/src/methods/case_sensitive_file_extension_comparisons.rs b/src/tools/clippy/clippy_lints/src/methods/case_sensitive_file_extension_comparisons.rs
index 0b3bf22743f..7711aa78b23 100644
--- a/src/tools/clippy/clippy_lints/src/methods/case_sensitive_file_extension_comparisons.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/case_sensitive_file_extension_comparisons.rs
@@ -30,7 +30,7 @@ pub(super) fn check<'tcx>(
     if_chain! {
         if let Some(method_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id);
         if let Some(impl_id) = cx.tcx.impl_of_method(method_id);
-        if cx.tcx.type_of(impl_id).is_str();
+        if cx.tcx.type_of(impl_id).subst_identity().is_str();
         if let ExprKind::Lit(Spanned { node: LitKind::Str(ext_literal, ..), ..}) = arg.kind;
         if (2..=6).contains(&ext_literal.as_str().len());
         let ext_str = ext_literal.as_str();
diff --git a/src/tools/clippy/clippy_lints/src/methods/get_first.rs b/src/tools/clippy/clippy_lints/src/methods/get_first.rs
index cb17af608a3..945bbf53bcf 100644
--- a/src/tools/clippy/clippy_lints/src/methods/get_first.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/get_first.rs
@@ -19,7 +19,7 @@ pub(super) fn check<'tcx>(
     if_chain! {
         if let Some(method_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id);
         if let Some(impl_id) = cx.tcx.impl_of_method(method_id);
-        if cx.tcx.type_of(impl_id).is_slice();
+        if cx.tcx.type_of(impl_id).subst_identity().is_slice();
         if let Some(_) = is_slice_of_primitives(cx, recv);
         if let hir::ExprKind::Lit(Spanned { node: LitKind::Int(0, _), .. }) = arg.kind;
         then {
diff --git a/src/tools/clippy/clippy_lints/src/methods/implicit_clone.rs b/src/tools/clippy/clippy_lints/src/methods/implicit_clone.rs
index 06ecbce4e70..374eb29fc52 100644
--- a/src/tools/clippy/clippy_lints/src/methods/implicit_clone.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/implicit_clone.rs
@@ -53,7 +53,7 @@ pub fn is_clone_like(cx: &LateContext<'_>, method_name: &str, method_def_id: hir
         "to_vec" => cx
             .tcx
             .impl_of_method(method_def_id)
-            .filter(|&impl_did| cx.tcx.type_of(impl_did).is_slice() && cx.tcx.impl_trait_ref(impl_did).is_none())
+            .filter(|&impl_did| cx.tcx.type_of(impl_did).subst_identity().is_slice() && cx.tcx.impl_trait_ref(impl_did).is_none())
             .is_some(),
         _ => false,
     }
diff --git a/src/tools/clippy/clippy_lints/src/methods/manual_ok_or.rs b/src/tools/clippy/clippy_lints/src/methods/manual_ok_or.rs
index 5b758f1e654..b9a0ec77996 100644
--- a/src/tools/clippy/clippy_lints/src/methods/manual_ok_or.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/manual_ok_or.rs
@@ -21,7 +21,7 @@ pub(super) fn check<'tcx>(
     if_chain! {
         if let Some(method_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id);
         if let Some(impl_id) = cx.tcx.impl_of_method(method_id);
-        if is_type_diagnostic_item(cx, cx.tcx.type_of(impl_id), sym::Option);
+        if is_type_diagnostic_item(cx, cx.tcx.type_of(impl_id).subst_identity(), sym::Option);
         if let ExprKind::Call(err_path, [err_arg]) = or_expr.kind;
         if is_res_lang_ctor(cx, path_res(cx, err_path), ResultErr);
         if is_ok_wrapping(cx, map_expr);
diff --git a/src/tools/clippy/clippy_lints/src/methods/map_clone.rs b/src/tools/clippy/clippy_lints/src/methods/map_clone.rs
index 52cc1e0464b..2b26ef01410 100644
--- a/src/tools/clippy/clippy_lints/src/methods/map_clone.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/map_clone.rs
@@ -19,7 +19,7 @@ pub(super) fn check(cx: &LateContext<'_>, e: &hir::Expr<'_>, recv: &hir::Expr<'_
     if_chain! {
         if let Some(method_id) = cx.typeck_results().type_dependent_def_id(e.hir_id);
         if cx.tcx.impl_of_method(method_id)
-            .map_or(false, |id| is_type_diagnostic_item(cx, cx.tcx.type_of(id), sym::Option))
+            .map_or(false, |id| is_type_diagnostic_item(cx, cx.tcx.type_of(id).subst_identity(), sym::Option))
             || is_diag_trait_item(cx, method_id, sym::Iterator);
         if let hir::ExprKind::Closure(&hir::Closure{ body, .. }) = arg.kind;
         then {
diff --git a/src/tools/clippy/clippy_lints/src/methods/map_err_ignore.rs b/src/tools/clippy/clippy_lints/src/methods/map_err_ignore.rs
index b773b3e423f..a5beb291f32 100644
--- a/src/tools/clippy/clippy_lints/src/methods/map_err_ignore.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/map_err_ignore.rs
@@ -9,7 +9,7 @@ use super::MAP_ERR_IGNORE;
 pub(super) fn check(cx: &LateContext<'_>, e: &Expr<'_>, arg: &Expr<'_>) {
     if let Some(method_id) = cx.typeck_results().type_dependent_def_id(e.hir_id)
         && let Some(impl_id) = cx.tcx.impl_of_method(method_id)
-        && is_type_diagnostic_item(cx, cx.tcx.type_of(impl_id), sym::Result)
+        && is_type_diagnostic_item(cx, cx.tcx.type_of(impl_id).subst_identity(), sym::Result)
         && let ExprKind::Closure(&Closure {
             capture_clause: CaptureBy::Ref,
             body,
diff --git a/src/tools/clippy/clippy_lints/src/methods/mod.rs b/src/tools/clippy/clippy_lints/src/methods/mod.rs
index f1e8be7f2b8..6301b3ded20 100644
--- a/src/tools/clippy/clippy_lints/src/methods/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/mod.rs
@@ -3349,7 +3349,7 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
         let name = impl_item.ident.name.as_str();
         let parent = cx.tcx.hir().get_parent_item(impl_item.hir_id()).def_id;
         let item = cx.tcx.hir().expect_item(parent);
-        let self_ty = cx.tcx.type_of(item.owner_id);
+        let self_ty = cx.tcx.type_of(item.owner_id).subst_identity();
 
         let implements_trait = matches!(item.kind, hir::ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }));
         if let hir::ImplItemKind::Fn(ref sig, id) = impl_item.kind {
diff --git a/src/tools/clippy/clippy_lints/src/methods/mut_mutex_lock.rs b/src/tools/clippy/clippy_lints/src/methods/mut_mutex_lock.rs
index b9593b3687d..d0aa39d0627 100644
--- a/src/tools/clippy/clippy_lints/src/methods/mut_mutex_lock.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/mut_mutex_lock.rs
@@ -15,7 +15,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, ex: &'tcx Expr<'tcx>, recv: &'
         if let ty::Ref(_, _, Mutability::Mut) = cx.typeck_results().expr_ty(recv).kind();
         if let Some(method_id) = cx.typeck_results().type_dependent_def_id(ex.hir_id);
         if let Some(impl_id) = cx.tcx.impl_of_method(method_id);
-        if is_type_diagnostic_item(cx, cx.tcx.type_of(impl_id), sym::Mutex);
+        if is_type_diagnostic_item(cx, cx.tcx.type_of(impl_id).subst_identity(), sym::Mutex);
         then {
             span_lint_and_sugg(
                 cx,
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 82d3b830d4f..8ddbacc3d7a 100644
--- a/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs
@@ -173,7 +173,7 @@ fn is_contains_sig(cx: &LateContext<'_>, call_id: HirId, iter_expr: &Expr<'_>) -
         && let Some(iter_item) = cx.tcx
             .associated_items(iter_trait)
             .find_by_name_and_kind(cx.tcx, Ident::with_dummy_span(Symbol::intern("Item")), AssocKind::Type, iter_trait)
-        && let substs = cx.tcx.mk_substs([GenericArg::from(typeck.expr_ty_adjusted(iter_expr))].into_iter())
+        && let substs = cx.tcx.intern_substs(&[GenericArg::from(typeck.expr_ty_adjusted(iter_expr))])
         && let proj_ty = cx.tcx.mk_projection(iter_item.def_id, substs)
         && let Ok(item_ty) = cx.tcx.try_normalize_erasing_regions(cx.param_env, proj_ty)
     {
diff --git a/src/tools/clippy/clippy_lints/src/methods/open_options.rs b/src/tools/clippy/clippy_lints/src/methods/open_options.rs
index 597af853dc6..c6a27cdd6fa 100644
--- a/src/tools/clippy/clippy_lints/src/methods/open_options.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/open_options.rs
@@ -11,7 +11,7 @@ use super::NONSENSICAL_OPEN_OPTIONS;
 pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>, recv: &'tcx Expr<'_>) {
     if let Some(method_id) = cx.typeck_results().type_dependent_def_id(e.hir_id)
         && let Some(impl_id) = cx.tcx.impl_of_method(method_id)
-        && match_type(cx, cx.tcx.type_of(impl_id), &paths::OPEN_OPTIONS)
+        && match_type(cx, cx.tcx.type_of(impl_id).subst_identity(), &paths::OPEN_OPTIONS)
     {
         let mut options = Vec::new();
         get_open_options(cx, recv, &mut options);
diff --git a/src/tools/clippy/clippy_lints/src/methods/path_buf_push_overwrite.rs b/src/tools/clippy/clippy_lints/src/methods/path_buf_push_overwrite.rs
index 0cc28c0dcb3..e3f2de3cd46 100644
--- a/src/tools/clippy/clippy_lints/src/methods/path_buf_push_overwrite.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/path_buf_push_overwrite.rs
@@ -14,7 +14,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, arg: &'t
     if_chain! {
         if let Some(method_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id);
         if let Some(impl_id) = cx.tcx.impl_of_method(method_id);
-        if is_type_diagnostic_item(cx, cx.tcx.type_of(impl_id), sym::PathBuf);
+        if is_type_diagnostic_item(cx, cx.tcx.type_of(impl_id).subst_identity(), sym::PathBuf);
         if let ExprKind::Lit(ref lit) = arg.kind;
         if let LitKind::Str(ref path_lit, _) = lit.node;
         if let pushed_path = Path::new(path_lit.as_str());
diff --git a/src/tools/clippy/clippy_lints/src/methods/stable_sort_primitive.rs b/src/tools/clippy/clippy_lints/src/methods/stable_sort_primitive.rs
index 09c8ca4cbe4..b5fd0ad8ce5 100644
--- a/src/tools/clippy/clippy_lints/src/methods/stable_sort_primitive.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/stable_sort_primitive.rs
@@ -10,7 +10,7 @@ use super::STABLE_SORT_PRIMITIVE;
 pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>, recv: &'tcx Expr<'_>) {
     if let Some(method_id) = cx.typeck_results().type_dependent_def_id(e.hir_id)
         && let Some(impl_id) = cx.tcx.impl_of_method(method_id)
-        && cx.tcx.type_of(impl_id).is_slice()
+        && cx.tcx.type_of(impl_id).subst_identity().is_slice()
         && let Some(slice_type) = is_slice_of_primitives(cx, recv)
     {
         span_lint_and_then(
diff --git a/src/tools/clippy/clippy_lints/src/methods/suspicious_splitn.rs b/src/tools/clippy/clippy_lints/src/methods/suspicious_splitn.rs
index 219a9edd657..90ca66bd70c 100644
--- a/src/tools/clippy/clippy_lints/src/methods/suspicious_splitn.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/suspicious_splitn.rs
@@ -13,7 +13,7 @@ pub(super) fn check(cx: &LateContext<'_>, method_name: &str, expr: &Expr<'_>, se
         if let Some(call_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id);
         if let Some(impl_id) = cx.tcx.impl_of_method(call_id);
         if cx.tcx.impl_trait_ref(impl_id).is_none();
-        let self_ty = cx.tcx.type_of(impl_id);
+        let self_ty = cx.tcx.type_of(impl_id).subst_identity();
         if self_ty.is_slice() || self_ty.is_str();
         then {
             // Ignore empty slice and string literals when used with a literal count.
diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_sort_by.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_sort_by.rs
index ed5a75b0f3c..5201da52bbf 100644
--- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_sort_by.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_sort_by.rs
@@ -122,7 +122,7 @@ fn detect_lint(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, arg: &Exp
     if_chain! {
         if let Some(method_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id);
         if let Some(impl_id) = cx.tcx.impl_of_method(method_id);
-        if cx.tcx.type_of(impl_id).is_slice();
+        if cx.tcx.type_of(impl_id).subst_identity().is_slice();
         if let ExprKind::Closure(&Closure { body, .. }) = arg.kind;
         if let closure_body = cx.tcx.hir().body(body);
         if let &[
diff --git a/src/tools/clippy/clippy_lints/src/methods/utils.rs b/src/tools/clippy/clippy_lints/src/methods/utils.rs
index d50346c166a..c96d6922697 100644
--- a/src/tools/clippy/clippy_lints/src/methods/utils.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/utils.rs
@@ -143,7 +143,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for CloneOrCopyVisitor<'cx, 'tcx> {
                         if_chain! {
                             if args.iter().all(|arg| !self.is_binding(arg));
                             if let Some(method_def_id) = self.cx.typeck_results().type_dependent_def_id(parent.hir_id);
-                            let method_ty = self.cx.tcx.type_of(method_def_id);
+                            let method_ty = self.cx.tcx.type_of(method_def_id).subst_identity();
                             let self_ty = method_ty.fn_sig(self.cx.tcx).input(0).skip_binder();
                             if matches!(self_ty.kind(), ty::Ref(_, _, Mutability::Not));
                             then {
diff --git a/src/tools/clippy/clippy_lints/src/methods/vec_resize_to_zero.rs b/src/tools/clippy/clippy_lints/src/methods/vec_resize_to_zero.rs
index 02d8364cb29..b0cfc163fd0 100644
--- a/src/tools/clippy/clippy_lints/src/methods/vec_resize_to_zero.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/vec_resize_to_zero.rs
@@ -20,7 +20,7 @@ pub(super) fn check<'tcx>(
     if_chain! {
         if let Some(method_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id);
         if let Some(impl_id) = cx.tcx.impl_of_method(method_id);
-        if is_type_diagnostic_item(cx, cx.tcx.type_of(impl_id), sym::Vec);
+        if is_type_diagnostic_item(cx, cx.tcx.type_of(impl_id).subst_identity(), sym::Vec);
         if let ExprKind::Lit(Spanned { node: LitKind::Int(0, _), .. }) = count_arg.kind;
         if let ExprKind::Lit(Spanned { node: LitKind::Int(..), .. }) = default_arg.kind;
         then {
diff --git a/src/tools/clippy/clippy_lints/src/mut_reference.rs b/src/tools/clippy/clippy_lints/src/mut_reference.rs
index 4547ed7eafc..e91aac41bc4 100644
--- a/src/tools/clippy/clippy_lints/src/mut_reference.rs
+++ b/src/tools/clippy/clippy_lints/src/mut_reference.rs
@@ -52,7 +52,7 @@ impl<'tcx> LateLintPass<'tcx> for UnnecessaryMutPassed {
             ExprKind::MethodCall(path, receiver, arguments, _) => {
                 let def_id = cx.typeck_results().type_dependent_def_id(e.hir_id).unwrap();
                 let substs = cx.typeck_results().node_substs(e.hir_id);
-                let method_type = cx.tcx.bound_type_of(def_id).subst(cx.tcx, substs);
+                let method_type = cx.tcx.type_of(def_id).subst(cx.tcx, substs);
                 check_arguments(
                     cx,
                     std::iter::once(receiver).chain(arguments.iter()).collect(),
diff --git a/src/tools/clippy/clippy_lints/src/new_without_default.rs b/src/tools/clippy/clippy_lints/src/new_without_default.rs
index faf9ec61ec5..653b1a8a05f 100644
--- a/src/tools/clippy/clippy_lints/src/new_without_default.rs
+++ b/src/tools/clippy/clippy_lints/src/new_without_default.rs
@@ -98,14 +98,15 @@ impl<'tcx> LateLintPass<'tcx> for NewWithoutDefault {
                             if name == sym::new;
                             if cx.effective_visibilities.is_reachable(impl_item.owner_id.def_id);
                             let self_def_id = cx.tcx.hir().get_parent_item(id.into());
-                            let self_ty = cx.tcx.type_of(self_def_id);
+                            let self_ty = cx.tcx.type_of(self_def_id).subst_identity();
                             if self_ty == return_ty(cx, id);
                             if let Some(default_trait_id) = cx.tcx.get_diagnostic_item(sym::Default);
                             then {
                                 if self.impling_types.is_none() {
                                     let mut impls = HirIdSet::default();
                                     cx.tcx.for_each_impl(default_trait_id, |d| {
-                                        if let Some(ty_def) = cx.tcx.type_of(d).ty_adt_def() {
+                                        let ty = cx.tcx.type_of(d).subst_identity();
+                                        if let Some(ty_def) = ty.ty_adt_def() {
                                             if let Some(local_def_id) = ty_def.did().as_local() {
                                                 impls.insert(cx.tcx.hir().local_def_id_to_hir_id(local_def_id));
                                             }
@@ -118,7 +119,8 @@ impl<'tcx> LateLintPass<'tcx> for NewWithoutDefault {
                                 // generics
                                 if_chain! {
                                     if let Some(ref impling_types) = self.impling_types;
-                                    if let Some(self_def) = cx.tcx.type_of(self_def_id).ty_adt_def();
+                                    let self_def = cx.tcx.type_of(self_def_id).subst_identity();
+                                    if let Some(self_def) = self_def.ty_adt_def();
                                     if let Some(self_local_did) = self_def.did().as_local();
                                     let self_id = cx.tcx.hir().local_def_id_to_hir_id(self_local_did);
                                     if impling_types.contains(&self_id);
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 07fd321d69f..0bedab05eec 100644
--- a/src/tools/clippy/clippy_lints/src/non_copy_const.rs
+++ b/src/tools/clippy/clippy_lints/src/non_copy_const.rs
@@ -313,7 +313,7 @@ impl<'tcx> LateLintPass<'tcx> for NonCopyConst {
                                 // and, in that case, the definition is *not* generic.
                                 cx.tcx.normalize_erasing_regions(
                                     cx.tcx.param_env(of_trait_def_id),
-                                    cx.tcx.type_of(of_assoc_item),
+                                    cx.tcx.type_of(of_assoc_item).subst_identity(),
                                 ),
                             ))
                             .is_err();
diff --git a/src/tools/clippy/clippy_lints/src/ptr.rs b/src/tools/clippy/clippy_lints/src/ptr.rs
index d88409c356e..fc550936165 100644
--- a/src/tools/clippy/clippy_lints/src/ptr.rs
+++ b/src/tools/clippy/clippy_lints/src/ptr.rs
@@ -505,13 +505,13 @@ fn check_mut_from_ref<'tcx>(cx: &LateContext<'tcx>, sig: &FnSig<'_>, body: Optio
     if let FnRetTy::Return(ty) = sig.decl.output
         && let Some((out, Mutability::Mut, _)) = get_ref_lm(ty)
     {
-        let out_region = cx.tcx.named_region(out.hir_id);
+        let out_region = cx.tcx.named_bound_var(out.hir_id);
         let args: Option<Vec<_>> = sig
             .decl
             .inputs
             .iter()
             .filter_map(get_ref_lm)
-            .filter(|&(lt, _, _)| cx.tcx.named_region(lt.hir_id) == out_region)
+            .filter(|&(lt, _, _)| cx.tcx.named_bound_var(lt.hir_id) == out_region)
             .map(|(_, mutability, span)| (mutability == Mutability::Not).then_some(span))
             .collect();
         if let Some(args) = args
diff --git a/src/tools/clippy/clippy_lints/src/redundant_slicing.rs b/src/tools/clippy/clippy_lints/src/redundant_slicing.rs
index 245a02ea26e..398329e455b 100644
--- a/src/tools/clippy/clippy_lints/src/redundant_slicing.rs
+++ b/src/tools/clippy/clippy_lints/src/redundant_slicing.rs
@@ -11,8 +11,6 @@ use rustc_middle::ty::adjustment::{Adjust, AutoBorrow, AutoBorrowMutability};
 use rustc_middle::ty::subst::GenericArg;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 
-use std::iter;
-
 declare_clippy_lint! {
     /// ### What it does
     /// Checks for redundant slicing expressions which use the full range, and
@@ -136,7 +134,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.tcx.mk_projection(target_id, cx.tcx.mk_substs(iter::once(GenericArg::from(indexed_ty)))),
+                        cx.tcx.mk_projection(target_id, cx.tcx.intern_substs(&[GenericArg::from(indexed_ty)])),
                     ) {
                         if deref_ty == expr_ty {
                             let snip = snippet_with_context(cx, indexed.span, ctxt, "..", &mut app).0;
diff --git a/src/tools/clippy/clippy_lints/src/self_named_constructors.rs b/src/tools/clippy/clippy_lints/src/self_named_constructors.rs
index 3ce030cd721..beca203c868 100644
--- a/src/tools/clippy/clippy_lints/src/self_named_constructors.rs
+++ b/src/tools/clippy/clippy_lints/src/self_named_constructors.rs
@@ -53,7 +53,7 @@ impl<'tcx> LateLintPass<'tcx> for SelfNamedConstructors {
 
         let parent = cx.tcx.hir().get_parent_item(impl_item.hir_id()).def_id;
         let item = cx.tcx.hir().expect_item(parent);
-        let self_ty = cx.tcx.type_of(item.owner_id);
+        let self_ty = cx.tcx.type_of(item.owner_id).subst_identity();
         let ret_ty = return_ty(cx, impl_item.owner_id);
 
         // Do not check trait impls
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 af0242348ac..5e24213d07f 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
@@ -273,7 +273,7 @@ fn reduce_ty<'tcx>(cx: &LateContext<'tcx>, mut ty: Ty<'tcx>) -> ReducedTy<'tcx>
                     .non_enum_variant()
                     .fields
                     .iter()
-                    .map(|f| cx.tcx.bound_type_of(f.did).subst(cx.tcx, substs));
+                    .map(|f| cx.tcx.type_of(f.did).subst(cx.tcx, substs));
                 let Some(sized_ty) = iter.find(|&ty| !is_zero_sized_ty(cx, ty)) else {
                     return ReducedTy::TypeErasure { raw_ptr_only: false };
                 };
diff --git a/src/tools/clippy/clippy_lints/src/use_self.rs b/src/tools/clippy/clippy_lints/src/use_self.rs
index 3cd35838961..e7c54000684 100644
--- a/src/tools/clippy/clippy_lints/src/use_self.rs
+++ b/src/tools/clippy/clippy_lints/src/use_self.rs
@@ -218,7 +218,7 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf {
             } else {
                 hir_ty_to_ty(cx.tcx, hir_ty)
             };
-            if same_type_and_consts(ty, cx.tcx.type_of(impl_id));
+            if same_type_and_consts(ty, cx.tcx.type_of(impl_id).subst_identity());
             then {
                 span_lint(cx, hir_ty.span);
             }
@@ -230,7 +230,7 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf {
             if !expr.span.from_expansion();
             if self.msrv.meets(msrvs::TYPE_ALIAS_ENUM_VARIANTS);
             if let Some(&StackItem::Check { impl_id, .. }) = self.stack.last();
-            if cx.typeck_results().expr_ty(expr) == cx.tcx.type_of(impl_id);
+            if cx.typeck_results().expr_ty(expr) == cx.tcx.type_of(impl_id).subst_identity();
             then {} else { return; }
         }
         match expr.kind {
@@ -254,7 +254,7 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf {
             if let PatKind::Path(QPath::Resolved(_, path))
                  | PatKind::TupleStruct(QPath::Resolved(_, path), _, _)
                  | PatKind::Struct(QPath::Resolved(_, path), _, _) = pat.kind;
-            if cx.typeck_results().pat_ty(pat) == cx.tcx.type_of(impl_id);
+            if cx.typeck_results().pat_ty(pat) == cx.tcx.type_of(impl_id).subst_identity();
             then {
                 check_path(cx, path);
             }
diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/interning_defined_symbol.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/interning_defined_symbol.rs
index 4b33d492a0e..688a8b865f3 100644
--- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/interning_defined_symbol.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/interning_defined_symbol.rs
@@ -78,7 +78,7 @@ impl<'tcx> LateLintPass<'tcx> for InterningDefinedSymbol {
                 for item in cx.tcx.module_children(def_id).iter() {
                     if_chain! {
                         if let Res::Def(DefKind::Const, item_def_id) = item.res;
-                        let ty = cx.tcx.type_of(item_def_id);
+                        let ty = cx.tcx.type_of(item_def_id).subst_identity();
                         if match_type(cx, ty, &paths::SYMBOL);
                         if let Ok(ConstValue::Scalar(value)) = cx.tcx.const_eval_poly(item_def_id);
                         if let Ok(value) = value.to_u32();
diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/msrv_attr_impl.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/msrv_attr_impl.rs
index 9876a8a765c..09f0f0d0adb 100644
--- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/msrv_attr_impl.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/msrv_attr_impl.rs
@@ -39,6 +39,7 @@ impl LateLintPass<'_> for MsrvAttrImpl {
             if self_ty_def.all_fields().any(|f| {
                 cx.tcx
                     .type_of(f.did)
+                    .subst_identity()
                     .walk()
                     .filter(|t| matches!(t.unpack(), GenericArgKind::Type(_)))
                     .any(|t| match_type(cx, t.expect_ty(), &paths::MSRV))
diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs
index 7144363637a..ee5e42bae0f 100644
--- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs
@@ -229,11 +229,11 @@ fn path_to_matched_type(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> Option<Ve
             Res::Def(DefKind::Static(_), def_id) => read_mir_alloc_def_path(
                 cx,
                 cx.tcx.eval_static_initializer(def_id).ok()?.inner(),
-                cx.tcx.type_of(def_id),
+                cx.tcx.type_of(def_id).subst_identity(),
             ),
             Res::Def(DefKind::Const, def_id) => match cx.tcx.const_eval_poly(def_id).ok()? {
                 ConstValue::ByRef { alloc, offset } if offset.bytes() == 0 => {
-                    read_mir_alloc_def_path(cx, alloc.inner(), cx.tcx.type_of(def_id))
+                    read_mir_alloc_def_path(cx, alloc.inner(), cx.tcx.type_of(def_id).subst_identity())
                 },
                 _ => None,
             },
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 5c89dd3e49f..6ff7728374f 100644
--- a/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs
+++ b/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs
@@ -50,7 +50,7 @@ fn fn_eagerness(cx: &LateContext<'_>, fn_id: DefId, name: Symbol, have_one_arg:
     let name = name.as_str();
 
     let ty = match cx.tcx.impl_of_method(fn_id) {
-        Some(id) => cx.tcx.type_of(id),
+        Some(id) => cx.tcx.type_of(id).subst_identity(),
         None => return Lazy,
     };
 
@@ -71,7 +71,7 @@ fn fn_eagerness(cx: &LateContext<'_>, fn_id: DefId, name: Symbol, have_one_arg:
             .variants()
             .iter()
             .flat_map(|v| v.fields.iter())
-            .any(|x| matches!(cx.tcx.type_of(x.did).peel_refs().kind(), ty::Param(_)))
+            .any(|x| matches!(cx.tcx.type_of(x.did).subst_identity().peel_refs().kind(), ty::Param(_)))
             && all_predicates_of(cx.tcx, fn_id).all(|(pred, _)| match pred.kind().skip_binder() {
                 PredicateKind::Clause(ty::Clause::Trait(pred)) => cx.tcx.trait_def(pred.trait_ref.def_id).is_marker,
                 _ => true,
diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs
index 3b8713e2b10..b2edd1bbfef 100644
--- a/src/tools/clippy/clippy_utils/src/lib.rs
+++ b/src/tools/clippy/clippy_utils/src/lib.rs
@@ -317,7 +317,7 @@ pub fn match_trait_method(cx: &LateContext<'_>, expr: &Expr<'_>, path: &[&str])
 /// Checks if a method is defined in an impl of a diagnostic item
 pub fn is_diag_item_method(cx: &LateContext<'_>, def_id: DefId, diag_item: Symbol) -> bool {
     if let Some(impl_did) = cx.tcx.impl_of_method(def_id) {
-        if let Some(adt) = cx.tcx.type_of(impl_did).ty_adt_def() {
+        if let Some(adt) = cx.tcx.type_of(impl_did).subst_identity().ty_adt_def() {
             return cx.tcx.is_diagnostic_item(diag_item, adt.did());
         }
     }
@@ -812,7 +812,7 @@ fn is_default_equivalent_ctor(cx: &LateContext<'_>, def_id: DefId, path: &QPath<
     if let QPath::TypeRelative(_, method) = path {
         if method.ident.name == sym::new {
             if let Some(impl_did) = cx.tcx.impl_of_method(def_id) {
-                if let Some(adt) = cx.tcx.type_of(impl_did).ty_adt_def() {
+                if let Some(adt) = cx.tcx.type_of(impl_did).subst_identity().ty_adt_def() {
                     return std_types_symbols.iter().any(|&symbol| {
                         cx.tcx.is_diagnostic_item(symbol, adt.did()) || Some(adt.did()) == cx.tcx.lang_items().string()
                     });
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 26b1d019749..1a35fe05067 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
@@ -30,7 +30,8 @@ pub fn is_min_const_fn<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, msrv: &Msrv)
                     ty::Clause::RegionOutlives(_)
                     | ty::Clause::TypeOutlives(_)
                     | ty::Clause::Projection(_)
-                    | ty::Clause::Trait(..),
+                    | ty::Clause::Trait(..)
+                    | ty::Clause::ConstArgHasType(..),
                 )
                 | ty::PredicateKind::WellFormed(_)
                 | ty::PredicateKind::ConstEvaluatable(..)
diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs
index d6af7a948a5..2ed301fcc22 100644
--- a/src/tools/clippy/clippy_utils/src/ty.rs
+++ b/src/tools/clippy/clippy_utils/src/ty.rs
@@ -780,7 +780,7 @@ impl core::ops::Add<u32> for EnumValue {
 #[expect(clippy::cast_possible_truncation, clippy::cast_possible_wrap)]
 pub fn read_explicit_enum_value(tcx: TyCtxt<'_>, id: DefId) -> Option<EnumValue> {
     if let Ok(ConstValue::Scalar(Scalar::Int(value))) = tcx.const_eval_poly(id) {
-        match tcx.type_of(id).kind() {
+        match tcx.type_of(id).subst_identity().kind() {
             ty::Int(_) => Some(EnumValue::Signed(match value.size().bytes() {
                 1 => i128::from(value.assert_bits(Size::from_bytes(1)) as u8 as i8),
                 2 => i128::from(value.assert_bits(Size::from_bytes(2)) as u16 as i16),
@@ -903,7 +903,7 @@ pub fn variant_of_res<'tcx>(cx: &LateContext<'tcx>, res: Res) -> Option<&'tcx Va
             let var_id = cx.tcx.parent(id);
             Some(cx.tcx.adt_def(cx.tcx.parent(var_id)).variant_with_id(var_id))
         },
-        Res::SelfCtor(id) => Some(cx.tcx.type_of(id).ty_adt_def().unwrap().non_enum_variant()),
+        Res::SelfCtor(id) => Some(cx.tcx.type_of(id).subst_identity().ty_adt_def().unwrap().non_enum_variant()),
         _ => None,
     }
 }
diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs
index e11ebca6ea9..d9b39927ca4 100644
--- a/src/tools/compiletest/src/header.rs
+++ b/src/tools/compiletest/src/header.rs
@@ -935,6 +935,7 @@ pub fn make_test_description<R: Read>(
     let has_asan = util::ASAN_SUPPORTED_TARGETS.contains(&&*config.target);
     let has_cfi = util::CFI_SUPPORTED_TARGETS.contains(&&*config.target);
     let has_kcfi = util::KCFI_SUPPORTED_TARGETS.contains(&&*config.target);
+    let has_kasan = util::KASAN_SUPPORTED_TARGETS.contains(&&*config.target);
     let has_lsan = util::LSAN_SUPPORTED_TARGETS.contains(&&*config.target);
     let has_msan = util::MSAN_SUPPORTED_TARGETS.contains(&&*config.target);
     let has_tsan = util::TSAN_SUPPORTED_TARGETS.contains(&&*config.target);
@@ -1010,6 +1011,7 @@ pub fn make_test_description<R: Read>(
         reason!(!has_asan && config.parse_name_directive(ln, "needs-sanitizer-address"));
         reason!(!has_cfi && config.parse_name_directive(ln, "needs-sanitizer-cfi"));
         reason!(!has_kcfi && config.parse_name_directive(ln, "needs-sanitizer-kcfi"));
+        reason!(!has_kasan && config.parse_name_directive(ln, "needs-sanitizer-kasan"));
         reason!(!has_lsan && config.parse_name_directive(ln, "needs-sanitizer-leak"));
         reason!(!has_msan && config.parse_name_directive(ln, "needs-sanitizer-memory"));
         reason!(!has_tsan && config.parse_name_directive(ln, "needs-sanitizer-thread"));
diff --git a/src/tools/compiletest/src/util.rs b/src/tools/compiletest/src/util.rs
index 67f49bb6397..5f6a27e5366 100644
--- a/src/tools/compiletest/src/util.rs
+++ b/src/tools/compiletest/src/util.rs
@@ -11,6 +11,8 @@ mod tests;
 
 pub const ASAN_SUPPORTED_TARGETS: &[&str] = &[
     "aarch64-apple-darwin",
+    "aarch64-apple-ios",
+    "aarch64-apple-ios-sim",
     "aarch64-unknown-fuchsia",
     "aarch64-linux-android",
     "aarch64-unknown-linux-gnu",
@@ -19,6 +21,7 @@ pub const ASAN_SUPPORTED_TARGETS: &[&str] = &[
     "i686-linux-android",
     "i686-unknown-linux-gnu",
     "x86_64-apple-darwin",
+    "x86_64-apple-ios",
     "x86_64-unknown-fuchsia",
     "x86_64-linux-android",
     "x86_64-unknown-freebsd",
@@ -45,6 +48,13 @@ pub const CFI_SUPPORTED_TARGETS: &[&str] = &[
 
 pub const KCFI_SUPPORTED_TARGETS: &[&str] = &["aarch64-linux-none", "x86_64-linux-none"];
 
+pub const KASAN_SUPPORTED_TARGETS: &[&str] = &[
+    "aarch64-unknown-none",
+    "riscv64gc-unknown-none-elf",
+    "riscv64imac-unknown-none-elf",
+    "x86_64-unknown-none",
+];
+
 pub const LSAN_SUPPORTED_TARGETS: &[&str] = &[
     // FIXME: currently broken, see #88132
     // "aarch64-apple-darwin",
@@ -63,8 +73,11 @@ pub const MSAN_SUPPORTED_TARGETS: &[&str] = &[
 
 pub const TSAN_SUPPORTED_TARGETS: &[&str] = &[
     "aarch64-apple-darwin",
+    "aarch64-apple-ios",
+    "aarch64-apple-ios-sim",
     "aarch64-unknown-linux-gnu",
     "x86_64-apple-darwin",
+    "x86_64-apple-ios",
     "x86_64-unknown-freebsd",
     "x86_64-unknown-linux-gnu",
     "s390x-unknown-linux-gnu",
diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version
index 8afb8e98235..3930fa0e940 100644
--- a/src/tools/miri/rust-version
+++ b/src/tools/miri/rust-version
@@ -1 +1 @@
-639377ed737b25830ec44dc6acf93467c980316a
+3eb5c4581a386b13c414e8c8bd73846ef37236d1
diff --git a/src/tools/miri/src/eval.rs b/src/tools/miri/src/eval.rs
index d61e17cbf9a..ebb71b57ae3 100644
--- a/src/tools/miri/src/eval.rs
+++ b/src/tools/miri/src/eval.rs
@@ -363,7 +363,7 @@ pub fn create_ecx<'mir, 'tcx: 'mir>(
                 tcx,
                 ty::ParamEnv::reveal_all(),
                 start_id,
-                tcx.mk_substs(::std::iter::once(ty::subst::GenericArg::from(main_ret_ty))),
+                tcx.intern_substs(&[ty::subst::GenericArg::from(main_ret_ty)]),
             )
             .unwrap()
             .unwrap();
diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs
index 269b441c504..f9a6ef34c2f 100644
--- a/src/tools/miri/src/machine.rs
+++ b/src/tools/miri/src/machine.rs
@@ -907,8 +907,8 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
                 panic!("extern_statics cannot contain wildcards")
             };
             let (shim_size, shim_align, _kind) = ecx.get_alloc_info(alloc_id);
-            let extern_decl_layout =
-                ecx.tcx.layout_of(ty::ParamEnv::empty().and(ecx.tcx.type_of(def_id))).unwrap();
+            let def_ty = ecx.tcx.type_of(def_id).subst_identity();
+            let extern_decl_layout = ecx.tcx.layout_of(ty::ParamEnv::empty().and(def_ty)).unwrap();
             if extern_decl_layout.size != shim_size || extern_decl_layout.align.abi != shim_align {
                 throw_unsup_format!(
                     "`extern` static `{name}` from crate `{krate}` has been declared \
diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs
index ef3abb9514f..409f7563184 100644
--- a/src/tools/tidy/src/ui_tests.rs
+++ b/src/tools/tidy/src/ui_tests.rs
@@ -10,7 +10,7 @@ use std::path::Path;
 const ENTRY_LIMIT: usize = 1000;
 // FIXME: The following limits should be reduced eventually.
 const ROOT_ENTRY_LIMIT: usize = 940;
-const ISSUES_ENTRY_LIMIT: usize = 2001;
+const ISSUES_ENTRY_LIMIT: usize = 1978;
 
 fn check_entries(path: &Path, bad: &mut bool) {
     for dir in Walk::new(&path.join("ui")) {
diff --git a/tests/codegen/sanitizer-kasan-emits-instrumentation.rs b/tests/codegen/sanitizer-kasan-emits-instrumentation.rs
new file mode 100644
index 00000000000..d6e3f2719df
--- /dev/null
+++ b/tests/codegen/sanitizer-kasan-emits-instrumentation.rs
@@ -0,0 +1,47 @@
+// Verifies that `-Zsanitizer=kernel-address` emits sanitizer instrumentation.
+
+// compile-flags: -Zsanitizer=kernel-address
+// revisions: aarch64 riscv64imac riscv64gc x86_64
+//[aarch64] compile-flags: --target aarch64-unknown-none
+//[aarch64] needs-llvm-components: aarch64
+//[riscv64imac] compile-flags: --target riscv64imac-unknown-none-elf
+//[riscv64imac] needs-llvm-components: riscv
+//[riscv64imac] min-llvm-version: 16
+//[riscv64gc] compile-flags: --target riscv64gc-unknown-none-elf
+//[riscv64gc] needs-llvm-components: riscv
+//[riscv64gc] min-llvm-version: 16
+//[x86_64] compile-flags: --target x86_64-unknown-none
+//[x86_64] needs-llvm-components: x86
+
+#![crate_type = "rlib"]
+#![feature(no_core, no_sanitize, lang_items)]
+#![no_core]
+
+#[lang = "sized"]
+trait Sized {}
+
+#[lang = "copy"]
+trait Copy {}
+
+impl Copy for u8 {}
+
+// CHECK-LABEL: ; sanitizer_kasan_emits_instrumentation::unsanitized
+// CHECK-NEXT:  ; Function Attrs:
+// CHECK-NOT:   sanitize_address
+// CHECK:       start:
+// CHECK-NOT:   call void @__asan_report_load
+// CHECK:       }
+#[no_sanitize(address)]
+pub fn unsanitized(b: &mut u8) -> u8 {
+    *b
+}
+
+// CHECK-LABEL: ; sanitizer_kasan_emits_instrumentation::sanitized
+// CHECK-NEXT:  ; Function Attrs:
+// CHECK:       sanitize_address
+// CHECK:       start:
+// CHECK:       call void @__asan_report_load
+// CHECK:       }
+pub fn sanitized(b: &mut u8) -> u8 {
+    *b
+}
diff --git a/tests/mir-opt/funky_arms.float_to_exponential_common.ConstProp.diff b/tests/mir-opt/funky_arms.float_to_exponential_common.ConstProp.diff
index 5ebaacd4ba9..1f5c533815d 100644
--- a/tests/mir-opt/funky_arms.float_to_exponential_common.ConstProp.diff
+++ b/tests/mir-opt/funky_arms.float_to_exponential_common.ConstProp.diff
@@ -86,8 +86,6 @@
   
       bb6: {
           _10 = ((_7 as Some).0: usize);   // scope 3 at $DIR/funky_arms.rs:+13:17: +13:26
-          StorageLive(_11);                // scope 3 at $DIR/funky_arms.rs:+15:43: +15:46
-          _11 = &mut (*_1);                // scope 3 at $DIR/funky_arms.rs:+15:43: +15:46
           StorageLive(_13);                // scope 3 at $DIR/funky_arms.rs:+15:53: +15:57
           _13 = _6;                        // scope 3 at $DIR/funky_arms.rs:+15:53: +15:57
           StorageLive(_14);                // scope 3 at $DIR/funky_arms.rs:+15:59: +15:79
@@ -95,7 +93,7 @@
           _15 = _10 as u32 (IntToInt);     // scope 3 at $DIR/funky_arms.rs:+15:59: +15:75
           _14 = Add(move _15, const 1_u32); // scope 3 at $DIR/funky_arms.rs:+15:59: +15:79
           StorageDead(_15);                // scope 3 at $DIR/funky_arms.rs:+15:78: +15:79
-          _0 = float_to_exponential_common_exact::<T>(move _11, _2, move _13, move _14, _3) -> bb7; // scope 3 at $DIR/funky_arms.rs:+15:9: +15:87
+          _0 = float_to_exponential_common_exact::<T>(_1, _2, move _13, move _14, _3) -> bb7; // scope 3 at $DIR/funky_arms.rs:+15:9: +15:87
                                            // mir::Constant
                                            // + span: $DIR/funky_arms.rs:26:9: 26:42
                                            // + literal: Const { ty: for<'a, 'b, 'c> fn(&'a mut Formatter<'b>, &'c T, Sign, u32, bool) -> Result<(), std::fmt::Error> {float_to_exponential_common_exact::<T>}, val: Value(<ZST>) }
@@ -104,16 +102,13 @@
       bb7: {
           StorageDead(_14);                // scope 3 at $DIR/funky_arms.rs:+15:86: +15:87
           StorageDead(_13);                // scope 3 at $DIR/funky_arms.rs:+15:86: +15:87
-          StorageDead(_11);                // scope 3 at $DIR/funky_arms.rs:+15:86: +15:87
           goto -> bb10;                    // scope 2 at $DIR/funky_arms.rs:+13:5: +18:6
       }
   
       bb8: {
-          StorageLive(_18);                // scope 2 at $DIR/funky_arms.rs:+17:46: +17:49
-          _18 = &mut (*_1);                // scope 2 at $DIR/funky_arms.rs:+17:46: +17:49
           StorageLive(_20);                // scope 2 at $DIR/funky_arms.rs:+17:56: +17:60
           _20 = _6;                        // scope 2 at $DIR/funky_arms.rs:+17:56: +17:60
-          _0 = float_to_exponential_common_shortest::<T>(move _18, _2, move _20, _3) -> bb9; // scope 2 at $DIR/funky_arms.rs:+17:9: +17:68
+          _0 = float_to_exponential_common_shortest::<T>(_1, _2, move _20, _3) -> bb9; // scope 2 at $DIR/funky_arms.rs:+17:9: +17:68
                                            // mir::Constant
                                            // + span: $DIR/funky_arms.rs:28:9: 28:45
                                            // + literal: Const { ty: for<'a, 'b, 'c> fn(&'a mut Formatter<'b>, &'c T, Sign, bool) -> Result<(), std::fmt::Error> {float_to_exponential_common_shortest::<T>}, val: Value(<ZST>) }
@@ -121,7 +116,6 @@
   
       bb9: {
           StorageDead(_20);                // scope 2 at $DIR/funky_arms.rs:+17:67: +17:68
-          StorageDead(_18);                // scope 2 at $DIR/funky_arms.rs:+17:67: +17:68
           goto -> bb10;                    // scope 2 at $DIR/funky_arms.rs:+13:5: +18:6
       }
   
diff --git a/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.a.Inline.after.mir b/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.a.Inline.after.mir
index dc0c3235043..6441a9668de 100644
--- a/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.a.Inline.after.mir
+++ b/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.a.Inline.after.mir
@@ -8,7 +8,6 @@ fn a(_1: &mut [T]) -> &mut [T] {
     let mut _4: &mut [T];                // in scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15
     scope 1 (inlined <[T] as AsMut<[T]>>::as_mut) { // at $DIR/issue_58867_inline_as_ref_as_mut.rs:3:7: 3:15
         debug self => _4;                // in scope 1 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
-        let mut _5: &mut [T];            // in scope 1 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
     }
 
     bb0: {
@@ -16,10 +15,7 @@ fn a(_1: &mut [T]) -> &mut [T] {
         StorageLive(_3);                 // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15
         StorageLive(_4);                 // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15
         _4 = &mut (*_1);                 // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15
-        StorageLive(_5);                 // scope 1 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
-        _5 = &mut (*_4);                 // scope 1 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
-        _3 = &mut (*_5);                 // scope 1 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
-        StorageDead(_5);                 // scope 1 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
+        _3 = _4;                         // scope 1 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
         _2 = &mut (*_3);                 // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15
         StorageDead(_4);                 // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:14: +1:15
         _0 = &mut (*_2);                 // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15
diff --git a/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.b.Inline.after.mir b/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.b.Inline.after.mir
index b6aff30149f..21570a88a6b 100644
--- a/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.b.Inline.after.mir
+++ b/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.b.Inline.after.mir
@@ -8,10 +8,8 @@ fn b(_1: &mut Box<T>) -> &mut T {
     let mut _4: &mut std::boxed::Box<T>; // in scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15
     scope 1 (inlined <Box<T> as AsMut<T>>::as_mut) { // at $DIR/issue_58867_inline_as_ref_as_mut.rs:8:7: 8:15
         debug self => _4;                // in scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
-        let mut _5: &mut T;              // in scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
-        let mut _6: &mut T;              // in scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
-        let mut _7: std::boxed::Box<T>;  // in scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
-        let mut _8: *const T;            // in scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
+        let mut _5: std::boxed::Box<T>;  // in scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
+        let mut _6: *const T;            // in scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
     }
 
     bb0: {
@@ -19,15 +17,9 @@ fn b(_1: &mut Box<T>) -> &mut T {
         StorageLive(_3);                 // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15
         StorageLive(_4);                 // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15
         _4 = &mut (*_1);                 // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15
-        StorageLive(_5);                 // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
-        StorageLive(_6);                 // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
-        _7 = deref_copy (*_4);           // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
-        _8 = (((_7.0: std::ptr::Unique<T>).0: std::ptr::NonNull<T>).0: *const T); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
-        _6 = &mut (*_8);                 // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
-        _5 = &mut (*_6);                 // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
-        _3 = &mut (*_5);                 // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
-        StorageDead(_6);                 // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
-        StorageDead(_5);                 // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
+        _5 = deref_copy (*_4);           // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
+        _6 = (((_5.0: std::ptr::Unique<T>).0: std::ptr::NonNull<T>).0: *const T); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
+        _3 = &mut (*_6);                 // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
         _2 = &mut (*_3);                 // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15
         StorageDead(_4);                 // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:14: +1:15
         _0 = &mut (*_2);                 // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15
diff --git a/tests/rustdoc/reexport-attr-merge.rs b/tests/rustdoc/reexport-attr-merge.rs
new file mode 100644
index 00000000000..f6c23a1365f
--- /dev/null
+++ b/tests/rustdoc/reexport-attr-merge.rs
@@ -0,0 +1,33 @@
+// Regression test for <https://github.com/rust-lang/rust/issues/59368>.
+// The goal is to ensure that `doc(hidden)`, `doc(inline)` and `doc(no_inline)`
+// are not copied from an item when inlined.
+
+#![crate_name = "foo"]
+#![feature(doc_cfg)]
+
+// @has 'foo/index.html'
+
+#[doc(hidden, cfg(feature = "foo"))]
+pub struct Foo;
+
+#[doc(hidden, no_inline, cfg(feature = "bar"))]
+pub use Foo as Foo1;
+
+#[doc(hidden, inline)]
+pub use Foo1 as Foo2;
+
+// First we ensure that only the reexport `Bar2` and the inlined struct `Bar`
+// are inlined.
+// @count - '//a[@class="struct"]' 2
+// Then we check that both `cfg` are displayed.
+// @has - '//*[@class="stab portability"]' 'foo'
+// @has - '//*[@class="stab portability"]' 'bar'
+// And finally we check that the only element displayed is `Bar`.
+// @has - '//a[@class="struct"]' 'Bar'
+#[doc(inline)]
+pub use Foo2 as Bar;
+
+// This one should appear but `Bar2` won't be linked because there is no
+// `#[doc(inline)]`.
+// @has - '//*[@id="reexport.Bar2"]' 'pub use Foo2 as Bar2;'
+pub use Foo2 as Bar2;
diff --git a/tests/ui/alloc-error/alloc-error-handler-bad-signature-3.stderr b/tests/ui/alloc-error/alloc-error-handler-bad-signature-3.stderr
index 77ea8ef0520..d1b9d7a40b4 100644
--- a/tests/ui/alloc-error/alloc-error-handler-bad-signature-3.stderr
+++ b/tests/ui/alloc-error/alloc-error-handler-bad-signature-3.stderr
@@ -7,7 +7,10 @@ LL |   fn oom() -> ! {
    |  _-^^^^^^^^^^^^
 LL | |     loop {}
 LL | | }
-   | |_- argument of type `core::alloc::Layout` unexpected
+   | | -
+   | | |
+   | |_unexpected argument of type `core::alloc::Layout`
+   |   help: remove the extra argument
    |
 note: function defined here
   --> $DIR/alloc-error-handler-bad-signature-3.rs:10:4
@@ -15,10 +18,6 @@ note: function defined here
 LL | fn oom() -> ! {
    |    ^^^
    = note: this error originates in the attribute macro `alloc_error_handler` (in Nightly builds, run with -Z macro-backtrace for more info)
-help: remove the extra argument
-   |
-LL | fn oom() -> !() {
-   |              ++
 
 error: aborting due to previous error
 
diff --git a/tests/ui/argument-suggestions/basic.stderr b/tests/ui/argument-suggestions/basic.stderr
index 062b3768858..c74186285f9 100644
--- a/tests/ui/argument-suggestions/basic.stderr
+++ b/tests/ui/argument-suggestions/basic.stderr
@@ -16,17 +16,16 @@ error[E0061]: this function takes 0 arguments but 1 argument was supplied
   --> $DIR/basic.rs:21:5
    |
 LL |     extra("");
-   |     ^^^^^ -- argument of type `&'static str` unexpected
+   |     ^^^^^ --
+   |           |
+   |           unexpected argument of type `&'static str`
+   |           help: remove the extra argument
    |
 note: function defined here
   --> $DIR/basic.rs:14:4
    |
 LL | fn extra() {}
    |    ^^^^^
-help: remove the extra argument
-   |
-LL |     extra();
-   |          ~~
 
 error[E0061]: this function takes 1 argument but 0 arguments were supplied
   --> $DIR/basic.rs:22:5
diff --git a/tests/ui/argument-suggestions/exotic-calls.stderr b/tests/ui/argument-suggestions/exotic-calls.stderr
index 0580e53c510..ff795b507f2 100644
--- a/tests/ui/argument-suggestions/exotic-calls.stderr
+++ b/tests/ui/argument-suggestions/exotic-calls.stderr
@@ -2,65 +2,61 @@ error[E0057]: this function takes 0 arguments but 1 argument was supplied
   --> $DIR/exotic-calls.rs:2:5
    |
 LL |     t(1i32);
-   |     ^ ---- argument of type `i32` unexpected
+   |     ^ ----
+   |       |
+   |       unexpected argument of type `i32`
+   |       help: remove the extra argument
    |
 note: callable defined here
   --> $DIR/exotic-calls.rs:1:11
    |
 LL | fn foo<T: Fn()>(t: T) {
    |           ^^^^
-help: remove the extra argument
-   |
-LL |     t();
-   |      ~~
 
 error[E0057]: this function takes 0 arguments but 1 argument was supplied
   --> $DIR/exotic-calls.rs:7:5
    |
 LL |     t(1i32);
-   |     ^ ---- argument of type `i32` unexpected
+   |     ^ ----
+   |       |
+   |       unexpected argument of type `i32`
+   |       help: remove the extra argument
    |
 note: type parameter defined here
   --> $DIR/exotic-calls.rs:6:11
    |
 LL | fn bar(t: impl Fn()) {
    |           ^^^^^^^^^
-help: remove the extra argument
-   |
-LL |     t();
-   |      ~~
 
 error[E0057]: this function takes 0 arguments but 1 argument was supplied
   --> $DIR/exotic-calls.rs:16:5
    |
 LL |     baz()(1i32)
-   |     ^^^^^ ---- argument of type `i32` unexpected
+   |     ^^^^^ ----
+   |           |
+   |           unexpected argument of type `i32`
+   |           help: remove the extra argument
    |
 note: opaque type defined here
   --> $DIR/exotic-calls.rs:11:13
    |
 LL | fn baz() -> impl Fn() {
    |             ^^^^^^^^^
-help: remove the extra argument
-   |
-LL |     baz()()
-   |          ~~
 
 error[E0057]: this function takes 0 arguments but 1 argument was supplied
   --> $DIR/exotic-calls.rs:22:5
    |
 LL |     x(1i32);
-   |     ^ ---- argument of type `i32` unexpected
+   |     ^ ----
+   |       |
+   |       unexpected argument of type `i32`
+   |       help: remove the extra argument
    |
 note: closure defined here
   --> $DIR/exotic-calls.rs:21:13
    |
 LL |     let x = || {};
    |             ^^
-help: remove the extra argument
-   |
-LL |     x();
-   |      ~~
 
 error: aborting due to 4 previous errors
 
diff --git a/tests/ui/argument-suggestions/extra_arguments.stderr b/tests/ui/argument-suggestions/extra_arguments.stderr
index 48787b0c352..0911685b428 100644
--- a/tests/ui/argument-suggestions/extra_arguments.stderr
+++ b/tests/ui/argument-suggestions/extra_arguments.stderr
@@ -2,57 +2,54 @@ error[E0061]: this function takes 0 arguments but 1 argument was supplied
   --> $DIR/extra_arguments.rs:7:3
    |
 LL |   empty("");
-   |   ^^^^^ -- argument of type `&'static str` unexpected
+   |   ^^^^^ --
+   |         |
+   |         unexpected argument of type `&'static str`
+   |         help: remove the extra argument
    |
 note: function defined here
   --> $DIR/extra_arguments.rs:1:4
    |
 LL | fn empty() {}
    |    ^^^^^
-help: remove the extra argument
-   |
-LL |   empty();
-   |        ~~
 
 error[E0061]: this function takes 1 argument but 2 arguments were supplied
   --> $DIR/extra_arguments.rs:9:3
    |
 LL |   one_arg(1, 1);
-   |   ^^^^^^^    - argument of type `{integer}` unexpected
+   |   ^^^^^^^  ---
+   |            | |
+   |            | unexpected argument of type `{integer}`
+   |            help: remove the extra argument
    |
 note: function defined here
   --> $DIR/extra_arguments.rs:2:4
    |
 LL | fn one_arg(_a: i32) {}
    |    ^^^^^^^ -------
-help: remove the extra argument
-   |
-LL |   one_arg(1);
-   |          ~~~
 
 error[E0061]: this function takes 1 argument but 2 arguments were supplied
   --> $DIR/extra_arguments.rs:10:3
    |
 LL |   one_arg(1, "");
-   |   ^^^^^^^    -- argument of type `&'static str` unexpected
+   |   ^^^^^^^  ----
+   |            | |
+   |            | unexpected argument of type `&'static str`
+   |            help: remove the extra argument
    |
 note: function defined here
   --> $DIR/extra_arguments.rs:2:4
    |
 LL | fn one_arg(_a: i32) {}
    |    ^^^^^^^ -------
-help: remove the extra argument
-   |
-LL |   one_arg(1);
-   |          ~~~
 
 error[E0061]: this function takes 1 argument but 3 arguments were supplied
   --> $DIR/extra_arguments.rs:11:3
    |
 LL |   one_arg(1, "", 1.0);
-   |   ^^^^^^^    --  --- argument of type `{float}` unexpected
+   |   ^^^^^^^    --  --- unexpected argument of type `{float}`
    |              |
-   |              argument of type `&'static str` unexpected
+   |              unexpected argument of type `&'static str`
    |
 note: function defined here
   --> $DIR/extra_arguments.rs:2:4
@@ -61,80 +58,77 @@ LL | fn one_arg(_a: i32) {}
    |    ^^^^^^^ -------
 help: remove the extra arguments
    |
-LL |   one_arg(1);
-   |          ~~~
+LL -   one_arg(1, "", 1.0);
+LL +   one_arg(1);
+   |
 
 error[E0061]: this function takes 2 arguments but 3 arguments were supplied
   --> $DIR/extra_arguments.rs:13:3
    |
 LL |   two_arg_same(1, 1, 1);
-   |   ^^^^^^^^^^^^       - argument of type `{integer}` unexpected
+   |   ^^^^^^^^^^^^     ---
+   |                    | |
+   |                    | unexpected argument of type `{integer}`
+   |                    help: remove the extra argument
    |
 note: function defined here
   --> $DIR/extra_arguments.rs:3:4
    |
 LL | fn two_arg_same(_a: i32, _b: i32) {}
    |    ^^^^^^^^^^^^ -------  -------
-help: remove the extra argument
-   |
-LL |   two_arg_same(1, 1);
-   |               ~~~~~~
 
 error[E0061]: this function takes 2 arguments but 3 arguments were supplied
   --> $DIR/extra_arguments.rs:14:3
    |
 LL |   two_arg_same(1, 1, 1.0);
-   |   ^^^^^^^^^^^^       --- argument of type `{float}` unexpected
+   |   ^^^^^^^^^^^^     -----
+   |                    | |
+   |                    | unexpected argument of type `{float}`
+   |                    help: remove the extra argument
    |
 note: function defined here
   --> $DIR/extra_arguments.rs:3:4
    |
 LL | fn two_arg_same(_a: i32, _b: i32) {}
    |    ^^^^^^^^^^^^ -------  -------
-help: remove the extra argument
-   |
-LL |   two_arg_same(1, 1);
-   |               ~~~~~~
 
 error[E0061]: this function takes 2 arguments but 3 arguments were supplied
   --> $DIR/extra_arguments.rs:16:3
    |
 LL |   two_arg_diff(1, 1, "");
-   |   ^^^^^^^^^^^^    - argument of type `{integer}` unexpected
+   |   ^^^^^^^^^^^^  ---
+   |                 | |
+   |                 | unexpected argument of type `{integer}`
+   |                 help: remove the extra argument
    |
 note: function defined here
   --> $DIR/extra_arguments.rs:4:4
    |
 LL | fn two_arg_diff(_a: i32, _b: &str) {}
    |    ^^^^^^^^^^^^ -------  --------
-help: remove the extra argument
-   |
-LL |   two_arg_diff(1, "");
-   |               ~~~~~~~
 
 error[E0061]: this function takes 2 arguments but 3 arguments were supplied
   --> $DIR/extra_arguments.rs:17:3
    |
 LL |   two_arg_diff(1, "", "");
-   |   ^^^^^^^^^^^^        -- argument of type `&'static str` unexpected
+   |   ^^^^^^^^^^^^      ----
+   |                     | |
+   |                     | unexpected argument of type `&'static str`
+   |                     help: remove the extra argument
    |
 note: function defined here
   --> $DIR/extra_arguments.rs:4:4
    |
 LL | fn two_arg_diff(_a: i32, _b: &str) {}
    |    ^^^^^^^^^^^^ -------  --------
-help: remove the extra argument
-   |
-LL |   two_arg_diff(1, "");
-   |               ~~~~~~~
 
 error[E0061]: this function takes 2 arguments but 4 arguments were supplied
   --> $DIR/extra_arguments.rs:18:3
    |
 LL |   two_arg_diff(1, 1, "", "");
-   |   ^^^^^^^^^^^^    -      -- argument of type `&'static str` unexpected
+   |   ^^^^^^^^^^^^    -      -- unexpected argument of type `&'static str`
    |                   |
-   |                   argument of type `{integer}` unexpected
+   |                   unexpected argument of type `{integer}`
    |
 note: function defined here
   --> $DIR/extra_arguments.rs:4:4
@@ -143,16 +137,17 @@ LL | fn two_arg_diff(_a: i32, _b: &str) {}
    |    ^^^^^^^^^^^^ -------  --------
 help: remove the extra arguments
    |
-LL |   two_arg_diff(1, "");
-   |               ~~~~~~~
+LL -   two_arg_diff(1, 1, "", "");
+LL +   two_arg_diff(1, "");
+   |
 
 error[E0061]: this function takes 2 arguments but 4 arguments were supplied
   --> $DIR/extra_arguments.rs:19:3
    |
 LL |   two_arg_diff(1, "", 1, "");
-   |   ^^^^^^^^^^^^        -  -- argument of type `&'static str` unexpected
+   |   ^^^^^^^^^^^^        -  -- unexpected argument of type `&'static str`
    |                       |
-   |                       argument of type `{integer}` unexpected
+   |                       unexpected argument of type `{integer}`
    |
 note: function defined here
   --> $DIR/extra_arguments.rs:4:4
@@ -161,78 +156,78 @@ LL | fn two_arg_diff(_a: i32, _b: &str) {}
    |    ^^^^^^^^^^^^ -------  --------
 help: remove the extra arguments
    |
-LL |   two_arg_diff(1, "");
-   |               ~~~~~~~
+LL -   two_arg_diff(1, "", 1, "");
+LL +   two_arg_diff(1, "");
+   |
 
 error[E0061]: this function takes 2 arguments but 3 arguments were supplied
   --> $DIR/extra_arguments.rs:22:3
    |
 LL |   two_arg_same(1, 1,     "");
-   |   ^^^^^^^^^^^^           -- argument of type `&'static str` unexpected
+   |   ^^^^^^^^^^^^     --------
+   |                    |     |
+   |                    |     unexpected argument of type `&'static str`
+   |                    help: remove the extra argument
    |
 note: function defined here
   --> $DIR/extra_arguments.rs:3:4
    |
 LL | fn two_arg_same(_a: i32, _b: i32) {}
    |    ^^^^^^^^^^^^ -------  -------
-help: remove the extra argument
-   |
-LL |   two_arg_same(1, 1);
-   |               ~~~~~~
 
 error[E0061]: this function takes 2 arguments but 3 arguments were supplied
   --> $DIR/extra_arguments.rs:23:3
    |
 LL |   two_arg_diff(1, 1,     "");
-   |   ^^^^^^^^^^^^    - argument of type `{integer}` unexpected
+   |   ^^^^^^^^^^^^  ---
+   |                 | |
+   |                 | unexpected argument of type `{integer}`
+   |                 help: remove the extra argument
    |
 note: function defined here
   --> $DIR/extra_arguments.rs:4:4
    |
 LL | fn two_arg_diff(_a: i32, _b: &str) {}
    |    ^^^^^^^^^^^^ -------  --------
-help: remove the extra argument
-   |
-LL |   two_arg_diff(1, "");
-   |               ~~~~~~~
 
 error[E0061]: this function takes 2 arguments but 3 arguments were supplied
   --> $DIR/extra_arguments.rs:24:3
    |
-LL |   two_arg_same(
-   |   ^^^^^^^^^^^^
-...
-LL |     ""
-   |     -- argument of type `&'static str` unexpected
+LL |     two_arg_same(
+   |     ^^^^^^^^^^^^
+LL |       1,
+LL |       1,
+   |  ______-
+LL | |     ""
+   | |     --
+   | |_____||
+   |       |help: remove the extra argument
+   |       unexpected argument of type `&'static str`
    |
 note: function defined here
   --> $DIR/extra_arguments.rs:3:4
    |
 LL | fn two_arg_same(_a: i32, _b: i32) {}
    |    ^^^^^^^^^^^^ -------  -------
-help: remove the extra argument
-   |
-LL |   two_arg_same(1, 1);
-   |               ~~~~~~
 
 error[E0061]: this function takes 2 arguments but 3 arguments were supplied
   --> $DIR/extra_arguments.rs:30:3
    |
-LL |   two_arg_diff(
-   |   ^^^^^^^^^^^^
-LL |     1,
-LL |     1,
-   |     - argument of type `{integer}` unexpected
+LL |     two_arg_diff(
+   |     ^^^^^^^^^^^^
+LL |       1,
+   |  ______-
+LL | |     1,
+   | |     -
+   | |     |
+   | |_____unexpected argument of type `{integer}`
+   |       help: remove the extra argument
    |
 note: function defined here
   --> $DIR/extra_arguments.rs:4:4
    |
 LL | fn two_arg_diff(_a: i32, _b: &str) {}
    |    ^^^^^^^^^^^^ -------  --------
-help: remove the extra argument
-   |
-LL |   two_arg_diff(1, "");
-   |               ~~~~~~~
 
 error: aborting due to 14 previous errors
 
diff --git a/tests/ui/argument-suggestions/issue-101097.stderr b/tests/ui/argument-suggestions/issue-101097.stderr
index 7582082ac72..061f510144b 100644
--- a/tests/ui/argument-suggestions/issue-101097.stderr
+++ b/tests/ui/argument-suggestions/issue-101097.stderr
@@ -4,7 +4,7 @@ error[E0061]: this function takes 6 arguments but 7 arguments were supplied
 LL |     f(C, A, A, A, B, B, C);
    |     ^ -     -  -  - expected `C`, found `B`
    |       |     |  |
-   |       |     |  argument of type `A` unexpected
+   |       |     |  unexpected argument of type `A`
    |       |     expected `B`, found `A`
    |       expected `A`, found `C`
    |
@@ -64,8 +64,8 @@ error[E0308]: arguments to this function are incorrect
 LL |     f(A, A, D, D, B, B);
    |     ^       -  -  ---- two arguments of type `C` and `C` are missing
    |             |  |
-   |             |  argument of type `D` unexpected
-   |             argument of type `D` unexpected
+   |             |  unexpected argument of type `D`
+   |             unexpected argument of type `D`
    |
 note: function defined here
   --> $DIR/issue-101097.rs:6:4
diff --git a/tests/ui/argument-suggestions/issue-97484.stderr b/tests/ui/argument-suggestions/issue-97484.stderr
index c2e6e001b17..a86cbbf1802 100644
--- a/tests/ui/argument-suggestions/issue-97484.stderr
+++ b/tests/ui/argument-suggestions/issue-97484.stderr
@@ -2,11 +2,11 @@ error[E0061]: this function takes 4 arguments but 7 arguments were supplied
   --> $DIR/issue-97484.rs:12:5
    |
 LL |     foo(&&A, B, C, D, E, F, G);
-   |     ^^^      -  -     -  - argument of type `F` unexpected
+   |     ^^^      -  -     -  - unexpected argument of type `F`
    |              |  |     |
    |              |  |     expected `&E`, found `E`
-   |              |  argument of type `C` unexpected
-   |              argument of type `B` unexpected
+   |              |  unexpected argument of type `C`
+   |              unexpected argument of type `B`
    |
 note: function defined here
   --> $DIR/issue-97484.rs:9:4
@@ -19,8 +19,9 @@ LL |     foo(&&A, B, C, D, &E, F, G);
    |                       ~~
 help: remove the extra arguments
    |
-LL |     foo(&&A, D, /* &E */, G);
-   |        ~~~~~~~~~~~~~~~~~~~~~
+LL -     foo(&&A, B, C, D, E, F, G);
+LL +     foo(&&A, D, /* &E */, G);
+   |
 
 error: aborting due to previous error
 
diff --git a/tests/ui/argument-suggestions/mixed_cases.stderr b/tests/ui/argument-suggestions/mixed_cases.stderr
index 8cf48060a63..c645dd38179 100644
--- a/tests/ui/argument-suggestions/mixed_cases.stderr
+++ b/tests/ui/argument-suggestions/mixed_cases.stderr
@@ -2,7 +2,7 @@ error[E0061]: this function takes 2 arguments but 3 arguments were supplied
   --> $DIR/mixed_cases.rs:10:3
    |
 LL |   two_args(1, "", X {});
-   |   ^^^^^^^^    --  ---- argument of type `X` unexpected
+   |   ^^^^^^^^    --  ---- unexpected argument of type `X`
    |               |
    |               expected `f32`, found `&str`
    |
@@ -13,16 +13,17 @@ LL | fn two_args(_a: i32, _b: f32) {}
    |    ^^^^^^^^ -------  -------
 help: remove the extra argument
    |
-LL |   two_args(1, /* f32 */);
-   |           ~~~~~~~~~~~~~~
+LL -   two_args(1, "", X {});
+LL +   two_args(1, /* f32 */);
+   |
 
 error[E0061]: this function takes 3 arguments but 4 arguments were supplied
   --> $DIR/mixed_cases.rs:11:3
    |
 LL |   three_args(1, "", X {}, "");
-   |   ^^^^^^^^^^    --  ----  -- argument of type `&'static str` unexpected
+   |   ^^^^^^^^^^    --  ----  -- unexpected argument of type `&'static str`
    |                 |   |
-   |                 |   argument of type `X` unexpected
+   |                 |   unexpected argument of type `X`
    |                 an argument of type `f32` is missing
    |
 note: function defined here
@@ -58,7 +59,7 @@ error[E0308]: arguments to this function are incorrect
   --> $DIR/mixed_cases.rs:17:3
    |
 LL |   three_args(1, "", X {});
-   |   ^^^^^^^^^^    --  ---- argument of type `X` unexpected
+   |   ^^^^^^^^^^    --  ---- unexpected argument of type `X`
    |                 |
    |                 an argument of type `f32` is missing
    |
diff --git a/tests/ui/issues/issue-38821.rs b/tests/ui/associated-types/issue-38821.rs
index 6753860e9ff..6753860e9ff 100644
--- a/tests/ui/issues/issue-38821.rs
+++ b/tests/ui/associated-types/issue-38821.rs
diff --git a/tests/ui/issues/issue-38821.stderr b/tests/ui/associated-types/issue-38821.stderr
index a52a9c138f1..a52a9c138f1 100644
--- a/tests/ui/issues/issue-38821.stderr
+++ b/tests/ui/associated-types/issue-38821.stderr
diff --git a/tests/ui/issues/issue-83924.fixed b/tests/ui/borrowck/issue-83924.fixed
index aa40da12b87..aa40da12b87 100644
--- a/tests/ui/issues/issue-83924.fixed
+++ b/tests/ui/borrowck/issue-83924.fixed
diff --git a/tests/ui/issues/issue-83924.rs b/tests/ui/borrowck/issue-83924.rs
index 22b80fe2f38..22b80fe2f38 100644
--- a/tests/ui/issues/issue-83924.rs
+++ b/tests/ui/borrowck/issue-83924.rs
diff --git a/tests/ui/issues/issue-83924.stderr b/tests/ui/borrowck/issue-83924.stderr
index 572414df2bf..572414df2bf 100644
--- a/tests/ui/issues/issue-83924.stderr
+++ b/tests/ui/borrowck/issue-83924.stderr
diff --git a/tests/ui/bounds-lifetime.stderr b/tests/ui/bounds-lifetime.stderr
index a0395ed4904..f0bfe784ccc 100644
--- a/tests/ui/bounds-lifetime.stderr
+++ b/tests/ui/bounds-lifetime.stderr
@@ -16,17 +16,24 @@ error: lifetime bounds cannot be used in this context
 LL | type C = for<'b, 'a: 'b +> fn();
    |                      ^^
 
-error: only lifetime parameters can be used in this context
+error[E0658]: only lifetime parameters can be used in this context
   --> $DIR/bounds-lifetime.rs:4:18
    |
 LL | type D = for<'a, T> fn();
    |                  ^
+   |
+   = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
+   = help: add `#![feature(non_lifetime_binders)]` to the crate attributes to enable
 
-error: only lifetime parameters can be used in this context
+error[E0658]: only lifetime parameters can be used in this context
   --> $DIR/bounds-lifetime.rs:5:18
    |
 LL | type E = dyn for<T> Fn();
    |                  ^
+   |
+   = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
+   = help: add `#![feature(non_lifetime_binders)]` to the crate attributes to enable
 
 error: aborting due to 5 previous errors
 
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/closures/binder/const-bound.rs b/tests/ui/closures/binder/const-bound.rs
new file mode 100644
index 00000000000..b1c79db1375
--- /dev/null
+++ b/tests/ui/closures/binder/const-bound.rs
@@ -0,0 +1,7 @@
+#![feature(closure_lifetime_binder, non_lifetime_binders)]
+//~^ WARN  is incomplete and may not be safe to use
+
+fn main()  {
+    for<const N: i32> || -> () {};
+    //~^ ERROR late-bound const parameter not allowed on closures
+}
diff --git a/tests/ui/closures/binder/const-bound.stderr b/tests/ui/closures/binder/const-bound.stderr
new file mode 100644
index 00000000000..c016465c101
--- /dev/null
+++ b/tests/ui/closures/binder/const-bound.stderr
@@ -0,0 +1,17 @@
+warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/const-bound.rs:1:37
+   |
+LL | #![feature(closure_lifetime_binder, non_lifetime_binders)]
+   |                                     ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+error: late-bound const parameter not allowed on closures
+  --> $DIR/const-bound.rs:5:9
+   |
+LL |     for<const N: i32> || -> () {};
+   |         ^^^^^^^^^^^^
+
+error: aborting due to previous error; 1 warning emitted
+
diff --git a/tests/ui/closures/binder/disallow-const.stderr b/tests/ui/closures/binder/disallow-const.stderr
index 3c3b43d8cf3..59f299315f8 100644
--- a/tests/ui/closures/binder/disallow-const.stderr
+++ b/tests/ui/closures/binder/disallow-const.stderr
@@ -1,8 +1,12 @@
-error: only lifetime parameters can be used in this context
+error[E0658]: only lifetime parameters can be used in this context
   --> $DIR/disallow-const.rs:4:15
    |
 LL |     for<const N: i32> || -> () {};
    |               ^
+   |
+   = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
+   = help: add `#![feature(non_lifetime_binders)]` to the crate attributes to enable
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/closures/binder/disallow-ty.stderr b/tests/ui/closures/binder/disallow-ty.stderr
index 51b6773edea..3370e21bd71 100644
--- a/tests/ui/closures/binder/disallow-ty.stderr
+++ b/tests/ui/closures/binder/disallow-ty.stderr
@@ -1,8 +1,12 @@
-error: only lifetime parameters can be used in this context
+error[E0658]: only lifetime parameters can be used in this context
   --> $DIR/disallow-ty.rs:4:9
    |
 LL |     for<T> || -> () {};
    |         ^
+   |
+   = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
+   = help: add `#![feature(non_lifetime_binders)]` to the crate attributes to enable
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/closures/binder/type-bound-2.rs b/tests/ui/closures/binder/type-bound-2.rs
new file mode 100644
index 00000000000..f4edcdaa9ca
--- /dev/null
+++ b/tests/ui/closures/binder/type-bound-2.rs
@@ -0,0 +1,7 @@
+#![feature(closure_lifetime_binder, non_lifetime_binders)]
+//~^ WARN  is incomplete and may not be safe to use
+
+fn main() {
+    for<T> || -> () {};
+    //~^ ERROR late-bound type parameter not allowed on closures
+}
diff --git a/tests/ui/closures/binder/type-bound-2.stderr b/tests/ui/closures/binder/type-bound-2.stderr
new file mode 100644
index 00000000000..14b2dbf0395
--- /dev/null
+++ b/tests/ui/closures/binder/type-bound-2.stderr
@@ -0,0 +1,17 @@
+warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/type-bound-2.rs:1:37
+   |
+LL | #![feature(closure_lifetime_binder, non_lifetime_binders)]
+   |                                     ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+error: late-bound type parameter not allowed on closures
+  --> $DIR/type-bound-2.rs:5:9
+   |
+LL |     for<T> || -> () {};
+   |         ^
+
+error: aborting due to previous error; 1 warning emitted
+
diff --git a/tests/ui/closures/binder/type-bound.rs b/tests/ui/closures/binder/type-bound.rs
new file mode 100644
index 00000000000..59a3353f496
--- /dev/null
+++ b/tests/ui/closures/binder/type-bound.rs
@@ -0,0 +1,7 @@
+#![feature(closure_lifetime_binder, non_lifetime_binders)]
+//~^ WARN  is incomplete and may not be safe to use
+
+fn main()  {
+    for<T> || -> T {};
+    //~^ ERROR late-bound type parameter not allowed on closures
+}
diff --git a/tests/ui/closures/binder/type-bound.stderr b/tests/ui/closures/binder/type-bound.stderr
new file mode 100644
index 00000000000..ef00a2dffce
--- /dev/null
+++ b/tests/ui/closures/binder/type-bound.stderr
@@ -0,0 +1,17 @@
+warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/type-bound.rs:1:37
+   |
+LL | #![feature(closure_lifetime_binder, non_lifetime_binders)]
+   |                                     ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+error: late-bound type parameter not allowed on closures
+  --> $DIR/type-bound.rs:5:9
+   |
+LL |     for<T> || -> T {};
+   |         ^
+
+error: aborting due to previous error; 1 warning emitted
+
diff --git a/tests/ui/conditional-compilation/cfg-generic-params.stderr b/tests/ui/conditional-compilation/cfg-generic-params.stderr
index 4d6560e96e5..f733c09c22e 100644
--- a/tests/ui/conditional-compilation/cfg-generic-params.stderr
+++ b/tests/ui/conditional-compilation/cfg-generic-params.stderr
@@ -1,21 +1,3 @@
-error: only lifetime parameters can be used in this context
-  --> $DIR/cfg-generic-params.rs:7:45
-   |
-LL | type FnBad = for<#[cfg(no)] 'a, #[cfg(yes)] T> fn();
-   |                                             ^
-
-error: only lifetime parameters can be used in this context
-  --> $DIR/cfg-generic-params.rs:11:51
-   |
-LL | type PolyBad = dyn for<#[cfg(no)] 'a, #[cfg(yes)] T> Copy;
-   |                                                   ^
-
-error: only lifetime parameters can be used in this context
-  --> $DIR/cfg-generic-params.rs:15:54
-   |
-LL | struct WhereBad where for<#[cfg(no)] 'a, #[cfg(yes)] T> u8: Copy;
-   |                                                      ^
-
 error: cannot find attribute `unknown` in this scope
   --> $DIR/cfg-generic-params.rs:19:29
    |
@@ -46,5 +28,33 @@ error: cannot find attribute `unknown` in this scope
 LL | struct WhereYes where for<#[cfg_attr(yes, unknown)] 'a> u8: Copy;
    |                                           ^^^^^^^
 
+error[E0658]: only lifetime parameters can be used in this context
+  --> $DIR/cfg-generic-params.rs:7:45
+   |
+LL | type FnBad = for<#[cfg(no)] 'a, #[cfg(yes)] T> fn();
+   |                                             ^
+   |
+   = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
+   = help: add `#![feature(non_lifetime_binders)]` to the crate attributes to enable
+
+error[E0658]: only lifetime parameters can be used in this context
+  --> $DIR/cfg-generic-params.rs:11:51
+   |
+LL | type PolyBad = dyn for<#[cfg(no)] 'a, #[cfg(yes)] T> Copy;
+   |                                                   ^
+   |
+   = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
+   = help: add `#![feature(non_lifetime_binders)]` to the crate attributes to enable
+
+error[E0658]: only lifetime parameters can be used in this context
+  --> $DIR/cfg-generic-params.rs:15:54
+   |
+LL | struct WhereBad where for<#[cfg(no)] 'a, #[cfg(yes)] T> u8: Copy;
+   |                                                      ^
+   |
+   = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
+   = help: add `#![feature(non_lifetime_binders)]` to the crate attributes to enable
+
 error: aborting due to 8 previous errors
 
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/const-generics/nested-type.min.stderr b/tests/ui/const-generics/nested-type.min.stderr
index cff02b0d445..257a9e31e14 100644
--- a/tests/ui/const-generics/nested-type.min.stderr
+++ b/tests/ui/const-generics/nested-type.min.stderr
@@ -1,3 +1,11 @@
+error[E0015]: cannot call non-const fn `Foo::{constant#0}::Foo::<17>::value` in constants
+  --> $DIR/nested-type.rs:15:5
+   |
+LL |     Foo::<17>::value()
+   |     ^^^^^^^^^^^^^^^^^^
+   |
+   = note: calls in constants are limited to constant functions, tuple structs and tuple variants
+
 error: `[u8; {
            struct Foo<const N: usize>;
        
@@ -24,5 +32,6 @@ LL | | }]>;
    = note: the only supported types are integers, `bool` and `char`
    = help: more complex types are supported with `#![feature(adt_const_params)]`
 
-error: aborting due to previous error
+error: aborting due to 2 previous errors
 
+For more information about this error, try `rustc --explain E0015`.
diff --git a/tests/ui/const-generics/nested-type.rs b/tests/ui/const-generics/nested-type.rs
index 742340f430e..5240f5c3b0b 100644
--- a/tests/ui/const-generics/nested-type.rs
+++ b/tests/ui/const-generics/nested-type.rs
@@ -13,7 +13,7 @@ struct Foo<const N: [u8; { //[min]~ ERROR `[u8; _]` is forbidden
     }
 
     Foo::<17>::value()
-    //[full]~^ ERROR cannot call non-const fn
+    //~^ ERROR cannot call non-const fn
 }]>;
 
 fn main() {}
diff --git a/tests/ui/issues/issue-33903.rs b/tests/ui/consts/issue-33903.rs
index 613aa121a47..613aa121a47 100644
--- a/tests/ui/issues/issue-33903.rs
+++ b/tests/ui/consts/issue-33903.rs
diff --git a/tests/ui/issues/issue-54582.rs b/tests/ui/consts/issue-54582.rs
index 8c50cac67f8..8c50cac67f8 100644
--- a/tests/ui/issues/issue-54582.rs
+++ b/tests/ui/consts/issue-54582.rs
diff --git a/tests/ui/issues/issue-2735-2.rs b/tests/ui/drop/issue-2735-2.rs
index 70ebce9d35a..70ebce9d35a 100644
--- a/tests/ui/issues/issue-2735-2.rs
+++ b/tests/ui/drop/issue-2735-2.rs
diff --git a/tests/ui/issues/issue-2735-3.rs b/tests/ui/drop/issue-2735-3.rs
index 23301537835..23301537835 100644
--- a/tests/ui/issues/issue-2735-3.rs
+++ b/tests/ui/drop/issue-2735-3.rs
diff --git a/tests/ui/issues/issue-2735.rs b/tests/ui/drop/issue-2735.rs
index 20d3949a9f9..20d3949a9f9 100644
--- a/tests/ui/issues/issue-2735.rs
+++ b/tests/ui/drop/issue-2735.rs
diff --git a/tests/ui/error-codes/E0057.stderr b/tests/ui/error-codes/E0057.stderr
index 163737895fe..9b0cf069824 100644
--- a/tests/ui/error-codes/E0057.stderr
+++ b/tests/ui/error-codes/E0057.stderr
@@ -18,17 +18,16 @@ error[E0057]: this function takes 1 argument but 2 arguments were supplied
   --> $DIR/E0057.rs:5:13
    |
 LL |     let c = f(2, 3);
-   |             ^    - argument of type `{integer}` unexpected
+   |             ^  ---
+   |                | |
+   |                | unexpected argument of type `{integer}`
+   |                help: remove the extra argument
    |
 note: closure defined here
   --> $DIR/E0057.rs:2:13
    |
 LL |     let f = |x| x * 3;
    |             ^^^
-help: remove the extra argument
-   |
-LL |     let c = f(2);
-   |              ~~~
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/feature-gates/feature-gate-non_lifetime_binders.rs b/tests/ui/feature-gates/feature-gate-non_lifetime_binders.rs
new file mode 100644
index 00000000000..221e9133fcc
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-non_lifetime_binders.rs
@@ -0,0 +1,4 @@
+fn foo() where for<T> T:, {}
+//~^ ERROR only lifetime parameters can be used in this context
+
+fn main() {}
diff --git a/tests/ui/feature-gates/feature-gate-non_lifetime_binders.stderr b/tests/ui/feature-gates/feature-gate-non_lifetime_binders.stderr
new file mode 100644
index 00000000000..01c8ee30c5f
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-non_lifetime_binders.stderr
@@ -0,0 +1,12 @@
+error[E0658]: only lifetime parameters can be used in this context
+  --> $DIR/feature-gate-non_lifetime_binders.rs:1:20
+   |
+LL | fn foo() where for<T> T:, {}
+   |                    ^
+   |
+   = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
+   = help: add `#![feature(non_lifetime_binders)]` to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/issues/issue-75307.rs b/tests/ui/fmt/issue-75307.rs
index cffa6bea8ed..cffa6bea8ed 100644
--- a/tests/ui/issues/issue-75307.rs
+++ b/tests/ui/fmt/issue-75307.rs
diff --git a/tests/ui/issues/issue-75307.stderr b/tests/ui/fmt/issue-75307.stderr
index c5b0b11e7d0..c5b0b11e7d0 100644
--- a/tests/ui/issues/issue-75307.stderr
+++ b/tests/ui/fmt/issue-75307.stderr
diff --git a/tests/ui/higher-rank-trait-bounds/hrtb-wrong-kind.stderr b/tests/ui/higher-rank-trait-bounds/hrtb-wrong-kind.stderr
index f31aa554634..765ea9f7854 100644
--- a/tests/ui/higher-rank-trait-bounds/hrtb-wrong-kind.stderr
+++ b/tests/ui/higher-rank-trait-bounds/hrtb-wrong-kind.stderr
@@ -1,14 +1,21 @@
-error: only lifetime parameters can be used in this context
+error[E0658]: only lifetime parameters can be used in this context
   --> $DIR/hrtb-wrong-kind.rs:1:18
    |
 LL | fn a() where for<T> T: Copy {}
    |                  ^
+   |
+   = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
+   = help: add `#![feature(non_lifetime_binders)]` to the crate attributes to enable
 
-error: only lifetime parameters can be used in this context
+error[E0658]: only lifetime parameters can be used in this context
   --> $DIR/hrtb-wrong-kind.rs:4:24
    |
 LL | fn b() where for<const C: usize> [(); C]: Copy {}
    |                        ^
+   |
+   = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
+   = help: add `#![feature(non_lifetime_binders)]` to the crate attributes to enable
 
 error: aborting due to 2 previous errors
 
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/issues/issue-39292.rs b/tests/ui/higher-rank-trait-bounds/issue-39292.rs
index 968cf08916f..968cf08916f 100644
--- a/tests/ui/issues/issue-39292.rs
+++ b/tests/ui/higher-rank-trait-bounds/issue-39292.rs
diff --git a/tests/ui/issues/issue-16939.stderr b/tests/ui/issues/issue-16939.stderr
index 76645645464..6db29bc61b1 100644
--- a/tests/ui/issues/issue-16939.stderr
+++ b/tests/ui/issues/issue-16939.stderr
@@ -2,17 +2,16 @@ error[E0057]: this function takes 0 arguments but 1 argument was supplied
   --> $DIR/issue-16939.rs:5:9
    |
 LL |     |t| f(t);
-   |         ^ - argument unexpected
+   |         ^ -
+   |           |
+   |           unexpected argument
+   |           help: remove the extra argument
    |
 note: callable defined here
   --> $DIR/issue-16939.rs:4:12
    |
 LL | fn _foo<F: Fn()> (f: F) {
    |            ^^^^
-help: remove the extra argument
-   |
-LL |     |t| f();
-   |          ~~
 
 error: aborting due to previous error
 
diff --git a/tests/ui/issues/issue-26094.rs b/tests/ui/issues/issue-26094.rs
index d3d670aa92a..abf3543ddb9 100644
--- a/tests/ui/issues/issue-26094.rs
+++ b/tests/ui/issues/issue-26094.rs
@@ -1,6 +1,6 @@
 macro_rules! some_macro {
     ($other: expr) => ({
-        $other(None) //~ NOTE argument of type `Option<_>` unexpected
+        $other(None) //~ NOTE unexpected argument of type `Option<_>`
     })
 }
 
diff --git a/tests/ui/issues/issue-26094.stderr b/tests/ui/issues/issue-26094.stderr
index 881a6e538ee..608d2c7aff9 100644
--- a/tests/ui/issues/issue-26094.stderr
+++ b/tests/ui/issues/issue-26094.stderr
@@ -2,7 +2,10 @@ error[E0061]: this function takes 0 arguments but 1 argument was supplied
   --> $DIR/issue-26094.rs:10:17
    |
 LL |         $other(None)
-   |                ---- argument of type `Option<_>` unexpected
+   |                ----
+   |                |
+   |                unexpected argument of type `Option<_>`
+   |                help: remove the extra argument
 ...
 LL |     some_macro!(some_function);
    |                 ^^^^^^^^^^^^^
@@ -12,10 +15,6 @@ note: function defined here
    |
 LL | fn some_function() {}
    |    ^^^^^^^^^^^^^
-help: remove the extra argument
-   |
-LL |         some_function()
-   |         ~~~~~~~~~~~~~~~
 
 error: aborting due to previous error
 
diff --git a/tests/ui/issues/issue-4935.stderr b/tests/ui/issues/issue-4935.stderr
index bb45fa08338..e544e424403 100644
--- a/tests/ui/issues/issue-4935.stderr
+++ b/tests/ui/issues/issue-4935.stderr
@@ -2,17 +2,16 @@ error[E0061]: this function takes 1 argument but 2 arguments were supplied
   --> $DIR/issue-4935.rs:5:13
    |
 LL | fn main() { foo(5, 6) }
-   |             ^^^    - argument of type `{integer}` unexpected
+   |             ^^^  ---
+   |                  | |
+   |                  | unexpected argument of type `{integer}`
+   |                  help: remove the extra argument
    |
 note: function defined here
   --> $DIR/issue-4935.rs:3:4
    |
 LL | fn foo(a: usize) {}
    |    ^^^ --------
-help: remove the extra argument
-   |
-LL | fn main() { foo(5) }
-   |                ~~~
 
 error: aborting due to previous error
 
diff --git a/tests/ui/lexer/issue-108019-bad-emoji-recovery.rs b/tests/ui/lexer/issue-108019-bad-emoji-recovery.rs
new file mode 100644
index 00000000000..f0f86224560
--- /dev/null
+++ b/tests/ui/lexer/issue-108019-bad-emoji-recovery.rs
@@ -0,0 +1,45 @@
+#![allow(unused_labels)]
+
+// FIXME(#108019): outdated Unicode table
+// fn foo() {
+//     '🥺 loop {
+//         break
+//     }
+// }
+
+fn bar() {
+    '🐱 loop {
+    //~^ ERROR labeled expression must be followed by `:`
+    //~| ERROR lifetimes or labels cannot contain emojis
+        break
+    }
+}
+
+fn qux() {
+    'a🐱 loop {
+    //~^ ERROR labeled expression must be followed by `:`
+    //~| ERROR lifetimes or labels cannot contain emojis
+        break
+    }
+}
+
+fn quux() {
+    '1🐱 loop {
+    //~^ ERROR labeled expression must be followed by `:`
+    //~| ERROR lifetimes or labels cannot start with a number
+        break
+    }
+}
+
+fn x<'🐱>() -> &'🐱 () {
+    //~^ ERROR lifetimes or labels cannot contain emojis
+    //~| ERROR lifetimes or labels cannot contain emojis
+    &()
+}
+
+fn y() {
+    'a🐱: loop {}
+    //~^ ERROR lifetimes or labels cannot contain emojis
+}
+
+fn main() {}
diff --git a/tests/ui/lexer/issue-108019-bad-emoji-recovery.stderr b/tests/ui/lexer/issue-108019-bad-emoji-recovery.stderr
new file mode 100644
index 00000000000..be77ffdea34
--- /dev/null
+++ b/tests/ui/lexer/issue-108019-bad-emoji-recovery.stderr
@@ -0,0 +1,86 @@
+error: labeled expression must be followed by `:`
+  --> $DIR/issue-108019-bad-emoji-recovery.rs:11:5
+   |
+LL |       '🐱 loop {
+   |       ^--- help: add `:` after the label
+   |       |
+   |  _____the label
+   | |
+LL | |
+LL | |
+LL | |         break
+LL | |     }
+   | |_____^
+   |
+   = note: labels are used before loops and blocks, allowing e.g., `break 'label` to them
+
+error: labeled expression must be followed by `:`
+  --> $DIR/issue-108019-bad-emoji-recovery.rs:19:5
+   |
+LL |       'a🐱 loop {
+   |       ^---- help: add `:` after the label
+   |       |
+   |  _____the label
+   | |
+LL | |
+LL | |
+LL | |         break
+LL | |     }
+   | |_____^
+   |
+   = note: labels are used before loops and blocks, allowing e.g., `break 'label` to them
+
+error: labeled expression must be followed by `:`
+  --> $DIR/issue-108019-bad-emoji-recovery.rs:27:5
+   |
+LL |       '1🐱 loop {
+   |       ^---- help: add `:` after the label
+   |       |
+   |  _____the label
+   | |
+LL | |
+LL | |
+LL | |         break
+LL | |     }
+   | |_____^
+   |
+   = note: labels are used before loops and blocks, allowing e.g., `break 'label` to them
+
+error: lifetimes or labels cannot contain emojis
+  --> $DIR/issue-108019-bad-emoji-recovery.rs:11:5
+   |
+LL |     '🐱 loop {
+   |     ^^^
+
+error: lifetimes or labels cannot contain emojis
+  --> $DIR/issue-108019-bad-emoji-recovery.rs:19:5
+   |
+LL |     'a🐱 loop {
+   |     ^^^^
+
+error: lifetimes or labels cannot start with a number
+  --> $DIR/issue-108019-bad-emoji-recovery.rs:27:5
+   |
+LL |     '1🐱 loop {
+   |     ^^^^
+
+error: lifetimes or labels cannot contain emojis
+  --> $DIR/issue-108019-bad-emoji-recovery.rs:34:6
+   |
+LL | fn x<'🐱>() -> &'🐱 () {
+   |      ^^^
+
+error: lifetimes or labels cannot contain emojis
+  --> $DIR/issue-108019-bad-emoji-recovery.rs:34:16
+   |
+LL | fn x<'🐱>() -> &'🐱 () {
+   |                 ^^^
+
+error: lifetimes or labels cannot contain emojis
+  --> $DIR/issue-108019-bad-emoji-recovery.rs:41:5
+   |
+LL |     'a🐱: loop {}
+   |     ^^^^
+
+error: aborting due to 9 previous errors
+
diff --git a/tests/ui/lint/issue-108155.rs b/tests/ui/lint/issue-108155.rs
new file mode 100644
index 00000000000..4ae0cbd92ff
--- /dev/null
+++ b/tests/ui/lint/issue-108155.rs
@@ -0,0 +1,15 @@
+// check-pass
+// check that `deref_into_dyn_supertrait` doesn't cause ICE by eagerly converting
+// a cancelled lint
+
+#![allow(deref_into_dyn_supertrait)]
+
+trait Trait {}
+impl std::ops::Deref for dyn Trait + Send + Sync {
+    type Target = dyn Trait;
+    fn deref(&self) -> &Self::Target {
+        self
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/issues/issue-50576.rs b/tests/ui/loops/issue-50576.rs
index e0c36b8273a..e0c36b8273a 100644
--- a/tests/ui/issues/issue-50576.rs
+++ b/tests/ui/loops/issue-50576.rs
diff --git a/tests/ui/issues/issue-50576.stderr b/tests/ui/loops/issue-50576.stderr
index 4ec22fde910..4ec22fde910 100644
--- a/tests/ui/issues/issue-50576.stderr
+++ b/tests/ui/loops/issue-50576.stderr
diff --git a/tests/ui/methods/method-call-err-msg.stderr b/tests/ui/methods/method-call-err-msg.stderr
index 81269b73b9a..0f37e8f09a9 100644
--- a/tests/ui/methods/method-call-err-msg.stderr
+++ b/tests/ui/methods/method-call-err-msg.stderr
@@ -2,17 +2,16 @@ error[E0061]: this method takes 0 arguments but 1 argument was supplied
   --> $DIR/method-call-err-msg.rs:13:7
    |
 LL |     x.zero(0)
-   |       ^^^^ - argument of type `{integer}` unexpected
+   |       ^^^^ -
+   |            |
+   |            unexpected argument of type `{integer}`
+   |            help: remove the extra argument
    |
 note: associated function defined here
   --> $DIR/method-call-err-msg.rs:5:8
    |
 LL |     fn zero(self) -> Foo { self }
    |        ^^^^
-help: remove the extra argument
-   |
-LL |     x.zero()
-   |           ~~
 
 error[E0061]: this method takes 1 argument but 0 arguments were supplied
   --> $DIR/method-call-err-msg.rs:14:7
diff --git a/tests/ui/mismatched_types/overloaded-calls-bad.stderr b/tests/ui/mismatched_types/overloaded-calls-bad.stderr
index 3a895acbdb5..cd483e7ad2c 100644
--- a/tests/ui/mismatched_types/overloaded-calls-bad.stderr
+++ b/tests/ui/mismatched_types/overloaded-calls-bad.stderr
@@ -32,7 +32,7 @@ error[E0057]: this function takes 1 argument but 2 arguments were supplied
   --> $DIR/overloaded-calls-bad.rs:37:15
    |
 LL |     let ans = s("burma", "shave");
-   |               ^ -------  ------- argument of type `&'static str` unexpected
+   |               ^ -------  ------- unexpected argument of type `&'static str`
    |                 |
    |                 expected `isize`, found `&str`
    |
@@ -43,8 +43,9 @@ LL | impl FnMut<(isize,)> for S {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^
 help: remove the extra argument
    |
-LL |     let ans = s(/* isize */);
-   |                ~~~~~~~~~~~~~
+LL -     let ans = s("burma", "shave");
+LL +     let ans = s(/* isize */);
+   |
 
 error[E0308]: mismatched types
   --> $DIR/overloaded-calls-bad.rs:40:7
diff --git a/tests/ui/issues/issue-22536-copy-mustnt-zero.rs b/tests/ui/moves/issue-22536-copy-mustnt-zero.rs
index 017f36484c1..017f36484c1 100644
--- a/tests/ui/issues/issue-22536-copy-mustnt-zero.rs
+++ b/tests/ui/moves/issue-22536-copy-mustnt-zero.rs
diff --git a/tests/ui/issues/issue-27583.rs b/tests/ui/nll/issue-27583.rs
index 84c94c7c905..84c94c7c905 100644
--- a/tests/ui/issues/issue-27583.rs
+++ b/tests/ui/nll/issue-27583.rs
diff --git a/tests/ui/issues/issue-48179.rs b/tests/ui/nll/issue-48179.rs
index f81203dc412..f81203dc412 100644
--- a/tests/ui/issues/issue-48179.rs
+++ b/tests/ui/nll/issue-48179.rs
diff --git a/tests/ui/issues/issue-75777.rs b/tests/ui/nll/issue-75777.rs
index a1e438bc617..a1e438bc617 100644
--- a/tests/ui/issues/issue-75777.rs
+++ b/tests/ui/nll/issue-75777.rs
diff --git a/tests/ui/issues/issue-75777.stderr b/tests/ui/nll/issue-75777.stderr
index 370cd72fd55..370cd72fd55 100644
--- a/tests/ui/issues/issue-75777.stderr
+++ b/tests/ui/nll/issue-75777.stderr
diff --git a/tests/ui/parser/numeric-lifetime.rs b/tests/ui/parser/numeric-lifetime.rs
index 2d82354c62c..a082a8a44df 100644
--- a/tests/ui/parser/numeric-lifetime.rs
+++ b/tests/ui/parser/numeric-lifetime.rs
@@ -1,6 +1,6 @@
 struct S<'1> { s: &'1 usize }
-//~^ ERROR lifetimes cannot start with a number
-//~| ERROR lifetimes cannot start with a number
+//~^ ERROR lifetimes or labels cannot start with a number
+//~| ERROR lifetimes or labels cannot start with a number
 fn main() {
     // verify that the parse error doesn't stop type checking
     let x: usize = "";
diff --git a/tests/ui/parser/numeric-lifetime.stderr b/tests/ui/parser/numeric-lifetime.stderr
index 7c1bcb72631..66e35dca923 100644
--- a/tests/ui/parser/numeric-lifetime.stderr
+++ b/tests/ui/parser/numeric-lifetime.stderr
@@ -6,13 +6,13 @@ LL |     let x: usize = "";
    |            |
    |            expected due to this
 
-error: lifetimes cannot start with a number
+error: lifetimes or labels cannot start with a number
   --> $DIR/numeric-lifetime.rs:1:10
    |
 LL | struct S<'1> { s: &'1 usize }
    |          ^^
 
-error: lifetimes cannot start with a number
+error: lifetimes or labels cannot start with a number
   --> $DIR/numeric-lifetime.rs:1:20
    |
 LL | struct S<'1> { s: &'1 usize }
diff --git a/tests/ui/parser/recover-fn-ptr-with-generics.stderr b/tests/ui/parser/recover-fn-ptr-with-generics.stderr
index 1da9c18571b..069fcffe9a0 100644
--- a/tests/ui/parser/recover-fn-ptr-with-generics.stderr
+++ b/tests/ui/parser/recover-fn-ptr-with-generics.stderr
@@ -88,12 +88,6 @@ error: expected identifier, found `>`
 LL |     type QuiteBroken = fn<const>();
    |                                ^ expected identifier
 
-error: lifetime bounds cannot be used in this context
-  --> $DIR/recover-fn-ptr-with-generics.rs:22:26
-   |
-LL |     let _: extern fn<'a: 'static>();
-   |                          ^^^^^^^
-
 error[E0412]: cannot find type `T` in this scope
   --> $DIR/recover-fn-ptr-with-generics.rs:5:27
    |
@@ -106,6 +100,12 @@ error[E0412]: cannot find type `T` in this scope
 LL |     type Identity = fn<T>(T) -> T;
    |                                 ^ not found in this scope
 
+error: lifetime bounds cannot be used in this context
+  --> $DIR/recover-fn-ptr-with-generics.rs:22:26
+   |
+LL |     let _: extern fn<'a: 'static>();
+   |                          ^^^^^^^
+
 error: aborting due to 12 previous errors
 
 For more information about this error, try `rustc --explain E0412`.
diff --git a/tests/ui/issues/issue-40003.rs b/tests/ui/recursion_limit/issue-40003.rs
index 5e61361f987..5e61361f987 100644
--- a/tests/ui/issues/issue-40003.rs
+++ b/tests/ui/recursion_limit/issue-40003.rs
diff --git a/tests/ui/repr/16-bit-repr-c-enum.rs b/tests/ui/repr/16-bit-repr-c-enum.rs
new file mode 100644
index 00000000000..2acfde4be46
--- /dev/null
+++ b/tests/ui/repr/16-bit-repr-c-enum.rs
@@ -0,0 +1,52 @@
+// build-pass
+// revisions: avr msp430
+//
+// [avr] needs-llvm-components: avr
+// [avr] compile-flags: --target=avr-unknown-gnu-atmega328 --crate-type=rlib
+// [msp430] needs-llvm-components: msp430
+// [msp430] compile-flags: --target=msp430-none-elf --crate-type=rlib
+#![feature(no_core, lang_items, intrinsics, staged_api)]
+#![no_core]
+#![crate_type = "lib"]
+#![stable(feature = "", since = "")]
+#![allow(dead_code)]
+
+// Test that the repr(C) attribute doesn't break compilation
+// Previous bad assumption was that 32-bit enum default width is fine on msp430, avr
+// But the width of the C int on these platforms is 16 bits, and C enums <= C int range
+// so we want no more than that, usually. This resulted in errors like
+// "layout decided on a larger discriminant type (I32) than typeck (I16)"
+#[repr(C)]
+enum Foo {
+    Bar,
+}
+
+extern "rust-intrinsic" {
+    #[stable(feature = "", since = "")]
+    #[rustc_const_stable(feature = "", since = "")]
+    #[rustc_safe_intrinsic]
+    fn size_of<T>() -> usize;
+}
+
+#[lang="sized"]
+trait Sized {}
+#[lang="copy"]
+trait Copy {}
+
+const EXPECTED: usize = 2;
+const ACTUAL: usize = size_of::<Foo>();
+// Validate that the size is indeed 16 bits, to match this C static_assert:
+/**
+```c
+#include <assert.h>
+enum foo {
+    BAR
+};
+int main(void)
+{
+    /* passes on msp430-elf-gcc */
+    static_assert(sizeof(enum foo) == 2);
+}
+```
+*/
+const _: [(); EXPECTED] = [(); ACTUAL];
diff --git a/tests/ui/resolve/resolve-primitive-fallback.stderr b/tests/ui/resolve/resolve-primitive-fallback.stderr
index 964302e924c..f803f9da2af 100644
--- a/tests/ui/resolve/resolve-primitive-fallback.stderr
+++ b/tests/ui/resolve/resolve-primitive-fallback.stderr
@@ -24,14 +24,13 @@ error[E0061]: this function takes 0 arguments but 1 argument was supplied
   --> $DIR/resolve-primitive-fallback.rs:3:5
    |
 LL |     std::mem::size_of(u16);
-   |     ^^^^^^^^^^^^^^^^^ --- argument unexpected
+   |     ^^^^^^^^^^^^^^^^^ ---
+   |                       |
+   |                       unexpected argument
+   |                       help: remove the extra argument
    |
 note: function defined here
   --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
-help: remove the extra argument
-   |
-LL |     std::mem::size_of();
-   |                      ~~
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/sanitize/cfg-kasan.rs b/tests/ui/sanitize/cfg-kasan.rs
new file mode 100644
index 00000000000..d721011f3ee
--- /dev/null
+++ b/tests/ui/sanitize/cfg-kasan.rs
@@ -0,0 +1,28 @@
+// Verifies that when compiling with -Zsanitizer=kernel-address,
+// the `#[cfg(sanitize = "address")]` attribute is configured.
+
+// check-pass
+// compile-flags: -Zsanitizer=kernel-address --cfg kernel_address
+// revisions: aarch64 riscv64imac riscv64gc x86_64
+//[aarch64] compile-flags: --target aarch64-unknown-none
+//[aarch64] needs-llvm-components: aarch64
+//[riscv64imac] compile-flags: --target riscv64imac-unknown-none-elf
+//[riscv64imac] needs-llvm-components: riscv
+//[riscv64imac] min-llvm-version: 16
+//[riscv64gc] compile-flags: --target riscv64gc-unknown-none-elf
+//[riscv64gc] needs-llvm-components: riscv
+//[riscv64gc] min-llvm-version: 16
+//[x86_64] compile-flags: --target x86_64-unknown-none
+//[x86_64] needs-llvm-components: x86
+
+#![crate_type = "rlib"]
+#![feature(cfg_sanitize, no_core, lang_items)]
+#![no_core]
+
+#[lang = "sized"]
+trait Sized {}
+
+const _: fn() -> () = main;
+
+#[cfg(all(sanitize = "address", kernel_address))]
+fn main() {}
diff --git a/tests/ui/span/issue-34264.stderr b/tests/ui/span/issue-34264.stderr
index 15179954adc..f0dea66f612 100644
--- a/tests/ui/span/issue-34264.stderr
+++ b/tests/ui/span/issue-34264.stderr
@@ -54,17 +54,16 @@ error[E0061]: this function takes 2 arguments but 3 arguments were supplied
   --> $DIR/issue-34264.rs:7:5
    |
 LL |     foo(Some(42), 2, "");
-   |     ^^^              -- argument of type `&'static str` unexpected
+   |     ^^^            ----
+   |                    | |
+   |                    | unexpected argument of type `&'static str`
+   |                    help: remove the extra argument
    |
 note: function defined here
   --> $DIR/issue-34264.rs:1:4
    |
 LL | fn foo(Option<i32>, String) {}
    |    ^^^ -----------  ------
-help: remove the extra argument
-   |
-LL |     foo(Some(42), 2);
-   |        ~~~~~~~~~~~~~
 
 error[E0308]: mismatched types
   --> $DIR/issue-34264.rs:8:13
@@ -84,17 +83,16 @@ error[E0061]: this function takes 2 arguments but 3 arguments were supplied
   --> $DIR/issue-34264.rs:10:5
    |
 LL |     bar(1, 2, 3);
-   |     ^^^       - argument of type `{integer}` unexpected
+   |     ^^^     ---
+   |             | |
+   |             | unexpected argument of type `{integer}`
+   |             help: remove the extra argument
    |
 note: function defined here
   --> $DIR/issue-34264.rs:3:4
    |
 LL | fn bar(x, y: usize) {}
    |    ^^^ -  --------
-help: remove the extra argument
-   |
-LL |     bar(1, 2);
-   |        ~~~~~~
 
 error: aborting due to 6 previous errors
 
diff --git a/tests/ui/suggestions/args-instead-of-tuple-errors.stderr b/tests/ui/suggestions/args-instead-of-tuple-errors.stderr
index e9736363816..510b99bb5af 100644
--- a/tests/ui/suggestions/args-instead-of-tuple-errors.stderr
+++ b/tests/ui/suggestions/args-instead-of-tuple-errors.stderr
@@ -2,7 +2,7 @@ error[E0061]: this enum variant takes 1 argument but 2 arguments were supplied
   --> $DIR/args-instead-of-tuple-errors.rs:6:34
    |
 LL |     let _: Option<(i32, bool)> = Some(1, 2);
-   |                                  ^^^^    - argument of type `{integer}` unexpected
+   |                                  ^^^^    - unexpected argument of type `{integer}`
    |
 note: expected `(i32, bool)`, found integer
   --> $DIR/args-instead-of-tuple-errors.rs:6:39
@@ -22,14 +22,15 @@ note: tuple variant defined here
   --> $SRC_DIR/core/src/option.rs:LL:COL
 help: remove the extra argument
    |
-LL |     let _: Option<(i32, bool)> = Some(/* (i32, bool) */);
-   |                                      ~~~~~~~~~~~~~~~~~~~
+LL -     let _: Option<(i32, bool)> = Some(1, 2);
+LL +     let _: Option<(i32, bool)> = Some(/* (i32, bool) */);
+   |
 
 error[E0061]: this function takes 1 argument but 2 arguments were supplied
   --> $DIR/args-instead-of-tuple-errors.rs:8:5
    |
 LL |     int_bool(1, 2);
-   |     ^^^^^^^^    - argument of type `{integer}` unexpected
+   |     ^^^^^^^^    - unexpected argument of type `{integer}`
    |
 note: expected `(i32, bool)`, found integer
   --> $DIR/args-instead-of-tuple-errors.rs:8:14
@@ -45,8 +46,9 @@ LL | fn int_bool(_: (i32, bool)) {
    |    ^^^^^^^^ --------------
 help: remove the extra argument
    |
-LL |     int_bool(/* (i32, bool) */);
-   |             ~~~~~~~~~~~~~~~~~~~
+LL -     int_bool(1, 2);
+LL +     int_bool(/* (i32, bool) */);
+   |
 
 error[E0061]: this enum variant takes 1 argument but 0 arguments were supplied
   --> $DIR/args-instead-of-tuple-errors.rs:11:28
diff --git a/tests/ui/traits/alias/issue-108072-unmet-trait-alias-bound.rs b/tests/ui/traits/alias/issue-108072-unmet-trait-alias-bound.rs
new file mode 100644
index 00000000000..d254c0ae3ef
--- /dev/null
+++ b/tests/ui/traits/alias/issue-108072-unmet-trait-alias-bound.rs
@@ -0,0 +1,11 @@
+// Regression test for #108072: do not ICE upon unmet trait alias constraint
+
+#![feature(trait_alias)]
+
+trait IteratorAlias = Iterator;
+
+fn f(_: impl IteratorAlias) {}
+
+fn main() {
+    f(()) //~ `()` is not an iterator
+}
diff --git a/tests/ui/traits/alias/issue-108072-unmet-trait-alias-bound.stderr b/tests/ui/traits/alias/issue-108072-unmet-trait-alias-bound.stderr
new file mode 100644
index 00000000000..39f974f962c
--- /dev/null
+++ b/tests/ui/traits/alias/issue-108072-unmet-trait-alias-bound.stderr
@@ -0,0 +1,19 @@
+error[E0277]: `()` is not an iterator
+  --> $DIR/issue-108072-unmet-trait-alias-bound.rs:10:7
+   |
+LL |     f(())
+   |     - ^^ `()` is not an iterator
+   |     |
+   |     required by a bound introduced by this call
+   |
+   = help: the trait `Iterator` is not implemented for `()`
+   = note: required for `()` to implement `IteratorAlias`
+note: required by a bound in `f`
+  --> $DIR/issue-108072-unmet-trait-alias-bound.rs:7:14
+   |
+LL | fn f(_: impl IteratorAlias) {}
+   |              ^^^^^^^^^^^^^ required by this bound in `f`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/alias/issue-108132-unmet-trait-alias-bound-on-generic-impl.rs b/tests/ui/traits/alias/issue-108132-unmet-trait-alias-bound-on-generic-impl.rs
new file mode 100644
index 00000000000..0b1f9ab57c9
--- /dev/null
+++ b/tests/ui/traits/alias/issue-108132-unmet-trait-alias-bound-on-generic-impl.rs
@@ -0,0 +1,15 @@
+// Regression test for #108132: do not ICE upon unmet trait alias constraint in generic impl
+
+#![feature(trait_alias)]
+
+trait IteratorAlias = Iterator;
+
+struct Foo<I>(I);
+
+impl<I: IteratorAlias> Foo<I> {
+    fn f() {}
+}
+
+fn main() {
+    Foo::<()>::f() //~ trait bounds were not satisfied
+}
diff --git a/tests/ui/traits/alias/issue-108132-unmet-trait-alias-bound-on-generic-impl.stderr b/tests/ui/traits/alias/issue-108132-unmet-trait-alias-bound-on-generic-impl.stderr
new file mode 100644
index 00000000000..f1b259d5a65
--- /dev/null
+++ b/tests/ui/traits/alias/issue-108132-unmet-trait-alias-bound-on-generic-impl.stderr
@@ -0,0 +1,25 @@
+error[E0599]: the function or associated item `f` exists for struct `Foo<()>`, but its trait bounds were not satisfied
+  --> $DIR/issue-108132-unmet-trait-alias-bound-on-generic-impl.rs:14:16
+   |
+LL | struct Foo<I>(I);
+   | ------------- function or associated item `f` not found for this struct
+...
+LL |     Foo::<()>::f()
+   |                ^ function or associated item cannot be called on `Foo<()>` due to unsatisfied trait bounds
+   |
+note: trait bound `(): Iterator` was not satisfied
+  --> $DIR/issue-108132-unmet-trait-alias-bound-on-generic-impl.rs:5:23
+   |
+LL | trait IteratorAlias = Iterator;
+   |       -------------   ^^^^^^^^ unsatisfied trait bound introduced here
+note: trait bound `(): IteratorAlias` was not satisfied
+  --> $DIR/issue-108132-unmet-trait-alias-bound-on-generic-impl.rs:9:9
+   |
+LL | impl<I: IteratorAlias> Foo<I> {
+   |         ^^^^^^^^^^^^^  ------
+   |         |
+   |         unsatisfied trait bound introduced here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/tests/ui/traits/non_lifetime_binders/basic.rs b/tests/ui/traits/non_lifetime_binders/basic.rs
new file mode 100644
index 00000000000..a797aae65db
--- /dev/null
+++ b/tests/ui/traits/non_lifetime_binders/basic.rs
@@ -0,0 +1,19 @@
+// check-pass
+// Basic test that show's we can succesfully typeck a `for<T>` where clause.
+
+#![feature(non_lifetime_binders)]
+//~^ WARN the feature `non_lifetime_binders` is incomplete
+
+trait Trait {}
+
+impl<T: ?Sized> Trait for T {}
+
+fn foo()
+where
+    for<T> T: Trait,
+{
+}
+
+fn main() {
+    foo();
+}
diff --git a/tests/ui/traits/non_lifetime_binders/basic.stderr b/tests/ui/traits/non_lifetime_binders/basic.stderr
new file mode 100644
index 00000000000..0fd16c5d0ee
--- /dev/null
+++ b/tests/ui/traits/non_lifetime_binders/basic.stderr
@@ -0,0 +1,11 @@
+warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/basic.rs:4:12
+   |
+LL | #![feature(non_lifetime_binders)]
+   |            ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/traits/non_lifetime_binders/fail.rs b/tests/ui/traits/non_lifetime_binders/fail.rs
new file mode 100644
index 00000000000..460f68907e8
--- /dev/null
+++ b/tests/ui/traits/non_lifetime_binders/fail.rs
@@ -0,0 +1,23 @@
+// Error reporting for where `for<T> T: Trait` doesn't hold
+
+#![feature(non_lifetime_binders)]
+//~^ WARN the feature `non_lifetime_binders` is incomplete
+
+trait Trait {}
+
+fn fail()
+where
+    for<T> T: Trait,
+{}
+
+fn auto_trait()
+where
+    for<T> T: Send,
+{}
+
+fn main() {
+    fail();
+    //~^ ERROR the trait bound `T: Trait` is not satisfied
+    auto_trait();
+    //~^ ERROR `T` cannot be sent between threads safely
+}
diff --git a/tests/ui/traits/non_lifetime_binders/fail.stderr b/tests/ui/traits/non_lifetime_binders/fail.stderr
new file mode 100644
index 00000000000..c3f4fd6a88e
--- /dev/null
+++ b/tests/ui/traits/non_lifetime_binders/fail.stderr
@@ -0,0 +1,43 @@
+warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/fail.rs:3:12
+   |
+LL | #![feature(non_lifetime_binders)]
+   |            ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+error[E0277]: the trait bound `T: Trait` is not satisfied
+  --> $DIR/fail.rs:19:5
+   |
+LL |     fail();
+   |     ^^^^ the trait `Trait` is not implemented for `T`
+   |
+note: required by a bound in `fail`
+  --> $DIR/fail.rs:10:15
+   |
+LL | fn fail()
+   |    ---- required by a bound in this
+LL | where
+LL |     for<T> T: Trait,
+   |               ^^^^^ required by this bound in `fail`
+
+error[E0277]: `T` cannot be sent between threads safely
+  --> $DIR/fail.rs:21:5
+   |
+LL |     auto_trait();
+   |     ^^^^^^^^^^ `T` cannot be sent between threads safely
+   |
+   = help: the trait `Send` is not implemented for `T`
+note: required by a bound in `auto_trait`
+  --> $DIR/fail.rs:15:15
+   |
+LL | fn auto_trait()
+   |    ---------- required by a bound in this
+LL | where
+LL |     for<T> T: Send,
+   |               ^^^^ required by this bound in `auto_trait`
+
+error: aborting due to 2 previous errors; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/non_lifetime_binders/on-dyn.rs b/tests/ui/traits/non_lifetime_binders/on-dyn.rs
new file mode 100644
index 00000000000..8fb7dd27605
--- /dev/null
+++ b/tests/ui/traits/non_lifetime_binders/on-dyn.rs
@@ -0,0 +1,13 @@
+// Tests to make sure that we reject polymorphic dyn trait.
+
+#![feature(non_lifetime_binders)]
+//~^ WARN the feature `non_lifetime_binders` is incomplete
+
+trait Test<T> {}
+
+fn foo() -> &'static dyn for<T> Test<T> {
+    //~^ ERROR late-bound type parameter not allowed on trait object types
+    todo!()
+}
+
+fn main() {}
diff --git a/tests/ui/traits/non_lifetime_binders/on-dyn.stderr b/tests/ui/traits/non_lifetime_binders/on-dyn.stderr
new file mode 100644
index 00000000000..95656f99976
--- /dev/null
+++ b/tests/ui/traits/non_lifetime_binders/on-dyn.stderr
@@ -0,0 +1,17 @@
+warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/on-dyn.rs:3:12
+   |
+LL | #![feature(non_lifetime_binders)]
+   |            ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+error: late-bound type parameter not allowed on trait object types
+  --> $DIR/on-dyn.rs:8:30
+   |
+LL | fn foo() -> &'static dyn for<T> Test<T> {
+   |                              ^
+
+error: aborting due to previous error; 1 warning emitted
+
diff --git a/tests/ui/traits/non_lifetime_binders/on-ptr.rs b/tests/ui/traits/non_lifetime_binders/on-ptr.rs
new file mode 100644
index 00000000000..0aaff52b6d8
--- /dev/null
+++ b/tests/ui/traits/non_lifetime_binders/on-ptr.rs
@@ -0,0 +1,13 @@
+// Tests to make sure that we reject polymorphic fn ptrs.
+
+#![feature(non_lifetime_binders)]
+//~^ WARN the feature `non_lifetime_binders` is incomplete
+
+fn foo() -> for<T> fn(T) {
+    //~^ ERROR late-bound type parameter not allowed on function pointer types
+    todo!()
+}
+
+fn main() {
+    foo()(1i32);
+}
diff --git a/tests/ui/traits/non_lifetime_binders/on-ptr.stderr b/tests/ui/traits/non_lifetime_binders/on-ptr.stderr
new file mode 100644
index 00000000000..3b17f7697b2
--- /dev/null
+++ b/tests/ui/traits/non_lifetime_binders/on-ptr.stderr
@@ -0,0 +1,17 @@
+warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/on-ptr.rs:3:12
+   |
+LL | #![feature(non_lifetime_binders)]
+   |            ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+error: late-bound type parameter not allowed on function pointer types
+  --> $DIR/on-ptr.rs:6:17
+   |
+LL | fn foo() -> for<T> fn(T) {
+   |                 ^
+
+error: aborting due to previous error; 1 warning emitted
+
diff --git a/tests/ui/tuple/wrong_argument_ice-3.stderr b/tests/ui/tuple/wrong_argument_ice-3.stderr
index 75dfe716395..7143c959478 100644
--- a/tests/ui/tuple/wrong_argument_ice-3.stderr
+++ b/tests/ui/tuple/wrong_argument_ice-3.stderr
@@ -2,7 +2,7 @@ error[E0061]: this method takes 1 argument but 2 arguments were supplied
   --> $DIR/wrong_argument_ice-3.rs:9:16
    |
 LL |         groups.push(new_group, vec![process]);
-   |                ^^^^            ------------- argument of type `Vec<&Process>` unexpected
+   |                ^^^^            ------------- unexpected argument of type `Vec<&Process>`
    |
 note: expected `(Vec<String>, Vec<Process>)`, found `Vec<String>`
   --> $DIR/wrong_argument_ice-3.rs:9:21
@@ -15,8 +15,9 @@ note: associated function defined here
   --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
 help: remove the extra argument
    |
-LL |         groups.push(/* (Vec<String>, Vec<Process>) */);
-   |                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+LL -         groups.push(new_group, vec![process]);
+LL +         groups.push(/* (Vec<String>, Vec<Process>) */);
+   |
 
 error: aborting due to previous error
 
diff --git a/tests/ui/tuple/wrong_argument_ice-4.stderr b/tests/ui/tuple/wrong_argument_ice-4.stderr
index a2686ab9440..d8569ebf6b6 100644
--- a/tests/ui/tuple/wrong_argument_ice-4.stderr
+++ b/tests/ui/tuple/wrong_argument_ice-4.stderr
@@ -6,17 +6,16 @@ LL |       (|| {})(|| {
 LL | |
 LL | |         let b = 1;
 LL | |     });
-   | |_____- argument of type `[closure@$DIR/wrong_argument_ice-4.rs:2:13: 2:15]` unexpected
+   | |     -
+   | |     |
+   | |_____unexpected argument of type `[closure@$DIR/wrong_argument_ice-4.rs:2:13: 2:15]`
+   |       help: remove the extra argument
    |
 note: closure defined here
   --> $DIR/wrong_argument_ice-4.rs:2:6
    |
 LL |     (|| {})(|| {
    |      ^^
-help: remove the extra argument
-   |
-LL |     (|| {})();
-   |            ~~
 
 error: aborting due to previous error
 
diff --git a/tests/ui/type/type-ascription-instead-of-initializer.stderr b/tests/ui/type/type-ascription-instead-of-initializer.stderr
index ba8d15d0b73..429501c2762 100644
--- a/tests/ui/type/type-ascription-instead-of-initializer.stderr
+++ b/tests/ui/type/type-ascription-instead-of-initializer.stderr
@@ -11,14 +11,13 @@ error[E0061]: this function takes 1 argument but 2 arguments were supplied
   --> $DIR/type-ascription-instead-of-initializer.rs:2:12
    |
 LL |     let x: Vec::with_capacity(10, 20);
-   |            ^^^^^^^^^^^^^^^^^^     -- argument of type `{integer}` unexpected
+   |            ^^^^^^^^^^^^^^^^^^   ----
+   |                                 | |
+   |                                 | unexpected argument of type `{integer}`
+   |                                 help: remove the extra argument
    |
 note: associated function defined here
   --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
-help: remove the extra argument
-   |
-LL |     let x: Vec::with_capacity(10);
-   |                              ~~~~
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/issues/issue-53712.rs b/tests/ui/typeck/issue-53712.rs
index 2353904d79d..2353904d79d 100644
--- a/tests/ui/issues/issue-53712.rs
+++ b/tests/ui/typeck/issue-53712.rs
diff --git a/tests/ui/issues/issue-53712.stderr b/tests/ui/typeck/issue-53712.stderr
index db85919afcb..db85919afcb 100644
--- a/tests/ui/issues/issue-53712.stderr
+++ b/tests/ui/typeck/issue-53712.stderr
diff --git a/tests/ui/issues/issue-7813.rs b/tests/ui/typeck/issue-7813.rs
index ce549bde601..ce549bde601 100644
--- a/tests/ui/issues/issue-7813.rs
+++ b/tests/ui/typeck/issue-7813.rs
diff --git a/tests/ui/issues/issue-7813.stderr b/tests/ui/typeck/issue-7813.stderr
index 2a747f679a8..2a747f679a8 100644
--- a/tests/ui/issues/issue-7813.stderr
+++ b/tests/ui/typeck/issue-7813.stderr
diff --git a/tests/ui/typeck/remove-extra-argument.stderr b/tests/ui/typeck/remove-extra-argument.stderr
index b734bcd4eb0..72ddebab486 100644
--- a/tests/ui/typeck/remove-extra-argument.stderr
+++ b/tests/ui/typeck/remove-extra-argument.stderr
@@ -2,17 +2,16 @@ error[E0061]: this function takes 1 argument but 2 arguments were supplied
   --> $DIR/remove-extra-argument.rs:6:5
    |
 LL |     l(vec![], vec![])
-   |     ^         ------ argument of type `Vec<_>` unexpected
+   |     ^       --------
+   |             | |
+   |             | unexpected argument of type `Vec<_>`
+   |             help: remove the extra argument
    |
 note: function defined here
   --> $DIR/remove-extra-argument.rs:3:4
    |
 LL | fn l(_a: Vec<u8>) {}
    |    ^ -----------
-help: remove the extra argument
-   |
-LL |     l(vec![])
-   |      ~~~~~~~~
 
 error: aborting due to previous error
 
diff --git a/tests/ui/typeck/struct-enum-wrong-args.stderr b/tests/ui/typeck/struct-enum-wrong-args.stderr
index fbced928a8a..57cbd1d2005 100644
--- a/tests/ui/typeck/struct-enum-wrong-args.stderr
+++ b/tests/ui/typeck/struct-enum-wrong-args.stderr
@@ -2,29 +2,29 @@ error[E0061]: this enum variant takes 1 argument but 2 arguments were supplied
   --> $DIR/struct-enum-wrong-args.rs:6:13
    |
 LL |     let _ = Some(3, 2);
-   |             ^^^^    - argument of type `{integer}` unexpected
+   |             ^^^^  ---
+   |                   | |
+   |                   | unexpected argument of type `{integer}`
+   |                   help: remove the extra argument
    |
 note: tuple variant defined here
   --> $SRC_DIR/core/src/option.rs:LL:COL
-help: remove the extra argument
-   |
-LL |     let _ = Some(3);
-   |                 ~~~
 
 error[E0061]: this enum variant takes 1 argument but 3 arguments were supplied
   --> $DIR/struct-enum-wrong-args.rs:7:13
    |
 LL |     let _ = Ok(3, 6, 2);
-   |             ^^    -  - argument of type `{integer}` unexpected
+   |             ^^    -  - unexpected argument of type `{integer}`
    |                   |
-   |                   argument of type `{integer}` unexpected
+   |                   unexpected argument of type `{integer}`
    |
 note: tuple variant defined here
   --> $SRC_DIR/core/src/result.rs:LL:COL
 help: remove the extra arguments
    |
-LL |     let _ = Ok(3);
-   |               ~~~
+LL -     let _ = Ok(3, 6, 2);
+LL +     let _ = Ok(3);
+   |
 
 error[E0061]: this enum variant takes 1 argument but 0 arguments were supplied
   --> $DIR/struct-enum-wrong-args.rs:8:13
@@ -59,17 +59,16 @@ error[E0061]: this struct takes 1 argument but 2 arguments were supplied
   --> $DIR/struct-enum-wrong-args.rs:10:13
    |
 LL |     let _ = Wrapper(5, 2);
-   |             ^^^^^^^    - argument of type `{integer}` unexpected
+   |             ^^^^^^^  ---
+   |                      | |
+   |                      | unexpected argument of type `{integer}`
+   |                      help: remove the extra argument
    |
 note: tuple struct defined here
   --> $DIR/struct-enum-wrong-args.rs:2:8
    |
 LL | struct Wrapper(i32);
    |        ^^^^^^^
-help: remove the extra argument
-   |
-LL |     let _ = Wrapper(5);
-   |                    ~~~
 
 error[E0061]: this struct takes 2 arguments but 0 arguments were supplied
   --> $DIR/struct-enum-wrong-args.rs:11:13
@@ -107,17 +106,16 @@ error[E0061]: this struct takes 2 arguments but 3 arguments were supplied
   --> $DIR/struct-enum-wrong-args.rs:13:13
    |
 LL |     let _ = DoubleWrapper(5, 2, 7);
-   |             ^^^^^^^^^^^^^       - argument of type `{integer}` unexpected
+   |             ^^^^^^^^^^^^^     ---
+   |                               | |
+   |                               | unexpected argument of type `{integer}`
+   |                               help: remove the extra argument
    |
 note: tuple struct defined here
   --> $DIR/struct-enum-wrong-args.rs:3:8
    |
 LL | struct DoubleWrapper(i32, i32);
    |        ^^^^^^^^^^^^^
-help: remove the extra argument
-   |
-LL |     let _ = DoubleWrapper(5, 2);
-   |                          ~~~~~~
 
 error: aborting due to 8 previous errors
 
diff --git a/triagebot.toml b/triagebot.toml
index 883bc8720e2..7a26457ab04 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -538,6 +538,7 @@ diagnostics = [
     "@TaKO8Ki",
 ]
 parser = [
+    "@compiler-errors",
     "@davidtwco",
     "@nnethercote",
     "@petrochenkov",
@@ -567,6 +568,7 @@ borrowck = [
     "@pnkfelix",
 ]
 ast_lowering = [
+    "@compiler-errors",
     "@spastorino",
 ]
 fallback = [
@@ -630,7 +632,7 @@ style-team = [
 "/src/stage0.json" =                         ["bootstrap"]
 "/tests/ui" =                                ["compiler"]
 "/src/tools/cargo" =                         ["@ehuss", "@joshtriplett"]
-"/src/tools/compiletest" =                   ["bootstrap"]
+"/src/tools/compiletest" =                   ["bootstrap", "@wesleywiser", "@oli-obk", "@compiler-errors"]
 "/src/tools/linkchecker" =                   ["@ehuss"]
 "/src/tools/rust-installer" =                ["bootstrap"]
 "/src/tools/rustbook" =                      ["@ehuss"]