about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_abi/src/layout.rs61
-rw-r--r--compiler/rustc_abi/src/lib.rs33
-rw-r--r--compiler/rustc_ast/src/token.rs2
-rw-r--r--compiler/rustc_ast_lowering/src/asm.rs7
-rw-r--r--compiler/rustc_borrowck/src/constraint_generation.rs10
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs121
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs6
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/mod.rs32
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/move_errors.rs14
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs97
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/region_errors.rs75
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/region_name.rs46
-rw-r--r--compiler/rustc_borrowck/src/lib.rs2
-rw-r--r--compiler/rustc_borrowck/src/region_infer/mod.rs34
-rw-r--r--compiler/rustc_borrowck/src/region_infer/opaque_types.rs36
-rw-r--r--compiler/rustc_borrowck/src/renumber.rs8
-rw-r--r--compiler/rustc_borrowck/src/type_check/constraint_conversion.rs10
-rw-r--r--compiler/rustc_borrowck/src/type_check/liveness/polonius.rs2
-rw-r--r--compiler/rustc_borrowck/src/type_check/mod.rs135
-rw-r--r--compiler/rustc_borrowck/src/type_check/relate_tys.rs6
-rw-r--r--compiler/rustc_borrowck/src/universal_regions.rs156
-rw-r--r--compiler/rustc_builtin_macros/src/asm.rs3
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs4
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs4
-rw-r--r--compiler/rustc_builtin_macros/src/env.rs7
-rw-r--r--compiler/rustc_builtin_macros/src/proc_macro_harness.rs4
-rw-r--r--compiler/rustc_codegen_cranelift/src/abi/comments.rs9
-rw-r--r--compiler/rustc_codegen_cranelift/src/abi/mod.rs12
-rw-r--r--compiler/rustc_codegen_cranelift/src/base.rs10
-rw-r--r--compiler/rustc_codegen_cranelift/src/constant.rs2
-rw-r--r--compiler/rustc_codegen_cranelift/src/global_asm.rs2
-rw-r--r--compiler/rustc_codegen_cranelift/src/inline_asm.rs4
-rw-r--r--compiler/rustc_codegen_cranelift/src/intrinsics/llvm.rs20
-rw-r--r--compiler/rustc_codegen_cranelift/src/intrinsics/llvm_aarch64.rs4
-rw-r--r--compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs4
-rw-r--r--compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs28
-rw-r--r--compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs4
-rw-r--r--compiler/rustc_codegen_cranelift/src/main_shim.rs6
-rw-r--r--compiler/rustc_codegen_cranelift/src/pretty_clif.rs6
-rw-r--r--compiler/rustc_codegen_cranelift/src/value_and_place.rs12
-rw-r--r--compiler/rustc_codegen_gcc/src/callee.rs6
-rw-r--r--compiler/rustc_codegen_gcc/src/intrinsic/mod.rs8
-rw-r--r--compiler/rustc_codegen_gcc/src/mono_item.rs2
-rw-r--r--compiler/rustc_codegen_gcc/src/type_of.rs4
-rw-r--r--compiler/rustc_codegen_llvm/src/callee.rs6
-rw-r--r--compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs4
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs23
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs18
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs12
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs12
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/mod.rs18
-rw-r--r--compiler/rustc_codegen_llvm/src/intrinsic.rs6
-rw-r--r--compiler/rustc_codegen_llvm/src/mono_item.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/type_of.rs4
-rw-r--r--compiler/rustc_codegen_ssa/src/back/link.rs19
-rw-r--r--compiler/rustc_codegen_ssa/src/back/symbol_export.rs38
-rw-r--r--compiler/rustc_codegen_ssa/src/base.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs42
-rw-r--r--compiler/rustc_codegen_ssa/src/meth.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/block.rs82
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/debuginfo.rs6
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/intrinsic.rs28
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/mod.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/place.rs12
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/rvalue.rs10
-rw-r--r--compiler/rustc_codegen_ssa/src/mono_item.rs4
-rw-r--r--compiler/rustc_codegen_ssa/src/target_features.rs8
-rw-r--r--compiler/rustc_const_eval/src/const_eval/error.rs4
-rw-r--r--compiler/rustc_const_eval/src/const_eval/eval_queries.rs10
-rw-r--r--compiler/rustc_const_eval/src/const_eval/machine.rs2
-rw-r--r--compiler/rustc_const_eval/src/const_eval/mod.rs2
-rw-r--r--compiler/rustc_const_eval/src/const_eval/valtrees.rs4
-rw-r--r--compiler/rustc_const_eval/src/interpret/cast.rs8
-rw-r--r--compiler/rustc_const_eval/src/interpret/discriminant.rs8
-rw-r--r--compiler/rustc_const_eval/src/interpret/eval_context.rs20
-rw-r--r--compiler/rustc_const_eval/src/interpret/intrinsics.rs18
-rw-r--r--compiler/rustc_const_eval/src/interpret/intrinsics/caller_location.rs2
-rw-r--r--compiler/rustc_const_eval/src/interpret/memory.rs6
-rw-r--r--compiler/rustc_const_eval/src/interpret/operand.rs4
-rw-r--r--compiler/rustc_const_eval/src/interpret/place.rs10
-rw-r--r--compiler/rustc_const_eval/src/interpret/terminator.rs41
-rw-r--r--compiler/rustc_const_eval/src/interpret/util.rs8
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/check.rs31
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/mod.rs8
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/ops.rs14
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs20
-rw-r--r--compiler/rustc_const_eval/src/transform/promote_consts.rs16
-rw-r--r--compiler/rustc_const_eval/src/transform/validate.rs36
-rw-r--r--compiler/rustc_const_eval/src/util/type_name.rs13
-rw-r--r--compiler/rustc_data_structures/src/graph/dominators/mod.rs4
-rw-r--r--compiler/rustc_data_structures/src/unord.rs73
-rw-r--r--compiler/rustc_errors/src/markdown/parse.rs2
-rw-r--r--compiler/rustc_errors/src/markdown/term.rs2
-rw-r--r--compiler/rustc_expand/src/base.rs2
-rw-r--r--compiler/rustc_expand/src/config.rs15
-rw-r--r--compiler/rustc_expand/src/expand.rs10
-rw-r--r--compiler/rustc_expand/src/mbe/diagnostics.rs3
-rw-r--r--compiler/rustc_expand/src/mbe/metavar_expr.rs11
-rw-r--r--compiler/rustc_expand/src/mbe/transcribe.rs8
-rw-r--r--compiler/rustc_feature/src/active.rs8
-rw-r--r--compiler/rustc_feature/src/builtin_attrs.rs2
-rw-r--r--compiler/rustc_hir/src/hir.rs12
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/bounds.rs16
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/errors.rs16
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/generics.rs42
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/mod.rs275
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/object_safety.rs18
-rw-r--r--compiler/rustc_hir_analysis/src/check/check.rs76
-rw-r--r--compiler/rustc_hir_analysis/src/check/compare_impl_item.rs181
-rw-r--r--compiler/rustc_hir_analysis/src/check/dropck.rs23
-rw-r--r--compiler/rustc_hir_analysis/src/check/intrinsic.rs8
-rw-r--r--compiler/rustc_hir_analysis/src/check/intrinsicck.rs14
-rw-r--r--compiler/rustc_hir_analysis/src/check/mod.rs22
-rw-r--r--compiler/rustc_hir_analysis/src/check/wfcheck.rs91
-rw-r--r--compiler/rustc_hir_analysis/src/check_unused.rs6
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/builtin.rs38
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/mod.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/orphan.rs26
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/unsafety.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/collect.rs49
-rw-r--r--compiler/rustc_hir_analysis/src/collect/generics_of.rs14
-rw-r--r--compiler/rustc_hir_analysis/src/collect/item_bounds.rs12
-rw-r--r--compiler/rustc_hir_analysis/src/collect/predicates_of.rs51
-rw-r--r--compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs18
-rw-r--r--compiler/rustc_hir_analysis/src/collect/type_of.rs31
-rw-r--r--compiler/rustc_hir_analysis/src/impl_wf_check.rs6
-rw-r--r--compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs80
-rw-r--r--compiler/rustc_hir_analysis/src/lib.rs20
-rw-r--r--compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs31
-rw-r--r--compiler/rustc_hir_analysis/src/outlives/mod.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/outlives/utils.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs55
-rw-r--r--compiler/rustc_hir_analysis/src/variance/constraints.rs40
-rw-r--r--compiler/rustc_hir_analysis/src/variance/mod.rs26
-rw-r--r--compiler/rustc_hir_analysis/src/variance/solve.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/_match.rs49
-rw-r--r--compiler/rustc_hir_typeck/src/callee.rs38
-rw-r--r--compiler/rustc_hir_typeck/src/cast.rs4
-rw-r--r--compiler/rustc_hir_typeck/src/check.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/closure.rs32
-rw-r--r--compiler/rustc_hir_typeck/src/coercion.rs62
-rw-r--r--compiler/rustc_hir_typeck/src/demand.rs256
-rw-r--r--compiler/rustc_hir_typeck/src/expr.rs89
-rw-r--r--compiler/rustc_hir_typeck/src/expr_use_visitor.rs4
-rw-r--r--compiler/rustc_hir_typeck/src/fallback.rs32
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs113
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs124
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs24
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs6
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs92
-rw-r--r--compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_build.rs6
-rw-r--r--compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/mod.rs10
-rw-r--r--compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/record_consumed_borrow.rs8
-rw-r--r--compiler/rustc_hir_typeck/src/inherited.rs6
-rw-r--r--compiler/rustc_hir_typeck/src/intrinsicck.rs4
-rw-r--r--compiler/rustc_hir_typeck/src/lib.rs5
-rw-r--r--compiler/rustc_hir_typeck/src/mem_categorization.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/method/confirm.rs103
-rw-r--r--compiler/rustc_hir_typeck/src/method/mod.rs24
-rw-r--r--compiler/rustc_hir_typeck/src/method/probe.rs82
-rw-r--r--compiler/rustc_hir_typeck/src/method/suggest.rs127
-rw-r--r--compiler/rustc_hir_typeck/src/pat.rs20
-rw-r--r--compiler/rustc_hir_typeck/src/place_op.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/rvalue_scopes.rs4
-rw-r--r--compiler/rustc_hir_typeck/src/upvar.rs80
-rw-r--r--compiler/rustc_hir_typeck/src/writeback.rs172
-rw-r--r--compiler/rustc_incremental/src/persist/fs.rs14
-rw-r--r--compiler/rustc_index/src/bit_set.rs4
-rw-r--r--compiler/rustc_infer/src/errors/mod.rs3
-rw-r--r--compiler/rustc_infer/src/infer/canonical/canonicalizer.rs2
-rw-r--r--compiler/rustc_infer/src/infer/canonical/mod.rs4
-rw-r--r--compiler/rustc_infer/src/infer/canonical/query_response.rs6
-rw-r--r--compiler/rustc_infer/src/infer/canonical/substitute.rs2
-rw-r--r--compiler/rustc_infer/src/infer/combine.rs6
-rw-r--r--compiler/rustc_infer/src/infer/equate.rs12
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/mod.rs68
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs105
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs10
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs24
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs8
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs4
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/note.rs54
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs33
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/suggest.rs60
-rw-r--r--compiler/rustc_infer/src/infer/freshen.rs2
-rw-r--r--compiler/rustc_infer/src/infer/generalize.rs22
-rw-r--r--compiler/rustc_infer/src/infer/mod.rs44
-rw-r--r--compiler/rustc_infer/src/infer/opaque_types.rs51
-rw-r--r--compiler/rustc_infer/src/infer/outlives/components.rs26
-rw-r--r--compiler/rustc_infer/src/infer/outlives/obligations.rs14
-rw-r--r--compiler/rustc_infer/src/infer/outlives/test_type_match.rs2
-rw-r--r--compiler/rustc_infer/src/infer/outlives/verify.rs2
-rw-r--r--compiler/rustc_infer/src/infer/type_variable.rs2
-rw-r--r--compiler/rustc_interface/src/interface.rs3
-rw-r--r--compiler/rustc_lint/src/array_into_iter.rs2
-rw-r--r--compiler/rustc_lint/src/builtin.rs63
-rw-r--r--compiler/rustc_lint/src/cast_ref_to_mut.rs4
-rw-r--r--compiler/rustc_lint/src/context.rs14
-rw-r--r--compiler/rustc_lint/src/deref_into_dyn_supertrait.rs2
-rw-r--r--compiler/rustc_lint/src/enum_intrinsics_non_enums.rs4
-rw-r--r--compiler/rustc_lint/src/for_loops_over_fallibles.rs12
-rw-r--r--compiler/rustc_lint/src/internal.rs24
-rw-r--r--compiler/rustc_lint/src/levels.rs16
-rw-r--r--compiler/rustc_lint/src/methods.rs4
-rw-r--r--compiler/rustc_lint/src/noop_method_call.rs11
-rw-r--r--compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs21
-rw-r--r--compiler/rustc_lint/src/pass_by_value.rs4
-rw-r--r--compiler/rustc_lint/src/traits.rs14
-rw-r--r--compiler/rustc_lint/src/types.rs68
-rw-r--r--compiler/rustc_lint/src/unused.rs39
-rw-r--r--compiler/rustc_lint_defs/src/lib.rs6
-rw-r--r--compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp4
-rw-r--r--compiler/rustc_llvm/llvm-wrapper/SymbolWrapper.cpp1
-rw-r--r--compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs14
-rw-r--r--compiler/rustc_macros/src/diagnostics/subdiagnostic.rs4
-rw-r--r--compiler/rustc_macros/src/newtype.rs6
-rw-r--r--compiler/rustc_metadata/src/creader.rs8
-rw-r--r--compiler/rustc_metadata/src/locator.rs8
-rw-r--r--compiler/rustc_metadata/src/native_libs.rs2
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder.rs24
-rw-r--r--compiler/rustc_metadata/src/rmeta/encoder.rs12
-rw-r--r--compiler/rustc_metadata/src/rmeta/table.rs6
-rw-r--r--compiler/rustc_middle/src/hir/map/mod.rs27
-rw-r--r--compiler/rustc_middle/src/infer/canonical.rs6
-rw-r--r--compiler/rustc_middle/src/infer/mod.rs2
-rw-r--r--compiler/rustc_middle/src/lint.rs20
-rw-r--r--compiler/rustc_middle/src/middle/exported_symbols.rs10
-rw-r--r--compiler/rustc_middle/src/middle/region.rs4
-rw-r--r--compiler/rustc_middle/src/mir/interpret/error.rs2
-rw-r--r--compiler/rustc_middle/src/mir/interpret/mod.rs4
-rw-r--r--compiler/rustc_middle/src/mir/interpret/queries.rs20
-rw-r--r--compiler/rustc_middle/src/mir/mod.rs57
-rw-r--r--compiler/rustc_middle/src/mir/mono.rs14
-rw-r--r--compiler/rustc_middle/src/mir/pretty.rs12
-rw-r--r--compiler/rustc_middle/src/mir/query.rs8
-rw-r--r--compiler/rustc_middle/src/mir/syntax.rs8
-rw-r--r--compiler/rustc_middle/src/mir/tcx.rs12
-rw-r--r--compiler/rustc_middle/src/mir/visit.rs28
-rw-r--r--compiler/rustc_middle/src/query/keys.rs10
-rw-r--r--compiler/rustc_middle/src/query/mod.rs22
-rw-r--r--compiler/rustc_middle/src/thir.rs16
-rw-r--r--compiler/rustc_middle/src/thir/visit.rs10
-rw-r--r--compiler/rustc_middle/src/traits/mod.rs8
-rw-r--r--compiler/rustc_middle/src/traits/query.rs4
-rw-r--r--compiler/rustc_middle/src/traits/solve/inspect.rs8
-rw-r--r--compiler/rustc_middle/src/traits/solve/inspect/format.rs112
-rw-r--r--compiler/rustc_middle/src/traits/specialization_graph.rs4
-rw-r--r--compiler/rustc_middle/src/traits/structural_impls.rs4
-rw-r--r--compiler/rustc_middle/src/ty/abstract_const.rs4
-rw-r--r--compiler/rustc_middle/src/ty/assoc.rs12
-rw-r--r--compiler/rustc_middle/src/ty/closure.rs8
-rw-r--r--compiler/rustc_middle/src/ty/codec.rs8
-rw-r--r--compiler/rustc_middle/src/ty/consts.rs18
-rw-r--r--compiler/rustc_middle/src/ty/consts/int.rs2
-rw-r--r--compiler/rustc_middle/src/ty/consts/kind.rs10
-rw-r--r--compiler/rustc_middle/src/ty/context.rs54
-rw-r--r--compiler/rustc_middle/src/ty/diagnostics.rs10
-rw-r--r--compiler/rustc_middle/src/ty/fast_reject.rs18
-rw-r--r--compiler/rustc_middle/src/ty/flags.rs62
-rw-r--r--compiler/rustc_middle/src/ty/generic_args.rs (renamed from compiler/rustc_middle/src/ty/subst.rs)277
-rw-r--r--compiler/rustc_middle/src/ty/generics.rs44
-rw-r--r--compiler/rustc_middle/src/ty/impls_ty.rs2
-rw-r--r--compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs24
-rw-r--r--compiler/rustc_middle/src/ty/inhabitedness/mod.rs10
-rw-r--r--compiler/rustc_middle/src/ty/instance.rs162
-rw-r--r--compiler/rustc_middle/src/ty/layout.rs25
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs67
-rw-r--r--compiler/rustc_middle/src/ty/normalize_erasing_regions.rs18
-rw-r--r--compiler/rustc_middle/src/ty/opaque_types.rs28
-rw-r--r--compiler/rustc_middle/src/ty/print/mod.rs43
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs138
-rw-r--r--compiler/rustc_middle/src/ty/relate.rs153
-rw-r--r--compiler/rustc_middle/src/ty/rvalue_scopes.rs4
-rw-r--r--compiler/rustc_middle/src/ty/structural_impls.rs34
-rw-r--r--compiler/rustc_middle/src/ty/sty.rs352
-rw-r--r--compiler/rustc_middle/src/ty/trait_def.rs2
-rw-r--r--compiler/rustc_middle/src/ty/typeck_results.rs40
-rw-r--r--compiler/rustc_middle/src/ty/util.rs91
-rw-r--r--compiler/rustc_middle/src/ty/walk.rs28
-rw-r--r--compiler/rustc_middle/src/util/call_kind.rs26
-rw-r--r--compiler/rustc_middle/src/util/find_self_call.rs10
-rw-r--r--compiler/rustc_mir_build/src/build/custom/parse.rs4
-rw-r--r--compiler/rustc_mir_build/src/build/custom/parse/instruction.rs10
-rw-r--r--compiler/rustc_mir_build/src/build/expr/as_constant.rs8
-rw-r--r--compiler/rustc_mir_build/src/build/expr/as_place.rs12
-rw-r--r--compiler/rustc_mir_build/src/build/expr/as_rvalue.rs18
-rw-r--r--compiler/rustc_mir_build/src/build/expr/into.rs4
-rw-r--r--compiler/rustc_mir_build/src/build/matches/mod.rs10
-rw-r--r--compiler/rustc_mir_build/src/build/matches/simplify.rs4
-rw-r--r--compiler/rustc_mir_build/src/build/matches/test.rs12
-rw-r--r--compiler/rustc_mir_build/src/build/mod.rs26
-rw-r--r--compiler/rustc_mir_build/src/build/scope.rs73
-rw-r--r--compiler/rustc_mir_build/src/check_unsafety.rs10
-rw-r--r--compiler/rustc_mir_build/src/lints.rs32
-rw-r--r--compiler/rustc_mir_build/src/thir/cx/expr.rs68
-rw-r--r--compiler/rustc_mir_build/src/thir/cx/mod.rs6
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/check_match.rs8
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs10
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs46
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/mod.rs38
-rw-r--r--compiler/rustc_mir_build/src/thir/print.rs18
-rw-r--r--compiler/rustc_mir_build/src/thir/util.rs2
-rw-r--r--compiler/rustc_mir_dataflow/src/elaborate_drops.rs46
-rw-r--r--compiler/rustc_mir_dataflow/src/impls/mod.rs8
-rw-r--r--compiler/rustc_mir_dataflow/src/rustc_peek.rs6
-rw-r--r--compiler/rustc_mir_dataflow/src/value_analysis.rs8
-rw-r--r--compiler/rustc_mir_transform/src/check_unsafety.rs2
-rw-r--r--compiler/rustc_mir_transform/src/const_prop.rs10
-rw-r--r--compiler/rustc_mir_transform/src/const_prop_lint.rs10
-rw-r--r--compiler/rustc_mir_transform/src/copy_prop.rs8
-rw-r--r--compiler/rustc_mir_transform/src/dataflow_const_prop.rs2
-rw-r--r--compiler/rustc_mir_transform/src/deduce_param_attrs.rs2
-rw-r--r--compiler/rustc_mir_transform/src/dest_prop.rs10
-rw-r--r--compiler/rustc_mir_transform/src/early_otherwise_branch.rs47
-rw-r--r--compiler/rustc_mir_transform/src/elaborate_box_derefs.rs9
-rw-r--r--compiler/rustc_mir_transform/src/function_item_references.rs41
-rw-r--r--compiler/rustc_mir_transform/src/generator.rs48
-rw-r--r--compiler/rustc_mir_transform/src/inline.rs36
-rw-r--r--compiler/rustc_mir_transform/src/inline/cycle.rs16
-rw-r--r--compiler/rustc_mir_transform/src/instsimplify.rs46
-rw-r--r--compiler/rustc_mir_transform/src/large_enums.rs2
-rw-r--r--compiler/rustc_mir_transform/src/lib.rs2
-rw-r--r--compiler/rustc_mir_transform/src/lower_intrinsics.rs17
-rw-r--r--compiler/rustc_mir_transform/src/ref_prop.rs42
-rw-r--r--compiler/rustc_mir_transform/src/remove_uninit_drops.rs21
-rw-r--r--compiler/rustc_mir_transform/src/remove_zsts.rs2
-rw-r--r--compiler/rustc_mir_transform/src/shim.rs56
-rw-r--r--compiler/rustc_mir_transform/src/simplify.rs3
-rw-r--r--compiler/rustc_mir_transform/src/sroa.rs8
-rw-r--r--compiler/rustc_mir_transform/src/ssa.rs8
-rw-r--r--compiler/rustc_mir_transform/src/uninhabited_enum_branching.rs3
-rw-r--r--compiler/rustc_monomorphize/src/collector.rs35
-rw-r--r--compiler/rustc_monomorphize/src/partitioning.rs6
-rw-r--r--compiler/rustc_monomorphize/src/polymorphize.rs25
-rw-r--r--compiler/rustc_monomorphize/src/util.rs4
-rw-r--r--compiler/rustc_parse/src/parser/diagnostics.rs5
-rw-r--r--compiler/rustc_parse/src/parser/mod.rs4
-rw-r--r--compiler/rustc_passes/src/check_attr.rs18
-rw-r--r--compiler/rustc_passes/src/dead.rs8
-rw-r--r--compiler/rustc_passes/src/layout_test.rs2
-rw-r--r--compiler/rustc_passes/src/liveness.rs10
-rw-r--r--compiler/rustc_passes/src/stability.rs4
-rw-r--r--compiler/rustc_privacy/src/lib.rs58
-rw-r--r--compiler/rustc_resolve/src/imports.rs4
-rw-r--r--compiler/rustc_resolve/src/late.rs19
-rw-r--r--compiler/rustc_resolve/src/late/diagnostics.rs38
-rw-r--r--compiler/rustc_resolve/src/lib.rs5
-rw-r--r--compiler/rustc_smir/src/lib.rs3
-rw-r--r--compiler/rustc_smir/src/rustc_internal/mod.rs16
-rw-r--r--compiler/rustc_smir/src/rustc_smir/mod.rs53
-rw-r--r--compiler/rustc_smir/src/stable_mir/mir/body.rs4
-rw-r--r--compiler/rustc_smir/src/stable_mir/ty.rs25
-rw-r--r--compiler/rustc_span/src/lib.rs3
-rw-r--r--compiler/rustc_span/src/symbol.rs2
-rw-r--r--compiler/rustc_symbol_mangling/src/legacy.rs20
-rw-r--r--compiler/rustc_symbol_mangling/src/lib.rs14
-rw-r--r--compiler/rustc_symbol_mangling/src/test.rs4
-rw-r--r--compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs75
-rw-r--r--compiler/rustc_symbol_mangling/src/v0.rs48
-rw-r--r--compiler/rustc_target/src/abi/call/aarch64.rs70
-rw-r--r--compiler/rustc_target/src/abi/call/m68k.rs2
-rw-r--r--compiler/rustc_target/src/abi/call/mod.rs29
-rw-r--r--compiler/rustc_target/src/abi/call/wasm.rs2
-rw-r--r--compiler/rustc_target/src/abi/call/x86.rs73
-rw-r--r--compiler/rustc_target/src/abi/call/x86_64.rs2
-rw-r--r--compiler/rustc_target/src/lib.rs1
-rw-r--r--compiler/rustc_trait_selection/src/solve/alias_relate.rs4
-rw-r--r--compiler/rustc_trait_selection/src/solve/assembly/mod.rs11
-rw-r--r--compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs50
-rw-r--r--compiler/rustc_trait_selection/src/solve/eval_ctxt.rs38
-rw-r--r--compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs4
-rw-r--r--compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs219
-rw-r--r--compiler/rustc_trait_selection/src/solve/fulfill.rs4
-rw-r--r--compiler/rustc_trait_selection/src/solve/inspect.rs37
-rw-r--r--compiler/rustc_trait_selection/src/solve/mod.rs17
-rw-r--r--compiler/rustc_trait_selection/src/solve/normalize.rs18
-rw-r--r--compiler/rustc_trait_selection/src/solve/opaques.rs12
-rw-r--r--compiler/rustc_trait_selection/src/solve/project_goals.rs195
-rw-r--r--compiler/rustc_trait_selection/src/solve/trait_goals.rs53
-rw-r--r--compiler/rustc_trait_selection/src/solve/weak_types.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/auto_trait.rs29
-rw-r--r--compiler/rustc_trait_selection/src/traits/coherence.rs29
-rw-r--r--compiler/rustc_trait_selection/src/traits/const_evaluatable.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs6
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs73
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs45
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs297
-rw-r--r--compiler/rustc_trait_selection/src/traits/fulfill.rs69
-rw-r--r--compiler/rustc_trait_selection/src/traits/misc.rs20
-rw-r--r--compiler/rustc_trait_selection/src/traits/mod.rs34
-rw-r--r--compiler/rustc_trait_selection/src/traits/object_safety.rs22
-rw-r--r--compiler/rustc_trait_selection/src/traits/outlives_bounds.rs3
-rw-r--r--compiler/rustc_trait_selection/src/traits/project.rs101
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs29
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/normalize.rs51
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/type_op/ascribe_user_type.rs22
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs23
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/confirmation.rs244
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/mod.rs98
-rw-r--r--compiler/rustc_trait_selection/src/traits/specialize/mod.rs75
-rw-r--r--compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/structural_match.rs10
-rw-r--r--compiler/rustc_trait_selection/src/traits/util.rs26
-rw-r--r--compiler/rustc_trait_selection/src/traits/vtable.rs16
-rw-r--r--compiler/rustc_trait_selection/src/traits/wf.rs71
-rw-r--r--compiler/rustc_traits/src/dropck_outlives.rs10
-rw-r--r--compiler/rustc_traits/src/normalize_projection_ty.rs4
-rw-r--r--compiler/rustc_transmute/src/layout/tree.rs14
-rw-r--r--compiler/rustc_ty_utils/src/abi.rs26
-rw-r--r--compiler/rustc_ty_utils/src/assoc.rs8
-rw-r--r--compiler/rustc_ty_utils/src/consts.rs13
-rw-r--r--compiler/rustc_ty_utils/src/implied_bounds.rs8
-rw-r--r--compiler/rustc_ty_utils/src/instance.rs73
-rw-r--r--compiler/rustc_ty_utils/src/layout.rs59
-rw-r--r--compiler/rustc_ty_utils/src/layout_sanity_check.rs4
-rw-r--r--compiler/rustc_ty_utils/src/needs_drop.rs38
-rw-r--r--compiler/rustc_ty_utils/src/opaque_types.rs36
-rw-r--r--compiler/rustc_ty_utils/src/representability.rs16
-rw-r--r--compiler/rustc_ty_utils/src/ty.rs28
-rw-r--r--compiler/rustc_type_ir/src/lib.rs2
-rw-r--r--compiler/rustc_type_ir/src/sty.rs84
423 files changed, 6514 insertions, 5537 deletions
diff --git a/compiler/rustc_abi/src/layout.rs b/compiler/rustc_abi/src/layout.rs
index f6875d895d3..aea88641f82 100644
--- a/compiler/rustc_abi/src/layout.rs
+++ b/compiler/rustc_abi/src/layout.rs
@@ -40,6 +40,8 @@ pub trait LayoutCalculator {
             largest_niche,
             align,
             size,
+            max_repr_align: None,
+            unadjusted_abi_align: align.abi,
         }
     }
 
@@ -122,6 +124,8 @@ pub trait LayoutCalculator {
             largest_niche: None,
             align: dl.i8_align,
             size: Size::ZERO,
+            max_repr_align: None,
+            unadjusted_abi_align: dl.i8_align.abi,
         }
     }
 
@@ -289,6 +293,9 @@ pub trait LayoutCalculator {
             }
 
             let mut align = dl.aggregate_align;
+            let mut max_repr_align = repr.align;
+            let mut unadjusted_abi_align = align.abi;
+
             let mut variant_layouts = variants
                 .iter_enumerated()
                 .map(|(j, v)| {
@@ -296,6 +303,8 @@ pub trait LayoutCalculator {
                     st.variants = Variants::Single { index: j };
 
                     align = align.max(st.align);
+                    max_repr_align = max_repr_align.max(st.max_repr_align);
+                    unadjusted_abi_align = unadjusted_abi_align.max(st.unadjusted_abi_align);
 
                     Some(st)
                 })
@@ -422,6 +431,8 @@ pub trait LayoutCalculator {
                 largest_niche,
                 size,
                 align,
+                max_repr_align,
+                unadjusted_abi_align,
             };
 
             Some(TmpLayout { layout, variants: variant_layouts })
@@ -456,6 +467,9 @@ pub trait LayoutCalculator {
         let (min_ity, signed) = discr_range_of_repr(min, max); //Integer::repr_discr(tcx, ty, &repr, min, max);
 
         let mut align = dl.aggregate_align;
+        let mut max_repr_align = repr.align;
+        let mut unadjusted_abi_align = align.abi;
+
         let mut size = Size::ZERO;
 
         // We're interested in the smallest alignment, so start large.
@@ -498,6 +512,8 @@ pub trait LayoutCalculator {
                 }
                 size = cmp::max(size, st.size);
                 align = align.max(st.align);
+                max_repr_align = max_repr_align.max(st.max_repr_align);
+                unadjusted_abi_align = unadjusted_abi_align.max(st.unadjusted_abi_align);
                 Some(st)
             })
             .collect::<Option<IndexVec<VariantIdx, _>>>()?;
@@ -691,6 +707,8 @@ pub trait LayoutCalculator {
             abi,
             align,
             size,
+            max_repr_align,
+            unadjusted_abi_align,
         };
 
         let tagged_layout = TmpLayout { layout: tagged_layout, variants: layout_variants };
@@ -730,10 +748,7 @@ pub trait LayoutCalculator {
         let dl = self.current_data_layout();
         let dl = dl.borrow();
         let mut align = if repr.pack.is_some() { dl.i8_align } else { dl.aggregate_align };
-
-        if let Some(repr_align) = repr.align {
-            align = align.max(AbiAndPrefAlign::new(repr_align));
-        }
+        let mut max_repr_align = repr.align;
 
         // If all the non-ZST fields have the same ABI and union ABI optimizations aren't
         // disabled, we can use that common ABI for the union as a whole.
@@ -751,6 +766,7 @@ pub trait LayoutCalculator {
             assert!(field.0.is_sized());
 
             align = align.max(field.align());
+            max_repr_align = max_repr_align.max(field.max_repr_align());
             size = cmp::max(size, field.size());
 
             if field.0.is_zst() {
@@ -787,6 +803,14 @@ pub trait LayoutCalculator {
         if let Some(pack) = repr.pack {
             align = align.min(AbiAndPrefAlign::new(pack));
         }
+        // The unadjusted ABI alignment does not include repr(align), but does include repr(pack).
+        // See documentation on `LayoutS::unadjusted_abi_align`.
+        let unadjusted_abi_align = align.abi;
+        if let Some(repr_align) = repr.align {
+            align = align.max(AbiAndPrefAlign::new(repr_align));
+        }
+        // `align` must not be modified after this, or `unadjusted_abi_align` could be inaccurate.
+        let align = align;
 
         // If all non-ZST fields have the same ABI, we may forward that ABI
         // for the union as a whole, unless otherwise inhibited.
@@ -809,6 +833,8 @@ pub trait LayoutCalculator {
             largest_niche: None,
             align,
             size: size.align_to(align.abi),
+            max_repr_align,
+            unadjusted_abi_align,
         })
     }
 }
@@ -829,6 +855,7 @@ fn univariant(
 ) -> Option<LayoutS> {
     let pack = repr.pack;
     let mut align = if pack.is_some() { dl.i8_align } else { dl.aggregate_align };
+    let mut max_repr_align = repr.align;
     let mut inverse_memory_index: IndexVec<u32, FieldIdx> = fields.indices().collect();
     let optimize = !repr.inhibit_struct_field_reordering_opt();
     if optimize && fields.len() > 1 {
@@ -997,6 +1024,7 @@ fn univariant(
         };
         offset = offset.align_to(field_align.abi);
         align = align.max(field_align);
+        max_repr_align = max_repr_align.max(field.max_repr_align());
 
         debug!("univariant offset: {:?} field: {:#?}", offset, field);
         offsets[i] = offset;
@@ -1018,9 +1046,16 @@ fn univariant(
 
         offset = offset.checked_add(field.size(), dl)?;
     }
+
+    // The unadjusted ABI alignment does not include repr(align), but does include repr(pack).
+    // See documentation on `LayoutS::unadjusted_abi_align`.
+    let unadjusted_abi_align = align.abi;
     if let Some(repr_align) = repr.align {
         align = align.max(AbiAndPrefAlign::new(repr_align));
     }
+    // `align` must not be modified after this point, or `unadjusted_abi_align` could be inaccurate.
+    let align = align;
+
     debug!("univariant min_size: {:?}", offset);
     let min_size = offset;
     // As stated above, inverse_memory_index holds field indices by increasing offset.
@@ -1036,6 +1071,7 @@ fn univariant(
         inverse_memory_index.into_iter().map(FieldIdx::as_u32).collect()
     };
     let size = min_size.align_to(align.abi);
+    let mut layout_of_single_non_zst_field = None;
     let mut abi = Abi::Aggregate { sized };
     // Unpack newtype ABIs and find scalar pairs.
     if sized && size.bytes() > 0 {
@@ -1045,6 +1081,8 @@ fn univariant(
         match (non_zst_fields.next(), non_zst_fields.next(), non_zst_fields.next()) {
             // We have exactly one non-ZST field.
             (Some((i, field)), None, None) => {
+                layout_of_single_non_zst_field = Some(field);
+
                 // Field fills the struct and it has a scalar or scalar pair ABI.
                 if offsets[i].bytes() == 0 && align.abi == field.align().abi && size == field.size()
                 {
@@ -1102,6 +1140,19 @@ fn univariant(
     if fields.iter().any(|f| f.abi().is_uninhabited()) {
         abi = Abi::Uninhabited;
     }
+
+    let unadjusted_abi_align = if repr.transparent() {
+        match layout_of_single_non_zst_field {
+            Some(l) => l.unadjusted_abi_align(),
+            None => {
+                // `repr(transparent)` with all ZST fields.
+                align.abi
+            }
+        }
+    } else {
+        unadjusted_abi_align
+    };
+
     Some(LayoutS {
         variants: Variants::Single { index: FIRST_VARIANT },
         fields: FieldsShape::Arbitrary { offsets, memory_index },
@@ -1109,6 +1160,8 @@ fn univariant(
         largest_niche,
         align,
         size,
+        max_repr_align,
+        unadjusted_abi_align,
     })
 }
 
diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs
index e1b9987f578..ef0c763ac20 100644
--- a/compiler/rustc_abi/src/lib.rs
+++ b/compiler/rustc_abi/src/lib.rs
@@ -1531,6 +1531,16 @@ pub struct LayoutS {
 
     pub align: AbiAndPrefAlign,
     pub size: Size,
+
+    /// The largest alignment explicitly requested with `repr(align)` on this type or any field.
+    /// Only used on i686-windows, where the argument passing ABI is different when alignment is
+    /// requested, even if the requested alignment is equal to the natural alignment.
+    pub max_repr_align: Option<Align>,
+
+    /// The alignment the type would have, ignoring any `repr(align)` but including `repr(packed)`.
+    /// Only used on aarch64-linux, where the argument passing ABI ignores the requested alignment
+    /// in some cases.
+    pub unadjusted_abi_align: Align,
 }
 
 impl LayoutS {
@@ -1545,6 +1555,8 @@ impl LayoutS {
             largest_niche,
             size,
             align,
+            max_repr_align: None,
+            unadjusted_abi_align: align.abi,
         }
     }
 }
@@ -1554,7 +1566,16 @@ impl fmt::Debug for LayoutS {
         // This is how `Layout` used to print before it become
         // `Interned<LayoutS>`. We print it like this to avoid having to update
         // expected output in a lot of tests.
-        let LayoutS { size, align, abi, fields, largest_niche, variants } = self;
+        let LayoutS {
+            size,
+            align,
+            abi,
+            fields,
+            largest_niche,
+            variants,
+            max_repr_align,
+            unadjusted_abi_align,
+        } = self;
         f.debug_struct("Layout")
             .field("size", size)
             .field("align", align)
@@ -1562,6 +1583,8 @@ impl fmt::Debug for LayoutS {
             .field("fields", fields)
             .field("largest_niche", largest_niche)
             .field("variants", variants)
+            .field("max_repr_align", max_repr_align)
+            .field("unadjusted_abi_align", unadjusted_abi_align)
             .finish()
     }
 }
@@ -1602,6 +1625,14 @@ impl<'a> Layout<'a> {
         self.0.0.size
     }
 
+    pub fn max_repr_align(self) -> Option<Align> {
+        self.0.0.max_repr_align
+    }
+
+    pub fn unadjusted_abi_align(self) -> Align {
+        self.0.0.unadjusted_abi_align
+    }
+
     /// Whether the layout is from a type that implements [`std::marker::PointerLike`].
     ///
     /// Currently, that means that the type is pointer-sized, pointer-aligned,
diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs
index 6646fa9446f..303bdd3a307 100644
--- a/compiler/rustc_ast/src/token.rs
+++ b/compiler/rustc_ast/src/token.rs
@@ -11,7 +11,7 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_data_structures::sync::Lrc;
 use rustc_macros::HashStable_Generic;
 use rustc_span::symbol::{kw, sym};
-#[cfg_attr(not(bootstrap), allow(hidden_glob_reexports))]
+#[allow(hidden_glob_reexports)]
 use rustc_span::symbol::{Ident, Symbol};
 use rustc_span::{self, edition::Edition, Span, DUMMY_SP};
 use std::borrow::Cow;
diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs
index d350498bc96..ab55c09465b 100644
--- a/compiler/rustc_ast_lowering/src/asm.rs
+++ b/compiler/rustc_ast_lowering/src/asm.rs
@@ -352,7 +352,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
 
                                     let idx2 = *o.get();
                                     let (ref op2, op_sp2) = operands[idx2];
-                                    let Some(asm::InlineAsmRegOrRegClass::Reg(reg2)) = op2.reg() else {
+                                    let Some(asm::InlineAsmRegOrRegClass::Reg(reg2)) = op2.reg()
+                                    else {
                                         unreachable!();
                                     };
 
@@ -368,7 +369,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                                             assert!(!*late);
                                             let out_op_sp = if input { op_sp2 } else { op_sp };
                                             Some(out_op_sp)
-                                        },
+                                        }
                                         _ => None,
                                     };
 
@@ -377,7 +378,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                                         op_span2: op_sp2,
                                         reg1_name: reg.name(),
                                         reg2_name: reg2.name(),
-                                        in_out
+                                        in_out,
                                     });
                                 }
                                 Entry::Vacant(v) => {
diff --git a/compiler/rustc_borrowck/src/constraint_generation.rs b/compiler/rustc_borrowck/src/constraint_generation.rs
index 743d117e00f..1f642099f08 100644
--- a/compiler/rustc_borrowck/src/constraint_generation.rs
+++ b/compiler/rustc_borrowck/src/constraint_generation.rs
@@ -7,8 +7,8 @@ use rustc_middle::mir::{
     Body, Local, Location, Place, PlaceRef, ProjectionElem, Rvalue, SourceInfo, Statement,
     StatementKind, Terminator, TerminatorKind, UserTypeProjection,
 };
-use rustc_middle::ty::subst::SubstsRef;
 use rustc_middle::ty::visit::TypeVisitable;
+use rustc_middle::ty::GenericArgsRef;
 use rustc_middle::ty::{self, RegionVid, Ty, TyCtxt};
 
 use crate::{
@@ -49,11 +49,11 @@ struct ConstraintGeneration<'cg, 'tcx> {
 }
 
 impl<'cg, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cg, 'tcx> {
-    /// We sometimes have `substs` within an rvalue, or within a
+    /// We sometimes have `args` within an rvalue, or within a
     /// call. Make them live at the location where they appear.
-    fn visit_substs(&mut self, substs: &SubstsRef<'tcx>, location: Location) {
-        self.add_regular_live_constraint(*substs, location);
-        self.super_substs(substs);
+    fn visit_args(&mut self, args: &GenericArgsRef<'tcx>, location: Location) {
+        self.add_regular_live_constraint(*args, location);
+        self.super_args(args);
     }
 
     /// We sometimes have `region` within an rvalue, or within a
diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index c8c8b72b389..278e450c6b5 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -363,21 +363,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             }
         }
         let hir = self.infcx.tcx.hir();
-        if let Some(hir::Node::Item(hir::Item {
-            kind: hir::ItemKind::Fn(_, _, body_id),
-            ..
-        })) = hir.find(self.mir_hir_id())
-            && let Some(hir::Node::Expr(expr)) = hir.find(body_id.hir_id)
-        {
+        if let Some(body_id) = hir.maybe_body_owned_by(self.mir_def_id()) {
+            let expr = hir.body(body_id).value;
             let place = &self.move_data.move_paths[mpi].place;
-            let span = place.as_local()
-                .map(|local| self.body.local_decls[local].source_info.span);
-            let mut finder = ExpressionFinder {
-                expr_span: move_span,
-                expr: None,
-                pat: None,
-                parent_pat: None,
-            };
+            let span = place.as_local().map(|local| self.body.local_decls[local].source_info.span);
+            let mut finder =
+                ExpressionFinder { expr_span: move_span, expr: None, pat: None, parent_pat: None };
             finder.visit_expr(expr);
             if let Some(span) = span && let Some(expr) = finder.expr {
                 for (_, expr) in hir.parent_iter(expr.hir_id) {
@@ -461,7 +452,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                     } = move_spans {
                         // We already suggest cloning for these cases in `explain_captures`.
                     } else {
-                        self.suggest_cloning(err, ty, move_span);
+                        self.suggest_cloning(err, ty, expr, move_span);
                     }
                 }
             }
@@ -702,11 +693,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                 .iter()
                 .copied()
                 .find_map(find_fn_kind_from_did),
-            ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => tcx
+            ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) => tcx
                 .explicit_item_bounds(def_id)
-                .subst_iter_copied(tcx, substs)
+                .arg_iter_copied(tcx, args)
                 .find_map(|(clause, span)| find_fn_kind_from_did((clause, span))),
-            ty::Closure(_, substs) => match substs.as_closure().kind() {
+            ty::Closure(_, args) => match args.as_closure().kind() {
                 ty::ClosureKind::Fn => Some(hir::Mutability::Not),
                 ty::ClosureKind::FnMut => Some(hir::Mutability::Mut),
                 _ => None,
@@ -714,7 +705,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             _ => None,
         };
 
-        let Some(borrow_level) = borrow_level else { return false; };
+        let Some(borrow_level) = borrow_level else {
+            return false;
+        };
         let sugg = move_sites
             .iter()
             .map(|move_site| {
@@ -734,9 +727,21 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         true
     }
 
-    fn suggest_cloning(&self, err: &mut Diagnostic, ty: Ty<'tcx>, span: Span) {
+    fn suggest_cloning(
+        &self,
+        err: &mut Diagnostic,
+        ty: Ty<'tcx>,
+        expr: &hir::Expr<'_>,
+        span: Span,
+    ) {
         let tcx = self.infcx.tcx;
         // Try to find predicates on *generic params* that would allow copying `ty`
+        let suggestion =
+            if let Some(symbol) = tcx.hir().maybe_get_struct_pattern_shorthand_field(expr) {
+                format!(": {}.clone()", symbol)
+            } else {
+                ".clone()".to_owned()
+            };
         if let Some(clone_trait_def) = tcx.lang_items().clone_trait()
             && self.infcx
                 .type_implements_trait(
@@ -749,7 +754,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             err.span_suggestion_verbose(
                 span.shrink_to_hi(),
                 "consider cloning the value if the performance cost is acceptable",
-                ".clone()",
+                suggestion,
                 Applicability::MachineApplicable,
             );
         }
@@ -763,7 +768,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             .typeck_root_def_id(self.mir_def_id().to_def_id())
             .as_local()
             .and_then(|def_id| tcx.hir().get_generics(def_id))
-        else { return; };
+        else {
+            return;
+        };
         // Try to find predicates on *generic params* that would allow copying `ty`
         let ocx = ObligationCtxt::new(&self.infcx);
         let copy_did = tcx.require_lang_item(LangItem::Copy, Some(span));
@@ -1220,18 +1227,20 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             return;
         };
         let inner_param_uses = find_all_local_uses::find(self.body, inner_param.local);
-        let Some((inner_call_loc, inner_call_term)) = inner_param_uses.into_iter().find_map(|loc| {
-            let Either::Right(term) = self.body.stmt_at(loc) else {
-                debug!("{:?} is a statement, so it can't be a call", loc);
-                return None;
-            };
-            let TerminatorKind::Call { args, .. } = &term.kind else {
-                debug!("not a call: {:?}", term);
-                return None;
-            };
-            debug!("checking call args for uses of inner_param: {:?}", args);
-            args.contains(&Operand::Move(inner_param)).then_some((loc, term))
-        }) else {
+        let Some((inner_call_loc, inner_call_term)) =
+            inner_param_uses.into_iter().find_map(|loc| {
+                let Either::Right(term) = self.body.stmt_at(loc) else {
+                    debug!("{:?} is a statement, so it can't be a call", loc);
+                    return None;
+                };
+                let TerminatorKind::Call { args, .. } = &term.kind else {
+                    debug!("not a call: {:?}", term);
+                    return None;
+                };
+                debug!("checking call args for uses of inner_param: {:?}", args);
+                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;
         };
@@ -1442,21 +1451,24 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         }
 
         // Get closure's arguments
-        let ty::Closure(_, substs) = typeck_results.expr_ty(closure_expr).kind() else { /* hir::Closure can be a generator too */ return };
-        let sig = substs.as_closure().sig();
+        let ty::Closure(_, args) = typeck_results.expr_ty(closure_expr).kind() else {
+            /* hir::Closure can be a generator too */
+            return;
+        };
+        let sig = args.as_closure().sig();
         let tupled_params =
             tcx.erase_late_bound_regions(sig.inputs().iter().next().unwrap().map_bound(|&b| b));
         let ty::Tuple(params) = tupled_params.kind() else { return };
 
         // Find the first argument with a matching type, get its name
-        let Some((_, this_name)) = params
-            .iter()
-            .zip(hir.body_param_names(closure.body))
-            .find(|(param_ty, name)|{
+        let Some((_, this_name)) =
+            params.iter().zip(hir.body_param_names(closure.body)).find(|(param_ty, name)| {
                 // FIXME: also support deref for stuff like `Rc` arguments
                 param_ty.peel_refs() == local_ty && name != &Ident::empty()
             })
-            else { return };
+        else {
+            return;
+        };
 
         let spans;
         if let Some((_path_expr, qpath)) = finder.error_path
@@ -2667,7 +2679,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                 kind: TerminatorKind::Call { call_source: CallSource::OverloadedOperator, .. },
                 ..
             }),
-            Some((method_did, method_substs)),
+            Some((method_did, method_args)),
         ) = (
             &self.body[loan.reserve_location.block].terminator,
             rustc_middle::util::find_self_call(
@@ -2680,7 +2692,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             if tcx.is_diagnostic_item(sym::deref_method, method_did) {
                 let deref_target =
                     tcx.get_diagnostic_item(sym::deref_target).and_then(|deref_target| {
-                        Instance::resolve(tcx, self.param_env, deref_target, method_substs)
+                        Instance::resolve(tcx, self.param_env, deref_target, method_args)
                             .transpose()
                     });
                 if let Some(Ok(instance)) = deref_target {
@@ -2847,11 +2859,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             if is_closure {
                 None
             } else {
-                let ty = self.infcx.tcx.type_of(self.mir_def_id()).subst_identity();
+                let ty = self.infcx.tcx.type_of(self.mir_def_id()).instantiate_identity();
                 match ty.kind() {
                     ty::FnDef(_, _) | ty::FnPtr(_) => self.annotate_fn_sig(
                         self.mir_def_id(),
-                        self.infcx.tcx.fn_sig(self.mir_def_id()).subst_identity(),
+                        self.infcx.tcx.fn_sig(self.mir_def_id()).instantiate_identity(),
                     ),
                     _ => None,
                 }
@@ -2893,13 +2905,15 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                         );
                         // Check if our `target` was captured by a closure.
                         if let Rvalue::Aggregate(
-                            box AggregateKind::Closure(def_id, substs),
+                            box AggregateKind::Closure(def_id, args),
                             operands,
                         ) = rvalue
                         {
                             let def_id = def_id.expect_local();
                             for operand in operands {
-                                let (Operand::Copy(assigned_from) | Operand::Move(assigned_from)) = operand else {
+                                let (Operand::Copy(assigned_from) | Operand::Move(assigned_from)) =
+                                    operand
+                                else {
                                     continue;
                                 };
                                 debug!(
@@ -2908,7 +2922,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                                 );
 
                                 // Find the local from the operand.
-                                let Some(assigned_from_local) = assigned_from.local_or_deref_local() else {
+                                let Some(assigned_from_local) =
+                                    assigned_from.local_or_deref_local()
+                                else {
                                     continue;
                                 };
 
@@ -2920,7 +2936,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                                 // into a place then we should annotate the closure in
                                 // case it ends up being assigned into the return place.
                                 annotated_closure =
-                                    self.annotate_fn_sig(def_id, substs.as_closure().sig());
+                                    self.annotate_fn_sig(def_id, args.as_closure().sig());
                                 debug!(
                                     "annotate_argument_and_return_for_borrow: \
                                      annotated_closure={:?} assigned_from_local={:?} \
@@ -2961,7 +2977,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                         );
 
                         // Find the local from the rvalue.
-                        let Some(assigned_from_local) = assigned_from.local_or_deref_local() else { continue };
+                        let Some(assigned_from_local) = assigned_from.local_or_deref_local() else {
+                            continue;
+                        };
                         debug!(
                             "annotate_argument_and_return_for_borrow: \
                              assigned_from_local={:?}",
@@ -3009,7 +3027,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                         assigned_to, args
                     );
                     for operand in args {
-                        let (Operand::Copy(assigned_from) | Operand::Move(assigned_from)) = operand else {
+                        let (Operand::Copy(assigned_from) | Operand::Move(assigned_from)) = operand
+                        else {
                             continue;
                         };
                         debug!(
diff --git a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
index 225c38efb2c..c92f32071f4 100644
--- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
@@ -168,17 +168,17 @@ impl<'tcx> BorrowExplanation<'tcx> {
                 let local_decl = &body.local_decls[dropped_local];
                 let mut ty = local_decl.ty;
                 if local_decl.source_info.span.desugaring_kind() == Some(DesugaringKind::ForLoop) {
-                    if let ty::Adt(adt, substs) = local_decl.ty.kind() {
+                    if let ty::Adt(adt, args) = local_decl.ty.kind() {
                         if tcx.is_diagnostic_item(sym::Option, adt.did()) {
                             // in for loop desugaring, only look at the `Some(..)` inner type
-                            ty = substs.type_at(0);
+                            ty = args.type_at(0);
                         }
                     }
                 }
                 let (dtor_desc, type_desc) = match ty.kind() {
                     // If type is an ADT that implements Drop, then
                     // simplify output by reporting just the ADT name.
-                    ty::Adt(adt, _substs) if adt.has_dtor(tcx) && !adt.is_box() => {
+                    ty::Adt(adt, _args) if adt.has_dtor(tcx) && !adt.is_box() => {
                         ("`Drop` code", format!("type `{}`", tcx.def_path_str(adt.did())))
                     }
 
diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs
index 0e56463e17c..099e07e8841 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mod.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs
@@ -732,18 +732,18 @@ impl<'tcx> BorrowedContentSource<'tcx> {
 
     fn from_call(func: Ty<'tcx>, tcx: TyCtxt<'tcx>) -> Option<Self> {
         match *func.kind() {
-            ty::FnDef(def_id, substs) => {
+            ty::FnDef(def_id, args) => {
                 let trait_id = tcx.trait_of_item(def_id)?;
 
                 let lang_items = tcx.lang_items();
                 if Some(trait_id) == lang_items.deref_trait()
                     || Some(trait_id) == lang_items.deref_mut_trait()
                 {
-                    Some(BorrowedContentSource::OverloadedDeref(substs.type_at(0)))
+                    Some(BorrowedContentSource::OverloadedDeref(args.type_at(0)))
                 } else if Some(trait_id) == lang_items.index_trait()
                     || Some(trait_id) == lang_items.index_mut_trait()
                 {
-                    Some(BorrowedContentSource::OverloadedIndex(substs.type_at(0)))
+                    Some(BorrowedContentSource::OverloadedIndex(args.type_at(0)))
                 } else {
                     None
                 }
@@ -847,14 +847,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             kind: TerminatorKind::Call { fn_span, call_source, .. }, ..
         }) = &self.body[location.block].terminator
         {
-            let Some((method_did, method_substs)) =
-            rustc_middle::util::find_self_call(
-                    self.infcx.tcx,
-                    &self.body,
-                    target_temp,
-                    location.block,
-                )
-            else {
+            let Some((method_did, method_args)) = rustc_middle::util::find_self_call(
+                self.infcx.tcx,
+                &self.body,
+                target_temp,
+                location.block,
+            ) else {
                 return normal_ret;
             };
 
@@ -862,7 +860,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                 self.infcx.tcx,
                 self.param_env,
                 method_did,
-                method_substs,
+                method_args,
                 *fn_span,
                 call_source.from_hir_call(),
                 Some(self.infcx.tcx.fn_arg_names(method_did)[0]),
@@ -1041,7 +1039,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                         });
                     }
                 }
-                CallKind::Normal { self_arg, desugaring, method_did, method_substs } => {
+                CallKind::Normal { self_arg, desugaring, method_did, method_args } => {
                     let self_arg = self_arg.unwrap();
                     let tcx = self.infcx.tcx;
                     if let Some((CallDesugaringKind::ForLoopIntoIter, _)) = desugaring {
@@ -1108,13 +1106,13 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                         // Erase and shadow everything that could be passed to the new infcx.
                         let ty = moved_place.ty(self.body, tcx).ty;
 
-                        if let ty::Adt(def, substs) = ty.kind()
+                        if let ty::Adt(def, args) = ty.kind()
                             && Some(def.did()) == tcx.lang_items().pin_type()
-                            && let ty::Ref(_, _, hir::Mutability::Mut) = substs.type_at(0).kind()
+                            && let ty::Ref(_, _, hir::Mutability::Mut) = args.type_at(0).kind()
                             && let self_ty = self.infcx.instantiate_binder_with_fresh_vars(
                                 fn_call_span,
                                 LateBoundRegionConversionTime::FnCall,
-                                tcx.fn_sig(method_did).subst(tcx, method_substs).input(0),
+                                tcx.fn_sig(method_did).instantiate(tcx, method_args).input(0),
                             )
                             && self.infcx.can_eq(self.param_env, ty, self_ty)
                         {
@@ -1163,7 +1161,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).subst_identity().kind() {
+                            .and_then(|did| match tcx.type_of(did).instantiate_identity().kind() {
                                 ty::Adt(def, ..) => Some(def.did()),
                                 _ => None,
                             });
diff --git a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs
index 8b77477a31a..e05c04e1188 100644
--- a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs
@@ -184,7 +184,9 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
             }
             // Error with the pattern
             LookupResult::Exact(_) => {
-                let LookupResult::Parent(Some(mpi)) = self.move_data.rev_lookup.find(move_from.as_ref()) else {
+                let LookupResult::Parent(Some(mpi)) =
+                    self.move_data.rev_lookup.find(move_from.as_ref())
+                else {
                     // move_from should be a projection from match_place.
                     unreachable!("Probably not unreachable...");
                 };
@@ -322,10 +324,10 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
             ty::Array(..) | ty::Slice(..) => {
                 self.cannot_move_out_of_interior_noncopy(span, ty, None)
             }
-            ty::Closure(def_id, closure_substs)
+            ty::Closure(def_id, closure_args)
                 if def_id.as_local() == Some(self.mir_def_id()) && upvar_field.is_some() =>
             {
-                let closure_kind_ty = closure_substs.as_closure().kind_ty();
+                let closure_kind_ty = closure_args.as_closure().kind_ty();
                 let closure_kind = match closure_kind_ty.to_opt_closure_kind() {
                     Some(kind @ (ty::ClosureKind::Fn | ty::ClosureKind::FnMut)) => kind,
                     Some(ty::ClosureKind::FnOnce) => {
@@ -494,8 +496,10 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
             if let LocalInfo::User(BindingForm::Var(VarBindingForm { pat_span, .. })) =
                 *bind_to.local_info()
             {
-                let Ok(pat_snippet) =
-                    self.infcx.tcx.sess.source_map().span_to_snippet(pat_span) else { continue; };
+                let Ok(pat_snippet) = self.infcx.tcx.sess.source_map().span_to_snippet(pat_span)
+                else {
+                    continue;
+                };
                 let Some(stripped) = pat_snippet.strip_prefix('&') else {
                     suggestions.push((
                         bind_to.source_info.span.shrink_to_lo(),
diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
index 1f2fefadf65..3c32121a51a 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
@@ -2,7 +2,6 @@ use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed
 use rustc_hir as hir;
 use rustc_hir::intravisit::Visitor;
 use rustc_hir::Node;
-use rustc_middle::hir::map::Map;
 use rustc_middle::mir::{Mutability, Place, PlaceRef, ProjectionElem};
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_middle::{
@@ -646,10 +645,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
             }
             let hir_map = self.infcx.tcx.hir();
             let def_id = self.body.source.def_id();
-            let hir_id = hir_map.local_def_id_to_hir_id(def_id.as_local().unwrap());
-            let node = hir_map.find(hir_id);
-            let Some(hir::Node::Item(item)) = node else { return; };
-            let hir::ItemKind::Fn(.., body_id) = item.kind else { return; };
+            let Some(local_def_id) = def_id.as_local() else { return };
+            let Some(body_id) = hir_map.maybe_body_owned_by(local_def_id) else { return };
             let body = self.infcx.tcx.hir().body(body_id);
 
             let mut v = V { assign_span: span, err, ty, suggested: false };
@@ -786,23 +783,12 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
     // In the future, attempt in all path but initially for RHS of for_loop
     fn suggest_similar_mut_method_for_for_loop(&self, err: &mut Diagnostic) {
         use hir::{
-            BodyId, Expr,
+            Expr,
             ExprKind::{Block, Call, DropTemps, Match, MethodCall},
-            HirId, ImplItem, ImplItemKind, Item, ItemKind,
         };
 
-        fn maybe_body_id_of_fn(hir_map: Map<'_>, id: HirId) -> Option<BodyId> {
-            match hir_map.find(id) {
-                Some(Node::Item(Item { kind: ItemKind::Fn(_, _, body_id), .. }))
-                | Some(Node::ImplItem(ImplItem { kind: ImplItemKind::Fn(_, body_id), .. })) => {
-                    Some(*body_id)
-                }
-                _ => None,
-            }
-        }
         let hir_map = self.infcx.tcx.hir();
-        let mir_body_hir_id = self.mir_hir_id();
-        if let Some(fn_body_id) = maybe_body_id_of_fn(hir_map, mir_body_hir_id) {
+        if let Some(body_id) = hir_map.maybe_body_owned_by(self.mir_def_id()) {
             if let Block(
                 hir::Block {
                     expr:
@@ -836,7 +822,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
                     ..
                 },
                 _,
-            ) = hir_map.body(fn_body_id).value.kind
+            ) = hir_map.body(body_id).value.kind
             {
                 let opt_suggestions = self
                     .infcx
@@ -1098,46 +1084,45 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
                 }
                 let hir_map = self.infcx.tcx.hir();
                 let def_id = self.body.source.def_id();
-                let hir_id = hir_map.local_def_id_to_hir_id(def_id.expect_local());
-                let node = hir_map.find(hir_id);
-                let hir_id = if let Some(hir::Node::Item(item)) = node
-                && let hir::ItemKind::Fn(.., body_id) = item.kind
-            {
-                let body = hir_map.body(body_id);
-                let mut v = BindingFinder {
-                    span: err_label_span,
-                    hir_id: None,
+                let hir_id = if let Some(local_def_id) = def_id.as_local() &&
+                    let Some(body_id) = hir_map.maybe_body_owned_by(local_def_id)
+                {
+                    let body = hir_map.body(body_id);
+                    let mut v = BindingFinder {
+                        span: err_label_span,
+                        hir_id: None,
+                    };
+                    v.visit_body(body);
+                    v.hir_id
+                } else {
+                    None
                 };
-                v.visit_body(body);
-                v.hir_id
-            } else {
-                None
-            };
+
                 if let Some(hir_id) = hir_id
                 && let Some(hir::Node::Local(local)) = hir_map.find(hir_id)
-            {
-                let (changing, span, sugg) = match local.ty {
-                    Some(ty) => ("changing", ty.span, message),
-                    None => (
-                        "specifying",
-                        local.pat.span.shrink_to_hi(),
-                        format!(": {message}"),
-                    ),
-                };
-                err.span_suggestion_verbose(
-                    span,
-                    format!("consider {changing} this binding's type"),
-                    sugg,
-                    Applicability::HasPlaceholders,
-                );
-            } else {
-                err.span_label(
-                    err_label_span,
-                    format!(
-                        "consider changing this binding's type to be: `{message}`"
-                    ),
-                );
-            }
+                {
+                    let (changing, span, sugg) = match local.ty {
+                        Some(ty) => ("changing", ty.span, message),
+                        None => (
+                            "specifying",
+                            local.pat.span.shrink_to_hi(),
+                            format!(": {message}"),
+                        ),
+                    };
+                    err.span_suggestion_verbose(
+                        span,
+                        format!("consider {changing} this binding's type"),
+                        sugg,
+                        Applicability::HasPlaceholders,
+                    );
+                } else {
+                    err.span_label(
+                        err_label_span,
+                        format!(
+                            "consider changing this binding's type to be: `{message}`"
+                        ),
+                    );
+                }
             }
             None => {}
         }
diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
index 617c85174cb..2ea399789b9 100644
--- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
@@ -22,7 +22,7 @@ use rustc_infer::infer::{
 };
 use rustc_middle::hir::place::PlaceBase;
 use rustc_middle::mir::{ConstraintCategory, ReturnConstraint};
-use rustc_middle::ty::subst::InternalSubsts;
+use rustc_middle::ty::GenericArgs;
 use rustc_middle::ty::TypeVisitor;
 use rustc_middle::ty::{self, RegionVid, Ty};
 use rustc_middle::ty::{Region, TyCtxt};
@@ -183,9 +183,9 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
     fn is_closure_fn_mut(&self, fr: RegionVid) -> bool {
         if let Some(ty::ReFree(free_region)) = self.to_error_region(fr).as_deref()
             && let ty::BoundRegionKind::BrEnv = free_region.bound_region
-            && let DefiningTy::Closure(_, substs) = self.regioncx.universal_regions().defining_ty
+            && let DefiningTy::Closure(_, args) = self.regioncx.universal_regions().defining_ty
         {
-            return substs.as_closure().kind() == ty::ClosureKind::FnMut;
+            return args.as_closure().kind() == ty::ClosureKind::FnMut;
         }
 
         false
@@ -224,12 +224,10 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
         let mut hrtb_bounds = vec![];
         gat_id_and_generics.iter().flatten().for_each(|(gat_hir_id, generics)| {
             for pred in generics.predicates {
-                let BoundPredicate(
-                        WhereBoundPredicate {
-                            bound_generic_params,
-                            bounds,
-                            ..
-                        }) = pred else { continue; };
+                let BoundPredicate(WhereBoundPredicate { bound_generic_params, bounds, .. }) = pred
+                else {
+                    continue;
+                };
                 if bound_generic_params
                     .iter()
                     .rfind(|bgp| hir.local_def_id_to_hir_id(bgp.def_id) == *gat_hir_id)
@@ -504,12 +502,12 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
                                 .to_string(),
                         )
                     }
-                    ty::Adt(adt, substs) => {
-                        let generic_arg = substs[param_index as usize];
-                        let identity_substs =
-                            InternalSubsts::identity_for_item(self.infcx.tcx, adt.did());
-                        let base_ty = Ty::new_adt(self.infcx.tcx, *adt, identity_substs);
-                        let base_generic_arg = identity_substs[param_index as usize];
+                    ty::Adt(adt, args) => {
+                        let generic_arg = args[param_index as usize];
+                        let identity_args =
+                            GenericArgs::identity_for_item(self.infcx.tcx, adt.did());
+                        let base_ty = Ty::new_adt(self.infcx.tcx, *adt, identity_args);
+                        let base_generic_arg = identity_args[param_index as usize];
                         let adt_desc = adt.descr();
 
                         let desc = format!(
@@ -522,12 +520,11 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
                     }
                     ty::FnDef(def_id, _) => {
                         let name = self.infcx.tcx.item_name(*def_id);
-                        let identity_substs =
-                            InternalSubsts::identity_for_item(self.infcx.tcx, *def_id);
+                        let identity_args = GenericArgs::identity_for_item(self.infcx.tcx, *def_id);
                         let desc = format!("a function pointer to `{name}`");
                         let note = format!(
                             "the function `{name}` is invariant over the parameter `{}`",
-                            identity_substs[param_index as usize]
+                            identity_args[param_index as usize]
                         );
                         (desc, note)
                     }
@@ -575,7 +572,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).subst_identity()
+            output_ty = self.infcx.tcx.type_of(def_id).instantiate_identity()
         };
 
         debug!("report_fnmut_error: output_ty={:?}", output_ty);
@@ -813,7 +810,9 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
                 return;
             }
             let suitable_region = self.infcx.tcx.is_suitable_region(f);
-            let Some(suitable_region) = suitable_region else { return; };
+            let Some(suitable_region) = suitable_region else {
+                return;
+            };
 
             let fn_returns = self.infcx.tcx.return_type_impl_or_dyn_traits(suitable_region.def_id);
 
@@ -848,7 +847,10 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
             let Some((alias_tys, alias_span, lt_addition_span)) = self
                 .infcx
                 .tcx
-                .return_type_impl_or_dyn_traits_with_type_alias(suitable_region.def_id) else { return; };
+                .return_type_impl_or_dyn_traits_with_type_alias(suitable_region.def_id)
+            else {
+                return;
+            };
 
             // in case the return type of the method is a type alias
             let mut spans_suggs: Vec<_> = Vec::new();
@@ -896,14 +898,14 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
         let tcx = self.infcx.tcx;
 
         let instance = if let ConstraintCategory::CallArgument(Some(func_ty)) = category {
-            let (fn_did, substs) = match func_ty.kind() {
-                ty::FnDef(fn_did, substs) => (fn_did, substs),
+            let (fn_did, args) = match func_ty.kind() {
+                ty::FnDef(fn_did, args) => (fn_did, args),
                 _ => return,
             };
-            debug!(?fn_did, ?substs);
+            debug!(?fn_did, ?args);
 
             // Only suggest this on function calls, not closures
-            let ty = tcx.type_of(fn_did).subst_identity();
+            let ty = tcx.type_of(fn_did).instantiate_identity();
             debug!("ty: {:?}, ty.kind: {:?}", ty, ty.kind());
             if let ty::Closure(_, _) = ty.kind() {
                 return;
@@ -913,7 +915,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
                 tcx,
                 self.param_env,
                 *fn_did,
-                self.infcx.resolve_vars_if_possible(substs),
+                self.infcx.resolve_vars_if_possible(args),
             ) {
                 instance
             } else {
@@ -932,8 +934,13 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
         let mut visitor = TraitObjectVisitor(FxIndexSet::default());
         visitor.visit_ty(param.param_ty);
 
-        let Some((ident, self_ty)) =
-            NiceRegionError::get_impl_ident_and_self_ty_from_trait(tcx, instance.def_id(), &visitor.0) else { return; };
+        let Some((ident, self_ty)) = NiceRegionError::get_impl_ident_and_self_ty_from_trait(
+            tcx,
+            instance.def_id(),
+            &visitor.0,
+        ) else {
+            return;
+        };
 
         self.suggest_constrain_dyn_trait_in_impl(diag, &visitor.0, ident, self_ty);
     }
@@ -981,23 +988,25 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
         sup: RegionVid,
     ) {
         let (Some(sub), Some(sup)) = (self.to_error_region(sub), self.to_error_region(sup)) else {
-            return
+            return;
         };
 
         let Some((ty_sub, _)) = self
             .infcx
             .tcx
             .is_suitable_region(sub)
-            .and_then(|anon_reg| find_anon_type(self.infcx.tcx, sub, &anon_reg.boundregion)) else {
-            return
+            .and_then(|anon_reg| find_anon_type(self.infcx.tcx, sub, &anon_reg.boundregion))
+        else {
+            return;
         };
 
         let Some((ty_sup, _)) = self
             .infcx
             .tcx
             .is_suitable_region(sup)
-            .and_then(|anon_reg| find_anon_type(self.infcx.tcx, sup, &anon_reg.boundregion)) else {
-            return
+            .and_then(|anon_reg| find_anon_type(self.infcx.tcx, sup, &anon_reg.boundregion))
+        else {
+            return;
         };
 
         suggest_adding_lifetime_params(self.infcx.tcx, sub, ty_sup, ty_sub, diag);
diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs
index 074f37bed13..9cad8fa5318 100644
--- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs
@@ -5,8 +5,8 @@ use rustc_errors::Diagnostic;
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_middle::ty::print::RegionHighlightMode;
-use rustc_middle::ty::subst::{GenericArgKind, SubstsRef};
 use rustc_middle::ty::{self, RegionVid, Ty};
+use rustc_middle::ty::{GenericArgKind, GenericArgsRef};
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::{Span, DUMMY_SP};
 
@@ -321,18 +321,18 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
                 ty::BoundRegionKind::BrEnv => {
                     let def_ty = self.regioncx.universal_regions().defining_ty;
 
-                    let DefiningTy::Closure(_, substs) = def_ty else {
+                    let DefiningTy::Closure(_, args) = def_ty else {
                         // Can't have BrEnv in functions, constants or generators.
                         bug!("BrEnv outside of closure.");
                     };
-                    let hir::ExprKind::Closure(&hir::Closure { fn_decl_span, .. })
-                        = tcx.hir().expect_expr(self.mir_hir_id()).kind
+                    let hir::ExprKind::Closure(&hir::Closure { fn_decl_span, .. }) =
+                        tcx.hir().expect_expr(self.mir_hir_id()).kind
                     else {
                         bug!("Closure is not defined by a closure expr");
                     };
                     let region_name = self.synthesize_region_name();
 
-                    let closure_kind_ty = substs.as_closure().kind_ty();
+                    let closure_kind_ty = args.as_closure().kind_ty();
                     let note = match closure_kind_ty.to_opt_closure_kind() {
                         Some(ty::ClosureKind::Fn) => {
                             "closure implements `Fn`, so references to captured variables \
@@ -510,10 +510,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
                 }
 
                 // Match up something like `Foo<'1>`
-                (
-                    ty::Adt(_adt_def, substs),
-                    hir::TyKind::Path(hir::QPath::Resolved(None, path)),
-                ) => {
+                (ty::Adt(_adt_def, args), hir::TyKind::Path(hir::QPath::Resolved(None, path))) => {
                     match path.res {
                         // Type parameters of the type alias have no reason to
                         // be the same as those of the ADT.
@@ -523,7 +520,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
                         _ => {
                             if let Some(last_segment) = path.segments.last() {
                                 if let Some(highlight) = self.match_adt_and_segment(
-                                    substs,
+                                    args,
                                     needle_fr,
                                     last_segment,
                                     search_stack,
@@ -560,22 +557,22 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
         None
     }
 
-    /// We've found an enum/struct/union type with the substitutions
-    /// `substs` and -- in the HIR -- a path type with the final
+    /// We've found an enum/struct/union type with the generic args
+    /// `args` and -- in the HIR -- a path type with the final
     /// segment `last_segment`. Try to find a `'_` to highlight in
     /// the generic args (or, if not, to produce new zipped pairs of
     /// types+hir to search through).
     fn match_adt_and_segment<'hir>(
         &self,
-        substs: SubstsRef<'tcx>,
+        args: GenericArgsRef<'tcx>,
         needle_fr: RegionVid,
         last_segment: &'hir hir::PathSegment<'hir>,
         search_stack: &mut Vec<(Ty<'tcx>, &'hir hir::Ty<'hir>)>,
     ) -> Option<RegionNameHighlight> {
         // Did the user give explicit arguments? (e.g., `Foo<..>`)
-        let args = last_segment.args.as_ref()?;
+        let explicit_args = last_segment.args.as_ref()?;
         let lifetime =
-            self.try_match_adt_and_generic_args(substs, needle_fr, args, search_stack)?;
+            self.try_match_adt_and_generic_args(args, needle_fr, explicit_args, search_stack)?;
         if lifetime.is_anonymous() {
             None
         } else {
@@ -583,19 +580,19 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
         }
     }
 
-    /// We've found an enum/struct/union type with the substitutions
-    /// `substs` and -- in the HIR -- a path with the generic
-    /// arguments `args`. If `needle_fr` appears in the args, return
+    /// We've found an enum/struct/union type with the generic args
+    /// `args` and -- in the HIR -- a path with the generic
+    /// arguments `hir_args`. If `needle_fr` appears in the args, return
     /// the `hir::Lifetime` that corresponds to it. If not, push onto
     /// `search_stack` the types+hir to search through.
     fn try_match_adt_and_generic_args<'hir>(
         &self,
-        substs: SubstsRef<'tcx>,
+        args: GenericArgsRef<'tcx>,
         needle_fr: RegionVid,
-        args: &'hir hir::GenericArgs<'hir>,
+        hir_args: &'hir hir::GenericArgs<'hir>,
         search_stack: &mut Vec<(Ty<'tcx>, &'hir hir::Ty<'hir>)>,
     ) -> Option<&'hir hir::Lifetime> {
-        for (kind, hir_arg) in iter::zip(substs, args.args) {
+        for (kind, hir_arg) in iter::zip(args, hir_args.args) {
             match (kind.unpack(), hir_arg) {
                 (GenericArgKind::Lifetime(r), hir::GenericArg::Lifetime(lt)) => {
                     if r.as_var() == needle_fr {
@@ -849,9 +846,10 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
             return None;
         };
 
-        let found = tcx.any_free_region_meets(&tcx.type_of(region_parent).subst_identity(), |r| {
-            *r == ty::ReEarlyBound(region)
-        });
+        let found = tcx
+            .any_free_region_meets(&tcx.type_of(region_parent).instantiate_identity(), |r| {
+                *r == ty::ReEarlyBound(region)
+            });
 
         Some(RegionName {
             name: self.synthesize_region_name(),
diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs
index 97d15cb53db..ea32506fc89 100644
--- a/compiler/rustc_borrowck/src/lib.rs
+++ b/compiler/rustc_borrowck/src/lib.rs
@@ -301,7 +301,7 @@ fn do_mir_borrowck<'tcx>(
     let movable_generator =
         // The first argument is the generator type passed by value
         if let Some(local) = body.local_decls.raw.get(1)
-        // Get the interior types and substs which typeck computed
+        // Get the interior types and args which typeck computed
         && let ty::Generator(_, _, hir::Movability::Static) = local.ty.kind()
     {
         false
diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs
index e45d3a2c882..fbbccc58ad6 100644
--- a/compiler/rustc_borrowck/src/region_infer/mod.rs
+++ b/compiler/rustc_borrowck/src/region_infer/mod.rs
@@ -1115,7 +1115,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     ) -> Option<ClosureOutlivesSubject<'tcx>> {
         let tcx = infcx.tcx;
 
-        // Opaque types' substs may include useless lifetimes.
+        // Opaque types' args may include useless lifetimes.
         // We will replace them with ReStatic.
         struct OpaqueFolder<'tcx> {
             tcx: TyCtxt<'tcx>,
@@ -1127,19 +1127,18 @@ impl<'tcx> RegionInferenceContext<'tcx> {
             fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
                 use ty::TypeSuperFoldable as _;
                 let tcx = self.tcx;
-                let &ty::Alias(ty::Opaque, ty::AliasTy { substs, def_id, .. }) = t.kind() else {
+                let &ty::Alias(ty::Opaque, ty::AliasTy { args, def_id, .. }) = t.kind() else {
                     return t.super_fold_with(self);
                 };
-                let substs =
-                    std::iter::zip(substs, tcx.variances_of(def_id)).map(|(arg, v)| {
-                        match (arg.unpack(), v) {
-                            (ty::GenericArgKind::Lifetime(_), ty::Bivariant) => {
-                                tcx.lifetimes.re_static.into()
-                            }
-                            _ => arg.fold_with(self),
+                let args = std::iter::zip(args, tcx.variances_of(def_id)).map(|(arg, v)| {
+                    match (arg.unpack(), v) {
+                        (ty::GenericArgKind::Lifetime(_), ty::Bivariant) => {
+                            tcx.lifetimes.re_static.into()
                         }
-                    });
-                Ty::new_opaque(tcx, def_id, tcx.mk_substs_from_iter(substs))
+                        _ => arg.fold_with(self),
+                    }
+                });
+                Ty::new_opaque(tcx, def_id, tcx.mk_args_from_iter(args))
             }
         }
 
@@ -2058,10 +2057,17 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         let mut extra_info = vec![];
         for constraint in path.iter() {
             let outlived = constraint.sub;
-            let Some(origin) = self.var_infos.get(outlived) else { continue; };
-            let RegionVariableOrigin::Nll(NllRegionVariableOrigin::Placeholder(p)) = origin.origin else { continue; };
+            let Some(origin) = self.var_infos.get(outlived) else {
+                continue;
+            };
+            let RegionVariableOrigin::Nll(NllRegionVariableOrigin::Placeholder(p)) = origin.origin
+            else {
+                continue;
+            };
             debug!(?constraint, ?p);
-            let ConstraintCategory::Predicate(span) = constraint.category else { continue; };
+            let ConstraintCategory::Predicate(span) = constraint.category else {
+                continue;
+            };
             extra_info.push(ExtraConstraintInfo::PlaceholderFromPredicate(span));
             // We only want to point to one
             break;
diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
index 1a227f2d110..d8e81827a3b 100644
--- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
+++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
@@ -6,9 +6,9 @@ use rustc_infer::infer::InferCtxt;
 use rustc_infer::infer::TyCtxtInferExt as _;
 use rustc_infer::traits::{Obligation, ObligationCause};
 use rustc_middle::traits::DefiningAnchor;
-use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts};
 use rustc_middle::ty::visit::TypeVisitableExt;
 use rustc_middle::ty::{self, OpaqueHiddenType, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable};
+use rustc_middle::ty::{GenericArgKind, GenericArgs};
 use rustc_span::Span;
 use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _;
 use rustc_trait_selection::traits::ObligationCtxt;
@@ -38,15 +38,15 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     /// back to concrete lifetimes: `'static`, `ReEarlyBound` or `ReFree`.
     ///
     /// First we map all the lifetimes in the concrete type to an equal
-    /// universal region that occurs in the concrete type's substs, in this case
-    /// this would result in `&'1 i32`. We only consider regions in the substs
+    /// universal region that occurs in the concrete type's args, in this case
+    /// this would result in `&'1 i32`. We only consider regions in the args
     /// in case there is an equal region that does not. For example, this should
     /// be allowed:
     /// `fn f<'a: 'b, 'b: 'a>(x: *mut &'b i32) -> impl Sized + 'a { x }`
     ///
     /// Then we map the regions in both the type and the subst to their
     /// `external_name` giving `concrete_type = &'a i32`,
-    /// `substs = ['static, 'a]`. This will then allow
+    /// `args = ['static, 'a]`. This will then allow
     /// `infer_opaque_definition_from_instantiation` to determine that
     /// `_Return<'_a> = &'_a i32`.
     ///
@@ -73,8 +73,8 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         debug!(?member_constraints);
 
         for (opaque_type_key, concrete_type) in opaque_ty_decls {
-            let substs = opaque_type_key.substs;
-            debug!(?concrete_type, ?substs);
+            let args = opaque_type_key.args;
+            debug!(?concrete_type, ?args);
 
             let mut subst_regions = vec![self.universal_regions.fr_static];
 
@@ -95,7 +95,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
                         ty::Region::new_error_with_message(
                             infcx.tcx,
                             concrete_type.span,
-                            "opaque type with non-universal region substs",
+                            "opaque type with non-universal region args",
                         )
                     }
                 }
@@ -110,17 +110,17 @@ impl<'tcx> RegionInferenceContext<'tcx> {
             }
             debug!(?subst_regions);
 
-            // Next, insert universal regions from substs, so we can translate regions that appear
-            // in them but are not subject to member constraints, for instance closure substs.
-            let universal_substs = infcx.tcx.fold_regions(substs, |region, _| {
+            // Next, insert universal regions from args, so we can translate regions that appear
+            // in them but are not subject to member constraints, for instance closure args.
+            let universal_args = infcx.tcx.fold_regions(args, |region, _| {
                 if let ty::RePlaceholder(..) = region.kind() {
-                    // Higher kinded regions don't need remapping, they don't refer to anything outside of this the substs.
+                    // Higher kinded regions don't need remapping, they don't refer to anything outside of this the args.
                     return region;
                 }
                 let vid = self.to_region_vid(region);
                 to_universal_region(vid, &mut subst_regions)
             });
-            debug!(?universal_substs);
+            debug!(?universal_args);
             debug!(?subst_regions);
 
             // Deduplicate the set of regions while keeping the chosen order.
@@ -139,7 +139,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
             debug!(?universal_concrete_type);
 
             let opaque_type_key =
-                OpaqueTypeKey { def_id: opaque_type_key.def_id, substs: universal_substs };
+                OpaqueTypeKey { def_id: opaque_type_key.def_id, args: universal_args };
             let ty = infcx.infer_opaque_definition_from_instantiation(
                 opaque_type_key,
                 universal_concrete_type,
@@ -175,7 +175,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
 
     /// Map the regions in the type to named regions. This is similar to what
     /// `infer_opaque_types` does, but can infer any universal region, not only
-    /// ones from the substs for the opaque type. It also doesn't double check
+    /// ones from the args for the opaque type. It also doesn't double check
     /// that the regions produced are in fact equal to the named region they are
     /// replaced with. This is fine because this function is only to improve the
     /// region names in error messages.
@@ -238,7 +238,7 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
     /// # Parameters
     ///
     /// - `def_id`, the `impl Trait` type
-    /// - `substs`, the substs used to instantiate this opaque type
+    /// - `args`, the args used to instantiate this opaque type
     /// - `instantiated_ty`, the inferred type C1 -- fully resolved, lifted version of
     ///   `opaque_defn.concrete_ty`
     #[instrument(level = "debug", skip(self))]
@@ -309,11 +309,11 @@ fn check_opaque_type_well_formed<'tcx>(
         })
         .build();
     let ocx = ObligationCtxt::new(&infcx);
-    let identity_substs = InternalSubsts::identity_for_item(tcx, def_id);
+    let identity_args = GenericArgs::identity_for_item(tcx, def_id);
 
     // Require that the hidden type actually fulfills all the bounds of the opaque type, even without
     // the bounds that the function supplies.
-    let opaque_ty = Ty::new_opaque(tcx, def_id.to_def_id(), identity_substs);
+    let opaque_ty = Ty::new_opaque(tcx, def_id.to_def_id(), identity_args);
     ocx.eq(&ObligationCause::misc(definition_span, def_id), param_env, opaque_ty, definition_ty)
         .map_err(|err| {
             infcx
@@ -384,7 +384,7 @@ fn check_opaque_type_parameter_valid(
     }
     let opaque_generics = tcx.generics_of(opaque_type_key.def_id);
     let mut seen_params: FxIndexMap<_, Vec<_>> = FxIndexMap::default();
-    for (i, arg) in opaque_type_key.substs.iter().enumerate() {
+    for (i, arg) in opaque_type_key.args.iter().enumerate() {
         let arg_is_param = match arg.unpack() {
             GenericArgKind::Type(ty) => matches!(ty.kind(), ty::Param(_)),
             GenericArgKind::Lifetime(lt) => {
diff --git a/compiler/rustc_borrowck/src/renumber.rs b/compiler/rustc_borrowck/src/renumber.rs
index 4389d2b60bc..4c69ea843c7 100644
--- a/compiler/rustc_borrowck/src/renumber.rs
+++ b/compiler/rustc_borrowck/src/renumber.rs
@@ -6,7 +6,7 @@ use rustc_infer::infer::NllRegionVariableOrigin;
 use rustc_middle::mir::visit::{MutVisitor, TyContext};
 use rustc_middle::mir::Constant;
 use rustc_middle::mir::{Body, Location, Promoted};
-use rustc_middle::ty::subst::SubstsRef;
+use rustc_middle::ty::GenericArgsRef;
 use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable};
 use rustc_span::{Span, Symbol};
 
@@ -94,10 +94,10 @@ impl<'a, 'tcx> MutVisitor<'tcx> for RegionRenumberer<'a, 'tcx> {
     }
 
     #[instrument(skip(self), level = "debug")]
-    fn visit_substs(&mut self, substs: &mut SubstsRef<'tcx>, location: Location) {
-        *substs = self.renumber_regions(*substs, || RegionCtxt::Location(location));
+    fn visit_args(&mut self, args: &mut GenericArgsRef<'tcx>, location: Location) {
+        *args = self.renumber_regions(*args, || RegionCtxt::Location(location));
 
-        debug!(?substs);
+        debug!(?args);
     }
 
     #[instrument(skip(self), level = "debug")]
diff --git a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs
index 71eae7b27d1..21d8026e170 100644
--- a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs
+++ b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs
@@ -5,7 +5,7 @@ use rustc_infer::infer::outlives::obligations::{TypeOutlives, TypeOutlivesDelega
 use rustc_infer::infer::region_constraints::{GenericKind, VerifyBound};
 use rustc_infer::infer::{self, InferCtxt, SubregionOrigin};
 use rustc_middle::mir::{ClosureOutlivesSubject, ClosureRegionRequirements, ConstraintCategory};
-use rustc_middle::ty::subst::GenericArgKind;
+use rustc_middle::ty::GenericArgKind;
 use rustc_middle::ty::{self, TyCtxt};
 use rustc_middle::ty::{TypeFoldable, TypeVisitableExt};
 use rustc_span::{Span, DUMMY_SP};
@@ -89,20 +89,20 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
 
     /// Given an instance of the closure type, this method instantiates the "extra" requirements
     /// that we computed for the closure. This has the effect of adding new outlives obligations
-    /// to existing region variables in `closure_substs`.
+    /// to existing region variables in `closure_args`.
     #[instrument(skip(self), level = "debug")]
     pub fn apply_closure_requirements(
         &mut self,
         closure_requirements: &ClosureRegionRequirements<'tcx>,
         closure_def_id: DefId,
-        closure_substs: ty::SubstsRef<'tcx>,
+        closure_args: ty::GenericArgsRef<'tcx>,
     ) {
-        // Extract the values of the free regions in `closure_substs`
+        // Extract the values of the free regions in `closure_args`
         // into a vector. These are the regions that we will be
         // relating to one another.
         let closure_mapping = &UniversalRegions::closure_mapping(
             self.tcx,
-            closure_substs,
+            closure_args,
             closure_requirements.num_external_vids,
             closure_def_id.expect_local(),
         );
diff --git a/compiler/rustc_borrowck/src/type_check/liveness/polonius.rs b/compiler/rustc_borrowck/src/type_check/liveness/polonius.rs
index 012075d7114..c621df37106 100644
--- a/compiler/rustc_borrowck/src/type_check/liveness/polonius.rs
+++ b/compiler/rustc_borrowck/src/type_check/liveness/polonius.rs
@@ -2,7 +2,7 @@ use crate::def_use::{self, DefUse};
 use crate::location::{LocationIndex, LocationTable};
 use rustc_middle::mir::visit::{MutatingUseContext, PlaceContext, Visitor};
 use rustc_middle::mir::{Body, Local, Location, Place};
-use rustc_middle::ty::subst::GenericArg;
+use rustc_middle::ty::GenericArg;
 use rustc_mir_dataflow::move_paths::{LookupResult, MoveData, MovePathIndex};
 
 use super::TypeChecker;
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index a15e1065c81..78aa513033c 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -30,12 +30,12 @@ use rustc_middle::traits::query::NoSolution;
 use rustc_middle::traits::ObligationCause;
 use rustc_middle::ty::adjustment::PointerCoercion;
 use rustc_middle::ty::cast::CastTy;
-use rustc_middle::ty::subst::{SubstsRef, UserSubsts};
 use rustc_middle::ty::visit::TypeVisitableExt;
 use rustc_middle::ty::{
     self, Binder, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, Dynamic,
     OpaqueHiddenType, OpaqueTypeKey, RegionVid, Ty, TyCtxt, UserType, UserTypeAnnotationIndex,
 };
+use rustc_middle::ty::{GenericArgsRef, UserArgs};
 use rustc_span::def_id::CRATE_DEF_ID;
 use rustc_span::symbol::sym;
 use rustc_span::{Span, DUMMY_SP};
@@ -389,15 +389,12 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
                 } else {
                     self.cx.ascribe_user_type(
                         constant.literal.ty(),
-                        UserType::TypeOf(
-                            uv.def,
-                            UserSubsts { substs: uv.substs, user_self_ty: None },
-                        ),
+                        UserType::TypeOf(uv.def, UserArgs { args: uv.args, user_self_ty: None }),
                         locations.span(&self.cx.body),
                     );
                 }
             } else if let Some(static_def_id) = constant.check_static_ptr(tcx) {
-                let unnormalized_ty = tcx.type_of(static_def_id).subst_identity();
+                let unnormalized_ty = tcx.type_of(static_def_id).instantiate_identity();
                 let normalized_ty = self.cx.normalize(unnormalized_ty, locations);
                 let literal_ty = constant.literal.ty().builtin_deref(true).unwrap().ty;
 
@@ -411,11 +408,11 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
                 }
             }
 
-            if let ty::FnDef(def_id, substs) = *constant.literal.ty().kind() {
+            if let ty::FnDef(def_id, args) = *constant.literal.ty().kind() {
                 // const_trait_impl: use a non-const param env when checking that a FnDef type is well formed.
                 // this is because the well-formedness of the function does not need to be proved to have `const`
                 // impls for trait bounds.
-                let instantiated_predicates = tcx.predicates_of(def_id).instantiate(tcx, substs);
+                let instantiated_predicates = tcx.predicates_of(def_id).instantiate(tcx, args);
                 let prev = self.cx.param_env;
                 self.cx.param_env = prev.without_const();
                 self.cx.normalize_and_prove_instantiated_predicates(
@@ -666,7 +663,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
                 })
             }
             ProjectionElem::Downcast(maybe_name, index) => match base_ty.kind() {
-                ty::Adt(adt_def, _substs) if adt_def.is_enum() => {
+                ty::Adt(adt_def, _args) if adt_def.is_enum() => {
                     if index.as_usize() >= adt_def.variants().len() {
                         PlaceTy::from_ty(span_mirbug_and_err!(
                             self,
@@ -776,16 +773,16 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
     ) -> Result<Ty<'tcx>, FieldAccessError> {
         let tcx = self.tcx();
 
-        let (variant, substs) = match base_ty {
+        let (variant, args) = match base_ty {
             PlaceTy { ty, variant_index: Some(variant_index) } => match *ty.kind() {
-                ty::Adt(adt_def, substs) => (adt_def.variant(variant_index), substs),
-                ty::Generator(def_id, substs, _) => {
-                    let mut variants = substs.as_generator().state_tys(def_id, tcx);
+                ty::Adt(adt_def, args) => (adt_def.variant(variant_index), args),
+                ty::Generator(def_id, args, _) => {
+                    let mut variants = args.as_generator().state_tys(def_id, tcx);
                     let Some(mut variant) = variants.nth(variant_index.into()) else {
                         bug!(
                             "variant_index of generator out of range: {:?}/{:?}",
                             variant_index,
-                            substs.as_generator().state_tys(def_id, tcx).count()
+                            args.as_generator().state_tys(def_id, tcx).count()
                         );
                     };
                     return match variant.nth(field.index()) {
@@ -796,11 +793,11 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
                 _ => bug!("can't have downcast of non-adt non-generator type"),
             },
             PlaceTy { ty, variant_index: None } => match *ty.kind() {
-                ty::Adt(adt_def, substs) if !adt_def.is_enum() => {
-                    (adt_def.variant(FIRST_VARIANT), substs)
+                ty::Adt(adt_def, args) if !adt_def.is_enum() => {
+                    (adt_def.variant(FIRST_VARIANT), args)
                 }
-                ty::Closure(_, substs) => {
-                    return match substs
+                ty::Closure(_, args) => {
+                    return match args
                         .as_closure()
                         .tupled_upvars_ty()
                         .tuple_fields()
@@ -808,17 +805,17 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
                     {
                         Some(&ty) => Ok(ty),
                         None => Err(FieldAccessError::OutOfRange {
-                            field_count: substs.as_closure().upvar_tys().count(),
+                            field_count: args.as_closure().upvar_tys().count(),
                         }),
                     };
                 }
-                ty::Generator(_, substs, _) => {
+                ty::Generator(_, args, _) => {
                     // Only prefix fields (upvars and current state) are
                     // accessible without a variant index.
-                    return match substs.as_generator().prefix_tys().nth(field.index()) {
+                    return match args.as_generator().prefix_tys().nth(field.index()) {
                         Some(ty) => Ok(ty),
                         None => Err(FieldAccessError::OutOfRange {
-                            field_count: substs.as_generator().prefix_tys().count(),
+                            field_count: args.as_generator().prefix_tys().count(),
                         }),
                     };
                 }
@@ -840,7 +837,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
         };
 
         if let Some(field) = variant.fields.get(field) {
-            Ok(self.cx.normalize(field.ty(tcx, substs), location))
+            Ok(self.cx.normalize(field.ty(tcx, args), location))
         } else {
             Err(FieldAccessError::OutOfRange { field_count: variant.fields.len() })
         }
@@ -1065,7 +1062,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
 
                         ocx.infcx.add_item_bounds_for_hidden_type(
                             opaque_type_key.def_id.to_def_id(),
-                            opaque_type_key.substs,
+                            opaque_type_key.args,
                             cause,
                             param_env,
                             hidden_ty.ty,
@@ -1770,32 +1767,32 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         let tcx = self.tcx();
 
         match *ak {
-            AggregateKind::Adt(adt_did, variant_index, substs, _, active_field_index) => {
+            AggregateKind::Adt(adt_did, variant_index, args, _, active_field_index) => {
                 let def = tcx.adt_def(adt_did);
                 let variant = &def.variant(variant_index);
                 let adj_field_index = active_field_index.unwrap_or(field_index);
                 if let Some(field) = variant.fields.get(adj_field_index) {
-                    Ok(self.normalize(field.ty(tcx, substs), location))
+                    Ok(self.normalize(field.ty(tcx, args), location))
                 } else {
                     Err(FieldAccessError::OutOfRange { field_count: variant.fields.len() })
                 }
             }
-            AggregateKind::Closure(_, substs) => {
-                match substs.as_closure().upvar_tys().nth(field_index.as_usize()) {
+            AggregateKind::Closure(_, args) => {
+                match args.as_closure().upvar_tys().nth(field_index.as_usize()) {
                     Some(ty) => Ok(ty),
                     None => Err(FieldAccessError::OutOfRange {
-                        field_count: substs.as_closure().upvar_tys().count(),
+                        field_count: args.as_closure().upvar_tys().count(),
                     }),
                 }
             }
-            AggregateKind::Generator(_, substs, _) => {
+            AggregateKind::Generator(_, args, _) => {
                 // It doesn't make sense to look at a field beyond the prefix;
                 // these require a variant index, and are not initialized in
                 // aggregate rvalues.
-                match substs.as_generator().prefix_tys().nth(field_index.as_usize()) {
+                match args.as_generator().prefix_tys().nth(field_index.as_usize()) {
                     Some(ty) => Ok(ty),
                     None => Err(FieldAccessError::OutOfRange {
-                        field_count: substs.as_generator().prefix_tys().count(),
+                        field_count: args.as_generator().prefix_tys().count(),
                     }),
                 }
             }
@@ -1821,8 +1818,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                     let def_id = uv.def;
                     if tcx.def_kind(def_id) == DefKind::InlineConst {
                         let def_id = def_id.expect_local();
-                        let predicates =
-                            self.prove_closure_bounds(tcx, def_id, uv.substs, location);
+                        let predicates = self.prove_closure_bounds(tcx, def_id, uv.args, location);
                         self.normalize_and_prove_instantiated_predicates(
                             def_id.to_def_id(),
                             predicates,
@@ -1939,7 +1935,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
 
                     CastKind::PointerCoercion(PointerCoercion::ClosureFnPointer(unsafety)) => {
                         let sig = match op.ty(body, tcx).kind() {
-                            ty::Closure(_, substs) => substs.as_closure().sig(),
+                            ty::Closure(_, args) => args.as_closure().sig(),
                             _ => bug!(),
                         };
                         let ty_fn_ptr_from =
@@ -2039,28 +2035,16 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                     }
 
                     CastKind::PointerCoercion(PointerCoercion::MutToConstPointer) => {
-                        let ty::RawPtr(ty::TypeAndMut {
-                            ty: ty_from,
-                            mutbl: hir::Mutability::Mut,
-                        }) = op.ty(body, tcx).kind() else {
-                            span_mirbug!(
-                                self,
-                                rvalue,
-                                "unexpected base type for cast {:?}",
-                                ty,
-                            );
+                        let ty::RawPtr(ty::TypeAndMut { ty: ty_from, mutbl: hir::Mutability::Mut }) =
+                            op.ty(body, tcx).kind()
+                        else {
+                            span_mirbug!(self, rvalue, "unexpected base type for cast {:?}", ty,);
                             return;
                         };
-                        let ty::RawPtr(ty::TypeAndMut {
-                            ty: ty_to,
-                            mutbl: hir::Mutability::Not,
-                        }) = ty.kind() else {
-                            span_mirbug!(
-                                self,
-                                rvalue,
-                                "unexpected target type for cast {:?}",
-                                ty,
-                            );
+                        let ty::RawPtr(ty::TypeAndMut { ty: ty_to, mutbl: hir::Mutability::Not }) =
+                            ty.kind()
+                        else {
+                            span_mirbug!(self, rvalue, "unexpected target type for cast {:?}", ty,);
                             return;
                         };
                         if let Err(terr) = self.sub_types(
@@ -2603,8 +2587,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         );
 
         let (def_id, instantiated_predicates) = match *aggregate_kind {
-            AggregateKind::Adt(adt_did, _, substs, _, _) => {
-                (adt_did, tcx.predicates_of(adt_did).instantiate(tcx, substs))
+            AggregateKind::Adt(adt_did, _, args, _, _) => {
+                (adt_did, tcx.predicates_of(adt_did).instantiate(tcx, args))
             }
 
             // For closures, we have some **extra requirements** we
@@ -2626,9 +2610,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
             // desugaring. A closure gets desugared to a struct, and
             // these extra requirements are basically like where
             // clauses on the struct.
-            AggregateKind::Closure(def_id, substs)
-            | AggregateKind::Generator(def_id, substs, _) => {
-                (def_id, self.prove_closure_bounds(tcx, def_id.expect_local(), substs, location))
+            AggregateKind::Closure(def_id, args) | AggregateKind::Generator(def_id, args, _) => {
+                (def_id, self.prove_closure_bounds(tcx, def_id.expect_local(), args, location))
             }
 
             AggregateKind::Array(_) | AggregateKind::Tuple => {
@@ -2647,7 +2630,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         &mut self,
         tcx: TyCtxt<'tcx>,
         def_id: LocalDefId,
-        substs: SubstsRef<'tcx>,
+        args: GenericArgsRef<'tcx>,
         location: Location,
     ) -> ty::InstantiatedPredicates<'tcx> {
         if let Some(closure_requirements) = &tcx.mir_borrowck(def_id).closure_requirements {
@@ -2665,26 +2648,26 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
             .apply_closure_requirements(
                 &closure_requirements,
                 def_id.to_def_id(),
-                substs,
+                args,
             );
         }
 
-        // Now equate closure substs to regions inherited from `typeck_root_def_id`. Fixes #98589.
+        // Now equate closure args to regions inherited from `typeck_root_def_id`. Fixes #98589.
         let typeck_root_def_id = tcx.typeck_root_def_id(self.body.source.def_id());
-        let typeck_root_substs = ty::InternalSubsts::identity_for_item(tcx, typeck_root_def_id);
+        let typeck_root_args = ty::GenericArgs::identity_for_item(tcx, typeck_root_def_id);
 
-        let parent_substs = match tcx.def_kind(def_id) {
-            DefKind::Closure => substs.as_closure().parent_substs(),
-            DefKind::Generator => substs.as_generator().parent_substs(),
-            DefKind::InlineConst => substs.as_inline_const().parent_substs(),
+        let parent_args = match tcx.def_kind(def_id) {
+            DefKind::Closure => args.as_closure().parent_args(),
+            DefKind::Generator => args.as_generator().parent_args(),
+            DefKind::InlineConst => args.as_inline_const().parent_args(),
             other => bug!("unexpected item {:?}", other),
         };
-        let parent_substs = tcx.mk_substs(parent_substs);
+        let parent_args = tcx.mk_args(parent_args);
 
-        assert_eq!(typeck_root_substs.len(), parent_substs.len());
-        if let Err(_) = self.eq_substs(
-            typeck_root_substs,
-            parent_substs,
+        assert_eq!(typeck_root_args.len(), parent_args.len());
+        if let Err(_) = self.eq_args(
+            typeck_root_args,
+            parent_args,
             location.to_locations(),
             ConstraintCategory::BoringNoLocation,
         ) {
@@ -2692,12 +2675,12 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                 self,
                 def_id,
                 "could not relate closure to parent {:?} != {:?}",
-                typeck_root_substs,
-                parent_substs
+                typeck_root_args,
+                parent_args
             );
         }
 
-        tcx.predicates_of(def_id).instantiate(tcx, substs)
+        tcx.predicates_of(def_id).instantiate(tcx, args)
     }
 
     #[instrument(skip(self, body), level = "debug")]
diff --git a/compiler/rustc_borrowck/src/type_check/relate_tys.rs b/compiler/rustc_borrowck/src/type_check/relate_tys.rs
index 8c4bfb2c6e0..e0c6295627b 100644
--- a/compiler/rustc_borrowck/src/type_check/relate_tys.rs
+++ b/compiler/rustc_borrowck/src/type_check/relate_tys.rs
@@ -42,10 +42,10 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
     }
 
     /// Add sufficient constraints to ensure `a == b`. See also [Self::relate_types].
-    pub(super) fn eq_substs(
+    pub(super) fn eq_args(
         &mut self,
-        a: ty::SubstsRef<'tcx>,
-        b: ty::SubstsRef<'tcx>,
+        a: ty::GenericArgsRef<'tcx>,
+        b: ty::GenericArgsRef<'tcx>,
         locations: Locations,
         category: ConstraintCategory<'tcx>,
     ) -> Result<(), NoSolution> {
diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs
index 7821b82bf2b..a751a9732f0 100644
--- a/compiler/rustc_borrowck/src/universal_regions.rs
+++ b/compiler/rustc_borrowck/src/universal_regions.rs
@@ -22,8 +22,8 @@ use rustc_hir::BodyOwnerKind;
 use rustc_index::IndexVec;
 use rustc_infer::infer::NllRegionVariableOrigin;
 use rustc_middle::ty::fold::TypeFoldable;
-use rustc_middle::ty::{self, InlineConstSubsts, InlineConstSubstsParts, RegionVid, Ty, TyCtxt};
-use rustc_middle::ty::{InternalSubsts, SubstsRef};
+use rustc_middle::ty::{self, InlineConstArgs, InlineConstArgsParts, RegionVid, Ty, TyCtxt};
+use rustc_middle::ty::{GenericArgs, GenericArgsRef};
 use rustc_span::symbol::{kw, sym};
 use rustc_span::Symbol;
 use std::iter;
@@ -88,26 +88,26 @@ pub struct UniversalRegions<'tcx> {
 #[derive(Copy, Clone, Debug)]
 pub enum DefiningTy<'tcx> {
     /// The MIR is a closure. The signature is found via
-    /// `ClosureSubsts::closure_sig_ty`.
-    Closure(DefId, SubstsRef<'tcx>),
+    /// `ClosureArgs::closure_sig_ty`.
+    Closure(DefId, GenericArgsRef<'tcx>),
 
     /// The MIR is a generator. The signature is that generators take
     /// no parameters and return the result of
-    /// `ClosureSubsts::generator_return_ty`.
-    Generator(DefId, SubstsRef<'tcx>, hir::Movability),
+    /// `ClosureArgs::generator_return_ty`.
+    Generator(DefId, GenericArgsRef<'tcx>, hir::Movability),
 
-    /// The MIR is a fn item with the given `DefId` and substs. The signature
+    /// The MIR is a fn item with the given `DefId` and args. The signature
     /// of the function can be bound then with the `fn_sig` query.
-    FnDef(DefId, SubstsRef<'tcx>),
+    FnDef(DefId, GenericArgsRef<'tcx>),
 
     /// The MIR represents some form of constant. The signature then
     /// is that it has no inputs and a single return value, which is
     /// the value of the constant.
-    Const(DefId, SubstsRef<'tcx>),
+    Const(DefId, GenericArgsRef<'tcx>),
 
     /// The MIR represents an inline const. The signature has no inputs and a
-    /// single return value found via `InlineConstSubsts::ty`.
-    InlineConst(DefId, SubstsRef<'tcx>),
+    /// single return value found via `InlineConstArgs::ty`.
+    InlineConst(DefId, GenericArgsRef<'tcx>),
 }
 
 impl<'tcx> DefiningTy<'tcx> {
@@ -117,9 +117,9 @@ impl<'tcx> DefiningTy<'tcx> {
     /// match up with the upvar order in the HIR, typesystem, and MIR.
     pub fn upvar_tys(self) -> impl Iterator<Item = Ty<'tcx>> + 'tcx {
         match self {
-            DefiningTy::Closure(_, substs) => Either::Left(substs.as_closure().upvar_tys()),
-            DefiningTy::Generator(_, substs, _) => {
-                Either::Right(Either::Left(substs.as_generator().upvar_tys()))
+            DefiningTy::Closure(_, args) => Either::Left(args.as_closure().upvar_tys()),
+            DefiningTy::Generator(_, args, _) => {
+                Either::Right(Either::Left(args.as_generator().upvar_tys()))
             }
             DefiningTy::FnDef(..) | DefiningTy::Const(..) | DefiningTy::InlineConst(..) => {
                 Either::Right(Either::Right(iter::empty()))
@@ -164,9 +164,9 @@ struct UniversalRegionIndices<'tcx> {
     /// used because trait matching and type-checking will feed us
     /// region constraints that reference those regions and we need to
     /// be able to map them to our internal `RegionVid`. This is
-    /// basically equivalent to an `InternalSubsts`, except that it also
+    /// basically equivalent to an `GenericArgs`, except that it also
     /// contains an entry for `ReStatic` -- it might be nice to just
-    /// use a substs, and then handle `ReStatic` another way.
+    /// use a args, and then handle `ReStatic` another way.
     indices: FxHashMap<ty::Region<'tcx>, RegionVid>,
 
     /// The vid assigned to `'static`. Used only for diagnostics.
@@ -243,13 +243,13 @@ impl<'tcx> UniversalRegions<'tcx> {
     /// `V[1]: V[2]`.
     pub fn closure_mapping(
         tcx: TyCtxt<'tcx>,
-        closure_substs: SubstsRef<'tcx>,
+        closure_args: GenericArgsRef<'tcx>,
         expected_num_vars: usize,
         closure_def_id: LocalDefId,
     ) -> IndexVec<RegionVid, ty::Region<'tcx>> {
         let mut region_mapping = IndexVec::with_capacity(expected_num_vars);
         region_mapping.push(tcx.lifetimes.re_static);
-        tcx.for_each_free_region(&closure_substs, |fr| {
+        tcx.for_each_free_region(&closure_args, |fr| {
             region_mapping.push(fr);
         });
 
@@ -334,11 +334,11 @@ impl<'tcx> UniversalRegions<'tcx> {
     /// state.
     pub(crate) fn annotate(&self, tcx: TyCtxt<'tcx>, err: &mut Diagnostic) {
         match self.defining_ty {
-            DefiningTy::Closure(def_id, substs) => {
+            DefiningTy::Closure(def_id, args) => {
                 err.note(format!(
-                    "defining type: {} with closure substs {:#?}",
-                    tcx.def_path_str_with_substs(def_id, substs),
-                    &substs[tcx.generics_of(def_id).parent_count..],
+                    "defining type: {} with closure args {:#?}",
+                    tcx.def_path_str_with_args(def_id, args),
+                    &args[tcx.generics_of(def_id).parent_count..],
                 ));
 
                 // FIXME: It'd be nice to print the late-bound regions
@@ -350,11 +350,11 @@ impl<'tcx> UniversalRegions<'tcx> {
                     err.note(format!("late-bound region is {:?}", self.to_region_vid(r)));
                 });
             }
-            DefiningTy::Generator(def_id, substs, _) => {
+            DefiningTy::Generator(def_id, args, _) => {
                 err.note(format!(
-                    "defining type: {} with generator substs {:#?}",
-                    tcx.def_path_str_with_substs(def_id, substs),
-                    &substs[tcx.generics_of(def_id).parent_count..],
+                    "defining type: {} with generator args {:#?}",
+                    tcx.def_path_str_with_args(def_id, args),
+                    &args[tcx.generics_of(def_id).parent_count..],
                 ));
 
                 // FIXME: As above, we'd like to print out the region
@@ -364,22 +364,19 @@ impl<'tcx> UniversalRegions<'tcx> {
                     err.note(format!("late-bound region is {:?}", self.to_region_vid(r)));
                 });
             }
-            DefiningTy::FnDef(def_id, substs) => {
-                err.note(format!(
-                    "defining type: {}",
-                    tcx.def_path_str_with_substs(def_id, substs),
-                ));
+            DefiningTy::FnDef(def_id, args) => {
+                err.note(format!("defining type: {}", tcx.def_path_str_with_args(def_id, args),));
             }
-            DefiningTy::Const(def_id, substs) => {
+            DefiningTy::Const(def_id, args) => {
                 err.note(format!(
                     "defining constant type: {}",
-                    tcx.def_path_str_with_substs(def_id, substs),
+                    tcx.def_path_str_with_args(def_id, args),
                 ));
             }
-            DefiningTy::InlineConst(def_id, substs) => {
+            DefiningTy::InlineConst(def_id, args) => {
                 err.note(format!(
                     "defining inline constant type: {}",
-                    tcx.def_path_str_with_substs(def_id, substs),
+                    tcx.def_path_str_with_args(def_id, args),
                 ));
             }
         }
@@ -501,8 +498,11 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
                     .as_var();
 
                 let region = ty::Region::new_var(self.infcx.tcx, reg_vid);
-                let va_list_ty =
-                    self.infcx.tcx.type_of(va_list_did).subst(self.infcx.tcx, &[region.into()]);
+                let va_list_ty = self
+                    .infcx
+                    .tcx
+                    .type_of(va_list_did)
+                    .instantiate(self.infcx.tcx, &[region.into()]);
 
                 unnormalized_input_tys = self.infcx.tcx.mk_type_list_from_iter(
                     unnormalized_input_tys.iter().copied().chain(iter::once(va_list_ty)),
@@ -522,7 +522,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
         debug!("build: local regions  = {}..{}", first_local_index, num_universals);
 
         let yield_ty = match defining_ty {
-            DefiningTy::Generator(_, substs, _) => Some(substs.as_generator().yield_ty()),
+            DefiningTy::Generator(_, args, _) => Some(args.as_generator().yield_ty()),
             _ => None,
         };
 
@@ -548,7 +548,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
 
         match tcx.hir().body_owner_kind(self.mir_def) {
             BodyOwnerKind::Closure | BodyOwnerKind::Fn => {
-                let defining_ty = tcx.type_of(self.mir_def).subst_identity();
+                let defining_ty = tcx.type_of(self.mir_def).instantiate_identity();
 
                 debug!("defining_ty (pre-replacement): {:?}", defining_ty);
 
@@ -556,11 +556,11 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
                     self.infcx.replace_free_regions_with_nll_infer_vars(FR, defining_ty);
 
                 match *defining_ty.kind() {
-                    ty::Closure(def_id, substs) => DefiningTy::Closure(def_id, substs),
-                    ty::Generator(def_id, substs, movability) => {
-                        DefiningTy::Generator(def_id, substs, movability)
+                    ty::Closure(def_id, args) => DefiningTy::Closure(def_id, args),
+                    ty::Generator(def_id, args, movability) => {
+                        DefiningTy::Generator(def_id, args, movability)
                     }
-                    ty::FnDef(def_id, substs) => DefiningTy::FnDef(def_id, substs),
+                    ty::FnDef(def_id, args) => DefiningTy::FnDef(def_id, args),
                     _ => span_bug!(
                         tcx.def_span(self.mir_def),
                         "expected defining type for `{:?}`: `{:?}`",
@@ -571,11 +571,11 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
             }
 
             BodyOwnerKind::Const | BodyOwnerKind::Static(..) => {
-                let identity_substs = InternalSubsts::identity_for_item(tcx, typeck_root_def_id);
+                let identity_args = GenericArgs::identity_for_item(tcx, typeck_root_def_id);
                 if self.mir_def.to_def_id() == typeck_root_def_id {
-                    let substs =
-                        self.infcx.replace_free_regions_with_nll_infer_vars(FR, identity_substs);
-                    DefiningTy::Const(self.mir_def.to_def_id(), substs)
+                    let args =
+                        self.infcx.replace_free_regions_with_nll_infer_vars(FR, identity_args);
+                    DefiningTy::Const(self.mir_def.to_def_id(), args)
                 } else {
                     // FIXME this line creates a dependency between borrowck and typeck.
                     //
@@ -584,18 +584,18 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
                     // into borrowck, which is ICE #78174.
                     //
                     // As a workaround, inline consts have an additional generic param (`ty`
-                    // below), so that `type_of(inline_const_def_id).substs(substs)` uses the
+                    // below), so that `type_of(inline_const_def_id).args(args)` uses the
                     // proper type with NLL infer vars.
                     let ty = tcx
                         .typeck(self.mir_def)
                         .node_type(tcx.local_def_id_to_hir_id(self.mir_def));
-                    let substs = InlineConstSubsts::new(
+                    let args = InlineConstArgs::new(
                         tcx,
-                        InlineConstSubstsParts { parent_substs: identity_substs, ty },
+                        InlineConstArgsParts { parent_args: identity_args, ty },
                     )
-                    .substs;
-                    let substs = self.infcx.replace_free_regions_with_nll_infer_vars(FR, substs);
-                    DefiningTy::InlineConst(self.mir_def.to_def_id(), substs)
+                    .args;
+                    let args = self.infcx.replace_free_regions_with_nll_infer_vars(FR, args);
+                    DefiningTy::InlineConst(self.mir_def.to_def_id(), args)
                 }
             }
         }
@@ -612,29 +612,29 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
     ) -> UniversalRegionIndices<'tcx> {
         let tcx = self.infcx.tcx;
         let typeck_root_def_id = tcx.typeck_root_def_id(self.mir_def.to_def_id());
-        let identity_substs = InternalSubsts::identity_for_item(tcx, typeck_root_def_id);
-        let fr_substs = match defining_ty {
-            DefiningTy::Closure(_, substs)
-            | DefiningTy::Generator(_, substs, _)
-            | DefiningTy::InlineConst(_, substs) => {
+        let identity_args = GenericArgs::identity_for_item(tcx, typeck_root_def_id);
+        let fr_args = match defining_ty {
+            DefiningTy::Closure(_, args)
+            | DefiningTy::Generator(_, args, _)
+            | DefiningTy::InlineConst(_, args) => {
                 // In the case of closures, we rely on the fact that
-                // the first N elements in the ClosureSubsts are
+                // the first N elements in the ClosureArgs are
                 // inherited from the `typeck_root_def_id`.
                 // Therefore, when we zip together (below) with
-                // `identity_substs`, we will get only those regions
+                // `identity_args`, we will get only those regions
                 // that correspond to early-bound regions declared on
                 // the `typeck_root_def_id`.
-                assert!(substs.len() >= identity_substs.len());
-                assert_eq!(substs.regions().count(), identity_substs.regions().count());
-                substs
+                assert!(args.len() >= identity_args.len());
+                assert_eq!(args.regions().count(), identity_args.regions().count());
+                args
             }
 
-            DefiningTy::FnDef(_, substs) | DefiningTy::Const(_, substs) => substs,
+            DefiningTy::FnDef(_, args) | DefiningTy::Const(_, args) => args,
         };
 
         let global_mapping = iter::once((tcx.lifetimes.re_static, fr_static));
         let subst_mapping =
-            iter::zip(identity_substs.regions(), fr_substs.regions().map(|r| r.as_var()));
+            iter::zip(identity_args.regions(), fr_args.regions().map(|r| r.as_var()));
 
         UniversalRegionIndices { indices: global_mapping.chain(subst_mapping).collect(), fr_static }
     }
@@ -646,9 +646,9 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
     ) -> ty::Binder<'tcx, &'tcx ty::List<Ty<'tcx>>> {
         let tcx = self.infcx.tcx;
         match defining_ty {
-            DefiningTy::Closure(def_id, substs) => {
+            DefiningTy::Closure(def_id, args) => {
                 assert_eq!(self.mir_def.to_def_id(), def_id);
-                let closure_sig = substs.as_closure().sig();
+                let closure_sig = args.as_closure().sig();
                 let inputs_and_output = closure_sig.inputs_and_output();
                 let bound_vars = tcx.mk_bound_variable_kinds_from_iter(
                     inputs_and_output
@@ -661,7 +661,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
                     kind: ty::BrEnv,
                 };
                 let env_region = ty::Region::new_late_bound(tcx, ty::INNERMOST, br);
-                let closure_ty = tcx.closure_env_ty(def_id, substs, env_region).unwrap();
+                let closure_ty = tcx.closure_env_ty(def_id, args, env_region).unwrap();
 
                 // The "inputs" of the closure in the
                 // signature appear as a tuple. The MIR side
@@ -681,18 +681,18 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
                 )
             }
 
-            DefiningTy::Generator(def_id, substs, movability) => {
+            DefiningTy::Generator(def_id, args, movability) => {
                 assert_eq!(self.mir_def.to_def_id(), def_id);
-                let resume_ty = substs.as_generator().resume_ty();
-                let output = substs.as_generator().return_ty();
-                let generator_ty = Ty::new_generator(tcx, def_id, substs, movability);
+                let resume_ty = args.as_generator().resume_ty();
+                let output = args.as_generator().return_ty();
+                let generator_ty = Ty::new_generator(tcx, def_id, args, movability);
                 let inputs_and_output =
                     self.infcx.tcx.mk_type_list(&[generator_ty, resume_ty, output]);
                 ty::Binder::dummy(inputs_and_output)
             }
 
             DefiningTy::FnDef(def_id, _) => {
-                let sig = tcx.fn_sig(def_id).subst_identity();
+                let sig = tcx.fn_sig(def_id).instantiate_identity();
                 let sig = indices.fold_to_region_vids(tcx, sig);
                 sig.inputs_and_output()
             }
@@ -701,14 +701,14 @@ 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.to_def_id(), def_id);
-                let ty = tcx.type_of(self.mir_def).subst_identity();
+                let ty = tcx.type_of(self.mir_def).instantiate_identity();
                 let ty = indices.fold_to_region_vids(tcx, ty);
                 ty::Binder::dummy(tcx.mk_type_list(&[ty]))
             }
 
-            DefiningTy::InlineConst(def_id, substs) => {
+            DefiningTy::InlineConst(def_id, args) => {
                 assert_eq!(self.mir_def.to_def_id(), def_id);
-                let ty = substs.as_inline_const().ty();
+                let ty = args.as_inline_const().ty();
                 ty::Binder::dummy(tcx.mk_type_list(&[ty]))
             }
         }
@@ -929,7 +929,9 @@ 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 ty::BoundVariableKind::Region(bound_region) = bound_var else {
+            continue;
+        };
         let liberated_region = ty::Region::new_free(tcx, mir_def_id.to_def_id(), bound_region);
         f(liberated_region);
     }
diff --git a/compiler/rustc_builtin_macros/src/asm.rs b/compiler/rustc_builtin_macros/src/asm.rs
index 6187e4f513b..19acefc38e3 100644
--- a/compiler/rustc_builtin_macros/src/asm.rs
+++ b/compiler/rustc_builtin_macros/src/asm.rs
@@ -157,8 +157,7 @@ pub fn parse_asm_args<'a>(
         } else if p.eat_keyword(sym::sym) {
             let expr = p.parse_expr()?;
             let ast::ExprKind::Path(qself, path) = &expr.kind else {
-                let err = diag
-                    .create_err(errors::AsmSymNoPath { span: expr.span });
+                let err = diag.create_err(errors::AsmSymNoPath { span: expr.span });
                 return Err(err);
             };
             let sym = ast::InlineAsmSym {
diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs
index 4401cf8a9c5..ea81cee78b7 100644
--- a/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs
@@ -61,8 +61,8 @@ pub fn cs_cmp(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> Bl
         |cx, fold| match fold {
             CsFold::Single(field) => {
                 let [other_expr] = &field.other_selflike_exprs[..] else {
-                        cx.span_bug(field.span, "not exactly 2 arguments in `derive(Ord)`");
-                    };
+                    cx.span_bug(field.span, "not exactly 2 arguments in `derive(Ord)`");
+                };
                 let args = thin_vec![field.self_expr.clone(), other_expr.clone()];
                 cx.expr_call_global(field.span, cmp_path.clone(), args)
             }
diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs
index 54b6cb7d713..a5b3a504e38 100644
--- a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs
@@ -94,8 +94,8 @@ fn cs_partial_cmp(
         |cx, fold| match fold {
             CsFold::Single(field) => {
                 let [other_expr] = &field.other_selflike_exprs[..] else {
-                        cx.span_bug(field.span, "not exactly 2 arguments in `derive(Ord)`");
-                    };
+                    cx.span_bug(field.span, "not exactly 2 arguments in `derive(Ord)`");
+                };
                 let args = thin_vec![field.self_expr.clone(), other_expr.clone()];
                 cx.expr_call_global(field.span, partial_cmp_path.clone(), args)
             }
diff --git a/compiler/rustc_builtin_macros/src/env.rs b/compiler/rustc_builtin_macros/src/env.rs
index 8f64e332861..bcff475f626 100644
--- a/compiler/rustc_builtin_macros/src/env.rs
+++ b/compiler/rustc_builtin_macros/src/env.rs
@@ -83,7 +83,12 @@ pub fn expand_env<'cx>(
         None => {
             // Use the string literal in the code in the diagnostic to avoid confusing diagnostics,
             // e.g. when the literal contains escape sequences.
-            let ast::ExprKind::Lit(ast::token::Lit { kind: ast::token::LitKind::Str, symbol: original_var, ..}) = &var_expr.kind else {
+            let ast::ExprKind::Lit(ast::token::Lit {
+                kind: ast::token::LitKind::Str,
+                symbol: original_var,
+                ..
+            }) = &var_expr.kind
+            else {
                 unreachable!("`expr_to_string` ensures this is a string lit")
             };
             cx.emit_err(errors::EnvNotDefined {
diff --git a/compiler/rustc_builtin_macros/src/proc_macro_harness.rs b/compiler/rustc_builtin_macros/src/proc_macro_harness.rs
index b35a2e2a292..a7908373b6d 100644
--- a/compiler/rustc_builtin_macros/src/proc_macro_harness.rs
+++ b/compiler/rustc_builtin_macros/src/proc_macro_harness.rs
@@ -89,7 +89,9 @@ impl<'a> CollectProcMacros<'a> {
     }
 
     fn collect_custom_derive(&mut self, item: &'a ast::Item, attr: &'a ast::Attribute) {
-        let Some((trait_name, proc_attrs)) = parse_macro_name_and_helper_attrs(self.handler, attr, "derive") else {
+        let Some((trait_name, proc_attrs)) =
+            parse_macro_name_and_helper_attrs(self.handler, attr, "derive")
+        else {
             return;
         };
 
diff --git a/compiler/rustc_codegen_cranelift/src/abi/comments.rs b/compiler/rustc_codegen_cranelift/src/abi/comments.rs
index 364503fd363..ade6968de2b 100644
--- a/compiler/rustc_codegen_cranelift/src/abi/comments.rs
+++ b/compiler/rustc_codegen_cranelift/src/abi/comments.rs
@@ -80,14 +80,7 @@ pub(super) fn add_local_place_comments<'tcx>(
         return;
     }
     let TyAndLayout { ty, layout } = place.layout();
-    let rustc_target::abi::LayoutS {
-        size,
-        align,
-        abi: _,
-        variants: _,
-        fields: _,
-        largest_niche: _,
-    } = layout.0.0;
+    let rustc_target::abi::LayoutS { size, align, .. } = layout.0.0;
 
     let (kind, extra) = place.debug_comment();
 
diff --git a/compiler/rustc_codegen_cranelift/src/abi/mod.rs b/compiler/rustc_codegen_cranelift/src/abi/mod.rs
index 199fa6861cf..eddb479073c 100644
--- a/compiler/rustc_codegen_cranelift/src/abi/mod.rs
+++ b/compiler/rustc_codegen_cranelift/src/abi/mod.rs
@@ -70,7 +70,7 @@ pub(crate) fn get_function_sig<'tcx>(
     default_call_conv: CallConv,
     inst: Instance<'tcx>,
 ) -> Signature {
-    assert!(!inst.substs.has_infer());
+    assert!(!inst.args.has_infer());
     clif_sig_from_fn_abi(
         tcx,
         default_call_conv,
@@ -377,16 +377,16 @@ pub(crate) fn codegen_terminator_call<'tcx>(
     let ret_place = codegen_place(fx, destination);
 
     // Handle special calls like intrinsics and empty drop glue.
-    let instance = if let ty::FnDef(def_id, substs) = *func.layout().ty.kind() {
+    let instance = if let ty::FnDef(def_id, fn_args) = *func.layout().ty.kind() {
         let instance =
-            ty::Instance::expect_resolve(fx.tcx, ty::ParamEnv::reveal_all(), def_id, substs)
+            ty::Instance::expect_resolve(fx.tcx, ty::ParamEnv::reveal_all(), def_id, fn_args)
                 .polymorphize(fx.tcx);
 
         if fx.tcx.symbol_name(instance).name.starts_with("llvm.") {
             crate::intrinsics::codegen_llvm_intrinsic_call(
                 fx,
                 &fx.tcx.symbol_name(instance).name,
-                substs,
+                fn_args,
                 args,
                 ret_place,
                 target,
@@ -611,7 +611,7 @@ pub(crate) fn codegen_drop<'tcx>(
                 // `Instance::resolve_drop_in_place`?
                 let virtual_drop = Instance {
                     def: ty::InstanceDef::Virtual(drop_instance.def_id(), 0),
-                    substs: drop_instance.substs,
+                    args: drop_instance.args,
                 };
                 let fn_abi =
                     RevealAllLayoutCx(fx.tcx).fn_abi_of_instance(virtual_drop, ty::List::empty());
@@ -648,7 +648,7 @@ pub(crate) fn codegen_drop<'tcx>(
 
                 let virtual_drop = Instance {
                     def: ty::InstanceDef::Virtual(drop_instance.def_id(), 0),
-                    substs: drop_instance.substs,
+                    args: drop_instance.args,
                 };
                 let fn_abi =
                     RevealAllLayoutCx(fx.tcx).fn_abi_of_instance(virtual_drop, ty::List::empty());
diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs
index 334b2780b49..e05f2146f0c 100644
--- a/compiler/rustc_codegen_cranelift/src/base.rs
+++ b/compiler/rustc_codegen_cranelift/src/base.rs
@@ -28,7 +28,7 @@ pub(crate) fn codegen_fn<'tcx>(
     module: &mut dyn Module,
     instance: Instance<'tcx>,
 ) -> CodegenedFunction {
-    debug_assert!(!instance.substs.has_infer());
+    debug_assert!(!instance.args.has_infer());
 
     let symbol_name = tcx.symbol_name(instance).name.to_string();
     let _timer = tcx.prof.generic_activity_with_arg("codegen fn", &*symbol_name);
@@ -578,13 +578,13 @@ fn codegen_stmt<'tcx>(
                     let from_ty = fx.monomorphize(operand.ty(&fx.mir.local_decls, fx.tcx));
                     let to_layout = fx.layout_of(fx.monomorphize(to_ty));
                     match *from_ty.kind() {
-                        ty::FnDef(def_id, substs) => {
+                        ty::FnDef(def_id, args) => {
                             let func_ref = fx.get_function_ref(
                                 Instance::resolve_for_fn_ptr(
                                     fx.tcx,
                                     ParamEnv::reveal_all(),
                                     def_id,
-                                    substs,
+                                    args,
                                 )
                                 .unwrap()
                                 .polymorphize(fx.tcx),
@@ -668,11 +668,11 @@ fn codegen_stmt<'tcx>(
                 ) => {
                     let operand = codegen_operand(fx, operand);
                     match *operand.layout().ty.kind() {
-                        ty::Closure(def_id, substs) => {
+                        ty::Closure(def_id, args) => {
                             let instance = Instance::resolve_closure(
                                 fx.tcx,
                                 def_id,
-                                substs,
+                                args,
                                 ty::ClosureKind::FnOnce,
                             )
                             .expect("failed to normalize and resolve closure during codegen")
diff --git a/compiler/rustc_codegen_cranelift/src/constant.rs b/compiler/rustc_codegen_cranelift/src/constant.rs
index 427340c333e..c3153574295 100644
--- a/compiler/rustc_codegen_cranelift/src/constant.rs
+++ b/compiler/rustc_codegen_cranelift/src/constant.rs
@@ -57,7 +57,7 @@ pub(crate) fn codegen_tls_ref<'tcx>(
     let tls_ptr = if !def_id.is_local() && fx.tcx.needs_thread_local_shim(def_id) {
         let instance = ty::Instance {
             def: ty::InstanceDef::ThreadLocalShim(def_id),
-            substs: ty::InternalSubsts::empty(),
+            args: ty::GenericArgs::empty(),
         };
         let func_ref = fx.get_function_ref(instance);
         let call = fx.bcx.ins().call(func_ref, &[]);
diff --git a/compiler/rustc_codegen_cranelift/src/global_asm.rs b/compiler/rustc_codegen_cranelift/src/global_asm.rs
index 63a1f6959dd..baadd7a9e81 100644
--- a/compiler/rustc_codegen_cranelift/src/global_asm.rs
+++ b/compiler/rustc_codegen_cranelift/src/global_asm.rs
@@ -42,7 +42,7 @@ pub(crate) fn codegen_global_asm_item(tcx: TyCtxt<'_>, global_asm: &mut String,
                         InlineAsmOperand::SymFn { anon_const } => {
                             let ty = tcx.typeck_body(anon_const.body).node_type(anon_const.hir_id);
                             let instance = match ty.kind() {
-                                &ty::FnDef(def_id, substs) => Instance::new(def_id, substs),
+                                &ty::FnDef(def_id, args) => Instance::new(def_id, args),
                                 _ => span_bug!(op_sp, "asm sym is not a function"),
                             };
                             let symbol = tcx.symbol_name(instance);
diff --git a/compiler/rustc_codegen_cranelift/src/inline_asm.rs b/compiler/rustc_codegen_cranelift/src/inline_asm.rs
index 3ba530c040f..518e3da07a4 100644
--- a/compiler/rustc_codegen_cranelift/src/inline_asm.rs
+++ b/compiler/rustc_codegen_cranelift/src/inline_asm.rs
@@ -254,12 +254,12 @@ pub(crate) fn codegen_inline_asm<'tcx>(
             }
             InlineAsmOperand::SymFn { ref value } => {
                 let literal = fx.monomorphize(value.literal);
-                if let ty::FnDef(def_id, substs) = *literal.ty().kind() {
+                if let ty::FnDef(def_id, args) = *literal.ty().kind() {
                     let instance = ty::Instance::resolve_for_fn_ptr(
                         fx.tcx,
                         ty::ParamEnv::reveal_all(),
                         def_id,
-                        substs,
+                        args,
                     )
                     .unwrap();
                     let symbol = fx.tcx.symbol_name(instance);
diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm.rs
index f67fdb59270..63b5402f2b6 100644
--- a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm.rs
+++ b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm.rs
@@ -3,23 +3,35 @@
 use crate::intrinsics::*;
 use crate::prelude::*;
 
-use rustc_middle::ty::subst::SubstsRef;
+use rustc_middle::ty::GenericArgsRef;
 
 pub(crate) fn codegen_llvm_intrinsic_call<'tcx>(
     fx: &mut FunctionCx<'_, '_, 'tcx>,
     intrinsic: &str,
-    substs: SubstsRef<'tcx>,
+    generic_args: GenericArgsRef<'tcx>,
     args: &[mir::Operand<'tcx>],
     ret: CPlace<'tcx>,
     target: Option<BasicBlock>,
 ) {
     if intrinsic.starts_with("llvm.aarch64") {
         return llvm_aarch64::codegen_aarch64_llvm_intrinsic_call(
-            fx, intrinsic, substs, args, ret, target,
+            fx,
+            intrinsic,
+            generic_args,
+            args,
+            ret,
+            target,
         );
     }
     if intrinsic.starts_with("llvm.x86") {
-        return llvm_x86::codegen_x86_llvm_intrinsic_call(fx, intrinsic, substs, args, ret, target);
+        return llvm_x86::codegen_x86_llvm_intrinsic_call(
+            fx,
+            intrinsic,
+            generic_args,
+            args,
+            ret,
+            target,
+        );
     }
 
     match intrinsic {
diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_aarch64.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_aarch64.rs
index 33b2f4702a7..c20a9915930 100644
--- a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_aarch64.rs
+++ b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_aarch64.rs
@@ -3,12 +3,12 @@
 use crate::intrinsics::*;
 use crate::prelude::*;
 
-use rustc_middle::ty::subst::SubstsRef;
+use rustc_middle::ty::GenericArgsRef;
 
 pub(crate) fn codegen_aarch64_llvm_intrinsic_call<'tcx>(
     fx: &mut FunctionCx<'_, '_, 'tcx>,
     intrinsic: &str,
-    _substs: SubstsRef<'tcx>,
+    _args: GenericArgsRef<'tcx>,
     args: &[mir::Operand<'tcx>],
     ret: CPlace<'tcx>,
     target: Option<BasicBlock>,
diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs
index 24ad0083a22..18162fb5ab2 100644
--- a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs
+++ b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs
@@ -3,12 +3,12 @@
 use crate::intrinsics::*;
 use crate::prelude::*;
 
-use rustc_middle::ty::subst::SubstsRef;
+use rustc_middle::ty::GenericArgsRef;
 
 pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>(
     fx: &mut FunctionCx<'_, '_, 'tcx>,
     intrinsic: &str,
-    _substs: SubstsRef<'tcx>,
+    _args: GenericArgsRef<'tcx>,
     args: &[mir::Operand<'tcx>],
     ret: CPlace<'tcx>,
     target: Option<BasicBlock>,
diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
index 5862f18299e..da8ab361331 100644
--- a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
+++ b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
@@ -24,7 +24,7 @@ pub(crate) use llvm::codegen_llvm_intrinsic_call;
 use rustc_middle::ty;
 use rustc_middle::ty::layout::{HasParamEnv, ValidityRequirement};
 use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths};
-use rustc_middle::ty::subst::SubstsRef;
+use rustc_middle::ty::GenericArgsRef;
 use rustc_span::symbol::{kw, sym, Symbol};
 
 use crate::prelude::*;
@@ -213,13 +213,13 @@ pub(crate) fn codegen_intrinsic_call<'tcx>(
     source_info: mir::SourceInfo,
 ) {
     let intrinsic = fx.tcx.item_name(instance.def_id());
-    let substs = instance.substs;
+    let instance_args = instance.args;
 
     if intrinsic.as_str().starts_with("simd_") {
         self::simd::codegen_simd_intrinsic_call(
             fx,
             intrinsic,
-            substs,
+            instance_args,
             args,
             destination,
             target.expect("target for simd intrinsic"),
@@ -233,7 +233,7 @@ pub(crate) fn codegen_intrinsic_call<'tcx>(
             fx,
             instance,
             intrinsic,
-            substs,
+            instance_args,
             args,
             destination,
             target,
@@ -365,7 +365,7 @@ fn codegen_regular_intrinsic_call<'tcx>(
     fx: &mut FunctionCx<'_, '_, 'tcx>,
     instance: Instance<'tcx>,
     intrinsic: Symbol,
-    substs: SubstsRef<'tcx>,
+    generic_args: GenericArgsRef<'tcx>,
     args: &[mir::Operand<'tcx>],
     ret: CPlace<'tcx>,
     destination: Option<BasicBlock>,
@@ -394,7 +394,7 @@ fn codegen_regular_intrinsic_call<'tcx>(
             let dst = dst.load_scalar(fx);
             let count = count.load_scalar(fx);
 
-            let elem_ty = substs.type_at(0);
+            let elem_ty = generic_args.type_at(0);
             let elem_size: u64 = fx.layout_of(elem_ty).size.bytes();
             assert_eq!(args.len(), 3);
             let byte_amount =
@@ -410,7 +410,7 @@ fn codegen_regular_intrinsic_call<'tcx>(
             let src = src.load_scalar(fx);
             let count = count.load_scalar(fx);
 
-            let elem_ty = substs.type_at(0);
+            let elem_ty = generic_args.type_at(0);
             let elem_size: u64 = fx.layout_of(elem_ty).size.bytes();
             assert_eq!(args.len(), 3);
             let byte_amount =
@@ -428,7 +428,7 @@ fn codegen_regular_intrinsic_call<'tcx>(
         sym::size_of_val => {
             intrinsic_args!(fx, args => (ptr); intrinsic);
 
-            let layout = fx.layout_of(substs.type_at(0));
+            let layout = fx.layout_of(generic_args.type_at(0));
             // Note: Can't use is_unsized here as truly unsized types need to take the fixed size
             // branch
             let size = if let Abi::ScalarPair(_, _) = ptr.layout().abi {
@@ -443,7 +443,7 @@ fn codegen_regular_intrinsic_call<'tcx>(
         sym::min_align_of_val => {
             intrinsic_args!(fx, args => (ptr); intrinsic);
 
-            let layout = fx.layout_of(substs.type_at(0));
+            let layout = fx.layout_of(generic_args.type_at(0));
             // Note: Can't use is_unsized here as truly unsized types need to take the fixed size
             // branch
             let align = if let Abi::ScalarPair(_, _) = ptr.layout().abi {
@@ -602,7 +602,7 @@ fn codegen_regular_intrinsic_call<'tcx>(
         sym::assert_inhabited | sym::assert_zero_valid | sym::assert_mem_uninitialized_valid => {
             intrinsic_args!(fx, args => (); intrinsic);
 
-            let ty = substs.type_at(0);
+            let ty = generic_args.type_at(0);
 
             let requirement = ValidityRequirement::from_intrinsic(intrinsic);
 
@@ -674,7 +674,7 @@ fn codegen_regular_intrinsic_call<'tcx>(
             intrinsic_args!(fx, args => (ptr, base); intrinsic);
             let ptr = ptr.load_scalar(fx);
             let base = base.load_scalar(fx);
-            let ty = substs.type_at(0);
+            let ty = generic_args.type_at(0);
 
             let pointee_size: u64 = fx.layout_of(ty).size.bytes();
             let diff_bytes = fx.bcx.ins().isub(ptr, base);
@@ -720,7 +720,7 @@ fn codegen_regular_intrinsic_call<'tcx>(
             intrinsic_args!(fx, args => (ptr); intrinsic);
             let ptr = ptr.load_scalar(fx);
 
-            let ty = substs.type_at(0);
+            let ty = generic_args.type_at(0);
             match ty.kind() {
                 ty::Uint(UintTy::U128) | ty::Int(IntTy::I128) => {
                     // FIXME implement 128bit atomics
@@ -751,7 +751,7 @@ fn codegen_regular_intrinsic_call<'tcx>(
             intrinsic_args!(fx, args => (ptr, val); intrinsic);
             let ptr = ptr.load_scalar(fx);
 
-            let ty = substs.type_at(0);
+            let ty = generic_args.type_at(0);
             match ty.kind() {
                 ty::Uint(UintTy::U128) | ty::Int(IntTy::I128) => {
                     // FIXME implement 128bit atomics
@@ -1128,7 +1128,7 @@ fn codegen_regular_intrinsic_call<'tcx>(
             let lhs_ref = lhs_ref.load_scalar(fx);
             let rhs_ref = rhs_ref.load_scalar(fx);
 
-            let size = fx.layout_of(substs.type_at(0)).layout.size();
+            let size = fx.layout_of(generic_args.type_at(0)).layout.size();
             // FIXME add and use emit_small_memcmp
             let is_eq_value = if size == Size::ZERO {
                 // No bytes means they're trivially equal
diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs
index 6741362e8b6..d1c29f24ab9 100644
--- a/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs
+++ b/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs
@@ -1,6 +1,6 @@
 //! Codegen `extern "platform-intrinsic"` intrinsics.
 
-use rustc_middle::ty::subst::SubstsRef;
+use rustc_middle::ty::GenericArgsRef;
 use rustc_span::Symbol;
 use rustc_target::abi::Endian;
 
@@ -21,7 +21,7 @@ fn report_simd_type_validation_error(
 pub(super) fn codegen_simd_intrinsic_call<'tcx>(
     fx: &mut FunctionCx<'_, '_, 'tcx>,
     intrinsic: Symbol,
-    _substs: SubstsRef<'tcx>,
+    _args: GenericArgsRef<'tcx>,
     args: &[mir::Operand<'tcx>],
     ret: CPlace<'tcx>,
     target: BasicBlock,
diff --git a/compiler/rustc_codegen_cranelift/src/main_shim.rs b/compiler/rustc_codegen_cranelift/src/main_shim.rs
index 20ba73f3852..b5efe44d8b3 100644
--- a/compiler/rustc_codegen_cranelift/src/main_shim.rs
+++ b/compiler/rustc_codegen_cranelift/src/main_shim.rs
@@ -1,6 +1,6 @@
 use rustc_hir::LangItem;
-use rustc_middle::ty::subst::GenericArg;
 use rustc_middle::ty::AssocKind;
+use rustc_middle::ty::GenericArg;
 use rustc_session::config::{sigpipe, EntryFnType};
 use rustc_span::symbol::Ident;
 
@@ -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)]),
+                    tcx.mk_args(&[GenericArg::from(main_ret_ty)]),
                 )
                 .unwrap()
                 .unwrap()
@@ -146,7 +146,7 @@ pub(crate) fn maybe_create_entry_wrapper(
                     tcx,
                     ParamEnv::reveal_all(),
                     start_def_id,
-                    tcx.mk_substs(&[main_ret_ty.into()]),
+                    tcx.mk_args(&[main_ret_ty.into()]),
                 )
                 .unwrap()
                 .unwrap()
diff --git a/compiler/rustc_codegen_cranelift/src/pretty_clif.rs b/compiler/rustc_codegen_cranelift/src/pretty_clif.rs
index 5a4f9e80445..0ead50c34ea 100644
--- a/compiler/rustc_codegen_cranelift/src/pretty_clif.rs
+++ b/compiler/rustc_codegen_cranelift/src/pretty_clif.rs
@@ -9,7 +9,7 @@
 //!
 //! function u0:22(i64) -> i8, i8 system_v {
 //! ; symbol _ZN97_$LT$example..IsNotEmpty$u20$as$u20$mini_core..FnOnce$LT$$LP$$RF$$RF$$u5b$u16$u5d$$C$$RP$$GT$$GT$9call_once17hd517c453d67c0915E
-//! ; instance Instance { def: Item(WithOptConstParam { did: DefId(0:42 ~ example[4e51]::{impl#0}::call_once), const_param_did: None }), substs: [ReErased, ReErased] }
+//! ; instance Instance { def: Item(WithOptConstParam { did: DefId(0:42 ~ example[4e51]::{impl#0}::call_once), const_param_did: None }), args: [ReErased, ReErased] }
 //! ; abi FnAbi { args: [ArgAbi { layout: TyAndLayout { ty: IsNotEmpty, layout: Layout { size: Size(0 bytes), align: AbiAndPrefAlign { abi: Align(1 bytes), pref: Align(8 bytes) }, abi: Aggregate { sized: true }, fields: Arbitrary { offsets: [], memory_index: [] }, largest_niche: None, variants: Single { index: 0 } } }, mode: Ignore }, ArgAbi { layout: TyAndLayout { ty: &&[u16], layout: Layout { size: Size(8 bytes), align: AbiAndPrefAlign { abi: Align(8 bytes), pref: Align(8 bytes) }, abi: Scalar(Initialized { value: Pointer(AddressSpace(0)), valid_range: 1..=18446744073709551615 }), fields: Primitive, largest_niche: Some(Niche { offset: Size(0 bytes), value: Pointer(AddressSpace(0)), valid_range: 1..=18446744073709551615 }), variants: Single { index: 0 } } }, mode: Direct(ArgAttributes { regular: NonNull | NoUndef, arg_ext: None, pointee_size: Size(0 bytes), pointee_align: Some(Align(8 bytes)) }) }], ret: ArgAbi { layout: TyAndLayout { ty: (u8, u8), layout: Layout { size: Size(2 bytes), align: AbiAndPrefAlign { abi: Align(1 bytes), pref: Align(8 bytes) }, abi: ScalarPair(Initialized { value: Int(I8, false), valid_range: 0..=255 }, Initialized { value: Int(I8, false), valid_range: 0..=255 }), fields: Arbitrary { offsets: [Size(0 bytes), Size(1 bytes)], memory_index: [0, 1] }, largest_niche: None, variants: Single { index: 0 } } }, mode: Pair(ArgAttributes { regular: NoUndef, arg_ext: None, pointee_size: Size(0 bytes), pointee_align: None }, ArgAttributes { regular: NoUndef, arg_ext: None, pointee_size: Size(0 bytes), pointee_align: None }) }, c_variadic: false, fixed_count: 1, conv: Rust, can_unwind: false }
 //!
 //! ; kind  loc.idx   param    pass mode                            ty
@@ -25,7 +25,7 @@
 //!
 //!     ss0 = explicit_slot 16
 //!     sig0 = (i64, i64) -> i8, i8 system_v
-//!     fn0 = colocated u0:23 sig0 ; Instance { def: Item(WithOptConstParam { did: DefId(0:46 ~ example[4e51]::{impl#1}::call_mut), const_param_did: None }), substs: [ReErased, ReErased] }
+//!     fn0 = colocated u0:23 sig0 ; Instance { def: Item(WithOptConstParam { did: DefId(0:46 ~ example[4e51]::{impl#1}::call_mut), const_param_did: None }), args: [ReErased, ReErased] }
 //!
 //! block0(v0: i64):
 //!     nop
@@ -261,7 +261,7 @@ pub(crate) fn write_clif_file(
 
 impl fmt::Debug for FunctionCx<'_, '_, '_> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        writeln!(f, "{:?}", self.instance.substs)?;
+        writeln!(f, "{:?}", self.instance.args)?;
         writeln!(f, "{:?}", self.local_map)?;
 
         let mut clif = String::new();
diff --git a/compiler/rustc_codegen_cranelift/src/value_and_place.rs b/compiler/rustc_codegen_cranelift/src/value_and_place.rs
index 133c989b686..ec0b61a7ce5 100644
--- a/compiler/rustc_codegen_cranelift/src/value_and_place.rs
+++ b/compiler/rustc_codegen_cranelift/src/value_and_place.rs
@@ -850,11 +850,11 @@ pub(crate) fn assert_assignable<'tcx>(
                 }
             }
         }
-        (&ty::Adt(adt_def_a, substs_a), &ty::Adt(adt_def_b, substs_b))
+        (&ty::Adt(adt_def_a, args_a), &ty::Adt(adt_def_b, args_b))
             if adt_def_a.did() == adt_def_b.did() =>
         {
-            let mut types_a = substs_a.types();
-            let mut types_b = substs_b.types();
+            let mut types_a = args_a.types();
+            let mut types_b = args_b.types();
             loop {
                 match (types_a.next(), types_b.next()) {
                     (Some(a), Some(b)) => assert_assignable(fx, a, b, limit - 1),
@@ -864,11 +864,11 @@ pub(crate) fn assert_assignable<'tcx>(
             }
         }
         (ty::Array(a, _), ty::Array(b, _)) => assert_assignable(fx, *a, *b, limit - 1),
-        (&ty::Closure(def_id_a, substs_a), &ty::Closure(def_id_b, substs_b))
+        (&ty::Closure(def_id_a, args_a), &ty::Closure(def_id_b, args_b))
             if def_id_a == def_id_b =>
         {
-            let mut types_a = substs_a.types();
-            let mut types_b = substs_b.types();
+            let mut types_a = args_a.types();
+            let mut types_b = args_b.types();
             loop {
                 match (types_a.next(), types_b.next()) {
                     (Some(a), Some(b)) => assert_assignable(fx, a, b, limit - 1),
diff --git a/compiler/rustc_codegen_gcc/src/callee.rs b/compiler/rustc_codegen_gcc/src/callee.rs
index 433b2585f82..a96bd66ba79 100644
--- a/compiler/rustc_codegen_gcc/src/callee.rs
+++ b/compiler/rustc_codegen_gcc/src/callee.rs
@@ -17,8 +17,8 @@ use crate::context::CodegenCx;
 pub fn get_fn<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, instance: Instance<'tcx>) -> Function<'gcc> {
     let tcx = cx.tcx();
 
-    assert!(!instance.substs.has_infer());
-    assert!(!instance.substs.has_escaping_bound_vars());
+    assert!(!instance.args.has_infer());
+    assert!(!instance.args.has_escaping_bound_vars());
 
     let sym = tcx.symbol_name(instance).name;
 
@@ -100,7 +100,7 @@ pub fn get_fn<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, instance: Instance<'tcx>)
             // whether we are sharing generics or not. The important thing here is
             // that the visibility we apply to the declaration is the same one that
             // has been applied to the definition (wherever that definition may be).
-            let is_generic = instance.substs.non_erasable_generics().next().is_some();
+            let is_generic = instance.args.non_erasable_generics().next().is_some();
 
             if is_generic {
                 // This is a monomorphization. Its expected visibility depends
diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs
index 0b208be4e62..fe604be33b6 100644
--- a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs
+++ b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs
@@ -92,8 +92,8 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
         let tcx = self.tcx;
         let callee_ty = instance.ty(tcx, ty::ParamEnv::reveal_all());
 
-        let (def_id, substs) = match *callee_ty.kind() {
-            ty::FnDef(def_id, substs) => (def_id, substs),
+        let (def_id, fn_args) = match *callee_ty.kind() {
+            ty::FnDef(def_id, fn_args) => (def_id, fn_args),
             _ => bug!("expected fn item type, found {}", callee_ty),
         };
 
@@ -142,7 +142,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
                 }
 
                 sym::volatile_load | sym::unaligned_volatile_load => {
-                    let tp_ty = substs.type_at(0);
+                    let tp_ty = fn_args.type_at(0);
                     let mut ptr = args[0].immediate();
                     if let PassMode::Cast(ty, _) = &fn_abi.ret.mode {
                         ptr = self.pointercast(ptr, self.type_ptr_to(ty.gcc_type(self)));
@@ -264,7 +264,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
 
                 sym::raw_eq => {
                     use rustc_target::abi::Abi::*;
-                    let tp_ty = substs.type_at(0);
+                    let tp_ty = fn_args.type_at(0);
                     let layout = self.layout_of(tp_ty).layout;
                     let _use_integer_compare = match layout.abi() {
                         Scalar(_) | ScalarPair(_, _) => true,
diff --git a/compiler/rustc_codegen_gcc/src/mono_item.rs b/compiler/rustc_codegen_gcc/src/mono_item.rs
index 342b830cedb..3322d56513b 100644
--- a/compiler/rustc_codegen_gcc/src/mono_item.rs
+++ b/compiler/rustc_codegen_gcc/src/mono_item.rs
@@ -31,7 +31,7 @@ impl<'gcc, 'tcx> PreDefineMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
 
     #[cfg_attr(not(feature="master"), allow(unused_variables))]
     fn predefine_fn(&self, instance: Instance<'tcx>, linkage: Linkage, visibility: Visibility, symbol_name: &str) {
-        assert!(!instance.substs.has_infer());
+        assert!(!instance.args.has_infer());
 
         let fn_abi = self.fn_abi_of_instance(instance, ty::List::empty());
         self.linkage.set(base::linkage_to_gcc(linkage));
diff --git a/compiler/rustc_codegen_gcc/src/type_of.rs b/compiler/rustc_codegen_gcc/src/type_of.rs
index e0823888f67..84d57838512 100644
--- a/compiler/rustc_codegen_gcc/src/type_of.rs
+++ b/compiler/rustc_codegen_gcc/src/type_of.rs
@@ -101,7 +101,7 @@ fn uncached_gcc_type<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, layout: TyAndLayout
             if let (&ty::Generator(_, _, _), &Variants::Single { index }) =
                 (layout.ty.kind(), &layout.variants)
             {
-                write!(&mut name, "::{}", ty::GeneratorSubsts::variant_name(index)).unwrap();
+                write!(&mut name, "::{}", ty::GeneratorArgs::variant_name(index)).unwrap();
             }
             Some(name)
         }
@@ -282,7 +282,7 @@ impl<'tcx> LayoutGccExt<'tcx> for TyAndLayout<'tcx> {
             }
             // only wide pointer boxes are handled as pointers
             // thin pointer boxes with scalar allocators are handled by the general logic below
-            ty::Adt(def, substs) if def.is_box() && cx.layout_of(substs.type_at(1)).is_zst() => {
+            ty::Adt(def, args) if def.is_box() && cx.layout_of(args.type_at(1)).is_zst() => {
                 let ptr_ty = Ty::new_mut_ptr(cx.tcx,self.ty.boxed_ty());
                 return cx.layout_of(ptr_ty).scalar_pair_element_gcc_type(cx, index, immediate);
             }
diff --git a/compiler/rustc_codegen_llvm/src/callee.rs b/compiler/rustc_codegen_llvm/src/callee.rs
index 4b9ca2e7d19..5d3e245f45f 100644
--- a/compiler/rustc_codegen_llvm/src/callee.rs
+++ b/compiler/rustc_codegen_llvm/src/callee.rs
@@ -27,8 +27,8 @@ pub fn get_fn<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'tcx>) ->
 
     debug!("get_fn(instance={:?})", instance);
 
-    assert!(!instance.substs.has_infer());
-    assert!(!instance.substs.has_escaping_bound_vars());
+    assert!(!instance.args.has_infer());
+    assert!(!instance.args.has_escaping_bound_vars());
 
     if let Some(&llfn) = cx.instances.borrow().get(&instance) {
         return llfn;
@@ -129,7 +129,7 @@ pub fn get_fn<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'tcx>) ->
         unsafe {
             llvm::LLVMRustSetLinkage(llfn, llvm::Linkage::ExternalLinkage);
 
-            let is_generic = instance.substs.non_erasable_generics().next().is_some();
+            let is_generic = instance.args.non_erasable_generics().next().is_some();
 
             if is_generic {
                 // This is a monomorphization. Its expected visibility depends
diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs
index 42fdbd78618..56a5c9e9061 100644
--- a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs
+++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs
@@ -22,7 +22,7 @@ use rustc_middle::mir::coverage::{
 use rustc_middle::mir::Coverage;
 use rustc_middle::ty;
 use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt};
-use rustc_middle::ty::subst::InternalSubsts;
+use rustc_middle::ty::GenericArgs;
 use rustc_middle::ty::Instance;
 use rustc_middle::ty::Ty;
 
@@ -250,7 +250,7 @@ fn declare_unused_fn<'tcx>(cx: &CodegenCx<'_, 'tcx>, def_id: DefId) -> Instance<
 
     let instance = Instance::new(
         def_id,
-        InternalSubsts::for_item(tcx, def_id, |param, _| {
+        GenericArgs::for_item(tcx, def_id, |param, _| {
             if let ty::GenericParamDefKind::Lifetime = param.kind {
                 tcx.lifetimes.re_erased.into()
             } else {
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs b/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs
index 65cbd5edc59..d174a3593b9 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs
@@ -91,7 +91,7 @@ fn make_mir_scope<'ll, 'tcx>(
             // FIXME(eddyb) this would be `self.monomorphize(&callee)`
             // if this is moved to `rustc_codegen_ssa::mir::debuginfo`.
             let callee = cx.tcx.subst_and_normalize_erasing_regions(
-                instance.substs,
+                instance.args,
                 ty::ParamEnv::reveal_all(),
                 ty::EarlyBinder::bind(callee),
             );
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
index d61400d3fa3..c6996f2e16a 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
@@ -449,7 +449,7 @@ pub fn type_di_node<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> &'ll D
         }
         // Box<T, A> may have a non-ZST allocator A. In that case, we
         // cannot treat Box<T, A> as just an owned alias of `*mut T`.
-        ty::Adt(def, substs) if def.is_box() && cx.layout_of(substs.type_at(1)).is_zst() => {
+        ty::Adt(def, args) if def.is_box() && cx.layout_of(args.type_at(1)).is_zst() => {
             build_pointer_or_reference_di_node(cx, t, t.boxed_ty(), unique_type_id)
         }
         ty::FnDef(..) | ty::FnPtr(_) => build_subroutine_type_di_node(cx, unique_type_id),
@@ -739,7 +739,10 @@ fn build_foreign_type_di_node<'ll, 'tcx>(
     debug!("build_foreign_type_di_node: {:?}", t);
 
     let &ty::Foreign(def_id) = unique_type_id.expect_ty().kind() else {
-        bug!("build_foreign_type_di_node() called with unexpected type: {:?}", unique_type_id.expect_ty());
+        bug!(
+            "build_foreign_type_di_node() called with unexpected type: {:?}",
+            unique_type_id.expect_ty()
+        );
     };
 
     build_type_with_children(
@@ -1004,12 +1007,12 @@ fn build_upvar_field_di_nodes<'ll, 'tcx>(
     closure_or_generator_di_node: &'ll DIType,
 ) -> SmallVec<&'ll DIType> {
     let (&def_id, up_var_tys) = match closure_or_generator_ty.kind() {
-        ty::Generator(def_id, substs, _) => {
-            let upvar_tys: SmallVec<_> = substs.as_generator().prefix_tys().collect();
+        ty::Generator(def_id, args, _) => {
+            let upvar_tys: SmallVec<_> = args.as_generator().prefix_tys().collect();
             (def_id, upvar_tys)
         }
-        ty::Closure(def_id, substs) => {
-            let upvar_tys: SmallVec<_> = substs.as_closure().upvar_tys().collect();
+        ty::Closure(def_id, args) => {
+            let upvar_tys: SmallVec<_> = args.as_closure().upvar_tys().collect();
             (def_id, upvar_tys)
         }
         _ => {
@@ -1099,7 +1102,7 @@ fn build_closure_env_di_node<'ll, 'tcx>(
     unique_type_id: UniqueTypeId<'tcx>,
 ) -> DINodeCreationResult<'ll> {
     let closure_env_type = unique_type_id.expect_ty();
-    let &ty::Closure(def_id, _substs) = closure_env_type.kind() else {
+    let &ty::Closure(def_id, _args) = closure_env_type.kind() else {
         bug!("build_closure_env_di_node() called with non-closure-type: {:?}", closure_env_type)
     };
     let containing_scope = get_namespace_for_item(cx, def_id);
@@ -1177,11 +1180,11 @@ fn build_generic_type_param_di_nodes<'ll, 'tcx>(
     cx: &CodegenCx<'ll, 'tcx>,
     ty: Ty<'tcx>,
 ) -> SmallVec<&'ll DIType> {
-    if let ty::Adt(def, substs) = *ty.kind() {
-        if substs.types().next().is_some() {
+    if let ty::Adt(def, args) = *ty.kind() {
+        if args.types().next().is_some() {
             let generics = cx.tcx.generics_of(def.did());
             let names = get_parameter_names(cx, generics);
-            let template_params: SmallVec<_> = iter::zip(substs, names)
+            let template_params: SmallVec<_> = iter::zip(args, names)
                 .filter_map(|(kind, name)| {
                     kind.as_type().map(|ty| {
                         let actual_type =
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs
index b2765ffc934..88040557a9b 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs
@@ -12,7 +12,7 @@ use rustc_middle::{
     ty::{
         self,
         layout::{LayoutOf, TyAndLayout},
-        AdtDef, GeneratorSubsts, Ty,
+        AdtDef, GeneratorArgs, Ty,
     },
 };
 use rustc_target::abi::{Align, Endian, Size, TagEncoding, VariantIdx, Variants};
@@ -199,7 +199,7 @@ pub(super) fn build_enum_type_di_node<'ll, 'tcx>(
     let enum_type = unique_type_id.expect_ty();
     let &ty::Adt(enum_adt_def, _) = enum_type.kind() else {
         bug!("build_enum_type_di_node() called with non-enum type: `{:?}`", enum_type)
-        };
+    };
 
     let enum_type_and_layout = cx.layout_of(enum_type);
     let enum_type_name = compute_debuginfo_type_name(cx.tcx, enum_type, false);
@@ -667,19 +667,21 @@ fn build_union_fields_for_direct_tag_generator<'ll, 'tcx>(
     generator_type_and_layout: TyAndLayout<'tcx>,
     generator_type_di_node: &'ll DIType,
 ) -> SmallVec<&'ll DIType> {
-    let Variants::Multiple { tag_encoding: TagEncoding::Direct, tag_field, .. } = generator_type_and_layout.variants else {
+    let Variants::Multiple { tag_encoding: TagEncoding::Direct, tag_field, .. } =
+        generator_type_and_layout.variants
+    else {
         bug!("This function only supports layouts with directly encoded tags.")
     };
 
-    let (generator_def_id, generator_substs) = match generator_type_and_layout.ty.kind() {
-        &ty::Generator(def_id, substs, _) => (def_id, substs.as_generator()),
+    let (generator_def_id, generator_args) = match generator_type_and_layout.ty.kind() {
+        &ty::Generator(def_id, args, _) => (def_id, args.as_generator()),
         _ => unreachable!(),
     };
 
     let generator_layout = cx.tcx.optimized_mir(generator_def_id).generator_layout().unwrap();
 
     let common_upvar_names = cx.tcx.closure_saved_names_of_captured_variables(generator_def_id);
-    let variant_range = generator_substs.variant_range(generator_def_id, cx.tcx);
+    let variant_range = generator_args.variant_range(generator_def_id, cx.tcx);
     let variant_count = (variant_range.start.as_u32()..variant_range.end.as_u32()).len();
 
     let tag_base_type = tag_base_type(cx, generator_type_and_layout);
@@ -689,11 +691,11 @@ fn build_union_fields_for_direct_tag_generator<'ll, 'tcx>(
         generator_type_di_node,
         variant_range
             .clone()
-            .map(|variant_index| (variant_index, GeneratorSubsts::variant_name(variant_index))),
+            .map(|variant_index| (variant_index, GeneratorArgs::variant_name(variant_index))),
     );
 
     let discriminants: IndexVec<VariantIdx, DiscrResult> = {
-        let discriminants_iter = generator_substs.discriminants(generator_def_id, cx.tcx);
+        let discriminants_iter = generator_args.discriminants(generator_def_id, cx.tcx);
         let mut discriminants: IndexVec<VariantIdx, DiscrResult> =
             IndexVec::with_capacity(variant_count);
         for (variant_index, discr) in discriminants_iter {
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs
index 8746ce0c5b1..b4beb80ca8b 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs
@@ -10,7 +10,7 @@ use rustc_middle::{
     ty::{
         self,
         layout::{IntegerExt, LayoutOf, PrimitiveExt, TyAndLayout},
-        AdtDef, GeneratorSubsts, Ty, VariantDef,
+        AdtDef, GeneratorArgs, Ty, VariantDef,
     },
 };
 use rustc_span::Symbol;
@@ -51,7 +51,7 @@ pub(super) fn build_enum_type_di_node<'ll, 'tcx>(
     let enum_type = unique_type_id.expect_ty();
     let &ty::Adt(enum_adt_def, _) = enum_type.kind() else {
         bug!("build_enum_type_di_node() called with non-enum type: `{:?}`", enum_type)
-        };
+    };
 
     let enum_type_and_layout = cx.layout_of(enum_type);
 
@@ -325,7 +325,7 @@ pub fn build_generator_variant_struct_type_di_node<'ll, 'tcx>(
     generator_layout: &GeneratorLayout<'tcx>,
     common_upvar_names: &IndexSlice<FieldIdx, Symbol>,
 ) -> &'ll DIType {
-    let variant_name = GeneratorSubsts::variant_name(variant_index);
+    let variant_name = GeneratorArgs::variant_name(variant_index);
     let unique_type_id = UniqueTypeId::for_enum_variant_struct_type(
         cx.tcx,
         generator_type_and_layout.ty,
@@ -334,8 +334,8 @@ pub fn build_generator_variant_struct_type_di_node<'ll, 'tcx>(
 
     let variant_layout = generator_type_and_layout.for_variant(cx, variant_index);
 
-    let generator_substs = match generator_type_and_layout.ty.kind() {
-        ty::Generator(_, substs, _) => substs.as_generator(),
+    let generator_args = match generator_type_and_layout.ty.kind() {
+        ty::Generator(_, args, _) => args.as_generator(),
         _ => unreachable!(),
     };
 
@@ -377,7 +377,7 @@ pub fn build_generator_variant_struct_type_di_node<'ll, 'tcx>(
                 .collect();
 
             // Fields that are common to all states
-            let common_fields: SmallVec<_> = generator_substs
+            let common_fields: SmallVec<_> = generator_args
                 .prefix_tys()
                 .zip(common_upvar_names)
                 .enumerate()
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs
index 4d1cd64865f..feac40d8c30 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs
@@ -57,7 +57,7 @@ pub(super) fn build_enum_type_di_node<'ll, 'tcx>(
     let enum_type = unique_type_id.expect_ty();
     let &ty::Adt(enum_adt_def, _) = enum_type.kind() else {
         bug!("build_enum_type_di_node() called with non-enum type: `{:?}`", enum_type)
-        };
+    };
 
     let containing_scope = get_namespace_for_item(cx, enum_adt_def.did());
     let enum_type_and_layout = cx.layout_of(enum_type);
@@ -132,9 +132,9 @@ pub(super) fn build_generator_di_node<'ll, 'tcx>(
     unique_type_id: UniqueTypeId<'tcx>,
 ) -> DINodeCreationResult<'ll> {
     let generator_type = unique_type_id.expect_ty();
-    let &ty::Generator(generator_def_id, _, _ ) = generator_type.kind() else {
+    let &ty::Generator(generator_def_id, _, _) = generator_type.kind() else {
         bug!("build_generator_di_node() called with non-generator type: `{:?}`", generator_type)
-        };
+    };
 
     let containing_scope = get_namespace_for_item(cx, generator_def_id);
     let generator_type_and_layout = cx.layout_of(generator_type);
@@ -158,7 +158,9 @@ pub(super) fn build_generator_di_node<'ll, 'tcx>(
             let generator_layout =
                 cx.tcx.optimized_mir(generator_def_id).generator_layout().unwrap();
 
-            let Variants::Multiple { tag_encoding: TagEncoding::Direct, ref variants, .. } = generator_type_and_layout.variants else {
+            let Variants::Multiple { tag_encoding: TagEncoding::Direct, ref variants, .. } =
+                generator_type_and_layout.variants
+            else {
                 bug!(
                     "Encountered generator with non-direct-tag layout: {:?}",
                     generator_type_and_layout
@@ -173,7 +175,7 @@ pub(super) fn build_generator_di_node<'ll, 'tcx>(
                 .indices()
                 .map(|variant_index| {
                     // FIXME: This is problematic because just a number is not a valid identifier.
-                    //        GeneratorSubsts::variant_name(variant_index), would be consistent
+                    //        GeneratorArgs::variant_name(variant_index), would be consistent
                     //        with enums?
                     let variant_name = format!("{}", variant_index.as_usize()).into();
 
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
index b924c771af7..40714a0afe9 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
@@ -27,7 +27,7 @@ use rustc_hir::def_id::{DefId, DefIdMap};
 use rustc_index::IndexVec;
 use rustc_middle::mir;
 use rustc_middle::ty::layout::LayoutOf;
-use rustc_middle::ty::subst::SubstsRef;
+use rustc_middle::ty::GenericArgsRef;
 use rustc_middle::ty::{self, Instance, ParamEnv, Ty, TypeVisitableExt};
 use rustc_session::config::{self, DebugInfo};
 use rustc_session::Session;
@@ -338,19 +338,19 @@ impl<'ll, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> {
         // Find the enclosing function, in case this is a closure.
         let enclosing_fn_def_id = tcx.typeck_root_def_id(def_id);
 
-        // We look up the generics of the enclosing function and truncate the substs
+        // We look up the generics of the enclosing function and truncate the args
         // to their length in order to cut off extra stuff that might be in there for
         // closures or generators.
         let generics = tcx.generics_of(enclosing_fn_def_id);
-        let substs = instance.substs.truncate_to(tcx, generics);
+        let args = instance.args.truncate_to(tcx, generics);
 
         type_names::push_generic_params(
             tcx,
-            tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), substs),
+            tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), args),
             &mut name,
         );
 
-        let template_parameters = get_template_parameters(self, generics, substs);
+        let template_parameters = get_template_parameters(self, generics, args);
 
         let linkage_name = &mangled_name_of_instance(self, instance).name;
         // Omit the linkage_name if it is the same as subprogram name.
@@ -471,16 +471,16 @@ impl<'ll, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> {
         fn get_template_parameters<'ll, 'tcx>(
             cx: &CodegenCx<'ll, 'tcx>,
             generics: &ty::Generics,
-            substs: SubstsRef<'tcx>,
+            args: GenericArgsRef<'tcx>,
         ) -> &'ll DIArray {
-            if substs.types().next().is_none() {
+            if args.types().next().is_none() {
                 return create_DIArray(DIB(cx), &[]);
             }
 
             // Again, only create type information if full debuginfo is enabled
             let template_params: Vec<_> = if cx.sess().opts.debuginfo == DebugInfo::Full {
                 let names = get_parameter_names(cx, generics);
-                iter::zip(substs, names)
+                iter::zip(args, names)
                     .filter_map(|(kind, name)| {
                         kind.as_type().map(|ty| {
                             let actual_type =
@@ -527,7 +527,7 @@ impl<'ll, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> {
                 // If the method does *not* belong to a trait, proceed
                 if cx.tcx.trait_id_of_impl(impl_def_id).is_none() {
                     let impl_self_ty = cx.tcx.subst_and_normalize_erasing_regions(
-                        instance.substs,
+                        instance.args,
                         ty::ParamEnv::reveal_all(),
                         cx.tcx.type_of(impl_def_id),
                     );
diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs
index a254c86c291..6df1b708ccd 100644
--- a/compiler/rustc_codegen_llvm/src/intrinsic.rs
+++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs
@@ -90,7 +90,7 @@ impl<'ll, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'_, 'll, 'tcx> {
         let tcx = self.tcx;
         let callee_ty = instance.ty(tcx, ty::ParamEnv::reveal_all());
 
-        let ty::FnDef(def_id, substs) = *callee_ty.kind() else {
+        let ty::FnDef(def_id, fn_args) = *callee_ty.kind() else {
             bug!("expected fn item type, found {}", callee_ty);
         };
 
@@ -163,7 +163,7 @@ impl<'ll, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'_, 'll, 'tcx> {
             }
 
             sym::volatile_load | sym::unaligned_volatile_load => {
-                let tp_ty = substs.type_at(0);
+                let tp_ty = fn_args.type_at(0);
                 let ptr = args[0].immediate();
                 let load = if let PassMode::Cast(ty, _) = &fn_abi.ret.mode {
                     let llty = ty.llvm_type(self);
@@ -298,7 +298,7 @@ impl<'ll, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'_, 'll, 'tcx> {
 
             sym::raw_eq => {
                 use abi::Abi::*;
-                let tp_ty = substs.type_at(0);
+                let tp_ty = fn_args.type_at(0);
                 let layout = self.layout_of(tp_ty).layout;
                 let use_integer_compare = match layout.abi() {
                     Scalar(_) | ScalarPair(_, _) => true,
diff --git a/compiler/rustc_codegen_llvm/src/mono_item.rs b/compiler/rustc_codegen_llvm/src/mono_item.rs
index c24854b27a0..e8cda626f54 100644
--- a/compiler/rustc_codegen_llvm/src/mono_item.rs
+++ b/compiler/rustc_codegen_llvm/src/mono_item.rs
@@ -48,7 +48,7 @@ impl<'tcx> PreDefineMethods<'tcx> for CodegenCx<'_, 'tcx> {
         visibility: Visibility,
         symbol_name: &str,
     ) {
-        assert!(!instance.substs.has_infer());
+        assert!(!instance.args.has_infer());
 
         let fn_abi = self.fn_abi_of_instance(instance, ty::List::empty());
         let lldecl = self.declare_fn(symbol_name, fn_abi, Some(instance));
diff --git a/compiler/rustc_codegen_llvm/src/type_of.rs b/compiler/rustc_codegen_llvm/src/type_of.rs
index 58e97be34f2..2dbd467cc84 100644
--- a/compiler/rustc_codegen_llvm/src/type_of.rs
+++ b/compiler/rustc_codegen_llvm/src/type_of.rs
@@ -57,7 +57,7 @@ fn uncached_llvm_type<'a, 'tcx>(
             if let (&ty::Generator(_, _, _), &Variants::Single { index }) =
                 (layout.ty.kind(), &layout.variants)
             {
-                write!(&mut name, "::{}", ty::GeneratorSubsts::variant_name(index)).unwrap();
+                write!(&mut name, "::{}", ty::GeneratorArgs::variant_name(index)).unwrap();
             }
             Some(name)
         }
@@ -336,7 +336,7 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyAndLayout<'tcx> {
             }
             // only wide pointer boxes are handled as pointers
             // thin pointer boxes with scalar allocators are handled by the general logic below
-            ty::Adt(def, substs) if def.is_box() && cx.layout_of(substs.type_at(1)).is_zst() => {
+            ty::Adt(def, args) if def.is_box() && cx.layout_of(args.type_at(1)).is_zst() => {
                 let ptr_ty = Ty::new_mut_ptr(cx.tcx, self.ty.boxed_ty());
                 return cx.layout_of(ptr_ty).scalar_pair_element_llvm_type(cx, index, immediate);
             }
diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs
index c7925be0d7d..b603a878746 100644
--- a/compiler/rustc_codegen_ssa/src/back/link.rs
+++ b/compiler/rustc_codegen_ssa/src/back/link.rs
@@ -2970,10 +2970,25 @@ fn add_lld_args(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) {
         return;
     }
 
+    let self_contained_linker = sess.opts.cg.link_self_contained.linker();
+
+    // FIXME: some targets default to using `lld`, but users can only override the linker on the CLI
+    // and cannot yet select the precise linker flavor to opt out of that. See for example issue
+    // #113597 for the `thumbv6m-none-eabi` target: a driver is used, and its default linker
+    // conflicts with the target's flavor, causing unexpected arguments being passed.
+    //
+    // Until the new `LinkerFlavor`-like CLI options are stabilized, we only adopt MCP510's behavior
+    // if its dedicated unstable CLI flags are used, to keep the current sub-optimal stable
+    // behavior.
+    let using_mcp510 =
+        self_contained_linker || sess.opts.cg.linker_flavor.is_some_and(|f| f.is_unstable());
+    if !using_mcp510 && !unstable_use_lld {
+        return;
+    }
+
     // 1. Implement the "self-contained" part of this feature by adding rustc distribution
     //    directories to the tool's search path.
-    let self_contained_linker = sess.opts.cg.link_self_contained.linker() || unstable_use_lld;
-    if self_contained_linker {
+    if self_contained_linker || unstable_use_lld {
         for path in sess.get_tools_search_paths(false) {
             cmd.arg({
                 let mut arg = OsString::from("-B");
diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
index a8b6030ac85..406048bfe05 100644
--- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
+++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
@@ -12,9 +12,9 @@ use rustc_middle::middle::exported_symbols::{
 };
 use rustc_middle::query::LocalCrate;
 use rustc_middle::query::{ExternProviders, Providers};
-use rustc_middle::ty::subst::{GenericArgKind, SubstsRef};
 use rustc_middle::ty::Instance;
 use rustc_middle::ty::{self, SymbolName, TyCtxt};
+use rustc_middle::ty::{GenericArgKind, GenericArgsRef};
 use rustc_session::config::{CrateType, OomStrategy};
 use rustc_target::spec::SanitizerSet;
 
@@ -342,9 +342,9 @@ fn exported_symbols_provider_local(
             }
 
             match *mono_item {
-                MonoItem::Fn(Instance { def: InstanceDef::Item(def), substs }) => {
-                    if substs.non_erasable_generics().next().is_some() {
-                        let symbol = ExportedSymbol::Generic(def, substs);
+                MonoItem::Fn(Instance { def: InstanceDef::Item(def), args }) => {
+                    if args.non_erasable_generics().next().is_some() {
+                        let symbol = ExportedSymbol::Generic(def, args);
                         symbols.push((
                             symbol,
                             SymbolExportInfo {
@@ -355,10 +355,10 @@ fn exported_symbols_provider_local(
                         ));
                     }
                 }
-                MonoItem::Fn(Instance { def: InstanceDef::DropGlue(_, Some(ty)), substs }) => {
+                MonoItem::Fn(Instance { def: InstanceDef::DropGlue(_, Some(ty)), args }) => {
                     // A little sanity-check
                     debug_assert_eq!(
-                        substs.non_erasable_generics().next(),
+                        args.non_erasable_generics().next(),
                         Some(GenericArgKind::Type(ty))
                     );
                     symbols.push((
@@ -386,7 +386,7 @@ fn exported_symbols_provider_local(
 fn upstream_monomorphizations_provider(
     tcx: TyCtxt<'_>,
     (): (),
-) -> DefIdMap<FxHashMap<SubstsRef<'_>, CrateNum>> {
+) -> DefIdMap<FxHashMap<GenericArgsRef<'_>, CrateNum>> {
     let cnums = tcx.crates(());
 
     let mut instances: DefIdMap<FxHashMap<_, _>> = Default::default();
@@ -395,11 +395,11 @@ fn upstream_monomorphizations_provider(
 
     for &cnum in cnums.iter() {
         for (exported_symbol, _) in tcx.exported_symbols(cnum).iter() {
-            let (def_id, substs) = match *exported_symbol {
-                ExportedSymbol::Generic(def_id, substs) => (def_id, substs),
+            let (def_id, args) = match *exported_symbol {
+                ExportedSymbol::Generic(def_id, args) => (def_id, args),
                 ExportedSymbol::DropGlue(ty) => {
                     if let Some(drop_in_place_fn_def_id) = drop_in_place_fn_def_id {
-                        (drop_in_place_fn_def_id, tcx.mk_substs(&[ty.into()]))
+                        (drop_in_place_fn_def_id, tcx.mk_args(&[ty.into()]))
                     } else {
                         // `drop_in_place` in place does not exist, don't try
                         // to use it.
@@ -414,9 +414,9 @@ fn upstream_monomorphizations_provider(
                 }
             };
 
-            let substs_map = instances.entry(def_id).or_default();
+            let args_map = instances.entry(def_id).or_default();
 
-            match substs_map.entry(substs) {
+            match args_map.entry(args) {
                 Occupied(mut e) => {
                     // If there are multiple monomorphizations available,
                     // we select one deterministically.
@@ -438,17 +438,17 @@ fn upstream_monomorphizations_provider(
 fn upstream_monomorphizations_for_provider(
     tcx: TyCtxt<'_>,
     def_id: DefId,
-) -> Option<&FxHashMap<SubstsRef<'_>, CrateNum>> {
+) -> Option<&FxHashMap<GenericArgsRef<'_>, CrateNum>> {
     debug_assert!(!def_id.is_local());
     tcx.upstream_monomorphizations(()).get(&def_id)
 }
 
 fn upstream_drop_glue_for_provider<'tcx>(
     tcx: TyCtxt<'tcx>,
-    substs: SubstsRef<'tcx>,
+    args: GenericArgsRef<'tcx>,
 ) -> Option<CrateNum> {
     if let Some(def_id) = tcx.lang_items().drop_in_place_fn() {
-        tcx.upstream_monomorphizations_for(def_id).and_then(|monos| monos.get(&substs).cloned())
+        tcx.upstream_monomorphizations_for(def_id).and_then(|monos| monos.get(&args).cloned())
     } else {
         None
     }
@@ -521,10 +521,10 @@ pub fn symbol_name_for_instance_in_crate<'tcx>(
                 instantiating_crate,
             )
         }
-        ExportedSymbol::Generic(def_id, substs) => {
+        ExportedSymbol::Generic(def_id, args) => {
             rustc_symbol_mangling::symbol_name_for_instance_in_crate(
                 tcx,
-                Instance::new(def_id, substs),
+                Instance::new(def_id, args),
                 instantiating_crate,
             )
         }
@@ -533,7 +533,7 @@ pub fn symbol_name_for_instance_in_crate<'tcx>(
                 tcx,
                 ty::Instance {
                     def: ty::InstanceDef::ThreadLocalShim(def_id),
-                    substs: ty::InternalSubsts::empty(),
+                    args: ty::GenericArgs::empty(),
                 },
                 instantiating_crate,
             )
@@ -580,7 +580,7 @@ pub fn linking_symbol_name_for_instance_in_crate<'tcx>(
             None
         }
         ExportedSymbol::NonGeneric(def_id) => Some(Instance::mono(tcx, def_id)),
-        ExportedSymbol::Generic(def_id, substs) => Some(Instance::new(def_id, substs)),
+        ExportedSymbol::Generic(def_id, args) => Some(Instance::new(def_id, args)),
         // DropGlue always use the Rust calling convention and thus follow the target's default
         // symbol decoration scheme.
         ExportedSymbol::DropGlue(..) => None,
diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs
index 9133601ecd1..dc862803274 100644
--- a/compiler/rustc_codegen_ssa/src/base.rs
+++ b/compiler/rustc_codegen_ssa/src/base.rs
@@ -499,7 +499,7 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
                     cx.tcx(),
                     ty::ParamEnv::reveal_all(),
                     start_def_id,
-                    cx.tcx().mk_substs(&[main_ret_ty.into()]),
+                    cx.tcx().mk_args(&[main_ret_ty.into()]),
                 )
                 .unwrap()
                 .unwrap(),
diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
index e91f7b86e5e..64f799bb1e6 100644
--- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
+++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
@@ -17,8 +17,8 @@ use rustc_hir::def_id::DefId;
 use rustc_hir::definitions::{DefPathData, DefPathDataName, DisambiguatedDefPathData};
 use rustc_hir::{AsyncGeneratorKind, GeneratorKind, Mutability};
 use rustc_middle::ty::layout::{IntegerExt, TyAndLayout};
-use rustc_middle::ty::subst::{GenericArgKind, SubstsRef};
 use rustc_middle::ty::{self, ExistentialProjection, ParamEnv, Ty, TyCtxt};
+use rustc_middle::ty::{GenericArgKind, GenericArgsRef};
 use rustc_target::abi::Integer;
 use smallvec::SmallVec;
 
@@ -77,7 +77,7 @@ fn push_debuginfo_type_name<'tcx>(
         ty::Uint(uint_ty) => output.push_str(uint_ty.name_str()),
         ty::Float(float_ty) => output.push_str(float_ty.name_str()),
         ty::Foreign(def_id) => push_item_name(tcx, def_id, qualified, output),
-        ty::Adt(def, substs) => {
+        ty::Adt(def, args) => {
             // `layout_for_cpp_like_fallback` will be `Some` if we want to use the fallback encoding.
             let layout_for_cpp_like_fallback = if cpp_like_debuginfo && def.is_enum() {
                 match tcx.layout_of(ParamEnv::reveal_all().and(t)) {
@@ -106,14 +106,14 @@ fn push_debuginfo_type_name<'tcx>(
                     ty_and_layout,
                     &|output, visited| {
                         push_item_name(tcx, def.did(), true, output);
-                        push_generic_params_internal(tcx, substs, output, visited);
+                        push_generic_params_internal(tcx, args, output, visited);
                     },
                     output,
                     visited,
                 );
             } else {
                 push_item_name(tcx, def.did(), qualified, output);
-                push_generic_params_internal(tcx, substs, output, visited);
+                push_generic_params_internal(tcx, args, output, visited);
             }
         }
         ty::Tuple(component_types) => {
@@ -238,7 +238,7 @@ fn push_debuginfo_type_name<'tcx>(
                     tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), principal);
                 push_item_name(tcx, principal.def_id, qualified, output);
                 let principal_has_generic_params =
-                    push_generic_params_internal(tcx, principal.substs, output, visited);
+                    push_generic_params_internal(tcx, principal.args, output, visited);
 
                 let projection_bounds: SmallVec<[_; 4]> = trait_data
                     .projection_bounds()
@@ -393,7 +393,7 @@ fn push_debuginfo_type_name<'tcx>(
             // processing
             visited.remove(&t);
         }
-        ty::Closure(def_id, substs) | ty::Generator(def_id, substs, ..) => {
+        ty::Closure(def_id, args) | ty::Generator(def_id, args, ..) => {
             // Name will be "{closure_env#0}<T1, T2, ...>", "{generator_env#0}<T1, T2, ...>", or
             // "{async_fn_env#0}<T1, T2, ...>", etc.
             // In the case of cpp-like debuginfo, the name additionally gets wrapped inside of
@@ -403,13 +403,13 @@ fn push_debuginfo_type_name<'tcx>(
                 msvc_enum_fallback(
                     ty_and_layout,
                     &|output, visited| {
-                        push_closure_or_generator_name(tcx, def_id, substs, true, output, visited);
+                        push_closure_or_generator_name(tcx, def_id, args, true, output, visited);
                     },
                     output,
                     visited,
                 );
             } else {
-                push_closure_or_generator_name(tcx, def_id, substs, qualified, output, visited);
+                push_closure_or_generator_name(tcx, def_id, args, qualified, output, visited);
             }
         }
         // Type parameters from polymorphized functions.
@@ -516,7 +516,7 @@ pub fn compute_debuginfo_vtable_name<'tcx>(
             tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), trait_ref);
         push_item_name(tcx, trait_ref.def_id, true, &mut vtable_name);
         visited.clear();
-        push_generic_params_internal(tcx, trait_ref.substs, &mut vtable_name, &mut visited);
+        push_generic_params_internal(tcx, trait_ref.args, &mut vtable_name, &mut visited);
     } else {
         vtable_name.push('_');
     }
@@ -609,21 +609,21 @@ fn push_unqualified_item_name(
 
 fn push_generic_params_internal<'tcx>(
     tcx: TyCtxt<'tcx>,
-    substs: SubstsRef<'tcx>,
+    args: GenericArgsRef<'tcx>,
     output: &mut String,
     visited: &mut FxHashSet<Ty<'tcx>>,
 ) -> bool {
-    if substs.non_erasable_generics().next().is_none() {
+    if args.non_erasable_generics().next().is_none() {
         return false;
     }
 
-    debug_assert_eq!(substs, tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), substs));
+    debug_assert_eq!(args, tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), args));
 
     let cpp_like_debuginfo = cpp_like_debuginfo(tcx);
 
     output.push('<');
 
-    for type_parameter in substs.non_erasable_generics() {
+    for type_parameter in args.non_erasable_generics() {
         match type_parameter {
             GenericArgKind::Type(type_parameter) => {
                 push_debuginfo_type_name(tcx, type_parameter, true, output, visited);
@@ -688,16 +688,20 @@ fn push_const_param<'tcx>(tcx: TyCtxt<'tcx>, ct: ty::Const<'tcx>, output: &mut S
     .unwrap();
 }
 
-pub fn push_generic_params<'tcx>(tcx: TyCtxt<'tcx>, substs: SubstsRef<'tcx>, output: &mut String) {
+pub fn push_generic_params<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    args: GenericArgsRef<'tcx>,
+    output: &mut String,
+) {
     let _prof = tcx.prof.generic_activity("compute_debuginfo_type_name");
     let mut visited = FxHashSet::default();
-    push_generic_params_internal(tcx, substs, output, &mut visited);
+    push_generic_params_internal(tcx, args, output, &mut visited);
 }
 
 fn push_closure_or_generator_name<'tcx>(
     tcx: TyCtxt<'tcx>,
     def_id: DefId,
-    substs: SubstsRef<'tcx>,
+    args: GenericArgsRef<'tcx>,
     qualified: bool,
     output: &mut String,
     visited: &mut FxHashSet<Ty<'tcx>>,
@@ -731,10 +735,10 @@ fn push_closure_or_generator_name<'tcx>(
     let enclosing_fn_def_id = tcx.typeck_root_def_id(def_id);
     let generics = tcx.generics_of(enclosing_fn_def_id);
 
-    // Truncate the substs to the length of the above generics. This will cut off
+    // Truncate the args to the length of the above generics. This will cut off
     // anything closure- or generator-specific.
-    let substs = substs.truncate_to(tcx, generics);
-    push_generic_params_internal(tcx, substs, output, visited);
+    let args = args.truncate_to(tcx, generics);
+    push_generic_params_internal(tcx, args, output, visited);
 }
 
 fn push_close_angle_bracket(cpp_like_debuginfo: bool, output: &mut String) {
diff --git a/compiler/rustc_codegen_ssa/src/meth.rs b/compiler/rustc_codegen_ssa/src/meth.rs
index a8b935bd65c..9abe7b25d0e 100644
--- a/compiler/rustc_codegen_ssa/src/meth.rs
+++ b/compiler/rustc_codegen_ssa/src/meth.rs
@@ -1,6 +1,6 @@
 use crate::traits::*;
 
-use rustc_middle::ty::{self, subst::GenericArgKind, Ty};
+use rustc_middle::ty::{self, GenericArgKind, Ty};
 use rustc_session::config::Lto;
 use rustc_symbol_mangling::typeid_for_trait_ref;
 use rustc_target::abi::call::FnAbi;
diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs
index 9d1b3ce8266..ed608bdbe9a 100644
--- a/compiler/rustc_codegen_ssa/src/mir/block.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/block.rs
@@ -23,6 +23,8 @@ use rustc_target::abi::call::{ArgAbi, FnAbi, PassMode, Reg};
 use rustc_target::abi::{self, HasDataLayout, WrappingRange};
 use rustc_target::spec::abi::Abi;
 
+use std::cmp;
+
 // Indicates if we are in the middle of merging a BB's successor into it. This
 // can happen when BB jumps directly to its successor and the successor has no
 // other predecessors.
@@ -491,7 +493,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                     //
                     let virtual_drop = Instance {
                         def: ty::InstanceDef::Virtual(drop_fn.def_id(), 0),
-                        substs: drop_fn.substs,
+                        args: drop_fn.args,
                     };
                     debug!("ty = {:?}", ty);
                     debug!("drop_fn = {:?}", drop_fn);
@@ -531,7 +533,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                     // SO THEN WE CAN USE THE ABOVE CODE.
                     let virtual_drop = Instance {
                         def: ty::InstanceDef::Virtual(drop_fn.def_id(), 0),
-                        substs: drop_fn.substs,
+                        args: drop_fn.args,
                     };
                     debug!("ty = {:?}", ty);
                     debug!("drop_fn = {:?}", drop_fn);
@@ -687,7 +689,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         // which mentions the offending type, even from a const context.
         let panic_intrinsic = intrinsic.and_then(|s| ValidityRequirement::from_intrinsic(s));
         if let Some(requirement) = panic_intrinsic {
-            let ty = instance.unwrap().substs.type_at(0);
+            let ty = instance.unwrap().args.type_at(0);
 
             let do_panic = !bx
                 .tcx()
@@ -760,13 +762,13 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         let callee = self.codegen_operand(bx, func);
 
         let (instance, mut llfn) = match *callee.layout.ty.kind() {
-            ty::FnDef(def_id, substs) => (
+            ty::FnDef(def_id, args) => (
                 Some(
                     ty::Instance::expect_resolve(
                         bx.tcx(),
                         ty::ParamEnv::reveal_all(),
                         def_id,
-                        substs,
+                        args,
                     )
                     .polymorphize(bx.tcx()),
                 ),
@@ -1125,12 +1127,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 }
                 mir::InlineAsmOperand::SymFn { ref value } => {
                     let literal = self.monomorphize(value.literal);
-                    if let ty::FnDef(def_id, substs) = *literal.ty().kind() {
+                    if let ty::FnDef(def_id, args) = *literal.ty().kind() {
                         let instance = ty::Instance::resolve_for_fn_ptr(
                             bx.tcx(),
                             ty::ParamEnv::reveal_all(),
                             def_id,
-                            substs,
+                            args,
                         )
                         .unwrap();
                         InlineAsmOperandRef::SymFn { instance }
@@ -1360,36 +1362,58 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         // Force by-ref if we have to load through a cast pointer.
         let (mut llval, align, by_ref) = match op.val {
             Immediate(_) | Pair(..) => match arg.mode {
-                PassMode::Indirect { .. } | PassMode::Cast(..) => {
+                PassMode::Indirect { attrs, .. } => {
+                    // Indirect argument may have higher alignment requirements than the type's alignment.
+                    // This can happen, e.g. when passing types with <4 byte alignment on the stack on x86.
+                    let required_align = match attrs.pointee_align {
+                        Some(pointee_align) => cmp::max(pointee_align, arg.layout.align.abi),
+                        None => arg.layout.align.abi,
+                    };
+                    let scratch = PlaceRef::alloca_aligned(bx, arg.layout, required_align);
+                    op.val.store(bx, scratch);
+                    (scratch.llval, scratch.align, true)
+                }
+                PassMode::Cast(..) => {
                     let scratch = PlaceRef::alloca(bx, arg.layout);
                     op.val.store(bx, scratch);
                     (scratch.llval, scratch.align, true)
                 }
                 _ => (op.immediate_or_packed_pair(bx), arg.layout.align.abi, false),
             },
-            Ref(llval, _, align) => {
-                if arg.is_indirect() && align < arg.layout.align.abi {
-                    // `foo(packed.large_field)`. We can't pass the (unaligned) field directly. I
-                    // think that ATM (Rust 1.16) we only pass temporaries, but we shouldn't
-                    // have scary latent bugs around.
-
-                    let scratch = PlaceRef::alloca(bx, arg.layout);
-                    base::memcpy_ty(
-                        bx,
-                        scratch.llval,
-                        scratch.align,
-                        llval,
-                        align,
-                        op.layout,
-                        MemFlags::empty(),
-                    );
-                    (scratch.llval, scratch.align, true)
-                } else {
-                    (llval, align, true)
+            Ref(llval, _, align) => match arg.mode {
+                PassMode::Indirect { attrs, .. } => {
+                    let required_align = match attrs.pointee_align {
+                        Some(pointee_align) => cmp::max(pointee_align, arg.layout.align.abi),
+                        None => arg.layout.align.abi,
+                    };
+                    if align < required_align {
+                        // For `foo(packed.large_field)`, and types with <4 byte alignment on x86,
+                        // alignment requirements may be higher than the type's alignment, so copy
+                        // to a higher-aligned alloca.
+                        let scratch = PlaceRef::alloca_aligned(bx, arg.layout, required_align);
+                        base::memcpy_ty(
+                            bx,
+                            scratch.llval,
+                            scratch.align,
+                            llval,
+                            align,
+                            op.layout,
+                            MemFlags::empty(),
+                        );
+                        (scratch.llval, scratch.align, true)
+                    } else {
+                        (llval, align, true)
+                    }
                 }
-            }
+                _ => (llval, align, true),
+            },
             ZeroSized => match arg.mode {
-                PassMode::Indirect { .. } => {
+                PassMode::Indirect { on_stack, .. } => {
+                    if on_stack {
+                        // It doesn't seem like any target can have `byval` ZSTs, so this assert
+                        // is here to replace a would-be untested codepath.
+                        bug!("ZST {op:?} passed on stack with abi {arg:?}");
+                    }
                     // Though `extern "Rust"` doesn't pass ZSTs, some ABIs pass
                     // a pointer for `repr(C)` structs even when empty, so get
                     // one from an `alloca` (which can be left uninitialized).
diff --git a/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs b/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs
index 4b27b64962d..34b8d8b5a6f 100644
--- a/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs
@@ -186,7 +186,11 @@ fn calculate_debuginfo_offset<
             } => {
                 let offset = indirect_offsets.last_mut().unwrap_or(&mut direct_offset);
                 let FieldsShape::Array { stride, count: _ } = place.layout().fields else {
-                    span_bug!(var.source_info.span, "ConstantIndex on non-array type {:?}", place.layout())
+                    span_bug!(
+                        var.source_info.span,
+                        "ConstantIndex on non-array type {:?}",
+                        place.layout()
+                    )
                 };
                 *offset += stride * index;
                 place = place.project_constant_index(bx, index);
diff --git a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs
index 8a65dd593b8..18201abd631 100644
--- a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs
@@ -64,7 +64,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
     ) {
         let callee_ty = instance.ty(bx.tcx(), ty::ParamEnv::reveal_all());
 
-        let ty::FnDef(def_id, substs) = *callee_ty.kind() else {
+        let ty::FnDef(def_id, fn_args) = *callee_ty.kind() else {
             bug!("expected fn item type, found {}", callee_ty);
         };
 
@@ -87,7 +87,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
             sym::va_start => bx.va_start(args[0].immediate()),
             sym::va_end => bx.va_end(args[0].immediate()),
             sym::size_of_val => {
-                let tp_ty = substs.type_at(0);
+                let tp_ty = fn_args.type_at(0);
                 if let OperandValue::Pair(_, meta) = args[0].val {
                     let (llsize, _) = glue::size_and_align_of_dst(bx, tp_ty, Some(meta));
                     llsize
@@ -96,7 +96,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 }
             }
             sym::min_align_of_val => {
-                let tp_ty = substs.type_at(0);
+                let tp_ty = fn_args.type_at(0);
                 if let OperandValue::Pair(_, meta) = args[0].val {
                     let (_, llalign) = glue::size_and_align_of_dst(bx, tp_ty, Some(meta));
                     llalign
@@ -136,7 +136,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 OperandRef::from_const(bx, value, ret_ty).immediate_or_packed_pair(bx)
             }
             sym::arith_offset => {
-                let ty = substs.type_at(0);
+                let ty = fn_args.type_at(0);
                 let layout = bx.layout_of(ty);
                 let ptr = args[0].immediate();
                 let offset = args[1].immediate();
@@ -147,7 +147,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                     bx,
                     true,
                     false,
-                    substs.type_at(0),
+                    fn_args.type_at(0),
                     args[1].immediate(),
                     args[0].immediate(),
                     args[2].immediate(),
@@ -158,7 +158,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 memset_intrinsic(
                     bx,
                     false,
-                    substs.type_at(0),
+                    fn_args.type_at(0),
                     args[0].immediate(),
                     args[1].immediate(),
                     args[2].immediate(),
@@ -171,7 +171,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                     bx,
                     false,
                     true,
-                    substs.type_at(0),
+                    fn_args.type_at(0),
                     args[0].immediate(),
                     args[1].immediate(),
                     args[2].immediate(),
@@ -183,7 +183,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                     bx,
                     true,
                     true,
-                    substs.type_at(0),
+                    fn_args.type_at(0),
                     args[0].immediate(),
                     args[1].immediate(),
                     args[2].immediate(),
@@ -194,7 +194,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 memset_intrinsic(
                     bx,
                     true,
-                    substs.type_at(0),
+                    fn_args.type_at(0),
                     args[0].immediate(),
                     args[1].immediate(),
                     args[2].immediate(),
@@ -307,7 +307,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                         let Some((success, failure)) = ordering.split_once('_') else {
                             bx.sess().emit_fatal(errors::AtomicCompareExchange);
                         };
-                        let ty = substs.type_at(0);
+                        let ty = fn_args.type_at(0);
                         if int_type_width_signed(ty, bx.tcx()).is_some() || ty.is_unsafe_ptr() {
                             let weak = instruction == "cxchgweak";
                             let mut dst = args[0].immediate();
@@ -338,7 +338,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                     }
 
                     "load" => {
-                        let ty = substs.type_at(0);
+                        let ty = fn_args.type_at(0);
                         if int_type_width_signed(ty, bx.tcx()).is_some() || ty.is_unsafe_ptr() {
                             let layout = bx.layout_of(ty);
                             let size = layout.size;
@@ -361,7 +361,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                     }
 
                     "store" => {
-                        let ty = substs.type_at(0);
+                        let ty = fn_args.type_at(0);
                         if int_type_width_signed(ty, bx.tcx()).is_some() || ty.is_unsafe_ptr() {
                             let size = bx.layout_of(ty).size;
                             let mut val = args[1].immediate();
@@ -407,7 +407,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                             _ => bx.sess().emit_fatal(errors::UnknownAtomicOperation),
                         };
 
-                        let ty = substs.type_at(0);
+                        let ty = fn_args.type_at(0);
                         if int_type_width_signed(ty, bx.tcx()).is_some() || ty.is_unsafe_ptr() {
                             let mut ptr = args[0].immediate();
                             let mut val = args[1].immediate();
@@ -439,7 +439,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
             }
 
             sym::ptr_offset_from | sym::ptr_offset_from_unsigned => {
-                let ty = substs.type_at(0);
+                let ty = fn_args.type_at(0);
                 let pointee_size = bx.layout_of(ty).size;
 
                 let a = args[0].immediate();
diff --git a/compiler/rustc_codegen_ssa/src/mir/mod.rs b/compiler/rustc_codegen_ssa/src/mir/mod.rs
index 9ff6a249748..3464f910829 100644
--- a/compiler/rustc_codegen_ssa/src/mir/mod.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/mod.rs
@@ -159,7 +159,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
     cx: &'a Bx::CodegenCx,
     instance: Instance<'tcx>,
 ) {
-    assert!(!instance.substs.has_infer());
+    assert!(!instance.args.has_infer());
 
     let llfn = cx.get_fn(instance);
 
diff --git a/compiler/rustc_codegen_ssa/src/mir/place.rs b/compiler/rustc_codegen_ssa/src/mir/place.rs
index ab493ae5c1f..90eab55f76e 100644
--- a/compiler/rustc_codegen_ssa/src/mir/place.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/place.rs
@@ -48,9 +48,17 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
         bx: &mut Bx,
         layout: TyAndLayout<'tcx>,
     ) -> Self {
+        Self::alloca_aligned(bx, layout, layout.align.abi)
+    }
+
+    pub fn alloca_aligned<Bx: BuilderMethods<'a, 'tcx, Value = V>>(
+        bx: &mut Bx,
+        layout: TyAndLayout<'tcx>,
+        align: Align,
+    ) -> Self {
         assert!(layout.is_sized(), "tried to statically allocate unsized place");
-        let tmp = bx.alloca(bx.cx().backend_type(layout), layout.align.abi);
-        Self::new_sized(tmp, layout)
+        let tmp = bx.alloca(bx.cx().backend_type(layout), align);
+        Self::new_sized_aligned(tmp, layout, align)
     }
 
     /// Returns a place for an indirect reference to an unsized place.
diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
index 956f03d2578..1f90a28eb8e 100644
--- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
@@ -417,12 +417,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                     }
                     mir::CastKind::PointerCoercion(PointerCoercion::ReifyFnPointer) => {
                         match *operand.layout.ty.kind() {
-                            ty::FnDef(def_id, substs) => {
+                            ty::FnDef(def_id, args) => {
                                 let instance = ty::Instance::resolve_for_fn_ptr(
                                     bx.tcx(),
                                     ty::ParamEnv::reveal_all(),
                                     def_id,
-                                    substs,
+                                    args,
                                 )
                                 .unwrap()
                                 .polymorphize(bx.cx().tcx());
@@ -433,11 +433,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                     }
                     mir::CastKind::PointerCoercion(PointerCoercion::ClosureFnPointer(_)) => {
                         match *operand.layout.ty.kind() {
-                            ty::Closure(def_id, substs) => {
+                            ty::Closure(def_id, args) => {
                                 let instance = Instance::resolve_closure(
                                     bx.cx().tcx(),
                                     def_id,
-                                    substs,
+                                    args,
                                     ty::ClosureKind::FnOnce,
                                 )
                                 .expect("failed to normalize and resolve closure during codegen")
@@ -711,7 +711,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 {
                     let instance = ty::Instance {
                         def: ty::InstanceDef::ThreadLocalShim(def_id),
-                        substs: ty::InternalSubsts::empty(),
+                        args: ty::GenericArgs::empty(),
                     };
                     let fn_ptr = bx.get_fn_addr(instance);
                     let fn_abi = bx.fn_abi_of_instance(instance, ty::List::empty());
diff --git a/compiler/rustc_codegen_ssa/src/mono_item.rs b/compiler/rustc_codegen_ssa/src/mono_item.rs
index 27da33581a1..b72a1a07866 100644
--- a/compiler/rustc_codegen_ssa/src/mono_item.rs
+++ b/compiler/rustc_codegen_ssa/src/mono_item.rs
@@ -64,7 +64,7 @@ impl<'a, 'tcx: 'a> MonoItemExt<'a, 'tcx> for MonoItem<'tcx> {
                                     .typeck_body(anon_const.body)
                                     .node_type(anon_const.hir_id);
                                 let instance = match ty.kind() {
-                                    &ty::FnDef(def_id, substs) => Instance::new(def_id, substs),
+                                    &ty::FnDef(def_id, args) => Instance::new(def_id, args),
                                     _ => span_bug!(*op_sp, "asm sym is not a function"),
                                 };
 
@@ -138,7 +138,7 @@ impl<'a, 'tcx: 'a> MonoItemExt<'a, 'tcx> for MonoItem<'tcx> {
     fn to_raw_string(&self) -> String {
         match *self {
             MonoItem::Fn(instance) => {
-                format!("Fn({:?}, {})", instance.def, instance.substs.as_ptr().addr())
+                format!("Fn({:?}, {})", instance.def, instance.args.as_ptr().addr())
             }
             MonoItem::Static(id) => format!("Static({:?})", id),
             MonoItem::GlobalAsm(id) => format!("GlobalAsm({:?})", id),
diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs
index 9e06fec550d..7b5d83c612a 100644
--- a/compiler/rustc_codegen_ssa/src/target_features.rs
+++ b/compiler/rustc_codegen_ssa/src/target_features.rs
@@ -369,13 +369,9 @@ pub fn from_target_feature(
         // We allow comma separation to enable multiple features.
         target_features.extend(value.as_str().split(',').filter_map(|feature| {
             let Some(feature_gate) = supported_target_features.get(feature) else {
-                let msg =
-                    format!("the feature named `{}` is not valid for this target", feature);
+                let msg = format!("the feature named `{}` is not valid for this target", feature);
                 let mut err = tcx.sess.struct_span_err(item.span(), msg);
-                err.span_label(
-                    item.span(),
-                    format!("`{}` is not valid for this target", feature),
-                );
+                err.span_label(item.span(), format!("`{}` is not valid for this target", feature));
                 if let Some(stripped) = feature.strip_prefix('+') {
                     let valid = supported_target_features.contains_key(stripped);
                     if valid {
diff --git a/compiler/rustc_const_eval/src/const_eval/error.rs b/compiler/rustc_const_eval/src/const_eval/error.rs
index 7890d878d08..ffeff8d079a 100644
--- a/compiler/rustc_const_eval/src/const_eval/error.rs
+++ b/compiler/rustc_const_eval/src/const_eval/error.rs
@@ -150,8 +150,8 @@ where
                 tcx.sess.create_err(Spanned { span, node: layout_error.into_diagnostic() });
             err.code(rustc_errors::error_code!(E0080));
             let Some((mut err, handler)) = err.into_diagnostic() else {
-                    panic!("did not emit diag");
-                };
+                panic!("did not emit diag");
+            };
             for frame in frames {
                 err.eager_subdiagnostic(handler, frame);
             }
diff --git a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs
index 417ab78fd54..b21cb984de6 100644
--- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs
+++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs
@@ -45,7 +45,7 @@ fn eval_body_using_ecx<'mir, 'tcx>(
         "Unexpected DefKind: {:?}",
         ecx.tcx.def_kind(cid.instance.def_id())
     );
-    let layout = ecx.layout_of(body.bound_return_ty().subst(tcx, cid.instance.substs))?;
+    let layout = ecx.layout_of(body.bound_return_ty().instantiate(tcx, cid.instance.args))?;
     assert!(layout.is_sized());
     let ret = ecx.allocate(layout, MemoryKind::Stack)?;
 
@@ -245,10 +245,10 @@ pub fn eval_to_const_value_raw_provider<'tcx>(
     // Catch such calls and evaluate them instead of trying to load a constant's MIR.
     if let ty::InstanceDef::Intrinsic(def_id) = key.value.instance.def {
         let ty = key.value.instance.ty(tcx, key.param_env);
-        let ty::FnDef(_, substs) = ty.kind() else {
+        let ty::FnDef(_, args) = ty.kind() else {
             bug!("intrinsic with type {:?}", ty);
         };
-        return eval_nullary_intrinsic(tcx, key.param_env, def_id, substs).map_err(|error| {
+        return eval_nullary_intrinsic(tcx, key.param_env, def_id, args).map_err(|error| {
             let span = tcx.def_span(def_id);
 
             super::report(
@@ -328,10 +328,10 @@ pub fn eval_to_allocation_raw_provider<'tcx>(
                 ("static", String::new())
             } else {
                 // If the current item has generics, we'd like to enrich the message with the
-                // instance and its substs: to show the actual compile-time values, in addition to
+                // instance and its args: to show the actual compile-time values, in addition to
                 // the expression, leading to the const eval error.
                 let instance = &key.value.instance;
-                if !instance.substs.is_empty() {
+                if !instance.args.is_empty() {
                     let instance = with_no_trimmed_paths!(instance.to_string());
                     ("const_with_path", instance)
                 } else {
diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs
index a20f0276b3e..267795a6cb4 100644
--- a/compiler/rustc_const_eval/src/const_eval/machine.rs
+++ b/compiler/rustc_const_eval/src/const_eval/machine.rs
@@ -230,7 +230,7 @@ impl<'mir, 'tcx: 'mir> CompileTimeEvalContext<'mir, 'tcx> {
                 *self.tcx,
                 ty::ParamEnv::reveal_all(),
                 const_def_id,
-                instance.substs,
+                instance.args,
             )
             .unwrap()
             .unwrap();
diff --git a/compiler/rustc_const_eval/src/const_eval/mod.rs b/compiler/rustc_const_eval/src/const_eval/mod.rs
index a3064b53db1..0a3c3914ff9 100644
--- a/compiler/rustc_const_eval/src/const_eval/mod.rs
+++ b/compiler/rustc_const_eval/src/const_eval/mod.rs
@@ -105,7 +105,7 @@ pub(crate) fn try_destructure_mir_constant_for_diagnostics<'tcx>(
             let down = ecx.operand_downcast(&op, variant).ok()?;
             (def.variants()[variant].fields.len(), Some(variant), down)
         }
-        ty::Tuple(substs) => (substs.len(), None, op),
+        ty::Tuple(args) => (args.len(), None, op),
         _ => bug!("cannot destructure mir constant {:?}", val),
     };
 
diff --git a/compiler/rustc_const_eval/src/const_eval/valtrees.rs b/compiler/rustc_const_eval/src/const_eval/valtrees.rs
index e574df27694..9531d973eb3 100644
--- a/compiler/rustc_const_eval/src/const_eval/valtrees.rs
+++ b/compiler/rustc_const_eval/src/const_eval/valtrees.rs
@@ -416,9 +416,9 @@ fn valtree_into_mplace<'tcx>(
                         debug!(?unsized_inner_ty);
 
                         let inner_ty = match ty.kind() {
-                            ty::Adt(def, substs) => {
+                            ty::Adt(def, args) => {
                                 let i = FieldIdx::from_usize(i);
-                                def.variant(FIRST_VARIANT).fields[i].ty(tcx, substs)
+                                def.variant(FIRST_VARIANT).fields[i].ty(tcx, args)
                             }
                             ty::Tuple(inner_tys) => inner_tys[i],
                             _ => bug!("unexpected unsized type {:?}", ty),
diff --git a/compiler/rustc_const_eval/src/interpret/cast.rs b/compiler/rustc_const_eval/src/interpret/cast.rs
index 83a072d6f8b..dd7a1fcc165 100644
--- a/compiler/rustc_const_eval/src/interpret/cast.rs
+++ b/compiler/rustc_const_eval/src/interpret/cast.rs
@@ -75,12 +75,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
 
                 // The src operand does not matter, just its type
                 match *src.layout.ty.kind() {
-                    ty::FnDef(def_id, substs) => {
+                    ty::FnDef(def_id, args) => {
                         let instance = ty::Instance::resolve_for_fn_ptr(
                             *self.tcx,
                             self.param_env,
                             def_id,
-                            substs,
+                            args,
                         )
                         .ok_or_else(|| err_inval!(TooGeneric))?;
 
@@ -108,11 +108,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
 
                 // The src operand does not matter, just its type
                 match *src.layout.ty.kind() {
-                    ty::Closure(def_id, substs) => {
+                    ty::Closure(def_id, args) => {
                         let instance = ty::Instance::resolve_closure(
                             *self.tcx,
                             def_id,
-                            substs,
+                            args,
                             ty::ClosureKind::FnOnce,
                         )
                         .ok_or_else(|| err_inval!(TooGeneric))?;
diff --git a/compiler/rustc_const_eval/src/interpret/discriminant.rs b/compiler/rustc_const_eval/src/interpret/discriminant.rs
index 015a9beab83..f23a455c2ca 100644
--- a/compiler/rustc_const_eval/src/interpret/discriminant.rs
+++ b/compiler/rustc_const_eval/src/interpret/discriminant.rs
@@ -164,11 +164,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                     ty::Adt(adt, _) => {
                         adt.discriminants(*self.tcx).find(|(_, var)| var.val == discr_bits)
                     }
-                    ty::Generator(def_id, substs, _) => {
-                        let substs = substs.as_generator();
-                        substs
-                            .discriminants(def_id, *self.tcx)
-                            .find(|(_, var)| var.val == discr_bits)
+                    ty::Generator(def_id, args, _) => {
+                        let args = args.as_generator();
+                        args.discriminants(def_id, *self.tcx).find(|(_, var)| var.val == discr_bits)
                     }
                     _ => span_bug!(self.cur_span(), "tagged layout for non-adt non-generator"),
                 }
diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs
index 5e5ad31d8c2..04e046fbda3 100644
--- a/compiler/rustc_const_eval/src/interpret/eval_context.rs
+++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs
@@ -13,7 +13,7 @@ use rustc_middle::ty::layout::{
     self, FnAbiError, FnAbiOfHelpers, FnAbiRequest, LayoutError, LayoutOf, LayoutOfHelpers,
     TyAndLayout,
 };
-use rustc_middle::ty::{self, subst::SubstsRef, ParamEnv, Ty, TyCtxt, TypeFoldable};
+use rustc_middle::ty::{self, GenericArgsRef, ParamEnv, Ty, TyCtxt, TypeFoldable};
 use rustc_mir_dataflow::storage::always_storage_live_locals;
 use rustc_session::Limit;
 use rustc_span::Span;
@@ -91,7 +91,7 @@ pub struct Frame<'mir, 'tcx, Prov: Provenance = AllocId, Extra = ()> {
     /// The MIR for the function called on this frame.
     pub body: &'mir mir::Body<'tcx>,
 
-    /// The def_id and substs of the current function.
+    /// The def_id and args of the current function.
     pub instance: ty::Instance<'tcx>,
 
     /// Extra data for the machine.
@@ -529,16 +529,16 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             .map_err(|_| err_inval!(TooGeneric))
     }
 
-    /// The `substs` are assumed to already be in our interpreter "universe" (param_env).
+    /// The `args` are assumed to already be in our interpreter "universe" (param_env).
     pub(super) fn resolve(
         &self,
         def: DefId,
-        substs: SubstsRef<'tcx>,
+        args: GenericArgsRef<'tcx>,
     ) -> InterpResult<'tcx, ty::Instance<'tcx>> {
-        trace!("resolve: {:?}, {:#?}", def, substs);
+        trace!("resolve: {:?}, {:#?}", def, args);
         trace!("param_env: {:#?}", self.param_env);
-        trace!("substs: {:#?}", substs);
-        match ty::Instance::resolve(*self.tcx, self.param_env, def, substs) {
+        trace!("args: {:#?}", args);
+        match ty::Instance::resolve(*self.tcx, self.param_env, def, args) {
             Ok(Some(instance)) => Ok(instance),
             Ok(None) => throw_inval!(TooGeneric),
 
@@ -604,7 +604,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 // the last field). Can't have foreign types here, how would we
                 // adjust alignment and size for them?
                 let field = layout.field(self, layout.fields.count() - 1);
-                let Some((unsized_size, mut unsized_align)) = self.size_and_align_of(metadata, &field)? else {
+                let Some((unsized_size, mut unsized_align)) =
+                    self.size_and_align_of(metadata, &field)?
+                else {
                     // A field with an extern type. We don't know the actual dynamic size
                     // or the alignment.
                     return Ok(None);
@@ -682,7 +684,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         return_to_block: StackPopCleanup,
     ) -> InterpResult<'tcx> {
         trace!("body: {:#?}", body);
-        // First push a stack frame so we have access to the local substs
+        // First push a stack frame so we have access to the local args
         let pre_frame = Frame {
             body,
             loc: Right(body.span), // Span used for errors caused during preamble.
diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs
index ed64a7655b5..04cae23f852 100644
--- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs
+++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs
@@ -12,7 +12,7 @@ use rustc_middle::mir::{
 };
 use rustc_middle::ty;
 use rustc_middle::ty::layout::{LayoutOf as _, ValidityRequirement};
-use rustc_middle::ty::subst::SubstsRef;
+use rustc_middle::ty::GenericArgsRef;
 use rustc_middle::ty::{Ty, TyCtxt};
 use rustc_span::symbol::{sym, Symbol};
 use rustc_target::abi::{Abi, Align, Primitive, Size};
@@ -56,9 +56,9 @@ pub(crate) fn eval_nullary_intrinsic<'tcx>(
     tcx: TyCtxt<'tcx>,
     param_env: ty::ParamEnv<'tcx>,
     def_id: DefId,
-    substs: SubstsRef<'tcx>,
+    args: GenericArgsRef<'tcx>,
 ) -> InterpResult<'tcx, ConstValue<'tcx>> {
-    let tp_ty = substs.type_at(0);
+    let tp_ty = args.type_at(0);
     let name = tcx.item_name(def_id);
     Ok(match name {
         sym::type_name => {
@@ -123,7 +123,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         dest: &PlaceTy<'tcx, M::Provenance>,
         ret: Option<mir::BasicBlock>,
     ) -> InterpResult<'tcx, bool> {
-        let substs = instance.substs;
+        let instance_args = instance.args;
         let intrinsic_name = self.tcx.item_name(instance.def_id());
 
         // First handle intrinsics without return place.
@@ -187,7 +187,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             | sym::ctlz_nonzero
             | sym::bswap
             | sym::bitreverse => {
-                let ty = substs.type_at(0);
+                let ty = instance_args.type_at(0);
                 let layout_of = self.layout_of(ty)?;
                 let val = self.read_scalar(&args[0])?;
                 let bits = val.to_bits(layout_of.size)?;
@@ -237,7 +237,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             sym::rotate_left | sym::rotate_right => {
                 // rotate_left: (X << (S % BW)) | (X >> ((BW - S) % BW))
                 // rotate_right: (X << ((BW - S) % BW)) | (X >> (S % BW))
-                let layout = self.layout_of(substs.type_at(0))?;
+                let layout = self.layout_of(instance_args.type_at(0))?;
                 let val = self.read_scalar(&args[0])?;
                 let val_bits = val.to_bits(layout.size)?;
                 let raw_shift = self.read_scalar(&args[1])?;
@@ -263,7 +263,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             sym::arith_offset => {
                 let ptr = self.read_pointer(&args[0])?;
                 let offset_count = self.read_target_isize(&args[1])?;
-                let pointee_ty = substs.type_at(0);
+                let pointee_ty = instance_args.type_at(0);
 
                 let pointee_size = i64::try_from(self.layout_of(pointee_ty)?.size.bytes()).unwrap();
                 let offset_bytes = offset_count.wrapping_mul(pointee_size);
@@ -368,7 +368,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                     assert!(self.target_isize_min() <= dist && dist <= self.target_isize_max());
                     isize_layout
                 };
-                let pointee_layout = self.layout_of(substs.type_at(0))?;
+                let pointee_layout = self.layout_of(instance_args.type_at(0))?;
                 // If ret_layout is unsigned, we checked that so is the distance, so we are good.
                 let val = ImmTy::from_int(dist, ret_layout);
                 let size = ImmTy::from_int(pointee_layout.size.bytes(), ret_layout);
@@ -378,7 +378,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             sym::assert_inhabited
             | sym::assert_zero_valid
             | sym::assert_mem_uninitialized_valid => {
-                let ty = instance.substs.type_at(0);
+                let ty = instance.args.type_at(0);
                 let requirement = ValidityRequirement::from_intrinsic(intrinsic_name).unwrap();
 
                 let should_panic = !self
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 df5b581000b..c4fe293bfac 100644
--- a/compiler/rustc_const_eval/src/interpret/intrinsics/caller_location.rs
+++ b/compiler/rustc_const_eval/src/interpret/intrinsics/caller_location.rs
@@ -96,7 +96,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         let loc_ty = self
             .tcx
             .type_of(self.tcx.require_lang_item(LangItem::PanicLocation, None))
-            .subst(*self.tcx, self.tcx.mk_substs(&[self.tcx.lifetimes.re_erased.into()]));
+            .instantiate(*self.tcx, self.tcx.mk_args(&[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 1125d8d1f0e..7b44a20ef03 100644
--- a/compiler/rustc_const_eval/src/interpret/memory.rs
+++ b/compiler/rustc_const_eval/src/interpret/memory.rs
@@ -1060,11 +1060,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         let size = Size::from_bytes(len);
         let Some(alloc_ref) = self.get_ptr_alloc_mut(ptr, size, Align::ONE)? else {
             // zero-sized access
-            assert_matches!(
-                src.next(),
-                None,
-                "iterator said it was empty but returned an element"
-            );
+            assert_matches!(src.next(), None, "iterator said it was empty but returned an element");
             return Ok(());
         };
 
diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs
index 6727937363e..da45fdca1a1 100644
--- a/compiler/rustc_const_eval/src/interpret/operand.rs
+++ b/compiler/rustc_const_eval/src/interpret/operand.rs
@@ -590,7 +590,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 throw_inval!(AlreadyReported(reported.into()))
             }
             ty::ConstKind::Unevaluated(uv) => {
-                let instance = self.resolve(uv.def, uv.substs)?;
+                let instance = self.resolve(uv.def, uv.args)?;
                 let cid = GlobalId { instance, promoted: None };
                 self.ctfe_query(span, |tcx| {
                     tcx.eval_to_valtree(self.param_env.with_const().and(cid))
@@ -619,7 +619,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             }
             mir::ConstantKind::Val(val, ty) => self.const_val_to_op(val, ty, layout),
             mir::ConstantKind::Unevaluated(uv, _) => {
-                let instance = self.resolve(uv.def, uv.substs)?;
+                let instance = self.resolve(uv.def, uv.args)?;
                 Ok(self.eval_global(GlobalId { instance, promoted: uv.promoted }, span)?.into())
             }
         }
diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs
index c2fb61753fe..a9b2b43f1e6 100644
--- a/compiler/rustc_const_eval/src/interpret/place.rs
+++ b/compiler/rustc_const_eval/src/interpret/place.rs
@@ -545,14 +545,17 @@ where
         // wrong type.
 
         let tcx = *self.tcx;
-        let Some(mut alloc) = self.get_place_alloc_mut(&MPlaceTy { mplace: dest, layout, align })? else {
+        let Some(mut alloc) =
+            self.get_place_alloc_mut(&MPlaceTy { mplace: dest, layout, align })?
+        else {
             // zero-sized access
             return Ok(());
         };
 
         match value {
             Immediate::Scalar(scalar) => {
-                let Abi::Scalar(s) = layout.abi else { span_bug!(
+                let Abi::Scalar(s) = layout.abi else {
+                    span_bug!(
                         self.cur_span(),
                         "write_immediate_to_mplace: invalid Scalar layout: {layout:#?}",
                     )
@@ -565,7 +568,8 @@ where
                 // We checked `ptr_align` above, so all fields will have the alignment they need.
                 // We would anyway check against `ptr_align.restrict_for_offset(b_offset)`,
                 // which `ptr.offset(b_offset)` cannot possibly fail to satisfy.
-                let Abi::ScalarPair(a, b) = layout.abi else { span_bug!(
+                let Abi::ScalarPair(a, b) = layout.abi else {
+                    span_bug!(
                         self.cur_span(),
                         "write_immediate_to_mplace: invalid ScalarPair layout: {:#?}",
                         layout
diff --git a/compiler/rustc_const_eval/src/interpret/terminator.rs b/compiler/rustc_const_eval/src/interpret/terminator.rs
index 97d7a68e190..c944782b487 100644
--- a/compiler/rustc_const_eval/src/interpret/terminator.rs
+++ b/compiler/rustc_const_eval/src/interpret/terminator.rs
@@ -135,8 +135,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                         let fn_val = self.get_ptr_fn(fn_ptr)?;
                         (fn_val, self.fn_abi_of_fn_ptr(fn_sig_binder, extra_args)?, false)
                     }
-                    ty::FnDef(def_id, substs) => {
-                        let instance = self.resolve(def_id, substs)?;
+                    ty::FnDef(def_id, args) => {
+                        let instance = self.resolve(def_id, args)?;
                         (
                             FnVal::Instance(instance),
                             self.fn_abi_of_instance(instance, extra_args)?,
@@ -390,7 +390,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             ));
             // Allocate enough memory to hold `src`.
             let Some((size, align)) = self.size_and_align_of_mplace(&src)? else {
-                span_bug!(self.cur_span(), "unsized fn arg with `extern` type tail should not be allowed")
+                span_bug!(
+                    self.cur_span(),
+                    "unsized fn arg with `extern` type tail should not be allowed"
+                )
             };
             let ptr = self.allocate_ptr(size, align, MemoryKind::Stack)?;
             let dest_place =
@@ -468,10 +471,18 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             | ty::InstanceDef::ThreadLocalShim(..)
             | ty::InstanceDef::Item(_) => {
                 // We need MIR for this fn
-                let Some((body, instance)) =
-                    M::find_mir_or_eval_fn(self, instance, caller_abi, args, destination, target, unwind)? else {
-                        return Ok(());
-                    };
+                let Some((body, instance)) = M::find_mir_or_eval_fn(
+                    self,
+                    instance,
+                    caller_abi,
+                    args,
+                    destination,
+                    target,
+                    unwind,
+                )?
+                else {
+                    return Ok(());
+                };
 
                 // Compute callee information using the `instance` returned by
                 // `find_mir_or_eval_fn`.
@@ -702,8 +713,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                         .tcx
                         .struct_tail_erasing_lifetimes(receiver_place.layout.ty, self.param_env);
                     let ty::Dynamic(data, _, ty::Dyn) = receiver_tail.kind() else {
-                            span_bug!(self.cur_span(), "dynamic call on non-`dyn` type {}", receiver_tail)
-                        };
+                        span_bug!(
+                            self.cur_span(),
+                            "dynamic call on non-`dyn` type {}",
+                            receiver_tail
+                        )
+                    };
                     assert!(receiver_place.layout.is_unsized());
 
                     // Get the required information from the vtable.
@@ -721,7 +736,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
 
                 // Now determine the actual method to call. We can do that in two different ways and
                 // compare them to ensure everything fits.
-                let Some(ty::VtblEntry::Method(fn_inst)) = self.get_vtable_entries(vptr)?.get(idx).copied() else {
+                let Some(ty::VtblEntry::Method(fn_inst)) =
+                    self.get_vtable_entries(vptr)?.get(idx).copied()
+                else {
                     // FIXME(fee1-dead) these could be variants of the UB info enum instead of this
                     throw_ub_custom!(fluent::const_eval_dyn_call_not_a_method);
                 };
@@ -731,7 +748,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
 
                     let trait_def_id = tcx.trait_of_item(def_id).unwrap();
                     let virtual_trait_ref =
-                        ty::TraitRef::from_method(tcx, trait_def_id, instance.substs);
+                        ty::TraitRef::from_method(tcx, trait_def_id, instance.args);
                     let existential_trait_ref =
                         ty::ExistentialTraitRef::erase_self_ty(tcx, virtual_trait_ref);
                     let concrete_trait_ref = existential_trait_ref.with_self_ty(tcx, dyn_ty);
@@ -740,7 +757,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                         tcx,
                         self.param_env,
                         def_id,
-                        instance.substs.rebase_onto(tcx, trait_def_id, concrete_trait_ref.substs),
+                        instance.args.rebase_onto(tcx, trait_def_id, concrete_trait_ref.args),
                     )
                     .unwrap();
                     assert_eq!(fn_inst, concrete_method);
diff --git a/compiler/rustc_const_eval/src/interpret/util.rs b/compiler/rustc_const_eval/src/interpret/util.rs
index 22bdd4d2c3f..b3319442388 100644
--- a/compiler/rustc_const_eval/src/interpret/util.rs
+++ b/compiler/rustc_const_eval/src/interpret/util.rs
@@ -33,12 +33,12 @@ where
 
             match *ty.kind() {
                 ty::Param(_) => ControlFlow::Break(FoundParam),
-                ty::Closure(def_id, substs)
-                | ty::Generator(def_id, substs, ..)
-                | ty::FnDef(def_id, substs) => {
+                ty::Closure(def_id, args)
+                | ty::Generator(def_id, args, ..)
+                | ty::FnDef(def_id, args) => {
                     let instance = ty::InstanceDef::Item(def_id);
                     let unused_params = self.tcx.unused_generic_params(instance);
-                    for (index, subst) in substs.into_iter().enumerate() {
+                    for (index, subst) in args.into_iter().enumerate() {
                         let index = index
                             .try_into()
                             .expect("more generic parameters than can fit into a `u32`");
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs
index 14540e8dfe7..d8b8fa927c7 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs
@@ -8,8 +8,8 @@ use rustc_infer::infer::TyCtxtInferExt;
 use rustc_infer::traits::{ImplSource, Obligation, ObligationCause};
 use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor};
 use rustc_middle::mir::*;
-use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts};
 use rustc_middle::ty::{self, adjustment::PointerCoercion, Instance, InstanceDef, Ty, TyCtxt};
+use rustc_middle::ty::{GenericArgKind, GenericArgs};
 use rustc_middle::ty::{TraitRef, TypeVisitableExt};
 use rustc_mir_dataflow::{self, Analysis};
 use rustc_span::{sym, Span, Symbol};
@@ -701,8 +701,8 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
 
                 let fn_ty = func.ty(body, tcx);
 
-                let (mut callee, mut substs) = match *fn_ty.kind() {
-                    ty::FnDef(def_id, substs) => (def_id, substs),
+                let (mut callee, mut fn_args) = match *fn_ty.kind() {
+                    ty::FnDef(def_id, fn_args) => (def_id, fn_args),
 
                     ty::FnPtr(_) => {
                         self.check_op(ops::FnCallIndirect);
@@ -721,7 +721,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
                 let infcx = tcx.infer_ctxt().build();
                 let ocx = ObligationCtxt::new(&infcx);
 
-                let predicates = tcx.predicates_of(callee).instantiate(tcx, substs);
+                let predicates = tcx.predicates_of(callee).instantiate(tcx, fn_args);
                 let cause = ObligationCause::new(
                     terminator.source_info.span,
                     self.body.source.def_id().expect_local(),
@@ -746,7 +746,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
                         self.check_op(ops::FnCallNonConst {
                             caller,
                             callee,
-                            substs,
+                            args: fn_args,
                             span: *fn_span,
                             call_source: *call_source,
                             feature: Some(sym::const_trait_impl),
@@ -754,7 +754,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
                         return;
                     }
 
-                    let trait_ref = TraitRef::from_method(tcx, trait_id, substs);
+                    let trait_ref = TraitRef::from_method(tcx, trait_id, fn_args);
                     let trait_ref = trait_ref.with_constness(ty::BoundConstness::ConstIfConst);
                     let obligation =
                         Obligation::new(tcx, ObligationCause::dummy(), param_env, trait_ref);
@@ -778,8 +778,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
                             if trait_ref.self_ty().is_closure()
                                 && tcx.fn_trait_kind_from_def_id(trait_id).is_some() =>
                         {
-                            let ty::Closure(closure_def_id, substs) =
-                                *trait_ref.self_ty().kind()
+                            let ty::Closure(closure_def_id, fn_args) = *trait_ref.self_ty().kind()
                             else {
                                 unreachable!()
                             };
@@ -787,7 +786,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
                                 self.check_op(ops::FnCallNonConst {
                                     caller,
                                     callee,
-                                    substs,
+                                    args: fn_args,
                                     span: *fn_span,
                                     call_source: *call_source,
                                     feature: None,
@@ -803,9 +802,9 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
                                 .iter()
                                 .find(|did| tcx.item_name(**did) == callee_name)
                             {
-                                // using internal substs is ok here, since this is only
+                                // using internal args is ok here, since this is only
                                 // used for the `resolve` call below
-                                substs = InternalSubsts::identity_for_item(tcx, did);
+                                fn_args = GenericArgs::identity_for_item(tcx, did);
                                 callee = did;
                             }
 
@@ -813,7 +812,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
                                 self.check_op(ops::FnCallNonConst {
                                     caller,
                                     callee,
-                                    substs,
+                                    args: fn_args,
                                     span: *fn_span,
                                     call_source: *call_source,
                                     feature: None,
@@ -829,7 +828,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
                                 && tcx.has_attr(callee_trait, sym::const_trait)
                                 && Some(callee_trait) == tcx.trait_of_item(caller.to_def_id())
                                 // Can only call methods when it's `<Self as TheTrait>::f`.
-                                && tcx.types.self_param == substs.type_at(0)
+                                && tcx.types.self_param == fn_args.type_at(0)
                             {
                                 nonconst_call_permission = true;
                             }
@@ -856,7 +855,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
                                 self.check_op(ops::FnCallNonConst {
                                     caller,
                                     callee,
-                                    substs,
+                                    args: fn_args,
                                     span: *fn_span,
                                     call_source: *call_source,
                                     feature: None,
@@ -869,7 +868,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
 
                     // Resolve a trait method call to its concrete implementation, which may be in a
                     // `const` trait impl.
-                    let instance = Instance::resolve(tcx, param_env, callee, substs);
+                    let instance = Instance::resolve(tcx, param_env, callee, fn_args);
                     debug!("Resolving ({:?}) -> {:?}", callee, instance);
                     if let Ok(Some(func)) = instance {
                         if let InstanceDef::Item(def) = func.def {
@@ -916,7 +915,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
                         self.check_op(ops::FnCallNonConst {
                             caller,
                             callee,
-                            substs,
+                            args: fn_args,
                             span: *fn_span,
                             call_source: *call_source,
                             feature: None,
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 8ebfee8878c..e77fb4ea2a2 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/mod.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/mod.rs
@@ -68,11 +68,11 @@ 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).subst_identity();
-            let ty::Closure(_, substs) = ty.kind() else { bug!("type_of closure not ty::Closure") };
-            substs.as_closure().sig()
+            let ty = self.tcx.type_of(did).instantiate_identity();
+            let ty::Closure(_, args) = ty.kind() else { bug!("type_of closure not ty::Closure") };
+            args.as_closure().sig()
         } else {
-            self.tcx.fn_sig(did).subst_identity()
+            self.tcx.fn_sig(did).instantiate_identity()
         }
     }
 }
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs
index 4eb278252c1..81337079af2 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs
@@ -9,9 +9,9 @@ use rustc_infer::infer::TyCtxtInferExt;
 use rustc_infer::traits::{ImplSource, Obligation, ObligationCause};
 use rustc_middle::mir::{self, CallSource};
 use rustc_middle::ty::print::with_no_trimmed_paths;
-use rustc_middle::ty::subst::{GenericArgKind, SubstsRef};
 use rustc_middle::ty::TraitRef;
 use rustc_middle::ty::{suggest_constraining_type_param, Adt, Closure, FnDef, FnPtr, Param, Ty};
+use rustc_middle::ty::{GenericArgKind, GenericArgsRef};
 use rustc_middle::util::{call_kind, CallDesugaringKind, CallKind};
 use rustc_session::parse::feature_err;
 use rustc_span::symbol::sym;
@@ -98,7 +98,7 @@ impl<'tcx> NonConstOp<'tcx> for FnCallIndirect {
 pub struct FnCallNonConst<'tcx> {
     pub caller: LocalDefId,
     pub callee: DefId,
-    pub substs: SubstsRef<'tcx>,
+    pub args: GenericArgsRef<'tcx>,
     pub span: Span,
     pub call_source: CallSource,
     pub feature: Option<Symbol>,
@@ -110,11 +110,11 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> {
         ccx: &ConstCx<'_, 'tcx>,
         _: Span,
     ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
-        let FnCallNonConst { caller, callee, substs, span, call_source, feature } = *self;
+        let FnCallNonConst { caller, callee, args, span, call_source, feature } = *self;
         let ConstCx { tcx, param_env, .. } = *ccx;
 
         let diag_trait = |err, self_ty: Ty<'_>, trait_id| {
-            let trait_ref = TraitRef::from_method(tcx, trait_id, substs);
+            let trait_ref = TraitRef::from_method(tcx, trait_id, args);
 
             match self_ty.kind() {
                 Param(param_ty) => {
@@ -154,7 +154,7 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> {
         };
 
         let call_kind =
-            call_kind(tcx, ccx.param_env, callee, substs, span, call_source.from_hir_call(), None);
+            call_kind(tcx, ccx.param_env, callee, args, span, call_source.from_hir_call(), None);
 
         debug!(?call_kind);
 
@@ -226,7 +226,7 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> {
                     let mut sugg = None;
 
                     if Some(trait_id) == ccx.tcx.lang_items().eq_trait() {
-                        match (substs[0].unpack(), substs[1].unpack()) {
+                        match (args[0].unpack(), args[1].unpack()) {
                             (GenericArgKind::Type(self_ty), GenericArgKind::Type(rhs_ty))
                                 if self_ty == rhs_ty
                                     && self_ty.is_ref()
@@ -297,7 +297,7 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> {
                 .create_err(errors::NonConstFmtMacroCall { span, kind: ccx.const_kind() }),
             _ => ccx.tcx.sess.create_err(errors::NonConstFnCall {
                 span,
-                def_path_str: ccx.tcx.def_path_str_with_substs(callee, substs),
+                def_path_str: ccx.tcx.def_path_str_with_args(callee, args),
                 kind: ccx.const_kind(),
             }),
         };
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs
index 015a4aa94cd..0ef7ace6965 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs
@@ -7,7 +7,7 @@ use rustc_hir::LangItem;
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_middle::mir;
 use rustc_middle::mir::*;
-use rustc_middle::ty::{self, subst::SubstsRef, AdtDef, Ty};
+use rustc_middle::ty::{self, AdtDef, GenericArgsRef, Ty};
 use rustc_trait_selection::traits::{
     self, ImplSource, Obligation, ObligationCause, ObligationCtxt, SelectionContext,
 };
@@ -72,7 +72,7 @@ pub trait Qualif {
     fn in_adt_inherently<'tcx>(
         cx: &ConstCx<'_, 'tcx>,
         adt: AdtDef<'tcx>,
-        substs: SubstsRef<'tcx>,
+        args: GenericArgsRef<'tcx>,
     ) -> bool;
 }
 
@@ -97,7 +97,7 @@ impl Qualif for HasMutInterior {
     fn in_adt_inherently<'tcx>(
         _cx: &ConstCx<'_, 'tcx>,
         adt: AdtDef<'tcx>,
-        _: SubstsRef<'tcx>,
+        _: GenericArgsRef<'tcx>,
     ) -> bool {
         // Exactly one type, `UnsafeCell`, has the `HasMutInterior` qualif inherently.
         // It arises structurally for all other types.
@@ -127,7 +127,7 @@ impl Qualif for NeedsDrop {
     fn in_adt_inherently<'tcx>(
         cx: &ConstCx<'_, 'tcx>,
         adt: AdtDef<'tcx>,
-        _: SubstsRef<'tcx>,
+        _: GenericArgsRef<'tcx>,
     ) -> bool {
         adt.has_dtor(cx.tcx)
     }
@@ -193,7 +193,7 @@ impl Qualif for NeedsNonConstDrop {
     fn in_adt_inherently<'tcx>(
         cx: &ConstCx<'_, 'tcx>,
         adt: AdtDef<'tcx>,
-        _: SubstsRef<'tcx>,
+        _: GenericArgsRef<'tcx>,
     ) -> bool {
         adt.has_non_const_dtor(cx.tcx)
     }
@@ -221,9 +221,9 @@ impl Qualif for CustomEq {
     fn in_adt_inherently<'tcx>(
         cx: &ConstCx<'_, 'tcx>,
         def: AdtDef<'tcx>,
-        substs: SubstsRef<'tcx>,
+        args: GenericArgsRef<'tcx>,
     ) -> bool {
-        let ty = Ty::new_adt(cx.tcx, def, substs);
+        let ty = Ty::new_adt(cx.tcx, def, args);
         !ty.is_structural_eq_shallow(cx.tcx)
     }
 }
@@ -276,9 +276,9 @@ where
         Rvalue::Aggregate(kind, operands) => {
             // Return early if we know that the struct or enum being constructed is always
             // qualified.
-            if let AggregateKind::Adt(adt_did, _, substs, ..) = **kind {
+            if let AggregateKind::Adt(adt_did, _, args, ..) = **kind {
                 let def = cx.tcx.adt_def(adt_did);
-                if Q::in_adt_inherently(cx, def, substs) {
+                if Q::in_adt_inherently(cx, def, args) {
                     return true;
                 }
                 if def.is_union() && Q::in_any_value_of_ty(cx, rvalue.ty(cx.body, cx.tcx)) {
@@ -360,7 +360,7 @@ where
         ConstantKind::Val(..) => None,
     };
 
-    if let Some(mir::UnevaluatedConst { def, substs: _, promoted }) = uneval {
+    if let Some(mir::UnevaluatedConst { def, args: _, promoted }) = uneval {
         // Use qualifs of the type for the promoted. Promoteds in MIR body should be possible
         // only for `NeedsNonConstDrop` with precise drop checking. This is the only const
         // check performed after the promotion. Verify that with an assertion.
diff --git a/compiler/rustc_const_eval/src/transform/promote_consts.rs b/compiler/rustc_const_eval/src/transform/promote_consts.rs
index 1b39a76e460..d79c65f1d1f 100644
--- a/compiler/rustc_const_eval/src/transform/promote_consts.rs
+++ b/compiler/rustc_const_eval/src/transform/promote_consts.rs
@@ -16,7 +16,7 @@ use rustc_hir as hir;
 use rustc_middle::mir;
 use rustc_middle::mir::visit::{MutVisitor, MutatingUseContext, PlaceContext, Visitor};
 use rustc_middle::mir::*;
-use rustc_middle::ty::subst::InternalSubsts;
+use rustc_middle::ty::GenericArgs;
 use rustc_middle::ty::{self, List, Ty, TyCtxt, TypeVisitableExt};
 use rustc_span::Span;
 
@@ -759,11 +759,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
             let (mut rvalue, source_info) = {
                 let statement = &mut self.source[loc.block].statements[loc.statement_index];
                 let StatementKind::Assign(box (_, rhs)) = &mut statement.kind else {
-                    span_bug!(
-                        statement.source_info.span,
-                        "{:?} is not an assignment",
-                        statement
-                    );
+                    span_bug!(statement.source_info.span, "{:?} is not an assignment", statement);
                 };
 
                 (
@@ -845,8 +841,8 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
             let mut promoted_operand = |ty, span| {
                 promoted.span = span;
                 promoted.local_decls[RETURN_PLACE] = LocalDecl::new(ty, span);
-                let substs = tcx.erase_regions(InternalSubsts::identity_for_item(tcx, def));
-                let uneval = mir::UnevaluatedConst { def, substs, promoted: Some(promoted_id) };
+                let args = tcx.erase_regions(GenericArgs::identity_for_item(tcx, def));
+                let uneval = mir::UnevaluatedConst { def, args, promoted: Some(promoted_id) };
 
                 Operand::Constant(Box::new(Constant {
                     span,
@@ -859,7 +855,9 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
             let local_decls = &mut self.source.local_decls;
             let loc = candidate.location;
             let statement = &mut blocks[loc.block].statements[loc.statement_index];
-            let StatementKind::Assign(box (_, Rvalue::Ref(region, borrow_kind, place))) = &mut statement.kind else {
+            let StatementKind::Assign(box (_, Rvalue::Ref(region, borrow_kind, place))) =
+                &mut statement.kind
+            else {
                 bug!()
             };
 
diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs
index 4cc923cd935..ea0d90dbd51 100644
--- a/compiler/rustc_const_eval/src/transform/validate.rs
+++ b/compiler/rustc_const_eval/src/transform/validate.rs
@@ -214,9 +214,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
             stack.clear();
             stack.insert(bb);
             loop {
-                let Some(parent)= parent[bb].take() else {
-                    break
-                };
+                let Some(parent) = parent[bb].take() else { break };
                 let no_cycle = stack.insert(parent);
                 if !no_cycle {
                     self.fail(
@@ -360,8 +358,8 @@ 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.type_of(def_id).subst(self.tcx, substs).kind()
+                    &ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) => {
+                        self.tcx.type_of(def_id).instantiate(self.tcx, args).kind()
                     }
                     kind => kind,
                 };
@@ -374,23 +372,23 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
                         };
                         check_equal(self, location, *f_ty);
                     }
-                    ty::Adt(adt_def, substs) => {
+                    ty::Adt(adt_def, args) => {
                         let var = parent_ty.variant_index.unwrap_or(FIRST_VARIANT);
                         let Some(field) = adt_def.variant(var).fields.get(f) else {
                             fail_out_of_bounds(self, location);
                             return;
                         };
-                        check_equal(self, location, field.ty(self.tcx, substs));
+                        check_equal(self, location, field.ty(self.tcx, args));
                     }
-                    ty::Closure(_, substs) => {
-                        let substs = substs.as_closure();
-                        let Some(f_ty) = substs.upvar_tys().nth(f.as_usize()) else {
+                    ty::Closure(_, args) => {
+                        let args = args.as_closure();
+                        let Some(f_ty) = args.upvar_tys().nth(f.as_usize()) else {
                             fail_out_of_bounds(self, location);
                             return;
                         };
                         check_equal(self, location, f_ty);
                     }
-                    &ty::Generator(def_id, substs, _) => {
+                    &ty::Generator(def_id, args, _) => {
                         let f_ty = if let Some(var) = parent_ty.variant_index {
                             let gen_body = if def_id == self.body.source.def_id() {
                                 self.body
@@ -399,7 +397,10 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
                             };
 
                             let Some(layout) = gen_body.generator_layout() else {
-                                self.fail(location, format!("No generator layout for {:?}", parent_ty));
+                                self.fail(
+                                    location,
+                                    format!("No generator layout for {:?}", parent_ty),
+                                );
                                 return;
                             };
 
@@ -409,13 +410,16 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
                             };
 
                             let Some(f_ty) = layout.field_tys.get(local) else {
-                                self.fail(location, format!("Out of bounds local {:?} for {:?}", local, parent_ty));
+                                self.fail(
+                                    location,
+                                    format!("Out of bounds local {:?} for {:?}", local, parent_ty),
+                                );
                                 return;
                             };
 
                             f_ty.ty
                         } else {
-                            let Some(f_ty) = substs.as_generator().prefix_tys().nth(f.index()) else {
+                            let Some(f_ty) = args.as_generator().prefix_tys().nth(f.index()) else {
                                 fail_out_of_bounds(self, location);
                                 return;
                             };
@@ -730,7 +734,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
 
                             current_ty = self.tcx.normalize_erasing_regions(self.param_env, f_ty);
                         }
-                        ty::Adt(adt_def, substs) => {
+                        ty::Adt(adt_def, args) => {
                             if adt_def.is_enum() {
                                 self.fail(
                                     location,
@@ -744,7 +748,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
                                 return;
                             };
 
-                            let f_ty = field.ty(self.tcx, substs);
+                            let f_ty = field.ty(self.tcx, args);
                             current_ty = self.tcx.normalize_erasing_regions(self.param_env, f_ty);
                         }
                         _ => {
diff --git a/compiler/rustc_const_eval/src/util/type_name.rs b/compiler/rustc_const_eval/src/util/type_name.rs
index 4f01e0a24a5..14a840ad1b1 100644
--- a/compiler/rustc_const_eval/src/util/type_name.rs
+++ b/compiler/rustc_const_eval/src/util/type_name.rs
@@ -4,8 +4,7 @@ use rustc_hir::definitions::DisambiguatedDefPathData;
 use rustc_middle::ty::{
     self,
     print::{PrettyPrinter, Print, Printer},
-    subst::{GenericArg, GenericArgKind},
-    Ty, TyCtxt,
+    GenericArg, GenericArgKind, Ty, TyCtxt,
 };
 use std::fmt::Write;
 
@@ -56,11 +55,11 @@ impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> {
             }
 
             // Types with identity (print the module path).
-            ty::Adt(ty::AdtDef(Interned(&ty::AdtDefData { did: def_id, .. }, _)), substs)
-            | ty::FnDef(def_id, substs)
-            | ty::Alias(ty::Projection | ty::Opaque, ty::AliasTy { def_id, substs, .. })
-            | ty::Closure(def_id, substs)
-            | ty::Generator(def_id, substs, _) => self.print_def_path(def_id, substs),
+            ty::Adt(ty::AdtDef(Interned(&ty::AdtDefData { did: def_id, .. }, _)), args)
+            | ty::FnDef(def_id, args)
+            | ty::Alias(ty::Projection | ty::Opaque, ty::AliasTy { def_id, args, .. })
+            | ty::Closure(def_id, args)
+            | ty::Generator(def_id, args, _) => self.print_def_path(def_id, args),
             ty::Foreign(def_id) => self.print_def_path(def_id, &[]),
 
             ty::Alias(ty::Weak, _) => bug!("type_name: unexpected weak projection"),
diff --git a/compiler/rustc_data_structures/src/graph/dominators/mod.rs b/compiler/rustc_data_structures/src/graph/dominators/mod.rs
index a5db14d9102..85ef2de9b5e 100644
--- a/compiler/rustc_data_structures/src/graph/dominators/mod.rs
+++ b/compiler/rustc_data_structures/src/graph/dominators/mod.rs
@@ -176,9 +176,7 @@ pub fn dominators<G: ControlFlowGraph>(graph: &G) -> Dominators<G::Node> {
             //
             // ...this may be the case if a MirPass modifies the CFG to remove
             // or rearrange certain blocks/edges.
-            let Some(v) = real_to_pre_order[v] else {
-                continue
-            };
+            let Some(v) = real_to_pre_order[v] else { continue };
 
             // eval returns a vertex x from which semi[x] is minimum among
             // vertices semi[v] +> x *> v.
diff --git a/compiler/rustc_data_structures/src/unord.rs b/compiler/rustc_data_structures/src/unord.rs
index 2b21815b687..47c56eba7ad 100644
--- a/compiler/rustc_data_structures/src/unord.rs
+++ b/compiler/rustc_data_structures/src/unord.rs
@@ -31,6 +31,7 @@ use crate::{
 ///
 /// It's still possible to do the same thing with an `Fn` by using interior mutability,
 /// but the chance of doing it accidentally is reduced.
+#[derive(Clone)]
 pub struct UnordItems<T, I: Iterator<Item = T>>(I);
 
 impl<T, I: Iterator<Item = T>> UnordItems<T, I> {
@@ -167,6 +168,14 @@ impl<T: Ord, I: Iterator<Item = T>> UnordItems<T, I> {
     }
 }
 
+/// A marker trait specifying that `Self` can consume `UnordItems<_>` without
+/// exposing any internal ordering.
+///
+/// Note: right now this is just a marker trait. It could be extended to contain
+/// some useful, common methods though, like `len`, `clear`, or the various
+/// kinds of `to_sorted`.
+trait UnordCollection {}
+
 /// This is a set collection type that tries very hard to not expose
 /// any internal iteration. This is a useful property when trying to
 /// uphold the determinism invariants imposed by the query system.
@@ -181,6 +190,8 @@ pub struct UnordSet<V: Eq + Hash> {
     inner: FxHashSet<V>,
 }
 
+impl<V: Eq + Hash> UnordCollection for UnordSet<V> {}
+
 impl<V: Eq + Hash> Default for UnordSet<V> {
     #[inline]
     fn default() -> Self {
@@ -195,6 +206,11 @@ impl<V: Eq + Hash> UnordSet<V> {
     }
 
     #[inline]
+    pub fn with_capacity(capacity: usize) -> Self {
+        Self { inner: FxHashSet::with_capacity_and_hasher(capacity, Default::default()) }
+    }
+
+    #[inline]
     pub fn len(&self) -> usize {
         self.inner.len()
     }
@@ -258,9 +274,9 @@ impl<V: Eq + Hash> UnordSet<V> {
     #[inline]
     pub fn to_sorted_stable_ord(&self) -> Vec<V>
     where
-        V: Ord + StableOrd + Copy,
+        V: Ord + StableOrd + Clone,
     {
-        let mut items: Vec<V> = self.inner.iter().copied().collect();
+        let mut items: Vec<V> = self.inner.iter().cloned().collect();
         items.sort_unstable();
         items
     }
@@ -279,16 +295,28 @@ impl<V: Eq + Hash> UnordSet<V> {
         to_sorted_vec(hcx, self.inner.into_iter(), cache_sort_key, |x| x)
     }
 
-    // We can safely extend this UnordSet from a set of unordered values because that
-    // won't expose the internal ordering anywhere.
     #[inline]
-    pub fn extend_unord<I: Iterator<Item = V>>(&mut self, items: UnordItems<V, I>) {
-        self.inner.extend(items.0)
+    pub fn clear(&mut self) {
+        self.inner.clear();
     }
+}
+
+pub trait ExtendUnord<T> {
+    /// Extend this unord collection with the given `UnordItems`.
+    /// This method is called `extend_unord` instead of just `extend` so it
+    /// does not conflict with `Extend::extend`. Otherwise there would be many
+    /// places where the two methods would have to be explicitly disambiguated
+    /// via UFCS.
+    fn extend_unord<I: Iterator<Item = T>>(&mut self, items: UnordItems<T, I>);
+}
 
+// Note: it is important that `C` implements `UnordCollection` in addition to
+// `Extend`, otherwise this impl would leak the internal iteration order of
+// `items`, e.g. when calling `some_vec.extend_unord(some_unord_items)`.
+impl<C: Extend<T> + UnordCollection, T> ExtendUnord<T> for C {
     #[inline]
-    pub fn clear(&mut self) {
-        self.inner.clear();
+    fn extend_unord<I: Iterator<Item = T>>(&mut self, items: UnordItems<T, I>) {
+        self.extend(items.0)
     }
 }
 
@@ -312,6 +340,12 @@ impl<V: Hash + Eq> From<FxHashSet<V>> for UnordSet<V> {
     }
 }
 
+impl<V: Hash + Eq, I: Iterator<Item = V>> From<UnordItems<V, I>> for UnordSet<V> {
+    fn from(value: UnordItems<V, I>) -> Self {
+        UnordSet { inner: FxHashSet::from_iter(value.0) }
+    }
+}
+
 impl<HCX, V: Hash + Eq + HashStable<HCX>> HashStable<HCX> for UnordSet<V> {
     #[inline]
     fn hash_stable(&self, hcx: &mut HCX, hasher: &mut StableHasher) {
@@ -333,6 +367,8 @@ pub struct UnordMap<K: Eq + Hash, V> {
     inner: FxHashMap<K, V>,
 }
 
+impl<K: Eq + Hash, V> UnordCollection for UnordMap<K, V> {}
+
 impl<K: Eq + Hash, V> Default for UnordMap<K, V> {
     #[inline]
     fn default() -> Self {
@@ -363,6 +399,11 @@ impl<K: Hash + Eq, V, I: Iterator<Item = (K, V)>> From<UnordItems<(K, V), I>> fo
 
 impl<K: Eq + Hash, V> UnordMap<K, V> {
     #[inline]
+    pub fn with_capacity(capacity: usize) -> Self {
+        Self { inner: FxHashMap::with_capacity_and_hasher(capacity, Default::default()) }
+    }
+
+    #[inline]
     pub fn len(&self) -> usize {
         self.inner.len()
     }
@@ -428,13 +469,6 @@ impl<K: Eq + Hash, V> UnordMap<K, V> {
         UnordItems(self.inner.into_iter())
     }
 
-    // We can safely extend this UnordMap from a set of unordered values because that
-    // won't expose the internal ordering anywhere.
-    #[inline]
-    pub fn extend<I: Iterator<Item = (K, V)>>(&mut self, items: UnordItems<(K, V), I>) {
-        self.inner.extend(items.0)
-    }
-
     /// Returns the entries of this map in stable sort order (as defined by `ToStableHashKey`).
     ///
     /// The `cache_sort_key` parameter controls if [slice::sort_by_cached_key] or
@@ -554,15 +588,10 @@ impl<V> UnordBag<V> {
     pub fn into_items(self) -> UnordItems<V, impl Iterator<Item = V>> {
         UnordItems(self.inner.into_iter())
     }
-
-    // We can safely extend this UnordSet from a set of unordered values because that
-    // won't expose the internal ordering anywhere.
-    #[inline]
-    pub fn extend<I: Iterator<Item = V>>(&mut self, items: UnordItems<V, I>) {
-        self.inner.extend(items.0)
-    }
 }
 
+impl<T> UnordCollection for UnordBag<T> {}
+
 impl<T> Extend<T> for UnordBag<T> {
     fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
         self.inner.extend(iter)
diff --git a/compiler/rustc_errors/src/markdown/parse.rs b/compiler/rustc_errors/src/markdown/parse.rs
index 362a451fde6..d3a08da6283 100644
--- a/compiler/rustc_errors/src/markdown/parse.rs
+++ b/compiler/rustc_errors/src/markdown/parse.rs
@@ -272,7 +272,7 @@ fn parse_ordered_li(buf: &[u8]) -> Parsed<'_> {
 fn get_indented_section(buf: &[u8]) -> (&[u8], &[u8]) {
     let mut end = buf.len();
     for (idx, window) in buf.windows(2).enumerate() {
-        let &[ch, next_ch] = window else {unreachable!("always 2 elements")};
+        let &[ch, next_ch] = window else { unreachable!("always 2 elements") };
         if idx >= buf.len().saturating_sub(2) && next_ch == b'\n' {
             // End of stream
             end = buf.len().saturating_sub(1);
diff --git a/compiler/rustc_errors/src/markdown/term.rs b/compiler/rustc_errors/src/markdown/term.rs
index e45ba6d2cda..88c3c8b9ff2 100644
--- a/compiler/rustc_errors/src/markdown/term.rs
+++ b/compiler/rustc_errors/src/markdown/term.rs
@@ -149,7 +149,7 @@ fn write_wrapping<B: io::Write>(
             let Some((end_idx, _ch)) = iter.nth(ch_count) else {
                 // Write entire line
                 buf.write_all(to_write.as_bytes())?;
-                cur.set(cur.get()+to_write.chars().count());
+                cur.set(cur.get() + to_write.chars().count());
                 break;
             };
 
diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs
index 8a251ea29d7..4b0907cf15a 100644
--- a/compiler/rustc_expand/src/base.rs
+++ b/compiler/rustc_expand/src/base.rs
@@ -1366,7 +1366,7 @@ pub fn parse_macro_name_and_helper_attrs(
         return None;
     }
     let Some(trait_attr) = list[0].meta_item() else {
-        diag.emit_err(errors::NotAMetaItem {span: list[0].span()});
+        diag.emit_err(errors::NotAMetaItem { span: list[0].span() });
         return None;
     };
     let trait_ident = match trait_attr.ident() {
diff --git a/compiler/rustc_expand/src/config.rs b/compiler/rustc_expand/src/config.rs
index 3e43eae006f..4ec5ac22e90 100644
--- a/compiler/rustc_expand/src/config.rs
+++ b/compiler/rustc_expand/src/config.rs
@@ -313,9 +313,10 @@ impl<'a> StripUnconfigured<'a> {
     /// the attribute is incorrect.
     pub(crate) fn expand_cfg_attr(&self, attr: &Attribute, recursive: bool) -> Vec<Attribute> {
         let Some((cfg_predicate, expanded_attrs)) =
-            rustc_parse::parse_cfg_attr(attr, &self.sess.parse_sess) else {
-                return vec![];
-            };
+            rustc_parse::parse_cfg_attr(attr, &self.sess.parse_sess)
+        else {
+            return vec![];
+        };
 
         // Lint on zero attributes in source.
         if expanded_attrs.is_empty() {
@@ -365,7 +366,9 @@ impl<'a> StripUnconfigured<'a> {
         // Use the `#` in `#[cfg_attr(pred, attr)]` as the `#` token
         // for `attr` when we expand it to `#[attr]`
         let mut orig_trees = orig_tokens.into_trees();
-        let TokenTree::Token(pound_token @ Token { kind: TokenKind::Pound, .. }, _) = orig_trees.next().unwrap() else {
+        let TokenTree::Token(pound_token @ Token { kind: TokenKind::Pound, .. }, _) =
+            orig_trees.next().unwrap()
+        else {
             panic!("Bad tokens for attribute {:?}", attr);
         };
         let pound_span = pound_token.span;
@@ -373,7 +376,9 @@ impl<'a> StripUnconfigured<'a> {
         let mut trees = vec![AttrTokenTree::Token(pound_token, Spacing::Alone)];
         if attr.style == AttrStyle::Inner {
             // For inner attributes, we do the same thing for the `!` in `#![some_attr]`
-            let TokenTree::Token(bang_token @ Token { kind: TokenKind::Not, .. }, _) = orig_trees.next().unwrap() else {
+            let TokenTree::Token(bang_token @ Token { kind: TokenKind::Not, .. }, _) =
+                orig_trees.next().unwrap()
+            else {
                 panic!("Bad tokens for attribute {:?}", attr);
             };
             trees.push(AttrTokenTree::Token(bang_token, Spacing::Alone));
diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs
index 9850723a857..3b6db9fd39c 100644
--- a/compiler/rustc_expand/src/expand.rs
+++ b/compiler/rustc_expand/src/expand.rs
@@ -651,7 +651,8 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
         ExpandResult::Ready(match invoc.kind {
             InvocationKind::Bang { mac, .. } => match ext {
                 SyntaxExtensionKind::Bang(expander) => {
-                    let Ok(tok_result) = expander.expand(self.cx, span, mac.args.tokens.clone()) else {
+                    let Ok(tok_result) = expander.expand(self.cx, span, mac.args.tokens.clone())
+                    else {
                         return ExpandResult::Ready(fragment_kind.dummy(span));
                     };
                     self.parse_ast_fragment(tok_result, fragment_kind, &mac.path, span)
@@ -704,7 +705,8 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
                         self.cx.emit_err(UnsupportedKeyValue { span });
                     }
                     let inner_tokens = attr_item.args.inner_tokens();
-                    let Ok(tok_result) = expander.expand(self.cx, span, inner_tokens, tokens) else {
+                    let Ok(tok_result) = expander.expand(self.cx, span, inner_tokens, tokens)
+                    else {
                         return ExpandResult::Ready(fragment_kind.dummy(span));
                     };
                     self.parse_ast_fragment(tok_result, fragment_kind, &attr_item.path, span)
@@ -1087,9 +1089,7 @@ impl InvocationCollectorNode for P<ast::Item> {
 
         // Work around borrow checker not seeing through `P`'s deref.
         let (ident, span, mut attrs) = (node.ident, node.span, mem::take(&mut node.attrs));
-        let ItemKind::Mod(_, mod_kind) = &mut node.kind else {
-            unreachable!()
-        };
+        let ItemKind::Mod(_, mod_kind) = &mut node.kind else { unreachable!() };
 
         let ecx = &mut collector.cx;
         let (file_path, dir_path, dir_ownership) = match mod_kind {
diff --git a/compiler/rustc_expand/src/mbe/diagnostics.rs b/compiler/rustc_expand/src/mbe/diagnostics.rs
index 3593bed2d02..03de33dc854 100644
--- a/compiler/rustc_expand/src/mbe/diagnostics.rs
+++ b/compiler/rustc_expand/src/mbe/diagnostics.rs
@@ -42,7 +42,8 @@ pub(super) fn failed_to_match_macro<'cx>(
         return result;
     }
 
-    let Some(BestFailure { token, msg: label, remaining_matcher, .. }) = tracker.best_failure else {
+    let Some(BestFailure { token, msg: label, remaining_matcher, .. }) = tracker.best_failure
+    else {
         return DummyResult::any(sp);
     };
 
diff --git a/compiler/rustc_expand/src/mbe/metavar_expr.rs b/compiler/rustc_expand/src/mbe/metavar_expr.rs
index 6e919615019..b6382dcb894 100644
--- a/compiler/rustc_expand/src/mbe/metavar_expr.rs
+++ b/compiler/rustc_expand/src/mbe/metavar_expr.rs
@@ -104,13 +104,10 @@ fn parse_depth<'sess>(
     span: Span,
 ) -> PResult<'sess, usize> {
     let Some(tt) = iter.next() else { return Ok(0) };
-    let TokenTree::Token(token::Token {
-        kind: token::TokenKind::Literal(lit), ..
-    }, _) = tt else {
-        return Err(sess.span_diagnostic.struct_span_err(
-            span,
-            "meta-variable expression depth must be a literal"
-        ));
+    let TokenTree::Token(token::Token { kind: token::TokenKind::Literal(lit), .. }, _) = tt else {
+        return Err(sess
+            .span_diagnostic
+            .struct_span_err(span, "meta-variable expression depth must be a literal"));
     };
     if let Ok(lit_kind) = LitKind::from_token_lit(*lit)
         && let LitKind::Int(n_u128, LitIntType::Unsuffixed) = lit_kind
diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs
index d523d3eacbe..a5f83b88f7e 100644
--- a/compiler/rustc_expand/src/mbe/transcribe.rs
+++ b/compiler/rustc_expand/src/mbe/transcribe.rs
@@ -182,9 +182,7 @@ pub(super) fn transcribe<'a>(
                     LockstepIterSize::Constraint(len, _) => {
                         // We do this to avoid an extra clone above. We know that this is a
                         // sequence already.
-                        let mbe::TokenTree::Sequence(sp, seq) = seq else {
-                            unreachable!()
-                        };
+                        let mbe::TokenTree::Sequence(sp, seq) = seq else { unreachable!() };
 
                         // Is the repetition empty?
                         if len == 0 {
@@ -399,7 +397,9 @@ fn lockstep_iter_size(
         }
         TokenTree::MetaVarExpr(_, expr) => {
             let default_rslt = LockstepIterSize::Unconstrained;
-            let Some(ident) = expr.ident() else { return default_rslt; };
+            let Some(ident) = expr.ident() else {
+                return default_rslt;
+            };
             let name = MacroRulesNormalizedIdent::new(ident);
             match lookup_cur_matched(name, interpolations, repeats) {
                 Some(MatchedSeq(ads)) => {
diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs
index 5185820a727..56a2c5eff3d 100644
--- a/compiler/rustc_feature/src/active.rs
+++ b/compiler/rustc_feature/src/active.rs
@@ -392,13 +392,13 @@ declare_features! (
     /// Allows `dyn* Trait` objects.
     (incomplete, dyn_star, "1.65.0", Some(102425), None),
     // Uses generic effect parameters for ~const bounds
-    (active, effects, "CURRENT_RUSTC_VERSION", Some(102090), None),
+    (active, effects, "1.72.0", Some(102090), None),
     /// Allows `X..Y` patterns.
     (active, exclusive_range_pattern, "1.11.0", Some(37854), None),
     /// Allows exhaustive pattern matching on types that contain uninhabited types.
     (active, exhaustive_patterns, "1.13.0", Some(51085), None),
     /// Allows explicit tail calls via `become` expression.
-    (incomplete, explicit_tail_calls, "CURRENT_RUSTC_VERSION", Some(112788), None),
+    (incomplete, explicit_tail_calls, "1.72.0", Some(112788), None),
     /// Allows using `efiapi`, `sysv64` and `win64` as calling convention
     /// for functions with varargs.
     (active, extended_varargs_abi_support, "1.65.0", Some(100189), None),
@@ -445,7 +445,7 @@ declare_features! (
     // Allows setting the threshold for the `large_assignments` lint.
     (active, large_assignments, "1.52.0", Some(83518), None),
     /// Allow to have type alias types for inter-crate use.
-    (active, lazy_type_alias, "CURRENT_RUSTC_VERSION", Some(112792), None),
+    (active, lazy_type_alias, "1.72.0", Some(112792), None),
     /// Allows `if/while p && let q = r && ...` chains.
     (active, let_chains, "1.37.0", Some(53667), None),
     /// Allows using `reason` in lint attributes and the `#[expect(lint)]` lint check.
@@ -546,7 +546,7 @@ declare_features! (
     /// not changed from prior instances of the same struct (RFC #2528)
     (active, type_changing_struct_update, "1.58.0", Some(86555), None),
     /// Allows using type privacy lints (`private_interfaces`, `private_bounds`, `unnameable_types`).
-    (active, type_privacy_lints, "CURRENT_RUSTC_VERSION", Some(48054), None),
+    (active, type_privacy_lints, "1.72.0", Some(48054), None),
     /// Enables rustc to generate code that instructs libstd to NOT ignore SIGPIPE.
     (active, unix_sigpipe, "1.65.0", Some(97889), None),
     /// Allows unsized fn parameters.
diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs
index 36600004404..a70671dd9fb 100644
--- a/compiler/rustc_feature/src/builtin_attrs.rs
+++ b/compiler/rustc_feature/src/builtin_attrs.rs
@@ -812,7 +812,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
         TEST, rustc_error, Normal,
         template!(Word, List: "delay_span_bug_from_inside_query"), WarnFollowingWordOnly
     ),
-    rustc_attr!(TEST, rustc_dump_user_substs, Normal, template!(Word), WarnFollowing),
+    rustc_attr!(TEST, rustc_dump_user_args, Normal, template!(Word), WarnFollowing),
     rustc_attr!(TEST, rustc_evaluate_where_clauses, Normal, template!(Word), WarnFollowing),
     rustc_attr!(
         TEST, rustc_if_this_changed, Normal, template!(Word, List: "DepNode"), DuplicatesOk
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index 6c419471de1..35ef30114b7 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -3150,7 +3150,9 @@ impl<'hir> Item<'hir> {
     /// Expect an [`ItemKind::ForeignMod`] or panic.
     #[track_caller]
     pub fn expect_foreign_mod(&self) -> (Abi, &'hir [ForeignItemRef]) {
-        let ItemKind::ForeignMod { abi, items } = self.kind else { self.expect_failed("a foreign module") };
+        let ItemKind::ForeignMod { abi, items } = self.kind else {
+            self.expect_failed("a foreign module")
+        };
         (abi, items)
     }
 
@@ -3201,14 +3203,18 @@ impl<'hir> Item<'hir> {
     pub fn expect_trait(
         self,
     ) -> (IsAuto, Unsafety, &'hir Generics<'hir>, GenericBounds<'hir>, &'hir [TraitItemRef]) {
-        let ItemKind::Trait(is_auto, unsafety, gen, bounds, items) = self.kind else { self.expect_failed("a trait") };
+        let ItemKind::Trait(is_auto, unsafety, gen, bounds, items) = self.kind else {
+            self.expect_failed("a trait")
+        };
         (is_auto, unsafety, gen, bounds, items)
     }
 
     /// Expect an [`ItemKind::TraitAlias`] or panic.
     #[track_caller]
     pub fn expect_trait_alias(&self) -> (&'hir Generics<'hir>, GenericBounds<'hir>) {
-        let ItemKind::TraitAlias(gen, bounds) = self.kind else { self.expect_failed("a trait alias") };
+        let ItemKind::TraitAlias(gen, bounds) = self.kind else {
+            self.expect_failed("a trait alias")
+        };
         (gen, bounds)
     }
 
diff --git a/compiler/rustc_hir_analysis/src/astconv/bounds.rs b/compiler/rustc_hir_analysis/src/astconv/bounds.rs
index b13de770137..30145b1a185 100644
--- a/compiler/rustc_hir_analysis/src/astconv/bounds.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/bounds.rs
@@ -341,8 +341,8 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
             // If we have an method return type bound, then we need to substitute
             // the method's early bound params with suitable late-bound params.
             let mut num_bound_vars = candidate.bound_vars().len();
-            let substs =
-                candidate.skip_binder().substs.extend_to(tcx, assoc_item.def_id, |param, _| {
+            let args =
+                candidate.skip_binder().args.extend_to(tcx, assoc_item.def_id, |param, _| {
                     let subst = match param.kind {
                         ty::GenericParamDefKind::Lifetime => ty::Region::new_late_bound(
                             tcx,
@@ -422,7 +422,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
             // params (and trait ref's late bound params). This logic is very similar to
             // `Predicate::subst_supertrait`, and it's no coincidence why.
             let shifted_output = tcx.shift_bound_var_indices(num_bound_vars, output);
-            let subst_output = ty::EarlyBinder::bind(shifted_output).subst(tcx, substs);
+            let subst_output = ty::EarlyBinder::bind(shifted_output).instantiate(tcx, args);
 
             let bound_vars = tcx.late_bound_vars(binding.hir_id);
             ty::Binder::bind_with_vars(subst_output, bound_vars)
@@ -438,16 +438,16 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
                     infer_args: false,
                 };
 
-                let substs_trait_ref_and_assoc_item = self.create_substs_for_associated_item(
+                let args_trait_ref_and_assoc_item = self.create_args_for_associated_item(
                     path_span,
                     assoc_item.def_id,
                     &item_segment,
-                    trait_ref.substs,
+                    trait_ref.args,
                 );
 
-                debug!(?substs_trait_ref_and_assoc_item);
+                debug!(?args_trait_ref_and_assoc_item);
 
-                tcx.mk_alias_ty(assoc_item.def_id, substs_trait_ref_and_assoc_item)
+                tcx.mk_alias_ty(assoc_item.def_id, args_trait_ref_and_assoc_item)
             })
         };
 
@@ -533,7 +533,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
                                 tcx,
                                 reported,
                                 tcx.type_of(assoc_item_def_id)
-                                    .subst(tcx, projection_ty.skip_binder().substs),
+                                    .instantiate(tcx, projection_ty.skip_binder().args),
                             )
                             .into(),
                             _ => unreachable!(),
diff --git a/compiler/rustc_hir_analysis/src/astconv/errors.rs b/compiler/rustc_hir_analysis/src/astconv/errors.rs
index ddf99853b2e..7f4927bbb98 100644
--- a/compiler/rustc_hir_analysis/src/astconv/errors.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/errors.rs
@@ -123,7 +123,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         let all_candidate_names: Vec<_> = all_candidates()
             .flat_map(|r| self.tcx().associated_items(r.def_id()).in_definition_order())
             .filter_map(|item| {
-                if item.opt_rpitit_info.is_none() && item.kind == ty::AssocKind::Type {
+                if !item.is_impl_trait_in_trait() && item.kind == ty::AssocKind::Type {
                     Some(item.name)
                 } else {
                     None
@@ -164,7 +164,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 self.tcx().associated_items(*trait_def_id).in_definition_order()
             })
             .filter_map(|item| {
-                if item.opt_rpitit_info.is_none() && item.kind == ty::AssocKind::Type {
+                if !item.is_impl_trait_in_trait() && item.kind == ty::AssocKind::Type {
                     Some(item.name)
                 } else {
                     None
@@ -247,7 +247,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 "the candidate".into()
             };
 
-            let impl_ty = tcx.at(span).type_of(impl_).subst_identity();
+            let impl_ty = tcx.at(span).type_of(impl_).instantiate_identity();
             let note = format!("{title} is defined in an impl for the type `{impl_ty}`");
 
             if let Some(span) = note_span {
@@ -295,7 +295,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             let type_candidates = candidates
                 .iter()
                 .take(limit)
-                .map(|&(impl_, _)| format!("- `{}`", tcx.at(span).type_of(impl_).subst_identity()))
+                .map(|&(impl_, _)| {
+                    format!("- `{}`", tcx.at(span).type_of(impl_).instantiate_identity())
+                })
                 .collect::<Vec<_>>()
                 .join("\n");
             let additional_types = if candidates.len() > limit {
@@ -356,13 +358,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                     // `<Foo as Iterator>::Item = String`.
                     let projection_ty = pred.skip_binder().projection_ty;
 
-                    let substs_with_infer_self = tcx.mk_substs_from_iter(
+                    let args_with_infer_self = tcx.mk_args_from_iter(
                         std::iter::once(Ty::new_var(tcx, ty::TyVid::from_u32(0)).into())
-                            .chain(projection_ty.substs.iter().skip(1)),
+                            .chain(projection_ty.args.iter().skip(1)),
                     );
 
                     let quiet_projection_ty =
-                        tcx.mk_alias_ty(projection_ty.def_id, substs_with_infer_self);
+                        tcx.mk_alias_ty(projection_ty.def_id, args_with_infer_self);
 
                     let term = pred.skip_binder().term;
 
diff --git a/compiler/rustc_hir_analysis/src/astconv/generics.rs b/compiler/rustc_hir_analysis/src/astconv/generics.rs
index 39d1d1f2de5..e81c61d80ed 100644
--- a/compiler/rustc_hir_analysis/src/astconv/generics.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/generics.rs
@@ -11,7 +11,7 @@ use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::DefId;
 use rustc_hir::GenericArg;
 use rustc_middle::ty::{
-    self, subst, subst::SubstsRef, GenericParamDef, GenericParamDefKind, IsSuggestable, Ty, TyCtxt,
+    self, GenericArgsRef, GenericParamDef, GenericParamDefKind, IsSuggestable, Ty, TyCtxt,
 };
 use rustc_session::lint::builtin::LATE_BOUND_LIFETIME_ARGUMENTS;
 use rustc_span::{symbol::kw, Span};
@@ -76,7 +76,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).subst_identity();
+                    let param_type = tcx.type_of(param.def_id).instantiate_identity();
                     if param_type.is_suggestable(tcx, false) {
                         err.span_suggestion(
                             tcx.def_span(src_def_id),
@@ -146,14 +146,14 @@ fn generic_arg_mismatch_err(
 ///
 /// To start, we are given the `def_id` of the thing we are
 /// creating the substitutions for, and a partial set of
-/// substitutions `parent_substs`. In general, the substitutions
+/// substitutions `parent_args`. In general, the substitutions
 /// for an item begin with substitutions for all the "parents" of
 /// that item -- e.g., for a method it might include the
 /// parameters from the impl.
 ///
 /// Therefore, the method begins by walking down these parents,
 /// starting with the outermost parent and proceed inwards until
-/// it reaches `def_id`. For each parent `P`, it will check `parent_substs`
+/// it reaches `def_id`. For each parent `P`, it will check `parent_args`
 /// first to see if the parent's substitutions are listed in there. If so,
 /// we can append those and move on. Otherwise, it invokes the
 /// three callback functions:
@@ -168,15 +168,15 @@ fn generic_arg_mismatch_err(
 ///   instantiate a `GenericArg`.
 /// - `inferred_kind`: if no parameter was provided, and inference is enabled, then
 ///   creates a suitable inference variable.
-pub fn create_substs_for_generic_args<'tcx, 'a>(
+pub fn create_args_for_parent_generic_args<'tcx, 'a>(
     tcx: TyCtxt<'tcx>,
     def_id: DefId,
-    parent_substs: &[subst::GenericArg<'tcx>],
+    parent_args: &[ty::GenericArg<'tcx>],
     has_self: bool,
     self_ty: Option<Ty<'tcx>>,
     arg_count: &GenericArgCountResult,
     ctx: &mut impl CreateSubstsForGenericArgsCtxt<'a, 'tcx>,
-) -> SubstsRef<'tcx> {
+) -> GenericArgsRef<'tcx> {
     // Collect the segments of the path; we need to substitute arguments
     // for parameters throughout the entire path (wherever there are
     // generic parameters).
@@ -191,27 +191,27 @@ pub fn create_substs_for_generic_args<'tcx, 'a>(
     // We manually build up the substitution, rather than using convenience
     // methods in `subst.rs`, so that we can iterate over the arguments and
     // parameters in lock-step linearly, instead of trying to match each pair.
-    let mut substs: SmallVec<[subst::GenericArg<'tcx>; 8]> = SmallVec::with_capacity(count);
+    let mut args: SmallVec<[ty::GenericArg<'tcx>; 8]> = SmallVec::with_capacity(count);
     // Iterate over each segment of the path.
     while let Some((def_id, defs)) = stack.pop() {
         let mut params = defs.params.iter().peekable();
 
         // If we have already computed substitutions for parents, we can use those directly.
         while let Some(&param) = params.peek() {
-            if let Some(&kind) = parent_substs.get(param.index as usize) {
-                substs.push(kind);
+            if let Some(&kind) = parent_args.get(param.index as usize) {
+                args.push(kind);
                 params.next();
             } else {
                 break;
             }
         }
 
-        // `Self` is handled first, unless it's been handled in `parent_substs`.
+        // `Self` is handled first, unless it's been handled in `parent_args`.
         if has_self {
             if let Some(&param) = params.peek() {
                 if param.index == 0 {
                     if let GenericParamDefKind::Type { .. } = param.kind {
-                        substs.push(
+                        args.push(
                             self_ty
                                 .map(|ty| ty.into())
                                 .unwrap_or_else(|| ctx.inferred_kind(None, param, true)),
@@ -226,7 +226,7 @@ pub fn create_substs_for_generic_args<'tcx, 'a>(
         let (generic_args, infer_args) = ctx.args_for_def_id(def_id);
 
         let args_iter = generic_args.iter().flat_map(|generic_args| generic_args.args.iter());
-        let mut args = args_iter.clone().peekable();
+        let mut args_iter = args_iter.clone().peekable();
 
         // If we encounter a type or const when we expect a lifetime, we infer the lifetimes.
         // If we later encounter a lifetime, we know that the arguments were provided in the
@@ -239,7 +239,7 @@ pub fn create_substs_for_generic_args<'tcx, 'a>(
             // provided, matching them with the generic parameters we expect.
             // Mismatches can occur as a result of elided lifetimes, or for malformed
             // input. We try to handle both sensibly.
-            match (args.peek(), params.peek()) {
+            match (args_iter.peek(), params.peek()) {
                 (Some(&arg), Some(&param)) => {
                     match (arg, &param.kind, arg_count.explicit_late_bound) {
                         (GenericArg::Lifetime(_), GenericParamDefKind::Lifetime, _)
@@ -253,8 +253,8 @@ pub fn create_substs_for_generic_args<'tcx, 'a>(
                             GenericParamDefKind::Const { .. },
                             _,
                         ) => {
-                            substs.push(ctx.provided_kind(param, arg));
-                            args.next();
+                            args.push(ctx.provided_kind(param, arg));
+                            args_iter.next();
                             params.next();
                         }
                         (
@@ -264,7 +264,7 @@ pub fn create_substs_for_generic_args<'tcx, 'a>(
                         ) => {
                             // We expected a lifetime argument, but got a type or const
                             // argument. That means we're inferring the lifetimes.
-                            substs.push(ctx.inferred_kind(None, param, infer_args));
+                            args.push(ctx.inferred_kind(None, param, infer_args));
                             force_infer_lt = Some((arg, param));
                             params.next();
                         }
@@ -273,7 +273,7 @@ pub fn create_substs_for_generic_args<'tcx, 'a>(
                             // the presence of explicit late bounds. This is most likely
                             // due to the presence of the explicit bound so we're just going to
                             // ignore it.
-                            args.next();
+                            args_iter.next();
                         }
                         (_, _, _) => {
                             // We expected one kind of parameter, but the user provided
@@ -327,7 +327,7 @@ pub fn create_substs_for_generic_args<'tcx, 'a>(
                             // errors. In this case, we're simply going to ignore the argument
                             // and any following arguments. The rest of the parameters will be
                             // inferred.
-                            while args.next().is_some() {}
+                            while args_iter.next().is_some() {}
                         }
                     }
                 }
@@ -360,7 +360,7 @@ pub fn create_substs_for_generic_args<'tcx, 'a>(
                 (None, Some(&param)) => {
                     // If there are fewer arguments than parameters, it means
                     // we're inferring the remaining arguments.
-                    substs.push(ctx.inferred_kind(Some(&substs), param, infer_args));
+                    args.push(ctx.inferred_kind(Some(&args), param, infer_args));
                     params.next();
                 }
 
@@ -369,7 +369,7 @@ pub fn create_substs_for_generic_args<'tcx, 'a>(
         }
     }
 
-    tcx.mk_substs(&substs)
+    tcx.mk_args(&args)
 }
 
 /// Checks that the correct number of generic arguments have been provided.
diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs
index db3d41ed247..ecbbfd92539 100644
--- a/compiler/rustc_hir_analysis/src/astconv/mod.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs
@@ -9,7 +9,7 @@ mod lint;
 mod object_safety;
 
 use crate::astconv::errors::prohibit_assoc_ty_binding;
-use crate::astconv::generics::{check_generic_arg_count, create_substs_for_generic_args};
+use crate::astconv::generics::{check_generic_arg_count, create_args_for_parent_generic_args};
 use crate::bounds::Bounds;
 use crate::collect::HirPlaceholderCollector;
 use crate::errors::{AmbiguousLifetimeBound, TypeofReservedKeywordUsed};
@@ -29,9 +29,10 @@ use rustc_hir::{GenericArg, GenericArgs, OpaqueTyOrigin};
 use rustc_infer::infer::{InferCtxt, InferOk, TyCtxtInferExt};
 use rustc_infer::traits::ObligationCause;
 use rustc_middle::middle::stability::AllowUnstable;
-use rustc_middle::ty::subst::{self, GenericArgKind, InternalSubsts, SubstsRef};
 use rustc_middle::ty::GenericParamDefKind;
-use rustc_middle::ty::{self, Const, IsSuggestable, Ty, TyCtxt, TypeVisitableExt};
+use rustc_middle::ty::{
+    self, Const, GenericArgKind, GenericArgsRef, IsSuggestable, Ty, TyCtxt, TypeVisitableExt,
+};
 use rustc_session::lint::builtin::AMBIGUOUS_ASSOCIATED_ITEMS;
 use rustc_span::edit_distance::find_best_match_for_name;
 use rustc_span::symbol::{kw, Ident, Symbol};
@@ -220,14 +221,14 @@ pub trait CreateSubstsForGenericArgsCtxt<'a, 'tcx> {
         &mut self,
         param: &ty::GenericParamDef,
         arg: &GenericArg<'_>,
-    ) -> subst::GenericArg<'tcx>;
+    ) -> ty::GenericArg<'tcx>;
 
     fn inferred_kind(
         &mut self,
-        substs: Option<&[subst::GenericArg<'tcx>]>,
+        args: Option<&[ty::GenericArg<'tcx>]>,
         param: &ty::GenericParamDef,
         infer_args: bool,
-    ) -> subst::GenericArg<'tcx>;
+    ) -> ty::GenericArg<'tcx>;
 }
 
 impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
@@ -291,13 +292,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
 
     /// Given a path `path` that refers to an item `I` with the declared generics `decl_generics`,
     /// returns an appropriate set of substitutions for this particular reference to `I`.
-    pub fn ast_path_substs_for_ty(
+    pub fn ast_path_args_for_ty(
         &self,
         span: Span,
         def_id: DefId,
         item_segment: &hir::PathSegment<'_>,
-    ) -> SubstsRef<'tcx> {
-        let (substs, _) = self.create_substs_for_ast_path(
+    ) -> GenericArgsRef<'tcx> {
+        let (args, _) = self.create_args_for_ast_path(
             span,
             def_id,
             &[],
@@ -311,7 +312,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             prohibit_assoc_ty_binding(self.tcx(), b.span, Some((item_segment, span)));
         }
 
-        substs
+        args
     }
 
     /// Given the type/lifetime/const arguments provided to some path (along with
@@ -330,7 +331,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
     /// 2. The path in question is the path to the trait `std::ops::Index`,
     ///    which will have been resolved to a `def_id`
     /// 3. The `generic_args` contains info on the `<...>` contents. The `usize` type
-    ///    parameters are returned in the `SubstsRef`, the associated type bindings like
+    ///    parameters are returned in the `GenericArgsRef`, the associated type bindings like
     ///    `Output = u32` are returned from `create_assoc_bindings_for_generic_args`.
     ///
     /// Note that the type listing given here is *exactly* what the user provided.
@@ -341,22 +342,22 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
     /// <Vec<u8> as Iterable<u8>>::Iter::<'a>
     /// ```
     ///
-    /// We have the parent substs are the substs for the parent trait:
+    /// We have the parent args are the args for the parent trait:
     /// `[Vec<u8>, u8]` and `generic_args` are the arguments for the associated
-    /// type itself: `['a]`. The returned `SubstsRef` concatenates these two
+    /// type itself: `['a]`. The returned `GenericArgsRef` concatenates these two
     /// lists: `[Vec<u8>, u8, 'a]`.
     #[instrument(level = "debug", skip(self, span), ret)]
-    fn create_substs_for_ast_path<'a>(
+    fn create_args_for_ast_path<'a>(
         &self,
         span: Span,
         def_id: DefId,
-        parent_substs: &[subst::GenericArg<'tcx>],
+        parent_args: &[ty::GenericArg<'tcx>],
         seg: &hir::PathSegment<'_>,
         generic_args: &'a hir::GenericArgs<'_>,
         infer_args: bool,
         self_ty: Option<Ty<'tcx>>,
         constness: ty::BoundConstness,
-    ) -> (SubstsRef<'tcx>, GenericArgCountResult) {
+    ) -> (GenericArgsRef<'tcx>, GenericArgCountResult) {
         // If the type is parameterized by this region, then replace this
         // region with the current anon region binding (in other words,
         // whatever & would get replaced with).
@@ -369,7 +370,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             if generics.parent.is_some() {
                 // The parent is a trait so it should have at least one subst
                 // for the `Self` type.
-                assert!(!parent_substs.is_empty())
+                assert!(!parent_args.is_empty())
             } else {
                 // This item (presumably a trait) needs a self-type.
                 assert!(self_ty.is_some());
@@ -395,7 +396,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         // here and so associated type bindings will be handled regardless of whether there are any
         // non-`Self` generic parameters.
         if generics.params.is_empty() {
-            return (tcx.mk_substs(parent_substs), arg_count);
+            return (tcx.mk_args(parent_args), arg_count);
         }
 
         struct SubstsForAstPathCtxt<'a, 'tcx> {
@@ -421,7 +422,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 &mut self,
                 param: &ty::GenericParamDef,
                 arg: &GenericArg<'_>,
-            ) -> subst::GenericArg<'tcx> {
+            ) -> ty::GenericArg<'tcx> {
                 let tcx = self.astconv.tcx();
 
                 let mut handle_ty_args = |has_default, ty: &hir::Ty<'_>| {
@@ -483,10 +484,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
 
             fn inferred_kind(
                 &mut self,
-                substs: Option<&[subst::GenericArg<'tcx>]>,
+                args: Option<&[ty::GenericArg<'tcx>]>,
                 param: &ty::GenericParamDef,
                 infer_args: bool,
-            ) -> subst::GenericArg<'tcx> {
+            ) -> ty::GenericArg<'tcx> {
                 let tcx = self.astconv.tcx();
                 match param.kind {
                     GenericParamDefKind::Lifetime => self
@@ -506,15 +507,15 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                     GenericParamDefKind::Type { has_default, .. } => {
                         if !infer_args && has_default {
                             // No type parameter provided, but a default exists.
-                            let substs = substs.unwrap();
-                            if substs.iter().any(|arg| match arg.unpack() {
+                            let args = args.unwrap();
+                            if args.iter().any(|arg| match arg.unpack() {
                                 GenericArgKind::Type(ty) => ty.references_error(),
                                 _ => false,
                             }) {
                                 // Avoid ICE #86756 when type error recovery goes awry.
                                 return Ty::new_misc_error(tcx).into();
                             }
-                            tcx.at(self.span).type_of(param.def_id).subst(tcx, substs).into()
+                            tcx.at(self.span).type_of(param.def_id).instantiate(tcx, args).into()
                         } else if infer_args {
                             self.astconv.ty_infer(Some(param), self.span).into()
                         } else {
@@ -532,7 +533,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                             return ty::Const::new_error(tcx, guar, ty).into();
                         }
                         if !infer_args && has_default {
-                            tcx.const_param_default(param.def_id).subst(tcx, substs.unwrap()).into()
+                            tcx.const_param_default(param.def_id)
+                                .instantiate(tcx, args.unwrap())
+                                .into()
                         } else {
                             if infer_args {
                                 self.astconv.ct_infer(ty, Some(param), self.span).into()
@@ -546,7 +549,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             }
         }
 
-        let mut substs_ctx = SubstsForAstPathCtxt {
+        let mut args_ctx = SubstsForAstPathCtxt {
             astconv: self,
             def_id,
             span,
@@ -554,14 +557,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             inferred_params: vec![],
             infer_args,
         };
-        let substs = create_substs_for_generic_args(
+        let args = create_args_for_parent_generic_args(
             tcx,
             def_id,
-            parent_substs,
+            parent_args,
             self_ty.is_some(),
             self_ty,
             &arg_count,
-            &mut substs_ctx,
+            &mut args_ctx,
         );
 
         if let ty::BoundConstness::ConstIfConst = constness
@@ -570,7 +573,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             tcx.sess.emit_err(crate::errors::ConstBoundForNonConstTrait { span } );
         }
 
-        (substs, arg_count)
+        (args, arg_count)
     }
 
     fn create_assoc_bindings_for_generic_args<'a>(
@@ -617,21 +620,21 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         assoc_bindings
     }
 
-    pub fn create_substs_for_associated_item(
+    pub fn create_args_for_associated_item(
         &self,
         span: Span,
         item_def_id: DefId,
         item_segment: &hir::PathSegment<'_>,
-        parent_substs: SubstsRef<'tcx>,
-    ) -> SubstsRef<'tcx> {
+        parent_args: GenericArgsRef<'tcx>,
+    ) -> GenericArgsRef<'tcx> {
         debug!(
-            "create_substs_for_associated_item(span: {:?}, item_def_id: {:?}, item_segment: {:?}",
+            "create_args_for_associated_item(span: {:?}, item_def_id: {:?}, item_segment: {:?}",
             span, item_def_id, item_segment
         );
-        let (args, _) = self.create_substs_for_ast_path(
+        let (args, _) = self.create_args_for_ast_path(
             span,
             item_def_id,
-            parent_substs,
+            parent_args,
             item_segment,
             item_segment.args(),
             item_segment.infer_args,
@@ -687,7 +690,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         self_ty: Ty<'tcx>,
         only_self_bounds: OnlySelfBounds,
     ) -> GenericArgCountResult {
-        let (substs, arg_count) = self.create_substs_for_ast_path(
+        let (generic_args, arg_count) = self.create_args_for_ast_path(
             trait_ref_span,
             trait_def_id,
             &[],
@@ -704,8 +707,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
 
         let assoc_bindings = self.create_assoc_bindings_for_generic_args(args);
 
-        let poly_trait_ref =
-            ty::Binder::bind_with_vars(ty::TraitRef::new(tcx, trait_def_id, substs), bound_vars);
+        let poly_trait_ref = ty::Binder::bind_with_vars(
+            ty::TraitRef::new(tcx, trait_def_id, generic_args),
+            bound_vars,
+        );
 
         debug!(?poly_trait_ref, ?assoc_bindings);
         bounds.push_trait_bound(tcx, poly_trait_ref, span, constness, polarity);
@@ -846,7 +851,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         is_impl: bool,
         constness: ty::BoundConstness,
     ) -> ty::TraitRef<'tcx> {
-        let (substs, _) = self.create_substs_for_ast_trait_ref(
+        let (generic_args, _) = self.create_args_for_ast_trait_ref(
             span,
             trait_def_id,
             self_ty,
@@ -857,11 +862,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         if let Some(b) = trait_segment.args().bindings.first() {
             prohibit_assoc_ty_binding(self.tcx(), b.span, Some((trait_segment, span)));
         }
-        ty::TraitRef::new(self.tcx(), trait_def_id, substs)
+        ty::TraitRef::new(self.tcx(), trait_def_id, generic_args)
     }
 
     #[instrument(level = "debug", skip(self, span))]
-    fn create_substs_for_ast_trait_ref<'a>(
+    fn create_args_for_ast_trait_ref<'a>(
         &self,
         span: Span,
         trait_def_id: DefId,
@@ -869,10 +874,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         trait_segment: &'a hir::PathSegment<'a>,
         is_impl: bool,
         constness: ty::BoundConstness,
-    ) -> (SubstsRef<'tcx>, GenericArgCountResult) {
+    ) -> (GenericArgsRef<'tcx>, GenericArgCountResult) {
         self.complain_about_internal_fn_trait(span, trait_def_id, trait_segment, is_impl);
 
-        self.create_substs_for_ast_path(
+        self.create_args_for_ast_path(
             span,
             trait_def_id,
             &[],
@@ -902,7 +907,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         did: DefId,
         item_segment: &hir::PathSegment<'_>,
     ) -> Ty<'tcx> {
-        let substs = self.ast_path_substs_for_ty(span, did, item_segment);
+        let args = self.ast_path_args_for_ty(span, did, item_segment);
         let ty = self.tcx().at(span).type_of(did);
 
         if matches!(self.tcx().def_kind(did), DefKind::TyAlias)
@@ -911,10 +916,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             // Type aliases referring to types that contain opaque types (but aren't just directly
             // referencing a single opaque type) get encoded as a type alias that normalization will
             // then actually instantiate the where bounds of.
-            let alias_ty = self.tcx().mk_alias_ty(did, substs);
+            let alias_ty = self.tcx().mk_alias_ty(did, args);
             Ty::new_alias(self.tcx(), ty::Weak, alias_ty)
         } else {
-            ty.subst(self.tcx(), substs)
+            ty.instantiate(self.tcx(), args)
         }
     }
 
@@ -1267,9 +1272,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                                 "you might have meant to specify type parameters on enum \
                                  `{type_name}`"
                             );
-                            let Some(args) = assoc_segment.args else { return; };
+                            let Some(args) = assoc_segment.args else {
+                                return;
+                            };
                             // Get the span of the generics args *including* the leading `::`.
-                            let args_span = assoc_segment.ident.span.shrink_to_hi().to(args.span_ext);
+                            let args_span =
+                                assoc_segment.ident.span.shrink_to_hi().to(args.span_ext);
                             if tcx.generics_of(adt_def.did()).count() == 0 {
                                 // FIXME(estebank): we could also verify that the arguments being
                                 // work for the `enum`, instead of just looking if it takes *any*.
@@ -1281,49 +1289,56 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                                 );
                                 return;
                             }
-                            let Ok(snippet) = tcx.sess.source_map().span_to_snippet(args_span) else {
+                            let Ok(snippet) = tcx.sess.source_map().span_to_snippet(args_span)
+                            else {
                                 err.note(msg);
                                 return;
                             };
-                            let (qself_sugg_span, is_self) = if let hir::TyKind::Path(
-                                hir::QPath::Resolved(_, path)
-                            ) = &qself.kind {
-                                // If the path segment already has type params, we want to overwrite
-                                // them.
-                                match &path.segments {
-                                    // `segment` is the previous to last element on the path,
-                                    // which would normally be the `enum` itself, while the last
-                                    // `_` `PathSegment` corresponds to the variant.
-                                    [.., hir::PathSegment {
-                                        ident,
-                                        args,
-                                        res: Res::Def(DefKind::Enum, _),
-                                        ..
-                                    }, _] => (
-                                        // We need to include the `::` in `Type::Variant::<Args>`
-                                        // to point the span to `::<Args>`, not just `<Args>`.
-                                        ident.span.shrink_to_hi().to(args.map_or(
-                                            ident.span.shrink_to_hi(),
-                                            |a| a.span_ext)),
-                                        false,
-                                    ),
-                                    [segment] => (
-                                        // We need to include the `::` in `Type::Variant::<Args>`
-                                        // to point the span to `::<Args>`, not just `<Args>`.
-                                        segment.ident.span.shrink_to_hi().to(segment.args.map_or(
-                                            segment.ident.span.shrink_to_hi(),
-                                            |a| a.span_ext)),
-                                        kw::SelfUpper == segment.ident.name,
-                                    ),
-                                    _ => {
-                                        err.note(msg);
-                                        return;
+                            let (qself_sugg_span, is_self) =
+                                if let hir::TyKind::Path(hir::QPath::Resolved(_, path)) =
+                                    &qself.kind
+                                {
+                                    // If the path segment already has type params, we want to overwrite
+                                    // them.
+                                    match &path.segments {
+                                        // `segment` is the previous to last element on the path,
+                                        // which would normally be the `enum` itself, while the last
+                                        // `_` `PathSegment` corresponds to the variant.
+                                        [
+                                            ..,
+                                            hir::PathSegment {
+                                                ident,
+                                                args,
+                                                res: Res::Def(DefKind::Enum, _),
+                                                ..
+                                            },
+                                            _,
+                                        ] => (
+                                            // We need to include the `::` in `Type::Variant::<Args>`
+                                            // to point the span to `::<Args>`, not just `<Args>`.
+                                            ident.span.shrink_to_hi().to(args
+                                                .map_or(ident.span.shrink_to_hi(), |a| a.span_ext)),
+                                            false,
+                                        ),
+                                        [segment] => (
+                                            // We need to include the `::` in `Type::Variant::<Args>`
+                                            // to point the span to `::<Args>`, not just `<Args>`.
+                                            segment.ident.span.shrink_to_hi().to(segment
+                                                .args
+                                                .map_or(segment.ident.span.shrink_to_hi(), |a| {
+                                                    a.span_ext
+                                                })),
+                                            kw::SelfUpper == segment.ident.name,
+                                        ),
+                                        _ => {
+                                            err.note(msg);
+                                            return;
+                                        }
                                     }
-                                }
-                            } else {
-                                err.note(msg);
-                                return;
-                            };
+                                } else {
+                                    err.note(msg);
+                                    return;
+                                };
                             let suggestion = vec![
                                 if is_self {
                                     // Account for people writing `Self::Variant::<Args>`, where
@@ -1373,7 +1388,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 };
 
                 self.one_bound_for_assoc_type(
-                    || traits::supertraits(tcx, ty::Binder::dummy(trait_ref.subst_identity())),
+                    || {
+                        traits::supertraits(
+                            tcx,
+                            ty::Binder::dummy(trait_ref.instantiate_identity()),
+                        )
+                    },
                     kw::SelfUpper,
                     assoc_ident,
                     span,
@@ -1455,7 +1475,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         };
 
         let trait_did = bound.def_id();
-        let Some(assoc_ty_did) = self.lookup_assoc_ty(assoc_ident, hir_ref_id, span, trait_did) else {
+        let Some(assoc_ty_did) = self.lookup_assoc_ty(assoc_ident, hir_ref_id, span, trait_did)
+        else {
             // Assume that if it's not matched, there must be a const defined with the same name
             // but it was used in a type position.
             let msg = format!("found associated const `{assoc_ident}` when type was expected");
@@ -1609,8 +1630,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                         let ocx = ObligationCtxt::new(&infcx);
                         ocx.register_obligations(obligations.clone());
 
-                        let impl_substs = infcx.fresh_substs_for_item(span, impl_);
-                        let impl_ty = tcx.type_of(impl_).subst(tcx, impl_substs);
+                        let impl_args = infcx.fresh_args_for_item(span, impl_);
+                        let impl_ty = tcx.type_of(impl_).instantiate(tcx, impl_args);
                         let impl_ty = ocx.normalize(&cause, param_env, impl_ty);
 
                         // Check that the self types can be related.
@@ -1622,7 +1643,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                         }
 
                         // Check whether the impl imposes obligations we have to worry about.
-                        let impl_bounds = tcx.predicates_of(impl_).instantiate(tcx, impl_substs);
+                        let impl_bounds = tcx.predicates_of(impl_).instantiate(tcx, impl_args);
                         let impl_bounds = ocx.normalize(&cause, param_env, impl_bounds);
                         let impl_obligations = traits::predicates_for_generics(
                             |_, _| cause.clone(),
@@ -1654,18 +1675,17 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         if let Some((impl_, (assoc_item, def_scope))) = applicable_candidates.pop() {
             self.check_assoc_ty(assoc_item, name, def_scope, block, span);
 
-            // FIXME(fmease): Currently creating throwaway `parent_substs` to please
-            // `create_substs_for_associated_item`. Modify the latter instead (or sth. similar) to
-            // not require the parent substs logic.
-            let parent_substs = InternalSubsts::identity_for_item(tcx, impl_);
-            let substs =
-                self.create_substs_for_associated_item(span, assoc_item, segment, parent_substs);
-            let substs = tcx.mk_substs_from_iter(
+            // FIXME(fmease): Currently creating throwaway `parent_args` to please
+            // `create_args_for_associated_item`. Modify the latter instead (or sth. similar) to
+            // not require the parent args logic.
+            let parent_args = ty::GenericArgs::identity_for_item(tcx, impl_);
+            let args = self.create_args_for_associated_item(span, assoc_item, segment, parent_args);
+            let args = tcx.mk_args_from_iter(
                 std::iter::once(ty::GenericArg::from(self_ty))
-                    .chain(substs.into_iter().skip(parent_substs.len())),
+                    .chain(args.into_iter().skip(parent_args.len())),
             );
 
-            let ty = Ty::new_alias(tcx, ty::Inherent, tcx.mk_alias_ty(assoc_item, substs));
+            let ty = Ty::new_alias(tcx, ty::Inherent, tcx.mk_alias_ty(assoc_item, args));
 
             return Ok(Some((ty, assoc_item)));
         }
@@ -1769,9 +1789,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                         .any(|impl_def_id| {
                             let trait_ref = tcx.impl_trait_ref(impl_def_id);
                             trait_ref.is_some_and(|trait_ref| {
-                                let impl_ = trait_ref.subst(
+                                let impl_ = trait_ref.instantiate(
                                     tcx,
-                                    infcx.fresh_substs_for_item(DUMMY_SP, impl_def_id),
+                                    infcx.fresh_args_for_item(DUMMY_SP, impl_def_id),
                                 );
                                 let value = tcx.fold_regions(qself_ty, |_, _| tcx.lifetimes.re_erased);
                                 // FIXME: Don't bother dealing with non-lifetime binders here...
@@ -1814,7 +1834,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
 
             debug!("qpath_to_ty: self.item_def_id()={:?}", def_id);
 
-            let parent_def_id = def_id.as_local().map(|def_id| tcx.hir().local_def_id_to_hir_id(def_id))
+            let parent_def_id = def_id
+                .as_local()
+                .map(|def_id| tcx.hir().local_def_id_to_hir_id(def_id))
                 .map(|hir_id| tcx.hir().get_parent_item(hir_id).to_def_id());
 
             debug!("qpath_to_ty: parent_def_id={:?}", parent_def_id);
@@ -1835,7 +1857,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                             && tcx.impl_polarity(impl_def_id) != ty::ImplPolarity::Negative
                     })
                     .filter_map(|impl_def_id| tcx.impl_trait_ref(impl_def_id))
-                    .map(|impl_| impl_.subst_identity().self_ty())
+                    .map(|impl_| impl_.instantiate_identity().self_ty())
                     // We don't care about blanket impls.
                     .filter(|self_ty| !self_ty.has_non_region_param())
                     .map(|self_ty| tcx.erase_regions(self_ty).to_string())
@@ -1850,7 +1872,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 &[path_str],
                 item_segment.ident.name,
             );
-            return Ty::new_error(tcx,reported)
+            return Ty::new_error(tcx, reported);
         };
 
         debug!("qpath_to_ty: self_type={:?}", self_ty);
@@ -1864,16 +1886,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             constness,
         );
 
-        let item_substs = self.create_substs_for_associated_item(
-            span,
-            item_def_id,
-            item_segment,
-            trait_ref.substs,
-        );
+        let item_args =
+            self.create_args_for_associated_item(span, item_def_id, item_segment, trait_ref.args);
 
         debug!("qpath_to_ty: trait_ref={:?}", trait_ref);
 
-        Ty::new_projection(tcx, item_def_id, item_substs)
+        Ty::new_projection(tcx, item_def_id, item_args)
     }
 
     pub fn prohibit_generics<'a>(
@@ -2135,8 +2153,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 self.prohibit_generics(item_segment.1.iter(), |err| {
                     err.note("`impl Trait` types can't have type parameters");
                 });
-                let substs = self.ast_path_substs_for_ty(span, did, item_segment.0);
-                Ty::new_opaque(tcx, did, substs)
+                let args = self.ast_path_args_for_ty(span, did, item_segment.0);
+                Ty::new_opaque(tcx, did, args)
             }
             Res::Def(
                 DefKind::Enum
@@ -2220,7 +2238,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).subst_identity();
+                let ty = tcx.at(span).type_of(def_id).instantiate_identity();
                 let span_of_impl = tcx.span_of_impl(def_id);
                 self.prohibit_generics(path.segments.iter(), |err| {
                     let def_id = match *ty.kind() {
@@ -2458,7 +2476,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             }
             &hir::TyKind::Path(hir::QPath::LangItem(lang_item, span, _)) => {
                 let def_id = tcx.require_lang_item(lang_item, Some(span));
-                let (substs, _) = self.create_substs_for_ast_path(
+                let (args, _) = self.create_args_for_ast_path(
                     span,
                     def_id,
                     &[],
@@ -2468,7 +2486,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                     None,
                     ty::BoundConstness::NotConst,
                 );
-                tcx.at(span).type_of(def_id).subst(tcx, substs)
+                tcx.at(span).type_of(def_id).instantiate(tcx, args)
             }
             hir::TyKind::Array(ty, length) => {
                 let length = match length {
@@ -2481,7 +2499,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 Ty::new_array_with_const_len(tcx, self.ast_ty_to_ty(ty), length)
             }
             hir::TyKind::Typeof(e) => {
-                let ty_erased = tcx.type_of(e.def_id).subst_identity();
+                let ty_erased = tcx.type_of(e.def_id).instantiate_identity();
                 let ty = tcx.fold_regions(ty_erased, |r, _| {
                     if r.is_erased() { tcx.lifetimes.re_static } else { r }
                 });
@@ -2523,7 +2541,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         let generics = tcx.generics_of(def_id);
 
         debug!("impl_trait_ty_to_ty: generics={:?}", generics);
-        let substs = InternalSubsts::for_item(tcx, def_id, |param, _| {
+        let args = ty::GenericArgs::for_item(tcx, def_id, |param, _| {
             // We use `generics.count() - lifetimes.len()` here instead of `generics.parent_count`
             // since return-position impl trait in trait squashes all of the generics from its source fn
             // into its own generics, so the opaque's "own" params isn't always just lifetimes.
@@ -2537,12 +2555,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 tcx.mk_param_from_def(param)
             }
         });
-        debug!("impl_trait_ty_to_ty: substs={:?}", substs);
+        debug!("impl_trait_ty_to_ty: args={:?}", args);
 
         if in_trait {
-            Ty::new_projection(tcx, def_id, substs)
+            Ty::new_projection(tcx, def_id, args)
         } else {
-            Ty::new_opaque(tcx, def_id, substs)
+            Ty::new_opaque(tcx, def_id, args)
         }
     }
 
@@ -2688,7 +2706,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         let hir = tcx.hir();
 
         let hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Fn(..), ident, .. }) =
-            hir.get(fn_hir_id) else { return None };
+            hir.get(fn_hir_id)
+        else {
+            return None;
+        };
         let i = hir.get_parent(fn_hir_id).expect_item().expect_impl();
 
         let trait_ref = self.instantiate_mono_trait_ref(
@@ -2704,9 +2725,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             trait_ref.def_id,
         )?;
 
-        let fn_sig = tcx.fn_sig(assoc.def_id).subst(
+        let fn_sig = tcx.fn_sig(assoc.def_id).instantiate(
             tcx,
-            trait_ref.substs.extend_to(tcx, assoc.def_id, |param, _| tcx.mk_param_from_def(param)),
+            trait_ref.args.extend_to(tcx, assoc.def_id, |param, _| tcx.mk_param_from_def(param)),
         );
         let fn_sig = tcx.liberate_late_bound_regions(fn_hir_id.expect_owner().to_def_id(), fn_sig);
 
diff --git a/compiler/rustc_hir_analysis/src/astconv/object_safety.rs b/compiler/rustc_hir_analysis/src/astconv/object_safety.rs
index 9227ee93451..a36ec0c5730 100644
--- a/compiler/rustc_hir_analysis/src/astconv/object_safety.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/object_safety.rs
@@ -173,7 +173,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                             tcx.associated_items(pred.def_id())
                                 .in_definition_order()
                                 .filter(|item| item.kind == ty::AssocKind::Type)
-                                .filter(|item| item.opt_rpitit_info.is_none())
+                                .filter(|item| !item.is_impl_trait_in_trait())
                                 .map(|item| item.def_id),
                         );
                     }
@@ -262,8 +262,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 let mut missing_type_params = vec![];
                 let mut references_self = false;
                 let generics = tcx.generics_of(trait_ref.def_id);
-                let substs: Vec<_> = trait_ref
-                    .substs
+                let args: Vec<_> = trait_ref
+                    .args
                     .iter()
                     .enumerate()
                     .skip(1) // Remove `Self` for `ExistentialPredicate`.
@@ -279,7 +279,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                         arg
                     })
                     .collect();
-                let substs = tcx.mk_substs(&substs);
+                let args = tcx.mk_args(&args);
 
                 let span = i.bottom().1;
                 let empty_generic_args = hir_trait_bounds.iter().any(|hir_bound| {
@@ -310,7 +310,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                     err.emit();
                 }
 
-                ty::ExistentialTraitRef { def_id: trait_ref.def_id, substs }
+                ty::ExistentialTraitRef { def_id: trait_ref.def_id, args }
             })
         });
 
@@ -325,7 +325,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
 
                     // Like for trait refs, verify that `dummy_self` did not leak inside default type
                     // parameters.
-                    let references_self = b.projection_ty.substs.iter().skip(1).any(|arg| {
+                    let references_self = b.projection_ty.args.iter().skip(1).any(|arg| {
                         if arg.walk().any(|arg| arg == dummy_self.into()) {
                             return true;
                         }
@@ -336,9 +336,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                             span,
                             "trait object projection bounds reference `Self`",
                         );
-                        let substs: Vec<_> = b
+                        let args: Vec<_> = b
                             .projection_ty
-                            .substs
+                            .args
                             .iter()
                             .map(|arg| {
                                 if arg.walk().any(|arg| arg == dummy_self.into()) {
@@ -347,7 +347,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                                 arg
                             })
                             .collect();
-                        b.projection_ty.substs = tcx.mk_substs(&substs);
+                        b.projection_ty.args = tcx.mk_args(&args);
                     }
 
                     ty::ExistentialProjection::erase_self_ty(tcx, b)
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index 91c33b09082..a4ef8e43527 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -20,8 +20,8 @@ use rustc_middle::hir::nested_filter;
 use rustc_middle::middle::stability::EvalResult;
 use rustc_middle::traits::DefiningAnchor;
 use rustc_middle::ty::layout::{LayoutError, MAX_SIMD_LANES};
-use rustc_middle::ty::subst::GenericArgKind;
 use rustc_middle::ty::util::{Discr, IntTypeExt};
+use rustc_middle::ty::GenericArgKind;
 use rustc_middle::ty::{
     self, AdtDef, ParamEnv, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
 };
@@ -96,8 +96,8 @@ 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).subst_identity();
-    if let ty::Adt(def, substs) = item_type.kind() {
+    let item_type = tcx.type_of(item_def_id).instantiate_identity();
+    if let ty::Adt(def, args) = item_type.kind() {
         assert!(def.is_union());
 
         fn allowed_union_field<'tcx>(
@@ -128,7 +128,7 @@ fn check_union_fields(tcx: TyCtxt<'_>, span: Span, item_def_id: LocalDefId) -> b
 
         let param_env = tcx.param_env(item_def_id);
         for field in &def.non_enum_variant().fields {
-            let field_ty = tcx.normalize_erasing_regions(param_env, field.ty(tcx, substs));
+            let field_ty = tcx.normalize_erasing_regions(param_env, field.ty(tcx, args));
 
             if !allowed_union_field(field_ty, tcx, param_env) {
                 let (field_span, ty_span) = match tcx.hir().get_if_local(field.did) {
@@ -163,7 +163,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).subst_identity();
+    let ty = tcx.type_of(def_id).instantiate_identity();
     let span = tcx.def_span(def_id);
     let layout = match tcx.layout_of(ParamEnv::reveal_all().and(ty)) {
         Ok(l) => l,
@@ -212,16 +212,16 @@ fn check_opaque(tcx: TyCtxt<'_>, id: hir::ItemId) {
         return;
     }
 
-    let substs = InternalSubsts::identity_for_item(tcx, item.owner_id);
+    let args = GenericArgs::identity_for_item(tcx, item.owner_id);
     let span = tcx.def_span(item.owner_id.def_id);
 
     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).subst_identity().references_error() {
+    if tcx.type_of(item.owner_id.def_id).instantiate_identity().references_error() {
         return;
     }
-    if check_opaque_for_cycles(tcx, item.owner_id.def_id, substs, span, &origin).is_err() {
+    if check_opaque_for_cycles(tcx, item.owner_id.def_id, args, span, &origin).is_err() {
         return;
     }
 
@@ -305,8 +305,8 @@ pub(super) fn check_opaque_for_inheriting_lifetimes(
         ..
     }) = item.kind
     {
-        let substs = InternalSubsts::identity_for_item(tcx, def_id);
-        let opaque_identity_ty = Ty::new_opaque(tcx, def_id.to_def_id(), substs);
+        let args = GenericArgs::identity_for_item(tcx, def_id);
+        let opaque_identity_ty = Ty::new_opaque(tcx, def_id.to_def_id(), args);
         let mut visitor = ProhibitOpaqueVisitor {
             opaque_identity_ty,
             parent_count: tcx.generics_of(def_id).parent_count as u32,
@@ -316,7 +316,7 @@ pub(super) fn check_opaque_for_inheriting_lifetimes(
         };
         let prohibit_opaque = tcx
             .explicit_item_bounds(def_id)
-            .subst_identity_iter_copied()
+            .instantiate_identity_iter_copied()
             .try_for_each(|(predicate, _)| predicate.visit_with(&mut visitor));
 
         if let Some(ty) = prohibit_opaque.break_value() {
@@ -355,11 +355,11 @@ pub(super) fn check_opaque_for_inheriting_lifetimes(
 pub(super) fn check_opaque_for_cycles<'tcx>(
     tcx: TyCtxt<'tcx>,
     def_id: LocalDefId,
-    substs: SubstsRef<'tcx>,
+    args: GenericArgsRef<'tcx>,
     span: Span,
     origin: &hir::OpaqueTyOrigin,
 ) -> Result<(), ErrorGuaranteed> {
-    if tcx.try_expand_impl_trait_type(def_id.to_def_id(), substs).is_err() {
+    if tcx.try_expand_impl_trait_type(def_id.to_def_id(), args).is_err() {
         let reported = match origin {
             hir::OpaqueTyOrigin::AsyncFn(..) => async_opaque_type_cycle_error(tcx, span),
             _ => opaque_type_cycle_error(tcx, def_id, span),
@@ -404,16 +404,16 @@ fn check_opaque_meets_bounds<'tcx>(
         .build();
     let ocx = ObligationCtxt::new(&infcx);
 
-    let substs = InternalSubsts::identity_for_item(tcx, def_id.to_def_id());
-    let opaque_ty = Ty::new_opaque(tcx, def_id.to_def_id(), substs);
+    let args = GenericArgs::identity_for_item(tcx, def_id.to_def_id());
+    let opaque_ty = Ty::new_opaque(tcx, def_id.to_def_id(), args);
 
-    // `ReErased` regions appear in the "parent_substs" of closures/generators.
+    // `ReErased` regions appear in the "parent_args" of closures/generators.
     // We're ignoring them here and replacing them with fresh region variables.
-    // See tests in ui/type-alias-impl-trait/closure_{parent_substs,wf_outlives}.rs.
+    // See tests in ui/type-alias-impl-trait/closure_{parent_args,wf_outlives}.rs.
     //
     // FIXME: Consider wrapping the hidden type in an existential `Binder` and instantiating it
     // here rather than using ReErased.
-    let hidden_ty = tcx.type_of(def_id.to_def_id()).subst(tcx, substs);
+    let hidden_ty = tcx.type_of(def_id.to_def_id()).instantiate(tcx, args);
     let hidden_ty = tcx.fold_regions(hidden_ty, |re, _dbi| match re.kind() {
         ty::ReErased => infcx.next_region_var(RegionVariableOrigin::MiscVariable(span)),
         _ => re,
@@ -472,7 +472,7 @@ fn check_opaque_meets_bounds<'tcx>(
 fn is_enum_of_nonnullable_ptr<'tcx>(
     tcx: TyCtxt<'tcx>,
     adt_def: AdtDef<'tcx>,
-    substs: SubstsRef<'tcx>,
+    args: GenericArgsRef<'tcx>,
 ) -> bool {
     if adt_def.repr().inhibit_enum_layout_opt() {
         return false;
@@ -484,14 +484,14 @@ fn is_enum_of_nonnullable_ptr<'tcx>(
     let (([], [field]) | ([field], [])) = (&var_one.fields.raw[..], &var_two.fields.raw[..]) else {
         return false;
     };
-    matches!(field.ty(tcx, substs).kind(), ty::FnPtr(..) | ty::Ref(..))
+    matches!(field.ty(tcx, args).kind(), ty::FnPtr(..) | ty::Ref(..))
 }
 
 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).subst_identity().kind() {
+        if match tcx.type_of(def_id).instantiate_identity().kind() {
             ty::RawPtr(_) => false,
-            ty::Adt(adt_def, substs) => !is_enum_of_nonnullable_ptr(tcx, *adt_def, *substs),
+            ty::Adt(adt_def, args) => !is_enum_of_nonnullable_ptr(tcx, *adt_def, *args),
             _ => true,
         } {
             tcx.sess.emit_err(LinkageType { span: tcx.def_span(def_id) });
@@ -525,7 +525,7 @@ fn check_item_type(tcx: TyCtxt<'_>, id: hir::ItemId) {
                 check_impl_items_against_trait(
                     tcx,
                     id.owner_id.def_id,
-                    impl_trait_ref.subst_identity(),
+                    impl_trait_ref.instantiate_identity(),
                 );
                 check_on_unimplemented(tcx, id);
             }
@@ -541,13 +541,13 @@ fn check_item_type(tcx: TyCtxt<'_>, id: hir::ItemId) {
                         fn_maybe_err(tcx, assoc_item.ident(tcx).span, abi);
                     }
                     ty::AssocKind::Type if assoc_item.defaultness(tcx).has_value() => {
-                        let trait_substs =
-                            InternalSubsts::identity_for_item(tcx, id.owner_id);
+                        let trait_args =
+                            GenericArgs::identity_for_item(tcx, id.owner_id);
                         let _: Result<_, rustc_errors::ErrorGuaranteed> = check_type_bounds(
                             tcx,
                             assoc_item,
                             assoc_item,
-                            ty::TraitRef::new(tcx, id.owner_id.to_def_id(), trait_substs),
+                            ty::TraitRef::new(tcx, id.owner_id.to_def_id(), trait_args),
                         );
                     }
                     _ => {}
@@ -572,7 +572,7 @@ fn check_item_type(tcx: TyCtxt<'_>, id: hir::ItemId) {
             }
         }
         DefKind::TyAlias => {
-            let pty_ty = tcx.type_of(id.owner_id).subst_identity();
+            let pty_ty = tcx.type_of(id.owner_id).instantiate_identity();
             let generics = tcx.generics_of(id.owner_id);
             check_type_params_are_used(tcx, &generics, pty_ty);
         }
@@ -886,8 +886,8 @@ 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).subst_identity();
-    if let ty::Adt(def, substs) = t.kind()
+    let t = tcx.type_of(def_id).instantiate_identity();
+    if let ty::Adt(def, args) = t.kind()
         && def.is_struct()
     {
         let fields = &def.non_enum_variant().fields;
@@ -895,8 +895,8 @@ pub fn check_simd(tcx: TyCtxt<'_>, sp: Span, def_id: LocalDefId) {
             struct_span_err!(tcx.sess, sp, E0075, "SIMD vector cannot be empty").emit();
             return;
         }
-        let e = fields[FieldIdx::from_u32(0)].ty(tcx, substs);
-        if !fields.iter().all(|f| f.ty(tcx, substs) == e) {
+        let e = fields[FieldIdx::from_u32(0)].ty(tcx, args);
+        if !fields.iter().all(|f| f.ty(tcx, args) == e) {
             struct_span_err!(tcx.sess, sp, E0076, "SIMD vector should be homogeneous")
                 .span_label(sp, "SIMD elements must have the same type")
                 .emit();
@@ -1003,7 +1003,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()).subst_identity(),
+                                    tcx.type_of(def.did()).instantiate_identity(),
                                     ident
                                 )
                             } else {
@@ -1025,7 +1025,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).subst_identity().kind() {
+    if let ty::Adt(def, args) = tcx.type_of(def_id).instantiate_identity().kind() {
         if def.is_struct() || def.is_union() {
             if def.repr().align.is_some() {
                 return Some(vec![(def.did(), DUMMY_SP)]);
@@ -1033,7 +1033,7 @@ pub(super) fn check_packed_inner(
 
             stack.push(def_id);
             for field in &def.non_enum_variant().fields {
-                if let ty::Adt(def, _) = field.ty(tcx, substs).kind()
+                if let ty::Adt(def, _) = field.ty(tcx, args).kind()
                     && !stack.contains(&def.did())
                     && let Some(mut defs) = check_packed_inner(tcx, def.did(), stack)
                 {
@@ -1072,7 +1072,7 @@ pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>)
     // For each field, figure out if it's known to be a ZST and align(1), with "known"
     // respecting #[non_exhaustive] attributes.
     let field_infos = adt.all_fields().map(|field| {
-        let ty = field.ty(tcx, InternalSubsts::identity_for_item(tcx, field.did));
+        let ty = field.ty(tcx, GenericArgs::identity_for_item(tcx, field.did));
         let param_env = tcx.param_env(field.did);
         let layout = tcx.layout_of(param_env.and(ty));
         // We are currently checking the type this field came from, so it must be local
@@ -1086,7 +1086,7 @@ pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>)
         fn check_non_exhaustive<'tcx>(
             tcx: TyCtxt<'tcx>,
             t: Ty<'tcx>,
-        ) -> ControlFlow<(&'static str, DefId, SubstsRef<'tcx>, bool)> {
+        ) -> ControlFlow<(&'static str, DefId, GenericArgsRef<'tcx>, bool)> {
             match t.kind() {
                 ty::Tuple(list) => list.iter().try_for_each(|t| check_non_exhaustive(tcx, t)),
                 ty::Array(ty, _) => check_non_exhaustive(tcx, *ty),
@@ -1140,7 +1140,7 @@ pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>)
             .span_label(span, "has alignment larger than 1")
             .emit();
         }
-        if incompat && let Some((descr, def_id, substs, non_exhaustive)) = non_exhaustive {
+        if incompat && let Some((descr, def_id, args, non_exhaustive)) = non_exhaustive {
             tcx.struct_span_lint_hir(
                 REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS,
                 tcx.hir().local_def_id_to_hir_id(adt.did().expect_local()),
@@ -1152,7 +1152,7 @@ pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>)
                     } else {
                         "contains private fields"
                     };
-                    let field_ty = tcx.def_path_str_with_substs(def_id, substs);
+                    let field_ty = tcx.def_path_str_with_args(def_id, args);
                     lint
                         .note(format!("this {descr} contains `{field_ty}`, which {note}, \
                             and makes it not a breaking change to become non-zero-sized in the future."))
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 22e576e345e..07f8dd948e2 100644
--- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
@@ -16,7 +16,7 @@ use rustc_infer::traits::util;
 use rustc_middle::ty::error::{ExpectedFound, TypeError};
 use rustc_middle::ty::util::ExplicitSelf;
 use rustc_middle::ty::{
-    self, InternalSubsts, Ty, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt,
+    self, GenericArgs, Ty, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt,
 };
 use rustc_middle::ty::{GenericParamDefKind, ToPredicate, TyCtxt};
 use rustc_span::{Span, DUMMY_SP};
@@ -96,15 +96,15 @@ fn check_method_is_structurally_compatible<'tcx>(
 /// For this we have to show that, assuming the bounds of the impl hold, the
 /// bounds of `trait_m` imply the bounds of `impl_m`.
 ///
-/// We start out with `trait_to_impl_substs`, that maps the trait
+/// We start out with `trait_to_impl_args`, that maps the trait
 /// type parameters to impl type parameters. This is taken from the
 /// impl trait reference:
 ///
 /// ```rust,ignore (pseudo-Rust)
-/// trait_to_impl_substs = {'t => 'j, T => &'i U, Self => Foo}
+/// trait_to_impl_args = {'t => 'j, T => &'i U, Self => Foo}
 /// ```
 ///
-/// We create a mapping `dummy_substs` that maps from the impl type
+/// We create a mapping `dummy_args` that maps from the impl type
 /// parameters to fresh types and regions. For type parameters,
 /// this is the identity transform, but we could as well use any
 /// placeholder types. For regions, we convert from bound to free
@@ -112,10 +112,10 @@ fn check_method_is_structurally_compatible<'tcx>(
 /// declared on the impl or used in type parameter bounds).
 ///
 /// ```rust,ignore (pseudo-Rust)
-/// impl_to_placeholder_substs = {'i => 'i0, U => U0, N => N0 }
+/// impl_to_placeholder_args = {'i => 'i0, U => U0, N => N0 }
 /// ```
 ///
-/// Now we can apply `placeholder_substs` to the type of the impl method
+/// Now we can apply `placeholder_args` to the type of the impl method
 /// to yield a new function type in terms of our fresh, placeholder
 /// types:
 ///
@@ -125,13 +125,13 @@ fn check_method_is_structurally_compatible<'tcx>(
 ///
 /// We now want to extract and substitute the type of the *trait*
 /// method and compare it. To do so, we must create a compound
-/// substitution by combining `trait_to_impl_substs` and
-/// `impl_to_placeholder_substs`, and also adding a mapping for the method
+/// substitution by combining `trait_to_impl_args` and
+/// `impl_to_placeholder_args`, and also adding a mapping for the method
 /// type parameters. We extend the mapping to also include
 /// the method parameters.
 ///
 /// ```rust,ignore (pseudo-Rust)
-/// trait_to_placeholder_substs = { T => &'i0 U0, Self => Foo, M => N0 }
+/// trait_to_placeholder_args = { T => &'i0 U0, Self => Foo, M => N0 }
 /// ```
 ///
 /// Applying this to the trait method type yields:
@@ -148,8 +148,8 @@ fn check_method_is_structurally_compatible<'tcx>(
 /// satisfied by the implementation's method.
 ///
 /// We do this by creating a parameter environment which contains a
-/// substitution corresponding to `impl_to_placeholder_substs`. We then build
-/// `trait_to_placeholder_substs` and use it to convert the predicates contained
+/// substitution corresponding to `impl_to_placeholder_args`. We then build
+/// `trait_to_placeholder_args` and use it to convert the predicates contained
 /// in the `trait_m` generics to the placeholder form.
 ///
 /// Finally we register each of these predicates as an obligation and check that
@@ -162,7 +162,7 @@ fn compare_method_predicate_entailment<'tcx>(
     impl_trait_ref: ty::TraitRef<'tcx>,
     check_implied_wf: CheckImpliedWfMode,
 ) -> Result<(), ErrorGuaranteed> {
-    let trait_to_impl_substs = impl_trait_ref.substs;
+    let trait_to_impl_args = impl_trait_ref.args;
 
     // This node-id should be used for the `body_id` field on each
     // `ObligationCause` (and the `FnCtxt`).
@@ -182,12 +182,12 @@ fn compare_method_predicate_entailment<'tcx>(
     );
 
     // Create mapping from impl to placeholder.
-    let impl_to_placeholder_substs = InternalSubsts::identity_for_item(tcx, impl_m.def_id);
+    let impl_to_placeholder_args = GenericArgs::identity_for_item(tcx, impl_m.def_id);
 
     // Create mapping from trait to placeholder.
-    let trait_to_placeholder_substs =
-        impl_to_placeholder_substs.rebase_onto(tcx, impl_m.container_id(tcx), trait_to_impl_substs);
-    debug!("compare_impl_method: trait_to_placeholder_substs={:?}", trait_to_placeholder_substs);
+    let trait_to_placeholder_args =
+        impl_to_placeholder_args.rebase_onto(tcx, impl_m.container_id(tcx), trait_to_impl_args);
+    debug!("compare_impl_method: trait_to_placeholder_args={:?}", trait_to_placeholder_args);
 
     let impl_m_predicates = tcx.predicates_of(impl_m.def_id);
     let trait_m_predicates = tcx.predicates_of(trait_m.def_id);
@@ -211,7 +211,7 @@ fn compare_method_predicate_entailment<'tcx>(
     // if all constraints hold.
     hybrid_preds.predicates.extend(
         trait_m_predicates
-            .instantiate_own(tcx, trait_to_placeholder_substs)
+            .instantiate_own(tcx, trait_to_placeholder_args)
             .map(|(predicate, _)| predicate),
     );
 
@@ -231,7 +231,7 @@ fn compare_method_predicate_entailment<'tcx>(
 
     debug!("compare_impl_method: caller_bounds={:?}", param_env.caller_bounds());
 
-    let impl_m_own_bounds = impl_m_predicates.instantiate_own(tcx, impl_to_placeholder_substs);
+    let impl_m_own_bounds = impl_m_predicates.instantiate_own(tcx, impl_to_placeholder_args);
     for (predicate, span) in impl_m_own_bounds {
         let normalize_cause = traits::ObligationCause::misc(span, impl_m_def_id);
         let predicate = ocx.normalize(&normalize_cause, param_env, predicate);
@@ -269,7 +269,7 @@ fn compare_method_predicate_entailment<'tcx>(
     let unnormalized_impl_sig = infcx.instantiate_binder_with_fresh_vars(
         impl_m_span,
         infer::HigherRankedType,
-        tcx.fn_sig(impl_m.def_id).subst_identity(),
+        tcx.fn_sig(impl_m.def_id).instantiate_identity(),
     );
     let unnormalized_impl_fty = Ty::new_fn_ptr(tcx, ty::Binder::dummy(unnormalized_impl_sig));
 
@@ -277,7 +277,7 @@ fn compare_method_predicate_entailment<'tcx>(
     let impl_sig = ocx.normalize(&norm_cause, param_env, unnormalized_impl_sig);
     debug!("compare_impl_method: impl_fty={:?}", impl_sig);
 
-    let trait_sig = tcx.fn_sig(trait_m.def_id).subst(tcx, trait_to_placeholder_substs);
+    let trait_sig = tcx.fn_sig(trait_m.def_id).instantiate(tcx, trait_to_placeholder_args);
     let trait_sig = tcx.liberate_late_bound_regions(impl_m.def_id, trait_sig);
 
     // Next, add all inputs and output as well-formed tys. Importantly,
@@ -615,14 +615,14 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
     let impl_m = tcx.opt_associated_item(impl_m_def_id.to_def_id()).unwrap();
     let trait_m = tcx.opt_associated_item(impl_m.trait_item_def_id.unwrap()).unwrap();
     let impl_trait_ref =
-        tcx.impl_trait_ref(impl_m.impl_container(tcx).unwrap()).unwrap().subst_identity();
+        tcx.impl_trait_ref(impl_m.impl_container(tcx).unwrap()).unwrap().instantiate_identity();
     let param_env = tcx.param_env(impl_m_def_id);
 
     // First, check a few of the same things as `compare_impl_method`,
     // just so we don't ICE during substitution later.
     check_method_is_structurally_compatible(tcx, impl_m, trait_m, impl_trait_ref, true)?;
 
-    let trait_to_impl_substs = impl_trait_ref.substs;
+    let trait_to_impl_args = impl_trait_ref.args;
 
     let impl_m_hir_id = tcx.hir().local_def_id_to_hir_id(impl_m_def_id);
     let return_span = tcx.hir().fn_decl_by_hir_id(impl_m_hir_id).unwrap().output.span();
@@ -637,11 +637,11 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
     );
 
     // Create mapping from impl to placeholder.
-    let impl_to_placeholder_substs = InternalSubsts::identity_for_item(tcx, impl_m.def_id);
+    let impl_to_placeholder_args = GenericArgs::identity_for_item(tcx, impl_m.def_id);
 
     // Create mapping from trait to placeholder.
-    let trait_to_placeholder_substs =
-        impl_to_placeholder_substs.rebase_onto(tcx, impl_m.container_id(tcx), trait_to_impl_substs);
+    let trait_to_placeholder_args =
+        impl_to_placeholder_args.rebase_onto(tcx, impl_m.container_id(tcx), trait_to_impl_args);
 
     let infcx = &tcx.infer_ctxt().build();
     let ocx = ObligationCtxt::new(infcx);
@@ -651,7 +651,10 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
     let impl_sig = ocx.normalize(
         &norm_cause,
         param_env,
-        tcx.liberate_late_bound_regions(impl_m.def_id, tcx.fn_sig(impl_m.def_id).subst_identity()),
+        tcx.liberate_late_bound_regions(
+            impl_m.def_id,
+            tcx.fn_sig(impl_m.def_id).instantiate_identity(),
+        ),
     );
     impl_sig.error_reported()?;
     let impl_return_ty = impl_sig.output();
@@ -665,7 +668,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
         .instantiate_binder_with_fresh_vars(
             return_span,
             infer::HigherRankedType,
-            tcx.fn_sig(trait_m.def_id).subst(tcx, trait_to_placeholder_substs),
+            tcx.fn_sig(trait_m.def_id).instantiate(tcx, trait_to_placeholder_args),
         )
         .fold_with(&mut collector);
 
@@ -758,47 +761,47 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
     ocx.resolve_regions_and_report_errors(impl_m_def_id, &outlives_env)?;
 
     let mut collected_tys = FxHashMap::default();
-    for (def_id, (ty, substs)) in collected_types {
-        match infcx.fully_resolve((ty, substs)) {
-            Ok((ty, substs)) => {
+    for (def_id, (ty, args)) in collected_types {
+        match infcx.fully_resolve((ty, args)) {
+            Ok((ty, args)) => {
                 // `ty` contains free regions that we created earlier while liberating the
                 // trait fn signature. However, projection normalization expects `ty` to
                 // contains `def_id`'s early-bound regions.
-                let id_substs = InternalSubsts::identity_for_item(tcx, def_id);
-                debug!(?id_substs, ?substs);
-                let map: FxHashMap<_, _> = std::iter::zip(substs, id_substs)
+                let id_args = GenericArgs::identity_for_item(tcx, def_id);
+                debug!(?id_args, ?args);
+                let map: FxHashMap<_, _> = std::iter::zip(args, id_args)
                     .skip(tcx.generics_of(trait_m.def_id).count())
                     .filter_map(|(a, b)| Some((a.as_region()?, b.as_region()?)))
                     .collect();
                 debug!(?map);
 
                 // NOTE(compiler-errors): RPITITs, like all other RPITs, have early-bound
-                // region substs that are synthesized during AST lowering. These are substs
-                // that are appended to the parent substs (trait and trait method). However,
+                // region args that are synthesized during AST lowering. These are args
+                // that are appended to the parent args (trait and trait method). However,
                 // we're trying to infer the unsubstituted type value of the RPITIT inside
-                // the *impl*, so we can later use the impl's method substs to normalize
+                // the *impl*, so we can later use the impl's method args to normalize
                 // an RPITIT to a concrete type (`confirm_impl_trait_in_trait_candidate`).
                 //
                 // Due to the design of RPITITs, during AST lowering, we have no idea that
                 // an impl method corresponds to a trait method with RPITITs in it. Therefore,
-                // we don't have a list of early-bound region substs for the RPITIT in the impl.
+                // we don't have a list of early-bound region args for the RPITIT in the impl.
                 // Since early region parameters are index-based, we can't just rebase these
-                // (trait method) early-bound region substs onto the impl, and there's no
-                // guarantee that the indices from the trait substs and impl substs line up.
-                // So to fix this, we subtract the number of trait substs and add the number of
-                // impl substs to *renumber* these early-bound regions to their corresponding
+                // (trait method) early-bound region args onto the impl, and there's no
+                // guarantee that the indices from the trait args and impl args line up.
+                // So to fix this, we subtract the number of trait args and add the number of
+                // impl args to *renumber* these early-bound regions to their corresponding
                 // indices in the impl's substitutions list.
                 //
-                // Also, we only need to account for a difference in trait and impl substs,
+                // Also, we only need to account for a difference in trait and impl args,
                 // since we previously enforce that the trait method and impl method have the
                 // same generics.
-                let num_trait_substs = trait_to_impl_substs.len();
-                let num_impl_substs = tcx.generics_of(impl_m.container_id(tcx)).params.len();
+                let num_trait_args = trait_to_impl_args.len();
+                let num_impl_args = tcx.generics_of(impl_m.container_id(tcx)).params.len();
                 let ty = match ty.try_fold_with(&mut RemapHiddenTyRegions {
                     tcx,
                     map,
-                    num_trait_substs,
-                    num_impl_substs,
+                    num_trait_args,
+                    num_impl_args,
                     def_id,
                     impl_def_id: impl_m.container_id(tcx),
                     ty,
@@ -824,7 +827,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
 
 struct ImplTraitInTraitCollector<'a, 'tcx> {
     ocx: &'a ObligationCtxt<'a, 'tcx>,
-    types: FxHashMap<DefId, (Ty<'tcx>, ty::SubstsRef<'tcx>)>,
+    types: FxHashMap<DefId, (Ty<'tcx>, ty::GenericArgsRef<'tcx>)>,
     span: Span,
     param_env: ty::ParamEnv<'tcx>,
     body_id: LocalDefId,
@@ -853,8 +856,8 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ImplTraitInTraitCollector<'_, 'tcx> {
             if let Some((ty, _)) = self.types.get(&proj.def_id) {
                 return *ty;
             }
-            //FIXME(RPITIT): Deny nested RPITIT in substs too
-            if proj.substs.has_escaping_bound_vars() {
+            //FIXME(RPITIT): Deny nested RPITIT in args too
+            if proj.args.has_escaping_bound_vars() {
                 bug!("FIXME(RPITIT): error here");
             }
             // Replace with infer var
@@ -862,9 +865,9 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ImplTraitInTraitCollector<'_, 'tcx> {
                 span: self.span,
                 kind: TypeVariableOriginKind::MiscVariable,
             });
-            self.types.insert(proj.def_id, (infer_ty, proj.substs));
+            self.types.insert(proj.def_id, (infer_ty, proj.args));
             // Recurse into bounds
-            for (pred, pred_span) in self.interner().explicit_item_bounds(proj.def_id).subst_iter_copied(self.interner(), proj.substs) {
+            for (pred, pred_span) in self.interner().explicit_item_bounds(proj.def_id).arg_iter_copied(self.interner(), proj.args) {
                 let pred = pred.fold_with(self);
                 let pred = self.ocx.normalize(
                     &ObligationCause::misc(self.span, self.body_id),
@@ -893,8 +896,8 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ImplTraitInTraitCollector<'_, 'tcx> {
 struct RemapHiddenTyRegions<'tcx> {
     tcx: TyCtxt<'tcx>,
     map: FxHashMap<ty::Region<'tcx>, ty::Region<'tcx>>,
-    num_trait_substs: usize,
-    num_impl_substs: usize,
+    num_trait_args: usize,
+    num_impl_args: usize,
     def_id: DefId,
     impl_def_id: DefId,
     ty: Ty<'tcx>,
@@ -909,16 +912,16 @@ impl<'tcx> ty::FallibleTypeFolder<TyCtxt<'tcx>> for RemapHiddenTyRegions<'tcx> {
     }
 
     fn try_fold_ty(&mut self, t: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
-        if let ty::Alias(ty::Opaque, ty::AliasTy { substs, def_id, .. }) = *t.kind() {
-            let mut mapped_substs = Vec::with_capacity(substs.len());
-            for (arg, v) in std::iter::zip(substs, self.tcx.variances_of(def_id)) {
-                mapped_substs.push(match (arg.unpack(), v) {
-                    // Skip uncaptured opaque substs
+        if let ty::Alias(ty::Opaque, ty::AliasTy { args, def_id, .. }) = *t.kind() {
+            let mut mapped_args = Vec::with_capacity(args.len());
+            for (arg, v) in std::iter::zip(args, self.tcx.variances_of(def_id)) {
+                mapped_args.push(match (arg.unpack(), v) {
+                    // Skip uncaptured opaque args
                     (ty::GenericArgKind::Lifetime(_), ty::Bivariant) => arg,
                     _ => arg.try_fold_with(self)?,
                 });
             }
-            Ok(Ty::new_opaque(self.tcx, def_id, self.tcx.mk_substs(&mapped_substs)))
+            Ok(Ty::new_opaque(self.tcx, def_id, self.tcx.mk_args(&mapped_args)))
         } else {
             t.try_super_fold_with(self)
         }
@@ -975,7 +978,7 @@ impl<'tcx> ty::FallibleTypeFolder<TyCtxt<'tcx>> for RemapHiddenTyRegions<'tcx> {
             ty::EarlyBoundRegion {
                 def_id: e.def_id,
                 name: e.name,
-                index: (e.index as usize - self.num_trait_substs + self.num_impl_substs) as u32,
+                index: (e.index as usize - self.num_trait_args + self.num_impl_args) as u32,
             },
         ))
     }
@@ -1214,7 +1217,7 @@ fn compare_self_type<'tcx>(
             ty::ImplContainer => impl_trait_ref.self_ty(),
             ty::TraitContainer => tcx.types.self_param,
         };
-        let self_arg_ty = tcx.fn_sig(method.def_id).subst_identity().input(0);
+        let self_arg_ty = tcx.fn_sig(method.def_id).instantiate_identity().input(0);
         let param_env = ty::ParamEnv::reveal_all();
 
         let infcx = tcx.infer_ctxt().build();
@@ -1319,7 +1322,7 @@ fn compare_number_of_generics<'tcx>(
     // has mismatched type or const generic arguments, then the method that it's
     // inheriting the generics from will also have mismatched arguments, and
     // we'll report an error for that instead. Delay a bug for safety, though.
-    if trait_.opt_rpitit_info.is_some() {
+    if trait_.is_impl_trait_in_trait() {
         return Err(tcx.sess.delay_span_bug(
             rustc_span::DUMMY_SP,
             "errors comparing numbers of generics of trait/impl functions were not emitted",
@@ -1738,7 +1741,7 @@ fn compare_generic_param_kinds<'tcx>(
                     format!(
                         "{} const parameter of type `{}`",
                         prefix,
-                        tcx.type_of(param.def_id).subst_identity()
+                        tcx.type_of(param.def_id).instantiate_identity()
                     )
                 }
                 Type { .. } => format!("{} type parameter", prefix),
@@ -1769,7 +1772,7 @@ pub(super) fn compare_impl_const_raw(
     let impl_const_item = tcx.associated_item(impl_const_item_def);
     let trait_const_item = tcx.associated_item(trait_const_item_def);
     let impl_trait_ref =
-        tcx.impl_trait_ref(impl_const_item.container_id(tcx)).unwrap().subst_identity();
+        tcx.impl_trait_ref(impl_const_item.container_id(tcx)).unwrap().instantiate_identity();
     debug!("compare_const_impl(impl_trait_ref={:?})", impl_trait_ref);
 
     let impl_c_span = tcx.def_span(impl_const_item_def.to_def_id());
@@ -1783,13 +1786,13 @@ pub(super) fn compare_impl_const_raw(
     // because we shouldn't really have to deal with lifetimes or
     // predicates. In fact some of this should probably be put into
     // shared functions because of DRY violations...
-    let trait_to_impl_substs = impl_trait_ref.substs;
+    let trait_to_impl_args = impl_trait_ref.args;
 
     // 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()).subst_identity();
-    let trait_ty = tcx.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()).instantiate_identity();
+    let trait_ty = tcx.type_of(trait_const_item_def).instantiate(tcx, trait_to_impl_args);
     let mut cause = ObligationCause::new(
         impl_c_span,
         impl_const_item_def,
@@ -1885,16 +1888,16 @@ fn compare_type_predicate_entailment<'tcx>(
     trait_ty: ty::AssocItem,
     impl_trait_ref: ty::TraitRef<'tcx>,
 ) -> Result<(), ErrorGuaranteed> {
-    let impl_substs = InternalSubsts::identity_for_item(tcx, impl_ty.def_id);
-    let trait_to_impl_substs =
-        impl_substs.rebase_onto(tcx, impl_ty.container_id(tcx), impl_trait_ref.substs);
+    let impl_args = GenericArgs::identity_for_item(tcx, impl_ty.def_id);
+    let trait_to_impl_args =
+        impl_args.rebase_onto(tcx, impl_ty.container_id(tcx), impl_trait_ref.args);
 
     let impl_ty_predicates = tcx.predicates_of(impl_ty.def_id);
     let trait_ty_predicates = tcx.predicates_of(trait_ty.def_id);
 
     check_region_bounds_on_impl_item(tcx, impl_ty, trait_ty, false)?;
 
-    let impl_ty_own_bounds = impl_ty_predicates.instantiate_own(tcx, impl_substs);
+    let impl_ty_own_bounds = impl_ty_predicates.instantiate_own(tcx, impl_args);
     if impl_ty_own_bounds.len() == 0 {
         // Nothing to check.
         return Ok(());
@@ -1904,7 +1907,7 @@ fn compare_type_predicate_entailment<'tcx>(
     // `ObligationCause` (and the `FnCtxt`). This is what
     // `regionck_item` expects.
     let impl_ty_def_id = impl_ty.def_id.expect_local();
-    debug!("compare_type_predicate_entailment: trait_to_impl_substs={:?}", trait_to_impl_substs);
+    debug!("compare_type_predicate_entailment: trait_to_impl_args={:?}", trait_to_impl_args);
 
     // The predicates declared by the impl definition, the trait and the
     // associated type in the trait are assumed.
@@ -1912,7 +1915,7 @@ fn compare_type_predicate_entailment<'tcx>(
     let mut hybrid_preds = impl_predicates.instantiate_identity(tcx);
     hybrid_preds.predicates.extend(
         trait_ty_predicates
-            .instantiate_own(tcx, trait_to_impl_substs)
+            .instantiate_own(tcx, trait_to_impl_args)
             .map(|(predicate, _)| predicate),
     );
 
@@ -1990,9 +1993,9 @@ pub(super) fn check_type_bounds<'tcx>(
     // }
     //
     // - `impl_trait_ref` would be `<(A, B) as Foo<u32>>`
-    // - `normalize_impl_ty_substs` would be `[A, B, ^0.0]` (`^0.0` here is the bound var with db 0 and index 0)
+    // - `normalize_impl_ty_args` would be `[A, B, ^0.0]` (`^0.0` here is the bound var with db 0 and index 0)
     // - `normalize_impl_ty` would be `Wrapper<A, B, ^0.0>`
-    // - `rebased_substs` would be `[(A, B), u32, ^0.0]`, combining the substs from
+    // - `rebased_args` would be `[(A, B), u32, ^0.0]`, combining the args from
     //    the *trait* with the generic associated type parameters (as bound vars).
     //
     // A note regarding the use of bound vars here:
@@ -2022,9 +2025,11 @@ pub(super) fn check_type_bounds<'tcx>(
     // the trait (notably, that X: Eq and T: Family).
     let mut bound_vars: smallvec::SmallVec<[ty::BoundVariableKind; 8]> =
         smallvec::SmallVec::with_capacity(tcx.generics_of(impl_ty.def_id).params.len());
-    // Extend the impl's identity substs with late-bound GAT vars
-    let normalize_impl_ty_substs = ty::InternalSubsts::identity_for_item(tcx, container_id)
-        .extend_to(tcx, impl_ty.def_id, |param, _| match param.kind {
+    // Extend the impl's identity args with late-bound GAT vars
+    let normalize_impl_ty_args = ty::GenericArgs::identity_for_item(tcx, container_id).extend_to(
+        tcx,
+        impl_ty.def_id,
+        |param, _| match param.kind {
             GenericParamDefKind::Type { .. } => {
                 let kind = ty::BoundTyKind::Param(param.def_id, param.name);
                 let bound_var = ty::BoundVariableKind::Ty(kind);
@@ -2060,7 +2065,8 @@ pub(super) fn check_type_bounds<'tcx>(
                 )
                 .into()
             }
-        });
+        },
+    );
     // When checking something like
     //
     // trait X { type Y: PartialEq<<Self as X>::Y> }
@@ -2070,15 +2076,14 @@ pub(super) fn check_type_bounds<'tcx>(
     // we want <T as X>::Y to normalize to S. This is valid because we are
     // checking the default value specifically here. Add this equality to the
     // ParamEnv for normalization specifically.
-    let normalize_impl_ty = tcx.type_of(impl_ty.def_id).subst(tcx, normalize_impl_ty_substs);
-    let rebased_substs =
-        normalize_impl_ty_substs.rebase_onto(tcx, container_id, impl_trait_ref.substs);
+    let normalize_impl_ty = tcx.type_of(impl_ty.def_id).instantiate(tcx, normalize_impl_ty_args);
+    let rebased_args = normalize_impl_ty_args.rebase_onto(tcx, container_id, impl_trait_ref.args);
     let bound_vars = tcx.mk_bound_variable_kinds(&bound_vars);
     let normalize_param_env = {
         let mut predicates = param_env.caller_bounds().iter().collect::<Vec<_>>();
         match normalize_impl_ty.kind() {
             ty::Alias(ty::Projection, proj)
-                if proj.def_id == trait_ty.def_id && proj.substs == rebased_substs =>
+                if proj.def_id == trait_ty.def_id && proj.args == rebased_args =>
             {
                 // Don't include this predicate if the projected type is
                 // exactly the same as the projection. This can occur in
@@ -2089,7 +2094,7 @@ pub(super) fn check_type_bounds<'tcx>(
             _ => predicates.push(
                 ty::Binder::bind_with_vars(
                     ty::ProjectionPredicate {
-                        projection_ty: tcx.mk_alias_ty(trait_ty.def_id, rebased_substs),
+                        projection_ty: tcx.mk_alias_ty(trait_ty.def_id, rebased_args),
                         term: normalize_impl_ty.into(),
                     },
                     bound_vars,
@@ -2102,8 +2107,8 @@ pub(super) fn check_type_bounds<'tcx>(
     debug!(?normalize_param_env);
 
     let impl_ty_def_id = impl_ty.def_id.expect_local();
-    let impl_ty_substs = InternalSubsts::identity_for_item(tcx, impl_ty.def_id);
-    let rebased_substs = impl_ty_substs.rebase_onto(tcx, container_id, impl_trait_ref.substs);
+    let impl_ty_args = GenericArgs::identity_for_item(tcx, impl_ty.def_id);
+    let rebased_args = impl_ty_args.rebase_onto(tcx, container_id, impl_trait_ref.args);
 
     let infcx = tcx.infer_ctxt().build();
     let ocx = ObligationCtxt::new(&infcx);
@@ -2111,7 +2116,7 @@ pub(super) fn check_type_bounds<'tcx>(
     // A synthetic impl Trait for RPITIT desugaring has no HIR, which we currently use to get the
     // span for an impl's associated type. Instead, for these, use the def_span for the synthesized
     // associated type.
-    let impl_ty_span = if impl_ty.opt_rpitit_info.is_some() {
+    let impl_ty_span = if impl_ty.is_impl_trait_in_trait() {
         tcx.def_span(impl_ty_def_id)
     } else {
         match tcx.hir().get_by_def_id(impl_ty_def_id) {
@@ -2144,7 +2149,7 @@ pub(super) fn check_type_bounds<'tcx>(
 
     let obligations: Vec<_> = tcx
         .explicit_item_bounds(trait_ty.def_id)
-        .subst_iter_copied(tcx, rebased_substs)
+        .arg_iter_copied(tcx, rebased_args)
         .map(|(concrete_ty_bound, span)| {
             debug!("check_type_bounds: concrete_ty_bound = {:?}", concrete_ty_bound);
             traits::Obligation::new(tcx, mk_cause(span), param_env, concrete_ty_bound)
diff --git a/compiler/rustc_hir_analysis/src/check/dropck.rs b/compiler/rustc_hir_analysis/src/check/dropck.rs
index 13d1abe2a65..4ac3a7c23ae 100644
--- a/compiler/rustc_hir_analysis/src/check/dropck.rs
+++ b/compiler/rustc_hir_analysis/src/check/dropck.rs
@@ -5,8 +5,8 @@ use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::{struct_span_err, ErrorGuaranteed};
 use rustc_infer::infer::outlives::env::OutlivesEnvironment;
 use rustc_infer::infer::{RegionResolutionError, TyCtxtInferExt};
-use rustc_middle::ty::subst::SubstsRef;
 use rustc_middle::ty::util::CheckRegions;
+use rustc_middle::ty::GenericArgsRef;
 use rustc_middle::ty::{self, TyCtxt};
 use rustc_trait_selection::traits::{self, ObligationCtxt};
 
@@ -44,21 +44,21 @@ pub fn check_drop_impl(tcx: TyCtxt<'_>, drop_impl_did: DefId) -> Result<(), Erro
             }));
         }
     }
-    let dtor_self_type = tcx.type_of(drop_impl_did).subst_identity();
+    let dtor_self_type = tcx.type_of(drop_impl_did).instantiate_identity();
     match dtor_self_type.kind() {
-        ty::Adt(adt_def, adt_to_impl_substs) => {
+        ty::Adt(adt_def, adt_to_impl_args) => {
             ensure_drop_params_and_item_params_correspond(
                 tcx,
                 drop_impl_did.expect_local(),
                 adt_def.did(),
-                adt_to_impl_substs,
+                adt_to_impl_args,
             )?;
 
             ensure_drop_predicates_are_implied_by_item_defn(
                 tcx,
                 drop_impl_did.expect_local(),
                 adt_def.did().expect_local(),
-                adt_to_impl_substs,
+                adt_to_impl_args,
             )
         }
         _ => {
@@ -79,10 +79,11 @@ fn ensure_drop_params_and_item_params_correspond<'tcx>(
     tcx: TyCtxt<'tcx>,
     drop_impl_did: LocalDefId,
     self_type_did: DefId,
-    adt_to_impl_substs: SubstsRef<'tcx>,
+    adt_to_impl_args: GenericArgsRef<'tcx>,
 ) -> Result<(), ErrorGuaranteed> {
-    let Err(arg) = tcx.uses_unique_generic_params(adt_to_impl_substs, CheckRegions::OnlyEarlyBound) else {
-        return Ok(())
+    let Err(arg) = tcx.uses_unique_generic_params(adt_to_impl_args, CheckRegions::OnlyEarlyBound)
+    else {
+        return Ok(());
     };
 
     let drop_impl_span = tcx.def_span(drop_impl_did);
@@ -114,12 +115,12 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
     tcx: TyCtxt<'tcx>,
     drop_impl_def_id: LocalDefId,
     adt_def_id: LocalDefId,
-    adt_to_impl_substs: SubstsRef<'tcx>,
+    adt_to_impl_args: GenericArgsRef<'tcx>,
 ) -> Result<(), ErrorGuaranteed> {
     let infcx = tcx.infer_ctxt().build();
     let ocx = ObligationCtxt::new(&infcx);
 
-    // Take the param-env of the adt and substitute the substs that show up in
+    // Take the param-env of the adt and substitute the args that show up in
     // the implementation's self type. This gives us the assumptions that the
     // self ty of the implementation is allowed to know just from it being a
     // well-formed adt, since that's all we're allowed to assume while proving
@@ -129,7 +130,7 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
     // substituting it with free params, so no additional param-env normalization
     // can occur on top of what has been done in the param_env query itself.
     let param_env = ty::EarlyBinder::bind(tcx.param_env(adt_def_id))
-        .subst(tcx, adt_to_impl_substs)
+        .instantiate(tcx, adt_to_impl_args)
         .with_constness(tcx.constness(drop_impl_def_id));
 
     for (pred, span) in tcx.predicates_of(drop_impl_def_id).instantiate_identity(tcx) {
diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
index 1248f991cc4..d5c9840887a 100644
--- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs
+++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
@@ -60,7 +60,7 @@ fn equate_intrinsic_type<'tcx>(
             tcx,
             &cause,
             ty::ParamEnv::empty(), // FIXME: do all intrinsics have an empty param env?
-            Ty::new_fn_ptr(tcx, tcx.fn_sig(it.owner_id).subst_identity()),
+            Ty::new_fn_ptr(tcx, tcx.fn_sig(it.owner_id).instantiate_identity()),
             fty,
         );
     }
@@ -155,7 +155,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
                 ty::INNERMOST,
                 ty::BoundRegion { var: ty::BoundVar::from_u32(1), kind: ty::BrEnv },
             );
-            let va_list_ty = tcx.type_of(did).subst(tcx, &[region.into()]);
+            let va_list_ty = tcx.type_of(did).instantiate(tcx, &[region.into()]);
             (Ty::new_ref(tcx, env_region, ty::TypeAndMut { ty: va_list_ty, mutbl }), va_list_ty)
         })
     };
@@ -238,7 +238,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
                             ty: Ty::new_adt(
                                 tcx,
                                 tcx.adt_def(option_def_id),
-                                tcx.mk_substs_from_iter([ty::GenericArg::from(p0)].into_iter()),
+                                tcx.mk_args_from_iter([ty::GenericArg::from(p0)].into_iter()),
                             ),
                             mutbl: hir::Mutability::Not,
                         },
@@ -412,7 +412,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
                         ty::Region::new_late_bound(tcx, ty::INNERMOST, br),
                         param(0),
                     )],
-                    Ty::new_projection(tcx, discriminant_def_id, tcx.mk_substs(&[param(0).into()])),
+                    Ty::new_projection(tcx, discriminant_def_id, tcx.mk_args(&[param(0).into()])),
                 )
             }
 
diff --git a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs
index 0bb1467ef31..8423a9550ba 100644
--- a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs
+++ b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs
@@ -81,9 +81,9 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
             ty::RawPtr(ty::TypeAndMut { ty, mutbl: _ }) if self.is_thin_ptr_ty(ty) => {
                 Some(asm_ty_isize)
             }
-            ty::Adt(adt, substs) if adt.repr().simd() => {
+            ty::Adt(adt, args) if adt.repr().simd() => {
                 let fields = &adt.non_enum_variant().fields;
-                let elem_ty = fields[FieldIdx::from_u32(0)].ty(self.tcx, substs);
+                let elem_ty = fields[FieldIdx::from_u32(0)].ty(self.tcx, args);
 
                 let (size, ty) = match elem_ty.kind() {
                     ty::Array(ty, len) => {
@@ -186,18 +186,14 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
         let Some((_, feature)) = supported_tys.iter().find(|&&(t, _)| t == asm_ty) else {
             let msg = format!("type `{ty}` cannot be used with this register class");
             let mut err = self.tcx.sess.struct_span_err(expr.span, msg);
-            let supported_tys: Vec<_> =
-                supported_tys.iter().map(|(t, _)| t.to_string()).collect();
+            let supported_tys: Vec<_> = supported_tys.iter().map(|(t, _)| t.to_string()).collect();
             err.note(format!(
                 "register class `{}` supports these types: {}",
                 reg_class.name(),
                 supported_tys.join(", "),
             ));
             if let Some(suggest) = reg_class.suggest_class(asm_arch, asm_ty) {
-                err.help(format!(
-                    "consider using the `{}` register class instead",
-                    suggest.name()
-                ));
+                err.help(format!("consider using the `{}` register class instead", suggest.name()));
             }
             err.emit();
             return Some(asm_ty);
@@ -427,7 +423,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).subst_identity();
+                    let ty = self.tcx.type_of(anon_const.def_id).instantiate_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 ce2da7cb1a3..5f679620c28 100644
--- a/compiler/rustc_hir_analysis/src/check/mod.rs
+++ b/compiler/rustc_hir_analysis/src/check/mod.rs
@@ -38,7 +38,7 @@ can be broken down into several distinct phases:
 
 While type checking a function, the intermediate types for the
 expressions, blocks, and so forth contained within the function are
-stored in `fcx.node_types` and `fcx.node_substs`. These types
+stored in `fcx.node_types` and `fcx.node_args`. These types
 may contain unresolved type variables. After type checking is
 complete, the functions in the writeback module are used to take the
 types from this table, resolve them, and then write them into their
@@ -80,7 +80,7 @@ use rustc_hir::intravisit::Visitor;
 use rustc_index::bit_set::BitSet;
 use rustc_middle::query::Providers;
 use rustc_middle::ty::{self, Ty, TyCtxt};
-use rustc_middle::ty::{InternalSubsts, SubstsRef};
+use rustc_middle::ty::{GenericArgs, GenericArgsRef};
 use rustc_session::parse::feature_err;
 use rustc_span::source_map::DUMMY_SP;
 use rustc_span::symbol::{kw, Ident};
@@ -188,7 +188,7 @@ fn missing_items_err(
     full_impl_span: Span,
 ) {
     let missing_items =
-        missing_items.iter().filter(|trait_item| trait_item.opt_rpitit_info.is_none());
+        missing_items.iter().filter(|trait_item| !trait_item.is_impl_trait_in_trait());
 
     let missing_items_msg = missing_items
         .clone()
@@ -211,7 +211,7 @@ fn missing_items_err(
         let snippet = suggestion_signature(
             tcx,
             trait_item,
-            tcx.impl_trait_ref(impl_def_id).unwrap().subst_identity(),
+            tcx.impl_trait_ref(impl_def_id).unwrap().instantiate_identity(),
         );
         let code = format!("{}{}\n{}", padding, snippet, padding);
         if let Some(span) = tcx.hir().span_if_local(trait_item.def_id) {
@@ -408,7 +408,7 @@ fn fn_sig_suggestion<'tcx>(
     let asyncness = if tcx.asyncness(assoc.def_id).is_async() {
         output = if let ty::Alias(_, alias_ty) = *output.kind() {
             tcx.explicit_item_bounds(alias_ty.def_id)
-                .subst_iter_copied(tcx, alias_ty.substs)
+                .arg_iter_copied(tcx, alias_ty.args)
                 .find_map(|(bound, _)| bound.as_projection_clause()?.no_bound_vars()?.term.ty())
                 .unwrap_or_else(|| {
                     span_bug!(
@@ -461,10 +461,10 @@ fn suggestion_signature<'tcx>(
     assoc: ty::AssocItem,
     impl_trait_ref: ty::TraitRef<'tcx>,
 ) -> String {
-    let substs = ty::InternalSubsts::identity_for_item(tcx, assoc.def_id).rebase_onto(
+    let args = ty::GenericArgs::identity_for_item(tcx, assoc.def_id).rebase_onto(
         tcx,
         assoc.container_id(tcx),
-        impl_trait_ref.with_self_ty(tcx, tcx.types.self_param).substs,
+        impl_trait_ref.with_self_ty(tcx, tcx.types.self_param).args,
     );
 
     match assoc.kind {
@@ -472,21 +472,21 @@ fn suggestion_signature<'tcx>(
             tcx,
             tcx.liberate_late_bound_regions(
                 assoc.def_id,
-                tcx.fn_sig(assoc.def_id).subst(tcx, substs),
+                tcx.fn_sig(assoc.def_id).instantiate(tcx, args),
             ),
             assoc.ident(tcx),
-            tcx.predicates_of(assoc.def_id).instantiate_own(tcx, substs),
+            tcx.predicates_of(assoc.def_id).instantiate_own(tcx, args),
             assoc,
         ),
         ty::AssocKind::Type => {
             let (generics, where_clauses) = bounds_from_generic_predicates(
                 tcx,
-                tcx.predicates_of(assoc.def_id).instantiate_own(tcx, substs),
+                tcx.predicates_of(assoc.def_id).instantiate_own(tcx, args),
             );
             format!("type {}{generics} = /* Type */{where_clauses};", assoc.name)
         }
         ty::AssocKind::Const => {
-            let ty = tcx.type_of(assoc.def_id).subst_identity();
+            let ty = tcx.type_of(assoc.def_id).instantiate_identity();
             let val = ty_kind_suggestion(ty).unwrap_or("todo!()");
             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 d4748b7ef0b..443d072f992 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -18,7 +18,7 @@ use rustc_middle::ty::{
     self, AdtKind, GenericParamDefKind, ToPredicate, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable,
     TypeVisitable, TypeVisitableExt, TypeVisitor,
 };
-use rustc_middle::ty::{GenericArgKind, InternalSubsts};
+use rustc_middle::ty::{GenericArgKind, GenericArgs};
 use rustc_session::parse::feature_err;
 use rustc_span::symbol::{sym, Ident, Symbol};
 use rustc_span::{Span, DUMMY_SP};
@@ -290,7 +290,7 @@ fn check_trait_item(tcx: TyCtxt<'_>, trait_item: &hir::TraitItem<'_>) {
 
 /// Require that the user writes where clauses on GATs for the implicit
 /// outlives bounds involving trait parameters in trait functions and
-/// lifetimes passed as GAT substs. See `self-outlives-lint` test.
+/// lifetimes passed as GAT args. See `self-outlives-lint` test.
 ///
 /// We use the following trait as an example throughout this function:
 /// ```rust,ignore (this code fails due to this lint)
@@ -314,7 +314,7 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, associated_items: &[hir::TraitItemRe
         for gat_item in associated_items {
             let gat_def_id = gat_item.id.owner_id;
             let gat_item = tcx.associated_item(gat_def_id);
-            // If this item is not an assoc ty, or has no substs, then it's not a GAT
+            // If this item is not an assoc ty, or has no args, then it's not a GAT
             if gat_item.kind != ty::AssocKind::Type {
                 continue;
             }
@@ -345,7 +345,7 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, associated_items: &[hir::TraitItemRe
                         // `Self::Iter<'a>` is a GAT we want to gather any potential missing bounds from.
                         let sig: ty::FnSig<'_> = tcx.liberate_late_bound_regions(
                             item_def_id.to_def_id(),
-                            tcx.fn_sig(item_def_id).subst_identity(),
+                            tcx.fn_sig(item_def_id).instantiate_identity(),
                         );
                         gather_gat_bounds(
                             tcx,
@@ -374,7 +374,7 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, associated_items: &[hir::TraitItemRe
                             param_env,
                             item_def_id,
                             tcx.explicit_item_bounds(item_def_id)
-                                .subst_identity_iter_copied()
+                                .instantiate_identity_iter_copied()
                                 .collect::<Vec<_>>(),
                             &FxIndexSet::default(),
                             gat_def_id.def_id,
@@ -737,7 +737,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for GATSubstCollector<'tcx> {
     fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
         match t.kind() {
             ty::Alias(ty::Projection, p) if p.def_id == self.gat => {
-                for (idx, subst) in p.substs.iter().enumerate() {
+                for (idx, subst) in p.args.iter().enumerate() {
                     match subst.unpack() {
                         GenericArgKind::Lifetime(lt) if !lt.is_late_bound() => {
                             self.regions.insert((lt, idx));
@@ -836,7 +836,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).subst_identity();
+            let ty = tcx.type_of(param.def_id).instantiate_identity();
 
             if tcx.features().adt_const_params {
                 enter_wf_checking_ctxt(tcx, hir_ty.span, param.def_id, |wfcx| {
@@ -910,17 +910,17 @@ 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)).subst_identity(),
+            ty::ImplContainer => tcx.type_of(item.container_id(tcx)).instantiate_identity(),
         };
 
         match item.kind {
             ty::AssocKind::Const => {
-                let ty = tcx.type_of(item.def_id).subst_identity();
+                let ty = tcx.type_of(item.def_id).instantiate_identity();
                 let ty = wfcx.normalize(span, Some(WellFormedLoc::Ty(item_id)), ty);
                 wfcx.register_wf_obligation(span, loc, ty.into());
             }
             ty::AssocKind::Fn => {
-                let sig = tcx.fn_sig(item.def_id).subst_identity();
+                let sig = tcx.fn_sig(item.def_id).instantiate_identity();
                 let hir_sig = sig_if_method.expect("bad signature for method");
                 check_fn_or_method(
                     wfcx,
@@ -936,7 +936,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).subst_identity();
+                    let ty = tcx.type_of(item.def_id).instantiate_identity();
                     let ty = wfcx.normalize(span, Some(WellFormedLoc::Ty(item_id)), ty);
                     wfcx.register_wf_obligation(span, loc, ty.into());
                 }
@@ -969,7 +969,11 @@ 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).subst_identity());
+                let ty = wfcx.normalize(
+                    hir_ty.span,
+                    None,
+                    tcx.type_of(field.did).instantiate_identity(),
+                );
                 wfcx.register_wf_obligation(
                     hir_ty.span,
                     Some(WellFormedLoc::Ty(field_id)),
@@ -981,7 +985,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.tail().did).subst_identity();
+                    let ty = tcx.type_of(variant.tail().did).instantiate_identity();
                     let ty = tcx.erase_regions(ty);
                     if ty.has_infer() {
                         tcx.sess
@@ -1003,7 +1007,11 @@ 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).subst_identity());
+                let ty = wfcx.normalize(
+                    hir_ty.span,
+                    None,
+                    tcx.type_of(field.did).instantiate_identity(),
+                );
                 wfcx.register_bound(
                     traits::ObligationCause::new(
                         hir_ty.span,
@@ -1083,16 +1091,17 @@ fn check_associated_type_bounds(wfcx: &WfCheckingCtxt<'_, '_>, item: ty::AssocIt
     let bounds = wfcx.tcx().explicit_item_bounds(item.def_id);
 
     debug!("check_associated_type_bounds: bounds={:?}", bounds);
-    let wf_obligations = bounds.subst_identity_iter_copied().flat_map(|(bound, bound_span)| {
-        let normalized_bound = wfcx.normalize(span, None, bound);
-        traits::wf::predicate_obligations(
-            wfcx.infcx,
-            wfcx.param_env,
-            wfcx.body_def_id,
-            normalized_bound.as_predicate(),
-            bound_span,
-        )
-    });
+    let wf_obligations =
+        bounds.instantiate_identity_iter_copied().flat_map(|(bound, bound_span)| {
+            let normalized_bound = wfcx.normalize(span, None, bound);
+            traits::wf::predicate_obligations(
+                wfcx.infcx,
+                wfcx.param_env,
+                wfcx.body_def_id,
+                normalized_bound.as_predicate(),
+                bound_span,
+            )
+        });
 
     wfcx.register_obligations(wf_obligations);
 }
@@ -1105,7 +1114,7 @@ fn check_item_fn(
     decl: &hir::FnDecl<'_>,
 ) {
     enter_wf_checking_ctxt(tcx, span, def_id, |wfcx| {
-        let sig = tcx.fn_sig(def_id).subst_identity();
+        let sig = tcx.fn_sig(def_id).instantiate_identity();
         check_fn_or_method(wfcx, ident.span, sig, decl, def_id);
     })
 }
@@ -1125,7 +1134,7 @@ fn check_item_type(
     debug!("check_item_type: {:?}", item_id);
 
     enter_wf_checking_ctxt(tcx, ty_span, item_id, |wfcx| {
-        let ty = tcx.type_of(item_id).subst_identity();
+        let ty = tcx.type_of(item_id).instantiate_identity();
         let item_ty = wfcx.normalize(ty_span, Some(WellFormedLoc::Ty(item_id)), ty);
 
         let forbid_unsized = match unsized_handling {
@@ -1178,7 +1187,7 @@ fn check_impl<'tcx>(
                 // `#[rustc_reservation_impl]` impls are not real impls and
                 // therefore don't need to be WF (the trait's `Self: Trait` predicate
                 // won't hold).
-                let trait_ref = tcx.impl_trait_ref(item.owner_id).unwrap().subst_identity();
+                let trait_ref = tcx.impl_trait_ref(item.owner_id).unwrap().instantiate_identity();
                 let trait_ref = wfcx.normalize(
                     ast_trait_ref.path.span,
                     Some(WellFormedLoc::Ty(item.hir_id().expect_owner().def_id)),
@@ -1211,7 +1220,7 @@ fn check_impl<'tcx>(
                 wfcx.register_obligations(obligations);
             }
             None => {
-                let self_ty = tcx.type_of(item.owner_id).subst_identity();
+                let self_ty = tcx.type_of(item.owner_id).instantiate_identity();
                 let self_ty = wfcx.normalize(
                     item.span,
                     Some(WellFormedLoc::Ty(item.hir_id().expect_owner().def_id)),
@@ -1256,7 +1265,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).subst_identity();
+                    let ty = tcx.type_of(param.def_id).instantiate_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.
@@ -1272,10 +1281,10 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id
             GenericParamDefKind::Const { .. } => {
                 if is_our_default(param) {
                     // FIXME(const_generics_defaults): This
-                    // is incorrect when dealing with unused substs, for example
+                    // is incorrect when dealing with unused args, for example
                     // for `struct Foo<const N: usize, const M: usize = { 1 - 2 }>`
                     // we should eagerly error.
-                    let default_ct = tcx.const_param_default(param.def_id).subst_identity();
+                    let default_ct = tcx.const_param_default(param.def_id).instantiate_identity();
                     if !default_ct.has_param() {
                         wfcx.register_wf_obligation(
                             tcx.def_span(param.def_id),
@@ -1298,7 +1307,7 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id
     // For more examples see tests `defaults-well-formedness.rs` and `type-check-defaults.rs`.
     //
     // First we build the defaulted substitution.
-    let substs = InternalSubsts::for_item(tcx, def_id.to_def_id(), |param, _| {
+    let args = GenericArgs::for_item(tcx, def_id.to_def_id(), |param, _| {
         match param.kind {
             GenericParamDefKind::Lifetime => {
                 // All regions are identity.
@@ -1308,7 +1317,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).subst_identity();
+                    let default_ty = tcx.type_of(param.def_id).instantiate_identity();
                     // ... and it's not a dependent default, ...
                     if !default_ty.has_param() {
                         // ... then substitute it with the default.
@@ -1321,7 +1330,7 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id
             GenericParamDefKind::Const { .. } => {
                 // If the param has a default, ...
                 if is_our_default(param) {
-                    let default_ct = tcx.const_param_default(param.def_id).subst_identity();
+                    let default_ct = tcx.const_param_default(param.def_id).instantiate_identity();
                     // ... and it's not a dependent default, ...
                     if !default_ct.has_param() {
                         // ... then substitute it with the default.
@@ -1366,7 +1375,7 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id
             }
             let mut param_count = CountParams::default();
             let has_region = pred.visit_with(&mut param_count).is_break();
-            let substituted_pred = ty::EarlyBinder::bind(pred).subst(tcx, substs);
+            let substituted_pred = ty::EarlyBinder::bind(pred).instantiate(tcx, args);
             // Don't check non-defaulted params, dependent defaults (including lifetimes)
             // or preds with multiple params.
             if substituted_pred.has_non_region_param() || param_count.params.len() > 1 || has_region
@@ -1529,7 +1538,7 @@ fn check_return_position_impl_trait_in_trait_bounds<'tcx>(
 // strategy, we can't just call `check_associated_item` on the new RPITITs,
 // because tests like `tests/ui/async-await/in-trait/implied-bounds.rs` will fail.
 // That's because we need to check that the bounds of the RPITIT hold using
-// the special substs that we create during opaque type lowering, otherwise we're
+// the special args that we create during opaque type lowering, otherwise we're
 // getting a bunch of early bound and free regions mixed up... Haven't looked too
 // deep into this, though.
 struct ImplTraitInTraitFinder<'a, 'tcx> {
@@ -1558,7 +1567,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ImplTraitInTraitFinder<'_, 'tcx> {
             });
             for (bound, bound_span) in tcx
                 .explicit_item_bounds(opaque_ty.def_id)
-                .subst_iter_copied(tcx, opaque_ty.substs)
+                .arg_iter_copied(tcx, opaque_ty.args)
             {
                 let bound = self.wfcx.normalize(bound_span, None, bound);
                 self.wfcx.register_obligations(traits::wf::predicate_obligations(
@@ -1569,7 +1578,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ImplTraitInTraitFinder<'_, 'tcx> {
                     bound_span,
                 ));
                 // Set the debruijn index back to innermost here, since we already eagerly
-                // shifted the substs that we use to generate these bounds. This is unfortunately
+                // shifted the args that we use to generate these bounds. This is unfortunately
                 // subtly different behavior than the `ImplTraitInTraitFinder` we use in `param_env`,
                 // but that function doesn't actually need to normalize the bound it's visiting
                 // (whereas we have to do so here)...
@@ -1601,7 +1610,7 @@ fn check_method_receiver<'tcx>(
 
     let span = fn_sig.decl.inputs[0].span;
 
-    let sig = tcx.fn_sig(method.def_id).subst_identity();
+    let sig = tcx.fn_sig(method.def_id).instantiate_identity();
     let sig = tcx.liberate_late_bound_regions(method.def_id, sig);
     let sig = wfcx.normalize(span, None, sig);
 
@@ -1773,9 +1782,9 @@ fn check_variances_for_type_defn<'tcx>(
     item: &hir::Item<'tcx>,
     hir_generics: &hir::Generics<'_>,
 ) {
-    let identity_substs = ty::InternalSubsts::identity_for_item(tcx, item.owner_id);
+    let identity_args = ty::GenericArgs::identity_for_item(tcx, item.owner_id);
     for field in tcx.adt_def(item.owner_id).all_fields() {
-        if field.ty(tcx, identity_substs).references_error() {
+        if field.ty(tcx, identity_args).references_error() {
             return;
         }
     }
diff --git a/compiler/rustc_hir_analysis/src/check_unused.rs b/compiler/rustc_hir_analysis/src/check_unused.rs
index 268b9ac530f..5318e637fc7 100644
--- a/compiler/rustc_hir_analysis/src/check_unused.rs
+++ b/compiler/rustc_hir_analysis/src/check_unused.rs
@@ -1,4 +1,4 @@
-use rustc_data_structures::unord::UnordSet;
+use rustc_data_structures::unord::{ExtendUnord, UnordSet};
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::LocalDefId;
 use rustc_middle::ty::TyCtxt;
@@ -7,6 +7,10 @@ use rustc_session::lint;
 pub fn check_crate(tcx: TyCtxt<'_>) {
     let mut used_trait_imports: UnordSet<LocalDefId> = Default::default();
 
+    // FIXME: Use `tcx.hir().par_body_owners()` when we implement creating `DefId`s
+    // for anon constants during their parents' typeck.
+    // Doing so at current will produce queries cycle errors because it may typeck
+    // on anon constants directly.
     for item_def_id in tcx.hir().body_owners() {
         let imports = tcx.used_trait_imports(item_def_id);
         debug!("GatherVisitor: item_def_id={:?} with imports {:#?}", item_def_id, imports);
diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs
index 79cc43edff1..3f65adcd36e 100644
--- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs
@@ -57,7 +57,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).subst_identity().kind() {
+    match tcx.type_of(impl_did).instantiate_identity().kind() {
         ty::Adt(def, _) if def.did().is_local() => return,
         ty::Error(_) => return,
         _ => {}
@@ -71,7 +71,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).subst_identity();
+    let self_type = tcx.type_of(impl_did).instantiate_identity();
     debug!("visit_implementation_of_copy: self_type={:?} (bound)", self_type);
 
     let param_env = tcx.param_env(impl_did);
@@ -100,7 +100,7 @@ fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
 }
 
 fn visit_implementation_of_const_param_ty(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
-    let self_type = tcx.type_of(impl_did).subst_identity();
+    let self_type = tcx.type_of(impl_did).instantiate_identity();
     assert!(!self_type.has_escaping_bound_vars());
 
     let param_env = tcx.param_env(impl_did);
@@ -139,13 +139,13 @@ 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).subst_identity();
+    let source = tcx.type_of(impl_did).instantiate_identity();
     assert!(!source.has_escaping_bound_vars());
     let target = {
-        let trait_ref = tcx.impl_trait_ref(impl_did).unwrap().subst_identity();
+        let trait_ref = tcx.impl_trait_ref(impl_did).unwrap().instantiate_identity();
         assert_eq!(trait_ref.def_id, dispatch_from_dyn_trait);
 
-        trait_ref.substs.type_at(1)
+        trait_ref.args.type_at(1)
     };
 
     debug!("visit_implementation_of_dispatch_from_dyn: {:?} -> {:?}", source, target);
@@ -163,9 +163,7 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef
             if infcx.at(&cause, param_env).eq(DefineOpaqueTypes::No, r_a, *r_b).is_ok()
                 && mutbl_a == *mutbl_b => {}
         (&RawPtr(tm_a), &RawPtr(tm_b)) if tm_a.mutbl == tm_b.mutbl => (),
-        (&Adt(def_a, substs_a), &Adt(def_b, substs_b))
-            if def_a.is_struct() && def_b.is_struct() =>
-        {
+        (&Adt(def_a, args_a), &Adt(def_b, args_b)) if def_a.is_struct() && def_b.is_struct() => {
             if def_a != def_b {
                 let source_path = tcx.def_path_str(def_a.did());
                 let target_path = tcx.def_path_str(def_b.did());
@@ -194,8 +192,8 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef
             let coerced_fields = fields
                 .iter()
                 .filter(|field| {
-                    let ty_a = field.ty(tcx, substs_a);
-                    let ty_b = field.ty(tcx, substs_b);
+                    let ty_a = field.ty(tcx, args_a);
+                    let ty_b = field.ty(tcx, args_b);
 
                     if let Ok(layout) = tcx.layout_of(param_env.and(ty_a)) {
                         if layout.is_zst() && layout.align.abi.bytes() == 1 {
@@ -250,8 +248,8 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef
                                 format!(
                                     "`{}` (`{}` to `{}`)",
                                     field.name,
-                                    field.ty(tcx, substs_a),
-                                    field.ty(tcx, substs_b),
+                                    field.ty(tcx, args_a),
+                                    field.ty(tcx, args_b),
                                 )
                             })
                             .collect::<Vec<_>>()
@@ -268,7 +266,7 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef
                         ty::TraitRef::new(
                             tcx,
                             dispatch_from_dyn_trait,
-                            [field.ty(tcx, substs_a), field.ty(tcx, substs_b)],
+                            [field.ty(tcx, args_a), field.ty(tcx, args_b)],
                         ),
                     ));
                 }
@@ -300,10 +298,10 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: LocalDefId) -> Coe
 
     let unsize_trait = tcx.require_lang_item(LangItem::Unsize, Some(span));
 
-    let source = tcx.type_of(impl_did).subst_identity();
-    let trait_ref = tcx.impl_trait_ref(impl_did).unwrap().subst_identity();
+    let source = tcx.type_of(impl_did).instantiate_identity();
+    let trait_ref = tcx.impl_trait_ref(impl_did).unwrap().instantiate_identity();
     assert_eq!(trait_ref.def_id, coerce_unsized_trait);
-    let target = trait_ref.substs.type_at(1);
+    let target = trait_ref.args.type_at(1);
     debug!("visit_implementation_of_coerce_unsized: {:?} -> {:?} (bound)", source, target);
 
     let param_env = tcx.param_env(impl_did);
@@ -348,7 +346,7 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: LocalDefId) -> Coe
             check_mutbl(mt_a, mt_b, &|ty| Ty::new_imm_ptr(tcx, ty))
         }
 
-        (&ty::Adt(def_a, substs_a), &ty::Adt(def_b, substs_b))
+        (&ty::Adt(def_a, args_a), &ty::Adt(def_b, args_b))
             if def_a.is_struct() && def_b.is_struct() =>
         {
             if def_a != def_b {
@@ -411,9 +409,9 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: LocalDefId) -> Coe
             let diff_fields = fields
                 .iter_enumerated()
                 .filter_map(|(i, f)| {
-                    let (a, b) = (f.ty(tcx, substs_a), f.ty(tcx, substs_b));
+                    let (a, b) = (f.ty(tcx, args_a), f.ty(tcx, args_b));
 
-                    if tcx.type_of(f.did).subst_identity().is_phantom_data() {
+                    if tcx.type_of(f.did).instantiate_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 33559020692..f5326e50614 100644
--- a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs
@@ -171,7 +171,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).subst_identity();
+        let self_ty = self.tcx.type_of(id).instantiate_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/mod.rs b/compiler/rustc_hir_analysis/src/coherence/mod.rs
index 5097f43607e..fc8fab0eabc 100644
--- a/compiler/rustc_hir_analysis/src/coherence/mod.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/mod.rs
@@ -122,7 +122,7 @@ fn coherent_trait(tcx: TyCtxt<'_>, def_id: DefId) {
 
     let impls = tcx.hir().trait_impls(def_id);
     for &impl_def_id in impls {
-        let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap().subst_identity();
+        let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap().instantiate_identity();
 
         check_impl(tcx, impl_def_id, trait_ref);
         check_object_overlap(tcx, impl_def_id, trait_ref);
diff --git a/compiler/rustc_hir_analysis/src/coherence/orphan.rs b/compiler/rustc_hir_analysis/src/coherence/orphan.rs
index 025bab14021..05c78f57088 100644
--- a/compiler/rustc_hir_analysis/src/coherence/orphan.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/orphan.rs
@@ -5,8 +5,8 @@ use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::{struct_span_err, DelayDm};
 use rustc_errors::{Diagnostic, ErrorGuaranteed};
 use rustc_hir as hir;
-use rustc_middle::ty::subst::InternalSubsts;
 use rustc_middle::ty::util::CheckRegions;
+use rustc_middle::ty::GenericArgs;
 use rustc_middle::ty::{
     self, AliasKind, ImplPolarity, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
     TypeVisitor,
@@ -22,7 +22,7 @@ pub(crate) fn orphan_check_impl(
     tcx: TyCtxt<'_>,
     impl_def_id: LocalDefId,
 ) -> Result<(), ErrorGuaranteed> {
-    let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap().subst_identity();
+    let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap().instantiate_identity();
     trait_ref.error_reported()?;
 
     let ret = do_orphan_check_impl(tcx, trait_ref, impl_def_id);
@@ -488,10 +488,10 @@ fn lint_auto_trait_impl<'tcx>(
     trait_ref: ty::TraitRef<'tcx>,
     impl_def_id: LocalDefId,
 ) {
-    assert_eq!(trait_ref.substs.len(), 1);
+    assert_eq!(trait_ref.args.len(), 1);
     let self_ty = trait_ref.self_ty();
-    let (self_type_did, substs) = match self_ty.kind() {
-        ty::Adt(def, substs) => (def.did(), substs),
+    let (self_type_did, args) = match self_ty.kind() {
+        ty::Adt(def, args) => (def.did(), args),
         _ => {
             // FIXME: should also lint for stuff like `&i32` but
             // considering that auto traits are unstable, that
@@ -502,9 +502,9 @@ fn lint_auto_trait_impl<'tcx>(
     };
 
     // Impls which completely cover a given root type are fine as they
-    // disable auto impls entirely. So only lint if the substs
-    // are not a permutation of the identity substs.
-    let Err(arg) = tcx.uses_unique_generic_params(substs, CheckRegions::No) else {
+    // disable auto impls entirely. So only lint if the args
+    // are not a permutation of the identity args.
+    let Err(arg) = tcx.uses_unique_generic_params(args, CheckRegions::No) else {
         // ok
         return;
     };
@@ -585,14 +585,14 @@ fn fast_reject_auto_impl<'tcx>(tcx: TyCtxt<'tcx>, trait_def_id: DefId, self_ty:
             }
 
             match t.kind() {
-                ty::Adt(def, substs) if def.is_phantom_data() => substs.visit_with(self),
-                ty::Adt(def, substs) => {
+                ty::Adt(def, args) if def.is_phantom_data() => args.visit_with(self),
+                ty::Adt(def, args) => {
                     // @lcnr: This is the only place where cycles can happen. We avoid this
                     // by only visiting each `DefId` once.
                     //
                     // This will be is incorrect in subtle cases, but I don't care :)
                     if self.seen.insert(def.did()) {
-                        for ty in def.all_fields().map(|field| field.ty(tcx, substs)) {
+                        for ty in def.all_fields().map(|field| field.ty(tcx, args)) {
                             ty.visit_with(self)?;
                         }
                     }
@@ -605,9 +605,7 @@ fn fast_reject_auto_impl<'tcx>(tcx: TyCtxt<'tcx>, trait_def_id: DefId, self_ty:
     }
 
     let self_ty_root = match self_ty.kind() {
-        ty::Adt(def, _) => {
-            Ty::new_adt(tcx, *def, InternalSubsts::identity_for_item(tcx, def.did()))
-        }
+        ty::Adt(def, _) => Ty::new_adt(tcx, *def, GenericArgs::identity_for_item(tcx, def.did())),
         _ => unimplemented!("unexpected self ty {:?}", self_ty),
     };
 
diff --git a/compiler/rustc_hir_analysis/src/coherence/unsafety.rs b/compiler/rustc_hir_analysis/src/coherence/unsafety.rs
index c6b16171311..6b18b0ebe9d 100644
--- a/compiler/rustc_hir_analysis/src/coherence/unsafety.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/unsafety.rs
@@ -12,7 +12,7 @@ pub(super) fn check_item(tcx: TyCtxt<'_>, def_id: LocalDefId) {
     let impl_ = item.expect_impl();
 
     if let Some(trait_ref) = tcx.impl_trait_ref(item.owner_id) {
-        let trait_ref = trait_ref.subst_identity();
+        let trait_ref = trait_ref.instantiate_identity();
         let trait_def = tcx.trait_def(trait_ref.def_id);
         let unsafe_attr =
             impl_.generics.params.iter().find(|p| p.pure_wrt_drop).map(|_| "may_dangle");
diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs
index f47df4f215b..c160cf2df6e 100644
--- a/compiler/rustc_hir_analysis/src/collect.rs
+++ b/compiler/rustc_hir_analysis/src/collect.rs
@@ -401,13 +401,13 @@ impl<'tcx> AstConv<'tcx> for ItemCtxt<'tcx> {
         poly_trait_ref: ty::PolyTraitRef<'tcx>,
     ) -> Ty<'tcx> {
         if let Some(trait_ref) = poly_trait_ref.no_bound_vars() {
-            let item_substs = self.astconv().create_substs_for_associated_item(
+            let item_args = self.astconv().create_args_for_associated_item(
                 span,
                 item_def_id,
                 item_segment,
-                trait_ref.substs,
+                trait_ref.args,
             );
-            Ty::new_projection(self.tcx(), item_def_id, item_substs)
+            Ty::new_projection(self.tcx(), item_def_id, item_args)
         } else {
             // There are no late-bound regions; we can just ignore the binder.
             let (mut mpart_sugg, mut inferred_sugg) = (None, None);
@@ -1145,8 +1145,8 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: LocalDefId) -> 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)).subst_identity();
-            let inputs = data.fields().iter().map(|f| tcx.type_of(f.def_id).subst_identity());
+            let ty = tcx.type_of(tcx.hir().get_parent_item(hir_id)).instantiate_identity();
+            let inputs = data.fields().iter().map(|f| tcx.type_of(f.def_id).instantiate_identity());
             ty::Binder::dummy(tcx.mk_fn_sig(
                 inputs,
                 ty,
@@ -1161,15 +1161,13 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<ty::PolyFnSig<
             // signatures and cannot be accessed through `fn_sig`. For
             // example, a closure signature excludes the `self`
             // argument. In any case they are embedded within the
-            // closure type as part of the `ClosureSubsts`.
+            // closure type as part of the `ClosureArgs`.
             //
             // To get the signature of a closure, you should use the
-            // `sig` method on the `ClosureSubsts`:
+            // `sig` method on the `ClosureArgs`:
             //
-            //    substs.as_closure().sig(def_id, tcx)
-            bug!(
-                "to get the signature of a closure, use `substs.as_closure().sig()` not `fn_sig()`",
-            );
+            //    args.as_closure().sig(def_id, tcx)
+            bug!("to get the signature of a closure, use `args.as_closure().sig()` not `fn_sig()`",);
         }
 
         x => {
@@ -1266,7 +1264,7 @@ fn suggest_impl_trait<'tcx>(
 ) -> Option<String> {
     let format_as_assoc: fn(_, _, _, _, _) -> _ =
         |tcx: TyCtxt<'tcx>,
-         _: ty::SubstsRef<'tcx>,
+         _: ty::GenericArgsRef<'tcx>,
          trait_def_id: DefId,
          assoc_item_def_id: DefId,
          item_ty: Ty<'tcx>| {
@@ -1276,13 +1274,15 @@ fn suggest_impl_trait<'tcx>(
         };
     let format_as_parenthesized: fn(_, _, _, _, _) -> _ =
         |tcx: TyCtxt<'tcx>,
-         substs: ty::SubstsRef<'tcx>,
+         args: ty::GenericArgsRef<'tcx>,
          trait_def_id: DefId,
          _: DefId,
          item_ty: Ty<'tcx>| {
             let trait_name = tcx.item_name(trait_def_id);
-            let args_tuple = substs.type_at(1);
-            let ty::Tuple(types) = *args_tuple.kind() else { return None; };
+            let args_tuple = args.type_at(1);
+            let ty::Tuple(types) = *args_tuple.kind() else {
+                return None;
+            };
             let types = types.make_suggestable(tcx, false)?;
             let maybe_ret =
                 if item_ty.is_unit() { String::new() } else { format!(" -> {item_ty}") };
@@ -1315,31 +1315,34 @@ fn suggest_impl_trait<'tcx>(
             format_as_parenthesized,
         ),
     ] {
-        let Some(trait_def_id) = trait_def_id else { continue; };
-        let Some(assoc_item_def_id) = assoc_item_def_id else { continue; };
+        let Some(trait_def_id) = trait_def_id else {
+            continue;
+        };
+        let Some(assoc_item_def_id) = assoc_item_def_id else {
+            continue;
+        };
         if tcx.def_kind(assoc_item_def_id) != DefKind::AssocTy {
             continue;
         }
         let param_env = tcx.param_env(def_id);
         let infcx = tcx.infer_ctxt().build();
-        let substs = ty::InternalSubsts::for_item(tcx, trait_def_id, |param, _| {
+        let args = ty::GenericArgs::for_item(tcx, trait_def_id, |param, _| {
             if param.index == 0 { ret_ty.into() } else { infcx.var_for_def(span, param) }
         });
-        if !infcx.type_implements_trait(trait_def_id, substs, param_env).must_apply_modulo_regions()
-        {
+        if !infcx.type_implements_trait(trait_def_id, args, param_env).must_apply_modulo_regions() {
             continue;
         }
         let ocx = ObligationCtxt::new(&infcx);
         let item_ty = ocx.normalize(
             &ObligationCause::misc(span, def_id),
             param_env,
-            Ty::new_projection(tcx, assoc_item_def_id, substs),
+            Ty::new_projection(tcx, assoc_item_def_id, args),
         );
         // FIXME(compiler-errors): We may benefit from resolving regions here.
         if ocx.select_where_possible().is_empty()
             && let item_ty = infcx.resolve_vars_if_possible(item_ty)
             && let Some(item_ty) = item_ty.make_suggestable(tcx, false)
-            && let Some(sugg) = formatter(tcx, infcx.resolve_vars_if_possible(substs), trait_def_id, assoc_item_def_id, item_ty)
+            && let Some(sugg) = formatter(tcx, infcx.resolve_vars_if_possible(args), trait_def_id, assoc_item_def_id, item_ty)
         {
             return Some(sugg);
         }
@@ -1357,7 +1360,7 @@ fn impl_trait_ref(
         .of_trait
         .as_ref()
         .map(|ast_trait_ref| {
-            let selfty = tcx.type_of(def_id).subst_identity();
+            let selfty = tcx.type_of(def_id).instantiate_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 ccc9f808411..edcb9527fe2 100644
--- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs
@@ -68,17 +68,17 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
                     //        ^ parent_def_id
                     //
                     // then we only want to return generics for params to the left of `N`. If we don't do that we
-                    // end up with that const looking like: `ty::ConstKind::Unevaluated(def_id, substs: [N#0])`.
+                    // end up with that const looking like: `ty::ConstKind::Unevaluated(def_id, args: [N#0])`.
                     //
-                    // This causes ICEs (#86580) when building the substs for Foo in `fn foo() -> Foo { .. }` as
-                    // we substitute the defaults with the partially built substs when we build the substs. Subst'ing
-                    // the `N#0` on the unevaluated const indexes into the empty substs we're in the process of building.
+                    // This causes ICEs (#86580) when building the args for Foo in `fn foo() -> Foo { .. }` as
+                    // we substitute the defaults with the partially built args when we build the args. Subst'ing
+                    // the `N#0` on the unevaluated const indexes into the empty args we're in the process of building.
                     //
                     // We fix this by having this function return the parent's generics ourselves and truncating the
                     // generics to only include non-forward declared params (with the exception of the `Self` ty)
                     //
-                    // For the above code example that means we want `substs: []`
-                    // For the following struct def we want `substs: [N#0]` when generics_of is called on
+                    // For the above code example that means we want `args: []`
+                    // For the following struct def we want `args: [N#0]` when generics_of is called on
                     // the def id of the `{ N + 1 }` anon const
                     // struct Foo<const N: usize, const M: usize = { N + 1 }>;
                     //
@@ -93,7 +93,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
 
                     return ty::Generics {
                         // we set the parent of these generics to be our parent's parent so that we
-                        // dont end up with substs: [N, M, N] for the const default on a struct like this:
+                        // dont end up with args: [N, M, N] for the const default on a struct like this:
                         // struct Foo<const N: usize, const M: usize = { ... }>;
                         parent: generics.parent,
                         parent_count: generics.parent_count,
diff --git a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
index d6f33869a03..758e9dc7230 100644
--- a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
+++ b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
@@ -2,7 +2,7 @@ use super::ItemCtxt;
 use crate::astconv::{AstConv, PredicateFilter};
 use rustc_hir as hir;
 use rustc_infer::traits::util;
-use rustc_middle::ty::subst::InternalSubsts;
+use rustc_middle::ty::GenericArgs;
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_span::def_id::{DefId, LocalDefId};
 use rustc_span::Span;
@@ -10,7 +10,7 @@ use rustc_span::Span;
 /// For associated types we include both bounds written on the type
 /// (`type X: Trait`) and predicates from the trait: `where Self::X: Trait`.
 ///
-/// Note that this filtering is done with the items identity substs to
+/// Note that this filtering is done with the items identity args to
 /// simplify checking that these bounds are met in impls. This means that
 /// a bound such as `for<'b> <Self as X<'b>>::U: Clone` can't be used, as in
 /// `hr-associated-type-bound-1.rs`.
@@ -23,7 +23,7 @@ fn associated_type_bounds<'tcx>(
     let item_ty = Ty::new_projection(
         tcx,
         assoc_item_def_id.to_def_id(),
-        InternalSubsts::identity_for_item(tcx, assoc_item_def_id),
+        GenericArgs::identity_for_item(tcx, assoc_item_def_id),
     );
 
     let icx = ItemCtxt::new(tcx, assoc_item_def_id);
@@ -95,7 +95,7 @@ pub(super) fn explicit_item_bounds(
                 Ty::new_projection(
                     tcx,
                     def_id.to_def_id(),
-                    ty::InternalSubsts::identity_for_item(tcx, def_id),
+                    ty::GenericArgs::identity_for_item(tcx, def_id),
                 ),
                 item.span,
             ));
@@ -117,8 +117,8 @@ pub(super) fn explicit_item_bounds(
             span,
             ..
         }) => {
-            let substs = InternalSubsts::identity_for_item(tcx, def_id);
-            let item_ty = Ty::new_opaque(tcx, def_id.to_def_id(), substs);
+            let args = GenericArgs::identity_for_item(tcx, def_id);
+            let item_ty = Ty::new_opaque(tcx, def_id.to_def_id(), args);
             opaque_type_bounds(tcx, def_id, bounds, item_ty, *span)
         }
         hir::Node::Item(hir::Item { kind: hir::ItemKind::TyAlias(..), .. }) => &[],
diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
index 12936664130..1c9070600db 100644
--- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
@@ -8,7 +8,6 @@ use rustc_hir as hir;
 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::{self, Ty, TyCtxt};
 use rustc_middle::ty::{GenericPredicates, Generics, ImplTraitInTraitData, ToPredicate};
 use rustc_span::symbol::{sym, Ident};
@@ -66,7 +65,11 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
         Some(ImplTraitInTraitData::Trait { opaque_def_id, fn_def_id }) => {
             let opaque_ty_id = tcx.hir().local_def_id_to_hir_id(opaque_def_id.expect_local());
             let opaque_ty_node = tcx.hir().get(opaque_ty_id);
-            let Node::Item(&Item { kind: ItemKind::OpaqueTy(OpaqueTy { lifetime_mapping, .. }), .. }) = opaque_ty_node else {
+            let Node::Item(&Item {
+                kind: ItemKind::OpaqueTy(OpaqueTy { lifetime_mapping, .. }),
+                ..
+            }) = opaque_ty_node
+            else {
                 bug!("unexpected {opaque_ty_node:?}")
             };
 
@@ -76,10 +79,9 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
             // both to ensure that the RPITITs are only instantiated when the
             // parent predicates would hold, and also so that the param-env
             // inherits these predicates as assumptions.
-            let identity_substs = InternalSubsts::identity_for_item(tcx, def_id);
-            predicates.extend(
-                tcx.explicit_predicates_of(fn_def_id).instantiate_own(tcx, identity_substs),
-            );
+            let identity_args = ty::GenericArgs::identity_for_item(tcx, def_id);
+            predicates
+                .extend(tcx.explicit_predicates_of(fn_def_id).instantiate_own(tcx, identity_args));
 
             // We also install bidirectional outlives predicates for the RPITIT
             // to keep the duplicates lifetimes from opaque lowering in sync.
@@ -104,15 +106,15 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
             let trait_assoc_predicates =
                 tcx.explicit_predicates_of(assoc_item.trait_item_def_id.unwrap());
 
-            let impl_assoc_identity_substs = InternalSubsts::identity_for_item(tcx, def_id);
+            let impl_assoc_identity_args = ty::GenericArgs::identity_for_item(tcx, def_id);
             let impl_def_id = tcx.parent(fn_def_id);
-            let impl_trait_ref_substs =
-                tcx.impl_trait_ref(impl_def_id).unwrap().subst_identity().substs;
+            let impl_trait_ref_args =
+                tcx.impl_trait_ref(impl_def_id).unwrap().instantiate_identity().args;
 
-            let impl_assoc_substs =
-                impl_assoc_identity_substs.rebase_onto(tcx, impl_def_id, impl_trait_ref_substs);
+            let impl_assoc_args =
+                impl_assoc_identity_args.rebase_onto(tcx, impl_def_id, impl_trait_ref_args);
 
-            let impl_predicates = trait_assoc_predicates.instantiate_own(tcx, impl_assoc_substs);
+            let impl_predicates = trait_assoc_predicates.instantiate_own(tcx, impl_assoc_args);
 
             return ty::GenericPredicates {
                 parent: Some(impl_def_id),
@@ -146,8 +148,9 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
         Node::Item(item) => match item.kind {
             ItemKind::Impl(impl_) => {
                 if impl_.defaultness.is_default() {
-                    is_default_impl_trait =
-                        tcx.impl_trait_ref(def_id).map(|t| ty::Binder::dummy(t.subst_identity()));
+                    is_default_impl_trait = tcx
+                        .impl_trait_ref(def_id)
+                        .map(|t| ty::Binder::dummy(t.instantiate_identity()));
                 }
                 impl_.generics
             }
@@ -333,8 +336,8 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
     // 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).subst_identity();
-        let trait_ref = tcx.impl_trait_ref(def_id).map(ty::EarlyBinder::subst_identity);
+        let self_ty = tcx.type_of(def_id).instantiate_identity();
+        let trait_ref = tcx.impl_trait_ref(def_id).map(ty::EarlyBinder::instantiate_identity);
         cgp::setup_constraining_predicates(
             tcx,
             &mut predicates,
@@ -393,11 +396,13 @@ fn compute_bidirectional_outlives_predicates<'tcx>(
         let orig_region = icx.astconv().ast_region_to_region(&arg, None);
         if !matches!(orig_region.kind(), ty::ReEarlyBound(..)) {
             // There is no late-bound lifetime to actually match up here, since the lifetime doesn't
-            // show up in the opaque's parent's substs.
+            // show up in the opaque's parent's args.
             continue;
         }
 
-        let Some(dup_index) = generics.param_def_id_to_index(icx.tcx, dup_def.to_def_id()) else { bug!() };
+        let Some(dup_index) = generics.param_def_id_to_index(icx.tcx, dup_def.to_def_id()) else {
+            bug!()
+        };
 
         let dup_region = ty::Region::new_early_bound(
             tcx,
@@ -493,20 +498,20 @@ pub(super) fn explicit_predicates_of<'tcx>(
         // Remove bounds on associated types from the predicates, they will be
         // returned by `explicit_item_bounds`.
         let predicates_and_bounds = tcx.trait_explicit_predicates_and_bounds(def_id);
-        let trait_identity_substs = InternalSubsts::identity_for_item(tcx, def_id);
+        let trait_identity_args = ty::GenericArgs::identity_for_item(tcx, def_id);
 
         let is_assoc_item_ty = |ty: Ty<'tcx>| {
             // For a predicate from a where clause to become a bound on an
             // associated type:
-            // * It must use the identity substs of the item.
+            // * It must use the identity args of the item.
             //   * We're in the scope of the trait, so we can't name any
             //     parameters of the GAT. That means that all we need to
-            //     check are that the substs of the projection are the
-            //     identity substs of the trait.
+            //     check are that the args of the projection are the
+            //     identity args of the trait.
             // * It must be an associated type for this trait (*not* a
             //   supertrait).
             if let ty::Alias(ty::Projection, projection) = ty.kind() {
-                projection.substs == trait_identity_substs
+                projection.args == trait_identity_args
                     // FIXME(return_type_notation): This check should be more robust
                     && !tcx.is_impl_trait_in_trait(projection.def_id)
                     && tcx.associated_item(projection.def_id).container_id(tcx)
diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
index acd0bcd8e5c..44f116ef2da 100644
--- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
+++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
@@ -749,9 +749,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
                 // `fn foo<'a>() -> MyAnonTy<'a> { ... }`
                 //          ^                 ^this gets resolved in the current scope
                 for lifetime in lifetimes {
-                    let hir::GenericArg::Lifetime(lifetime) = lifetime else {
-                        continue
-                    };
+                    let hir::GenericArg::Lifetime(lifetime) = lifetime else { continue };
                     self.visit_lifetime(lifetime);
 
                     // Check for predicates like `impl for<'a> Trait<impl OtherTrait<'a>>`
@@ -759,12 +757,8 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'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(ResolvedArg::LateBound(_, _, def_id)) = def else {
-                        continue
-                    };
-                    let Some(def_id) = def_id.as_local() else {
-                        continue
-                    };
+                    let Some(ResolvedArg::LateBound(_, _, def_id)) = def else { continue };
+                    let Some(def_id) = def_id.as_local() else { continue };
                     let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id);
                     // Ensure that the parent of the def is an item, not HRTB
                     let parent_id = self.tcx.hir().parent_id(hir_id);
@@ -1727,7 +1721,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
                         },
                     ));
                     bound_vars
-                        .extend(self.tcx.fn_sig(assoc_fn.def_id).subst_identity().bound_vars());
+                        .extend(self.tcx.fn_sig(assoc_fn.def_id).instantiate_identity().bound_vars());
                     bound_vars
                 } else {
                     self.tcx.sess.delay_span_bug(
@@ -2044,12 +2038,12 @@ fn is_late_bound_map(
                     hir::Path { res: Res::Def(DefKind::TyAlias, alias_def), segments, span },
                 )) => {
                     // See comments on `ConstrainedCollectorPostAstConv` for why this arm does not just consider
-                    // substs to be unconstrained.
+                    // args to be unconstrained.
                     let generics = self.tcx.generics_of(alias_def);
                     let mut walker = ConstrainedCollectorPostAstConv {
                         arg_is_constrained: vec![false; generics.params.len()].into_boxed_slice(),
                     };
-                    walker.visit_ty(self.tcx.type_of(alias_def).subst_identity());
+                    walker.visit_ty(self.tcx.type_of(alias_def).instantiate_identity());
 
                     match segments.last() {
                         Some(hir::PathSegment { args: Some(args), .. }) => {
diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs
index 3755342aef5..c39edaa1577 100644
--- a/compiler/rustc_hir_analysis/src/collect/type_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs
@@ -3,7 +3,6 @@ use rustc_hir as hir;
 use rustc_hir::def_id::LocalDefId;
 use rustc_hir::HirId;
 use rustc_middle::ty::print::with_forced_trimmed_paths;
-use rustc_middle::ty::subst::InternalSubsts;
 use rustc_middle::ty::util::IntTypeExt;
 use rustc_middle::ty::{self, ImplTraitInTraitData, IsSuggestable, Ty, TyCtxt, TypeVisitableExt};
 use rustc_span::symbol::Ident;
@@ -338,8 +337,8 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Ty
     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);
-                Ty::new_fn_def(tcx, def_id.to_def_id(), substs)
+                let args = ty::GenericArgs::identity_for_item(tcx, def_id);
+                Ty::new_fn_def(tcx, def_id.to_def_id(), args)
             }
             TraitItemKind::Const(ty, body_id) => body_id
                 .and_then(|body_id| {
@@ -363,8 +362,8 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Ty
 
         Node::ImplItem(item) => match item.kind {
             ImplItemKind::Fn(..) => {
-                let substs = InternalSubsts::identity_for_item(tcx, def_id);
-                Ty::new_fn_def(tcx, def_id.to_def_id(), substs)
+                let args = ty::GenericArgs::identity_for_item(tcx, def_id);
+                Ty::new_fn_def(tcx, def_id.to_def_id(), args)
             }
             ImplItemKind::Const(ty, body_id) => {
                 if is_suggestable_infer_ty(ty) {
@@ -426,13 +425,13 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Ty
                     _ => icx.to_ty(*self_ty),
                 },
                 ItemKind::Fn(..) => {
-                    let substs = InternalSubsts::identity_for_item(tcx, def_id);
-                    Ty::new_fn_def(tcx, def_id.to_def_id(), substs)
+                    let args = ty::GenericArgs::identity_for_item(tcx, def_id);
+                    Ty::new_fn_def(tcx, def_id.to_def_id(), args)
                 }
                 ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Union(..) => {
                     let def = tcx.adt_def(def_id);
-                    let substs = InternalSubsts::identity_for_item(tcx, def_id);
-                    Ty::new_adt(tcx, def, substs)
+                    let args = ty::GenericArgs::identity_for_item(tcx, def_id);
+                    Ty::new_adt(tcx, def, args)
                 }
                 ItemKind::OpaqueTy(OpaqueTy {
                     origin: hir::OpaqueTyOrigin::TyAlias { .. },
@@ -472,8 +471,8 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Ty
 
         Node::ForeignItem(foreign_item) => match foreign_item.kind {
             ForeignItemKind::Fn(..) => {
-                let substs = InternalSubsts::identity_for_item(tcx, def_id);
-                Ty::new_fn_def(tcx, def_id.to_def_id(), substs)
+                let args = ty::GenericArgs::identity_for_item(tcx, def_id);
+                Ty::new_fn_def(tcx, def_id.to_def_id(), args)
             }
             ForeignItemKind::Static(t, _) => icx.to_ty(t),
             ForeignItemKind::Type => Ty::new_foreign(tcx, def_id.to_def_id()),
@@ -481,11 +480,11 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<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)).subst_identity()
+                tcx.type_of(tcx.hir().get_parent_item(hir_id)).instantiate_identity()
             }
             VariantData::Tuple(..) => {
-                let substs = InternalSubsts::identity_for_item(tcx, def_id);
-                Ty::new_fn_def(tcx, def_id.to_def_id(), substs)
+                let args = ty::GenericArgs::identity_for_item(tcx, def_id);
+                Ty::new_fn_def(tcx, def_id.to_def_id(), args)
             }
         },
 
@@ -498,8 +497,8 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Ty
         Node::AnonConst(_) => anon_const_type_of(tcx, def_id),
 
         Node::ConstBlock(_) => {
-            let substs = InternalSubsts::identity_for_item(tcx, def_id.to_def_id());
-            substs.as_inline_const().ty()
+            let args = ty::GenericArgs::identity_for_item(tcx, def_id.to_def_id());
+            args.as_inline_const().ty()
         }
 
         Node::GenericParam(param) => match &param.kind {
diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check.rs b/compiler/rustc_hir_analysis/src/impl_wf_check.rs
index d654b0be620..62f22bda9f9 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).subst_identity();
+    let impl_self_ty = tcx.type_of(impl_def_id).instantiate_identity();
     if impl_self_ty.references_error() {
         // Don't complain about unconstrained type params when self ty isn't known due to errors.
         // (#36836)
@@ -85,7 +85,7 @@ fn enforce_impl_params_are_constrained(tcx: TyCtxt<'_>, impl_def_id: LocalDefId)
     }
     let impl_generics = tcx.generics_of(impl_def_id);
     let impl_predicates = tcx.predicates_of(impl_def_id);
-    let impl_trait_ref = tcx.impl_trait_ref(impl_def_id).map(ty::EarlyBinder::subst_identity);
+    let impl_trait_ref = tcx.impl_trait_ref(impl_def_id).map(ty::EarlyBinder::instantiate_identity);
 
     let mut input_parameters = cgp::parameters_for_impl(impl_self_ty, impl_trait_ref);
     cgp::identify_constrained_generic_params(
@@ -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).subst_identity(), true)
+                        cgp::parameters_for(&tcx.type_of(def_id).instantiate_identity(), true)
                     } else {
                         vec![]
                     }
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 c64fb469bb2..81993789bcf 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
@@ -14,15 +14,15 @@
 //! To enforce this requirement on specializations we take the following
 //! approach:
 //!
-//! 1. Match up the substs for `impl2` so that the implemented trait and
+//! 1. Match up the args for `impl2` so that the implemented trait and
 //!    self-type match those for `impl1`.
-//! 2. Check for any direct use of `'static` in the substs of `impl2`.
+//! 2. Check for any direct use of `'static` in the args of `impl2`.
 //! 3. Check that all of the generic parameters of `impl1` occur at most once
-//!    in the *unconstrained* substs for `impl2`. A parameter is constrained if
+//!    in the *unconstrained* args for `impl2`. A parameter is constrained if
 //!    its value is completely determined by an associated type projection
 //!    predicate.
 //! 4. Check that all predicates on `impl1` either exist on `impl2` (after
-//!    matching substs), or are well-formed predicates for the trait's type
+//!    matching args), or are well-formed predicates for the trait's type
 //!    arguments.
 //!
 //! ## Example
@@ -74,13 +74,13 @@ use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_infer::infer::outlives::env::OutlivesEnvironment;
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_infer::traits::specialization_graph::Node;
-use rustc_middle::ty::subst::{GenericArg, InternalSubsts, SubstsRef};
 use rustc_middle::ty::trait_def::TraitSpecializationKind;
 use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt};
+use rustc_middle::ty::{GenericArg, GenericArgs, GenericArgsRef};
 use rustc_span::{ErrorGuaranteed, Span};
 use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
 use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _;
-use rustc_trait_selection::traits::{self, translate_substs_with_cause, wf, ObligationCtxt};
+use rustc_trait_selection::traits::{self, translate_args_with_cause, wf, ObligationCtxt};
 
 pub(super) fn check_min_specialization(tcx: TyCtxt<'_>, impl_def_id: LocalDefId) {
     if let Some(node) = parent_specialization_node(tcx, impl_def_id) {
@@ -113,20 +113,20 @@ fn check_always_applicable(tcx: TyCtxt<'_>, impl1_def_id: LocalDefId, impl2_node
     let span = tcx.def_span(impl1_def_id);
     check_has_items(tcx, impl1_def_id, impl2_node, span);
 
-    if let Ok((impl1_substs, impl2_substs)) = get_impl_substs(tcx, impl1_def_id, impl2_node) {
+    if let Ok((impl1_args, impl2_args)) = get_impl_args(tcx, impl1_def_id, impl2_node) {
         let impl2_def_id = impl2_node.def_id();
-        debug!(?impl2_def_id, ?impl2_substs);
+        debug!(?impl2_def_id, ?impl2_args);
 
-        let parent_substs = if impl2_node.is_from_trait() {
-            impl2_substs.to_vec()
+        let parent_args = if impl2_node.is_from_trait() {
+            impl2_args.to_vec()
         } else {
-            unconstrained_parent_impl_substs(tcx, impl2_def_id, impl2_substs)
+            unconstrained_parent_impl_args(tcx, impl2_def_id, impl2_args)
         };
 
         check_constness(tcx, impl1_def_id, impl2_node, span);
-        check_static_lifetimes(tcx, &parent_substs, span);
-        check_duplicate_params(tcx, impl1_substs, &parent_substs, span);
-        check_predicates(tcx, impl1_def_id, impl1_substs, impl2_node, impl2_substs, span);
+        check_static_lifetimes(tcx, &parent_args, span);
+        check_duplicate_params(tcx, impl1_args, &parent_args, span);
+        check_predicates(tcx, impl1_def_id, impl1_args, impl2_node, impl2_args, span);
     }
 }
 
@@ -167,23 +167,23 @@ fn check_constness(tcx: TyCtxt<'_>, impl1_def_id: LocalDefId, impl2_node: Node,
 /// ```
 ///
 /// Would return `S1 = [C]` and `S2 = [Vec<C>, C]`.
-fn get_impl_substs(
+fn get_impl_args(
     tcx: TyCtxt<'_>,
     impl1_def_id: LocalDefId,
     impl2_node: Node,
-) -> Result<(SubstsRef<'_>, SubstsRef<'_>), ErrorGuaranteed> {
+) -> Result<(GenericArgsRef<'_>, GenericArgsRef<'_>), ErrorGuaranteed> {
     let infcx = &tcx.infer_ctxt().build();
     let ocx = ObligationCtxt::new(infcx);
     let param_env = tcx.param_env(impl1_def_id);
     let impl1_span = tcx.def_span(impl1_def_id);
     let assumed_wf_types = ocx.assumed_wf_types_and_report_errors(param_env, impl1_def_id)?;
 
-    let impl1_substs = InternalSubsts::identity_for_item(tcx, impl1_def_id);
-    let impl2_substs = translate_substs_with_cause(
+    let impl1_args = GenericArgs::identity_for_item(tcx, impl1_def_id);
+    let impl2_args = translate_args_with_cause(
         infcx,
         param_env,
         impl1_def_id.to_def_id(),
-        impl1_substs,
+        impl1_args,
         impl2_node,
         |_, span| {
             traits::ObligationCause::new(
@@ -203,12 +203,12 @@ fn get_impl_substs(
     let implied_bounds = infcx.implied_bounds_tys(param_env, impl1_def_id, assumed_wf_types);
     let outlives_env = OutlivesEnvironment::with_bounds(param_env, implied_bounds);
     let _ = ocx.resolve_regions_and_report_errors(impl1_def_id, &outlives_env);
-    let Ok(impl2_substs) = infcx.fully_resolve(impl2_substs) else {
+    let Ok(impl2_args) = infcx.fully_resolve(impl2_args) else {
         let span = tcx.def_span(impl1_def_id);
         let guar = tcx.sess.emit_err(SubstsOnOverriddenImpl { span });
         return Err(guar);
     };
-    Ok((impl1_substs, impl2_substs))
+    Ok((impl1_args, impl2_args))
 }
 
 /// Returns a list of all of the unconstrained subst of the given impl.
@@ -217,17 +217,17 @@ fn get_impl_substs(
 ///
 /// impl<'a, T, I> ... where &'a I: IntoIterator<Item=&'a T>
 ///
-/// This would return the substs corresponding to `['a, I]`, because knowing
+/// This would return the args corresponding to `['a, I]`, because knowing
 /// `'a` and `I` determines the value of `T`.
-fn unconstrained_parent_impl_substs<'tcx>(
+fn unconstrained_parent_impl_args<'tcx>(
     tcx: TyCtxt<'tcx>,
     impl_def_id: DefId,
-    impl_substs: SubstsRef<'tcx>,
+    impl_args: GenericArgsRef<'tcx>,
 ) -> Vec<GenericArg<'tcx>> {
     let impl_generic_predicates = tcx.predicates_of(impl_def_id);
     let mut unconstrained_parameters = FxHashSet::default();
     let mut constrained_params = FxHashSet::default();
-    let impl_trait_ref = tcx.impl_trait_ref(impl_def_id).map(ty::EarlyBinder::subst_identity);
+    let impl_trait_ref = tcx.impl_trait_ref(impl_def_id).map(ty::EarlyBinder::instantiate_identity);
 
     // Unfortunately the functions in `constrained_generic_parameters` don't do
     // what we want here. We want only a list of constrained parameters while
@@ -255,7 +255,7 @@ fn unconstrained_parent_impl_substs<'tcx>(
         }
     }
 
-    impl_substs
+    impl_args
         .iter()
         .enumerate()
         .filter(|&(idx, _)| !constrained_params.contains(&(idx as u32)))
@@ -264,7 +264,7 @@ fn unconstrained_parent_impl_substs<'tcx>(
 }
 
 /// Check that parameters of the derived impl don't occur more than once in the
-/// equated substs of the base impl.
+/// equated args of the base impl.
 ///
 /// For example forbid the following:
 ///
@@ -280,19 +280,19 @@ fn unconstrained_parent_impl_substs<'tcx>(
 /// impl<T> Tr<T> for Vec<T> { }
 /// ```
 ///
-/// The substs for the parent impl here are `[T, Vec<T>]`, which repeats `T`,
-/// but `S` is constrained in the parent impl, so `parent_substs` is only
+/// The args for the parent impl here are `[T, Vec<T>]`, which repeats `T`,
+/// but `S` is constrained in the parent impl, so `parent_args` is only
 /// `[Vec<T>]`. This means we allow this impl.
 fn check_duplicate_params<'tcx>(
     tcx: TyCtxt<'tcx>,
-    impl1_substs: SubstsRef<'tcx>,
-    parent_substs: &Vec<GenericArg<'tcx>>,
+    impl1_args: GenericArgsRef<'tcx>,
+    parent_args: &Vec<GenericArg<'tcx>>,
     span: Span,
 ) {
-    let mut base_params = cgp::parameters_for(parent_substs, true);
+    let mut base_params = cgp::parameters_for(parent_args, true);
     base_params.sort_by_key(|param| param.0);
     if let (_, [duplicate, ..]) = base_params.partition_dedup() {
-        let param = impl1_substs[duplicate.0 as usize];
+        let param = impl1_args[duplicate.0 as usize];
         tcx.sess
             .struct_span_err(span, format!("specializing impl repeats parameter `{}`", param))
             .emit();
@@ -309,10 +309,10 @@ fn check_duplicate_params<'tcx>(
 /// ```
 fn check_static_lifetimes<'tcx>(
     tcx: TyCtxt<'tcx>,
-    parent_substs: &Vec<GenericArg<'tcx>>,
+    parent_args: &Vec<GenericArg<'tcx>>,
     span: Span,
 ) {
-    if tcx.any_free_region_meets(parent_substs, |r| r.is_static()) {
+    if tcx.any_free_region_meets(parent_args, |r| r.is_static()) {
         tcx.sess.emit_err(errors::StaticSpecialize { span });
     }
 }
@@ -331,14 +331,14 @@ fn check_static_lifetimes<'tcx>(
 fn check_predicates<'tcx>(
     tcx: TyCtxt<'tcx>,
     impl1_def_id: LocalDefId,
-    impl1_substs: SubstsRef<'tcx>,
+    impl1_args: GenericArgsRef<'tcx>,
     impl2_node: Node,
-    impl2_substs: SubstsRef<'tcx>,
+    impl2_args: GenericArgsRef<'tcx>,
     span: Span,
 ) {
     let impl1_predicates: Vec<_> = traits::elaborate(
         tcx,
-        tcx.predicates_of(impl1_def_id).instantiate(tcx, impl1_substs).into_iter(),
+        tcx.predicates_of(impl1_def_id).instantiate(tcx, impl1_args).into_iter(),
     )
     .collect();
 
@@ -350,7 +350,7 @@ fn check_predicates<'tcx>(
         traits::elaborate(
             tcx,
             tcx.predicates_of(impl2_node.def_id())
-                .instantiate(tcx, impl2_substs)
+                .instantiate(tcx, impl2_args)
                 .into_iter()
                 .map(|(c, _s)| c.as_predicate()),
         )
@@ -385,7 +385,7 @@ fn check_predicates<'tcx>(
         .map(|(c, _span)| c.as_predicate());
 
     // Include the well-formed predicates of the type parameters of the impl.
-    for arg in tcx.impl_trait_ref(impl1_def_id).unwrap().subst_identity().substs {
+    for arg in tcx.impl_trait_ref(impl1_def_id).unwrap().instantiate_identity().args {
         let infcx = &tcx.infer_ctxt().build();
         let obligations =
             wf::obligations(infcx, tcx.param_env(impl1_def_id), impl1_def_id, 0, arg, span)
diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs
index a68832d96a6..677d94f1731 100644
--- a/compiler/rustc_hir_analysis/src/lib.rs
+++ b/compiler/rustc_hir_analysis/src/lib.rs
@@ -116,6 +116,7 @@ use std::ops::Not;
 
 use astconv::{AstConv, OnlySelfBounds};
 use bounds::Bounds;
+use rustc_hir::def::DefKind;
 
 fluent_messages! { "../messages.ftl" }
 
@@ -177,12 +178,12 @@ fn require_same_types<'tcx>(
 }
 
 fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) {
-    let main_fnsig = tcx.fn_sig(main_def_id).subst_identity();
+    let main_fnsig = tcx.fn_sig(main_def_id).instantiate_identity();
     let main_span = tcx.def_span(main_def_id);
 
     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).subst_identity();
+            let hir_type = tcx.type_of(local_def_id).instantiate_identity();
             if !matches!(hir_type.kind(), ty::FnDef(..)) {
                 span_bug!(sp, "main has a non-function type: found `{}`", hir_type);
             }
@@ -349,7 +350,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).subst_identity();
+    let start_t = tcx.type_of(start_def_id).instantiate_identity();
     match start_t.kind() {
         ty::FnDef(..) => {
             if let Some(Node::Item(it)) = tcx.hir().find(start_id) {
@@ -420,7 +421,7 @@ fn check_start_fn_ty(tcx: TyCtxt<'_>, start_def_id: DefId) {
                 ),
                 ty::ParamEnv::empty(), // start should not have any where bounds.
                 se_ty,
-                Ty::new_fn_ptr(tcx, tcx.fn_sig(start_def_id).subst_identity()),
+                Ty::new_fn_ptr(tcx, tcx.fn_sig(start_def_id).instantiate_identity()),
             );
         }
         _ => {
@@ -500,6 +501,17 @@ pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed> {
         tcx.hir().for_each_module(|module| tcx.ensure().check_mod_item_types(module))
     });
 
+    // FIXME: Remove this when we implement creating `DefId`s
+    // for anon constants during their parents' typeck.
+    // Typeck all body owners in parallel will produce queries
+    // cycle errors because it may typeck on anon constants directly.
+    tcx.hir().par_body_owners(|item_def_id| {
+        let def_kind = tcx.def_kind(item_def_id);
+        if !matches!(def_kind, DefKind::AnonConst) {
+            tcx.ensure().typeck(item_def_id);
+        }
+    });
+
     check_unused::check_crate(tcx);
     check_for_entry_fn(tcx);
 
diff --git a/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs b/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs
index 71dca918fc5..c17925471d9 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).subst_identity();
+                        let field_ty = tcx.type_of(field_def.did).instantiate_identity();
                         let field_span = tcx.def_span(field_def.did);
                         insert_required_predicates_to_be_wf(
                             tcx,
@@ -117,7 +117,7 @@ fn insert_required_predicates_to_be_wf<'tcx>(
             // can load the current set of inferred and explicit
             // predicates from `global_inferred_outlives` and filter the
             // ones that are TypeOutlives.
-            ty::Adt(def, substs) => {
+            ty::Adt(def, args) => {
                 // First check the inferred predicates
                 //
                 // Example 1:
@@ -146,7 +146,7 @@ fn insert_required_predicates_to_be_wf<'tcx>(
                         // get `T: 'a` (or `predicate`):
                         let predicate = unsubstituted_predicates
                             .rebind(*unsubstituted_predicate)
-                            .subst(tcx, substs);
+                            .instantiate(tcx, args);
                         insert_outlives_predicate(
                             tcx,
                             predicate.0,
@@ -159,11 +159,11 @@ fn insert_required_predicates_to_be_wf<'tcx>(
 
                 // Check if the type has any explicit predicates that need
                 // to be added to `required_predicates`
-                // let _: () = substs.region_at(0);
+                // let _: () = args.region_at(0);
                 check_explicit_predicates(
                     tcx,
                     def.did(),
-                    substs,
+                    args,
                     required_predicates,
                     explicit_map,
                     None,
@@ -186,12 +186,11 @@ fn insert_required_predicates_to_be_wf<'tcx>(
                     // predicates in `check_explicit_predicates` we
                     // need to ignore checking the explicit_map for
                     // Self type.
-                    let substs =
-                        ex_trait_ref.with_self_ty(tcx, tcx.types.usize).skip_binder().substs;
+                    let args = ex_trait_ref.with_self_ty(tcx, tcx.types.usize).skip_binder().args;
                     check_explicit_predicates(
                         tcx,
                         ex_trait_ref.skip_binder().def_id,
-                        substs,
+                        args,
                         required_predicates,
                         explicit_map,
                         Some(tcx.types.self_param),
@@ -206,7 +205,7 @@ fn insert_required_predicates_to_be_wf<'tcx>(
                 check_explicit_predicates(
                     tcx,
                     tcx.parent(obj.def_id),
-                    obj.substs,
+                    obj.args,
                     required_predicates,
                     explicit_map,
                     None,
@@ -239,18 +238,18 @@ fn insert_required_predicates_to_be_wf<'tcx>(
 fn check_explicit_predicates<'tcx>(
     tcx: TyCtxt<'tcx>,
     def_id: DefId,
-    substs: &[GenericArg<'tcx>],
+    args: &[GenericArg<'tcx>],
     required_predicates: &mut RequiredPredicates<'tcx>,
     explicit_map: &mut ExplicitPredicatesMap<'tcx>,
     ignored_self_ty: Option<Ty<'tcx>>,
 ) {
     debug!(
         "check_explicit_predicates(def_id={:?}, \
-         substs={:?}, \
+         args={:?}, \
          explicit_map={:?}, \
          required_predicates={:?}, \
          ignored_self_ty={:?})",
-        def_id, substs, explicit_map, required_predicates, ignored_self_ty,
+        def_id, args, explicit_map, required_predicates, ignored_self_ty,
     );
     let explicit_predicates = explicit_map.explicit_predicates_of(tcx, def_id);
 
@@ -278,10 +277,10 @@ fn check_explicit_predicates<'tcx>(
         // that is represented by the `dyn Trait`, not to the `X` type parameter
         // (or any other generic parameter) declared on `MyStruct`.
         //
-        // Note that we do this check for self **before** applying `substs`. In the
-        // case that `substs` come from a `dyn Trait` type, our caller will have
+        // Note that we do this check for self **before** applying `args`. In the
+        // case that `args` come from a `dyn Trait` type, our caller will have
         // included `Self = usize` as the value for `Self`. If we were
-        // to apply the substs, and not filter this predicate, we might then falsely
+        // to apply the args, and not filter this predicate, we might then falsely
         // conclude that e.g., `X: 'x` was a reasonable inferred requirement.
         //
         // Another similar case is where we have an inferred
@@ -299,7 +298,7 @@ fn check_explicit_predicates<'tcx>(
             continue;
         }
 
-        let predicate = explicit_predicates.rebind(*outlives_predicate).subst(tcx, substs);
+        let predicate = explicit_predicates.rebind(*outlives_predicate).instantiate(tcx, args);
         debug!("predicate = {:?}", &predicate);
         insert_outlives_predicate(tcx, predicate.0, predicate.1, span, required_predicates);
     }
diff --git a/compiler/rustc_hir_analysis/src/outlives/mod.rs b/compiler/rustc_hir_analysis/src/outlives/mod.rs
index 48624cefe4d..be9d076bd6e 100644
--- a/compiler/rustc_hir_analysis/src/outlives/mod.rs
+++ b/compiler/rustc_hir_analysis/src/outlives/mod.rs
@@ -2,7 +2,7 @@ use hir::Node;
 use rustc_hir as hir;
 use rustc_hir::def_id::LocalDefId;
 use rustc_middle::query::Providers;
-use rustc_middle::ty::subst::GenericArgKind;
+use rustc_middle::ty::GenericArgKind;
 use rustc_middle::ty::{self, CratePredicatesMap, ToPredicate, TyCtxt};
 use rustc_span::symbol::sym;
 use rustc_span::Span;
diff --git a/compiler/rustc_hir_analysis/src/outlives/utils.rs b/compiler/rustc_hir_analysis/src/outlives/utils.rs
index c5c5f63a108..a6410c944f7 100644
--- a/compiler/rustc_hir_analysis/src/outlives/utils.rs
+++ b/compiler/rustc_hir_analysis/src/outlives/utils.rs
@@ -1,6 +1,6 @@
 use rustc_infer::infer::outlives::components::{push_outlives_components, Component};
-use rustc_middle::ty::subst::{GenericArg, GenericArgKind};
 use rustc_middle::ty::{self, Region, Ty, TyCtxt};
+use rustc_middle::ty::{GenericArg, GenericArgKind};
 use rustc_span::Span;
 use smallvec::smallvec;
 use std::collections::BTreeMap;
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 ee3457282d3..0828fe9e0f2 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
@@ -360,9 +360,11 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
                 &[]
             };
             ret.extend(params.iter().filter_map(|p| {
-                let hir::GenericParamKind::Lifetime { kind: hir::LifetimeParamKind::Explicit }
-                    = p.kind
-                else { return None };
+                let hir::GenericParamKind::Lifetime { kind: hir::LifetimeParamKind::Explicit } =
+                    p.kind
+                else {
+                    return None;
+                };
                 let hir::ParamName::Plain(name) = p.name else { return None };
                 Some(name.to_string())
             }));
@@ -793,29 +795,36 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
         num_trait_generics_except_self: usize,
     ) {
         let sm = self.tcx.sess.source_map();
-        let hir::ExprKind::MethodCall(_, rcvr, args, _) = expr.kind else { return; };
+        let hir::ExprKind::MethodCall(_, rcvr, args, _) = expr.kind else {
+            return;
+        };
         if num_assoc_fn_excess_args != num_trait_generics_except_self {
             return;
         }
-        let Some(gen_args) = self.gen_args.span_ext() else { return; };
-        let Ok(generics) = sm.span_to_snippet(gen_args) else { return; };
-        let Ok(rcvr) = sm.span_to_snippet(
-            rcvr.span.find_ancestor_inside(expr.span).unwrap_or(rcvr.span)
-        ) else { return; };
-        let Ok(rest) =
-            (match args {
-                [] => Ok(String::new()),
-                [arg] => sm.span_to_snippet(
-                    arg.span.find_ancestor_inside(expr.span).unwrap_or(arg.span),
-                ),
-                [first, .., last] => {
-                    let first_span =
-                        first.span.find_ancestor_inside(expr.span).unwrap_or(first.span);
-                    let last_span =
-                        last.span.find_ancestor_inside(expr.span).unwrap_or(last.span);
-                    sm.span_to_snippet(first_span.to(last_span))
-                }
-            }) else { return; };
+        let Some(gen_args) = self.gen_args.span_ext() else {
+            return;
+        };
+        let Ok(generics) = sm.span_to_snippet(gen_args) else {
+            return;
+        };
+        let Ok(rcvr) =
+            sm.span_to_snippet(rcvr.span.find_ancestor_inside(expr.span).unwrap_or(rcvr.span))
+        else {
+            return;
+        };
+        let Ok(rest) = (match args {
+            [] => Ok(String::new()),
+            [arg] => {
+                sm.span_to_snippet(arg.span.find_ancestor_inside(expr.span).unwrap_or(arg.span))
+            }
+            [first, .., last] => {
+                let first_span = first.span.find_ancestor_inside(expr.span).unwrap_or(first.span);
+                let last_span = last.span.find_ancestor_inside(expr.span).unwrap_or(last.span);
+                sm.span_to_snippet(first_span.to(last_span))
+            }
+        }) else {
+            return;
+        };
         let comma = if args.len() > 0 { ", " } else { "" };
         let trait_path = self.tcx.def_path_str(trait_def_id);
         let method_name = self.tcx.item_name(self.def_id);
diff --git a/compiler/rustc_hir_analysis/src/variance/constraints.rs b/compiler/rustc_hir_analysis/src/variance/constraints.rs
index 6f0afae1b4c..ec8889781f4 100644
--- a/compiler/rustc_hir_analysis/src/variance/constraints.rs
+++ b/compiler/rustc_hir_analysis/src/variance/constraints.rs
@@ -6,8 +6,8 @@
 use hir::def_id::{DefId, LocalDefId};
 use rustc_hir as hir;
 use rustc_hir::def::DefKind;
-use rustc_middle::ty::subst::{GenericArgKind, SubstsRef};
 use rustc_middle::ty::{self, Ty, TyCtxt};
+use rustc_middle::ty::{GenericArgKind, GenericArgsRef};
 
 use super::terms::VarianceTerm::*;
 use super::terms::*;
@@ -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).subst_identity().kind() {
+        match tcx.type_of(def_id).instantiate_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).subst_identity(),
+                        tcx.type_of(field.did).instantiate_identity(),
                         self.covariant,
                     );
                 }
@@ -121,7 +121,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
             ty::FnDef(..) => {
                 self.add_constraints_from_sig(
                     current_item,
-                    tcx.fn_sig(def_id).subst_identity(),
+                    tcx.fn_sig(def_id).instantiate_identity(),
                     self.covariant,
                 );
             }
@@ -175,16 +175,16 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
     }
 
     #[instrument(level = "debug", skip(self, current))]
-    fn add_constraints_from_invariant_substs(
+    fn add_constraints_from_invariant_args(
         &mut self,
         current: &CurrentItem,
-        substs: SubstsRef<'tcx>,
+        args: GenericArgsRef<'tcx>,
         variance: VarianceTermPtr<'a>,
     ) {
         // Trait are always invariant so we can take advantage of that.
         let variance_i = self.invariant(variance);
 
-        for k in substs {
+        for k in args {
             match k.unpack() {
                 GenericArgKind::Lifetime(lt) => {
                     self.add_constraints_from_region(current, lt, variance_i)
@@ -248,12 +248,12 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
                 }
             }
 
-            ty::Adt(def, substs) => {
-                self.add_constraints_from_substs(current, def.did(), substs, variance);
+            ty::Adt(def, args) => {
+                self.add_constraints_from_args(current, def.did(), args, variance);
             }
 
             ty::Alias(_, ref data) => {
-                self.add_constraints_from_invariant_substs(current, data.substs, variance);
+                self.add_constraints_from_invariant_args(current, data.args, variance);
             }
 
             ty::Dynamic(data, r, _) => {
@@ -261,9 +261,9 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
                 self.add_constraints_from_region(current, r, variance);
 
                 if let Some(poly_trait_ref) = data.principal() {
-                    self.add_constraints_from_invariant_substs(
+                    self.add_constraints_from_invariant_args(
                         current,
-                        poly_trait_ref.skip_binder().substs,
+                        poly_trait_ref.skip_binder().args,
                         variance,
                     );
                 }
@@ -305,20 +305,20 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
 
     /// Adds constraints appropriate for a nominal type (enum, struct,
     /// object, etc) appearing in a context with ambient variance `variance`
-    fn add_constraints_from_substs(
+    fn add_constraints_from_args(
         &mut self,
         current: &CurrentItem,
         def_id: DefId,
-        substs: SubstsRef<'tcx>,
+        args: GenericArgsRef<'tcx>,
         variance: VarianceTermPtr<'a>,
     ) {
         debug!(
-            "add_constraints_from_substs(def_id={:?}, substs={:?}, variance={:?})",
-            def_id, substs, variance
+            "add_constraints_from_args(def_id={:?}, args={:?}, variance={:?})",
+            def_id, args, variance
         );
 
         // We don't record `inferred_starts` entries for empty generics.
-        if substs.is_empty() {
+        if args.is_empty() {
             return;
         }
 
@@ -328,7 +328,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
             (None, Some(self.tcx().variances_of(def_id)))
         };
 
-        for (i, k) in substs.iter().enumerate() {
+        for (i, k) in args.iter().enumerate() {
             let variance_decl = if let Some(InferredIndex(start)) = local {
                 // Parameter on an item defined within current crate:
                 // variance not yet inferred, so return a symbolic
@@ -341,7 +341,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
             };
             let variance_i = self.xform(variance, variance_decl);
             debug!(
-                "add_constraints_from_substs: variance_decl={:?} variance_i={:?}",
+                "add_constraints_from_args: variance_decl={:?} variance_i={:?}",
                 variance_decl, variance_i
             );
             match k.unpack() {
@@ -368,7 +368,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
 
         match &c.kind() {
             ty::ConstKind::Unevaluated(uv) => {
-                self.add_constraints_from_invariant_substs(current, uv.substs, variance);
+                self.add_constraints_from_invariant_args(current, uv.args, variance);
             }
             _ => {}
         }
diff --git a/compiler/rustc_hir_analysis/src/variance/mod.rs b/compiler/rustc_hir_analysis/src/variance/mod.rs
index c703cb03515..199cdabb7e9 100644
--- a/compiler/rustc_hir_analysis/src/variance/mod.rs
+++ b/compiler/rustc_hir_analysis/src/variance/mod.rs
@@ -7,7 +7,7 @@ use rustc_arena::DroplessArena;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_middle::query::Providers;
-use rustc_middle::ty::{self, CrateVariancesMap, SubstsRef, Ty, TyCtxt};
+use rustc_middle::ty::{self, CrateVariancesMap, GenericArgsRef, Ty, TyCtxt};
 use rustc_middle::ty::{TypeSuperVisitable, TypeVisitable};
 use std::ops::ControlFlow;
 
@@ -83,17 +83,17 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc
 
     impl<'tcx> OpaqueTypeLifetimeCollector<'tcx> {
         #[instrument(level = "trace", skip(self), ret)]
-        fn visit_opaque(&mut self, def_id: DefId, substs: SubstsRef<'tcx>) -> ControlFlow<!> {
+        fn visit_opaque(&mut self, def_id: DefId, args: GenericArgsRef<'tcx>) -> ControlFlow<!> {
             if def_id != self.root_def_id && self.tcx.is_descendant_of(def_id, self.root_def_id) {
                 let child_variances = self.tcx.variances_of(def_id);
-                for (a, v) in substs.iter().zip(child_variances) {
+                for (a, v) in args.iter().zip(child_variances) {
                     if *v != ty::Bivariant {
                         a.visit_with(self)?;
                     }
                 }
                 ControlFlow::Continue(())
             } else {
-                substs.visit_with(self)
+                args.visit_with(self)
             }
         }
     }
@@ -110,10 +110,10 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc
         #[instrument(level = "trace", skip(self), ret)]
         fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
             match t.kind() {
-                ty::Alias(_, ty::AliasTy { def_id, substs, .. })
+                ty::Alias(_, ty::AliasTy { def_id, args, .. })
                     if matches!(self.tcx.def_kind(*def_id), DefKind::OpaqueTy) =>
                 {
-                    self.visit_opaque(*def_id, substs)
+                    self.visit_opaque(*def_id, args)
                 }
                 _ => t.super_visit_with(self),
             }
@@ -144,30 +144,30 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc
 
     let mut collector =
         OpaqueTypeLifetimeCollector { tcx, root_def_id: item_def_id.to_def_id(), variances };
-    let id_substs = ty::InternalSubsts::identity_for_item(tcx, item_def_id);
-    for (pred, _) in tcx.explicit_item_bounds(item_def_id).subst_iter_copied(tcx, id_substs) {
+    let id_args = ty::GenericArgs::identity_for_item(tcx, item_def_id);
+    for (pred, _) in tcx.explicit_item_bounds(item_def_id).arg_iter_copied(tcx, id_args) {
         debug!(?pred);
 
-        // We only ignore opaque type substs if the opaque type is the outermost type.
+        // We only ignore opaque type args if the opaque type is the outermost type.
         // The opaque type may be nested within itself via recursion in e.g.
         // type Foo<'a> = impl PartialEq<Foo<'a>>;
         // which thus mentions `'a` and should thus accept hidden types that borrow 'a
         // instead of requiring an additional `+ 'a`.
         match pred.kind().skip_binder() {
             ty::ClauseKind::Trait(ty::TraitPredicate {
-                trait_ref: ty::TraitRef { def_id: _, substs, .. },
+                trait_ref: ty::TraitRef { def_id: _, args, .. },
                 constness: _,
                 polarity: _,
             }) => {
-                for subst in &substs[1..] {
+                for subst in &args[1..] {
                     subst.visit_with(&mut collector);
                 }
             }
             ty::ClauseKind::Projection(ty::ProjectionPredicate {
-                projection_ty: ty::AliasTy { substs, .. },
+                projection_ty: ty::AliasTy { args, .. },
                 term,
             }) => {
-                for subst in &substs[1..] {
+                for subst in &args[1..] {
                     subst.visit_with(&mut collector);
                 }
                 term.visit_with(&mut collector);
diff --git a/compiler/rustc_hir_analysis/src/variance/solve.rs b/compiler/rustc_hir_analysis/src/variance/solve.rs
index c27c176e35f..54da3277026 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).subst_identity().kind() {
+                if let ty::FnDef(..) = tcx.type_of(def_id).instantiate_identity().kind() {
                     for variance in variances.iter_mut() {
                         if *variance == ty::Bivariant {
                             *variance = ty::Invariant;
diff --git a/compiler/rustc_hir_typeck/src/_match.rs b/compiler/rustc_hir_typeck/src/_match.rs
index e8720a5da02..f2a43cc414d 100644
--- a/compiler/rustc_hir_typeck/src/_match.rs
+++ b/compiler/rustc_hir_typeck/src/_match.rs
@@ -188,11 +188,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let hir = self.tcx.hir();
 
         // First, check that we're actually in the tail of a function.
-        let Some(body_id) = hir.maybe_body_owned_by(self.body_id) else { return; };
+        let Some(body_id) = hir.maybe_body_owned_by(self.body_id) else {
+            return;
+        };
         let body = hir.body(body_id);
-        let hir::ExprKind::Block(block, _) = body.value.kind else { return; };
-        let Some(hir::Stmt { kind: hir::StmtKind::Semi(last_expr), .. })
-            = block.innermost_block().stmts.last() else {  return; };
+        let hir::ExprKind::Block(block, _) = body.value.kind else {
+            return;
+        };
+        let Some(hir::Stmt { kind: hir::StmtKind::Semi(last_expr), .. }) =
+            block.innermost_block().stmts.last()
+        else {
+            return;
+        };
         if last_expr.hir_id != expr.hir_id {
             return;
         }
@@ -201,7 +208,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let Some(ret) = hir
             .find_by_def_id(self.body_id)
             .and_then(|owner| owner.fn_decl())
-            .map(|decl| decl.output.span()) else { return; };
+            .map(|decl| decl.output.span())
+        else {
+            return;
+        };
         let Expectation::IsLast(stmt) = expectation else {
             return;
         };
@@ -508,9 +518,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     span,
                     kind: TypeVariableOriginKind::OpaqueTypeInference(rpit_def_id),
                     ..
-                } = self.type_var_origin(expected)? else { return None; };
+                } = self.type_var_origin(expected)?
+                else {
+                    return None;
+                };
 
-                let Some(rpit_local_def_id) = rpit_def_id.as_local() else { return None; };
+                let Some(rpit_local_def_id) = rpit_def_id.as_local() else {
+                    return None;
+                };
                 if !matches!(
                     self.tcx.hir().expect_item(rpit_local_def_id).expect_opaque_ty().origin,
                     hir::OpaqueTyOrigin::FnReturn(..)
@@ -520,12 +535,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
                 let sig = self.body_fn_sig()?;
 
-                let substs = sig.output().walk().find_map(|arg| {
+                let args = sig.output().walk().find_map(|arg| {
                     if let ty::GenericArgKind::Type(ty) = arg.unpack()
-                        && let ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) = *ty.kind()
+                        && let ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) = *ty.kind()
                         && def_id == rpit_def_id
                     {
-                        Some(substs)
+                        Some(args)
                     } else {
                         None
                     }
@@ -536,26 +551,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 }
 
                 for ty in [first_ty, second_ty] {
-                    for (clause, _) in self
-                        .tcx
-                        .explicit_item_bounds(rpit_def_id)
-                        .subst_iter_copied(self.tcx, substs)
+                    for (clause, _) in
+                        self.tcx.explicit_item_bounds(rpit_def_id).arg_iter_copied(self.tcx, args)
                     {
                         let pred = clause.kind().rebind(match clause.kind().skip_binder() {
                             ty::ClauseKind::Trait(trait_pred) => {
                                 // FIXME(rpitit): This will need to be fixed when we move to associated types
                                 assert!(matches!(
                                     *trait_pred.trait_ref.self_ty().kind(),
-                                    ty::Alias(_, ty::AliasTy { def_id, substs: alias_substs, .. })
-                                    if def_id == rpit_def_id && substs == alias_substs
+                                    ty::Alias(_, ty::AliasTy { def_id, args: alias_args, .. })
+                                    if def_id == rpit_def_id && args == alias_args
                                 ));
                                 ty::ClauseKind::Trait(trait_pred.with_self_ty(self.tcx, ty))
                             }
                             ty::ClauseKind::Projection(mut proj_pred) => {
                                 assert!(matches!(
                                     *proj_pred.projection_ty.self_ty().kind(),
-                                    ty::Alias(_, ty::AliasTy { def_id, substs: alias_substs, .. })
-                                    if def_id == rpit_def_id && substs == alias_substs
+                                    ty::Alias(_, ty::AliasTy { def_id, args: alias_args, .. })
+                                    if def_id == rpit_def_id && args == alias_args
                                 ));
                                 proj_pred = proj_pred.with_self_ty(self.tcx, ty);
                                 ty::ClauseKind::Projection(proj_pred)
diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs
index f306653c1ab..a24d1ff077f 100644
--- a/compiler/rustc_hir_typeck/src/callee.rs
+++ b/compiler/rustc_hir_typeck/src/callee.rs
@@ -21,7 +21,7 @@ use rustc_infer::{
 use rustc_middle::ty::adjustment::{
     Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability,
 };
-use rustc_middle::ty::SubstsRef;
+use rustc_middle::ty::GenericArgsRef;
 use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
 use rustc_span::def_id::LocalDefId;
 use rustc_span::symbol::{sym, Ident};
@@ -149,14 +149,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 return Some(CallStep::Builtin(adjusted_ty));
             }
 
-            ty::Closure(def_id, substs) => {
+            ty::Closure(def_id, args) => {
                 let def_id = def_id.expect_local();
 
                 // Check whether this is a call to a closure where we
                 // haven't yet decided on whether the closure is fn vs
                 // fnmut vs fnonce. If so, we have to defer further processing.
-                if self.closure_kind(substs).is_none() {
-                    let closure_sig = substs.as_closure().sig();
+                if self.closure_kind(args).is_none() {
+                    let closure_sig = args.as_closure().sig();
                     let closure_sig = self.instantiate_binder_with_fresh_vars(
                         call_expr.span,
                         infer::FnCall,
@@ -171,7 +171,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             adjusted_ty,
                             adjustments,
                             fn_sig: closure_sig,
-                            closure_substs: substs,
+                            closure_args: args,
                         },
                     );
                     return Some(CallStep::DeferredClosure(def_id, closure_sig));
@@ -380,16 +380,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         expected: Expectation<'tcx>,
     ) -> Ty<'tcx> {
         let (fn_sig, def_id) = match *callee_ty.kind() {
-            ty::FnDef(def_id, substs) => {
-                self.enforce_context_effects(call_expr.hir_id, call_expr.span, def_id, substs);
-                let fn_sig = self.tcx.fn_sig(def_id).subst(self.tcx, substs);
+            ty::FnDef(def_id, args) => {
+                self.enforce_context_effects(call_expr.hir_id, call_expr.span, def_id, args);
+                let fn_sig = self.tcx.fn_sig(def_id).instantiate(self.tcx, args);
 
                 // Unit testing: function items annotated with
                 // `#[rustc_evaluate_where_clauses]` trigger special output
                 // to let us test the trait evaluation system.
                 if self.tcx.has_attr(def_id, sym::rustc_evaluate_where_clauses) {
                     let predicates = self.tcx.predicates_of(def_id);
-                    let predicates = predicates.instantiate(self.tcx, substs);
+                    let predicates = predicates.instantiate(self.tcx, args);
                     for (predicate, predicate_span) in predicates {
                         let obligation = Obligation::new(
                             self.tcx,
@@ -499,15 +499,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         expected: Expectation<'tcx>,
     ) {
         if let [callee_expr, rest @ ..] = arg_exprs {
-            let Some(callee_ty) = self.typeck_results.borrow().expr_ty_adjusted_opt(callee_expr) else {
+            let Some(callee_ty) = self.typeck_results.borrow().expr_ty_adjusted_opt(callee_expr)
+            else {
                 return;
             };
 
             // First, do a probe with `IsSuggestion(true)` to avoid emitting
             // any strange errors. If it's successful, then we'll do a true
             // method lookup.
-            let Ok(pick) = self
-            .lookup_probe_for_diagnostic(
+            let Ok(pick) = self.lookup_probe_for_diagnostic(
                 segment.ident,
                 callee_ty,
                 call_expr,
@@ -751,7 +751,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         call_expr_hir: HirId,
         span: Span,
         callee_did: DefId,
-        callee_substs: SubstsRef<'tcx>,
+        callee_args: GenericArgsRef<'tcx>,
     ) {
         let tcx = self.tcx;
 
@@ -774,18 +774,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let effect = match const_context {
             Some(hir::ConstContext::Static(_) | hir::ConstContext::Const) => tcx.consts.false_,
             Some(hir::ConstContext::ConstFn) => {
-                let substs = ty::InternalSubsts::identity_for_item(tcx, context);
-                substs.host_effect_param().expect("ConstContext::Maybe must have host effect param")
+                let args = ty::GenericArgs::identity_for_item(tcx, context);
+                args.host_effect_param().expect("ConstContext::Maybe must have host effect param")
             }
             None => tcx.consts.true_,
         };
 
         let generics = tcx.generics_of(callee_did);
 
-        trace!(?effect, ?generics, ?callee_substs);
+        trace!(?effect, ?generics, ?callee_args);
 
         if let Some(idx) = generics.host_effect_index {
-            let param = callee_substs.const_at(idx);
+            let param = callee_args.const_at(idx);
             let cause = self.misc(span);
             match self.at(&cause, self.param_env).eq(infer::DefineOpaqueTypes::No, effect, param) {
                 Ok(infer::InferOk { obligations, value: () }) => {
@@ -827,7 +827,7 @@ pub struct DeferredCallResolution<'tcx> {
     adjusted_ty: Ty<'tcx>,
     adjustments: Vec<Adjustment<'tcx>>,
     fn_sig: ty::FnSig<'tcx>,
-    closure_substs: SubstsRef<'tcx>,
+    closure_args: GenericArgsRef<'tcx>,
 }
 
 impl<'a, 'tcx> DeferredCallResolution<'tcx> {
@@ -836,7 +836,7 @@ impl<'a, 'tcx> DeferredCallResolution<'tcx> {
 
         // we should not be invoked until the closure kind has been
         // determined by upvar inference
-        assert!(fcx.closure_kind(self.closure_substs).is_some());
+        assert!(fcx.closure_kind(self.closure_args).is_some());
 
         // We may now know enough to figure out fn vs fnmut etc.
         match fcx.try_overloaded_call_traits(self.call_expr, self.adjusted_ty, None) {
diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs
index 633933317c0..7597ce88f93 100644
--- a/compiler/rustc_hir_typeck/src/cast.rs
+++ b/compiler/rustc_hir_typeck/src/cast.rs
@@ -103,10 +103,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         Ok(match *t.kind() {
             ty::Slice(_) | ty::Str => Some(PointerKind::Length),
             ty::Dynamic(ref tty, _, ty::Dyn) => Some(PointerKind::VTable(tty.principal_def_id())),
-            ty::Adt(def, substs) if def.is_struct() => match def.non_enum_variant().tail_opt() {
+            ty::Adt(def, args) if def.is_struct() => match def.non_enum_variant().tail_opt() {
                 None => Some(PointerKind::Thin),
                 Some(f) => {
-                    let field_ty = self.field_ty(span, f, substs);
+                    let field_ty = self.field_ty(span, f, args);
                     self.pointer_kind(field_ty, span)?
                 }
             },
diff --git a/compiler/rustc_hir_typeck/src/check.rs b/compiler/rustc_hir_typeck/src/check.rs
index 8b57e311fc0..53bae315d78 100644
--- a/compiler/rustc_hir_typeck/src/check.rs
+++ b/compiler/rustc_hir_typeck/src/check.rs
@@ -80,7 +80,7 @@ pub(super) fn check_fn<'a, 'tcx>(
         let va_list_did = tcx.require_lang_item(LangItem::VaList, Some(span));
         let region = fcx.next_region_var(RegionVariableOrigin::MiscVariable(span));
 
-        tcx.type_of(va_list_did).subst(tcx, &[region.into()])
+        tcx.type_of(va_list_did).instantiate(tcx, &[region.into()])
     });
 
     // Add formal parameters.
diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs
index 78a9ac49de2..e7df9ecf383 100644
--- a/compiler/rustc_hir_typeck/src/closure.rs
+++ b/compiler/rustc_hir_typeck/src/closure.rs
@@ -10,8 +10,8 @@ use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKi
 use rustc_infer::infer::{DefineOpaqueTypes, LateBoundRegionConversionTime};
 use rustc_infer::infer::{InferOk, InferResult};
 use rustc_macros::{TypeFoldable, TypeVisitable};
-use rustc_middle::ty::subst::InternalSubsts;
 use rustc_middle::ty::visit::{TypeVisitable, TypeVisitableExt};
+use rustc_middle::ty::GenericArgs;
 use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitor};
 use rustc_span::def_id::LocalDefId;
 use rustc_span::source_map::Span;
@@ -93,7 +93,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             false,
         );
 
-        let parent_substs = InternalSubsts::identity_for_item(
+        let parent_args = GenericArgs::identity_for_item(
             self.tcx,
             self.tcx.typeck_root_def_id(expr_def_id.to_def_id()),
         );
@@ -105,10 +105,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         if let Some(GeneratorTypes { resume_ty, yield_ty, interior, movability }) = generator_types
         {
-            let generator_substs = ty::GeneratorSubsts::new(
+            let generator_args = ty::GeneratorArgs::new(
                 self.tcx,
-                ty::GeneratorSubstsParts {
-                    parent_substs,
+                ty::GeneratorArgsParts {
+                    parent_args,
                     resume_ty,
                     yield_ty,
                     return_ty: liberated_sig.output(),
@@ -120,7 +120,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             return Ty::new_generator(
                 self.tcx,
                 expr_def_id.to_def_id(),
-                generator_substs.substs,
+                generator_args.args,
                 movability,
             );
         }
@@ -151,17 +151,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             }),
         };
 
-        let closure_substs = ty::ClosureSubsts::new(
+        let closure_args = ty::ClosureArgs::new(
             self.tcx,
-            ty::ClosureSubstsParts {
-                parent_substs,
+            ty::ClosureArgsParts {
+                parent_args,
                 closure_kind_ty,
                 closure_sig_as_fn_ptr_ty: Ty::new_fn_ptr(self.tcx, sig),
                 tupled_upvars_ty,
             },
         );
 
-        Ty::new_closure(self.tcx, expr_def_id.to_def_id(), closure_substs.substs)
+        Ty::new_closure(self.tcx, expr_def_id.to_def_id(), closure_args.args)
     }
 
     /// Given the expected type, figures out what it can about this closure we
@@ -172,12 +172,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         expected_ty: Ty<'tcx>,
     ) -> (Option<ExpectedSig<'tcx>>, Option<ty::ClosureKind>) {
         match *expected_ty.kind() {
-            ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => self
+            ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) => self
                 .deduce_closure_signature_from_predicates(
                     expected_ty,
                     self.tcx
                         .explicit_item_bounds(def_id)
-                        .subst_iter_copied(self.tcx, substs)
+                        .arg_iter_copied(self.tcx, args)
                         .map(|(c, s)| (c.as_predicate(), s)),
                 ),
             ty::Dynamic(ref object_type, ..) => {
@@ -315,7 +315,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         }
 
         let input_tys = if is_fn {
-            let arg_param_ty = projection.skip_binder().projection_ty.substs.type_at(1);
+            let arg_param_ty = projection.skip_binder().projection_ty.args.type_at(1);
             let arg_param_ty = self.resolve_vars_if_possible(arg_param_ty);
             debug!(?arg_param_ty);
 
@@ -717,16 +717,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     get_future_output(obligation.predicate, obligation.cause.span)
                 })?
             }
-            ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => self
+            ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) => self
                 .tcx
                 .explicit_item_bounds(def_id)
-                .subst_iter_copied(self.tcx, substs)
+                .arg_iter_copied(self.tcx, args)
                 .find_map(|(p, s)| get_future_output(p.as_predicate(), s))?,
             ty::Error(_) => return None,
             ty::Alias(ty::Projection, proj) if self.tcx.is_impl_trait_in_trait(proj.def_id) => self
                 .tcx
                 .explicit_item_bounds(proj.def_id)
-                .subst_iter_copied(self.tcx, proj.substs)
+                .arg_iter_copied(self.tcx, proj.args)
                 .find_map(|(p, s)| get_future_output(p.as_predicate(), s))?,
             _ => span_bug!(
                 self.tcx.def_span(expr_def_id),
diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs
index dc58d99ed9d..3b1d9c8905b 100644
--- a/compiler/rustc_hir_typeck/src/coercion.rs
+++ b/compiler/rustc_hir_typeck/src/coercion.rs
@@ -51,8 +51,8 @@ use rustc_middle::ty::adjustment::{
 };
 use rustc_middle::ty::error::TypeError;
 use rustc_middle::ty::relate::RelateResult;
-use rustc_middle::ty::subst::SubstsRef;
 use rustc_middle::ty::visit::TypeVisitableExt;
+use rustc_middle::ty::GenericArgsRef;
 use rustc_middle::ty::{self, Ty, TypeAndMut};
 use rustc_session::parse::feature_err;
 use rustc_span::symbol::sym;
@@ -251,11 +251,11 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
                 // unsafe qualifier.
                 self.coerce_from_fn_pointer(a, a_f, b)
             }
-            ty::Closure(closure_def_id_a, substs_a) => {
+            ty::Closure(closure_def_id_a, args_a) => {
                 // Non-capturing closures are coercible to
                 // function pointers or unsafe function pointers.
                 // It cannot convert closures that require unsafe.
-                self.coerce_closure_to_fn(a, closure_def_id_a, substs_a, b)
+                self.coerce_closure_to_fn(a, closure_def_id_a, args_a, b)
             }
             _ => {
                 // Otherwise, just use unification rules.
@@ -636,9 +636,10 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
                 Some(ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_pred)))
                     if traits.contains(&trait_pred.def_id()) =>
                 {
+                    let trait_pred = self.resolve_vars_if_possible(trait_pred);
                     if unsize_did == trait_pred.def_id() {
                         let self_ty = trait_pred.self_ty();
-                        let unsize_ty = trait_pred.trait_ref.substs[1].expect_ty();
+                        let unsize_ty = trait_pred.trait_ref.args[1].expect_ty();
                         if let (ty::Dynamic(ref data_a, ..), ty::Dynamic(ref data_b, ..)) =
                             (self_ty.kind(), unsize_ty.kind())
                             && data_a.principal_def_id() != data_b.principal_def_id()
@@ -662,9 +663,8 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
                 // Uncertain or unimplemented.
                 Ok(None) => {
                     if trait_pred.def_id() == unsize_did {
-                        let trait_pred = self.resolve_vars_if_possible(trait_pred);
                         let self_ty = trait_pred.self_ty();
-                        let unsize_ty = trait_pred.trait_ref.substs[1].expect_ty();
+                        let unsize_ty = trait_pred.trait_ref.args[1].expect_ty();
                         debug!("coerce_unsized: ambiguous unsize case for {:?}", trait_pred);
                         match (self_ty.kind(), unsize_ty.kind()) {
                             (&ty::Infer(ty::TyVar(v)), ty::Dynamic(..))
@@ -916,7 +916,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
         &self,
         a: Ty<'tcx>,
         closure_def_id_a: DefId,
-        substs_a: SubstsRef<'tcx>,
+        args_a: GenericArgsRef<'tcx>,
         b: Ty<'tcx>,
     ) -> CoerceResult<'tcx> {
         //! Attempts to coerce from the type of a non-capturing closure
@@ -927,7 +927,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
 
         match b.kind() {
             // At this point we haven't done capture analysis, which means
-            // that the ClosureSubsts just contains an inference variable instead
+            // that the ClosureArgs just contains an inference variable instead
             // of tuple of captured types.
             //
             // All we care here is if any variable is being captured and not the exact paths,
@@ -944,7 +944,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
                 //     `fn(arg0,arg1,...) -> _`
                 // or
                 //     `unsafe fn(arg0,arg1,...) -> _`
-                let closure_sig = substs_a.as_closure().sig();
+                let closure_sig = args_a.as_closure().sig();
                 let unsafety = fn_ty.unsafety();
                 let pointer_ty =
                     Ty::new_fn_ptr(self.tcx, self.tcx.signature_unclosure(closure_sig, unsafety));
@@ -1109,10 +1109,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         }
 
         // Special-case that coercion alone cannot handle:
-        // Function items or non-capturing closures of differing IDs or InternalSubsts.
+        // Function items or non-capturing closures of differing IDs or GenericArgs.
         let (a_sig, b_sig) = {
             let is_capturing_closure = |ty: Ty<'tcx>| {
-                if let &ty::Closure(closure_def_id, _substs) = ty.kind() {
+                if let &ty::Closure(closure_def_id, _args) = ty.kind() {
                     self.tcx.upvars_mentioned(closure_def_id.expect_local()).is_some()
                 } else {
                     false
@@ -1139,30 +1139,30 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             }
                         }
                     }
-                    (ty::Closure(_, substs), ty::FnDef(..)) => {
+                    (ty::Closure(_, args), ty::FnDef(..)) => {
                         let b_sig = new_ty.fn_sig(self.tcx);
-                        let a_sig = self
-                            .tcx
-                            .signature_unclosure(substs.as_closure().sig(), b_sig.unsafety());
+                        let a_sig =
+                            self.tcx.signature_unclosure(args.as_closure().sig(), b_sig.unsafety());
                         (Some(a_sig), Some(b_sig))
                     }
-                    (ty::FnDef(..), ty::Closure(_, substs)) => {
+                    (ty::FnDef(..), ty::Closure(_, args)) => {
                         let a_sig = prev_ty.fn_sig(self.tcx);
-                        let b_sig = self
-                            .tcx
-                            .signature_unclosure(substs.as_closure().sig(), a_sig.unsafety());
+                        let b_sig =
+                            self.tcx.signature_unclosure(args.as_closure().sig(), a_sig.unsafety());
                         (Some(a_sig), Some(b_sig))
                     }
-                    (ty::Closure(_, substs_a), ty::Closure(_, substs_b)) => (
-                        Some(self.tcx.signature_unclosure(
-                            substs_a.as_closure().sig(),
-                            hir::Unsafety::Normal,
-                        )),
-                        Some(self.tcx.signature_unclosure(
-                            substs_b.as_closure().sig(),
-                            hir::Unsafety::Normal,
-                        )),
-                    ),
+                    (ty::Closure(_, args_a), ty::Closure(_, args_b)) => {
+                        (
+                            Some(self.tcx.signature_unclosure(
+                                args_a.as_closure().sig(),
+                                hir::Unsafety::Normal,
+                            )),
+                            Some(self.tcx.signature_unclosure(
+                                args_b.as_closure().sig(),
+                                hir::Unsafety::Normal,
+                            )),
+                        )
+                    }
                     _ => (None, None),
                 }
             }
@@ -1670,7 +1670,9 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
         expr: &hir::Expr<'tcx>,
         ret_exprs: &Vec<&'tcx hir::Expr<'tcx>>,
     ) {
-        let hir::ExprKind::Loop(_, _, _, loop_span) = expr.kind else { return;};
+        let hir::ExprKind::Loop(_, _, _, loop_span) = expr.kind else {
+            return;
+        };
         let mut span: MultiSpan = vec![loop_span].into();
         span.push_span_label(loop_span, "this might have zero elements to iterate on");
         const MAXITER: usize = 3;
diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs
index cc8198aab25..429c3366fed 100644
--- a/compiler/rustc_hir_typeck/src/demand.rs
+++ b/compiler/rustc_hir_typeck/src/demand.rs
@@ -15,7 +15,7 @@ use rustc_middle::ty::error::{ExpectedFound, TypeError};
 use rustc_middle::ty::fold::BottomUpFolder;
 use rustc_middle::ty::print::with_no_trimmed_paths;
 use rustc_middle::ty::{self, Article, AssocItem, Ty, TypeAndMut, TypeFoldable};
-use rustc_span::symbol::{sym, Symbol};
+use rustc_span::symbol::sym;
 use rustc_span::{BytePos, Span, DUMMY_SP};
 use rustc_trait_selection::infer::InferCtxtExt as _;
 use rustc_trait_selection::traits::ObligationCause;
@@ -102,7 +102,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         found_expr: &mut &'tcx hir::Expr<'tcx>,
         expected_expr: &mut Option<&'tcx hir::Expr<'tcx>>,
     ) {
-        let Some(expected_expr) = expected_expr else { return; };
+        let Some(expected_expr) = expected_expr else {
+            return;
+        };
 
         if !found_expr.span.eq_ctxt(expected_expr.span) {
             return;
@@ -121,11 +123,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let hir::ExprKind::Unary(
             hir::UnOp::Deref,
             hir::Expr { kind: hir::ExprKind::Path(found_path), .. },
-        ) = found_expr.kind else { return; };
+        ) = found_expr.kind
+        else {
+            return;
+        };
         let hir::ExprKind::Unary(
             hir::UnOp::Deref,
             hir::Expr { kind: hir::ExprKind::Path(expected_path), .. },
-        ) = expected_expr.kind else { return; };
+        ) = expected_expr.kind
+        else {
+            return;
+        };
 
         for (path, name, idx, var) in [
             (expected_path, "left_val", 0, expected_expr),
@@ -285,16 +293,26 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     ) -> bool {
         let hir = self.tcx.hir();
 
-        let hir::ExprKind::Path(hir::QPath::Resolved(None, p)) = expr.kind else { return false; };
-        let [hir::PathSegment { ident, args: None, .. }] = p.segments else { return false; };
-        let hir::def::Res::Local(local_hir_id) = p.res else { return false; };
-        let hir::Node::Pat(pat) = hir.get(local_hir_id) else { return false; };
+        let hir::ExprKind::Path(hir::QPath::Resolved(None, p)) = expr.kind else {
+            return false;
+        };
+        let [hir::PathSegment { ident, args: None, .. }] = p.segments else {
+            return false;
+        };
+        let hir::def::Res::Local(local_hir_id) = p.res else {
+            return false;
+        };
+        let hir::Node::Pat(pat) = hir.get(local_hir_id) else {
+            return false;
+        };
         let (init_ty_hir_id, init) = match hir.get_parent(pat.hir_id) {
             hir::Node::Local(hir::Local { ty: Some(ty), init, .. }) => (ty.hir_id, *init),
             hir::Node::Local(hir::Local { init: Some(init), .. }) => (init.hir_id, Some(*init)),
             _ => return false,
         };
-        let Some(init_ty) = self.node_ty_opt(init_ty_hir_id) else { return false; };
+        let Some(init_ty) = self.node_ty_opt(init_ty_hir_id) else {
+            return false;
+        };
 
         // Locate all the usages of the relevant binding.
         struct FindExprs<'tcx> {
@@ -413,14 +431,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             // Bindings always update their recorded type after the fact, so we
             // need to look at the *following* usage's type to see when the
             // binding became incompatible.
-            let [binding, next_usage] = *window else { continue; };
+            let [binding, next_usage] = *window else {
+                continue;
+            };
 
             // Don't go past the binding (always gonna be a nonsense label if so)
             if binding.hir_id == expr.hir_id {
                 break;
             }
 
-            let Some(next_use_ty) = self.node_ty_opt(next_usage.hir_id) else { continue; };
+            let Some(next_use_ty) = self.node_ty_opt(next_usage.hir_id) else {
+                continue;
+            };
 
             // If the type is not constrained in a way making it not possible to
             // equate with `expected_ty` by this point, skip.
@@ -634,27 +656,36 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         error: Option<TypeError<'tcx>>,
     ) {
         let parent = self.tcx.hir().parent_id(expr.hir_id);
-        let Some(TypeError::Sorts(ExpectedFound { expected, .. })) = error else {return;};
-        let Some(hir::Node::Expr(hir::Expr {
-                    kind: hir::ExprKind::Assign(lhs, rhs, _), ..
-                })) = self.tcx.hir().find(parent) else {return; };
+        let Some(TypeError::Sorts(ExpectedFound { expected, .. })) = error else {
+            return;
+        };
+        let Some(hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Assign(lhs, rhs, _), .. })) =
+            self.tcx.hir().find(parent)
+        else {
+            return;
+        };
         if rhs.hir_id != expr.hir_id || expected.is_closure() {
             return;
         }
-        let hir::ExprKind::Unary(hir::UnOp::Deref, deref) = lhs.kind else { return; };
-        let hir::ExprKind::MethodCall(path, base, args, _) = deref.kind else { return; };
-        let Some(self_ty) = self.typeck_results.borrow().expr_ty_adjusted_opt(base) else { return; };
+        let hir::ExprKind::Unary(hir::UnOp::Deref, deref) = lhs.kind else {
+            return;
+        };
+        let hir::ExprKind::MethodCall(path, base, args, _) = deref.kind else {
+            return;
+        };
+        let Some(self_ty) = self.typeck_results.borrow().expr_ty_adjusted_opt(base) else {
+            return;
+        };
 
-        let Ok(pick) = self
-            .lookup_probe_for_diagnostic(
-                path.ident,
-                self_ty,
-                deref,
-                probe::ProbeScope::TraitsInScope,
-                None,
-            ) else {
-                return;
-            };
+        let Ok(pick) = self.lookup_probe_for_diagnostic(
+            path.ident,
+            self_ty,
+            deref,
+            probe::ProbeScope::TraitsInScope,
+            None,
+        ) else {
+            return;
+        };
         let in_scope_methods = self.probe_for_name_many(
             probe::Mode::MethodCall,
             path.ident,
@@ -681,7 +712,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             .filter(|c| c.item.def_id != pick.item.def_id)
             .map(|c| {
                 let m = c.item;
-                let substs = ty::InternalSubsts::for_item(self.tcx, m.def_id, |param, _| {
+                let generic_args = ty::GenericArgs::for_item(self.tcx, m.def_id, |param, _| {
                     self.var_for_def(deref.span, param)
                 });
                 let mutability =
@@ -696,7 +727,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         format!(
                             "{}({}",
                             with_no_trimmed_paths!(
-                                self.tcx.def_path_str_with_substs(m.def_id, substs,)
+                                self.tcx.def_path_str_with_args(m.def_id, generic_args,)
                             ),
                             mutability,
                         ),
@@ -793,8 +824,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         expected: Ty<'tcx>,
         found: Ty<'tcx>,
     ) -> bool {
-        let ty::Adt(e, substs_e) = expected.kind() else { return false; };
-        let ty::Adt(f, substs_f) = found.kind() else { return false; };
+        let ty::Adt(e, args_e) = expected.kind() else {
+            return false;
+        };
+        let ty::Adt(f, args_f) = found.kind() else {
+            return false;
+        };
         if e.did() != f.did() {
             return false;
         }
@@ -811,8 +846,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         } else {
             return false;
         }
-        let e = substs_e.type_at(1);
-        let f = substs_f.type_at(1);
+        let e = args_e.type_at(1);
+        let f = args_f.type_at(1);
         if self
             .infcx
             .type_implements_trait(
@@ -845,7 +880,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         expected: Ty<'tcx>,
         expr_ty: Ty<'tcx>,
     ) -> bool {
-        if let ty::Adt(expected_adt, substs) = expected.kind() {
+        if let ty::Adt(expected_adt, args) = expected.kind() {
             if let hir::ExprKind::Field(base, ident) = expr.kind {
                 let base_ty = self.typeck_results.borrow().expr_ty(base);
                 if self.can_eq(self.param_env, base_ty, expected)
@@ -944,7 +979,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     let note_about_variant_field_privacy = (field_is_local && !field_is_accessible)
                         .then(|| " (its field is private, but it's local to this crate and its privacy can be changed)".to_string());
 
-                    let sole_field_ty = sole_field.ty(self.tcx, substs);
+                    let sole_field_ty = sole_field.ty(self.tcx, args);
                     if self.can_coerce(expr_ty, sole_field_ty) {
                         let variant_path =
                             with_no_trimmed_paths!(self.tcx.def_path_str(variant.def_id));
@@ -962,7 +997,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 .collect();
 
             let suggestions_for = |variant: &_, ctor_kind, field_name| {
-                let prefix = match self.maybe_get_struct_pattern_shorthand_field(expr) {
+                let prefix = match self.tcx.hir().maybe_get_struct_pattern_shorthand_field(expr) {
                     Some(ident) => format!("{ident}: "),
                     None => String::new(),
                 };
@@ -1037,9 +1072,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let tcx = self.tcx;
         let (adt, unwrap) = match expected.kind() {
             // In case Option<NonZero*> is wanted, but * is provided, suggest calling new
-            ty::Adt(adt, substs) if tcx.is_diagnostic_item(sym::Option, adt.did()) => {
+            ty::Adt(adt, args) if tcx.is_diagnostic_item(sym::Option, adt.did()) => {
                 // Unwrap option
-                let ty::Adt(adt, _) = substs.type_at(0).kind() else { return false; };
+                let ty::Adt(adt, _) = args.type_at(0).kind() else {
+                    return false;
+                };
 
                 (adt, "")
             }
@@ -1061,10 +1098,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             (sym::NonZeroI128, tcx.types.i128),
         ];
 
-        let Some((s, _)) = map
-            .iter()
-            .find(|&&(s, t)| self.tcx.is_diagnostic_item(s, adt.did()) && self.can_coerce(expr_ty, t))
-            else { return false; };
+        let Some((s, _)) = map.iter().find(|&&(s, t)| {
+            self.tcx.is_diagnostic_item(s, adt.did()) && self.can_coerce(expr_ty, t)
+        }) else {
+            return false;
+        };
 
         let path = self.tcx.def_path_str(adt.non_enum_variant().def_id);
 
@@ -1152,7 +1190,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         };
 
         let local_parent = self.tcx.hir().parent_id(local_id);
-        let Some(Node::Param(hir::Param { hir_id: param_hir_id, .. })) = self.tcx.hir().find(local_parent) else {
+        let Some(Node::Param(hir::Param { hir_id: param_hir_id, .. })) =
+            self.tcx.hir().find(local_parent)
+        else {
             return None;
         };
 
@@ -1161,7 +1201,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             hir_id: expr_hir_id,
             kind: hir::ExprKind::Closure(hir::Closure { fn_decl: closure_fn_decl, .. }),
             ..
-        })) = self.tcx.hir().find(param_parent) else {
+        })) = self.tcx.hir().find(param_parent)
+        else {
             return None;
         };
 
@@ -1174,7 +1215,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 ..
             })),
             1,
-        ) = (hir, closure_params_len) else {
+        ) = (hir, closure_params_len)
+        else {
             return None;
         };
 
@@ -1198,39 +1240,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         }
     }
 
-    pub(crate) fn maybe_get_struct_pattern_shorthand_field(
-        &self,
-        expr: &hir::Expr<'_>,
-    ) -> Option<Symbol> {
-        let hir = self.tcx.hir();
-        let local = match expr {
-            hir::Expr {
-                kind:
-                    hir::ExprKind::Path(hir::QPath::Resolved(
-                        None,
-                        hir::Path {
-                            res: hir::def::Res::Local(_),
-                            segments: [hir::PathSegment { ident, .. }],
-                            ..
-                        },
-                    )),
-                ..
-            } => Some(ident),
-            _ => None,
-        }?;
-
-        match hir.find_parent(expr.hir_id)? {
-            Node::ExprField(field) => {
-                if field.ident.name == local.name && field.is_shorthand {
-                    return Some(local.name);
-                }
-            }
-            _ => {}
-        }
-
-        None
-    }
-
     /// If the given `HirId` corresponds to a block with a trailing expression, return that expression
     pub(crate) fn maybe_get_block_expr(
         &self,
@@ -1425,7 +1434,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         ));
                     }
 
-                    let prefix = match self.maybe_get_struct_pattern_shorthand_field(expr) {
+                    let prefix = match self.tcx.hir().maybe_get_struct_pattern_shorthand_field(expr) {
                         Some(ident) => format!("{ident}: "),
                         None => String::new(),
                     };
@@ -1619,7 +1628,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             )
                         };
 
-                        let prefix = match self.maybe_get_struct_pattern_shorthand_field(expr) {
+                        let prefix = match self.tcx.hir().maybe_get_struct_pattern_shorthand_field(expr) {
                             Some(ident) => format!("{ident}: "),
                             None => String::new(),
                         };
@@ -2028,11 +2037,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         if !hir::is_range_literal(expr) {
             return;
         }
-        let hir::ExprKind::Struct(
-            hir::QPath::LangItem(LangItem::Range, ..),
-            [start, end],
-            _,
-        ) = expr.kind else { return; };
+        let hir::ExprKind::Struct(hir::QPath::LangItem(LangItem::Range, ..), [start, end], _) =
+            expr.kind
+        else {
+            return;
+        };
         let parent = self.tcx.hir().parent_id(expr.hir_id);
         if let Some(hir::Node::ExprField(_)) = self.tcx.hir().find(parent) {
             // Ignore `Foo { field: a..Default::default() }`
@@ -2048,8 +2057,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             // cannot guide the method probe.
             expectation = None;
         }
-        let hir::ExprKind::Call(method_name, _) = expr.kind else { return; };
-        let ty::Adt(adt, _) = checked_ty.kind() else { return; };
+        let hir::ExprKind::Call(method_name, _) = expr.kind else {
+            return;
+        };
+        let ty::Adt(adt, _) = checked_ty.kind() else {
+            return;
+        };
         if self.tcx.lang_items().range_struct() != Some(adt.did()) {
             return;
         }
@@ -2059,8 +2072,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             return;
         }
         // Check if start has method named end.
-        let hir::ExprKind::Path(hir::QPath::Resolved(None, p)) = method_name.kind else { return; };
-        let [hir::PathSegment { ident, .. }] = p.segments else { return; };
+        let hir::ExprKind::Path(hir::QPath::Resolved(None, p)) = method_name.kind else {
+            return;
+        };
+        let [hir::PathSegment { ident, .. }] = p.segments else {
+            return;
+        };
         let self_ty = self.typeck_results.borrow().expr_ty(start.expr);
         let Ok(_pick) = self.lookup_probe_for_diagnostic(
             *ident,
@@ -2068,7 +2085,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             expr,
             probe::ProbeScope::AllTraits,
             expectation,
-        ) else { return; };
+        ) else {
+            return;
+        };
         let mut sugg = ".";
         let mut span = start.expr.span.between(end.expr.span);
         if span.lo() + BytePos(2) == span.hi() {
@@ -2097,17 +2116,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         if !checked_ty.is_unit() {
             return;
         }
-        let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = expr.kind else { return; };
-        let hir::def::Res::Local(hir_id) = path.res else { return; };
+        let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = expr.kind else {
+            return;
+        };
+        let hir::def::Res::Local(hir_id) = path.res else {
+            return;
+        };
         let Some(hir::Node::Pat(pat)) = self.tcx.hir().find(hir_id) else {
             return;
         };
-        let Some(hir::Node::Local(hir::Local {
-            ty: None,
-            init: Some(init),
-            ..
-        })) = self.tcx.hir().find_parent(pat.hir_id) else { return; };
-        let hir::ExprKind::Block(block, None) = init.kind else { return; };
+        let Some(hir::Node::Local(hir::Local { ty: None, init: Some(init), .. })) =
+            self.tcx.hir().find_parent(pat.hir_id)
+        else {
+            return;
+        };
+        let hir::ExprKind::Block(block, None) = init.kind else {
+            return;
+        };
         if block.expr.is_some() {
             return;
         }
@@ -2115,8 +2140,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             err.span_label(block.span, "this empty block is missing a tail expression");
             return;
         };
-        let hir::StmtKind::Semi(tail_expr) = stmt.kind else { return; };
-        let Some(ty) = self.node_ty_opt(tail_expr.hir_id) else { return; };
+        let hir::StmtKind::Semi(tail_expr) = stmt.kind else {
+            return;
+        };
+        let Some(ty) = self.node_ty_opt(tail_expr.hir_id) else {
+            return;
+        };
         if self.can_eq(self.param_env, expected_ty, ty) {
             err.span_suggestion_short(
                 stmt.span.with_lo(tail_expr.span.hi()),
@@ -2135,7 +2164,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         expr: &hir::Expr<'_>,
         checked_ty: Ty<'tcx>,
     ) {
-        let Some(hir::Node::Expr(parent_expr)) = self.tcx.hir().find_parent(expr.hir_id) else { return; };
+        let Some(hir::Node::Expr(parent_expr)) = self.tcx.hir().find_parent(expr.hir_id) else {
+            return;
+        };
         enum CallableKind {
             Function,
             Method,
@@ -2151,7 +2182,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 return;
             }
             let fn_sig = fn_ty.fn_sig(self.tcx).skip_binder();
-            let Some(&arg) = fn_sig.inputs().get(arg_idx + if matches!(kind, CallableKind::Method) { 1 } else { 0 }) else { return; };
+            let Some(&arg) = fn_sig
+                .inputs()
+                .get(arg_idx + if matches!(kind, CallableKind::Method) { 1 } else { 0 })
+            else {
+                return;
+            };
             if matches!(arg.kind(), ty::Param(_))
                 && fn_sig.output().contains(arg)
                 && self.node_ty(args[arg_idx].hir_id) == checked_ty
@@ -2185,8 +2221,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         };
         match parent_expr.kind {
             hir::ExprKind::Call(fun, args) => {
-                let hir::ExprKind::Path(hir::QPath::Resolved(_, path)) = fun.kind else { return; };
-                let hir::def::Res::Def(kind, def_id) = path.res else { return; };
+                let hir::ExprKind::Path(hir::QPath::Resolved(_, path)) = fun.kind else {
+                    return;
+                };
+                let hir::def::Res::Def(kind, def_id) = path.res else {
+                    return;
+                };
                 let callable_kind = if matches!(kind, hir::def::DefKind::Ctor(_, _)) {
                     CallableKind::Constructor
                 } else {
@@ -2195,7 +2235,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 maybe_emit_help(def_id, path.segments[0].ident, args, callable_kind);
             }
             hir::ExprKind::MethodCall(method, _receiver, args, _span) => {
-                let Some(def_id) = self.typeck_results.borrow().type_dependent_def_id(parent_expr.hir_id) else { return; };
+                let Some(def_id) =
+                    self.typeck_results.borrow().type_dependent_def_id(parent_expr.hir_id)
+                else {
+                    return;
+                };
                 maybe_emit_help(def_id, method.ident, args, CallableKind::Method)
             }
             _ => return,
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index 72b29f7b6e9..29488c9011a 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -44,7 +44,7 @@ use rustc_infer::traits::ObligationCause;
 use rustc_middle::middle::stability;
 use rustc_middle::ty::adjustment::{Adjust, Adjustment, AllowTwoPhase};
 use rustc_middle::ty::error::TypeError::FieldMisMatch;
-use rustc_middle::ty::subst::SubstsRef;
+use rustc_middle::ty::GenericArgsRef;
 use rustc_middle::ty::{self, AdtKind, Ty, TypeVisitableExt};
 use rustc_session::errors::ExprParenthesesNeeded;
 use rustc_session::parse::feature_err;
@@ -593,8 +593,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         // We always require that the type provided as the value for
         // a type parameter outlives the moment of instantiation.
-        let substs = self.typeck_results.borrow().node_substs(expr.hir_id);
-        self.add_wf_bounds(substs, expr);
+        let args = self.typeck_results.borrow().node_args(expr.hir_id);
+        self.add_wf_bounds(args, expr);
 
         ty
     }
@@ -650,7 +650,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             let mut enclosing_breakables = self.enclosing_breakables.borrow_mut();
             let Some(ctxt) = enclosing_breakables.opt_find_breakable(target_id) else {
                 // Avoid ICE when `break` is inside a closure (#65383).
-                return Ty::new_error_with_message(tcx,
+                return Ty::new_error_with_message(
+                    tcx,
                     expr.span,
                     "break was outside loop, but no error was emitted",
                 );
@@ -1280,7 +1281,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 // We could add a "consider `foo::<params>`" suggestion here, but I wasn't able to
                 // trigger this codepath causing `structurally_resolve_type` to emit an error.
 
-                self.enforce_context_effects(expr.hir_id, expr.span, method.def_id, method.substs);
+                self.enforce_context_effects(expr.hir_id, expr.span, method.def_id, method.args);
                 self.write_method_call(expr.hir_id, method);
                 Ok(method)
             }
@@ -1390,11 +1391,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let parent_node = self.tcx.hir().parent_iter(expr.hir_id).find(|(_, node)| {
             !matches!(node, hir::Node::Expr(hir::Expr { kind: hir::ExprKind::AddrOf(..), .. }))
         });
-        let Some((_,
+        let Some((
+            _,
             hir::Node::Local(hir::Local { ty: Some(ty), .. })
-            | hir::Node::Item(hir::Item { kind: hir::ItemKind::Const(ty, _), .. }))
-        ) = parent_node else {
-            return
+            | hir::Node::Item(hir::Item { kind: hir::ItemKind::Const(ty, _), .. }),
+        )) = parent_node
+        else {
+            return;
         };
         if let hir::TyKind::Array(_, length) = ty.peel_refs().kind
             && let hir::ArrayLen::Body(hir::AnonConst { hir_id, .. }) = length
@@ -1617,7 +1620,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         // re-link the regions that EIfEO can erase.
         self.demand_eqtype(span, adt_ty_hint, adt_ty);
 
-        let ty::Adt(adt, substs) = adt_ty.kind() else {
+        let ty::Adt(adt, args) = adt_ty.kind() else {
             span_bug!(span, "non-ADT passed to check_expr_struct_fields");
         };
         let adt_kind = adt.adt_kind();
@@ -1646,7 +1649,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     tcx.check_stability(v_field.did, Some(expr_id), field.span, None);
                 }
 
-                self.field_ty(field.span, v_field, substs)
+                self.field_ty(field.span, v_field, args)
             } else {
                 error_happened = true;
                 let guar = if let Some(prev_span) = seen_fields.get(&ident) {
@@ -1678,7 +1681,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             if let Some(mut diag) = diag {
                 if idx == ast_fields.len() - 1 {
                     if remaining_fields.is_empty() {
-                        self.suggest_fru_from_range(field, variant, substs, &mut diag);
+                        self.suggest_fru_from_range(field, variant, args, &mut diag);
                         diag.emit();
                     } else {
                         diag.stash(field.span, StashKey::MaybeFruTypo);
@@ -1718,7 +1721,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             let fru_tys = if self.tcx.features().type_changing_struct_update {
                 if adt.is_struct() {
                     // Make some fresh substitutions for our ADT type.
-                    let fresh_substs = self.fresh_substs_for_item(base_expr.span, adt.did());
+                    let fresh_args = self.fresh_args_for_item(base_expr.span, adt.did());
                     // We do subtyping on the FRU fields first, so we can
                     // learn exactly what types we expect the base expr
                     // needs constrained to be compatible with the struct
@@ -1727,13 +1730,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         .fields
                         .iter()
                         .map(|f| {
-                            let fru_ty = self.normalize(
-                                expr_span,
-                                self.field_ty(base_expr.span, f, fresh_substs),
-                            );
+                            let fru_ty = self
+                                .normalize(expr_span, self.field_ty(base_expr.span, f, fresh_args));
                             let ident = self.tcx.adjust_ident(f.ident(self.tcx), variant.def_id);
                             if let Some(_) = remaining_fields.remove(&ident) {
-                                let target_ty = self.field_ty(base_expr.span, f, substs);
+                                let target_ty = self.field_ty(base_expr.span, f, args);
                                 let cause = self.misc(base_expr.span);
                                 match self.at(&cause, self.param_env).sup(
                                     DefineOpaqueTypes::No,
@@ -1760,7 +1761,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             self.resolve_vars_if_possible(fru_ty)
                         })
                         .collect();
-                    // The use of fresh substs that we have subtyped against
+                    // The use of fresh args that we have subtyped against
                     // our base ADT type's fields allows us to guide inference
                     // along so that, e.g.
                     // ```
@@ -1778,7 +1779,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     // `MyStruct<'a, _, F2, C>`, as opposed to just `_`...
                     // This is important to allow coercions to happen in
                     // `other_struct` itself. See `coerce-in-base-expr.rs`.
-                    let fresh_base_ty = Ty::new_adt(self.tcx, *adt, fresh_substs);
+                    let fresh_base_ty = Ty::new_adt(self.tcx, *adt, fresh_args);
                     self.check_expr_has_type_or_error(
                         base_expr,
                         self.resolve_vars_if_possible(fresh_base_ty),
@@ -1810,10 +1811,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     }
                 });
                 match adt_ty.kind() {
-                    ty::Adt(adt, substs) if adt.is_struct() => variant
+                    ty::Adt(adt, args) if adt.is_struct() => variant
                         .fields
                         .iter()
-                        .map(|f| self.normalize(expr_span, f.ty(self.tcx, substs)))
+                        .map(|f| self.normalize(expr_span, f.ty(self.tcx, args)))
                         .collect(),
                     _ => {
                         self.tcx
@@ -1841,7 +1842,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     remaining_fields,
                     variant,
                     ast_fields,
-                    substs,
+                    args,
                 );
             }
         }
@@ -1878,7 +1879,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         remaining_fields: FxHashMap<Ident, (FieldIdx, &ty::FieldDef)>,
         variant: &'tcx ty::VariantDef,
         ast_fields: &'tcx [hir::ExprField<'tcx>],
-        substs: SubstsRef<'tcx>,
+        args: GenericArgsRef<'tcx>,
     ) {
         let len = remaining_fields.len();
 
@@ -1917,7 +1918,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         err.span_label(span, format!("missing {remaining_fields_names}{truncated_fields_error}"));
 
         if let Some(last) = ast_fields.last() {
-            self.suggest_fru_from_range(last, variant, substs, &mut err);
+            self.suggest_fru_from_range(last, variant, args, &mut err);
         }
 
         err.emit();
@@ -1929,7 +1930,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         &self,
         last_expr_field: &hir::ExprField<'tcx>,
         variant: &ty::VariantDef,
-        substs: SubstsRef<'tcx>,
+        args: GenericArgsRef<'tcx>,
         err: &mut Diagnostic,
     ) {
         // I don't use 'is_range_literal' because only double-sided, half-open ranges count.
@@ -1942,7 +1943,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 variant.fields.iter().find(|field| field.ident(self.tcx) == last_expr_field.ident)
             && let range_def_id = self.tcx.lang_items().range_struct()
             && variant_field
-                .and_then(|field| field.ty(self.tcx, substs).ty_adt_def())
+                .and_then(|field| field.ty(self.tcx, args).ty_adt_def())
                 .map(|adt| adt.did())
                 != range_def_id
         {
@@ -2265,7 +2266,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         while let Some((deref_base_ty, _)) = autoderef.next() {
             debug!("deref_base_ty: {:?}", deref_base_ty);
             match deref_base_ty.kind() {
-                ty::Adt(base_def, substs) if !base_def.is_enum() => {
+                ty::Adt(base_def, args) if !base_def.is_enum() => {
                     debug!("struct named {:?}", deref_base_ty);
                     let body_hir_id = self.tcx.hir().local_def_id_to_hir_id(self.body_id);
                     let (ident, def_scope) =
@@ -2275,7 +2276,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         .iter_enumerated()
                         .find(|(_, f)| f.ident(self.tcx).normalize_to_macros_2_0() == ident)
                     {
-                        let field_ty = self.field_ty(expr.span, field, substs);
+                        let field_ty = self.field_ty(expr.span, field, args);
                         // Save the index of all fields regardless of their visibility in case
                         // of error recovery.
                         self.write_field_index(expr.hir_id, index);
@@ -2416,7 +2417,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         base: &'tcx hir::Expr<'tcx>,
         ty: Ty<'tcx>,
     ) {
-        let Some(output_ty) = self.get_impl_future_output_ty(ty) else { return; };
+        let Some(output_ty) = self.get_impl_future_output_ty(ty) else {
+            return;
+        };
         let mut add_label = true;
         if let ty::Adt(def, _) = output_ty.kind() {
             // no field access on enum type
@@ -2711,7 +2714,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         // try to add a suggestion in case the field is a nested field of a field of the Adt
         let mod_id = self.tcx.parent_module(id).to_def_id();
-        if let Some((fields, substs)) =
+        if let Some((fields, args)) =
             self.get_field_candidates_considering_privacy(span, expr_t, mod_id)
         {
             let candidate_fields: Vec<_> = fields
@@ -2720,7 +2723,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         span,
                         &|candidate_field, _| candidate_field.ident(self.tcx()) == field,
                         candidate_field,
-                        substs,
+                        args,
                         vec![],
                         mod_id,
                     )
@@ -2775,12 +2778,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         span: Span,
         base_ty: Ty<'tcx>,
         mod_id: DefId,
-    ) -> Option<(impl Iterator<Item = &'tcx ty::FieldDef> + 'tcx, SubstsRef<'tcx>)> {
+    ) -> Option<(impl Iterator<Item = &'tcx ty::FieldDef> + 'tcx, GenericArgsRef<'tcx>)> {
         debug!("get_field_candidates(span: {:?}, base_t: {:?}", span, base_ty);
 
         for (base_t, _) in self.autoderef(span, base_ty) {
             match base_t.kind() {
-                ty::Adt(base_def, substs) if !base_def.is_enum() => {
+                ty::Adt(base_def, args) if !base_def.is_enum() => {
                     let tcx = self.tcx;
                     let fields = &base_def.non_enum_variant().fields;
                     // Some struct, e.g. some that impl `Deref`, have all private fields
@@ -2795,7 +2798,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             .filter(move |field| field.vis.is_accessible_from(mod_id, tcx))
                             // For compile-time reasons put a limit on number of fields we search
                             .take(100),
-                        substs,
+                        args,
                     ));
                 }
                 _ => {}
@@ -2811,7 +2814,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         span: Span,
         matches: &impl Fn(&ty::FieldDef, Ty<'tcx>) -> bool,
         candidate_field: &ty::FieldDef,
-        subst: SubstsRef<'tcx>,
+        subst: GenericArgsRef<'tcx>,
         mut field_path: Vec<Ident>,
         mod_id: DefId,
     ) -> Option<Vec<Ident>> {
@@ -2970,9 +2973,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         self.commit_if_ok(|_| {
             let ocx = ObligationCtxt::new(self);
-            let impl_substs = self.fresh_substs_for_item(base_expr.span, impl_def_id);
+            let impl_args = self.fresh_args_for_item(base_expr.span, impl_def_id);
             let impl_trait_ref =
-                self.tcx.impl_trait_ref(impl_def_id).unwrap().subst(self.tcx, impl_substs);
+                self.tcx.impl_trait_ref(impl_def_id).unwrap().instantiate(self.tcx, impl_args);
             let cause = self.misc(base_expr.span);
 
             // Match the impl self type against the base ty. If this fails,
@@ -3004,7 +3007,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     )
                 },
                 self.param_env,
-                self.tcx.predicates_of(impl_def_id).instantiate(self.tcx, impl_substs),
+                self.tcx.predicates_of(impl_def_id).instantiate(self.tcx, impl_args),
             ));
 
             // Normalize the output type, which we can use later on as the
@@ -3012,7 +3015,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             let element_ty = ocx.normalize(
                 &cause,
                 self.param_env,
-                Ty::new_projection(self.tcx, index_trait_output_def_id, impl_trait_ref.substs),
+                Ty::new_projection(self.tcx, index_trait_output_def_id, impl_trait_ref.args),
             );
 
             let errors = ocx.select_where_possible();
@@ -3020,7 +3023,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             // will still delay a span bug in `report_fulfillment_errors`.
             Ok::<_, NoSolution>((
                 self.err_ctxt().report_fulfillment_errors(&errors),
-                impl_trait_ref.substs.type_at(1),
+                impl_trait_ref.args.type_at(1),
                 element_ty,
             ))
         })
@@ -3152,7 +3155,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             let container = self.structurally_resolve_type(expr.span, current_container);
 
             match container.kind() {
-                ty::Adt(container_def, substs) if !container_def.is_enum() => {
+                ty::Adt(container_def, args) if !container_def.is_enum() => {
                     let block = self.tcx.hir().local_def_id_to_hir_id(self.body_id);
                     let (ident, def_scope) =
                         self.tcx.adjust_ident_and_get_scope(field, container_def.did(), block);
@@ -3162,7 +3165,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         .iter_enumerated()
                         .find(|(_, f)| f.ident(self.tcx).normalize_to_macros_2_0() == ident)
                     {
-                        let field_ty = self.field_ty(expr.span, field, substs);
+                        let field_ty = self.field_ty(expr.span, field, args);
 
                         // FIXME: DSTs with static alignment should be allowed
                         self.require_type_is_sized(field_ty, expr.span, traits::MiscObligation);
diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
index 0d2e0602e1c..a59061cbf67 100644
--- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
+++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
@@ -549,7 +549,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
         // Select just those fields of the `with`
         // expression that will actually be used
         match with_place.place.ty().kind() {
-            ty::Adt(adt, substs) if adt.is_struct() => {
+            ty::Adt(adt, args) if adt.is_struct() => {
                 // Consume those fields of the with expression that are needed.
                 for (f_index, with_field) in adt.non_enum_variant().fields.iter_enumerated() {
                     let is_mentioned = fields
@@ -559,7 +559,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
                         let field_place = self.mc.cat_projection(
                             &*with_expr,
                             with_place.clone(),
-                            with_field.ty(self.tcx(), substs),
+                            with_field.ty(self.tcx(), args),
                             ProjectionKind::Field(f_index, FIRST_VARIANT),
                         );
                         self.delegate_consume(&field_place, field_place.hir_id);
diff --git a/compiler/rustc_hir_typeck/src/fallback.rs b/compiler/rustc_hir_typeck/src/fallback.rs
index a76db6e73a1..5b5986a349f 100644
--- a/compiler/rustc_hir_typeck/src/fallback.rs
+++ b/compiler/rustc_hir_typeck/src/fallback.rs
@@ -1,8 +1,8 @@
 use crate::FnCtxt;
 use rustc_data_structures::{
-    fx::{FxHashMap, FxHashSet},
     graph::WithSuccessors,
     graph::{iterate::DepthFirstSearch, vec_graph::VecGraph},
+    unord::{UnordBag, UnordMap, UnordSet},
 };
 use rustc_middle::ty::{self, Ty};
 
@@ -83,7 +83,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
     fn fallback_if_possible(
         &self,
         ty: Ty<'tcx>,
-        diverging_fallback: &FxHashMap<Ty<'tcx>, Ty<'tcx>>,
+        diverging_fallback: &UnordMap<Ty<'tcx>, Ty<'tcx>>,
     ) {
         // Careful: we do NOT shallow-resolve `ty`. We know that `ty`
         // is an unsolved variable, and we determine its fallback
@@ -193,7 +193,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
     fn calculate_diverging_fallback(
         &self,
         unsolved_variables: &[Ty<'tcx>],
-    ) -> FxHashMap<Ty<'tcx>, Ty<'tcx>> {
+    ) -> UnordMap<Ty<'tcx>, Ty<'tcx>> {
         debug!("calculate_diverging_fallback({:?})", unsolved_variables);
 
         // Construct a coercion graph where an edge `A -> B` indicates
@@ -210,10 +210,10 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
         //
         // These variables are the ones that are targets for fallback to
         // either `!` or `()`.
-        let diverging_roots: FxHashSet<ty::TyVid> = self
+        let diverging_roots: UnordSet<ty::TyVid> = self
             .diverging_type_vars
             .borrow()
-            .iter()
+            .items()
             .map(|&ty| self.shallow_resolve(ty))
             .filter_map(|ty| ty.ty_vid())
             .map(|vid| self.root_var(vid))
@@ -284,8 +284,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
         // For each diverging variable, figure out whether it can
         // reach a member of N. If so, it falls back to `()`. Else
         // `!`.
-        let mut diverging_fallback = FxHashMap::default();
-        diverging_fallback.reserve(diverging_vids.len());
+        let mut diverging_fallback = UnordMap::with_capacity(diverging_vids.len());
         for &diverging_vid in &diverging_vids {
             let diverging_ty = Ty::new_var(self.tcx, diverging_vid);
             let root_vid = self.root_var(diverging_vid);
@@ -293,14 +292,19 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
                 .depth_first_search(root_vid)
                 .any(|n| roots_reachable_from_non_diverging.visited(n));
 
-            let mut found_infer_var_info = ty::InferVarInfo { self_in_trait: false, output: false };
+            let infer_var_infos: UnordBag<_> = self
+                .inh
+                .infer_var_info
+                .borrow()
+                .items()
+                .filter(|&(vid, _)| self.infcx.root_var(*vid) == root_vid)
+                .map(|(_, info)| *info)
+                .collect();
 
-            for (vid, info) in self.inh.infer_var_info.borrow().iter() {
-                if self.infcx.root_var(*vid) == root_vid {
-                    found_infer_var_info.self_in_trait |= info.self_in_trait;
-                    found_infer_var_info.output |= info.output;
-                }
-            }
+            let found_infer_var_info = ty::InferVarInfo {
+                self_in_trait: infer_var_infos.items().any(|info| info.self_in_trait),
+                output: infer_var_infos.items().any(|info| info.output),
+            };
 
             if found_infer_var_info.self_in_trait && found_infer_var_info.output {
                 // This case falls back to () to ensure that the code pattern in
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
index 9a80a9c9303..bd7e7a671e6 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
@@ -12,7 +12,7 @@ use rustc_hir::def_id::DefId;
 use rustc_hir::lang_items::LangItem;
 use rustc_hir::{ExprKind, GenericArg, Node, QPath};
 use rustc_hir_analysis::astconv::generics::{
-    check_generic_arg_count_for_call, create_substs_for_generic_args,
+    check_generic_arg_count_for_call, create_args_for_parent_generic_args,
 };
 use rustc_hir_analysis::astconv::{
     AstConv, CreateSubstsForGenericArgsCtxt, ExplicitLateBound, GenericArgCountMismatch,
@@ -28,7 +28,7 @@ use rustc_middle::ty::visit::{TypeVisitable, TypeVisitableExt};
 use rustc_middle::ty::{
     self, AdtKind, CanonicalUserType, GenericParamDefKind, Ty, TyCtxt, UserType,
 };
-use rustc_middle::ty::{GenericArgKind, SubstsRef, UserSelfTy, UserSubsts};
+use rustc_middle::ty::{GenericArgKind, GenericArgsRef, UserArgs, UserSelfTy};
 use rustc_session::lint;
 use rustc_span::def_id::LocalDefId;
 use rustc_span::hygiene::DesugaringKind;
@@ -169,18 +169,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     #[instrument(level = "debug", skip(self))]
     pub fn write_method_call(&self, hir_id: hir::HirId, method: MethodCallee<'tcx>) {
         self.write_resolution(hir_id, Ok((DefKind::AssocFn, method.def_id)));
-        self.write_substs(hir_id, method.substs);
+        self.write_args(hir_id, method.args);
     }
 
-    pub fn write_substs(&self, node_id: hir::HirId, substs: SubstsRef<'tcx>) {
-        if !substs.is_empty() {
-            debug!("write_substs({:?}, {:?}) in fcx {}", node_id, substs, self.tag());
+    pub fn write_args(&self, node_id: hir::HirId, args: GenericArgsRef<'tcx>) {
+        if !args.is_empty() {
+            debug!("write_args({:?}, {:?}) in fcx {}", node_id, args, self.tag());
 
-            self.typeck_results.borrow_mut().node_substs_mut().insert(node_id, substs);
+            self.typeck_results.borrow_mut().node_args_mut().insert(node_id, args);
         }
     }
 
-    /// Given the substs that we just converted from the HIR, try to
+    /// Given the args that we just converted from the HIR, try to
     /// canonicalize them and store them as user-given substitutions
     /// (i.e., substitutions that must be respected by the NLL check).
     ///
@@ -188,19 +188,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     /// occurred**, so that annotations like `Vec<_>` are preserved
     /// properly.
     #[instrument(skip(self), level = "debug")]
-    pub fn write_user_type_annotation_from_substs(
+    pub fn write_user_type_annotation_from_args(
         &self,
         hir_id: hir::HirId,
         def_id: DefId,
-        substs: SubstsRef<'tcx>,
+        args: GenericArgsRef<'tcx>,
         user_self_ty: Option<UserSelfTy<'tcx>>,
     ) {
         debug!("fcx {}", self.tag());
 
-        if Self::can_contain_user_lifetime_bounds((substs, user_self_ty)) {
+        if Self::can_contain_user_lifetime_bounds((args, user_self_ty)) {
             let canonicalized = self.canonicalize_user_type_annotation(UserType::TypeOf(
                 def_id,
-                UserSubsts { substs, user_self_ty },
+                UserArgs { args, user_self_ty },
             ));
             debug!(?canonicalized);
             self.write_user_type_annotation(hir_id, canonicalized);
@@ -221,7 +221,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 .user_provided_types_mut()
                 .insert(hir_id, canonical_user_type_annotation);
         } else {
-            debug!("skipping identity substs");
+            debug!("skipping identity args");
         }
     }
 
@@ -306,12 +306,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         &self,
         span: Span,
         def_id: DefId,
-        substs: SubstsRef<'tcx>,
+        args: GenericArgsRef<'tcx>,
     ) -> ty::InstantiatedPredicates<'tcx> {
         let bounds = self.tcx.predicates_of(def_id);
-        let result = bounds.instantiate(self.tcx, substs);
+        let result = bounds.instantiate(self.tcx, args);
         let result = self.normalize(span, result);
-        debug!("instantiate_bounds(bounds={:?}, substs={:?}) = {:?}", bounds, substs, result);
+        debug!("instantiate_bounds(bounds={:?}, args={:?}) = {:?}", bounds, args, result);
         result
     }
 
@@ -397,11 +397,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         ty.normalized
     }
 
-    pub(super) fn user_substs_for_adt(ty: RawTy<'tcx>) -> UserSubsts<'tcx> {
+    pub(super) fn user_args_for_adt(ty: RawTy<'tcx>) -> UserArgs<'tcx> {
         match (ty.raw.kind(), ty.normalized.kind()) {
-            (ty::Adt(_, substs), _) => UserSubsts { substs, user_self_ty: None },
-            (_, ty::Adt(adt, substs)) => UserSubsts {
-                substs,
+            (ty::Adt(_, args), _) => UserArgs { args, user_self_ty: None },
+            (_, ty::Adt(adt, args)) => UserArgs {
+                args,
                 user_self_ty: Some(UserSelfTy { impl_def_id: adt.did(), self_ty: ty.raw }),
             },
             _ => bug!("non-adt type {:?}", ty),
@@ -489,9 +489,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         ));
     }
 
-    /// Registers obligations that all `substs` are well-formed.
-    pub fn add_wf_bounds(&self, substs: SubstsRef<'tcx>, expr: &hir::Expr<'_>) {
-        for arg in substs.iter().filter(|arg| {
+    /// Registers obligations that all `args` are well-formed.
+    pub fn add_wf_bounds(&self, args: GenericArgsRef<'tcx>, expr: &hir::Expr<'_>) {
+        for arg in args.iter().filter(|arg| {
             matches!(arg.unpack(), GenericArgKind::Type(..) | GenericArgKind::Const(..))
         }) {
             self.register_wf_obligation(arg, expr.span, traits::WellFormed(None));
@@ -505,9 +505,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         &self,
         span: Span,
         field: &'tcx ty::FieldDef,
-        substs: SubstsRef<'tcx>,
+        args: GenericArgsRef<'tcx>,
     ) -> Ty<'tcx> {
-        self.normalize(span, field.ty(self.tcx, substs))
+        self.normalize(span, field.ty(self.tcx, args))
     }
 
     pub(in super::super) fn resolve_rvalue_scopes(&self, def_id: DefId) {
@@ -554,11 +554,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             debug!(?expr_def_id);
 
             // Create the `GeneratorWitness` type that we will unify with `interior`.
-            let substs = ty::InternalSubsts::identity_for_item(
+            let args = ty::GenericArgs::identity_for_item(
                 self.tcx,
                 self.tcx.typeck_root_def_id(expr_def_id.to_def_id()),
             );
-            let witness = Ty::new_generator_witness_mir(self.tcx, expr_def_id.to_def_id(), substs);
+            let witness = Ty::new_generator_witness_mir(self.tcx, expr_def_id.to_def_id(), args);
 
             // Unify `interior` with `witness` and collect all the resulting obligations.
             let span = self.tcx.hir().body(body_id).value.span;
@@ -737,7 +737,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         // tests/ui/impl-trait/hidden-type-is-opaque-2.rs for examples that hit this path.
         if formal_ret.has_infer_types() {
             for ty in ret_ty.walk() {
-                if let ty::subst::GenericArgKind::Type(ty) = ty.unpack()
+                if let ty::GenericArgKind::Type(ty) = ty.unpack()
                     && let ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) = *ty.kind()
                     && let Some(def_id) = def_id.as_local()
                     && self.opaque_type_origin(def_id).is_some() {
@@ -784,8 +784,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         } else {
             self.tcx.type_of(def_id)
         };
-        let substs = self.fresh_substs_for_item(span, def_id);
-        let ty = item_ty.subst(self.tcx, substs);
+        let args = self.fresh_args_for_item(span, def_id);
+        let ty = item_ty.instantiate(self.tcx, args);
 
         self.write_resolution(hir_id, Ok((def_kind, def_id)));
 
@@ -802,9 +802,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             _ => None,
         };
         if let Some(code) = code {
-            self.add_required_obligations_with_code(span, def_id, substs, move |_, _| code.clone());
+            self.add_required_obligations_with_code(span, def_id, args, move |_, _| code.clone());
         } else {
-            self.add_required_obligations_for_hir(span, def_id, substs, hir_id);
+            self.add_required_obligations_for_hir(span, def_id, args, hir_id);
         }
 
         (Res::Def(def_kind, def_id), ty)
@@ -1205,8 +1205,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let has_self =
             path_segs.last().is_some_and(|PathSeg(def_id, _)| tcx.generics_of(*def_id).has_self);
 
-        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).subst_identity());
+        let (res, self_ctor_args) = if let Res::SelfCtor(impl_def_id) = res {
+            let ty =
+                self.handle_raw_ty(span, tcx.at(span).type_of(impl_def_id).instantiate_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();
@@ -1217,9 +1218,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             .emit_err(CtorIsPrivate { span, def: tcx.def_path_str(adt_def.did()) });
                     }
                     let new_res = Res::Def(DefKind::Ctor(CtorOf::Struct, ctor_kind), ctor_def_id);
-                    let user_substs = Self::user_substs_for_adt(ty);
-                    user_self_ty = user_substs.user_self_ty;
-                    (new_res, Some(user_substs.substs))
+                    let user_args = Self::user_args_for_adt(ty);
+                    user_self_ty = user_args.user_self_ty;
+                    (new_res, Some(user_args.args))
                 }
                 _ => {
                     let mut err = tcx.sess.struct_span_err(
@@ -1324,7 +1325,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
             fn inferred_kind(
                 &mut self,
-                substs: Option<&[ty::GenericArg<'tcx>]>,
+                args: Option<&[ty::GenericArg<'tcx>]>,
                 param: &ty::GenericParamDef,
                 infer_args: bool,
             ) -> ty::GenericArg<'tcx> {
@@ -1338,7 +1339,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.type_of(param.def_id).subst(tcx, substs.unwrap()).into()
+                            tcx.type_of(param.def_id).instantiate(tcx, args.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.
@@ -1349,7 +1350,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     }
                     GenericParamDefKind::Const { has_default } => {
                         if !infer_args && has_default {
-                            tcx.const_param_default(param.def_id).subst(tcx, substs.unwrap()).into()
+                            tcx.const_param_default(param.def_id)
+                                .instantiate(tcx, args.unwrap())
+                                .into()
                         } else {
                             self.fcx.var_for_def(self.span, param)
                         }
@@ -1358,8 +1361,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             }
         }
 
-        let substs_raw = self_ctor_substs.unwrap_or_else(|| {
-            create_substs_for_generic_args(
+        let args_raw = self_ctor_args.unwrap_or_else(|| {
+            create_args_for_parent_generic_args(
                 tcx,
                 def_id,
                 &[],
@@ -1376,20 +1379,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             )
         });
 
-        // First, store the "user substs" for later.
-        self.write_user_type_annotation_from_substs(hir_id, def_id, substs_raw, user_self_ty);
+        // First, store the "user args" for later.
+        self.write_user_type_annotation_from_args(hir_id, def_id, args_raw, user_self_ty);
 
         // Normalize only after registering type annotations.
-        let substs = self.normalize(span, substs_raw);
+        let args = self.normalize(span, args_raw);
 
-        self.add_required_obligations_for_hir(span, def_id, &substs, hir_id);
+        self.add_required_obligations_for_hir(span, def_id, &args, hir_id);
 
         // Substitute the values for the type parameters into the type of
         // the referenced item.
         let ty = tcx.type_of(def_id);
-        assert!(!substs.has_escaping_bound_vars());
+        assert!(!args.has_escaping_bound_vars());
         assert!(!ty.skip_binder().has_escaping_bound_vars());
-        let ty_substituted = self.normalize(span, ty.subst(tcx, substs));
+        let ty_substituted = self.normalize(span, ty.instantiate(tcx, args));
 
         if let Some(UserSelfTy { impl_def_id, self_ty }) = user_self_ty {
             // In the case of `Foo<T>::method` and `<Foo<T>>::method`, if `method`
@@ -1397,7 +1400,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.type_of(impl_def_id).subst(tcx, substs));
+            let impl_ty = self.normalize(span, tcx.type_of(impl_def_id).instantiate(tcx, args));
             let self_ty = self.normalize(span, self_ty);
             match self.at(&self.misc(span), self.param_env).eq(
                 DefineOpaqueTypes::No,
@@ -1419,7 +1422,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         }
 
         debug!("instantiate_value_path: type of {:?} is {:?}", hir_id, ty_substituted);
-        self.write_substs(hir_id, substs);
+        self.write_args(hir_id, args);
 
         (ty_substituted, res)
     }
@@ -1429,10 +1432,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         &self,
         span: Span,
         def_id: DefId,
-        substs: SubstsRef<'tcx>,
+        args: GenericArgsRef<'tcx>,
         hir_id: hir::HirId,
     ) {
-        self.add_required_obligations_with_code(span, def_id, substs, |idx, span| {
+        self.add_required_obligations_with_code(span, def_id, args, |idx, span| {
             if span.is_dummy() {
                 ObligationCauseCode::ExprItemObligation(def_id, hir_id, idx)
             } else {
@@ -1441,17 +1444,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         })
     }
 
-    #[instrument(level = "debug", skip(self, code, span, substs))]
+    #[instrument(level = "debug", skip(self, code, span, args))]
     fn add_required_obligations_with_code(
         &self,
         span: Span,
         def_id: DefId,
-        substs: SubstsRef<'tcx>,
+        args: GenericArgsRef<'tcx>,
         code: impl Fn(usize, Span) -> ObligationCauseCode<'tcx>,
     ) {
         let param_env = self.param_env;
 
-        let bounds = self.instantiate_bounds(span, def_id, &substs);
+        let bounds = self.instantiate_bounds(span, def_id, &args);
 
         for obligation in traits::predicates_for_generics(
             |idx, predicate_span| {
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 ed9bb4945af..15ca5808a93 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
@@ -14,19 +14,32 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         &self,
         error: &mut traits::FulfillmentError<'tcx>,
     ) -> bool {
-        let (traits::ExprItemObligation(def_id, hir_id, idx) | traits::ExprBindingObligation(def_id, _, hir_id, idx))
-            = *error.obligation.cause.code().peel_derives() else { return false; };
+        let (traits::ExprItemObligation(def_id, hir_id, idx)
+        | traits::ExprBindingObligation(def_id, _, hir_id, idx)) =
+            *error.obligation.cause.code().peel_derives()
+        else {
+            return false;
+        };
         let hir = self.tcx.hir();
-        let hir::Node::Expr(expr) = hir.get(hir_id) else { return false; };
+        let hir::Node::Expr(expr) = hir.get(hir_id) else {
+            return false;
+        };
 
-        let Some(unsubstituted_pred) =
-            self.tcx.predicates_of(def_id).instantiate_identity(self.tcx).predicates.into_iter().nth(idx)
-            else { return false; };
+        let Some(unsubstituted_pred) = self
+            .tcx
+            .predicates_of(def_id)
+            .instantiate_identity(self.tcx)
+            .predicates
+            .into_iter()
+            .nth(idx)
+        else {
+            return false;
+        };
 
         let generics = self.tcx.generics_of(def_id);
-        let predicate_substs = match unsubstituted_pred.kind().skip_binder() {
-            ty::ClauseKind::Trait(pred) => pred.trait_ref.substs.to_vec(),
-            ty::ClauseKind::Projection(pred) => pred.projection_ty.substs.to_vec(),
+        let predicate_args = match unsubstituted_pred.kind().skip_binder() {
+            ty::ClauseKind::Trait(pred) => pred.trait_ref.args.to_vec(),
+            ty::ClauseKind::Projection(pred) => pred.projection_ty.args.to_vec(),
             ty::ClauseKind::ConstArgHasType(arg, ty) => {
                 vec![ty.into(), arg.into()]
             }
@@ -35,7 +48,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         };
 
         let find_param_matching = |matches: &dyn Fn(ty::ParamTerm) -> bool| {
-            predicate_substs.iter().find_map(|arg| {
+            predicate_args.iter().find_map(|arg| {
                 arg.walk().find_map(|arg| {
                     if let ty::GenericArgKind::Type(ty) = arg.unpack()
                         && let ty::Param(param_ty) = *ty.kind()
@@ -225,18 +238,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         param_to_point_at: ty::GenericArg<'tcx>,
         segment: &hir::PathSegment<'tcx>,
     ) -> bool {
-        let own_substs = self
+        let own_args = self
             .tcx
             .generics_of(def_id)
-            .own_substs(ty::InternalSubsts::identity_for_item(self.tcx, def_id));
-        let Some((index, _)) = own_substs
-            .iter()
-            .enumerate()
-            .find(|(_, arg)| **arg == param_to_point_at) else { return false };
-        let Some(arg) = segment
-            .args()
-            .args
-            .get(index) else { return false; };
+            .own_args(ty::GenericArgs::identity_for_item(self.tcx, def_id));
+        let Some((index, _)) =
+            own_args.iter().enumerate().find(|(_, arg)| **arg == param_to_point_at)
+        else {
+            return false;
+        };
+        let Some(arg) = segment.args().args.get(index) else {
+            return false;
+        };
         error.obligation.cause.span = arg
             .span()
             .find_ancestor_in_same_ctxt(error.obligation.cause.span)
@@ -258,7 +271,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         origin.kind
                     && let generics = self.0.tcx.generics_of(self.1)
                     && let Some(index) = generics.param_def_id_to_index(self.0.tcx, def_id)
-                    && let Some(subst) = ty::InternalSubsts::identity_for_item(self.0.tcx, self.1)
+                    && let Some(subst) = ty::GenericArgs::identity_for_item(self.0.tcx, self.1)
                         .get(index as usize)
                 {
                     ControlFlow::Break(*subst)
@@ -298,13 +311,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     ) -> Option<(&'tcx hir::Expr<'tcx>, Ty<'tcx>)> {
         let def = self.tcx.adt_def(def_id);
 
-        let identity_substs = ty::InternalSubsts::identity_for_item(self.tcx, def_id);
+        let identity_args = ty::GenericArgs::identity_for_item(self.tcx, def_id);
         let fields_referencing_param: Vec<_> = def
             .variant_with_id(variant_def_id)
             .fields
             .iter()
             .filter(|field| {
-                let field_ty = field.ty(self.tcx, identity_substs);
+                let field_ty = field.ty(self.tcx, identity_args);
                 find_param_in_ty(field_ty.into(), param_to_point_at)
             })
             .collect();
@@ -315,7 +328,10 @@ 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).subst_identity()));
+                    return Some((
+                        expr_field.expr,
+                        self.tcx.type_of(field.did).instantiate_identity(),
+                    ));
                 }
             }
         }
@@ -342,7 +358,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).subst_identity();
+        let ty = self.tcx.type_of(def_id).instantiate_identity();
         if !ty.is_fn() {
             return false;
         }
@@ -484,7 +500,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             ty::TraitRef::new(
                 self.tcx,
                 obligation.impl_or_alias_def_id,
-                ty::InternalSubsts::identity_for_item(self.tcx, obligation.impl_or_alias_def_id),
+                ty::GenericArgs::identity_for_item(self.tcx, obligation.impl_or_alias_def_id),
             )
         } else {
             self.tcx
@@ -573,9 +589,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             // Find out which of `in_ty_elements` refer to `param`.
             // FIXME: It may be better to take the first if there are multiple,
             // just so that the error points to a smaller expression.
-            let Some((drill_expr, drill_ty)) = is_iterator_singleton(expr_elements.iter().zip( in_ty_elements.iter()).filter(|(_expr_elem, in_ty_elem)| {
-                find_param_in_ty((*in_ty_elem).into(), param)
-            })) else {
+            let Some((drill_expr, drill_ty)) =
+                is_iterator_singleton(expr_elements.iter().zip(in_ty_elements.iter()).filter(
+                    |(_expr_elem, in_ty_elem)| find_param_in_ty((*in_ty_elem).into(), param),
+                ))
+            else {
                 // The param is not mentioned, or it is mentioned in multiple indexes.
                 return Err(expr);
             };
@@ -594,7 +612,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         {
             // First, confirm that this struct is the same one as in the types, and if so,
             // find the right variant.
-            let Res::Def(expr_struct_def_kind, expr_struct_def_id) = self.typeck_results.borrow().qpath_res(expr_struct_path, expr.hir_id) else {
+            let Res::Def(expr_struct_def_kind, expr_struct_def_id) =
+                self.typeck_results.borrow().qpath_res(expr_struct_path, expr.hir_id)
+            else {
                 return Err(expr);
             };
 
@@ -621,16 +641,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
             // We need to know which of the generic parameters mentions our target param.
             // We expect that at least one of them does, since it is expected to be mentioned.
-            let Some((drill_generic_index, generic_argument_type)) =
-                is_iterator_singleton(
-                    in_ty_adt_generic_args.iter().enumerate().filter(
-                        |(_index, in_ty_generic)| {
-                            find_param_in_ty(*in_ty_generic, param)
-                        },
-                    ),
-                ) else {
-                    return Err(expr);
-                };
+            let Some((drill_generic_index, generic_argument_type)) = is_iterator_singleton(
+                in_ty_adt_generic_args
+                    .iter()
+                    .enumerate()
+                    .filter(|(_index, in_ty_generic)| find_param_in_ty(*in_ty_generic, param)),
+            ) else {
+                return Err(expr);
+            };
 
             let struct_generic_parameters: &ty::Generics = self.tcx.generics_of(in_ty_adt.did());
             if drill_generic_index >= struct_generic_parameters.params.len() {
@@ -703,7 +721,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             };
             // This is (possibly) a constructor call, like `Some(...)` or `MyStruct(a, b, c)`.
 
-            let Res::Def(expr_struct_def_kind, expr_ctor_def_id) = self.typeck_results.borrow().qpath_res(expr_callee_path, expr_callee.hir_id) else {
+            let Res::Def(expr_struct_def_kind, expr_ctor_def_id) =
+                self.typeck_results.borrow().qpath_res(expr_callee_path, expr_callee.hir_id)
+            else {
                 return Err(expr);
             };
 
@@ -744,16 +764,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
             // We need to know which of the generic parameters mentions our target param.
             // We expect that at least one of them does, since it is expected to be mentioned.
-            let Some((drill_generic_index, generic_argument_type)) =
-                is_iterator_singleton(
-                    in_ty_adt_generic_args.iter().enumerate().filter(
-                        |(_index, in_ty_generic)| {
-                            find_param_in_ty(*in_ty_generic, param)
-                        },
-                    ),
-                ) else {
-                    return Err(expr);
-                };
+            let Some((drill_generic_index, generic_argument_type)) = is_iterator_singleton(
+                in_ty_adt_generic_args
+                    .iter()
+                    .enumerate()
+                    .filter(|(_index, in_ty_generic)| find_param_in_ty(*in_ty_generic, param)),
+            ) else {
+                return Err(expr);
+            };
 
             let struct_generic_parameters: &ty::Generics = self.tcx.generics_of(in_ty_adt.did());
             if drill_generic_index >= struct_generic_parameters.params.len() {
@@ -794,7 +812,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     .iter()
                     .map(|field| field.ty(self.tcx, *in_ty_adt_generic_args))
                     .enumerate()
-                    .filter(|(_index, field_type)| find_param_in_ty((*field_type).into(), param))
+                    .filter(|(_index, field_type)| find_param_in_ty((*field_type).into(), param)),
             ) else {
                 return Err(expr);
             };
@@ -846,7 +864,7 @@ fn find_param_in_ty<'tcx>(
                 // This logic may seem a bit strange, but typically when
                 // we have a projection type in a function signature, the
                 // argument that's being passed into that signature is
-                // not actually constraining that projection's substs in
+                // not actually constraining that projection's args in
                 // a meaningful way. So we skip it, and see improvements
                 // in some UI tests.
                 walk.skip_current_subtree();
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
index 41f5fafe72f..a9610009db1 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
@@ -93,7 +93,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         expected: Expectation<'tcx>,
     ) -> Ty<'tcx> {
         let has_error = match method {
-            Ok(method) => method.substs.references_error() || method.sig.references_error(),
+            Ok(method) => method.args.references_error() || method.sig.references_error(),
             Err(_) => true,
         };
         if has_error {
@@ -753,11 +753,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         }
 
         errors.retain(|error| {
-            let Error::Invalid(
-                provided_idx,
-                expected_idx,
-                Compatibility::Incompatible(Some(e)),
-            ) = error else { return true };
+            let Error::Invalid(provided_idx, expected_idx, Compatibility::Incompatible(Some(e))) =
+                error
+            else {
+                return true;
+            };
             let (provided_ty, provided_span) = provided_arg_tys[*provided_idx];
             let trace =
                 mk_trace(provided_span, formal_and_expected_inputs[*expected_idx], provided_ty);
@@ -1366,7 +1366,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             }
             Res::Def(DefKind::Variant, _) => match ty.normalized.ty_adt_def() {
                 Some(adt) => {
-                    Some((adt.variant_of_res(def), adt.did(), Self::user_substs_for_adt(ty)))
+                    Some((adt.variant_of_res(def), adt.did(), Self::user_args_for_adt(ty)))
                 }
                 _ => bug!("unexpected type: {:?}", ty.normalized),
             },
@@ -1374,21 +1374,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             | Res::SelfTyParam { .. }
             | Res::SelfTyAlias { .. } => match ty.normalized.ty_adt_def() {
                 Some(adt) if !adt.is_enum() => {
-                    Some((adt.non_enum_variant(), adt.did(), Self::user_substs_for_adt(ty)))
+                    Some((adt.non_enum_variant(), adt.did(), Self::user_args_for_adt(ty)))
                 }
                 _ => None,
             },
             _ => bug!("unexpected definition: {:?}", def),
         };
 
-        if let Some((variant, did, ty::UserSubsts { substs, user_self_ty })) = variant {
-            debug!("check_struct_path: did={:?} substs={:?}", did, substs);
+        if let Some((variant, did, ty::UserArgs { args, user_self_ty })) = variant {
+            debug!("check_struct_path: did={:?} args={:?}", did, args);
 
             // Register type annotation.
-            self.write_user_type_annotation_from_substs(hir_id, did, substs, user_self_ty);
+            self.write_user_type_annotation_from_args(hir_id, did, args, user_self_ty);
 
             // Check bounds on type arguments used in the path.
-            self.add_required_obligations_for_hir(path_span, did, substs, hir_id);
+            self.add_required_obligations_for_hir(path_span, did, args, hir_id);
 
             Ok((variant, ty.normalized))
         } else {
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
index 20b34df99b2..1e8af6c6ed7 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
@@ -288,14 +288,14 @@ impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> {
             poly_trait_ref,
         );
 
-        let item_substs = self.astconv().create_substs_for_associated_item(
+        let item_args = self.astconv().create_args_for_associated_item(
             span,
             item_def_id,
             item_segment,
-            trait_ref.substs,
+            trait_ref.args,
         );
 
-        Ty::new_projection(self.tcx(), item_def_id, item_substs)
+        Ty::new_projection(self.tcx(), item_def_id, item_args)
     }
 
     fn probe_adt(&self, span: Span, ty: Ty<'tcx>) -> Option<ty::AdtDef<'tcx>> {
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
index 79a7c016185..ec19d017c25 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
@@ -97,8 +97,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         found: Ty<'tcx>,
         can_satisfy: impl FnOnce(Ty<'tcx>) -> bool,
     ) -> bool {
-        let Some((def_id_or_name, output, inputs)) = self.extract_callable_info(found)
-            else { return false; };
+        let Some((def_id_or_name, output, inputs)) = self.extract_callable_info(found) else {
+            return false;
+        };
         if can_satisfy(output) {
             let (sugg_call, mut applicability) = match inputs.len() {
                 0 => ("".to_string(), Applicability::MachineApplicable),
@@ -180,10 +181,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         rhs_ty: Ty<'tcx>,
         can_satisfy: impl FnOnce(Ty<'tcx>, Ty<'tcx>) -> bool,
     ) -> bool {
-        let Some((_, lhs_output_ty, lhs_inputs)) = self.extract_callable_info(lhs_ty)
-            else { return false; };
-        let Some((_, rhs_output_ty, rhs_inputs)) = self.extract_callable_info(rhs_ty)
-            else { return false; };
+        let Some((_, lhs_output_ty, lhs_inputs)) = self.extract_callable_info(lhs_ty) else {
+            return false;
+        };
+        let Some((_, rhs_output_ty, rhs_inputs)) = self.extract_callable_info(rhs_ty) else {
+            return false;
+        };
 
         if can_satisfy(lhs_output_ty, rhs_output_ty) {
             let mut sugg = vec![];
@@ -392,7 +395,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         vec![(expr.span.shrink_to_hi(), format!(".{}()", conversion_method.name))]
                     };
                     let struct_pat_shorthand_field =
-                        self.maybe_get_struct_pattern_shorthand_field(expr);
+                        self.tcx.hir().maybe_get_struct_pattern_shorthand_field(expr);
                     if let Some(name) = struct_pat_shorthand_field {
                         sugg.insert(0, (expr.span.shrink_to_lo(), format!("{}: ", name)));
                     }
@@ -478,23 +481,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         found_ty: Ty<'tcx>,
         expected_ty: Ty<'tcx>,
     ) -> Option<(Ty<'tcx>, Ty<'tcx>, Option<(Ty<'tcx>, Ty<'tcx>)>)> {
-        let ty::Adt(found_adt, found_substs) = found_ty.peel_refs().kind() else {
+        let ty::Adt(found_adt, found_args) = found_ty.peel_refs().kind() else {
             return None;
         };
-        let ty::Adt(expected_adt, expected_substs) = expected_ty.kind() else {
+        let ty::Adt(expected_adt, expected_args) = expected_ty.kind() else {
             return None;
         };
         if self.tcx.is_diagnostic_item(sym::Option, found_adt.did())
             && self.tcx.is_diagnostic_item(sym::Option, expected_adt.did())
         {
-            Some((found_substs.type_at(0), expected_substs.type_at(0), None))
+            Some((found_args.type_at(0), expected_args.type_at(0), None))
         } else if self.tcx.is_diagnostic_item(sym::Result, found_adt.did())
             && self.tcx.is_diagnostic_item(sym::Result, expected_adt.did())
         {
             Some((
-                found_substs.type_at(0),
-                expected_substs.type_at(0),
-                Some((found_substs.type_at(1), expected_substs.type_at(1))),
+                found_args.type_at(0),
+                expected_args.type_at(0),
+                Some((found_args.type_at(1), expected_args.type_at(1))),
             ))
         } else {
             None
@@ -635,7 +638,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 // is and we were expecting a Box, ergo Pin<Box<expected>>, we
                 // can suggest Box::pin.
                 let parent = self.tcx.hir().parent_id(expr.hir_id);
-                let Some(Node::Expr(Expr { kind: ExprKind::Call(fn_name, _), .. })) = self.tcx.hir().find(parent) else {
+                let Some(Node::Expr(Expr { kind: ExprKind::Call(fn_name, _), .. })) =
+                    self.tcx.hir().find(parent)
+                else {
                     return false;
                 };
                 match fn_name.kind {
@@ -758,9 +763,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 if let Some(found) = found.make_suggestable(self.tcx, false) {
                     err.subdiagnostic(AddReturnTypeSuggestion::Add { span, found: found.to_string() });
                     return true;
-                } else if let ty::Closure(_, substs) = found.kind()
+                } else if let ty::Closure(_, args) = found.kind()
                     // FIXME(compiler-errors): Get better at printing binders...
-                    && let closure = substs.as_closure()
+                    && let closure = args.as_closure()
                     && closure.sig().is_suggestable(self.tcx, false)
                 {
                     err.subdiagnostic(AddReturnTypeSuggestion::Add { span, found: closure.print_as_impl_trait().to_string() });
@@ -850,12 +855,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let Some(hir::Node::Item(hir::Item {
             kind:
                 hir::ItemKind::Fn(
-                    hir::FnSig { decl: hir::FnDecl { inputs: fn_parameters, output: fn_return, .. }, .. },
+                    hir::FnSig {
+                        decl: hir::FnDecl { inputs: fn_parameters, output: fn_return, .. },
+                        ..
+                    },
                     hir::Generics { params, predicates, .. },
                     _body_id,
                 ),
             ..
-        })) = fn_node else { return };
+        })) = fn_node
+        else {
+            return;
+        };
 
         if params.get(expected_ty_as_param.index as usize).is_none() {
             return;
@@ -1058,7 +1069,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 )
                 .must_apply_modulo_regions()
           {
-            let suggestion = match self.maybe_get_struct_pattern_shorthand_field(expr) {
+            let suggestion = match self.tcx.hir().maybe_get_struct_pattern_shorthand_field(expr) {
                 Some(ident) => format!(": {}.clone()", ident),
                 None => ".clone()".to_string()
             };
@@ -1081,15 +1092,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         expr_ty: Ty<'tcx>,
         expected_ty: Ty<'tcx>,
     ) -> bool {
-        let ty::Adt(adt_def, substs) = expr_ty.kind() else { return false; };
-        let ty::Adt(expected_adt_def, expected_substs) = expected_ty.kind() else { return false; };
+        let ty::Adt(adt_def, args) = expr_ty.kind() else {
+            return false;
+        };
+        let ty::Adt(expected_adt_def, expected_args) = expected_ty.kind() else {
+            return false;
+        };
         if adt_def != expected_adt_def {
             return false;
         }
 
         let mut suggest_copied_or_cloned = || {
-            let expr_inner_ty = substs.type_at(0);
-            let expected_inner_ty = expected_substs.type_at(0);
+            let expr_inner_ty = args.type_at(0);
+            let expected_inner_ty = expected_args.type_at(0);
             if let &ty::Ref(_, ty, hir::Mutability::Not) = expr_inner_ty.kind()
                 && self.can_eq(self.param_env, ty, expected_inner_ty)
             {
@@ -1129,7 +1144,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         if let Some(result_did) = self.tcx.get_diagnostic_item(sym::Result)
             && adt_def.did() == result_did
             // Check that the error types are equal
-            && self.can_eq(self.param_env, substs.type_at(1), expected_substs.type_at(1))
+            && self.can_eq(self.param_env, args.type_at(1), expected_args.type_at(1))
         {
             return suggest_copied_or_cloned();
         } else if let Some(option_did) = self.tcx.get_diagnostic_item(sym::Option)
@@ -1205,7 +1220,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             return false;
         }
 
-        let ty::Adt(def, _) = expr_ty.peel_refs().kind() else { return false; };
+        let ty::Adt(def, _) = expr_ty.peel_refs().kind() else {
+            return false;
+        };
         if !self.tcx.is_diagnostic_item(sym::Option, def.did()) {
             return false;
         }
@@ -1230,7 +1247,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             return false;
         }
 
-        let suggestion = match self.maybe_get_struct_pattern_shorthand_field(expr) {
+        let suggestion = match self.tcx.hir().maybe_get_struct_pattern_shorthand_field(expr) {
             Some(ident) => format!(": {}.is_some()", ident),
             None => ".is_some()".to_string(),
         };
@@ -1327,7 +1344,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 node: rustc_ast::LitKind::Int(lit, rustc_ast::LitIntType::Unsuffixed),
                 span,
             }) => {
-                let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(*span) else { return false; };
+                let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(*span) else {
+                    return false;
+                };
                 if !(snippet.starts_with("0x") || snippet.starts_with("0X")) {
                     return false;
                 }
@@ -1367,10 +1386,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         };
 
         // Provided expression needs to be a literal `0`.
-        let ExprKind::Lit(Spanned {
-            node: rustc_ast::LitKind::Int(0, _),
-            span,
-        }) = expr.kind else {
+        let ExprKind::Lit(Spanned { node: rustc_ast::LitKind::Int(0, _), span }) = expr.kind else {
             return false;
         };
 
@@ -1401,7 +1417,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         expr: &hir::Expr<'_>,
         expected_ty: Ty<'tcx>,
     ) -> bool {
-        let Some((DefKind::AssocFn, old_def_id)) = self.typeck_results.borrow().type_dependent_def(expr.hir_id) else {
+        let Some((DefKind::AssocFn, old_def_id)) =
+            self.typeck_results.borrow().type_dependent_def(expr.hir_id)
+        else {
             return false;
         };
         let old_item_name = self.tcx.item_name(old_def_id);
@@ -1457,7 +1475,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             // Same item
             return false;
         }
-        let item_ty = self.tcx.type_of(item.def_id).subst_identity();
+        let item_ty = self.tcx.type_of(item.def_id).instantiate_identity();
         // FIXME(compiler-errors): This check is *so* rudimentary
         if item_ty.has_param() {
             return false;
@@ -1494,8 +1512,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         found_ty: Ty<'tcx>,
         expr: &hir::Expr<'_>,
     ) {
-        let hir::ExprKind::MethodCall(segment, callee_expr, &[], _) = expr.kind else { return; };
-        let Some(clone_trait_did) = self.tcx.lang_items().clone_trait() else { return; };
+        let hir::ExprKind::MethodCall(segment, callee_expr, &[], _) = expr.kind else {
+            return;
+        };
+        let Some(clone_trait_did) = self.tcx.lang_items().clone_trait() else {
+            return;
+        };
         let ty::Ref(_, pointee_ty, _) = found_ty.kind() else { return };
         let results = self.typeck_results.borrow();
         // First, look for a `Clone::clone` call
diff --git a/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_build.rs b/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_build.rs
index b84c4918649..b059db23bb4 100644
--- a/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_build.rs
+++ b/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_build.rs
@@ -6,7 +6,7 @@ use hir::{
     intravisit::{self, Visitor},
     Body, Expr, ExprKind, Guard, HirId, LoopIdError,
 };
-use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_data_structures::unord::{UnordMap, UnordSet};
 use rustc_hir as hir;
 use rustc_index::IndexVec;
 use rustc_infer::infer::InferCtxt;
@@ -28,7 +28,7 @@ pub(super) fn build_control_flow_graph<'tcx>(
     consumed_borrowed_places: ConsumedAndBorrowedPlaces,
     body: &'tcx Body<'tcx>,
     num_exprs: usize,
-) -> (DropRangesBuilder, FxHashSet<HirId>) {
+) -> (DropRangesBuilder, UnordSet<HirId>) {
     let mut drop_range_visitor = DropRangeVisitor::new(
         infcx,
         typeck_results,
@@ -528,7 +528,7 @@ impl DropRangesBuilder {
         hir: Map<'_>,
         num_exprs: usize,
     ) -> Self {
-        let mut tracked_value_map = FxHashMap::<_, TrackedValueIndex>::default();
+        let mut tracked_value_map = UnordMap::<_, TrackedValueIndex>::default();
         let mut next = <_>::from(0u32);
         for value in tracked_values {
             for_each_consumable(hir, value, |value| {
diff --git a/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/mod.rs b/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/mod.rs
index ecafbd668e2..e01dcf83a38 100644
--- a/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/mod.rs
+++ b/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/mod.rs
@@ -17,7 +17,7 @@ use self::record_consumed_borrow::find_consumed_and_borrowed;
 use crate::FnCtxt;
 use hir::def_id::DefId;
 use hir::{Body, HirId, HirIdMap, Node};
-use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_data_structures::unord::{UnordMap, UnordSet};
 use rustc_hir as hir;
 use rustc_index::bit_set::BitSet;
 use rustc_index::IndexVec;
@@ -63,7 +63,7 @@ pub fn compute_drop_ranges<'a, 'tcx>(
         // If drop range tracking is not enabled, skip all the analysis and produce an
         // empty set of DropRanges.
         DropRanges {
-            tracked_value_map: FxHashMap::default(),
+            tracked_value_map: UnordMap::default(),
             nodes: IndexVec::new(),
             borrowed_temporaries: None,
         }
@@ -182,9 +182,9 @@ impl TryFrom<&PlaceWithHirId<'_>> for TrackedValue {
 }
 
 pub struct DropRanges {
-    tracked_value_map: FxHashMap<TrackedValue, TrackedValueIndex>,
+    tracked_value_map: UnordMap<TrackedValue, TrackedValueIndex>,
     nodes: IndexVec<PostOrderId, NodeInfo>,
-    borrowed_temporaries: Option<FxHashSet<HirId>>,
+    borrowed_temporaries: Option<UnordSet<HirId>>,
 }
 
 impl DropRanges {
@@ -227,7 +227,7 @@ struct DropRangesBuilder {
     /// (see NodeInfo::drop_state). The hir_id_map field stores the mapping
     /// from HirIds to the HirIdIndex that is used to represent that value in
     /// bitvector.
-    tracked_value_map: FxHashMap<TrackedValue, TrackedValueIndex>,
+    tracked_value_map: UnordMap<TrackedValue, TrackedValueIndex>,
 
     /// When building the control flow graph, we don't always know the
     /// post-order index of the target node at the point we encounter it.
diff --git a/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/record_consumed_borrow.rs b/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/record_consumed_borrow.rs
index 8ab0bd535d6..50a3bbf49d5 100644
--- a/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/record_consumed_borrow.rs
+++ b/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/record_consumed_borrow.rs
@@ -4,7 +4,7 @@ use crate::{
     FnCtxt,
 };
 use hir::{def_id::DefId, Body, HirId, HirIdMap};
-use rustc_data_structures::fx::FxHashSet;
+use rustc_data_structures::{fx::FxIndexSet, unord::UnordSet};
 use rustc_hir as hir;
 use rustc_middle::ty::{ParamEnv, TyCtxt};
 use rustc_middle::{
@@ -30,13 +30,13 @@ pub(super) struct ConsumedAndBorrowedPlaces {
     ///
     /// Note that this set excludes "partial drops" -- for example, a statement like `drop(x.y)` is
     /// not considered a drop of `x`, although it would be a drop of `x.y`.
-    pub(super) consumed: HirIdMap<FxHashSet<TrackedValue>>,
+    pub(super) consumed: HirIdMap<FxIndexSet<TrackedValue>>,
 
     /// A set of hir-ids of values or variables that are borrowed at some point within the body.
-    pub(super) borrowed: FxHashSet<TrackedValue>,
+    pub(super) borrowed: UnordSet<TrackedValue>,
 
     /// A set of hir-ids of values or variables that are borrowed at some point within the body.
-    pub(super) borrowed_temporaries: FxHashSet<HirId>,
+    pub(super) borrowed_temporaries: UnordSet<HirId>,
 }
 
 /// Works with ExprUseVisitor to find interesting values for the drop range analysis.
diff --git a/compiler/rustc_hir_typeck/src/inherited.rs b/compiler/rustc_hir_typeck/src/inherited.rs
index d5619af2aae..7064484a40f 100644
--- a/compiler/rustc_hir_typeck/src/inherited.rs
+++ b/compiler/rustc_hir_typeck/src/inherited.rs
@@ -1,6 +1,6 @@
 use super::callee::DeferredCallResolution;
 
-use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_data_structures::unord::{UnordMap, UnordSet};
 use rustc_hir as hir;
 use rustc_hir::def_id::LocalDefId;
 use rustc_hir::HirIdMap;
@@ -61,9 +61,9 @@ pub struct Inherited<'tcx> {
     /// Whenever we introduce an adjustment from `!` into a type variable,
     /// we record that type variable here. This is later used to inform
     /// fallback. See the `fallback` module for details.
-    pub(super) diverging_type_vars: RefCell<FxHashSet<Ty<'tcx>>>,
+    pub(super) diverging_type_vars: RefCell<UnordSet<Ty<'tcx>>>,
 
-    pub(super) infer_var_info: RefCell<FxHashMap<ty::TyVid, ty::InferVarInfo>>,
+    pub(super) infer_var_info: RefCell<UnordMap<ty::TyVid, ty::InferVarInfo>>,
 }
 
 impl<'tcx> Deref for Inherited<'tcx> {
diff --git a/compiler/rustc_hir_typeck/src/intrinsicck.rs b/compiler/rustc_hir_typeck/src/intrinsicck.rs
index e58efc9d1e3..2d85451c9e1 100644
--- a/compiler/rustc_hir_typeck/src/intrinsicck.rs
+++ b/compiler/rustc_hir_typeck/src/intrinsicck.rs
@@ -11,7 +11,7 @@ use super::FnCtxt;
 /// If the type is `Option<T>`, it will return `T`, otherwise
 /// the type itself. Works on most `Option`-like types.
 fn unpack_option_like<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
-    let ty::Adt(def, substs) = *ty.kind() else { return ty };
+    let ty::Adt(def, args) = *ty.kind() else { return ty };
 
     if def.variants().len() == 2 && !def.repr().c() && def.repr().int.is_none() {
         let data_idx;
@@ -28,7 +28,7 @@ fn unpack_option_like<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
         }
 
         if def.variant(data_idx).fields.len() == 1 {
-            return def.variant(data_idx).single_field().ty(tcx, substs);
+            return def.variant(data_idx).single_field().ty(tcx, args);
         }
     }
 
diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs
index 862430f5eb1..28e7f290737 100644
--- a/compiler/rustc_hir_typeck/src/lib.rs
+++ b/compiler/rustc_hir_typeck/src/lib.rs
@@ -6,7 +6,6 @@
 #![feature(min_specialization)]
 #![feature(control_flow_enum)]
 #![feature(option_as_slice)]
-#![allow(rustc::potential_query_instability)]
 #![recursion_limit = "256"]
 
 #[macro_use]
@@ -145,7 +144,7 @@ fn used_trait_imports(tcx: TyCtxt<'_>, def_id: LocalDefId) -> &UnordSet<LocalDef
 }
 
 fn typeck<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &ty::TypeckResults<'tcx> {
-    let fallback = move || tcx.type_of(def_id.to_def_id()).subst_identity();
+    let fallback = move || tcx.type_of(def_id.to_def_id()).instantiate_identity();
     typeck_with_fallback(tcx, def_id, fallback)
 }
 
@@ -195,7 +194,7 @@ fn typeck_with_fallback<'tcx>(
         let fn_sig = if rustc_hir_analysis::collect::get_infer_ret_ty(&decl.output).is_some() {
             fcx.astconv().ty_of_fn(id, header.unsafety, header.abi, decl, None, None)
         } else {
-            tcx.fn_sig(def_id).subst_identity()
+            tcx.fn_sig(def_id).instantiate_identity()
         };
 
         check_abi(tcx, id, span, fn_sig.abi());
diff --git a/compiler/rustc_hir_typeck/src/mem_categorization.rs b/compiler/rustc_hir_typeck/src/mem_categorization.rs
index a1aa090841a..0700e2e0554 100644
--- a/compiler/rustc_hir_typeck/src/mem_categorization.rs
+++ b/compiler/rustc_hir_typeck/src/mem_categorization.rs
@@ -595,7 +595,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
     fn total_fields_in_tuple(&self, pat_hir_id: hir::HirId, span: Span) -> McResult<usize> {
         let ty = self.typeck_results.node_type(pat_hir_id);
         match ty.kind() {
-            ty::Tuple(substs) => Ok(substs.len()),
+            ty::Tuple(args) => Ok(args.len()),
             _ => {
                 self.tcx().sess.delay_span_bug(span, "tuple pattern not applied to a tuple");
                 Err(())
diff --git a/compiler/rustc_hir_typeck/src/method/confirm.rs b/compiler/rustc_hir_typeck/src/method/confirm.rs
index 87edb803148..6835782b5bd 100644
--- a/compiler/rustc_hir_typeck/src/method/confirm.rs
+++ b/compiler/rustc_hir_typeck/src/method/confirm.rs
@@ -5,7 +5,7 @@ use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_hir::GenericArg;
 use rustc_hir_analysis::astconv::generics::{
-    check_generic_arg_count_for_call, create_substs_for_generic_args,
+    check_generic_arg_count_for_call, create_args_for_parent_generic_args,
 };
 use rustc_hir_analysis::astconv::{AstConv, CreateSubstsForGenericArgsCtxt, IsMethodCall};
 use rustc_infer::infer::{self, DefineOpaqueTypes, InferOk};
@@ -13,9 +13,9 @@ use rustc_middle::traits::{ObligationCauseCode, UnifyReceiverContext};
 use rustc_middle::ty::adjustment::{Adjust, Adjustment, PointerCoercion};
 use rustc_middle::ty::adjustment::{AllowTwoPhase, AutoBorrow, AutoBorrowMutability};
 use rustc_middle::ty::fold::TypeFoldable;
-use rustc_middle::ty::subst::{self, SubstsRef};
-use rustc_middle::ty::{self, GenericParamDefKind, Ty, TyCtxt};
-use rustc_middle::ty::{InternalSubsts, UserSubsts, UserType};
+use rustc_middle::ty::{
+    self, GenericArgs, GenericArgsRef, GenericParamDefKind, Ty, TyCtxt, UserArgs, UserType,
+};
 use rustc_span::{Span, DUMMY_SP};
 use rustc_trait_selection::traits;
 
@@ -96,13 +96,13 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
         let self_ty = self.adjust_self_ty(unadjusted_self_ty, &pick);
 
         // Create substitutions for the method's type parameters.
-        let rcvr_substs = self.fresh_receiver_substs(self_ty, &pick);
-        let all_substs = self.instantiate_method_substs(&pick, segment, rcvr_substs);
+        let rcvr_args = self.fresh_receiver_args(self_ty, &pick);
+        let all_args = self.instantiate_method_args(&pick, segment, rcvr_args);
 
-        debug!("rcvr_substs={rcvr_substs:?}, all_substs={all_substs:?}");
+        debug!("rcvr_args={rcvr_args:?}, all_args={all_args:?}");
 
         // Create the final signature for the method, replacing late-bound regions.
-        let (method_sig, method_predicates) = self.instantiate_method_sig(&pick, all_substs);
+        let (method_sig, method_predicates) = self.instantiate_method_sig(&pick, all_args);
 
         // If there is a `Self: Sized` bound and `Self` is a trait object, it is possible that
         // something which derefs to `Self` actually implements the trait and the caller
@@ -112,10 +112,10 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
         // In that case, we'll error anyway, but we'll also re-run the search with all traits
         // in scope, and if we find another method which can be used, we'll output an
         // appropriate hint suggesting to import the trait.
-        let filler_substs = rcvr_substs
+        let filler_args = rcvr_args
             .extend_to(self.tcx, pick.item.def_id, |def, _| self.tcx.mk_param_from_def(def));
         let illegal_sized_bound = self.predicates_require_illegal_sized_bound(
-            self.tcx.predicates_of(pick.item.def_id).instantiate(self.tcx, filler_substs),
+            self.tcx.predicates_of(pick.item.def_id).instantiate(self.tcx, filler_args),
         );
 
         // Unify the (adjusted) self type with what the method expects.
@@ -129,7 +129,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
             "confirm: self_ty={:?} method_sig_rcvr={:?} method_sig={:?} method_predicates={:?}",
             self_ty, method_sig_rcvr, method_sig, method_predicates
         );
-        self.unify_receivers(self_ty, method_sig_rcvr, &pick, all_substs);
+        self.unify_receivers(self_ty, method_sig_rcvr, &pick, all_args);
 
         let (method_sig, method_predicates) =
             self.normalize(self.span, (method_sig, method_predicates));
@@ -144,7 +144,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
         if illegal_sized_bound.is_none() {
             self.add_obligations(
                 Ty::new_fn_ptr(self.tcx, method_sig),
-                all_substs,
+                all_args,
                 method_predicates,
                 pick.item.def_id,
             );
@@ -153,7 +153,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
         // Create the final `MethodCallee`.
         let callee = MethodCallee {
             def_id: pick.item.def_id,
-            substs: all_substs,
+            args: all_args,
             sig: method_sig.skip_binder(),
         };
         ConfirmResult { callee, illegal_sized_bound }
@@ -171,7 +171,8 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
         // time writing the results into the various typeck results.
         let mut autoderef = self.autoderef(self.call_expr.span, unadjusted_self_ty);
         let Some((ty, n)) = autoderef.nth(pick.autoderefs) else {
-            return Ty::new_error_with_message(self.tcx,
+            return Ty::new_error_with_message(
+                self.tcx,
                 rustc_span::DUMMY_SP,
                 format!("failed autoderef {}", pick.autoderefs),
             );
@@ -251,11 +252,11 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
     ///
     /// Note that this substitution may include late-bound regions from the impl level. If so,
     /// these are instantiated later in the `instantiate_method_sig` routine.
-    fn fresh_receiver_substs(
+    fn fresh_receiver_args(
         &mut self,
         self_ty: Ty<'tcx>,
         pick: &probe::Pick<'tcx>,
-    ) -> SubstsRef<'tcx> {
+    ) -> GenericArgsRef<'tcx> {
         match pick.kind {
             probe::InherentImplPick => {
                 let impl_def_id = pick.item.container_id(self.tcx);
@@ -264,7 +265,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
                     "impl {:?} is not an inherent impl",
                     impl_def_id
                 );
-                self.fresh_substs_for_item(self.span, impl_def_id)
+                self.fresh_args_for_item(self.span, impl_def_id)
             }
 
             probe::ObjectPick => {
@@ -288,7 +289,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
                         "original_poly_trait_ref={:?} upcast_trait_ref={:?} target_trait={:?}",
                         original_poly_trait_ref, upcast_trait_ref, trait_def_id
                     );
-                    upcast_trait_ref.substs
+                    upcast_trait_ref.args
                 })
             }
 
@@ -300,13 +301,13 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
                 // the process we will unify the transformed-self-type
                 // of the method with the actual type in order to
                 // unify some of these variables.
-                self.fresh_substs_for_item(self.span, trait_def_id)
+                self.fresh_args_for_item(self.span, trait_def_id)
             }
 
             probe::WhereClausePick(poly_trait_ref) => {
                 // Where clauses can have bound regions in them. We need to instantiate
                 // those to convert from a poly-trait-ref to a trait-ref.
-                self.instantiate_binder_with_fresh_vars(poly_trait_ref).substs
+                self.instantiate_binder_with_fresh_vars(poly_trait_ref).args
             }
         }
     }
@@ -343,12 +344,12 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
             })
     }
 
-    fn instantiate_method_substs(
+    fn instantiate_method_args(
         &mut self,
         pick: &probe::Pick<'tcx>,
         seg: &hir::PathSegment<'_>,
-        parent_substs: SubstsRef<'tcx>,
-    ) -> SubstsRef<'tcx> {
+        parent_args: GenericArgsRef<'tcx>,
+    ) -> GenericArgsRef<'tcx> {
         // Determine the values for the generic parameters of the method.
         // If they were not explicitly supplied, just construct fresh
         // variables.
@@ -365,7 +366,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
 
         // Create subst for early-bound lifetime parameters, combining
         // parameters from the type and those from the method.
-        assert_eq!(generics.parent_count, parent_substs.len());
+        assert_eq!(generics.parent_count, parent_args.len());
 
         struct MethodSubstsCtxt<'a, 'tcx> {
             cfcx: &'a ConfirmContext<'a, 'tcx>,
@@ -389,7 +390,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
                 &mut self,
                 param: &ty::GenericParamDef,
                 arg: &GenericArg<'_>,
-            ) -> subst::GenericArg<'tcx> {
+            ) -> ty::GenericArg<'tcx> {
                 match (&param.kind, arg) {
                     (GenericParamDefKind::Lifetime, GenericArg::Lifetime(lt)) => {
                         self.cfcx.fcx.astconv().ast_region_to_region(lt, Some(param)).into()
@@ -421,31 +422,31 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
 
             fn inferred_kind(
                 &mut self,
-                _substs: Option<&[subst::GenericArg<'tcx>]>,
+                _args: Option<&[ty::GenericArg<'tcx>]>,
                 param: &ty::GenericParamDef,
                 _infer_args: bool,
-            ) -> subst::GenericArg<'tcx> {
+            ) -> ty::GenericArg<'tcx> {
                 self.cfcx.var_for_def(self.cfcx.span, param)
             }
         }
 
-        let substs = create_substs_for_generic_args(
+        let args = create_args_for_parent_generic_args(
             self.tcx,
             pick.item.def_id,
-            parent_substs,
+            parent_args,
             false,
             None,
             &arg_count_correct,
             &mut MethodSubstsCtxt { cfcx: self, pick, seg },
         );
 
-        // When the method is confirmed, the `substs` includes
+        // When the method is confirmed, the `args` includes
         // parameters from not just the method, but also the impl of
         // the method -- in particular, the `Self` type will be fully
         // resolved. However, those are not something that the "user
         // specified" -- i.e., those types come from the inferred type
         // of the receiver, not something the user wrote. So when we
-        // create the user-substs, we want to replace those earlier
+        // create the user-args, we want to replace those earlier
         // types with just the types that the user actually wrote --
         // that is, those that appear on the *method itself*.
         //
@@ -453,15 +454,15 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
         // `foo.bar::<u32>(...)` -- the `Self` type here will be the
         // type of `foo` (possibly adjusted), but we don't want to
         // include that. We want just the `[_, u32]` part.
-        if !substs.is_empty() && !generics.params.is_empty() {
+        if !args.is_empty() && !generics.params.is_empty() {
             let user_type_annotation = self.probe(|_| {
-                let user_substs = UserSubsts {
-                    substs: InternalSubsts::for_item(self.tcx, pick.item.def_id, |param, _| {
+                let user_args = UserArgs {
+                    args: GenericArgs::for_item(self.tcx, pick.item.def_id, |param, _| {
                         let i = param.index as usize;
                         if i < generics.parent_count {
                             self.fcx.var_for_def(DUMMY_SP, param)
                         } else {
-                            substs[i]
+                            args[i]
                         }
                     }),
                     user_self_ty: None, // not relevant here
@@ -469,18 +470,18 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
 
                 self.fcx.canonicalize_user_type_annotation(UserType::TypeOf(
                     pick.item.def_id,
-                    user_substs,
+                    user_args,
                 ))
             });
 
-            debug!("instantiate_method_substs: user_type_annotation={:?}", user_type_annotation);
+            debug!("instantiate_method_args: user_type_annotation={:?}", user_type_annotation);
 
             if !self.skip_record_for_diagnostics {
                 self.fcx.write_user_type_annotation(self.call_expr.hir_id, user_type_annotation);
             }
         }
 
-        self.normalize(self.span, substs)
+        self.normalize(self.span, args)
     }
 
     fn unify_receivers(
@@ -488,7 +489,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
         self_ty: Ty<'tcx>,
         method_self_ty: Ty<'tcx>,
         pick: &probe::Pick<'tcx>,
-        substs: SubstsRef<'tcx>,
+        args: GenericArgsRef<'tcx>,
     ) {
         debug!(
             "unify_receivers: self_ty={:?} method_self_ty={:?} span={:?} pick={:?}",
@@ -499,7 +500,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
             ObligationCauseCode::UnifyReceiver(Box::new(UnifyReceiverContext {
                 assoc_item: pick.item,
                 param_env: self.param_env,
-                substs,
+                args,
             })),
         );
         match self.at(&cause, self.param_env).sup(DefineOpaqueTypes::No, method_self_ty, self_ty) {
@@ -509,7 +510,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
             Err(terr) => {
                 // FIXME(arbitrary_self_types): We probably should limit the
                 // situations where this can occur by adding additional restrictions
-                // to the feature, like the self type can't reference method substs.
+                // to the feature, like the self type can't reference method args.
                 if self.tcx.features().arbitrary_self_types {
                     self.err_ctxt()
                         .report_mismatched_types(&cause, method_self_ty, self_ty, terr)
@@ -532,19 +533,19 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
     fn instantiate_method_sig(
         &mut self,
         pick: &probe::Pick<'tcx>,
-        all_substs: SubstsRef<'tcx>,
+        all_args: GenericArgsRef<'tcx>,
     ) -> (ty::FnSig<'tcx>, ty::InstantiatedPredicates<'tcx>) {
-        debug!("instantiate_method_sig(pick={:?}, all_substs={:?})", pick, all_substs);
+        debug!("instantiate_method_sig(pick={:?}, all_args={:?})", pick, all_args);
 
         // Instantiate the bounds on the method with the
         // type/early-bound-regions substitutions performed. There can
         // be no late-bound regions appearing here.
         let def_id = pick.item.def_id;
-        let method_predicates = self.tcx.predicates_of(def_id).instantiate(self.tcx, all_substs);
+        let method_predicates = self.tcx.predicates_of(def_id).instantiate(self.tcx, all_args);
 
         debug!("method_predicates after subst = {:?}", method_predicates);
 
-        let sig = self.tcx.fn_sig(def_id).subst(self.tcx, all_substs);
+        let sig = self.tcx.fn_sig(def_id).instantiate(self.tcx, all_args);
         debug!("type scheme substituted, sig={:?}", sig);
 
         let sig = self.instantiate_binder_with_fresh_vars(sig);
@@ -556,18 +557,18 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
     fn add_obligations(
         &mut self,
         fty: Ty<'tcx>,
-        all_substs: SubstsRef<'tcx>,
+        all_args: GenericArgsRef<'tcx>,
         method_predicates: ty::InstantiatedPredicates<'tcx>,
         def_id: DefId,
     ) {
         debug!(
-            "add_obligations: fty={:?} all_substs={:?} method_predicates={:?} def_id={:?}",
-            fty, all_substs, method_predicates, def_id
+            "add_obligations: fty={:?} all_args={:?} method_predicates={:?} def_id={:?}",
+            fty, all_args, method_predicates, def_id
         );
 
         // FIXME: could replace with the following, but we already calculated `method_predicates`,
         // so we just call `predicates_for_generics` directly to avoid redoing work.
-        // `self.add_required_obligations(self.span, def_id, &all_substs);`
+        // `self.add_required_obligations(self.span, def_id, &all_args);`
         for obligation in traits::predicates_for_generics(
             |idx, span| {
                 let code = if span.is_dummy() {
@@ -590,10 +591,10 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
 
         // this is a projection from a trait reference, so we have to
         // make sure that the trait reference inputs are well-formed.
-        self.add_wf_bounds(all_substs, self.call_expr);
+        self.add_wf_bounds(all_args, self.call_expr);
 
         // the function type must also be well-formed (this is not
-        // implied by the substs being well-formed because of inherent
+        // implied by the args being well-formed because of inherent
         // impls and late-bound regions - see issue #28609).
         self.register_wf_obligation(fty.into(), self.span, traits::WellFormed(None));
     }
diff --git a/compiler/rustc_hir_typeck/src/method/mod.rs b/compiler/rustc_hir_typeck/src/method/mod.rs
index c59e9e315b1..356e7022aea 100644
--- a/compiler/rustc_hir_typeck/src/method/mod.rs
+++ b/compiler/rustc_hir_typeck/src/method/mod.rs
@@ -19,8 +19,8 @@ use rustc_hir::def_id::DefId;
 use rustc_infer::infer::{self, InferOk};
 use rustc_middle::query::Providers;
 use rustc_middle::traits::ObligationCause;
-use rustc_middle::ty::subst::{InternalSubsts, SubstsRef};
 use rustc_middle::ty::{self, GenericParamDefKind, Ty, TypeVisitableExt};
+use rustc_middle::ty::{GenericArgs, GenericArgsRef};
 use rustc_span::symbol::Ident;
 use rustc_span::Span;
 use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
@@ -36,7 +36,7 @@ pub fn provide(providers: &mut Providers) {
 pub struct MethodCallee<'tcx> {
     /// Impl method ID, for inherent methods, or trait method ID, otherwise.
     pub def_id: DefId,
-    pub substs: SubstsRef<'tcx>,
+    pub args: GenericArgsRef<'tcx>,
 
     /// Instantiated method signature, i.e., it has been
     /// substituted, normalized, and has had late-bound
@@ -321,9 +321,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         trait_def_id: DefId,
         self_ty: Ty<'tcx>,
         opt_input_types: Option<&[Ty<'tcx>]>,
-    ) -> (traits::PredicateObligation<'tcx>, &'tcx ty::List<ty::subst::GenericArg<'tcx>>) {
+    ) -> (traits::PredicateObligation<'tcx>, &'tcx ty::List<ty::GenericArg<'tcx>>) {
         // Construct a trait-reference `self_ty : Trait<input_tys>`
-        let substs = InternalSubsts::for_item(self.tcx, trait_def_id, |param, _| {
+        let args = GenericArgs::for_item(self.tcx, trait_def_id, |param, _| {
             match param.kind {
                 GenericParamDefKind::Lifetime | GenericParamDefKind::Const { .. } => {}
                 GenericParamDefKind::Type { .. } => {
@@ -337,7 +337,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             self.var_for_def(cause.span, param)
         });
 
-        let trait_ref = ty::TraitRef::new(self.tcx, trait_def_id, substs);
+        let trait_ref = ty::TraitRef::new(self.tcx, trait_def_id, args);
 
         // Construct an obligation
         let poly_trait_ref = ty::Binder::dummy(trait_ref);
@@ -348,7 +348,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 self.param_env,
                 poly_trait_ref.without_const(),
             ),
-            substs,
+            args,
         )
     }
 
@@ -366,9 +366,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         self_ty: Ty<'tcx>,
         opt_input_types: Option<&[Ty<'tcx>]>,
     ) -> Option<InferOk<'tcx, MethodCallee<'tcx>>> {
-        let (obligation, substs) =
+        let (obligation, args) =
             self.obligation_for_method(cause, trait_def_id, self_ty, opt_input_types);
-        self.construct_obligation_for_trait(m_name, trait_def_id, obligation, substs)
+        self.construct_obligation_for_trait(m_name, trait_def_id, obligation, args)
     }
 
     // FIXME(#18741): it seems likely that we can consolidate some of this
@@ -379,7 +379,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         m_name: Ident,
         trait_def_id: DefId,
         obligation: traits::PredicateObligation<'tcx>,
-        substs: &'tcx ty::List<ty::subst::GenericArg<'tcx>>,
+        args: &'tcx ty::List<ty::GenericArg<'tcx>>,
     ) -> Option<InferOk<'tcx, MethodCallee<'tcx>>> {
         debug!(?obligation);
 
@@ -425,7 +425,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         // N.B., instantiate late-bound regions before normalizing the
         // function signature so that normalization does not need to deal
         // with bound regions.
-        let fn_sig = tcx.fn_sig(def_id).subst(self.tcx, substs);
+        let fn_sig = tcx.fn_sig(def_id).instantiate(self.tcx, args);
         let fn_sig =
             self.instantiate_binder_with_fresh_vars(obligation.cause.span, infer::FnCall, fn_sig);
 
@@ -444,7 +444,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         //
         // Note that as the method comes from a trait, it should not have
         // any late-bound regions appearing in its bounds.
-        let bounds = self.tcx.predicates_of(def_id).instantiate(self.tcx, substs);
+        let bounds = self.tcx.predicates_of(def_id).instantiate(self.tcx, args);
 
         let InferOk { value, obligations: o } =
             self.at(&obligation.cause, self.param_env).normalize(bounds);
@@ -477,7 +477,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             ))),
         ));
 
-        let callee = MethodCallee { def_id, substs, sig: fn_sig };
+        let callee = MethodCallee { def_id, args, sig: fn_sig };
 
         debug!("callee = {:?}", callee);
 
diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs
index 03a3eebbdf5..9ef97243c5e 100644
--- a/compiler/rustc_hir_typeck/src/method/probe.rs
+++ b/compiler/rustc_hir_typeck/src/method/probe.rs
@@ -22,7 +22,7 @@ use rustc_middle::ty::AssocItem;
 use rustc_middle::ty::GenericParamDefKind;
 use rustc_middle::ty::ToPredicate;
 use rustc_middle::ty::{self, ParamEnvAnd, Ty, TyCtxt, TypeFoldable, TypeVisitableExt};
-use rustc_middle::ty::{InternalSubsts, SubstsRef};
+use rustc_middle::ty::{GenericArgs, GenericArgsRef};
 use rustc_session::lint;
 use rustc_span::def_id::DefId;
 use rustc_span::def_id::LocalDefId;
@@ -100,10 +100,10 @@ impl<'a, 'tcx> Deref for ProbeContext<'a, 'tcx> {
 #[derive(Debug, Clone)]
 pub(crate) struct Candidate<'tcx> {
     // Candidates are (I'm not quite sure, but they are mostly) basically
-    // some metadata on top of a `ty::AssocItem` (without substs).
+    // some metadata on top of a `ty::AssocItem` (without args).
     //
     // However, method probing wants to be able to evaluate the predicates
-    // for a function with the substs applied - for example, if a function
+    // for a function with the args applied - for example, if a function
     // has `where Self: Sized`, we don't want to consider it unless `Self`
     // is actually `Sized`, and similarly, return-type suggestions want
     // to consider the "actual" return type.
@@ -140,7 +140,7 @@ pub(crate) struct Candidate<'tcx> {
 #[derive(Debug, Clone)]
 pub(crate) enum CandidateKind<'tcx> {
     InherentImplCandidate(
-        SubstsRef<'tcx>,
+        GenericArgsRef<'tcx>,
         // Normalize obligations
         Vec<traits::PredicateObligation<'tcx>>,
     ),
@@ -738,13 +738,13 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
                 continue;
             }
 
-            let (impl_ty, impl_substs) = self.impl_ty_and_substs(impl_def_id);
-            let impl_ty = impl_ty.subst(self.tcx, impl_substs);
+            let (impl_ty, impl_args) = self.impl_ty_and_args(impl_def_id);
+            let impl_ty = impl_ty.instantiate(self.tcx, impl_args);
 
             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_args);
             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
@@ -770,7 +770,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
                     xform_self_ty,
                     xform_ret_ty,
                     item,
-                    kind: InherentImplCandidate(impl_substs, obligations),
+                    kind: InherentImplCandidate(impl_args, obligations),
                     import_ids: smallvec![],
                 },
                 true,
@@ -813,7 +813,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.args);
             this.push_candidate(
                 Candidate {
                     xform_self_ty,
@@ -859,7 +859,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
             );
 
             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.args);
 
             this.push_candidate(
                 Candidate {
@@ -929,8 +929,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
     ) -> bool {
         match method.kind {
             ty::AssocKind::Fn => self.probe(|_| {
-                let substs = self.fresh_substs_for_item(self.span, method.def_id);
-                let fty = self.tcx.fn_sig(method.def_id).subst(self.tcx, substs);
+                let args = self.fresh_args_for_item(self.span, method.def_id);
+                let fty = self.tcx.fn_sig(method.def_id).instantiate(self.tcx, args);
                 let fty = self.instantiate_binder_with_fresh_vars(self.span, infer::FnCall, fty);
 
                 if let Some(self_ty) = self_ty {
@@ -954,8 +954,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
         trait_def_id: DefId,
     ) {
         debug!("assemble_extension_candidates_for_trait(trait_def_id={:?})", trait_def_id);
-        let trait_substs = self.fresh_substs_for_item(self.span, trait_def_id);
-        let trait_ref = ty::TraitRef::new(self.tcx, trait_def_id, trait_substs);
+        let trait_args = self.fresh_args_for_item(self.span, trait_def_id);
+        let trait_ref = ty::TraitRef::new(self.tcx, trait_def_id, trait_args);
 
         if self.tcx.is_trait_alias(trait_def_id) {
             // For trait aliases, recursively assume all explicitly named traits are relevant
@@ -977,7 +977,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
                         );
 
                         let (xform_self_ty, xform_ret_ty) =
-                            self.xform_self_ty(item, new_trait_ref.self_ty(), new_trait_ref.substs);
+                            self.xform_self_ty(item, new_trait_ref.self_ty(), new_trait_ref.args);
                         self.push_candidate(
                             Candidate {
                                 xform_self_ty,
@@ -1005,7 +1005,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_args);
                 self.push_candidate(
                     Candidate {
                         xform_self_ty,
@@ -1510,7 +1510,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
             // match as well (or at least may match, sometimes we
             // don't have enough information to fully evaluate).
             match probe.kind {
-                InherentImplCandidate(ref substs, ref ref_obligations) => {
+                InherentImplCandidate(ref args, ref ref_obligations) => {
                     // `xform_ret_ty` hasn't been normalized yet, only `xform_self_ty`,
                     // see the reasons mentioned in the comments in `assemble_inherent_impl_probe`
                     // for why this is necessary
@@ -1524,7 +1524,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
                     // Check whether the impl imposes obligations we have to worry about.
                     let impl_def_id = probe.item.container_id(self.tcx);
                     let impl_bounds = self.tcx.predicates_of(impl_def_id);
-                    let impl_bounds = impl_bounds.instantiate(self.tcx, substs);
+                    let impl_bounds = impl_bounds.instantiate(self.tcx, args);
 
                     let InferOk { value: impl_bounds, obligations: norm_obligations } =
                         self.fcx.at(&cause, self.param_env).normalize(impl_bounds);
@@ -1843,10 +1843,10 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
         &self,
         item: ty::AssocItem,
         impl_ty: Ty<'tcx>,
-        substs: SubstsRef<'tcx>,
+        args: GenericArgsRef<'tcx>,
     ) -> (Ty<'tcx>, Option<Ty<'tcx>>) {
         if item.kind == ty::AssocKind::Fn && self.mode == Mode::MethodCall {
-            let sig = self.xform_method_sig(item.def_id, substs);
+            let sig = self.xform_method_sig(item.def_id, args);
             (sig.inputs()[0], Some(sig.output()))
         } else {
             (impl_ty, None)
@@ -1854,11 +1854,11 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
     }
 
     #[instrument(level = "debug", skip(self))]
-    fn xform_method_sig(&self, method: DefId, substs: SubstsRef<'tcx>) -> ty::FnSig<'tcx> {
+    fn xform_method_sig(&self, method: DefId, args: GenericArgsRef<'tcx>) -> ty::FnSig<'tcx> {
         let fn_sig = self.tcx.fn_sig(method);
         debug!(?fn_sig);
 
-        assert!(!substs.has_escaping_bound_vars());
+        assert!(!args.has_escaping_bound_vars());
 
         // It is possible for type parameters or early-bound lifetimes
         // to appear in the signature of `self`. The substitutions we
@@ -1866,15 +1866,15 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
         // method yet. So create fresh variables here for those too,
         // if there are any.
         let generics = self.tcx.generics_of(method);
-        assert_eq!(substs.len(), generics.parent_count as usize);
+        assert_eq!(args.len(), generics.parent_count as usize);
 
         let xform_fn_sig = if generics.params.is_empty() {
-            fn_sig.subst(self.tcx, substs)
+            fn_sig.instantiate(self.tcx, args)
         } else {
-            let substs = InternalSubsts::for_item(self.tcx, method, |param, _| {
+            let args = GenericArgs::for_item(self.tcx, method, |param, _| {
                 let i = param.index as usize;
-                if i < substs.len() {
-                    substs[i]
+                if i < args.len() {
+                    args[i]
                 } else {
                     match param.kind {
                         GenericParamDefKind::Lifetime => {
@@ -1887,18 +1887,18 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
                     }
                 }
             });
-            fn_sig.subst(self.tcx, substs)
+            fn_sig.instantiate(self.tcx, args)
         };
 
         self.erase_late_bound_regions(xform_fn_sig)
     }
 
     /// Gets the type of an impl and generate substitutions with inference vars.
-    fn impl_ty_and_substs(
+    fn impl_ty_and_args(
         &self,
         impl_def_id: DefId,
-    ) -> (ty::EarlyBinder<Ty<'tcx>>, SubstsRef<'tcx>) {
-        (self.tcx.type_of(impl_def_id), self.fresh_substs_for_item(self.span, impl_def_id))
+    ) -> (ty::EarlyBinder<Ty<'tcx>>, GenericArgsRef<'tcx>) {
+        (self.tcx.type_of(impl_def_id), self.fresh_args_for_item(self.span, impl_def_id))
     }
 
     /// Replaces late-bound-regions bound by `value` with `'static` using
@@ -1938,13 +1938,21 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
     /// Determine if the associated item withe the given DefId matches
     /// the desired name via a doc alias.
     fn matches_by_doc_alias(&self, def_id: DefId) -> bool {
-        let Some(name) = self.method_name else { return false; };
-        let Some(local_def_id) = def_id.as_local() else { return false; };
+        let Some(name) = self.method_name else {
+            return false;
+        };
+        let Some(local_def_id) = def_id.as_local() else {
+            return false;
+        };
         let hir_id = self.fcx.tcx.hir().local_def_id_to_hir_id(local_def_id);
         let attrs = self.fcx.tcx.hir().attrs(hir_id);
         for attr in attrs {
-            let sym::doc = attr.name_or_empty() else { continue; };
-            let Some(values) = attr.meta_item_list() else { continue; };
+            let sym::doc = attr.name_or_empty() else {
+                continue;
+            };
+            let Some(values) = attr.meta_item_list() else {
+                continue;
+            };
             for v in values {
                 if v.name_or_empty() != sym::alias {
                     continue;
@@ -2032,8 +2040,8 @@ impl<'tcx> Candidate<'tcx> {
                     // means they are safe to put into the
                     // `WhereClausePick`.
                     assert!(
-                        !trait_ref.skip_binder().substs.has_infer()
-                            && !trait_ref.skip_binder().substs.has_placeholders()
+                        !trait_ref.skip_binder().args.has_infer()
+                            && !trait_ref.skip_binder().args.has_placeholders()
                     );
 
                     WhereClausePick(*trait_ref)
diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs
index 5f924f30936..e3e0eff23d2 100644
--- a/compiler/rustc_hir_typeck/src/method/suggest.rs
+++ b/compiler/rustc_hir_typeck/src/method/suggest.rs
@@ -7,7 +7,9 @@ use crate::errors::NoAssociatedItem;
 use crate::Expectation;
 use crate::FnCtxt;
 use rustc_ast::ast::Mutability;
-use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_data_structures::fx::FxIndexMap;
+use rustc_data_structures::fx::FxIndexSet;
+use rustc_data_structures::unord::UnordSet;
 use rustc_errors::StashKey;
 use rustc_errors::{
     pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed,
@@ -31,6 +33,7 @@ use rustc_middle::ty::fast_reject::{simplify_type, TreatParams};
 use rustc_middle::ty::print::{with_crate_prefix, with_forced_trimmed_paths};
 use rustc_middle::ty::IsSuggestable;
 use rustc_middle::ty::{self, GenericArgKind, Ty, TyCtxt, TypeVisitableExt};
+use rustc_span::def_id::DefIdSet;
 use rustc_span::symbol::{kw, sym, Ident};
 use rustc_span::Symbol;
 use rustc_span::{edit_distance, source_map, ExpnKind, FileName, MacroKind, Span};
@@ -536,11 +539,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 ));
             }
         } else if !unsatisfied_predicates.is_empty() {
-            let mut type_params = FxHashMap::default();
+            let mut type_params = FxIndexMap::default();
 
             // Pick out the list of unimplemented traits on the receiver.
             // This is used for custom error messages with the `#[rustc_on_unimplemented]` attribute.
-            let mut unimplemented_traits = FxHashMap::default();
+            let mut unimplemented_traits = FxIndexMap::default();
             let mut unimplemented_traits_only = true;
             for (predicate, _parent_pred, cause) in unsatisfied_predicates {
                 if let (ty::PredicateKind::Clause(ty::ClauseKind::Trait(p)), Some(cause)) =
@@ -606,7 +609,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             );
                             type_params
                                 .entry(key)
-                                .or_insert_with(FxHashSet::default)
+                                .or_insert_with(UnordSet::default)
                                 .insert(obligation.to_owned());
                             return true;
                         }
@@ -647,13 +650,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         // `<Foo as Iterator>::Item = String`.
                         let projection_ty = pred.skip_binder().projection_ty;
 
-                        let substs_with_infer_self = tcx.mk_substs_from_iter(
+                        let args_with_infer_self = tcx.mk_args_from_iter(
                             iter::once(Ty::new_var(tcx, ty::TyVid::from_u32(0)).into())
-                                .chain(projection_ty.substs.iter().skip(1)),
+                                .chain(projection_ty.args.iter().skip(1)),
                         );
 
                         let quiet_projection_ty =
-                            tcx.mk_alias_ty(projection_ty.def_id, substs_with_infer_self);
+                            tcx.mk_alias_ty(projection_ty.def_id, args_with_infer_self);
 
                         let term = pred.skip_binder().term;
 
@@ -680,8 +683,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             };
 
             // Find all the requirements that come from a local `impl` block.
-            let mut skip_list: FxHashSet<_> = Default::default();
-            let mut spanned_predicates = FxHashMap::default();
+            let mut skip_list: UnordSet<_> = Default::default();
+            let mut spanned_predicates = FxIndexMap::default();
             for (p, parent_p, cause) in unsatisfied_predicates {
                 // Extract the predicate span and parent def id of the cause,
                 // if we have one.
@@ -723,7 +726,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         let span = self_ty.span.ctxt().outer_expn_data().call_site;
                         let entry = spanned_predicates.entry(span);
                         let entry = entry.or_insert_with(|| {
-                            (FxHashSet::default(), FxHashSet::default(), Vec::new())
+                            (FxIndexSet::default(), FxIndexSet::default(), Vec::new())
                         });
                         entry.0.insert(span);
                         entry.1.insert((
@@ -771,7 +774,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         skip_list.insert(p);
                         let entry = spanned_predicates.entry(self_ty.span);
                         let entry = entry.or_insert_with(|| {
-                            (FxHashSet::default(), FxHashSet::default(), Vec::new())
+                            (FxIndexSet::default(), FxIndexSet::default(), Vec::new())
                         });
                         entry.2.push(p);
                         if cause_span != *item_span {
@@ -806,7 +809,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         skip_list.insert(p);
                         let entry = spanned_predicates.entry(ident.span);
                         let entry = entry.or_insert_with(|| {
-                            (FxHashSet::default(), FxHashSet::default(), Vec::new())
+                            (FxIndexSet::default(), FxIndexSet::default(), Vec::new())
                         });
                         entry.0.insert(cause_span);
                         entry.1.insert((ident.span, ""));
@@ -840,7 +843,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 unsatisfied_bounds = true;
             }
 
-            let mut suggested_bounds = FxHashSet::default();
+            let mut suggested_bounds = UnordSet::default();
             // The requirements that didn't have an `impl` span to show.
             let mut bound_list = unsatisfied_predicates
                 .iter()
@@ -889,8 +892,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             for ((span, add_where_or_comma), obligations) in type_params.into_iter() {
                 restrict_type_params = true;
                 // #74886: Sort here so that the output is always the same.
-                let mut obligations = obligations.into_iter().collect::<Vec<_>>();
-                obligations.sort();
+                let obligations = obligations.to_sorted_stable_ord();
                 err.span_suggestion_verbose(
                     span,
                     format!(
@@ -993,9 +995,13 @@ 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).subst_identity()
+                                        self.tcx.at(span).type_of(*def_id).instantiate_identity()
                                             != rcvr_ty
-                                            && self.tcx.at(span).type_of(*def_id).subst_identity()
+                                            && self
+                                                .tcx
+                                                .at(span)
+                                                .type_of(*def_id)
+                                                .instantiate_identity()
                                                 != rcvr_ty
                                     }
                                     (Mode::Path, false, _) => true,
@@ -1018,7 +1024,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             .map(|impl_item| {
                                 format!(
                                     "- `{}`",
-                                    self.tcx.at(span).type_of(*impl_item).subst_identity()
+                                    self.tcx.at(span).type_of(*impl_item).instantiate_identity()
                                 )
                             })
                             .collect::<Vec<_>>()
@@ -1197,7 +1203,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         None
                     };
 
-                    let impl_ty = self.tcx.at(span).type_of(impl_did).subst_identity();
+                    let impl_ty = self.tcx.at(span).type_of(impl_did).instantiate_identity();
 
                     let insertion = match self.tcx.impl_trait_ref(impl_did) {
                         None => String::new(),
@@ -1243,7 +1249,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             ty::AssocKind::Fn => self
                                 .tcx
                                 .fn_sig(item.def_id)
-                                .subst_identity()
+                                .instantiate_identity()
                                 .inputs()
                                 .skip_binder()
                                 .get(0)
@@ -1326,7 +1332,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).subst_identity();
+            let impl_ty = self.tcx.type_of(*impl_did).instantiate_identity();
             let target_ty = self
                 .autoderef(sugg_span, rcvr_ty)
                 .find(|(rcvr_ty, _)| {
@@ -1335,10 +1341,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 })
                 .map_or(impl_ty, |(ty, _)| ty)
                 .peel_refs();
-            if let ty::Adt(def, substs) = target_ty.kind() {
+            if let ty::Adt(def, args) = target_ty.kind() {
                 // If there are any inferred arguments, (`{integer}`), we should replace
                 // them with underscores to allow the compiler to infer them
-                let infer_substs = self.tcx.mk_substs_from_iter(substs.into_iter().map(|arg| {
+                let infer_args = self.tcx.mk_args_from_iter(args.into_iter().map(|arg| {
                     if !arg.is_suggestable(self.tcx, true) {
                         has_unsuggestable_args = true;
                         match arg.unpack() {
@@ -1368,7 +1374,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     }
                 }));
 
-                self.tcx.value_path_str_with_substs(def.did(), infer_substs)
+                self.tcx.value_path_str_with_args(def.did(), infer_args)
             } else {
                 self.ty_to_value_string(target_ty)
             }
@@ -1380,7 +1386,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 && let Some(assoc) = self.associated_value(*impl_did, item_name)
                 && assoc.kind == ty::AssocKind::Fn
             {
-                let sig = self.tcx.fn_sig(assoc.def_id).subst_identity();
+                let sig = self.tcx.fn_sig(assoc.def_id).instantiate_identity();
                 sig.inputs().skip_binder().get(0).and_then(|first| if first.peel_refs() == rcvr_ty.peel_refs() {
                     None
                 } else {
@@ -1445,11 +1451,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     ) -> bool {
         let tcx = self.tcx;
         let field_receiver = self.autoderef(span, rcvr_ty).find_map(|(ty, _)| match ty.kind() {
-            ty::Adt(def, substs) if !def.is_enum() => {
+            ty::Adt(def, args) if !def.is_enum() => {
                 let variant = &def.non_enum_variant();
                 tcx.find_field_index(item_name, variant).map(|index| {
                     let field = &variant.fields[index];
-                    let field_ty = field.ty(tcx, substs);
+                    let field_ty = field.ty(tcx, args);
                     (field, field_ty)
                 })
             }
@@ -1546,7 +1552,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     }
 
                     let range_def_id = self.tcx.require_lang_item(lang_item.unwrap(), None);
-                    let range_ty = self.tcx.type_of(range_def_id).subst(self.tcx, &[actual.into()]);
+                    let range_ty =
+                        self.tcx.type_of(range_def_id).instantiate(self.tcx, &[actual.into()]);
 
                     let pick = self.lookup_probe_for_diagnostic(
                         item_name,
@@ -1699,10 +1706,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     /// we try to suggest `rect.area()`
     pub(crate) fn suggest_assoc_method_call(&self, segs: &[PathSegment<'_>]) {
         debug!("suggest_assoc_method_call segs: {:?}", segs);
-        let [seg1, seg2] = segs else { return; };
+        let [seg1, seg2] = segs else {
+            return;
+        };
         let Some(mut diag) =
-                self.tcx.sess.diagnostic().steal_diagnostic(seg1.ident.span, StashKey::CallAssocMethod)
-                else { return };
+            self.tcx.sess.diagnostic().steal_diagnostic(seg1.ident.span, StashKey::CallAssocMethod)
+        else {
+            return;
+        };
 
         let map = self.infcx.tcx.hir();
         let body_id = self.tcx.hir().body_owned_by(self.body_id);
@@ -1766,7 +1777,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     ) {
         if let SelfSource::MethodCall(expr) = source
         && let mod_id = self.tcx.parent_module(expr.hir_id).to_def_id()
-        && let Some((fields, substs)) =
+        && let Some((fields, args)) =
             self.get_field_candidates_considering_privacy(span, actual, mod_id)
         {
             let call_expr = self.tcx.hir().expect_expr(self.tcx.hir().parent_id(expr.hir_id));
@@ -1801,7 +1812,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             })
                         },
                         candidate_field,
-                        substs,
+                        args,
                         vec![],
                         mod_id,
                     )
@@ -1839,18 +1850,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         item_name: Ident,
     ) {
         let tcx = self.tcx;
-        let SelfSource::MethodCall(expr) = source else { return; };
+        let SelfSource::MethodCall(expr) = source else {
+            return;
+        };
         let call_expr = tcx.hir().expect_expr(tcx.hir().parent_id(expr.hir_id));
 
-        let ty::Adt(kind, substs) = actual.kind() else { return; };
+        let ty::Adt(kind, args) = actual.kind() else {
+            return;
+        };
         match kind.adt_kind() {
             ty::AdtKind::Enum => {
                 let matching_variants: Vec<_> = kind
                     .variants()
                     .iter()
                     .flat_map(|variant| {
-                        let [field] = &variant.fields.raw[..] else { return None; };
-                        let field_ty = field.ty(tcx, substs);
+                        let [field] = &variant.fields.raw[..] else {
+                            return None;
+                        };
+                        let field_ty = field.ty(tcx, args);
 
                         // Skip `_`, since that'll just lead to ambiguity.
                         if self.resolve_vars_if_possible(field_ty).is_ty_var() {
@@ -1885,7 +1902,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
                 match &matching_variants[..] {
                     [(_, field, pick)] => {
-                        let self_ty = field.ty(tcx, substs);
+                        let self_ty = field.ty(tcx, args);
                         err.span_note(
                             tcx.def_span(pick.item.def_id),
                             format!("the method `{item_name}` exists on the type `{self_ty}`"),
@@ -1927,15 +1944,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             // Target wrapper types - types that wrap or pretend to wrap another type,
             // perhaps this inner type is meant to be called?
             ty::AdtKind::Struct | ty::AdtKind::Union => {
-                let [first] = ***substs else { return; };
-                let ty::GenericArgKind::Type(ty) = first.unpack() else { return; };
+                let [first] = ***args else {
+                    return;
+                };
+                let ty::GenericArgKind::Type(ty) = first.unpack() else {
+                    return;
+                };
                 let Ok(pick) = self.lookup_probe_for_diagnostic(
                     item_name,
                     ty,
                     call_expr,
                     ProbeScope::TraitsInScope,
                     None,
-                )  else { return; };
+                ) else {
+                    return;
+                };
 
                 let name = self.ty_to_value_string(actual);
                 let inner_id = kind.did();
@@ -2037,7 +2060,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 ty::Adt(def, _) => Some(def.did()),
                 _ => None,
             })
-            .collect::<FxHashSet<_>>();
+            .collect::<FxIndexSet<_>>();
         let mut spans: MultiSpan = def_ids
             .iter()
             .filter_map(|def_id| {
@@ -2100,7 +2123,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             let Some(ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_pred))) =
                 pred.kind().no_bound_vars()
             else {
-                continue
+                continue;
             };
             let adt = match trait_pred.self_ty().ty_adt_def() {
                 Some(adt) if adt.did().is_local() => adt,
@@ -2197,7 +2220,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         item_name: Ident,
         expected: Expectation<'tcx>,
     ) {
-        let SelfSource::QPath(ty) = self_source else { return; };
+        let SelfSource::QPath(ty) = self_source else {
+            return;
+        };
         for (deref_ty, _) in self.autoderef(rustc_span::DUMMY_SP, rcvr_ty).skip(1) {
             if let Ok(pick) = self.probe_for_name(
                 Mode::Path,
@@ -2214,7 +2239,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     // just changing the path.
                     && pick.item.fn_has_self_parameter
                     && let Some(self_ty) =
-                        self.tcx.fn_sig(pick.item.def_id).subst_identity().inputs().skip_binder().get(0)
+                        self.tcx.fn_sig(pick.item.def_id).instantiate_identity().inputs().skip_binder().get(0)
                     && self_ty.is_ref()
                 {
                     let suggested_path = match deref_ty.kind() {
@@ -2255,7 +2280,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     /// Print out the type for use in value namespace.
     fn ty_to_value_string(&self, ty: Ty<'tcx>) -> String {
         match ty.kind() {
-            ty::Adt(def, substs) => self.tcx.def_path_str_with_substs(def.did(), substs),
+            ty::Adt(def, args) => self.tcx.def_path_str_with_args(def.did(), args),
             _ => self.ty_to_string(ty),
         }
     }
@@ -2651,7 +2676,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                                 Nothing,
                             }
                             let ast_generics = hir.get_generics(id.owner.def_id).unwrap();
-                            let trait_def_ids: FxHashSet<DefId> = ast_generics
+                            let trait_def_ids: DefIdSet = ast_generics
                                 .bounds_for_param(def_id)
                                 .flat_map(|bp| bp.bounds.iter())
                                 .filter_map(|bound| bound.trait_ref()?.trait_def_id())
@@ -2752,7 +2777,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             self.tcx.impl_polarity(*imp_did) == ty::ImplPolarity::Negative
                         })
                         .any(|imp_did| {
-                            let imp = self.tcx.impl_trait_ref(imp_did).unwrap().subst_identity();
+                            let imp =
+                                self.tcx.impl_trait_ref(imp_did).unwrap().instantiate_identity();
                             let imp_simp =
                                 simplify_type(self.tcx, imp.self_ty(), TreatParams::ForLookup);
                             imp_simp.is_some_and(|s| s == simp_rcvr_ty)
@@ -2834,9 +2860,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         found: Ty<'tcx>,
         expected: Ty<'tcx>,
     ) -> bool {
-        let Some((_def_id_or_name, output, _inputs)) =
-            self.extract_callable_info(found) else {
-                return false;
+        let Some((_def_id_or_name, output, _inputs)) = self.extract_callable_info(found) else {
+            return false;
         };
 
         if !self.can_coerce(output, expected) {
diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs
index 69c8cc8c590..8bf95d4bf9a 100644
--- a/compiler/rustc_hir_typeck/src/pat.rs
+++ b/compiler/rustc_hir_typeck/src/pat.rs
@@ -1094,12 +1094,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         if subpats.len() == variant.fields.len()
             || subpats.len() < variant.fields.len() && ddpos.as_opt_usize().is_some()
         {
-            let ty::Adt(_, substs) = pat_ty.kind() else {
+            let ty::Adt(_, args) = pat_ty.kind() else {
                 bug!("unexpected pattern type {:?}", pat_ty);
             };
             for (i, subpat) in subpats.iter().enumerate_and_adjust(variant.fields.len(), ddpos) {
                 let field = &variant.fields[FieldIdx::from_usize(i)];
-                let field_ty = self.field_ty(subpat.span, field, substs);
+                let field_ty = self.field_ty(subpat.span, field, args);
                 self.check_pat(subpat, field_ty, def_bm, ti);
 
                 self.tcx.check_stability(
@@ -1182,10 +1182,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         // with the subpatterns directly in the tuple variant pattern, e.g., `V_i(p_0, .., p_N)`.
         let missing_parentheses = match (&expected.kind(), fields, had_err) {
             // #67037: only do this if we could successfully type-check the expected type against
-            // the tuple struct pattern. Otherwise the substs could get out of range on e.g.,
+            // the tuple struct pattern. Otherwise the args could get out of range on e.g.,
             // `let P() = U;` where `P != U` with `struct P<T>(T);`.
-            (ty::Adt(_, substs), [field], false) => {
-                let field_ty = self.field_ty(pat_span, field, substs);
+            (ty::Adt(_, args), [field], false) => {
+                let field_ty = self.field_ty(pat_span, field, args);
                 match field_ty.kind() {
                     ty::Tuple(fields) => fields.len() == subpats.len(),
                     _ => false,
@@ -1335,7 +1335,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     ) -> bool {
         let tcx = self.tcx;
 
-        let ty::Adt(adt, substs) = adt_ty.kind() else {
+        let ty::Adt(adt, args) = adt_ty.kind() else {
             span_bug!(pat.span, "struct pattern is not an ADT");
         };
 
@@ -1368,7 +1368,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         .map(|(i, f)| {
                             self.write_field_index(field.hir_id, *i);
                             self.tcx.check_stability(f.did, Some(pat.hir_id), span, None);
-                            self.field_ty(span, f, substs)
+                            self.field_ty(span, f, args)
                         })
                         .unwrap_or_else(|| {
                             inexistent_fields.push(field);
@@ -1396,7 +1396,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 &inexistent_fields,
                 &mut unmentioned_fields,
                 variant,
-                substs,
+                args,
             ))
         } else {
             None
@@ -1566,7 +1566,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         inexistent_fields: &[&hir::PatField<'tcx>],
         unmentioned_fields: &mut Vec<(&'tcx ty::FieldDef, Ident)>,
         variant: &ty::VariantDef,
-        substs: &'tcx ty::List<ty::subst::GenericArg<'tcx>>,
+        args: &'tcx ty::List<ty::GenericArg<'tcx>>,
     ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
         let tcx = self.tcx;
         let (field_names, t, plural) = if inexistent_fields.len() == 1 {
@@ -1636,7 +1636,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                                 self.field_ty(
                                     unmentioned_fields[0].1.span,
                                     unmentioned_fields[0].0,
-                                    substs,
+                                    args,
                                 ),
                             ) => {}
                         _ => {
diff --git a/compiler/rustc_hir_typeck/src/place_op.rs b/compiler/rustc_hir_typeck/src/place_op.rs
index fd43b475e3a..1eb84eb1637 100644
--- a/compiler/rustc_hir_typeck/src/place_op.rs
+++ b/compiler/rustc_hir_typeck/src/place_op.rs
@@ -392,7 +392,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 // We also could not use `expr_ty_adjusted` of index_expr because reborrowing
                 // during coercions can also cause type of index_expr to differ from `T`,
                 // which can potentially cause regionck failure (#74933).
-                Some(self.typeck_results.borrow().node_substs(expr.hir_id).type_at(1))
+                Some(self.typeck_results.borrow().node_args(expr.hir_id).type_at(1))
             }
         };
         let arg_tys = arg_ty.as_slice();
diff --git a/compiler/rustc_hir_typeck/src/rvalue_scopes.rs b/compiler/rustc_hir_typeck/src/rvalue_scopes.rs
index 22c9e796107..091e88abe97 100644
--- a/compiler/rustc_hir_typeck/src/rvalue_scopes.rs
+++ b/compiler/rustc_hir_typeck/src/rvalue_scopes.rs
@@ -74,9 +74,7 @@ pub fn resolve_rvalue_scopes<'a, 'tcx>(
     debug!("start resolving rvalue scopes, def_id={def_id:?}");
     debug!("rvalue_scope: rvalue_candidates={:?}", scope_tree.rvalue_candidates);
     for (&hir_id, candidate) in &scope_tree.rvalue_candidates {
-        let Some(Node::Expr(expr)) = hir_map.find(hir_id) else {
-            bug!("hir node does not exist")
-        };
+        let Some(Node::Expr(expr)) = hir_map.find(hir_id) else { bug!("hir node does not exist") };
         record_rvalue_scope(&mut rvalue_scopes, expr, candidate);
     }
     rvalue_scopes
diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs
index 208c40a3932..f77a4d16b5f 100644
--- a/compiler/rustc_hir_typeck/src/upvar.rs
+++ b/compiler/rustc_hir_typeck/src/upvar.rs
@@ -33,6 +33,7 @@
 use super::FnCtxt;
 
 use crate::expr_use_visitor as euv;
+use rustc_data_structures::unord::{ExtendUnord, UnordSet};
 use rustc_errors::{Applicability, MultiSpan};
 use rustc_hir as hir;
 use rustc_hir::def_id::LocalDefId;
@@ -41,14 +42,14 @@ use rustc_infer::infer::UpvarRegion;
 use rustc_middle::hir::place::{Place, PlaceBase, PlaceWithHirId, Projection, ProjectionKind};
 use rustc_middle::mir::FakeReadCause;
 use rustc_middle::ty::{
-    self, ClosureSizeProfileData, Ty, TyCtxt, TypeckResults, UpvarCapture, UpvarSubsts,
+    self, ClosureSizeProfileData, Ty, TyCtxt, TypeckResults, UpvarArgs, UpvarCapture,
 };
 use rustc_session::lint;
 use rustc_span::sym;
 use rustc_span::{BytePos, Pos, Span, Symbol};
 use rustc_trait_selection::infer::InferCtxtExt;
 
-use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
 use rustc_target::abi::FIRST_VARIANT;
 
 use std::iter;
@@ -168,9 +169,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     ) {
         // Extract the type of the closure.
         let ty = self.node_ty(closure_hir_id);
-        let (closure_def_id, substs) = match *ty.kind() {
-            ty::Closure(def_id, substs) => (def_id, UpvarSubsts::Closure(substs)),
-            ty::Generator(def_id, substs, _) => (def_id, UpvarSubsts::Generator(substs)),
+        let (closure_def_id, args) = match *ty.kind() {
+            ty::Closure(def_id, args) => (def_id, UpvarArgs::Closure(args)),
+            ty::Generator(def_id, args, _) => (def_id, UpvarArgs::Generator(args)),
             ty::Error(_) => {
                 // #51714: skip analysis when we have already encountered type errors
                 return;
@@ -186,8 +187,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         };
         let closure_def_id = closure_def_id.expect_local();
 
-        let infer_kind = if let UpvarSubsts::Closure(closure_substs) = substs {
-            self.closure_kind(closure_substs).is_none().then_some(closure_substs)
+        let infer_kind = if let UpvarArgs::Closure(closure_args) = args {
+            self.closure_kind(closure_args).is_none().then_some(closure_args)
         } else {
             None
         };
@@ -256,10 +257,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         let before_feature_tys = self.final_upvar_tys(closure_def_id);
 
-        if let Some(closure_substs) = infer_kind {
+        if let Some(closure_args) = infer_kind {
             // Unify the (as yet unbound) type variable in the closure
-            // substs with the kind we inferred.
-            let closure_kind_ty = closure_substs.as_closure().kind_ty();
+            // args with the kind we inferred.
+            let closure_kind_ty = closure_args.as_closure().kind_ty();
             self.demand_eqtype(span, closure_kind.to_ty(self.tcx), closure_kind_ty);
 
             // If we have an origin, store it.
@@ -294,14 +295,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         // Equate the type variables for the upvars with the actual types.
         let final_upvar_tys = self.final_upvar_tys(closure_def_id);
         debug!(
-            "analyze_closure: id={:?} substs={:?} final_upvar_tys={:?}",
-            closure_hir_id, substs, final_upvar_tys
+            "analyze_closure: id={:?} args={:?} final_upvar_tys={:?}",
+            closure_hir_id, args, final_upvar_tys
         );
 
         // 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 = Ty::new_tup(self.tcx, &final_upvar_tys);
-        self.demand_suptype(span, substs.tupled_upvars_ty(), final_tupled_upvars_type);
+        self.demand_suptype(span, args.tupled_upvars_ty(), final_tupled_upvars_type);
 
         let fake_reads = delegate
             .fake_reads
@@ -644,7 +645,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             for capture in captures {
                 match capture.info.capture_kind {
                     ty::UpvarCapture::ByRef(_) => {
-                        let PlaceBase::Upvar(upvar_id) = capture.place.base else { bug!("expected upvar") };
+                        let PlaceBase::Upvar(upvar_id) = capture.place.base else {
+                            bug!("expected upvar")
+                        };
                         let origin = UpvarRegion(upvar_id, closure_span);
                         let upvar_region = self.next_region_var(origin);
                         capture.region = Some(upvar_region);
@@ -908,19 +911,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     /// Combines all the reasons for 2229 migrations
     fn compute_2229_migrations_reasons(
         &self,
-        auto_trait_reasons: FxHashSet<&'static str>,
+        auto_trait_reasons: UnordSet<&'static str>,
         drop_order: bool,
     ) -> MigrationWarningReason {
-        let mut reasons = MigrationWarningReason::default();
-
-        reasons.auto_traits.extend(auto_trait_reasons);
-        reasons.drop_order = drop_order;
-
-        // `auto_trait_reasons` are in hashset order, so sort them to put the
-        // diagnostics we emit later in a cross-platform-consistent order.
-        reasons.auto_traits.sort_unstable();
-
-        reasons
+        MigrationWarningReason {
+            auto_traits: auto_trait_reasons.to_sorted_stable_ord(),
+            drop_order,
+        }
     }
 
     /// Figures out the list of root variables (and their types) that aren't completely
@@ -934,7 +931,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         min_captures: Option<&ty::RootVariableMinCaptureList<'tcx>>,
         var_hir_id: hir::HirId,
         closure_clause: hir::CaptureBy,
-    ) -> Option<FxHashMap<UpvarMigrationInfo, FxHashSet<&'static str>>> {
+    ) -> Option<FxIndexMap<UpvarMigrationInfo, UnordSet<&'static str>>> {
         let auto_traits_def_id = vec![
             self.tcx.lang_items().clone_trait(),
             self.tcx.lang_items().sync_trait(),
@@ -979,7 +976,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             }));
         }
 
-        let mut problematic_captures = FxHashMap::default();
+        let mut problematic_captures = FxIndexMap::default();
         // Check whether captured fields also implement the trait
         for capture in root_var_min_capture_list.iter() {
             let ty = apply_capture_kind_on_capture_ty(
@@ -999,7 +996,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 }));
             }
 
-            let mut capture_problems = FxHashSet::default();
+            let mut capture_problems = UnordSet::default();
 
             // Checks if for any of the auto traits, one or more trait is implemented
             // by the root variable but not by the capture
@@ -1045,7 +1042,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         min_captures: Option<&ty::RootVariableMinCaptureList<'tcx>>,
         closure_clause: hir::CaptureBy,
         var_hir_id: hir::HirId,
-    ) -> Option<FxHashSet<UpvarMigrationInfo>> {
+    ) -> Option<FxIndexSet<UpvarMigrationInfo>> {
         let ty = self.resolve_vars_if_possible(self.node_ty(var_hir_id));
 
         if !ty.has_significant_drop(self.tcx, self.tcx.param_env(closure_def_id)) {
@@ -1064,14 +1061,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             // ```
             debug!("no path starting from it is used");
 
-
             match closure_clause {
                 // Only migrate if closure is a move closure
                 hir::CaptureBy::Value => {
-                    let mut diagnostics_info = FxHashSet::default();
-                    let upvars = self.tcx.upvars_mentioned(closure_def_id).expect("must be an upvar");
+                    let mut diagnostics_info = FxIndexSet::default();
+                    let upvars =
+                        self.tcx.upvars_mentioned(closure_def_id).expect("must be an upvar");
                     let upvar = upvars[&var_hir_id];
-                    diagnostics_info.insert(UpvarMigrationInfo::CapturingNothing { use_span: upvar.span });
+                    diagnostics_info
+                        .insert(UpvarMigrationInfo::CapturingNothing { use_span: upvar.span });
                     return Some(diagnostics_info);
                 }
                 hir::CaptureBy::Ref => {}
@@ -1082,7 +1080,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         debug!(?root_var_min_capture_list);
 
         let mut projections_list = Vec::new();
-        let mut diagnostics_info = FxHashSet::default();
+        let mut diagnostics_info = FxIndexSet::default();
 
         for captured_place in root_var_min_capture_list.iter() {
             match captured_place.info.capture_kind {
@@ -1152,7 +1150,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         };
 
         let mut need_migrations = Vec::new();
-        let mut auto_trait_migration_reasons = FxHashSet::default();
+        let mut auto_trait_migration_reasons = UnordSet::default();
         let mut drop_migration_needed = false;
 
         // Perform auto-trait analysis
@@ -1164,7 +1162,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             {
                 diagnostics_info
             } else {
-                FxHashMap::default()
+                FxIndexMap::default()
             };
 
             let drop_reorder_diagnostic = if let Some(diagnostics_info) = self
@@ -1178,7 +1176,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 drop_migration_needed = true;
                 diagnostics_info
             } else {
-                FxHashSet::default()
+                FxIndexSet::default()
             };
 
             // Combine all the captures responsible for needing migrations into one HashSet
@@ -1195,7 +1193,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     if let Some(reasons) = auto_trait_diagnostic.get(&captures_info) {
                         reasons.clone()
                     } else {
-                        FxHashSet::default()
+                        UnordSet::default()
                     };
 
                 // Check if migration is needed because of drop reorder as a result of that capture
@@ -1203,7 +1201,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
                 // Combine all the reasons of why the root variable should be captured as a result of
                 // auto trait implementation issues
-                auto_trait_migration_reasons.extend(capture_trait_reasons.iter().copied());
+                auto_trait_migration_reasons.extend_unord(capture_trait_reasons.items().copied());
 
                 diagnostics_info.push(MigrationLintNote {
                     captures_info,
@@ -1385,7 +1383,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             ty::Ref(..) => unreachable!(),
             ty::RawPtr(..) => unreachable!(),
 
-            ty::Adt(def, substs) => {
+            ty::Adt(def, args) => {
                 // Multi-variant enums are captured in entirety,
                 // which would've been handled in the case of single empty slice in `captured_by_move_projs`.
                 assert_eq!(def.variants().len(), 1);
@@ -1412,7 +1410,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             })
                             .collect();
 
-                        let after_field_ty = field.ty(self.tcx, substs);
+                        let after_field_ty = field.ty(self.tcx, args);
                         self.has_significant_drop_outside_of_captures(
                             closure_def_id,
                             closure_span,
diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs
index 10645753609..cf6c7f70de3 100644
--- a/compiler/rustc_hir_typeck/src/writeback.rs
+++ b/compiler/rustc_hir_typeck/src/writeback.rs
@@ -4,17 +4,15 @@
 
 use crate::FnCtxt;
 use hir::def_id::LocalDefId;
-use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::unord::ExtendUnord;
 use rustc_errors::{ErrorGuaranteed, StashKey};
 use rustc_hir as hir;
 use rustc_hir::intravisit::{self, Visitor};
 use rustc_infer::infer::error_reporting::TypeAnnotationNeeded::E0282;
-use rustc_middle::hir::place::Place as HirPlace;
-use rustc_middle::mir::FakeReadCause;
 use rustc_middle::ty::adjustment::{Adjust, Adjustment, PointerCoercion};
 use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
 use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt};
-use rustc_middle::ty::{self, ClosureSizeProfileData, Ty, TyCtxt};
+use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_span::symbol::sym;
 use rustc_span::Span;
 
@@ -42,9 +40,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         // This attribute causes us to dump some writeback information
         // in the form of errors, which is used for unit tests.
-        let rustc_dump_user_substs = self.tcx.has_attr(item_def_id, sym::rustc_dump_user_substs);
+        let rustc_dump_user_args = self.tcx.has_attr(item_def_id, sym::rustc_dump_user_args);
 
-        let mut wbcx = WritebackCx::new(self, body, rustc_dump_user_substs);
+        let mut wbcx = WritebackCx::new(self, body, rustc_dump_user_args);
         for param in body.params {
             wbcx.visit_node_id(param.pat.span, param.hir_id);
         }
@@ -102,14 +100,14 @@ struct WritebackCx<'cx, 'tcx> {
 
     body: &'tcx hir::Body<'tcx>,
 
-    rustc_dump_user_substs: bool,
+    rustc_dump_user_args: bool,
 }
 
 impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
     fn new(
         fcx: &'cx FnCtxt<'cx, 'tcx>,
         body: &'tcx hir::Body<'tcx>,
-        rustc_dump_user_substs: bool,
+        rustc_dump_user_args: bool,
     ) -> WritebackCx<'cx, 'tcx> {
         let owner = body.id().hir_id.owner;
 
@@ -117,7 +115,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
             fcx,
             typeck_results: ty::TypeckResults::new(owner),
             body,
-            rustc_dump_user_substs,
+            rustc_dump_user_args,
         };
 
         // HACK: We specifically don't want the (opaque) error from tainting our
@@ -154,7 +152,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
 
                 if inner_ty.is_scalar() {
                     self.typeck_results.type_dependent_defs_mut().remove(e.hir_id);
-                    self.typeck_results.node_substs_mut().remove(e.hir_id);
+                    self.typeck_results.node_args_mut().remove(e.hir_id);
                 }
             }
             hir::ExprKind::Binary(ref op, lhs, rhs) | hir::ExprKind::AssignOp(ref op, lhs, rhs) => {
@@ -163,7 +161,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
 
                 if lhs_ty.is_scalar() && rhs_ty.is_scalar() {
                     self.typeck_results.type_dependent_defs_mut().remove(e.hir_id);
-                    self.typeck_results.node_substs_mut().remove(e.hir_id);
+                    self.typeck_results.node_args_mut().remove(e.hir_id);
 
                     match e.kind {
                         hir::ExprKind::Binary(..) => {
@@ -241,7 +239,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
                 if self.is_builtin_index(e, base_ty_inner, index_ty) {
                     // Remove the method call record
                     self.typeck_results.type_dependent_defs_mut().remove(e.hir_id);
-                    self.typeck_results.node_substs_mut().remove(e.hir_id);
+                    self.typeck_results.node_args_mut().remove(e.hir_id);
 
                     if let Some(a) = self.typeck_results.adjustments_mut().get_mut(base.hir_id) {
                         // Discard the need for a mutable borrow
@@ -376,66 +374,75 @@ impl<'cx, 'tcx> Visitor<'tcx> for WritebackCx<'cx, 'tcx> {
 
 impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
     fn eval_closure_size(&mut self) {
-        let mut res: FxHashMap<LocalDefId, ClosureSizeProfileData<'tcx>> = Default::default();
-        for (&closure_def_id, data) in self.fcx.typeck_results.borrow().closure_size_eval.iter() {
-            let closure_hir_id = self.tcx().hir().local_def_id_to_hir_id(closure_def_id);
-
-            let data = self.resolve(*data, &closure_hir_id);
-
-            res.insert(closure_def_id, data);
-        }
-
-        self.typeck_results.closure_size_eval = res;
+        self.tcx().with_stable_hashing_context(|ref hcx| {
+            let fcx_typeck_results = self.fcx.typeck_results.borrow();
+
+            self.typeck_results.closure_size_eval = fcx_typeck_results
+                .closure_size_eval
+                .to_sorted(hcx, false)
+                .into_iter()
+                .map(|(&closure_def_id, data)| {
+                    let closure_hir_id = self.tcx().hir().local_def_id_to_hir_id(closure_def_id);
+                    let data = self.resolve(*data, &closure_hir_id);
+                    (closure_def_id, data)
+                })
+                .collect();
+        })
     }
-    fn visit_min_capture_map(&mut self) {
-        let mut min_captures_wb = ty::MinCaptureInformationMap::with_capacity_and_hasher(
-            self.fcx.typeck_results.borrow().closure_min_captures.len(),
-            Default::default(),
-        );
-        for (&closure_def_id, root_min_captures) in
-            self.fcx.typeck_results.borrow().closure_min_captures.iter()
-        {
-            let mut root_var_map_wb = ty::RootVariableMinCaptureList::with_capacity_and_hasher(
-                root_min_captures.len(),
-                Default::default(),
-            );
-            for (var_hir_id, min_list) in root_min_captures.iter() {
-                let min_list_wb = min_list
-                    .iter()
-                    .map(|captured_place| {
-                        let locatable = captured_place.info.path_expr_id.unwrap_or_else(|| {
-                            self.tcx().hir().local_def_id_to_hir_id(closure_def_id)
-                        });
-
-                        self.resolve(captured_place.clone(), &locatable)
-                    })
-                    .collect();
-                root_var_map_wb.insert(*var_hir_id, min_list_wb);
-            }
-            min_captures_wb.insert(closure_def_id, root_var_map_wb);
-        }
 
-        self.typeck_results.closure_min_captures = min_captures_wb;
+    fn visit_min_capture_map(&mut self) {
+        self.tcx().with_stable_hashing_context(|ref hcx| {
+            let fcx_typeck_results = self.fcx.typeck_results.borrow();
+
+            self.typeck_results.closure_min_captures = fcx_typeck_results
+                .closure_min_captures
+                .to_sorted(hcx, false)
+                .into_iter()
+                .map(|(&closure_def_id, root_min_captures)| {
+                    let root_var_map_wb = root_min_captures
+                        .iter()
+                        .map(|(var_hir_id, min_list)| {
+                            let min_list_wb = min_list
+                                .iter()
+                                .map(|captured_place| {
+                                    let locatable =
+                                        captured_place.info.path_expr_id.unwrap_or_else(|| {
+                                            self.tcx().hir().local_def_id_to_hir_id(closure_def_id)
+                                        });
+                                    self.resolve(captured_place.clone(), &locatable)
+                                })
+                                .collect();
+                            (*var_hir_id, min_list_wb)
+                        })
+                        .collect();
+                    (closure_def_id, root_var_map_wb)
+                })
+                .collect();
+        })
     }
 
     fn visit_fake_reads_map(&mut self) {
-        let mut resolved_closure_fake_reads: FxHashMap<
-            LocalDefId,
-            Vec<(HirPlace<'tcx>, FakeReadCause, hir::HirId)>,
-        > = Default::default();
-        for (&closure_def_id, fake_reads) in
-            self.fcx.typeck_results.borrow().closure_fake_reads.iter()
-        {
-            let mut resolved_fake_reads = Vec::<(HirPlace<'tcx>, FakeReadCause, hir::HirId)>::new();
-            for (place, cause, hir_id) in fake_reads.iter() {
-                let locatable = self.tcx().hir().local_def_id_to_hir_id(closure_def_id);
-
-                let resolved_fake_read = self.resolve(place.clone(), &locatable);
-                resolved_fake_reads.push((resolved_fake_read, *cause, *hir_id));
-            }
-            resolved_closure_fake_reads.insert(closure_def_id, resolved_fake_reads);
-        }
-        self.typeck_results.closure_fake_reads = resolved_closure_fake_reads;
+        self.tcx().with_stable_hashing_context(move |ref hcx| {
+            let fcx_typeck_results = self.fcx.typeck_results.borrow();
+
+            self.typeck_results.closure_fake_reads = fcx_typeck_results
+                .closure_fake_reads
+                .to_sorted(hcx, true)
+                .into_iter()
+                .map(|(&closure_def_id, fake_reads)| {
+                    let resolved_fake_reads = fake_reads
+                        .iter()
+                        .map(|(place, cause, hir_id)| {
+                            let locatable = self.tcx().hir().local_def_id_to_hir_id(closure_def_id);
+                            let resolved_fake_read = self.resolve(place.clone(), &locatable);
+                            (resolved_fake_read, *cause, *hir_id)
+                        })
+                        .collect();
+
+                    (closure_def_id, resolved_fake_reads)
+                })
+                .collect();
+        });
     }
 
     fn visit_closures(&mut self) {
@@ -470,7 +477,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
         assert_eq!(fcx_typeck_results.hir_owner, self.typeck_results.hir_owner);
         let common_hir_owner = fcx_typeck_results.hir_owner;
 
-        if self.rustc_dump_user_substs {
+        if self.rustc_dump_user_args {
             let sorted_user_provided_types =
                 fcx_typeck_results.user_provided_types().items_in_stable_order();
 
@@ -478,7 +485,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
             for (local_id, c_ty) in sorted_user_provided_types {
                 let hir_id = hir::HirId { owner: common_hir_owner, local_id };
 
-                if let ty::UserType::TypeOf(_, user_substs) = c_ty.value {
+                if let ty::UserType::TypeOf(_, user_args) = c_ty.value {
                     // This is a unit-testing mechanism.
                     let span = self.tcx().hir().span(hir_id);
                     // We need to buffer the errors in order to guarantee a consistent
@@ -486,7 +493,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
                     let err = self
                         .tcx()
                         .sess
-                        .struct_span_err(span, format!("user substs: {:?}", user_substs));
+                        .struct_span_err(span, format!("user args: {:?}", user_args));
                     err.buffer(&mut errors_buffer);
                 }
             }
@@ -520,7 +527,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
         let fcx_typeck_results = self.fcx.typeck_results.borrow();
         assert_eq!(fcx_typeck_results.hir_owner, self.typeck_results.hir_owner);
 
-        self.typeck_results.user_provided_sigs.extend(
+        self.typeck_results.user_provided_sigs.extend_unord(
             fcx_typeck_results.user_provided_sigs.items().map(|(&def_id, c_sig)| {
                 if cfg!(debug_assertions) && c_sig.has_infer() {
                     span_bug!(
@@ -540,10 +547,15 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
         assert_eq!(fcx_typeck_results.hir_owner, self.typeck_results.hir_owner);
         self.typeck_results.generator_interior_types =
             fcx_typeck_results.generator_interior_types.clone();
-        for (&expr_def_id, predicates) in fcx_typeck_results.generator_interior_predicates.iter() {
-            let predicates = self.resolve(predicates.clone(), &self.fcx.tcx.def_span(expr_def_id));
-            self.typeck_results.generator_interior_predicates.insert(expr_def_id, predicates);
-        }
+        self.tcx().with_stable_hashing_context(move |ref hcx| {
+            for (&expr_def_id, predicates) in
+                fcx_typeck_results.generator_interior_predicates.to_sorted(hcx, false).into_iter()
+            {
+                let predicates =
+                    self.resolve(predicates.clone(), &self.fcx.tcx.def_span(expr_def_id));
+                self.typeck_results.generator_interior_predicates.insert(expr_def_id, predicates);
+            }
+        })
     }
 
     #[instrument(skip(self), level = "debug")]
@@ -619,11 +631,11 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
         debug!(?n_ty);
 
         // Resolve any substitutions
-        if let Some(substs) = self.fcx.typeck_results.borrow().node_substs_opt(hir_id) {
-            let substs = self.resolve(substs, &span);
-            debug!("write_substs_to_tcx({:?}, {:?})", hir_id, substs);
-            assert!(!substs.has_infer() && !substs.has_placeholders());
-            self.typeck_results.node_substs_mut().insert(hir_id, substs);
+        if let Some(args) = self.fcx.typeck_results.borrow().node_args_opt(hir_id) {
+            let args = self.resolve(args, &span);
+            debug!("write_args_to_tcx({:?}, {:?})", hir_id, args);
+            assert!(!args.has_infer() && !args.has_placeholders());
+            self.typeck_results.node_args_mut().insert(hir_id, args);
         }
     }
 
diff --git a/compiler/rustc_incremental/src/persist/fs.rs b/compiler/rustc_incremental/src/persist/fs.rs
index 7708deecec7..929a1e149b6 100644
--- a/compiler/rustc_incremental/src/persist/fs.rs
+++ b/compiler/rustc_incremental/src/persist/fs.rs
@@ -730,13 +730,13 @@ pub fn garbage_collect_session_directories(sess: &Session) -> io::Result<()> {
             debug!("garbage_collect_session_directories() - inspecting: {}", directory_name);
 
             let Ok(timestamp) = extract_timestamp_from_session_dir(directory_name) else {
-            debug!(
-                "found session-dir with malformed timestamp: {}",
-                crate_directory.join(directory_name).display()
-            );
-            // Ignore it
-            return None;
-        };
+                debug!(
+                    "found session-dir with malformed timestamp: {}",
+                    crate_directory.join(directory_name).display()
+                );
+                // Ignore it
+                return None;
+            };
 
             if is_finalized(directory_name) {
                 let lock_file_path = crate_directory.join(lock_file_name);
diff --git a/compiler/rustc_index/src/bit_set.rs b/compiler/rustc_index/src/bit_set.rs
index 15bc3b4e388..12a7ecf8133 100644
--- a/compiler/rustc_index/src/bit_set.rs
+++ b/compiler/rustc_index/src/bit_set.rs
@@ -804,9 +804,7 @@ impl<'a, T: Idx> Iterator for ChunkedBitIter<'a, T> {
         // advance the iterator to the start of the next chunk, before proceeding in chunk sized
         // steps.
         while self.index % CHUNK_BITS != 0 {
-            let Some(item) = self.next() else {
-                return init
-            };
+            let Some(item) = self.next() else { return init };
             init = f(init, item);
         }
         let start_chunk = self.index / CHUNK_BITS;
diff --git a/compiler/rustc_infer/src/errors/mod.rs b/compiler/rustc_infer/src/errors/mod.rs
index 7e1fa08f23a..1ffa8633afd 100644
--- a/compiler/rustc_infer/src/errors/mod.rs
+++ b/compiler/rustc_infer/src/errors/mod.rs
@@ -363,7 +363,8 @@ impl AddToDiagnostic for AddLifetimeParamsSuggestion<'_> {
             let (
                 hir::Ty { kind: hir::TyKind::Ref(lifetime_sub, _), .. },
                 hir::Ty { kind: hir::TyKind::Ref(lifetime_sup, _), .. },
-            ) = (self.ty_sub, self.ty_sup) else {
+            ) = (self.ty_sub, self.ty_sup)
+            else {
                 return false;
             };
 
diff --git a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
index e57532e2de2..1fd5d2adf80 100644
--- a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
+++ b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
@@ -11,7 +11,7 @@ use crate::infer::canonical::{
 use crate::infer::InferCtxt;
 use rustc_middle::ty::flags::FlagComputation;
 use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
-use rustc_middle::ty::subst::GenericArg;
+use rustc_middle::ty::GenericArg;
 use rustc_middle::ty::{self, BoundVar, InferConst, List, Ty, TyCtxt, TypeFlags, TypeVisitableExt};
 use std::sync::atomic::Ordering;
 
diff --git a/compiler/rustc_infer/src/infer/canonical/mod.rs b/compiler/rustc_infer/src/infer/canonical/mod.rs
index f765c41a367..8ca2e403043 100644
--- a/compiler/rustc_infer/src/infer/canonical/mod.rs
+++ b/compiler/rustc_infer/src/infer/canonical/mod.rs
@@ -25,7 +25,7 @@ use crate::infer::{ConstVariableOrigin, ConstVariableOriginKind};
 use crate::infer::{InferCtxt, RegionVariableOrigin, TypeVariableOrigin, TypeVariableOriginKind};
 use rustc_index::IndexVec;
 use rustc_middle::ty::fold::TypeFoldable;
-use rustc_middle::ty::subst::GenericArg;
+use rustc_middle::ty::GenericArg;
 use rustc_middle::ty::{self, List, Ty, TyCtxt};
 use rustc_span::source_map::Span;
 
@@ -88,7 +88,7 @@ impl<'tcx> InferCtxt<'tcx> {
         universe_map: impl Fn(ty::UniverseIndex) -> ty::UniverseIndex,
     ) -> CanonicalVarValues<'tcx> {
         CanonicalVarValues {
-            var_values: self.tcx.mk_substs_from_iter(
+            var_values: self.tcx.mk_args_from_iter(
                 variables
                     .iter()
                     .map(|info| self.instantiate_canonical_var(span, info, &universe_map)),
diff --git a/compiler/rustc_infer/src/infer/canonical/query_response.rs b/compiler/rustc_infer/src/infer/canonical/query_response.rs
index 9c3ab04deae..ed101082130 100644
--- a/compiler/rustc_infer/src/infer/canonical/query_response.rs
+++ b/compiler/rustc_infer/src/infer/canonical/query_response.rs
@@ -25,8 +25,8 @@ use rustc_middle::arena::ArenaAllocatable;
 use rustc_middle::mir::ConstraintCategory;
 use rustc_middle::ty::fold::TypeFoldable;
 use rustc_middle::ty::relate::TypeRelation;
-use rustc_middle::ty::subst::{GenericArg, GenericArgKind};
 use rustc_middle::ty::{self, BoundVar, ToPredicate, Ty, TyCtxt};
+use rustc_middle::ty::{GenericArg, GenericArgKind};
 use rustc_span::{Span, Symbol};
 use std::fmt::Debug;
 use std::iter;
@@ -484,7 +484,7 @@ impl<'tcx> InferCtxt<'tcx> {
         // given variable in the loop above, use that. Otherwise, use
         // a fresh inference variable.
         let result_subst = CanonicalVarValues {
-            var_values: self.tcx.mk_substs_from_iter(
+            var_values: self.tcx.mk_args_from_iter(
                 query_response.variables.iter().enumerate().map(|(index, info)| {
                     if info.is_existential() {
                         match opt_values[BoundVar::new(index)] {
@@ -520,7 +520,7 @@ impl<'tcx> InferCtxt<'tcx> {
                 self.at(cause, param_env)
                     .eq(
                         DefineOpaqueTypes::Yes,
-                        Ty::new_opaque(self.tcx, a.def_id.to_def_id(), a.substs),
+                        Ty::new_opaque(self.tcx, a.def_id.to_def_id(), a.args),
                         b,
                     )?
                     .obligations,
diff --git a/compiler/rustc_infer/src/infer/canonical/substitute.rs b/compiler/rustc_infer/src/infer/canonical/substitute.rs
index cac3b407251..f368b30fbd1 100644
--- a/compiler/rustc_infer/src/infer/canonical/substitute.rs
+++ b/compiler/rustc_infer/src/infer/canonical/substitute.rs
@@ -8,7 +8,7 @@
 
 use crate::infer::canonical::{Canonical, CanonicalVarValues};
 use rustc_middle::ty::fold::{FnMutDelegate, TypeFoldable};
-use rustc_middle::ty::subst::GenericArgKind;
+use rustc_middle::ty::GenericArgKind;
 use rustc_middle::ty::{self, TyCtxt};
 
 /// FIXME(-Ztrait-solver=next): This or public because it is shared with the
diff --git a/compiler/rustc_infer/src/infer/combine.rs b/compiler/rustc_infer/src/infer/combine.rs
index a9cdb8c51cf..38f8ad744a6 100644
--- a/compiler/rustc_infer/src/infer/combine.rs
+++ b/compiler/rustc_infer/src/infer/combine.rs
@@ -254,7 +254,7 @@ impl<'tcx> InferCtxt<'tcx> {
     /// in `ct` with `ct` itself.
     ///
     /// This is especially important as unevaluated consts use their parents generics.
-    /// They therefore often contain unused substs, making these errors far more likely.
+    /// They therefore often contain unused args, making these errors far more likely.
     ///
     /// A good example of this is the following:
     ///
@@ -272,12 +272,12 @@ impl<'tcx> InferCtxt<'tcx> {
     /// ```
     ///
     /// Here `3 + 4` ends up as `ConstKind::Unevaluated` which uses the generics
-    /// of `fn bind` (meaning that its substs contain `N`).
+    /// of `fn bind` (meaning that its args contain `N`).
     ///
     /// `bind(arr)` now infers that the type of `arr` must be `[u8; N]`.
     /// The assignment `arr = bind(arr)` now tries to equate `N` with `3 + 4`.
     ///
-    /// As `3 + 4` contains `N` in its substs, this must not succeed.
+    /// As `3 + 4` contains `N` in its args, this must not succeed.
     ///
     /// See `tests/ui/const-generics/occurs-check/` for more examples where this is relevant.
     #[instrument(level = "debug", skip(self))]
diff --git a/compiler/rustc_infer/src/infer/equate.rs b/compiler/rustc_infer/src/infer/equate.rs
index 495c250a77d..1dbab48fd6c 100644
--- a/compiler/rustc_infer/src/infer/equate.rs
+++ b/compiler/rustc_infer/src/infer/equate.rs
@@ -5,7 +5,7 @@ use super::combine::{CombineFields, ObligationEmittingRelation};
 use super::Subtype;
 
 use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation};
-use rustc_middle::ty::subst::SubstsRef;
+use rustc_middle::ty::GenericArgsRef;
 use rustc_middle::ty::TyVar;
 use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
 
@@ -43,12 +43,12 @@ impl<'tcx> TypeRelation<'tcx> for Equate<'_, '_, 'tcx> {
         self.a_is_expected
     }
 
-    fn relate_item_substs(
+    fn relate_item_args(
         &mut self,
         _item_def_id: DefId,
-        a_subst: SubstsRef<'tcx>,
-        b_subst: SubstsRef<'tcx>,
-    ) -> RelateResult<'tcx, SubstsRef<'tcx>> {
+        a_arg: GenericArgsRef<'tcx>,
+        b_arg: GenericArgsRef<'tcx>,
+    ) -> RelateResult<'tcx, GenericArgsRef<'tcx>> {
         // N.B., once we are equating types, we don't care about
         // variance, so don't try to lookup the variance here. This
         // also avoids some cycles (e.g., #41849) since looking up
@@ -56,7 +56,7 @@ impl<'tcx> TypeRelation<'tcx> for Equate<'_, '_, 'tcx> {
         // performing trait matching (which then performs equality
         // unification).
 
-        relate::relate_substs(self, a_subst, b_subst)
+        relate::relate_args(self, a_arg, b_arg)
     }
 
     fn relate_with_variance<T: Relate<'tcx>>(
diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
index b826ced0453..bf46f9881d4 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
@@ -315,7 +315,7 @@ pub fn unexpected_hidden_region_diagnostic<'tcx>(
 ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
     let mut err = tcx.sess.create_err(errors::OpaqueCapturesLifetime {
         span,
-        opaque_ty: Ty::new_opaque(tcx, opaque_ty_key.def_id.to_def_id(), opaque_ty_key.substs),
+        opaque_ty: Ty::new_opaque(tcx, opaque_ty_key.def_id.to_def_id(), opaque_ty_key.args),
         opaque_ty_span: tcx.def_span(opaque_ty_key.def_id),
     });
 
@@ -386,16 +386,16 @@ pub fn unexpected_hidden_region_diagnostic<'tcx>(
 
 impl<'tcx> InferCtxt<'tcx> {
     pub fn get_impl_future_output_ty(&self, ty: Ty<'tcx>) -> Option<Ty<'tcx>> {
-        let (def_id, substs) = match *ty.kind() {
-            ty::Alias(_, ty::AliasTy { def_id, substs, .. })
+        let (def_id, args) = match *ty.kind() {
+            ty::Alias(_, ty::AliasTy { def_id, args, .. })
                 if matches!(self.tcx.def_kind(def_id), DefKind::OpaqueTy) =>
             {
-                (def_id, substs)
+                (def_id, args)
             }
-            ty::Alias(_, ty::AliasTy { def_id, substs, .. })
+            ty::Alias(_, ty::AliasTy { def_id, args, .. })
                 if self.tcx.is_impl_trait_in_trait(def_id) =>
             {
-                (def_id, substs)
+                (def_id, args)
             }
             _ => return None,
         };
@@ -403,7 +403,7 @@ impl<'tcx> InferCtxt<'tcx> {
         let future_trait = self.tcx.require_lang_item(LangItem::Future, None);
         let item_def_id = self.tcx.associated_item_def_ids(future_trait)[0];
 
-        self.tcx.explicit_item_bounds(def_id).subst_iter_copied(self.tcx, substs).find_map(
+        self.tcx.explicit_item_bounds(def_id).arg_iter_copied(self.tcx, args).find_map(
             |(predicate, _)| {
                 predicate
                     .kind()
@@ -573,7 +573,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
         use hir::def_id::CrateNum;
         use rustc_hir::definitions::DisambiguatedDefPathData;
         use ty::print::Printer;
-        use ty::subst::GenericArg;
+        use ty::GenericArg;
 
         struct AbsolutePathPrinter<'tcx> {
             tcx: TyCtxt<'tcx>,
@@ -711,10 +711,10 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                 {
                     // don't show type `_`
                     if span.desugaring_kind() == Some(DesugaringKind::ForLoop)
-                        && let ty::Adt(def, substs) = ty.kind()
+                        && let ty::Adt(def, args) = ty.kind()
                         && Some(def.did()) == self.tcx.get_diagnostic_item(sym::Option)
                     {
-                        err.span_label(span, format!("this is an iterator with items of type `{}`", substs.type_at(0)));
+                        err.span_label(span, format!("this is an iterator with items of type `{}`", args.type_at(0)));
                     } else {
                     err.span_label(span, format!("this expression has type `{}`", ty));
                 }
@@ -908,7 +908,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
         value: &mut DiagnosticStyledString,
         other_value: &mut DiagnosticStyledString,
         name: String,
-        sub: ty::subst::SubstsRef<'tcx>,
+        sub: ty::GenericArgsRef<'tcx>,
         pos: usize,
         other_ty: Ty<'tcx>,
     ) {
@@ -986,9 +986,9 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
         other_path: String,
         other_ty: Ty<'tcx>,
     ) -> Option<()> {
-        // FIXME/HACK: Go back to `SubstsRef` to use its inherent methods,
+        // FIXME/HACK: Go back to `GenericArgsRef` to use its inherent methods,
         // ideally that shouldn't be necessary.
-        let sub = self.tcx.mk_substs(sub);
+        let sub = self.tcx.mk_args(sub);
         for (i, ta) in sub.types().enumerate() {
             if ta == other_ty {
                 self.highlight_outer(&mut t1_out, &mut t2_out, path, sub, i, other_ty);
@@ -1180,9 +1180,9 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                 let did1 = def1.did();
                 let did2 = def2.did();
                 let sub_no_defaults_1 =
-                    self.tcx.generics_of(did1).own_substs_no_defaults(self.tcx, sub1);
+                    self.tcx.generics_of(did1).own_args_no_defaults(self.tcx, sub1);
                 let sub_no_defaults_2 =
-                    self.tcx.generics_of(did2).own_substs_no_defaults(self.tcx, sub2);
+                    self.tcx.generics_of(did2).own_args_no_defaults(self.tcx, sub2);
                 let mut values = (DiagnosticStyledString::new(), DiagnosticStyledString::new());
                 let path1 = self.tcx.def_path_str(did1);
                 let path2 = self.tcx.def_path_str(did2);
@@ -1403,11 +1403,11 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
             }
 
             // When encountering tuples of the same size, highlight only the differing types
-            (&ty::Tuple(substs1), &ty::Tuple(substs2)) if substs1.len() == substs2.len() => {
+            (&ty::Tuple(args1), &ty::Tuple(args2)) if args1.len() == args2.len() => {
                 let mut values =
                     (DiagnosticStyledString::normal("("), DiagnosticStyledString::normal("("));
-                let len = substs1.len();
-                for (i, (left, right)) in substs1.iter().zip(substs2).enumerate() {
+                let len = args1.len();
+                for (i, (left, right)) in args1.iter().zip(args2).enumerate() {
                     let (x1, x2) = self.cmp(left, right);
                     (values.0).0.extend(x1.0);
                     (values.1).0.extend(x2.0);
@@ -1423,35 +1423,34 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                 values
             }
 
-            (ty::FnDef(did1, substs1), ty::FnDef(did2, substs2)) => {
-                let sig1 = self.tcx.fn_sig(*did1).subst(self.tcx, substs1);
-                let sig2 = self.tcx.fn_sig(*did2).subst(self.tcx, substs2);
+            (ty::FnDef(did1, args1), ty::FnDef(did2, args2)) => {
+                let sig1 = self.tcx.fn_sig(*did1).instantiate(self.tcx, args1);
+                let sig2 = self.tcx.fn_sig(*did2).instantiate(self.tcx, args2);
                 let mut values = self.cmp_fn_sig(&sig1, &sig2);
-                let path1 = format!(" {{{}}}", self.tcx.def_path_str_with_substs(*did1, substs1));
-                let path2 = format!(" {{{}}}", self.tcx.def_path_str_with_substs(*did2, substs2));
+                let path1 = format!(" {{{}}}", self.tcx.def_path_str_with_args(*did1, args1));
+                let path2 = format!(" {{{}}}", self.tcx.def_path_str_with_args(*did2, args2));
                 let same_path = path1 == path2;
                 values.0.push(path1, !same_path);
                 values.1.push(path2, !same_path);
                 values
             }
 
-            (ty::FnDef(did1, substs1), ty::FnPtr(sig2)) => {
-                let sig1 = self.tcx.fn_sig(*did1).subst(self.tcx, substs1);
+            (ty::FnDef(did1, args1), ty::FnPtr(sig2)) => {
+                let sig1 = self.tcx.fn_sig(*did1).instantiate(self.tcx, args1);
                 let mut values = self.cmp_fn_sig(&sig1, sig2);
                 values.0.push_highlighted(format!(
                     " {{{}}}",
-                    self.tcx.def_path_str_with_substs(*did1, substs1)
+                    self.tcx.def_path_str_with_args(*did1, args1)
                 ));
                 values
             }
 
-            (ty::FnPtr(sig1), ty::FnDef(did2, substs2)) => {
-                let sig2 = self.tcx.fn_sig(*did2).subst(self.tcx, substs2);
+            (ty::FnPtr(sig1), ty::FnDef(did2, args2)) => {
+                let sig2 = self.tcx.fn_sig(*did2).instantiate(self.tcx, args2);
                 let mut values = self.cmp_fn_sig(sig1, &sig2);
-                values.1.push_normal(format!(
-                    " {{{}}}",
-                    self.tcx.def_path_str_with_substs(*did2, substs2)
-                ));
+                values
+                    .1
+                    .push_normal(format!(" {{{}}}", self.tcx.def_path_str_with_args(*did2, args2)));
                 values
             }
 
@@ -2109,14 +2108,13 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
         found: Ty<'tcx>,
         expected_fields: &List<Ty<'tcx>>,
     ) -> Option<TypeErrorAdditionalDiags> {
-        let [expected_tup_elem] = expected_fields[..] else { return None};
+        let [expected_tup_elem] = expected_fields[..] else { return None };
 
         if !self.same_type_modulo_infer(expected_tup_elem, found) {
             return None;
         }
 
-        let Ok(code) = self.tcx.sess().source_map().span_to_snippet(span)
-            else { return None };
+        let Ok(code) = self.tcx.sess().source_map().span_to_snippet(span) else { return None };
 
         let sugg = if code.starts_with('(') && code.ends_with(')') {
             let before_close = span.hi() - BytePos::from_u32(1);
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 a90a41f5d70..b4d8205fd6d 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
@@ -18,7 +18,7 @@ use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKin
 use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow};
 use rustc_middle::ty::print::{FmtPrinter, PrettyPrinter, Print, Printer};
 use rustc_middle::ty::{self, InferConst};
-use rustc_middle::ty::{GenericArg, GenericArgKind, SubstsRef};
+use rustc_middle::ty::{GenericArg, GenericArgKind, GenericArgsRef};
 use rustc_middle::ty::{IsSuggestable, Ty, TyCtxt, TypeckResults};
 use rustc_span::symbol::{kw, sym, Ident};
 use rustc_span::{BytePos, Span};
@@ -226,8 +226,8 @@ fn ty_to_string<'tcx>(
 /// something users are familiar with. Directly printing the `fn_sig` of closures also
 /// doesn't work as they actually use the "rust-call" API.
 fn closure_as_fn_str<'tcx>(infcx: &InferCtxt<'tcx>, ty: Ty<'tcx>) -> String {
-    let ty::Closure(_, substs) = ty.kind() else { unreachable!() };
-    let fn_sig = substs.as_closure().sig();
+    let ty::Closure(_, args) = ty.kind() else { unreachable!() };
+    let fn_sig = args.as_closure().sig();
     let args = fn_sig
         .inputs()
         .skip_binder()
@@ -419,7 +419,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
         }
 
         let Some(InferSource { span, kind }) = local_visitor.infer_source else {
-            return self.bad_inference_failure_err(failure_span, arg_data, error_code)
+            return self.bad_inference_failure_err(failure_span, arg_data, error_code);
         };
 
         let (source_kind, name) = kind.ty_localized_msg(self);
@@ -524,9 +524,9 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                     });
                 }
             }
-            InferSourceKind::FullyQualifiedMethodCall { receiver, successor, substs, def_id } => {
+            InferSourceKind::FullyQualifiedMethodCall { receiver, successor, args, def_id } => {
                 let printer = fmt_printer(self, Namespace::ValueNS);
-                let def_path = printer.print_def_path(def_id, substs).unwrap().into_buffer();
+                let def_path = printer.print_def_path(def_id, args).unwrap().into_buffer();
 
                 // We only care about whether we have to add `&` or `&mut ` for now.
                 // This is the case if the last adjustment is a borrow and the
@@ -659,7 +659,7 @@ enum InferSourceKind<'tcx> {
         /// If the method has other arguments, this is ", " and the start of the first argument,
         /// while for methods without arguments this is ")" and the end of the method call.
         successor: (&'static str, BytePos),
-        substs: SubstsRef<'tcx>,
+        args: GenericArgsRef<'tcx>,
         def_id: DefId,
     },
     ClosureReturn {
@@ -710,7 +710,7 @@ impl<'tcx> InferSourceKind<'tcx> {
 #[derive(Debug)]
 struct InsertableGenericArgs<'tcx> {
     insert_span: Span,
-    substs: SubstsRef<'tcx>,
+    args: GenericArgsRef<'tcx>,
     generics_def_id: DefId,
     def_id: DefId,
     have_turbofish: bool,
@@ -774,11 +774,11 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> {
                     ty::Closure(..) => 1000,
                     ty::FnDef(..) => 150,
                     ty::FnPtr(..) => 30,
-                    ty::Adt(def, substs) => {
+                    ty::Adt(def, args) => {
                         5 + self
                             .tcx
                             .generics_of(def.did())
-                            .own_substs_no_defaults(self.tcx, substs)
+                            .own_args_no_defaults(self.tcx, args)
                             .iter()
                             .map(|&arg| self.arg_cost(arg))
                             .sum::<usize>()
@@ -805,8 +805,8 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> {
                 };
                 variant_cost + generic_args.iter().map(|&arg| ctx.arg_cost(arg)).sum::<usize>()
             }
-            InferSourceKind::FullyQualifiedMethodCall { substs, .. } => {
-                20 + substs.iter().map(|arg| ctx.arg_cost(arg)).sum::<usize>()
+            InferSourceKind::FullyQualifiedMethodCall { args, .. } => {
+                20 + args.iter().map(|arg| ctx.arg_cost(arg)).sum::<usize>()
             }
             InferSourceKind::ClosureReturn { ty, should_wrap_expr, .. } => {
                 30 + ctx.ty_cost(ty) + if should_wrap_expr.is_some() { 10 } else { 0 }
@@ -840,9 +840,9 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> {
         }
     }
 
-    fn node_substs_opt(&self, hir_id: HirId) -> Option<SubstsRef<'tcx>> {
-        let substs = self.typeck_results.node_substs_opt(hir_id);
-        self.infcx.resolve_vars_if_possible(substs)
+    fn node_args_opt(&self, hir_id: HirId) -> Option<GenericArgsRef<'tcx>> {
+        let args = self.typeck_results.node_args_opt(hir_id);
+        self.infcx.resolve_vars_if_possible(args)
     }
 
     fn opt_node_type(&self, hir_id: HirId) -> Option<Ty<'tcx>> {
@@ -923,15 +923,15 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> {
         false
     }
 
-    fn expr_inferred_subst_iter(
+    fn expr_inferred_arg_iter(
         &self,
         expr: &'tcx hir::Expr<'tcx>,
     ) -> Box<dyn Iterator<Item = InsertableGenericArgs<'tcx>> + 'a> {
         let tcx = self.infcx.tcx;
         match expr.kind {
             hir::ExprKind::Path(ref path) => {
-                if let Some(substs) = self.node_substs_opt(expr.hir_id) {
-                    return self.path_inferred_subst_iter(expr.hir_id, substs, path);
+                if let Some(args) = self.node_args_opt(expr.hir_id) {
+                    return self.path_inferred_arg_iter(expr.hir_id, args, path);
                 }
             }
             // FIXME(#98711): Ideally we would also deal with type relative
@@ -943,7 +943,7 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> {
             // However, the `type_dependent_def_id` for `Self::Output` in an
             // impl is currently the `DefId` of `Output` in the trait definition
             // which makes this somewhat difficult and prevents us from just
-            // using `self.path_inferred_subst_iter` here.
+            // using `self.path_inferred_arg_iter` here.
             hir::ExprKind::Struct(&hir::QPath::Resolved(_self_ty, path), _, _)
             // FIXME(TaKO8Ki): Ideally we should support this. For that
             // we have to map back from the self type to the
@@ -953,9 +953,9 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> {
             // a example.
             if !matches!(path.res, Res::Def(DefKind::TyAlias, _)) => {
                 if let Some(ty) = self.opt_node_type(expr.hir_id)
-                    && let ty::Adt(_, substs) = ty.kind()
+                    && let ty::Adt(_, args) = ty.kind()
                 {
-                    return Box::new(self.resolved_path_inferred_subst_iter(path, substs));
+                    return Box::new(self.resolved_path_inferred_arg_iter(path, args));
                 }
             }
             hir::ExprKind::MethodCall(segment, ..) => {
@@ -965,12 +965,12 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> {
                         if generics.has_impl_trait() {
                             None?
                         }
-                        let substs = self.node_substs_opt(expr.hir_id)?;
+                        let args = self.node_args_opt(expr.hir_id)?;
                         let span = tcx.hir().span(segment.hir_id);
                         let insert_span = segment.ident.span.shrink_to_hi().with_hi(span.hi());
                         InsertableGenericArgs {
                             insert_span,
-                            substs,
+                            args,
                             generics_def_id: def_id,
                             def_id,
                             have_turbofish: false,
@@ -985,10 +985,10 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> {
         Box::new(iter::empty())
     }
 
-    fn resolved_path_inferred_subst_iter(
+    fn resolved_path_inferred_arg_iter(
         &self,
         path: &'tcx hir::Path<'tcx>,
-        substs: SubstsRef<'tcx>,
+        args: GenericArgsRef<'tcx>,
     ) -> impl Iterator<Item = InsertableGenericArgs<'tcx>> + 'a {
         let tcx = self.infcx.tcx;
         let have_turbofish = path.segments.iter().any(|segment| {
@@ -1009,7 +1009,7 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> {
                 path.segments.last().unwrap().ident.span.shrink_to_hi().with_hi(path.span.hi());
             InsertableGenericArgs {
                 insert_span,
-                substs,
+                args,
                 generics_def_id,
                 def_id: path.res.def_id(),
                 have_turbofish,
@@ -1029,7 +1029,7 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> {
                 let insert_span = segment.ident.span.shrink_to_hi().with_hi(span.hi());
                 Some(InsertableGenericArgs {
                     insert_span,
-                    substs,
+                    args,
                     generics_def_id,
                     def_id: res.def_id(),
                     have_turbofish,
@@ -1038,16 +1038,16 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> {
             .chain(last_segment_using_path_data)
     }
 
-    fn path_inferred_subst_iter(
+    fn path_inferred_arg_iter(
         &self,
         hir_id: HirId,
-        substs: SubstsRef<'tcx>,
+        args: GenericArgsRef<'tcx>,
         qpath: &'tcx hir::QPath<'tcx>,
     ) -> Box<dyn Iterator<Item = InsertableGenericArgs<'tcx>> + 'a> {
         let tcx = self.infcx.tcx;
         match qpath {
             hir::QPath::Resolved(_self_ty, path) => {
-                Box::new(self.resolved_path_inferred_subst_iter(path, substs))
+                Box::new(self.resolved_path_inferred_arg_iter(path, args))
             }
             hir::QPath::TypeRelative(ty, segment) => {
                 let Some(def_id) = self.typeck_results.type_dependent_def_id(hir_id) else {
@@ -1063,7 +1063,7 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> {
                     let insert_span = segment.ident.span.shrink_to_hi().with_hi(span.hi());
                     InsertableGenericArgs {
                         insert_span,
-                        substs,
+                        args,
                         generics_def_id: def_id,
                         def_id,
                         have_turbofish: false,
@@ -1072,10 +1072,10 @@ 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.type_of(parent_def_id).subst(tcx, substs);
+                    let parent_ty = tcx.type_of(parent_def_id).instantiate(tcx, args);
                     match (parent_ty.kind(), &ty.kind) {
                         (
-                            ty::Adt(def, substs),
+                            ty::Adt(def, args),
                             hir::TyKind::Path(hir::QPath::Resolved(_self_ty, path)),
                         ) => {
                             if tcx.res_generics_def_id(path.res) != Some(def.did()) {
@@ -1092,14 +1092,13 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> {
                                     // so there's nothing for us to do here.
                                     Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } => {}
                                     _ => warn!(
-                                        "unexpected path: def={:?} substs={:?} path={:?}",
-                                        def, substs, path,
+                                        "unexpected path: def={:?} args={:?} path={:?}",
+                                        def, args, path,
                                     ),
                                 }
                             } else {
                                 return Box::new(
-                                    self.resolved_path_inferred_subst_iter(path, substs)
-                                        .chain(segment),
+                                    self.resolved_path_inferred_arg_iter(path, args).chain(segment),
                                 );
                             }
                         }
@@ -1157,9 +1156,7 @@ impl<'a, 'tcx> Visitor<'tcx> for FindInferSourceVisitor<'a, 'tcx> {
                 continue;
             }
 
-            let Some(param_ty) = self.opt_node_type(param.hir_id) else {
-                continue
-            };
+            let Some(param_ty) = self.opt_node_type(param.hir_id) else { continue };
 
             if self.generic_arg_contains_target(param_ty.into()) {
                 self.update_infer_source(InferSource {
@@ -1189,27 +1186,27 @@ impl<'a, 'tcx> Visitor<'tcx> for FindInferSourceVisitor<'a, 'tcx> {
             _ => intravisit::walk_expr(self, expr),
         }
 
-        for args in self.expr_inferred_subst_iter(expr) {
+        for args in self.expr_inferred_arg_iter(expr) {
             debug!(?args);
             let InsertableGenericArgs {
                 insert_span,
-                substs,
+                args,
                 generics_def_id,
                 def_id,
                 have_turbofish,
             } = args;
             let generics = tcx.generics_of(generics_def_id);
             if let Some(mut argument_index) = generics
-                .own_substs(substs)
+                .own_args(args)
                 .iter()
                 .position(|&arg| self.generic_arg_contains_target(arg))
             {
                 if generics.parent.is_none() && generics.has_self {
                     argument_index += 1;
                 }
-                let substs = self.infcx.resolve_vars_if_possible(substs);
-                let generic_args = &generics.own_substs_no_defaults(tcx, substs)
-                    [generics.own_counts().lifetimes..];
+                let args = self.infcx.resolve_vars_if_possible(args);
+                let generic_args =
+                    &generics.own_args_no_defaults(tcx, args)[generics.own_counts().lifetimes..];
                 let span = match expr.kind {
                     ExprKind::MethodCall(path, ..) => path.ident.span,
                     _ => expr.span,
@@ -1232,10 +1229,10 @@ impl<'a, 'tcx> Visitor<'tcx> for FindInferSourceVisitor<'a, 'tcx> {
         if let Some(node_ty) = self.opt_node_type(expr.hir_id) {
             if let (
                 &ExprKind::Closure(&Closure { fn_decl, body, fn_decl_span, .. }),
-                ty::Closure(_, substs),
+                ty::Closure(_, args),
             ) = (&expr.kind, node_ty.kind())
             {
-                let output = substs.as_closure().sig().output().skip_binder();
+                let output = args.as_closure().sig().output().skip_binder();
                 if self.generic_arg_contains_target(output.into()) {
                     let body = self.infcx.tcx.hir().body(body);
                     let should_wrap_expr = if matches!(body.value.kind, ExprKind::Block(..)) {
@@ -1261,22 +1258,22 @@ impl<'a, 'tcx> Visitor<'tcx> for FindInferSourceVisitor<'a, 'tcx> {
             })
             .any(|generics| generics.has_impl_trait())
         };
-        if let ExprKind::MethodCall(path, receiver, args, span) = expr.kind
-            && let Some(substs) = self.node_substs_opt(expr.hir_id)
-            && substs.iter().any(|arg| self.generic_arg_contains_target(arg))
+        if let ExprKind::MethodCall(path, receiver, method_args, span) = expr.kind
+            && let Some(args) = self.node_args_opt(expr.hir_id)
+            && args.iter().any(|arg| self.generic_arg_contains_target(arg))
             && let Some(def_id) = self.typeck_results.type_dependent_def_id(expr.hir_id)
             && self.infcx.tcx.trait_of_item(def_id).is_some()
             && !has_impl_trait(def_id)
         {
             let successor =
-                args.get(0).map_or_else(|| (")", span.hi()), |arg| (", ", arg.span.lo()));
-            let substs = self.infcx.resolve_vars_if_possible(substs);
+                method_args.get(0).map_or_else(|| (")", span.hi()), |arg| (", ", arg.span.lo()));
+            let args = self.infcx.resolve_vars_if_possible(args);
             self.update_infer_source(InferSource {
                 span: path.ident.span,
                 kind: InferSourceKind::FullyQualifiedMethodCall {
                     receiver,
                     successor,
-                    substs,
+                    args,
                     def_id,
                 }
             })
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 2c63a390410..6901955af65 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
@@ -38,8 +38,9 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
         let ObligationCauseCode::MatchImpl(parent, impl_def_id) = code else {
             return None;
         };
-        let (ObligationCauseCode::BindingObligation(_, binding_span) | ObligationCauseCode::ExprBindingObligation(_, binding_span, ..))
-            = *parent.code() else {
+        let (ObligationCauseCode::BindingObligation(_, binding_span)
+        | ObligationCauseCode::ExprBindingObligation(_, binding_span, ..)) = *parent.code()
+        else {
             return None;
         };
 
@@ -67,12 +68,13 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
             let hir::Node::Item(hir::Item {
                 kind: hir::ItemKind::Impl(hir::Impl { self_ty: impl_self_ty, .. }),
                 ..
-            }) = impl_node else {
+            }) = impl_node
+            else {
                 bug!("Node not an impl.");
             };
 
             // Next, let's figure out the set of trait objects with implicit static bounds
-            let ty = self.tcx().type_of(*impl_def_id).subst_identity();
+            let ty = self.tcx().type_of(*impl_def_id).instantiate_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 0b3bc1ce6b3..f903f7a49ef 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
@@ -13,7 +13,7 @@ use rustc_hir::def::Namespace;
 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::GenericArgsRef;
 use rustc_middle::ty::{self, RePlaceholder, Region, TyCtxt};
 
 use std::fmt;
@@ -196,11 +196,11 @@ impl<'tcx> NiceRegionError<'_, 'tcx> {
         sup_placeholder: Option<Region<'tcx>>,
         value_pairs: &ValuePairs<'tcx>,
     ) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> {
-        let (expected_substs, found_substs, trait_def_id) = match value_pairs {
+        let (expected_args, found_args, trait_def_id) = match value_pairs {
             ValuePairs::TraitRefs(ExpectedFound { expected, found })
                 if expected.def_id == found.def_id =>
             {
-                (expected.substs, found.substs, expected.def_id)
+                (expected.args, found.args, expected.def_id)
             }
             ValuePairs::PolyTraitRefs(ExpectedFound { expected, found })
                 if expected.def_id() == found.def_id() =>
@@ -208,7 +208,7 @@ impl<'tcx> NiceRegionError<'_, 'tcx> {
                 // It's possible that the placeholders come from a binder
                 // outside of this value pair. Use `no_bound_vars` as a
                 // simple heuristic for that.
-                (expected.no_bound_vars()?.substs, found.no_bound_vars()?.substs, expected.def_id())
+                (expected.no_bound_vars()?.args, found.no_bound_vars()?.args, expected.def_id())
             }
             _ => return None,
         };
@@ -219,8 +219,8 @@ impl<'tcx> NiceRegionError<'_, 'tcx> {
             sub_placeholder,
             sup_placeholder,
             trait_def_id,
-            expected_substs,
-            found_substs,
+            expected_args,
+            found_args,
         ))
     }
 
@@ -241,8 +241,8 @@ impl<'tcx> NiceRegionError<'_, 'tcx> {
         sub_placeholder: Option<Region<'tcx>>,
         sup_placeholder: Option<Region<'tcx>>,
         trait_def_id: DefId,
-        expected_substs: SubstsRef<'tcx>,
-        actual_substs: SubstsRef<'tcx>,
+        expected_args: GenericArgsRef<'tcx>,
+        actual_args: GenericArgsRef<'tcx>,
     ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
         let span = cause.span();
 
@@ -264,12 +264,12 @@ impl<'tcx> NiceRegionError<'_, 'tcx> {
         let expected_trait_ref = self.cx.resolve_vars_if_possible(ty::TraitRef::new(
             self.cx.tcx,
             trait_def_id,
-            expected_substs,
+            expected_args,
         ));
         let actual_trait_ref = self.cx.resolve_vars_if_possible(ty::TraitRef::new(
             self.cx.tcx,
             trait_def_id,
-            actual_substs,
+            actual_args,
         ));
 
         // Search the expected and actual trait references to see (a)
@@ -413,9 +413,9 @@ impl<'tcx> NiceRegionError<'_, 'tcx> {
             if self_ty.value.is_closure() && self.tcx().is_fn_trait(expected_trait_ref.value.def_id)
             {
                 let closure_sig = self_ty.map(|closure| {
-                    if let ty::Closure(_, substs) = closure.kind() {
+                    if let ty::Closure(_, args) = closure.kind() {
                         self.tcx().signature_unclosure(
-                            substs.as_closure().sig(),
+                            args.as_closure().sig(),
                             rustc_hir::Unsafety::Normal,
                         )
                     } else {
diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs
index a9b485a6f7e..cc92bfbfdfe 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs
@@ -288,7 +288,7 @@ pub fn suggest_new_region_bound(
 
                 // Get the identity type for this RPIT
                 let did = item_id.owner_id.to_def_id();
-                let ty = Ty::new_opaque(tcx, did, ty::InternalSubsts::identity_for_item(tcx, did));
+                let ty = Ty::new_opaque(tcx, did, ty::GenericArgs::identity_for_item(tcx, did));
 
                 if let Some(span) = opaque.bounds.iter().find_map(|arg| match arg {
                     GenericBound::Outlives(Lifetime {
@@ -493,7 +493,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
             tcx,
             ctxt.param_env,
             ctxt.assoc_item.def_id,
-            self.cx.resolve_vars_if_possible(ctxt.substs),
+            self.cx.resolve_vars_if_possible(ctxt.args),
         ) else {
             return false;
         };
@@ -503,7 +503,9 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
 
         // Get the `Ident` of the method being called and the corresponding `impl` (to point at
         // `Bar` in `impl Foo for dyn Bar {}` and the definition of the method being called).
-        let Some((ident, self_ty)) = NiceRegionError::get_impl_ident_and_self_ty_from_trait(tcx, instance.def_id(), &v.0) else {
+        let Some((ident, self_ty)) =
+            NiceRegionError::get_impl_ident_and_self_ty_from_trait(tcx, instance.def_id(), &v.0)
+        else {
             return false;
         };
 
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 c5ef48fe3da..2775b5ded03 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
@@ -65,7 +65,7 @@ pub fn find_param_with_region<'tcx>(
 
     let owner_id = hir.body_owner(body_id);
     let fn_decl = hir.fn_decl_by_hir_id(owner_id).unwrap();
-    let poly_fn_sig = tcx.fn_sig(id).subst_identity();
+    let poly_fn_sig = tcx.fn_sig(id).instantiate_identity();
 
     let fn_sig = tcx.liberate_late_bound_regions(id, poly_fn_sig);
     let body = hir.body(body_id);
@@ -123,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).subst_identity();
+        let fn_ty = self.tcx().type_of(scope_def_id).instantiate_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.rs b/compiler/rustc_infer/src/infer/error_reporting/note.rs
index e55e9e75fb6..7144084c78e 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/note.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/note.rs
@@ -295,34 +295,40 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
         // but right now it's not really very smart when it comes to implicit `Sized`
         // predicates and bounds on the trait itself.
 
-        let Some(impl_def_id) =
-            self.tcx.associated_item(impl_item_def_id).impl_container(self.tcx) else { return; };
-        let Some(trait_ref) = self
-            .tcx
-            .impl_trait_ref(impl_def_id)
-            else { return; };
-        let trait_substs = trait_ref
-            .subst_identity()
+        let Some(impl_def_id) = self.tcx.associated_item(impl_item_def_id).impl_container(self.tcx)
+        else {
+            return;
+        };
+        let Some(trait_ref) = self.tcx.impl_trait_ref(impl_def_id) else {
+            return;
+        };
+        let trait_args = trait_ref
+            .instantiate_identity()
             // Replace the explicit self type with `Self` for better suggestion rendering
             .with_self_ty(self.tcx, Ty::new_param(self.tcx, 0, kw::SelfUpper))
-            .substs;
-        let trait_item_substs = ty::InternalSubsts::identity_for_item(self.tcx, impl_item_def_id)
-            .rebase_onto(self.tcx, impl_def_id, trait_substs);
+            .args;
+        let trait_item_args = ty::GenericArgs::identity_for_item(self.tcx, impl_item_def_id)
+            .rebase_onto(self.tcx, impl_def_id, trait_args);
 
-        let Ok(trait_predicates) = self
-            .tcx
-            .explicit_predicates_of(trait_item_def_id)
-            .instantiate_own(self.tcx, trait_item_substs)
-            .map(|(pred, _)| {
-                if pred.is_suggestable(self.tcx, false) {
-                    Ok(pred.to_string())
-                } else {
-                    Err(())
-                }
-            })
-            .collect::<Result<Vec<_>, ()>>() else { return; };
+        let Ok(trait_predicates) =
+            self.tcx
+                .explicit_predicates_of(trait_item_def_id)
+                .instantiate_own(self.tcx, trait_item_args)
+                .map(|(pred, _)| {
+                    if pred.is_suggestable(self.tcx, false) {
+                        Ok(pred.to_string())
+                    } else {
+                        Err(())
+                    }
+                })
+                .collect::<Result<Vec<_>, ()>>()
+        else {
+            return;
+        };
 
-        let Some(generics) = self.tcx.hir().get_generics(impl_item_def_id) else { return; };
+        let Some(generics) = self.tcx.hir().get_generics(impl_item_def_id) else {
+            return;
+        };
 
         let suggestion = if trait_predicates.is_empty() {
             WhereClauseSuggestions::Remove { span: generics.where_clause_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 63613b59020..8e3f6b97e8f 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
@@ -100,9 +100,9 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                         {
                             // Synthesize the associated type restriction `Add<Output = Expected>`.
                             // FIXME: extract this logic for use in other diagnostics.
-                            let (trait_ref, assoc_substs) = proj.trait_ref_and_own_substs(tcx);
+                            let (trait_ref, assoc_args) = proj.trait_ref_and_own_args(tcx);
                             let item_name = tcx.item_name(proj.def_id);
-                            let item_args = self.format_generic_args(assoc_substs);
+                            let item_args = self.format_generic_args(assoc_args);
 
                             // Here, we try to see if there's an existing
                             // trait implementation that matches the one that
@@ -316,7 +316,7 @@ impl<T> Trait<T> for X {
     ) -> bool {
         let tcx = self.tcx;
         let assoc = tcx.associated_item(proj_ty.def_id);
-        let (trait_ref, assoc_substs) = proj_ty.trait_ref_and_own_substs(tcx);
+        let (trait_ref, assoc_args) = proj_ty.trait_ref_and_own_args(tcx);
         if let Some(item) = tcx.hir().get_if_local(body_owner_def_id) {
             if let Some(hir_generics) = item.generics() {
                 // Get the `DefId` for the type parameter corresponding to `A` in `<A as T>::Foo`.
@@ -339,7 +339,7 @@ impl<T> Trait<T> for X {
                         &trait_ref,
                         pred.bounds,
                         assoc,
-                        assoc_substs,
+                        assoc_args,
                         ty,
                         &msg,
                         false,
@@ -488,14 +488,14 @@ fn foo(&self) -> Self::T { String::new() }
                 return false;
             };
 
-            let (trait_ref, assoc_substs) = proj_ty.trait_ref_and_own_substs(tcx);
+            let (trait_ref, assoc_args) = proj_ty.trait_ref_and_own_args(tcx);
 
             self.constrain_generic_bound_associated_type_structured_suggestion(
                 diag,
                 &trait_ref,
                 opaque_hir_ty.bounds,
                 assoc,
-                assoc_substs,
+                assoc_args,
                 ty,
                 msg,
                 true,
@@ -527,7 +527,7 @@ fn foo(&self) -> Self::T { String::new() }
                     && !tcx.is_doc_hidden(item.def_id)
             })
             .filter_map(|item| {
-                let method = tcx.fn_sig(item.def_id).subst_identity();
+                let method = tcx.fn_sig(item.def_id).instantiate_identity();
                 match *method.output().skip_binder().kind() {
                     ty::Alias(ty::Projection, ty::AliasTy { def_id: item_def_id, .. })
                         if item_def_id == proj_ty_item_def_id =>
@@ -597,7 +597,7 @@ fn foo(&self) -> Self::T { String::new() }
                             if let hir::Defaultness::Default { has_value: true } =
                                 tcx.defaultness(item.id.owner_id)
                             {
-                                let assoc_ty = tcx.type_of(item.id.owner_id).subst_identity();
+                                let assoc_ty = tcx.type_of(item.id.owner_id).instantiate_identity();
                                 if self.infcx.can_eq(param_env, assoc_ty, found) {
                                     diag.span_label(
                                         item.span,
@@ -618,7 +618,7 @@ fn foo(&self) -> Self::T { String::new() }
             })) => {
                 for item in &items[..] {
                     if let hir::AssocItemKind::Type = item.kind {
-                        let assoc_ty = tcx.type_of(item.id.owner_id).subst_identity();
+                        let assoc_ty = tcx.type_of(item.id.owner_id).instantiate_identity();
 
                         if self.infcx.can_eq(param_env, assoc_ty, found) {
                             diag.span_label(item.span, "expected this associated type");
@@ -645,7 +645,7 @@ fn foo(&self) -> Self::T { String::new() }
         trait_ref: &ty::TraitRef<'tcx>,
         bounds: hir::GenericBounds<'_>,
         assoc: ty::AssocItem,
-        assoc_substs: &[ty::GenericArg<'tcx>],
+        assoc_args: &[ty::GenericArg<'tcx>],
         ty: Ty<'tcx>,
         msg: impl Fn() -> String,
         is_bound_surely_present: bool,
@@ -671,14 +671,7 @@ fn foo(&self) -> Self::T { String::new() }
             _ => return false,
         };
 
-        self.constrain_associated_type_structured_suggestion(
-            diag,
-            span,
-            assoc,
-            assoc_substs,
-            ty,
-            msg,
-        )
+        self.constrain_associated_type_structured_suggestion(diag, span, assoc, assoc_args, ty, msg)
     }
 
     /// Given a span corresponding to a bound, provide a structured suggestion to set an
@@ -688,7 +681,7 @@ fn foo(&self) -> Self::T { String::new() }
         diag: &mut Diagnostic,
         span: Span,
         assoc: ty::AssocItem,
-        assoc_substs: &[ty::GenericArg<'tcx>],
+        assoc_args: &[ty::GenericArg<'tcx>],
         ty: Ty<'tcx>,
         msg: impl Fn() -> String,
     ) -> bool {
@@ -702,7 +695,7 @@ fn foo(&self) -> Self::T { String::new() }
                 let span = Span::new(pos, pos, span.ctxt(), span.parent());
                 (span, format!(", {} = {}", assoc.ident(tcx), ty))
             } else {
-                let item_args = self.format_generic_args(assoc_substs);
+                let item_args = self.format_generic_args(assoc_args);
                 (span.shrink_to_hi(), format!("<{}{} = {}>", assoc.ident(tcx), item_args, ty))
             };
             diag.span_suggestion_verbose(span, msg(), sugg, MaybeIncorrect);
diff --git a/compiler/rustc_infer/src/infer/error_reporting/suggest.rs b/compiler/rustc_infer/src/infer/error_reporting/suggest.rs
index b0e7cf23cae..ce5d3791a48 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/suggest.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/suggest.rs
@@ -105,7 +105,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
         // Heavily inspired by `FnCtxt::suggest_compatible_variants`, with
         // some modifications due to that being in typeck and this being in infer.
         if let ObligationCauseCode::Pattern { .. } = cause.code() {
-            if let ty::Adt(expected_adt, substs) = exp_found.expected.kind() {
+            if let ty::Adt(expected_adt, args) = exp_found.expected.kind() {
                 let compatible_variants: Vec<_> = expected_adt
                     .variants()
                     .iter()
@@ -114,7 +114,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                     })
                     .filter_map(|variant| {
                         let sole_field = &variant.single_field();
-                        let sole_field_ty = sole_field.ty(self.tcx, substs);
+                        let sole_field_ty = sole_field.ty(self.tcx, args);
                         if self.same_type_modulo_infer(sole_field_ty, exp_found.found) {
                             let variant_path =
                                 with_no_trimmed_paths!(self.tcx.def_path_str(variant.def_id));
@@ -260,7 +260,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
             "suggest_accessing_field_where_appropriate(cause={:?}, exp_found={:?})",
             cause, exp_found
         );
-        if let ty::Adt(expected_def, expected_substs) = exp_found.expected.kind() {
+        if let ty::Adt(expected_def, expected_args) = exp_found.expected.kind() {
             if expected_def.is_enum() {
                 return;
             }
@@ -270,7 +270,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                 .fields
                 .iter()
                 .filter(|field| field.vis.is_accessible_from(field.did, self.tcx))
-                .map(|field| (field.name, field.ty(self.tcx, expected_substs)))
+                .map(|field| (field.name, field.ty(self.tcx, expected_args)))
                 .find(|(_, ty)| self.same_type_modulo_infer(*ty, exp_found.found))
             {
                 if let ObligationCauseCode::Pattern { span: Some(span), .. } = *cause.code() {
@@ -304,12 +304,12 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
             return;
         }
         match (&expected_inner.kind(), &found_inner.kind()) {
-            (ty::FnPtr(sig), ty::FnDef(did, substs)) => {
+            (ty::FnPtr(sig), ty::FnDef(did, args)) => {
                 let expected_sig = &(self.normalize_fn_sig)(*sig);
                 let found_sig =
-                    &(self.normalize_fn_sig)(self.tcx.fn_sig(*did).subst(self.tcx, substs));
+                    &(self.normalize_fn_sig)(self.tcx.fn_sig(*did).instantiate(self.tcx, args));
 
-                let fn_name = self.tcx.def_path_str_with_substs(*did, substs);
+                let fn_name = self.tcx.def_path_str_with_args(*did, args);
 
                 if !self.same_type_modulo_infer(*found_sig, *expected_sig)
                     || !sig.is_suggestable(self.tcx, true)
@@ -332,11 +332,11 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                 };
                 diag.subdiagnostic(sugg);
             }
-            (ty::FnDef(did1, substs1), ty::FnDef(did2, substs2)) => {
+            (ty::FnDef(did1, args1), ty::FnDef(did2, args2)) => {
                 let expected_sig =
-                    &(self.normalize_fn_sig)(self.tcx.fn_sig(*did1).subst(self.tcx, substs1));
+                    &(self.normalize_fn_sig)(self.tcx.fn_sig(*did1).instantiate(self.tcx, args1));
                 let found_sig =
-                    &(self.normalize_fn_sig)(self.tcx.fn_sig(*did2).subst(self.tcx, substs2));
+                    &(self.normalize_fn_sig)(self.tcx.fn_sig(*did2).instantiate(self.tcx, args2));
 
                 if self.same_type_modulo_infer(*expected_sig, *found_sig) {
                     diag.subdiagnostic(FnUniqTypes);
@@ -351,7 +351,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                     return;
                 }
 
-                let fn_name = self.tcx.def_path_str_with_substs(*did2, substs2);
+                let fn_name = self.tcx.def_path_str_with_args(*did2, args2);
                 let sug = if found.is_ref() {
                     FunctionPointerSuggestion::CastBothRef {
                         span,
@@ -370,16 +370,16 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
 
                 diag.subdiagnostic(sug);
             }
-            (ty::FnDef(did, substs), ty::FnPtr(sig)) => {
+            (ty::FnDef(did, args), ty::FnPtr(sig)) => {
                 let expected_sig =
-                    &(self.normalize_fn_sig)(self.tcx.fn_sig(*did).subst(self.tcx, substs));
+                    &(self.normalize_fn_sig)(self.tcx.fn_sig(*did).instantiate(self.tcx, args));
                 let found_sig = &(self.normalize_fn_sig)(*sig);
 
                 if !self.same_type_modulo_infer(*found_sig, *expected_sig) {
                     return;
                 }
 
-                let fn_name = self.tcx.def_path_str_with_substs(*did, substs);
+                let fn_name = self.tcx.def_path_str_with_args(*did, args);
 
                 let casting = if expected.is_ref() {
                     format!("&({fn_name} as {found_sig})")
@@ -400,10 +400,10 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
         expected: Ty<'tcx>,
         found: Ty<'tcx>,
     ) -> Option<SuggestAsRefKind> {
-        if let (ty::Adt(exp_def, exp_substs), ty::Ref(_, found_ty, _)) =
+        if let (ty::Adt(exp_def, exp_args), ty::Ref(_, found_ty, _)) =
             (expected.kind(), found.kind())
         {
-            if let ty::Adt(found_def, found_substs) = *found_ty.kind() {
+            if let ty::Adt(found_def, found_args) = *found_ty.kind() {
                 if exp_def == &found_def {
                     let have_as_ref = &[
                         (sym::Option, SuggestAsRefKind::Option),
@@ -414,7 +414,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                     }) {
                         let mut show_suggestion = true;
                         for (exp_ty, found_ty) in
-                            std::iter::zip(exp_substs.types(), found_substs.types())
+                            std::iter::zip(exp_args.types(), found_args.types())
                         {
                             match *exp_ty.kind() {
                                 ty::Ref(_, exp_ty, _) => {
@@ -526,13 +526,23 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
         diag: &mut Diagnostic,
     ) {
         // 0. Extract fn_decl from hir
-        let hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Closure(hir::Closure { body, fn_decl, .. }), .. }) = hir else { return; };
+        let hir::Node::Expr(hir::Expr {
+            kind: hir::ExprKind::Closure(hir::Closure { body, fn_decl, .. }),
+            ..
+        }) = hir
+        else {
+            return;
+        };
         let hir::Body { params, .. } = self.tcx.hir().body(*body);
 
-        // 1. Get the substs of the closure.
+        // 1. Get the args of the closure.
         // 2. Assume exp_found is FnOnce / FnMut / Fn, we can extract function parameters from [1].
-        let Some(expected) = exp_found.expected.skip_binder().substs.get(1) else { return; };
-        let Some(found) = exp_found.found.skip_binder().substs.get(1) else { return; };
+        let Some(expected) = exp_found.expected.skip_binder().args.get(1) else {
+            return;
+        };
+        let Some(found) = exp_found.found.skip_binder().args.get(1) else {
+            return;
+        };
         let expected = expected.unpack();
         let found = found.unpack();
         // 3. Extract the tuple type from Fn trait and suggest the change.
@@ -621,8 +631,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                 ty::Alias(ty::Opaque, ty::AliasTy { def_id: exp_def_id, .. }),
             ) if last_def_id == exp_def_id => StatementAsExpression::CorrectType,
             (
-                ty::Alias(ty::Opaque, ty::AliasTy { def_id: last_def_id, substs: last_bounds, .. }),
-                ty::Alias(ty::Opaque, ty::AliasTy { def_id: exp_def_id, substs: exp_bounds, .. }),
+                ty::Alias(ty::Opaque, ty::AliasTy { def_id: last_def_id, args: last_bounds, .. }),
+                ty::Alias(ty::Opaque, ty::AliasTy { def_id: exp_def_id, args: exp_bounds, .. }),
             ) => {
                 debug!(
                     "both opaque, likely future {:?} {:?} {:?} {:?}",
@@ -711,7 +721,9 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
 
         let hir = self.tcx.hir();
         for stmt in blk.stmts.iter().rev() {
-            let hir::StmtKind::Local(local) = &stmt.kind else { continue; };
+            let hir::StmtKind::Local(local) = &stmt.kind else {
+                continue;
+            };
             local.pat.walk(&mut find_compatible_candidates);
         }
         match hir.find_parent(blk.hir_id) {
diff --git a/compiler/rustc_infer/src/infer/freshen.rs b/compiler/rustc_infer/src/infer/freshen.rs
index 05769b7907a..689945d644c 100644
--- a/compiler/rustc_infer/src/infer/freshen.rs
+++ b/compiler/rustc_infer/src/infer/freshen.rs
@@ -11,7 +11,7 @@
 //!
 //! To handle closures, freshened types also have to contain the signature and kind of any
 //! closure in the local inference context, as otherwise the cache key might be invalidated.
-//! The way this is done is somewhat hacky - the closure signature is appended to the substs,
+//! The way this is done is somewhat hacky - the closure signature is appended to the args,
 //! as well as the closure kind "encoded" as a type. Also, special handling is needed when
 //! the closure signature contains a reference to the original closure.
 //!
diff --git a/compiler/rustc_infer/src/infer/generalize.rs b/compiler/rustc_infer/src/infer/generalize.rs
index 78025016757..cf674d5dda6 100644
--- a/compiler/rustc_infer/src/infer/generalize.rs
+++ b/compiler/rustc_infer/src/infer/generalize.rs
@@ -173,21 +173,21 @@ where
         true
     }
 
-    fn relate_item_substs(
+    fn relate_item_args(
         &mut self,
         item_def_id: DefId,
-        a_subst: ty::SubstsRef<'tcx>,
-        b_subst: ty::SubstsRef<'tcx>,
-    ) -> RelateResult<'tcx, ty::SubstsRef<'tcx>> {
+        a_subst: ty::GenericArgsRef<'tcx>,
+        b_subst: ty::GenericArgsRef<'tcx>,
+    ) -> RelateResult<'tcx, ty::GenericArgsRef<'tcx>> {
         if self.ambient_variance == ty::Variance::Invariant {
             // Avoid fetching the variance if we are in an invariant
             // context; no need, and it can induce dependency cycles
             // (e.g., #41849).
-            relate::relate_substs(self, a_subst, b_subst)
+            relate::relate_args(self, a_subst, b_subst)
         } else {
             let tcx = self.tcx();
             let opt_variances = tcx.variances_of(item_def_id);
-            relate::relate_substs_with_variances(
+            relate::relate_args_with_variances(
                 self,
                 item_def_id,
                 opt_variances,
@@ -405,16 +405,16 @@ where
             }
             // FIXME: remove this branch once `structurally_relate_consts` is fully
             // structural.
-            ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, substs }) => {
-                let substs = self.relate_with_variance(
+            ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, args }) => {
+                let args = self.relate_with_variance(
                     ty::Variance::Invariant,
                     ty::VarianceDiagInfo::default(),
-                    substs,
-                    substs,
+                    args,
+                    args,
                 )?;
                 Ok(ty::Const::new_unevaluated(
                     self.tcx(),
-                    ty::UnevaluatedConst { def, substs },
+                    ty::UnevaluatedConst { def, args },
                     c.ty(),
                 ))
             }
diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs
index a123effd0f0..a73e84f94c4 100644
--- a/compiler/rustc_infer/src/infer/mod.rs
+++ b/compiler/rustc_infer/src/infer/mod.rs
@@ -30,11 +30,11 @@ use rustc_middle::ty::error::{ExpectedFound, TypeError};
 use rustc_middle::ty::fold::BoundVarReplacerDelegate;
 use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
 use rustc_middle::ty::relate::RelateResult;
-use rustc_middle::ty::subst::{GenericArg, GenericArgKind, InternalSubsts, SubstsRef};
 use rustc_middle::ty::visit::{TypeVisitable, TypeVisitableExt};
 pub use rustc_middle::ty::IntVarValue;
 use rustc_middle::ty::{self, GenericParamDefKind, InferConst, InferTy, Ty, TyCtxt};
 use rustc_middle::ty::{ConstVid, FloatVid, IntVid, TyVid};
+use rustc_middle::ty::{GenericArg, GenericArgKind, GenericArgs, GenericArgsRef};
 use rustc_span::symbol::Symbol;
 use rustc_span::Span;
 
@@ -1184,8 +1184,8 @@ impl<'tcx> InferCtxt<'tcx> {
 
     /// Given a set of generics defined on a type or impl, returns a substitution mapping each
     /// type/region parameter to a fresh inference variable.
-    pub fn fresh_substs_for_item(&self, span: Span, def_id: DefId) -> SubstsRef<'tcx> {
-        InternalSubsts::for_item(self.tcx, def_id, |param, _| self.var_for_def(span, param))
+    pub fn fresh_args_for_item(&self, span: Span, def_id: DefId) -> GenericArgsRef<'tcx> {
+        GenericArgs::for_item(self.tcx, def_id, |param, _| self.var_for_def(span, param))
     }
 
     /// Returns `true` if errors have been reported since this infcx was
@@ -1474,8 +1474,8 @@ impl<'tcx> InferCtxt<'tcx> {
     /// Obtains the latest type of the given closure; this may be a
     /// closure in the current function, in which case its
     /// `ClosureKind` may not yet be known.
-    pub fn closure_kind(&self, closure_substs: SubstsRef<'tcx>) -> Option<ty::ClosureKind> {
-        let closure_kind_ty = closure_substs.as_closure().kind_ty();
+    pub fn closure_kind(&self, closure_args: GenericArgsRef<'tcx>) -> Option<ty::ClosureKind> {
+        let closure_kind_ty = closure_args.as_closure().kind_ty();
         let closure_kind_ty = self.shallow_resolve(closure_kind_ty);
         closure_kind_ty.to_opt_closure_kind()
     }
@@ -1534,7 +1534,7 @@ impl<'tcx> InferCtxt<'tcx> {
     /// too generic for the constant to be evaluated then `Err(ErrorHandled::TooGeneric)` is
     /// returned.
     ///
-    /// This handles inferences variables within both `param_env` and `substs` by
+    /// This handles inferences variables within both `param_env` and `args` by
     /// performing the operation on their respective canonical forms.
     #[instrument(skip(self), level = "debug")]
     pub fn const_eval_resolve(
@@ -1543,34 +1543,34 @@ impl<'tcx> InferCtxt<'tcx> {
         unevaluated: ty::UnevaluatedConst<'tcx>,
         span: Option<Span>,
     ) -> EvalToValTreeResult<'tcx> {
-        let mut substs = self.resolve_vars_if_possible(unevaluated.substs);
-        debug!(?substs);
+        let mut args = self.resolve_vars_if_possible(unevaluated.args);
+        debug!(?args);
 
-        // Postpone the evaluation of constants whose substs depend on inference
+        // Postpone the evaluation of constants whose args depend on inference
         // variables
         let tcx = self.tcx;
-        if substs.has_non_region_infer() {
+        if args.has_non_region_infer() {
             if let Some(ct) = tcx.thir_abstract_const(unevaluated.def)? {
-                let ct = tcx.expand_abstract_consts(ct.subst(tcx, substs));
+                let ct = tcx.expand_abstract_consts(ct.instantiate(tcx, args));
                 if let Err(e) = ct.error_reported() {
                     return Err(ErrorHandled::Reported(e.into()));
                 } else if ct.has_non_region_infer() || ct.has_non_region_param() {
                     return Err(ErrorHandled::TooGeneric);
                 } else {
-                    substs = replace_param_and_infer_substs_with_placeholder(tcx, substs);
+                    args = replace_param_and_infer_args_with_placeholder(tcx, args);
                 }
             } else {
-                substs = InternalSubsts::identity_for_item(tcx, unevaluated.def);
+                args = GenericArgs::identity_for_item(tcx, unevaluated.def);
                 param_env = tcx.param_env(unevaluated.def);
             }
         }
 
         let param_env_erased = tcx.erase_regions(param_env);
-        let substs_erased = tcx.erase_regions(substs);
+        let args_erased = tcx.erase_regions(args);
         debug!(?param_env_erased);
-        debug!(?substs_erased);
+        debug!(?args_erased);
 
-        let unevaluated = ty::UnevaluatedConst { def: unevaluated.def, substs: substs_erased };
+        let unevaluated = ty::UnevaluatedConst { def: unevaluated.def, args: args_erased };
 
         // The return value is the evaluated value which doesn't contain any reference to inference
         // variables, thus we don't need to substitute back the original values.
@@ -1959,13 +1959,13 @@ impl RegionVariableOrigin {
     }
 }
 
-/// Replaces substs that reference param or infer variables with suitable
+/// Replaces args that reference param or infer variables with suitable
 /// placeholders. This function is meant to remove these param and infer
-/// substs when they're not actually needed to evaluate a constant.
-fn replace_param_and_infer_substs_with_placeholder<'tcx>(
+/// args when they're not actually needed to evaluate a constant.
+fn replace_param_and_infer_args_with_placeholder<'tcx>(
     tcx: TyCtxt<'tcx>,
-    substs: SubstsRef<'tcx>,
-) -> SubstsRef<'tcx> {
+    args: GenericArgsRef<'tcx>,
+) -> GenericArgsRef<'tcx> {
     struct ReplaceParamAndInferWithPlaceholder<'tcx> {
         tcx: TyCtxt<'tcx>,
         idx: u32,
@@ -2023,5 +2023,5 @@ fn replace_param_and_infer_substs_with_placeholder<'tcx>(
         }
     }
 
-    substs.fold_with(&mut ReplaceParamAndInferWithPlaceholder { tcx, idx: 0 })
+    args.fold_with(&mut ReplaceParamAndInferWithPlaceholder { tcx, idx: 0 })
 }
diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs
index 5927f79a183..90f0b4ce401 100644
--- a/compiler/rustc_infer/src/infer/opaque_types.rs
+++ b/compiler/rustc_infer/src/infer/opaque_types.rs
@@ -103,7 +103,7 @@ impl<'tcx> InferCtxt<'tcx> {
         }
         let (a, b) = if a_is_expected { (a, b) } else { (b, a) };
         let process = |a: Ty<'tcx>, b: Ty<'tcx>, a_is_expected| match *a.kind() {
-            ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) if def_id.is_local() => {
+            ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) if def_id.is_local() => {
                 let def_id = def_id.expect_local();
                 match self.defining_use_anchor {
                     DefiningAnchor::Bind(_) => {
@@ -165,7 +165,7 @@ impl<'tcx> InferCtxt<'tcx> {
                     }
                 }
                 Some(self.register_hidden_type(
-                    OpaqueTypeKey { def_id, substs },
+                    OpaqueTypeKey { def_id, args },
                     cause.clone(),
                     param_env,
                     b,
@@ -214,12 +214,12 @@ impl<'tcx> InferCtxt<'tcx> {
     /// fn foo<'a, 'b>(..) -> (Foo1<'a>, Foo2<'b>) { .. }
     ///                    //  ^^^^ ^^
     ///                    //  |    |
-    ///                    //  |    substs
+    ///                    //  |    args
     ///                    //  def_id
     /// ```
     ///
     /// As indicating in the comments above, each of those references
-    /// is (in the compiler) basically a substitution (`substs`)
+    /// is (in the compiler) basically a substitution (`args`)
     /// applied to the type of a suitable `def_id` (which identifies
     /// `Foo1` or `Foo2`).
     ///
@@ -278,7 +278,7 @@ impl<'tcx> InferCtxt<'tcx> {
     ///
     /// We generally prefer to make `<=` constraints, since they
     /// integrate best into the region solver. To do that, we find the
-    /// "minimum" of all the arguments that appear in the substs: that
+    /// "minimum" of all the arguments that appear in the args: that
     /// is, some region which is less than all the others. In the case
     /// of `Foo1<'a>`, that would be `'a` (it's the only choice, after
     /// all). Then we apply that as a least bound to the variables
@@ -350,7 +350,7 @@ impl<'tcx> InferCtxt<'tcx> {
         // opaque type definition.
         let choice_regions: Lrc<Vec<ty::Region<'tcx>>> = Lrc::new(
             opaque_type_key
-                .substs
+                .args
                 .iter()
                 .enumerate()
                 .filter(|(i, _)| variances[*i] == ty::Variance::Invariant)
@@ -445,28 +445,28 @@ where
         }
 
         match ty.kind() {
-            ty::Closure(_, ref substs) => {
+            ty::Closure(_, ref args) => {
                 // Skip lifetime parameters of the enclosing item(s)
 
-                substs.as_closure().tupled_upvars_ty().visit_with(self);
-                substs.as_closure().sig_as_fn_ptr_ty().visit_with(self);
+                args.as_closure().tupled_upvars_ty().visit_with(self);
+                args.as_closure().sig_as_fn_ptr_ty().visit_with(self);
             }
 
-            ty::Generator(_, ref substs, _) => {
+            ty::Generator(_, ref args, _) => {
                 // Skip lifetime parameters of the enclosing item(s)
                 // Also skip the witness type, because that has no free regions.
 
-                substs.as_generator().tupled_upvars_ty().visit_with(self);
-                substs.as_generator().return_ty().visit_with(self);
-                substs.as_generator().yield_ty().visit_with(self);
-                substs.as_generator().resume_ty().visit_with(self);
+                args.as_generator().tupled_upvars_ty().visit_with(self);
+                args.as_generator().return_ty().visit_with(self);
+                args.as_generator().yield_ty().visit_with(self);
+                args.as_generator().resume_ty().visit_with(self);
             }
 
-            ty::Alias(ty::Opaque, ty::AliasTy { def_id, ref substs, .. }) => {
+            ty::Alias(ty::Opaque, ty::AliasTy { def_id, ref args, .. }) => {
                 // Skip lifetime parameters that are not captures.
                 let variances = self.tcx.variances_of(*def_id);
 
-                for (v, s) in std::iter::zip(variances, substs.iter()) {
+                for (v, s) in std::iter::zip(variances, args.iter()) {
                     if *v != ty::Variance::Bivariant {
                         s.visit_with(self);
                     }
@@ -519,7 +519,7 @@ impl<'tcx> InferCtxt<'tcx> {
 
         self.add_item_bounds_for_hidden_type(
             opaque_type_key.def_id.to_def_id(),
-            opaque_type_key.substs,
+            opaque_type_key.args,
             cause,
             param_env,
             hidden_ty,
@@ -582,7 +582,7 @@ impl<'tcx> InferCtxt<'tcx> {
     pub fn add_item_bounds_for_hidden_type(
         &self,
         def_id: DefId,
-        substs: ty::SubstsRef<'tcx>,
+        args: ty::GenericArgsRef<'tcx>,
         cause: ObligationCause<'tcx>,
         param_env: ty::ParamEnv<'tcx>,
         hidden_ty: Ty<'tcx>,
@@ -591,7 +591,7 @@ impl<'tcx> InferCtxt<'tcx> {
         let tcx = self.tcx;
         let item_bounds = tcx.explicit_item_bounds(def_id);
 
-        for (predicate, _) in item_bounds.subst_iter_copied(tcx, substs) {
+        for (predicate, _) in item_bounds.arg_iter_copied(tcx, args) {
             let predicate = predicate.fold_with(&mut BottomUpFolder {
                 tcx,
                 ty_op: |ty| match *ty.kind() {
@@ -614,17 +614,18 @@ impl<'tcx> InferCtxt<'tcx> {
                     }
                     // Replace all other mentions of the same opaque type with the hidden type,
                     // as the bounds must hold on the hidden type after all.
-                    ty::Alias(ty::Opaque, ty::AliasTy { def_id: def_id2, substs: substs2, .. })
-                        if def_id == def_id2 && substs == substs2 =>
+                    ty::Alias(ty::Opaque, ty::AliasTy { def_id: def_id2, args: args2, .. })
+                        if def_id == def_id2 && args == args2 =>
                     {
                         hidden_ty
                     }
                     // FIXME(RPITIT): This can go away when we move to associated types
                     // FIXME(inherent_associated_types): Extend this to support `ty::Inherent`, too.
-                    ty::Alias(
-                        ty::Projection,
-                        ty::AliasTy { def_id: def_id2, substs: substs2, .. },
-                    ) if def_id == def_id2 && substs == substs2 => hidden_ty,
+                    ty::Alias(ty::Projection, ty::AliasTy { def_id: def_id2, args: args2, .. })
+                        if def_id == def_id2 && args == args2 =>
+                    {
+                        hidden_ty
+                    }
                     _ => ty,
                 },
                 lt_op: |lt| lt,
diff --git a/compiler/rustc_infer/src/infer/outlives/components.rs b/compiler/rustc_infer/src/infer/outlives/components.rs
index cb63d2f18b6..2ac9568f60b 100644
--- a/compiler/rustc_infer/src/infer/outlives/components.rs
+++ b/compiler/rustc_infer/src/infer/outlives/components.rs
@@ -3,8 +3,8 @@
 // RFC for reference.
 
 use rustc_data_structures::sso::SsoHashSet;
-use rustc_middle::ty::subst::{GenericArg, GenericArgKind};
 use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
+use rustc_middle::ty::{GenericArg, GenericArgKind};
 use smallvec::{smallvec, SmallVec};
 
 #[derive(Debug)]
@@ -71,15 +71,15 @@ fn compute_components<'tcx>(
     // in the `subtys` iterator (e.g., when encountering a
     // projection).
     match *ty.kind() {
-            ty::FnDef(_, substs) => {
-                // HACK(eddyb) ignore lifetimes found shallowly in `substs`.
-                // This is inconsistent with `ty::Adt` (including all substs)
-                // and with `ty::Closure` (ignoring all substs other than
+            ty::FnDef(_, args) => {
+                // HACK(eddyb) ignore lifetimes found shallowly in `args`.
+                // This is inconsistent with `ty::Adt` (including all args)
+                // and with `ty::Closure` (ignoring all args other than
                 // upvars, of which a `ty::FnDef` doesn't have any), but
                 // consistent with previous (accidental) behavior.
                 // See https://github.com/rust-lang/rust/issues/70917
                 // for further background and discussion.
-                for child in substs {
+                for child in args {
                     match child.unpack() {
                         GenericArgKind::Type(ty) => {
                             compute_components(tcx, ty, out, visited);
@@ -97,14 +97,14 @@ fn compute_components<'tcx>(
                 compute_components(tcx, element, out, visited);
             }
 
-            ty::Closure(_, ref substs) => {
-                let tupled_ty = substs.as_closure().tupled_upvars_ty();
+            ty::Closure(_, ref args) => {
+                let tupled_ty = args.as_closure().tupled_upvars_ty();
                 compute_components(tcx, tupled_ty, out, visited);
             }
 
-            ty::Generator(_, ref substs, _) => {
+            ty::Generator(_, ref args, _) => {
                 // Same as the closure case
-                let tupled_ty = substs.as_generator().tupled_upvars_ty();
+                let tupled_ty = args.as_generator().tupled_upvars_ty();
                 compute_components(tcx, tupled_ty, out, visited);
 
                 // We ignore regions in the generator interior as we don't
@@ -189,7 +189,7 @@ fn compute_components<'tcx>(
         }
 }
 
-/// Collect [Component]s for *all* the substs of `parent`.
+/// Collect [Component]s for *all* the args of `parent`.
 ///
 /// This should not be used to get the components of `parent` itself.
 /// Use [push_outlives_components] instead.
@@ -201,7 +201,7 @@ pub(super) fn compute_alias_components_recursive<'tcx>(
 ) {
     let ty::Alias(kind, alias_ty) = alias_ty.kind() else { bug!() };
     let opt_variances = if *kind == ty::Opaque { tcx.variances_of(alias_ty.def_id) } else { &[] };
-    for (index, child) in alias_ty.substs.iter().enumerate() {
+    for (index, child) in alias_ty.args.iter().enumerate() {
         if opt_variances.get(index) == Some(&ty::Bivariant) {
             continue;
         }
@@ -225,7 +225,7 @@ pub(super) fn compute_alias_components_recursive<'tcx>(
     }
 }
 
-/// Collect [Component]s for *all* the substs of `parent`.
+/// Collect [Component]s for *all* the args of `parent`.
 ///
 /// This should not be used to get the components of `parent` itself.
 /// Use [push_outlives_components] instead.
diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs
index 73df6d03f86..0681f414ce9 100644
--- a/compiler/rustc_infer/src/infer/outlives/obligations.rs
+++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs
@@ -68,8 +68,8 @@ use crate::infer::{
 use crate::traits::{ObligationCause, ObligationCauseCode};
 use rustc_data_structures::undo_log::UndoLogs;
 use rustc_middle::mir::ConstraintCategory;
-use rustc_middle::ty::subst::GenericArgKind;
-use rustc_middle::ty::{self, Region, SubstsRef, Ty, TyCtxt, TypeVisitableExt};
+use rustc_middle::ty::GenericArgKind;
+use rustc_middle::ty::{self, GenericArgsRef, Region, Ty, TyCtxt, TypeVisitableExt};
 use smallvec::smallvec;
 
 use super::env::OutlivesEnvironment;
@@ -279,7 +279,7 @@ where
         alias_ty: ty::AliasTy<'tcx>,
     ) {
         // An optimization for a common case with opaque types.
-        if alias_ty.substs.is_empty() {
+        if alias_ty.args.is_empty() {
             return;
         }
 
@@ -348,7 +348,7 @@ where
         {
             debug!("no declared bounds");
             let opt_variances = is_opaque.then(|| self.tcx.variances_of(alias_ty.def_id));
-            self.substs_must_outlive(alias_ty.substs, origin, region, opt_variances);
+            self.args_must_outlive(alias_ty.args, origin, region, opt_variances);
             return;
         }
 
@@ -395,15 +395,15 @@ where
     }
 
     #[instrument(level = "debug", skip(self))]
-    fn substs_must_outlive(
+    fn args_must_outlive(
         &mut self,
-        substs: SubstsRef<'tcx>,
+        args: GenericArgsRef<'tcx>,
         origin: infer::SubregionOrigin<'tcx>,
         region: ty::Region<'tcx>,
         opt_variances: Option<&[ty::Variance]>,
     ) {
         let constraint = origin.to_constraint_category();
-        for (index, k) in substs.iter().enumerate() {
+        for (index, k) in args.iter().enumerate() {
             match k.unpack() {
                 GenericArgKind::Lifetime(lt) => {
                     let variance = if let Some(variances) = opt_variances {
diff --git a/compiler/rustc_infer/src/infer/outlives/test_type_match.rs b/compiler/rustc_infer/src/infer/outlives/test_type_match.rs
index cd2462d3c31..fefa8959545 100644
--- a/compiler/rustc_infer/src/infer/outlives/test_type_match.rs
+++ b/compiler/rustc_infer/src/infer/outlives/test_type_match.rs
@@ -157,7 +157,7 @@ impl<'tcx> TypeRelation<'tcx> for Match<'tcx> {
         a: T,
         b: T,
     ) -> RelateResult<'tcx, T> {
-        // Opaque types substs have lifetime parameters.
+        // Opaque types args have lifetime parameters.
         // We must not check them to be equal, as we never insert anything to make them so.
         if variance != ty::Bivariant { self.relate(a, b) } else { Ok(a) }
     }
diff --git a/compiler/rustc_infer/src/infer/outlives/verify.rs b/compiler/rustc_infer/src/infer/outlives/verify.rs
index 1a5e2b520b8..1e1ecd3fb94 100644
--- a/compiler/rustc_infer/src/infer/outlives/verify.rs
+++ b/compiler/rustc_infer/src/infer/outlives/verify.rs
@@ -295,7 +295,7 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
         let bounds = tcx.item_bounds(alias_ty.def_id);
         trace!("{:#?}", bounds.skip_binder());
         bounds
-            .subst_iter(tcx, alias_ty.substs)
+            .arg_iter(tcx, alias_ty.args)
             .filter_map(|p| p.as_type_outlives_clause())
             .filter_map(|p| p.no_bound_vars())
             .map(|OutlivesPredicate(_, r)| r)
diff --git a/compiler/rustc_infer/src/infer/type_variable.rs b/compiler/rustc_infer/src/infer/type_variable.rs
index 01c11d16345..bc83f8d3f96 100644
--- a/compiler/rustc_infer/src/infer/type_variable.rs
+++ b/compiler/rustc_infer/src/infer/type_variable.rs
@@ -125,7 +125,7 @@ pub enum TypeVariableOriginKind {
     OpaqueTypeInference(DefId),
     TypeParameterDefinition(Symbol, DefId),
 
-    /// One of the upvars or closure kind parameters in a `ClosureSubsts`
+    /// One of the upvars or closure kind parameters in a `ClosureArgs`
     /// (before it has been determined).
     // FIXME(eddyb) distinguish upvar inference variables from the rest.
     ClosureSynthetic,
diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs
index 953c2e4b8f8..6471dce88c2 100644
--- a/compiler/rustc_interface/src/interface.rs
+++ b/compiler/rustc_interface/src/interface.rs
@@ -190,7 +190,8 @@ pub fn parse_check_cfg(handler: &EarlyErrorHandler, specs: Vec<String>) -> Check
                                                 ExpectedValues::Some(FxHashSet::default())
                                             });
 
-                                        let ExpectedValues::Some(expected_values) = expected_values else {
+                                        let ExpectedValues::Some(expected_values) = expected_values
+                                        else {
                                             bug!("`expected_values` should be a list a values")
                                         };
 
diff --git a/compiler/rustc_lint/src/array_into_iter.rs b/compiler/rustc_lint/src/array_into_iter.rs
index bccb0a94e98..d0967ba5644 100644
--- a/compiler/rustc_lint/src/array_into_iter.rs
+++ b/compiler/rustc_lint/src/array_into_iter.rs
@@ -81,7 +81,7 @@ impl<'tcx> LateLintPass<'tcx> for ArrayIntoIter {
             let adjustments = cx.typeck_results().expr_adjustments(receiver_arg);
 
             let Some(Adjustment { kind: Adjust::Borrow(_), target }) = adjustments.last() else {
-                return
+                return;
             };
 
             let types =
diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index b821933e908..84aca80b0de 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -61,7 +61,7 @@ use rustc_hir::{Body, FnDecl, ForeignItemKind, GenericParamKind, Node, PatKind,
 use rustc_middle::lint::in_external_macro;
 use rustc_middle::ty::layout::{LayoutError, LayoutOf};
 use rustc_middle::ty::print::with_no_trimmed_paths;
-use rustc_middle::ty::subst::GenericArgKind;
+use rustc_middle::ty::GenericArgKind;
 use rustc_middle::ty::TypeVisitableExt;
 use rustc_middle::ty::{self, Instance, Ty, TyCtxt, VariantDef};
 use rustc_session::config::ExpectedValues;
@@ -181,9 +181,11 @@ impl<'tcx> LateLintPass<'tcx> for BoxPointers {
             | hir::ItemKind::TyAlias(..)
             | hir::ItemKind::Enum(..)
             | hir::ItemKind::Struct(..)
-            | hir::ItemKind::Union(..) => {
-                self.check_heap_type(cx, it.span, cx.tcx.type_of(it.owner_id).subst_identity())
-            }
+            | hir::ItemKind::Union(..) => self.check_heap_type(
+                cx,
+                it.span,
+                cx.tcx.type_of(it.owner_id).instantiate_identity(),
+            ),
             _ => (),
         }
 
@@ -194,7 +196,7 @@ impl<'tcx> LateLintPass<'tcx> for BoxPointers {
                     self.check_heap_type(
                         cx,
                         field.span,
-                        cx.tcx.type_of(field.def_id).subst_identity(),
+                        cx.tcx.type_of(field.def_id).instantiate_identity(),
                     );
                 }
             }
@@ -591,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).subst_identity();
+                let impl_ty = cx.tcx.type_of(parent).instantiate_identity();
                 let outerdef = match impl_ty.kind() {
                     ty::Adt(def, _) => Some(def.did()),
                     ty::Foreign(def_id) => Some(*def_id),
@@ -700,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).subst_identity().is_unsafe_ptr() {
+            if cx.tcx.type_of(did).instantiate_identity().is_unsafe_ptr() {
                 return;
             }
         }
@@ -793,14 +795,12 @@ impl<'tcx> LateLintPass<'tcx> for MissingDebugImplementations {
             _ => return,
         }
 
-        let Some(debug) = cx.tcx.get_diagnostic_item(sym::Debug) else {
-            return
-        };
+        let Some(debug) = cx.tcx.get_diagnostic_item(sym::Debug) else { return };
 
         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).subst_identity().ty_adt_def() {
+                if let Some(ty_def) = cx.tcx.type_of(d).instantiate_identity().ty_adt_def() {
                     if let Some(def_id) = ty_def.did().as_local() {
                         impls.insert(def_id);
                     }
@@ -1458,9 +1458,7 @@ impl TypeAliasBounds {
 
 impl<'tcx> LateLintPass<'tcx> for TypeAliasBounds {
     fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) {
-        let hir::ItemKind::TyAlias(ty, type_alias_generics) = &item.kind else {
-            return
-        };
+        let hir::ItemKind::TyAlias(ty, type_alias_generics) = &item.kind else { return };
         if cx.tcx.type_of(item.owner_id.def_id).skip_binder().has_opaque_types() {
             // Bounds are respected for `type X = impl Trait` and `type X = (impl Trait, Y);`
             return;
@@ -2147,8 +2145,8 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements {
                             match predicate.bounded_ty.kind {
                                 hir::TyKind::Path(hir::QPath::Resolved(None, path)) => {
                                     let Res::Def(DefKind::TyParam, def_id) = path.res else {
-                                    continue;
-                                };
+                                        continue;
+                                    };
                                     let index = ty_generics.param_def_id_to_index[&def_id];
                                     (
                                         Self::lifetimes_outliving_type(inferred_outlives, index),
@@ -2459,12 +2457,12 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue {
             cx: &LateContext<'tcx>,
             ty: Ty<'tcx>,
             variant: &VariantDef,
-            substs: ty::SubstsRef<'tcx>,
+            args: ty::GenericArgsRef<'tcx>,
             descr: &str,
             init: InitKind,
         ) -> Option<InitError> {
             let mut field_err = variant.fields.iter().find_map(|field| {
-                ty_find_init_error(cx, field.ty(cx.tcx, substs), init).map(|mut err| {
+                ty_find_init_error(cx, field.ty(cx.tcx, args), init).map(|mut err| {
                     if !field.did.is_local() {
                         err
                     } else if err.span.is_none() {
@@ -2541,14 +2539,14 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue {
                     Some("raw pointers must be initialized".into())
                 }
                 // Recurse and checks for some compound types. (but not unions)
-                Adt(adt_def, substs) if !adt_def.is_union() => {
+                Adt(adt_def, args) if !adt_def.is_union() => {
                     // Handle structs.
                     if adt_def.is_struct() {
                         return variant_find_init_error(
                             cx,
                             ty,
                             adt_def.non_enum_variant(),
-                            substs,
+                            args,
                             "struct field",
                             init,
                         );
@@ -2558,7 +2556,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue {
                     let mut potential_variants = adt_def.variants().iter().filter_map(|variant| {
                         let definitely_inhabited = match variant
                             .inhabited_predicate(cx.tcx, *adt_def)
-                            .subst(cx.tcx, substs)
+                            .instantiate(cx.tcx, args)
                             .apply_any_module(cx.tcx, cx.param_env)
                         {
                             // Entirely skip uninhabited variants.
@@ -2570,7 +2568,10 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue {
                         Some((variant, definitely_inhabited))
                     });
                     let Some(first_variant) = potential_variants.next() else {
-                        return Some(InitError::from("enums with no inhabited variants have no valid value").spanned(span));
+                        return Some(
+                            InitError::from("enums with no inhabited variants have no valid value")
+                                .spanned(span),
+                        );
                     };
                     // So we have at least one potentially inhabited variant. Might we have two?
                     let Some(second_variant) = potential_variants.next() else {
@@ -2579,7 +2580,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue {
                             cx,
                             ty,
                             &first_variant.0,
-                            substs,
+                            args,
                             "field of the only potentially inhabited enum variant",
                             init,
                         );
@@ -2779,7 +2780,7 @@ impl ClashingExternDeclarations {
             // type unless the newtype makes the type non-null.
             let non_transparent_ty = |mut ty: Ty<'tcx>| -> Ty<'tcx> {
                 loop {
-                    if let ty::Adt(def, substs) = *ty.kind() {
+                    if let ty::Adt(def, args) = *ty.kind() {
                         let is_transparent = def.repr().transparent();
                         let is_non_null = crate::types::nonnull_optimization_guaranteed(tcx, def);
                         debug!(
@@ -2792,7 +2793,7 @@ impl ClashingExternDeclarations {
                             // continue with `ty`'s non-ZST field,
                             // otherwise `ty` is a ZST and we can return
                             if let Some(field) = transparent_newtype_field(tcx, v) {
-                                ty = field.ty(tcx, substs);
+                                ty = field.ty(tcx, args);
                                 continue;
                             }
                         }
@@ -2858,8 +2859,8 @@ impl ClashingExternDeclarations {
                                     structurally_same_type_impl(
                                         seen_types,
                                         cx,
-                                        tcx.type_of(a_did).subst_identity(),
-                                        tcx.type_of(b_did).subst_identity(),
+                                        tcx.type_of(a_did).instantiate_identity(),
+                                        tcx.type_of(b_did).instantiate_identity(),
                                         ckind,
                                     )
                                 },
@@ -2906,8 +2907,8 @@ impl ClashingExternDeclarations {
                                     ckind,
                                 )
                         }
-                        (Tuple(a_substs), Tuple(b_substs)) => {
-                            a_substs.iter().eq_by(b_substs.iter(), |a_ty, b_ty| {
+                        (Tuple(a_args), Tuple(b_args)) => {
+                            a_args.iter().eq_by(b_args.iter(), |a_ty, b_ty| {
                                 structurally_same_type_impl(seen_types, cx, a_ty, b_ty, ckind)
                             })
                         }
@@ -2961,7 +2962,7 @@ impl<'tcx> LateLintPass<'tcx> for ClashingExternDeclarations {
             let tcx = cx.tcx;
             if let Some(existing_did) = self.insert(tcx, this_fi) {
                 let existing_decl_ty = tcx.type_of(existing_did).skip_binder();
-                let this_decl_ty = tcx.type_of(this_fi.owner_id).subst_identity();
+                let this_decl_ty = tcx.type_of(this_fi.owner_id).instantiate_identity();
                 debug!(
                     "ClashingExternDeclarations: Comparing existing {:?}: {:?} to this {:?}: {:?}",
                     existing_did, existing_decl_ty, this_fi.owner_id, this_decl_ty
@@ -3181,7 +3182,7 @@ impl<'tcx> LateLintPass<'tcx> for NamedAsmLabels {
                         let mut chars = possible_label.chars();
                         let Some(c) = chars.next() else {
                             // Empty string means a leading ':' in this section, which is not a label
-                            break
+                            break;
                         };
                         // A label starts with an alphabetic character or . or _ and continues with alphanumeric characters, _, or $
                         if (c.is_alphabetic() || matches!(c, '.' | '_'))
diff --git a/compiler/rustc_lint/src/cast_ref_to_mut.rs b/compiler/rustc_lint/src/cast_ref_to_mut.rs
index 84308d48c10..82bb70bc9e7 100644
--- a/compiler/rustc_lint/src/cast_ref_to_mut.rs
+++ b/compiler/rustc_lint/src/cast_ref_to_mut.rs
@@ -37,7 +37,9 @@ declare_lint_pass!(CastRefToMut => [CAST_REF_TO_MUT]);
 
 impl<'tcx> LateLintPass<'tcx> for CastRefToMut {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
-        let ExprKind::Unary(UnOp::Deref, e) = &expr.kind else { return; };
+        let ExprKind::Unary(UnOp::Deref, e) = &expr.kind else {
+            return;
+        };
 
         let e = e.peel_blocks();
         let e = if let ExprKind::Cast(e, t) = e.kind
diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs
index 3761754f3ae..6522e449386 100644
--- a/compiler/rustc_lint/src/context.rs
+++ b/compiler/rustc_lint/src/context.rs
@@ -35,7 +35,7 @@ use rustc_middle::middle::privacy::EffectiveVisibilities;
 use rustc_middle::middle::stability;
 use rustc_middle::ty::layout::{LayoutError, LayoutOfHelpers, TyAndLayout};
 use rustc_middle::ty::print::with_no_trimmed_paths;
-use rustc_middle::ty::{self, print::Printer, subst::GenericArg, RegisteredTools, Ty, TyCtxt};
+use rustc_middle::ty::{self, print::Printer, GenericArg, RegisteredTools, Ty, TyCtxt};
 use rustc_session::config::ExpectedValues;
 use rustc_session::lint::{BuiltinLintDiagnostics, LintExpectationId};
 use rustc_session::lint::{FutureIncompatibleInfo, Level, Lint, LintBuffer, LintId};
@@ -956,6 +956,14 @@ pub trait LintContext: Sized {
                     db.span_note(glob_reexport_span, format!("the name `{}` in the {} namespace is supposed to be publicly re-exported here", name, namespace));
                     db.span_note(private_item_span, "but the private item here shadows it".to_owned());
                 }
+                BuiltinLintDiagnostics::UnusedQualifications { path_span, unqualified_path } => {
+                    db.span_suggestion_verbose(
+                        path_span,
+                        "replace it with the unqualified path",
+                        unqualified_path,
+                        Applicability::MachineApplicable
+                    );
+                }
             }
             // Rewrap `db`, and pass control to the user.
             decorate(db)
@@ -1265,8 +1273,8 @@ impl<'tcx> LateContext<'tcx> {
                 trait_ref: Option<ty::TraitRef<'tcx>>,
             ) -> Result<Self::Path, Self::Error> {
                 if trait_ref.is_none() {
-                    if let ty::Adt(def, substs) = self_ty.kind() {
-                        return self.print_def_path(def.did(), substs);
+                    if let ty::Adt(def, args) = self_ty.kind() {
+                        return self.print_def_path(def.did(), args);
                     }
                 }
 
diff --git a/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs b/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs
index ccf95992a6e..851c6493daf 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).subst_identity()
+            && let t = cx.tcx.type_of(item.owner_id).instantiate_identity()
             && let opt_did @ Some(did) = trait_.trait_def_id()
             && opt_did == cx.tcx.lang_items().deref_trait()
             // `t` is `dyn t_principal`
diff --git a/compiler/rustc_lint/src/enum_intrinsics_non_enums.rs b/compiler/rustc_lint/src/enum_intrinsics_non_enums.rs
index 2ce28f3a049..05fe64830d1 100644
--- a/compiler/rustc_lint/src/enum_intrinsics_non_enums.rs
+++ b/compiler/rustc_lint/src/enum_intrinsics_non_enums.rs
@@ -51,7 +51,7 @@ fn enforce_mem_discriminant(
     expr_span: Span,
     args_span: Span,
 ) {
-    let ty_param = cx.typeck_results().node_substs(func_expr.hir_id).type_at(0);
+    let ty_param = cx.typeck_results().node_args(func_expr.hir_id).type_at(0);
     if is_non_enum(ty_param) {
         cx.emit_spanned_lint(
             ENUM_INTRINSICS_NON_ENUMS,
@@ -62,7 +62,7 @@ fn enforce_mem_discriminant(
 }
 
 fn enforce_mem_variant_count(cx: &LateContext<'_>, func_expr: &hir::Expr<'_>, span: Span) {
-    let ty_param = cx.typeck_results().node_substs(func_expr.hir_id).type_at(0);
+    let ty_param = cx.typeck_results().node_args(func_expr.hir_id).type_at(0);
     if is_non_enum(ty_param) {
         cx.emit_spanned_lint(
             ENUM_INTRINSICS_NON_ENUMS,
diff --git a/compiler/rustc_lint/src/for_loops_over_fallibles.rs b/compiler/rustc_lint/src/for_loops_over_fallibles.rs
index 7b58bf03bbe..c299e38842a 100644
--- a/compiler/rustc_lint/src/for_loops_over_fallibles.rs
+++ b/compiler/rustc_lint/src/for_loops_over_fallibles.rs
@@ -51,7 +51,7 @@ impl<'tcx> LateLintPass<'tcx> for ForLoopsOverFallibles {
 
         let ty = cx.typeck_results().expr_ty(arg);
 
-        let &ty::Adt(adt, substs) = ty.kind() else { return };
+        let &ty::Adt(adt, args) = ty.kind() else { return };
 
         let (article, ty, var) = match adt.did() {
             did if cx.tcx.is_diagnostic_item(sym::Option, did) => ("an", "Option", "Some"),
@@ -66,7 +66,7 @@ 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 = suggest_question_mark(cx, adt, substs, expr.span)
+        let question_mark = suggest_question_mark(cx, adt, args, expr.span)
             .then(|| ForLoopsOverFalliblesQuestionMark { suggestion: arg.span.shrink_to_hi() });
         let suggestion = ForLoopsOverFalliblesSuggestion {
             var,
@@ -115,11 +115,13 @@ fn extract_iterator_next_call<'tcx>(
 fn suggest_question_mark<'tcx>(
     cx: &LateContext<'tcx>,
     adt: ty::AdtDef<'tcx>,
-    substs: &List<ty::GenericArg<'tcx>>,
+    args: &List<ty::GenericArg<'tcx>>,
     span: Span,
 ) -> bool {
     let Some(body_id) = cx.enclosing_body else { return false };
-    let Some(into_iterator_did) = cx.tcx.get_diagnostic_item(sym::IntoIterator) else { return false };
+    let Some(into_iterator_did) = cx.tcx.get_diagnostic_item(sym::IntoIterator) else {
+        return false;
+    };
 
     if !cx.tcx.is_diagnostic_item(sym::Result, adt.did()) {
         return false;
@@ -135,7 +137,7 @@ fn suggest_question_mark<'tcx>(
         }
     }
 
-    let ty = substs.type_at(0);
+    let ty = args.type_at(0);
     let infcx = cx.tcx.infer_ctxt().build();
     let ocx = ObligationCtxt::new(&infcx);
 
diff --git a/compiler/rustc_lint/src/internal.rs b/compiler/rustc_lint/src/internal.rs
index 6f773e04a97..4b803621f71 100644
--- a/compiler/rustc_lint/src/internal.rs
+++ b/compiler/rustc_lint/src/internal.rs
@@ -52,20 +52,20 @@ impl LateLintPass<'_> for DefaultHashTypes {
 }
 
 /// Helper function for lints that check for expressions with calls and use typeck results to
-/// get the `DefId` and `SubstsRef` of the function.
+/// get the `DefId` and `GenericArgsRef` of the function.
 fn typeck_results_of_method_fn<'tcx>(
     cx: &LateContext<'tcx>,
     expr: &Expr<'_>,
-) -> Option<(Span, DefId, ty::subst::SubstsRef<'tcx>)> {
+) -> Option<(Span, DefId, ty::GenericArgsRef<'tcx>)> {
     match expr.kind {
         ExprKind::MethodCall(segment, ..)
             if let Some(def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id) =>
         {
-            Some((segment.ident.span, def_id, cx.typeck_results().node_substs(expr.hir_id)))
+            Some((segment.ident.span, def_id, cx.typeck_results().node_args(expr.hir_id)))
         },
         _ => {
             match cx.typeck_results().node_type(expr.hir_id).kind() {
-                &ty::FnDef(def_id, substs) => Some((expr.span, def_id, substs)),
+                &ty::FnDef(def_id, args) => Some((expr.span, def_id, args)),
                 _ => None,
             }
         }
@@ -89,8 +89,8 @@ declare_lint_pass!(QueryStability => [POTENTIAL_QUERY_INSTABILITY]);
 
 impl LateLintPass<'_> for QueryStability {
     fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
-        let Some((span, def_id, substs)) = typeck_results_of_method_fn(cx, expr) else { return };
-        if let Ok(Some(instance)) = ty::Instance::resolve(cx.tcx, cx.param_env, def_id, substs) {
+        let Some((span, def_id, args)) = typeck_results_of_method_fn(cx, expr) else { return };
+        if let Ok(Some(instance)) = ty::Instance::resolve(cx.tcx, cx.param_env, def_id, args) {
             let def_id = instance.def_id();
             if cx.tcx.has_attr(def_id, sym::rustc_lint_query_instability) {
                 cx.emit_spanned_lint(
@@ -232,7 +232,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).subst_identity().kind() {
+            if let ty::Adt(adt, args) = cx.tcx.type_of(did).instantiate_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
@@ -241,7 +241,7 @@ fn is_ty_or_ty_ctxt(cx: &LateContext<'_>, path: &Path<'_>) -> Option<String> {
                     //
                     // I(@lcnr) still kept this branch in so we don't miss this
                     // if we ever change it in the future.
-                    return Some(format!("{}<{}>", name, substs[0]));
+                    return Some(format!("{}<{}>", name, args[0]));
                 }
             }
         }
@@ -379,9 +379,9 @@ declare_lint_pass!(Diagnostics => [ UNTRANSLATABLE_DIAGNOSTIC, DIAGNOSTIC_OUTSID
 
 impl LateLintPass<'_> for Diagnostics {
     fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
-        let Some((span, def_id, substs)) = typeck_results_of_method_fn(cx, expr) else { return };
-        debug!(?span, ?def_id, ?substs);
-        let has_attr = ty::Instance::resolve(cx.tcx, cx.param_env, def_id, substs)
+        let Some((span, def_id, args)) = typeck_results_of_method_fn(cx, expr) else { return };
+        debug!(?span, ?def_id, ?args);
+        let has_attr = ty::Instance::resolve(cx.tcx, cx.param_env, def_id, args)
             .ok()
             .flatten()
             .is_some_and(|inst| cx.tcx.has_attr(inst.def_id(), sym::rustc_lint_diagnostics));
@@ -414,7 +414,7 @@ impl LateLintPass<'_> for Diagnostics {
         }
 
         let mut found_diagnostic_message = false;
-        for ty in substs.types() {
+        for ty in args.types() {
             debug!(?ty);
             if let Some(adt_def) = ty.ty_adt_def() &&
                 let Some(name) =  cx.tcx.get_diagnostic_name(adt_def.did()) &&
diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs
index 8376835f52c..c9ee2da6fdf 100644
--- a/compiler/rustc_lint/src/levels.rs
+++ b/compiler/rustc_lint/src/levels.rs
@@ -265,7 +265,10 @@ impl LintLevelsProvider for QueryMapExpectationsWrapper<'_> {
         self.specs.lint_level_id_at_node(self.tcx, LintId::of(lint), self.cur)
     }
     fn push_expectation(&mut self, id: LintExpectationId, expectation: LintExpectation) {
-        let LintExpectationId::Stable { attr_id: Some(attr_id), hir_id, attr_index, .. } = id else { bug!("unstable expectation id should already be mapped") };
+        let LintExpectationId::Stable { attr_id: Some(attr_id), hir_id, attr_index, .. } = id
+        else {
+            bug!("unstable expectation id should already be mapped")
+        };
         let key = LintExpectationId::Unstable { attr_id, lint_index: None };
 
         self.unstable_to_stable_ids.entry(key).or_insert(LintExpectationId::Stable {
@@ -542,7 +545,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> {
 
             let Ok(ids) = self.store.find_lints(&lint_name) else {
                 // errors handled in check_lint_name_cmdline above
-                continue
+                continue;
             };
             for id in ids {
                 // ForceWarn and Forbid cannot be overridden
@@ -685,9 +688,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> {
                 Some(lvl) => lvl,
             };
 
-            let Some(mut metas) = attr.meta_item_list() else {
-                continue
-            };
+            let Some(mut metas) = attr.meta_item_list() else { continue };
 
             if metas.is_empty() {
                 // This emits the unused_attributes lint for `#[level()]`
@@ -956,8 +957,9 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> {
                     continue;
                 }
 
-                let LintLevelSource::Node { name: lint_attr_name, span: lint_attr_span, .. } = *src else {
-                    continue
+                let LintLevelSource::Node { name: lint_attr_name, span: lint_attr_span, .. } = *src
+                else {
+                    continue;
                 };
 
                 self.emit_spanned_lint(
diff --git a/compiler/rustc_lint/src/methods.rs b/compiler/rustc_lint/src/methods.rs
index 4c25d94a1f3..5b63b19c53c 100644
--- a/compiler/rustc_lint/src/methods.rs
+++ b/compiler/rustc_lint/src/methods.rs
@@ -53,9 +53,9 @@ fn lint_cstring_as_ptr(
     unwrap: &rustc_hir::Expr<'_>,
 ) {
     let source_type = cx.typeck_results().expr_ty(source);
-    if let ty::Adt(def, substs) = source_type.kind() {
+    if let ty::Adt(def, args) = source_type.kind() {
         if cx.tcx.is_diagnostic_item(sym::Result, def.did()) {
-            if let ty::Adt(adt, _) = substs.type_at(0).kind() {
+            if let ty::Adt(adt, _) = args.type_at(0).kind() {
                 if cx.tcx.is_diagnostic_item(sym::cstring_type, adt.did()) {
                     cx.emit_spanned_lint(
                         TEMPORARY_CSTRING_AS_PTR,
diff --git a/compiler/rustc_lint/src/noop_method_call.rs b/compiler/rustc_lint/src/noop_method_call.rs
index d56c35bb677..13f650c2008 100644
--- a/compiler/rustc_lint/src/noop_method_call.rs
+++ b/compiler/rustc_lint/src/noop_method_call.rs
@@ -79,8 +79,7 @@ impl<'tcx> LateLintPass<'tcx> for NoopMethodCall {
         // We only care about method calls corresponding to the `Clone`, `Deref` and `Borrow`
         // traits and ignore any other method call.
 
-        let Some((DefKind::AssocFn, did)) =
-            cx.typeck_results().type_dependent_def(expr.hir_id)
+        let Some((DefKind::AssocFn, did)) = cx.typeck_results().type_dependent_def(expr.hir_id)
         else {
             return;
         };
@@ -94,13 +93,11 @@ impl<'tcx> LateLintPass<'tcx> for NoopMethodCall {
             return;
         };
 
-        let substs = cx
+        let args = cx
             .tcx
-            .normalize_erasing_regions(cx.param_env, cx.typeck_results().node_substs(expr.hir_id));
+            .normalize_erasing_regions(cx.param_env, cx.typeck_results().node_args(expr.hir_id));
         // Resolve the trait method instance.
-        let Ok(Some(i)) = ty::Instance::resolve(cx.tcx, cx.param_env, did, substs) else {
-            return
-        };
+        let Ok(Some(i)) = ty::Instance::resolve(cx.tcx, cx.param_env, did, args) else { return };
         // (Re)check that it implements the noop diagnostic.
         let Some(name) = cx.tcx.get_diagnostic_name(i.def_id()) else { return };
 
diff --git a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs
index 09a1651c2f5..d5f0290767a 100644
--- a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs
+++ b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs
@@ -68,13 +68,17 @@ declare_lint_pass!(OpaqueHiddenInferredBound => [OPAQUE_HIDDEN_INFERRED_BOUND]);
 
 impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound {
     fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) {
-        let hir::ItemKind::OpaqueTy(opaque) = &item.kind else { return; };
+        let hir::ItemKind::OpaqueTy(opaque) = &item.kind else {
+            return;
+        };
         let def_id = item.owner_id.def_id.to_def_id();
         let infcx = &cx.tcx.infer_ctxt().build();
         // For every projection predicate in the opaque type's explicit bounds,
         // check that the type that we're assigning actually satisfies the bounds
         // of the associated type.
-        for (pred, pred_span) in cx.tcx.explicit_item_bounds(def_id).subst_identity_iter_copied() {
+        for (pred, pred_span) in
+            cx.tcx.explicit_item_bounds(def_id).instantiate_identity_iter_copied()
+        {
             // Liberate bound regions in the predicate since we
             // don't actually care about lifetimes in this check.
             let predicate = cx.tcx.liberate_late_bound_regions(def_id, pred.kind());
@@ -97,7 +101,7 @@ impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound {
             }
 
             let proj_ty =
-                Ty::new_projection(cx.tcx, proj.projection_ty.def_id, proj.projection_ty.substs);
+                Ty::new_projection(cx.tcx, proj.projection_ty.def_id, proj.projection_ty.args);
             // For every instance of the projection type in the bounds,
             // replace them with the term we're assigning to the associated
             // type in our opaque type.
@@ -113,10 +117,15 @@ impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound {
             for (assoc_pred, assoc_pred_span) in cx
                 .tcx
                 .explicit_item_bounds(proj.projection_ty.def_id)
-                .subst_iter_copied(cx.tcx, &proj.projection_ty.substs)
+                .arg_iter_copied(cx.tcx, &proj.projection_ty.args)
             {
                 let assoc_pred = assoc_pred.fold_with(proj_replacer);
-                let Ok(assoc_pred) = traits::fully_normalize(infcx, traits::ObligationCause::dummy(), cx.param_env, assoc_pred) else {
+                let Ok(assoc_pred) = traits::fully_normalize(
+                    infcx,
+                    traits::ObligationCause::dummy(),
+                    cx.param_env,
+                    assoc_pred,
+                ) else {
                     continue;
                 };
                 // If that predicate doesn't hold modulo regions (but passed during type-check),
@@ -147,7 +156,7 @@ impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound {
                             ty: Ty::new_opaque(
                                 cx.tcx,
                                 def_id,
-                                ty::InternalSubsts::identity_for_item(cx.tcx, def_id),
+                                ty::GenericArgs::identity_for_item(cx.tcx, def_id),
                             ),
                             proj_ty: proj_term,
                             assoc_pred_span,
diff --git a/compiler/rustc_lint/src/pass_by_value.rs b/compiler/rustc_lint/src/pass_by_value.rs
index 2bb2a3aab55..cad2cd7fa4c 100644
--- a/compiler/rustc_lint/src/pass_by_value.rs
+++ b/compiler/rustc_lint/src/pass_by_value.rs
@@ -50,9 +50,9 @@ 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).subst_identity().kind() {
+                if let ty::Adt(adt, args) = cx.tcx.type_of(did).instantiate_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));
+                        return Some(cx.tcx.def_path_str_with_args(adt.did(), args));
                     }
                 }
             }
diff --git a/compiler/rustc_lint/src/traits.rs b/compiler/rustc_lint/src/traits.rs
index de11208062d..56508a2a6cc 100644
--- a/compiler/rustc_lint/src/traits.rs
+++ b/compiler/rustc_lint/src/traits.rs
@@ -92,7 +92,7 @@ impl<'tcx> LateLintPass<'tcx> for DropTraitConstraints {
         let predicates = cx.tcx.explicit_predicates_of(item.owner_id);
         for &(predicate, span) in predicates.predicates {
             let ClauseKind::Trait(trait_predicate) = predicate.kind().skip_binder() else {
-                continue
+                continue;
             };
             let def_id = trait_predicate.trait_ref.def_id;
             if cx.tcx.lang_items().drop_trait() == Some(def_id) {
@@ -100,9 +100,7 @@ impl<'tcx> LateLintPass<'tcx> for DropTraitConstraints {
                 if trait_predicate.trait_ref.self_ty().is_impl_trait() {
                     continue;
                 }
-                let Some(def_id) = cx.tcx.get_diagnostic_item(sym::needs_drop) else {
-                    return
-                };
+                let Some(def_id) = cx.tcx.get_diagnostic_item(sym::needs_drop) else { return };
                 cx.emit_spanned_lint(
                     DROP_BOUNDS,
                     span,
@@ -113,15 +111,11 @@ impl<'tcx> LateLintPass<'tcx> for DropTraitConstraints {
     }
 
     fn check_ty(&mut self, cx: &LateContext<'_>, ty: &'tcx hir::Ty<'tcx>) {
-        let hir::TyKind::TraitObject(bounds, _lifetime, _syntax) = &ty.kind else {
-            return
-        };
+        let hir::TyKind::TraitObject(bounds, _lifetime, _syntax) = &ty.kind else { return };
         for bound in &bounds[..] {
             let def_id = bound.trait_ref.trait_def_id();
             if cx.tcx.lang_items().drop_trait() == def_id {
-                let Some(def_id) = cx.tcx.get_diagnostic_item(sym::needs_drop) else {
-                    return
-                };
+                let Some(def_id) = cx.tcx.get_diagnostic_item(sym::needs_drop) else { return };
                 cx.emit_spanned_lint(DYN_DROP, bound.span, DropGlue { tcx: cx.tcx, def_id });
             }
         }
diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs
index 2509d493a4c..cc8a3408004 100644
--- a/compiler/rustc_lint/src/types.rs
+++ b/compiler/rustc_lint/src/types.rs
@@ -17,7 +17,7 @@ use rustc_errors::DiagnosticMessage;
 use rustc_hir as hir;
 use rustc_hir::{is_range_literal, Expr, ExprKind, Node};
 use rustc_middle::ty::layout::{IntegerExt, LayoutOf, SizeSkeleton};
-use rustc_middle::ty::subst::SubstsRef;
+use rustc_middle::ty::GenericArgsRef;
 use rustc_middle::ty::{
     self, AdtKind, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
 };
@@ -560,7 +560,10 @@ fn lint_nan<'tcx>(
         let expr = expr.peel_blocks().peel_borrows();
         match expr.kind {
             ExprKind::Path(qpath) => {
-                let Some(def_id) = cx.typeck_results().qpath_res(&qpath, expr.hir_id).opt_def_id() else { return false; };
+                let Some(def_id) = cx.typeck_results().qpath_res(&qpath, expr.hir_id).opt_def_id()
+                else {
+                    return false;
+                };
 
                 matches!(cx.tcx.get_diagnostic_name(def_id), Some(sym::f32_nan | sym::f64_nan))
             }
@@ -805,7 +808,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).subst_identity();
+        let field_ty = tcx.type_of(field.did).instantiate_identity();
         let is_zst = tcx.layout_of(param_env.and(field_ty)).is_ok_and(|layout| layout.is_zst());
         !is_zst
     })
@@ -818,7 +821,7 @@ fn ty_is_known_nonnull<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, mode: CItemKi
         ty::FnPtr(_) => true,
         ty::Ref(..) => true,
         ty::Adt(def, _) if def.is_box() && matches!(mode, CItemKind::Definition) => true,
-        ty::Adt(def, substs) if def.repr().transparent() && !def.is_union() => {
+        ty::Adt(def, args) if def.repr().transparent() && !def.is_union() => {
             let marked_non_null = nonnull_optimization_guaranteed(tcx, *def);
 
             if marked_non_null {
@@ -833,7 +836,7 @@ fn ty_is_known_nonnull<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, mode: CItemKi
             def.variants()
                 .iter()
                 .filter_map(|variant| transparent_newtype_field(cx.tcx, variant))
-                .any(|field| ty_is_known_nonnull(cx, field.ty(tcx, substs), mode))
+                .any(|field| ty_is_known_nonnull(cx, field.ty(tcx, args), mode))
         }
         _ => false,
     }
@@ -844,7 +847,7 @@ fn ty_is_known_nonnull<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, mode: CItemKi
 fn get_nullable_type<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option<Ty<'tcx>> {
     let tcx = cx.tcx;
     Some(match *ty.kind() {
-        ty::Adt(field_def, field_substs) => {
+        ty::Adt(field_def, field_args) => {
             let inner_field_ty = {
                 let mut first_non_zst_ty = field_def
                     .variants()
@@ -858,7 +861,7 @@ fn get_nullable_type<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option<Ty<'t
                 first_non_zst_ty
                     .next_back()
                     .expect("No non-zst fields in transparent type.")
-                    .ty(tcx, field_substs)
+                    .ty(tcx, field_args)
             };
             return get_nullable_type(cx, inner_field_ty);
         }
@@ -897,10 +900,10 @@ pub(crate) fn repr_nullable_ptr<'tcx>(
     ckind: CItemKind,
 ) -> Option<Ty<'tcx>> {
     debug!("is_repr_nullable_ptr(cx, ty = {:?})", ty);
-    if let ty::Adt(ty_def, substs) = ty.kind() {
+    if let ty::Adt(ty_def, args) = ty.kind() {
         let field_ty = match &ty_def.variants().raw[..] {
             [var_one, var_two] => match (&var_one.fields.raw[..], &var_two.fields.raw[..]) {
-                ([], [field]) | ([field], []) => field.ty(cx.tcx, substs),
+                ([], [field]) | ([field], []) => field.ty(cx.tcx, args),
                 _ => return None,
             },
             _ => return None,
@@ -960,9 +963,9 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
         &self,
         cache: &mut FxHashSet<Ty<'tcx>>,
         field: &ty::FieldDef,
-        substs: SubstsRef<'tcx>,
+        args: GenericArgsRef<'tcx>,
     ) -> FfiResult<'tcx> {
-        let field_ty = field.ty(self.cx.tcx, substs);
+        let field_ty = field.ty(self.cx.tcx, args);
         if field_ty.has_opaque_types() {
             self.check_type_for_ffi(cache, field_ty)
         } else {
@@ -978,7 +981,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
         ty: Ty<'tcx>,
         def: ty::AdtDef<'tcx>,
         variant: &ty::VariantDef,
-        substs: SubstsRef<'tcx>,
+        args: GenericArgsRef<'tcx>,
     ) -> FfiResult<'tcx> {
         use FfiResult::*;
 
@@ -986,7 +989,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
             // Can assume that at most one field is not a ZST, so only check
             // that field's type for FFI-safety.
             if let Some(field) = transparent_newtype_field(self.cx.tcx, variant) {
-                return self.check_field_type_for_ffi(cache, field, substs);
+                return self.check_field_type_for_ffi(cache, field, args);
             } else {
                 // All fields are ZSTs; this means that the type should behave
                 // like (), which is FFI-unsafe... except if all fields are PhantomData,
@@ -998,7 +1001,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
         // actually safe.
         let mut all_phantom = !variant.fields.is_empty();
         for field in &variant.fields {
-            match self.check_field_type_for_ffi(cache, &field, substs) {
+            match self.check_field_type_for_ffi(cache, &field, args) {
                 FfiSafe => {
                     all_phantom = false;
                 }
@@ -1033,7 +1036,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
         }
 
         match *ty.kind() {
-            ty::Adt(def, substs) => {
+            ty::Adt(def, args) => {
                 if def.is_box() && matches!(self.mode, CItemKind::Definition) {
                     if ty.boxed_ty().is_sized(tcx, self.cx.param_env) {
                         return FfiSafe;
@@ -1096,7 +1099,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
                             };
                         }
 
-                        self.check_variant_for_ffi(cache, ty, def, def.non_enum_variant(), substs)
+                        self.check_variant_for_ffi(cache, ty, def, def.non_enum_variant(), args)
                     }
                     AdtKind::Enum => {
                         if def.variants().is_empty() {
@@ -1137,7 +1140,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
                                 };
                             }
 
-                            match self.check_variant_for_ffi(cache, ty, def, variant, substs) {
+                            match self.check_variant_for_ffi(cache, ty, def, variant, args) {
                                 FfiSafe => (),
                                 r => return r,
                             }
@@ -1384,7 +1387,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
     /// For a external ABI function, argument types and the result type are walked to find fn-ptr
     /// types that have external ABIs, as these still need checked.
     fn check_fn(&mut self, def_id: LocalDefId, decl: &'tcx hir::FnDecl<'_>) {
-        let sig = self.cx.tcx.fn_sig(def_id).subst_identity();
+        let sig = self.cx.tcx.fn_sig(def_id).instantiate_identity();
         let sig = self.cx.tcx.erase_late_bound_regions(sig);
 
         for (input_ty, input_hir) in iter::zip(sig.inputs(), decl.inputs) {
@@ -1402,7 +1405,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
 
     /// Check if a function's argument types and result type are "ffi-safe".
     fn check_foreign_fn(&mut self, def_id: LocalDefId, decl: &'tcx hir::FnDecl<'_>) {
-        let sig = self.cx.tcx.fn_sig(def_id).subst_identity();
+        let sig = self.cx.tcx.fn_sig(def_id).instantiate_identity();
         let sig = self.cx.tcx.erase_late_bound_regions(sig);
 
         for (input_ty, input_hir) in iter::zip(sig.inputs(), decl.inputs) {
@@ -1415,7 +1418,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).subst_identity();
+        let ty = self.cx.tcx.type_of(id).instantiate_identity();
         self.check_type_for_ffi_and_report_errors(span, ty, true, false);
     }
 
@@ -1521,7 +1524,7 @@ impl<'tcx> LateLintPass<'tcx> for ImproperCTypesDefinitions {
                 self.check_ty_maybe_containing_foreign_fnptr(
                     cx,
                     ty,
-                    cx.tcx.type_of(item.owner_id).subst_identity(),
+                    cx.tcx.type_of(item.owner_id).instantiate_identity(),
                 );
             }
             // See `check_fn`..
@@ -1546,7 +1549,7 @@ impl<'tcx> LateLintPass<'tcx> for ImproperCTypesDefinitions {
         self.check_ty_maybe_containing_foreign_fnptr(
             cx,
             field.ty,
-            cx.tcx.type_of(field.def_id).subst_identity(),
+            cx.tcx.type_of(field.def_id).instantiate_identity(),
         );
     }
 
@@ -1581,13 +1584,13 @@ 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).subst_identity();
+            let t = cx.tcx.type_of(it.owner_id).instantiate_identity();
             let ty = cx.tcx.erase_regions(t);
             let Ok(layout) = cx.layout_of(ty) else { return };
-            let Variants::Multiple {
-                    tag_encoding: TagEncoding::Direct, tag, ref variants, ..
-                } = &layout.variants else {
-                return
+            let Variants::Multiple { tag_encoding: TagEncoding::Direct, tag, ref variants, .. } =
+                &layout.variants
+            else {
+                return;
             };
 
             let tag_size = tag.size(&cx.tcx).bytes();
@@ -1701,7 +1704,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).subst_identity().ty_adt_def()
+            && let Some(adt) = cx.tcx.type_of(impl_did).instantiate_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())
@@ -1760,8 +1763,13 @@ impl InvalidAtomicOrdering {
     }
 
     fn check_atomic_compare_exchange(cx: &LateContext<'_>, expr: &Expr<'_>) {
-        let Some((method, args)) = Self::inherent_atomic_method_call(cx, expr, &[sym::fetch_update, sym::compare_exchange, sym::compare_exchange_weak])
-            else {return };
+        let Some((method, args)) = Self::inherent_atomic_method_call(
+            cx,
+            expr,
+            &[sym::fetch_update, sym::compare_exchange, sym::compare_exchange_weak],
+        ) else {
+            return;
+        };
 
         let fail_order_arg = match method {
             sym::fetch_update => &args[1],
diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs
index 5015b751eee..f78da284a3a 100644
--- a/compiler/rustc_lint/src/unused.rs
+++ b/compiler/rustc_lint/src/unused.rs
@@ -94,7 +94,9 @@ declare_lint_pass!(UnusedResults => [UNUSED_MUST_USE, UNUSED_RESULTS]);
 
 impl<'tcx> LateLintPass<'tcx> for UnusedResults {
     fn check_stmt(&mut self, cx: &LateContext<'_>, s: &hir::Stmt<'_>) {
-        let hir::StmtKind::Semi(mut expr) = s.kind else { return; };
+        let hir::StmtKind::Semi(mut expr) = s.kind else {
+            return;
+        };
 
         let mut expr_is_from_block = false;
         while let hir::ExprKind::Block(blk, ..) = expr.kind
@@ -284,22 +286,25 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
                 }
                 ty::Adt(def, _) => is_def_must_use(cx, def.did(), span),
                 ty::Alias(ty::Opaque, ty::AliasTy { def_id: def, .. }) => {
-                    elaborate(cx.tcx, cx.tcx.explicit_item_bounds(def).subst_identity_iter_copied())
-                        // We only care about self bounds for the impl-trait
-                        .filter_only_self()
-                        .find_map(|(pred, _span)| {
-                            // We only look at the `DefId`, so it is safe to skip the binder here.
-                            if let ty::ClauseKind::Trait(ref poly_trait_predicate) =
-                                pred.kind().skip_binder()
-                            {
-                                let def_id = poly_trait_predicate.trait_ref.def_id;
-
-                                is_def_must_use(cx, def_id, span)
-                            } else {
-                                None
-                            }
-                        })
-                        .map(|inner| MustUsePath::Opaque(Box::new(inner)))
+                    elaborate(
+                        cx.tcx,
+                        cx.tcx.explicit_item_bounds(def).instantiate_identity_iter_copied(),
+                    )
+                    // We only care about self bounds for the impl-trait
+                    .filter_only_self()
+                    .find_map(|(pred, _span)| {
+                        // We only look at the `DefId`, so it is safe to skip the binder here.
+                        if let ty::ClauseKind::Trait(ref poly_trait_predicate) =
+                            pred.kind().skip_binder()
+                        {
+                            let def_id = poly_trait_predicate.trait_ref.def_id;
+
+                            is_def_must_use(cx, def_id, span)
+                        } else {
+                            None
+                        }
+                    })
+                    .map(|inner| MustUsePath::Opaque(Box::new(inner)))
                 }
                 ty::Dynamic(binders, _, _) => binders.iter().find_map(|predicate| {
                     if let ty::ExistentialPredicate::Trait(ref trait_ref) = predicate.skip_binder()
diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs
index 5a5031b7919..f6ffd46b1fe 100644
--- a/compiler/rustc_lint_defs/src/lib.rs
+++ b/compiler/rustc_lint_defs/src/lib.rs
@@ -550,6 +550,12 @@ pub enum BuiltinLintDiagnostics {
         /// The local binding that shadows the glob reexport.
         private_item_span: Span,
     },
+    UnusedQualifications {
+        /// The span of the unnecessarily-qualified path.
+        path_span: Span,
+        /// The replacement unqualified path.
+        unqualified_path: Ident,
+    },
 }
 
 /// Lints that are buffered up early on in the `Session` before the
diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
index c43a0272477..eb3d67e720f 100644
--- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
@@ -667,6 +667,7 @@ LLVMRustOptimize(
     assert(!PGOUsePath && !PGOSampleUsePath);
     PGOOpt = PGOOptions(PGOGenPath, "", "",
 #if LLVM_VERSION_GE(17, 0)
+                        "",
                         FS,
 #endif
                         PGOOptions::IRInstr, PGOOptions::NoCSAction,
@@ -675,6 +676,7 @@ LLVMRustOptimize(
     assert(!PGOSampleUsePath);
     PGOOpt = PGOOptions(PGOUsePath, "", "",
 #if LLVM_VERSION_GE(17, 0)
+                        "",
                         FS,
 #endif
                         PGOOptions::IRUse, PGOOptions::NoCSAction,
@@ -682,6 +684,7 @@ LLVMRustOptimize(
   } else if (PGOSampleUsePath) {
     PGOOpt = PGOOptions(PGOSampleUsePath, "", "",
 #if LLVM_VERSION_GE(17, 0)
+                        "",
                         FS,
 #endif
                         PGOOptions::SampleUse, PGOOptions::NoCSAction,
@@ -689,6 +692,7 @@ LLVMRustOptimize(
   } else if (DebugInfoForProfiling) {
     PGOOpt = PGOOptions("", "", "",
 #if LLVM_VERSION_GE(17, 0)
+                        "",
                         FS,
 #endif
                         PGOOptions::NoAction, PGOOptions::NoCSAction,
diff --git a/compiler/rustc_llvm/llvm-wrapper/SymbolWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/SymbolWrapper.cpp
index 0493d6b05d0..bf00d11edf6 100644
--- a/compiler/rustc_llvm/llvm-wrapper/SymbolWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/SymbolWrapper.cpp
@@ -7,6 +7,7 @@
 // * https://github.com/llvm/llvm-project/blob/8ef3e895ad8ab1724e2b87cabad1dacdc7a397a3/llvm/include/llvm/Object/ArchiveWriter.h
 // * https://github.com/llvm/llvm-project/blob/8ef3e895ad8ab1724e2b87cabad1dacdc7a397a3/llvm/lib/Object/ArchiveWriter.cpp
 
+#include "llvm/ADT/SmallString.h"
 #include "llvm/IR/LLVMContext.h"
 #include "llvm/Object/ObjectFile.h"
 
diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs
index 2e6e84ad80e..e9a5cd9de97 100644
--- a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs
+++ b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs
@@ -203,14 +203,18 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> {
                 if first && (nested.input.is_empty() || nested.input.peek(Token![,])) {
                     self.slug.set_once(path.clone(), path.span().unwrap());
                     first = false;
-                    return Ok(())
+                    return Ok(());
                 }
 
                 first = false;
 
                 let Ok(nested) = nested.value() else {
-                    span_err(nested.input.span().unwrap(), "diagnostic slug must be the first argument").emit();
-                    return Ok(())
+                    span_err(
+                        nested.input.span().unwrap(),
+                        "diagnostic slug must be the first argument",
+                    )
+                    .emit();
+                    return Ok(());
                 };
 
                 if path.is_ident("code") {
@@ -221,7 +225,9 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> {
                         #diag.code(rustc_errors::DiagnosticId::Error(#code.to_string()));
                     });
                 } else {
-                    span_err(path.span().unwrap(), "unknown argument").note("only the `code` parameter is valid after the slug").emit();
+                    span_err(path.span().unwrap(), "unknown argument")
+                        .note("only the `code` parameter is valid after the slug")
+                        .emit();
 
                     // consume the buffer so we don't have syntax errors from syn
                     let _ = nested.parse::<TokenStream>();
diff --git a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs
index e8dc986914e..877e9745054 100644
--- a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs
+++ b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs
@@ -188,7 +188,9 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> {
         let mut kind_slugs = vec![];
 
         for attr in self.variant.ast().attrs {
-            let Some(SubdiagnosticVariant { kind, slug, no_span }) = SubdiagnosticVariant::from_attr(attr, self)? else {
+            let Some(SubdiagnosticVariant { kind, slug, no_span }) =
+                SubdiagnosticVariant::from_attr(attr, self)?
+            else {
                 // Some attributes aren't errors - like documentation comments - but also aren't
                 // subdiagnostics.
                 continue;
diff --git a/compiler/rustc_macros/src/newtype.rs b/compiler/rustc_macros/src/newtype.rs
index 415a89b0f92..72b47de1abc 100644
--- a/compiler/rustc_macros/src/newtype.rs
+++ b/compiler/rustc_macros/src/newtype.rs
@@ -36,7 +36,8 @@ impl Parse for Newtype {
                     false
                 }
                 "max" => {
-                    let Meta::NameValue(MetaNameValue { value: Expr::Lit(lit), .. }) = &attr.meta else {
+                    let Meta::NameValue(MetaNameValue { value: Expr::Lit(lit), .. }) = &attr.meta
+                    else {
                         panic!("#[max = NUMBER] attribute requires max value");
                     };
 
@@ -47,7 +48,8 @@ impl Parse for Newtype {
                     false
                 }
                 "debug_format" => {
-                    let Meta::NameValue(MetaNameValue { value: Expr::Lit(lit), .. }) = &attr.meta else {
+                    let Meta::NameValue(MetaNameValue { value: Expr::Lit(lit), .. }) = &attr.meta
+                    else {
                         panic!("#[debug_format = FMT] attribute requires a format");
                     };
 
diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs
index b3976d756eb..571af82d13a 100644
--- a/compiler/rustc_metadata/src/creader.rs
+++ b/compiler/rustc_metadata/src/creader.rs
@@ -741,7 +741,9 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
         };
         info!("panic runtime not found -- loading {}", name);
 
-        let Some(cnum) = self.resolve_crate(name, DUMMY_SP, CrateDepKind::Implicit) else { return; };
+        let Some(cnum) = self.resolve_crate(name, DUMMY_SP, CrateDepKind::Implicit) else {
+            return;
+        };
         let data = self.cstore.get_crate_data(cnum);
 
         // Sanity check the loaded crate to ensure it is indeed a panic runtime
@@ -774,7 +776,9 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
             self.sess.emit_err(errors::ProfilerBuiltinsNeedsCore);
         }
 
-        let Some(cnum) = self.resolve_crate(name, DUMMY_SP, CrateDepKind::Implicit) else { return; };
+        let Some(cnum) = self.resolve_crate(name, DUMMY_SP, CrateDepKind::Implicit) else {
+            return;
+        };
         let data = self.cstore.get_crate_data(cnum);
 
         // Sanity check the loaded crate to ensure it is indeed a profiler runtime
diff --git a/compiler/rustc_metadata/src/locator.rs b/compiler/rustc_metadata/src/locator.rs
index a89d7b464e2..a1511c4b570 100644
--- a/compiler/rustc_metadata/src/locator.rs
+++ b/compiler/rustc_metadata/src/locator.rs
@@ -804,8 +804,12 @@ fn get_metadata_section<'p>(
             }
 
             // Length of the compressed stream - this allows linkers to pad the section if they want
-            let Ok(len_bytes) = <[u8; 4]>::try_from(&buf[header_len..cmp::min(data_start, buf.len())]) else {
-                return Err(MetadataError::LoadFailure("invalid metadata length found".to_string()));
+            let Ok(len_bytes) =
+                <[u8; 4]>::try_from(&buf[header_len..cmp::min(data_start, buf.len())])
+            else {
+                return Err(MetadataError::LoadFailure(
+                    "invalid metadata length found".to_string(),
+                ));
             };
             let compressed_len = u32::from_be_bytes(len_bytes) as usize;
 
diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs
index 0dd7b119791..9e0bf81d58d 100644
--- a/compiler/rustc_metadata/src/native_libs.rs
+++ b/compiler/rustc_metadata/src/native_libs.rs
@@ -480,7 +480,7 @@ 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()
+                .instantiate_identity()
                 .fn_sig(self.tcx)
                 .inputs()
                 .map_bound(|slice| self.tcx.mk_type_list(slice)),
diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs
index b9318aee581..8fa1d365728 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder.rs
@@ -311,8 +311,10 @@ impl<'a, 'tcx> DecodeContext<'a, 'tcx> {
     #[inline]
     fn tcx(&self) -> TyCtxt<'tcx> {
         let Some(tcx) = self.tcx else {
-            bug!("No TyCtxt found for decoding. \
-                You need to explicitly pass `(crate_metadata_ref, tcx)` to `decode` instead of just `crate_metadata_ref`.");
+            bug!(
+                "No TyCtxt found for decoding. \
+                You need to explicitly pass `(crate_metadata_ref, tcx)` to `decode` instead of just `crate_metadata_ref`."
+            );
         };
         tcx
     }
@@ -448,8 +450,10 @@ impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for SyntaxContext {
         let cdata = decoder.cdata();
 
         let Some(sess) = decoder.sess else {
-            bug!("Cannot decode SyntaxContext without Session.\
-                You need to explicitly pass `(crate_metadata_ref, tcx)` to `decode` instead of just `crate_metadata_ref`.");
+            bug!(
+                "Cannot decode SyntaxContext without Session.\
+                You need to explicitly pass `(crate_metadata_ref, tcx)` to `decode` instead of just `crate_metadata_ref`."
+            );
         };
 
         let cname = cdata.root.name();
@@ -470,8 +474,10 @@ impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for ExpnId {
         let local_cdata = decoder.cdata();
 
         let Some(sess) = decoder.sess else {
-            bug!("Cannot decode ExpnId without Session. \
-                You need to explicitly pass `(crate_metadata_ref, tcx)` to `decode` instead of just `crate_metadata_ref`.");
+            bug!(
+                "Cannot decode ExpnId without Session. \
+                You need to explicitly pass `(crate_metadata_ref, tcx)` to `decode` instead of just `crate_metadata_ref`."
+            );
         };
 
         let cnum = CrateNum::decode(decoder);
@@ -521,8 +527,10 @@ impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for Span {
         let hi = lo + len;
 
         let Some(sess) = decoder.sess else {
-            bug!("Cannot decode Span without Session. \
-                You need to explicitly pass `(crate_metadata_ref, tcx)` to `decode` instead of just `crate_metadata_ref`.")
+            bug!(
+                "Cannot decode Span without Session. \
+                You need to explicitly pass `(crate_metadata_ref, tcx)` to `decode` instead of just `crate_metadata_ref`."
+            )
         };
 
         // Index of the file in the corresponding crate's list of encoded files.
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index 01dd35b0e5b..b5f955d14fb 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -1136,7 +1136,7 @@ fn should_encode_type(tcx: TyCtxt<'_>, def_id: LocalDefId, def_kind: DefKind) ->
                 // the default projection predicates in default trait methods
                 // with RPITITs.
                 ty::AssocItemContainer::TraitContainer => {
-                    assoc_item.defaultness(tcx).has_value() || assoc_item.opt_rpitit_info.is_some()
+                    assoc_item.defaultness(tcx).has_value() || assoc_item.is_impl_trait_in_trait()
                 }
             }
         }
@@ -1671,7 +1671,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
     fn encode_info_for_macro(&mut self, def_id: LocalDefId) {
         let tcx = self.tcx;
 
-        let hir::ItemKind::Macro(ref macro_def, _) = tcx.hir().expect_item(def_id).kind else { bug!() };
+        let hir::ItemKind::Macro(ref macro_def, _) = tcx.hir().expect_item(def_id).kind else {
+            bug!()
+        };
         self.tables.is_macro_rules.set(def_id.local_def_index, macro_def.macro_rules);
         record!(self.tables.macro_definition[def_id.to_def_id()] <- &*macro_def.body);
     }
@@ -1911,7 +1913,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
             FxHashMap::default();
 
         for id in tcx.hir().items() {
-            let DefKind::Impl { of_trait } = tcx.def_kind(id.owner_id) else { continue; };
+            let DefKind::Impl { of_trait } = tcx.def_kind(id.owner_id) else {
+                continue;
+            };
             let def_id = id.owner_id.to_def_id();
 
             self.tables.defaultness.set_some(def_id.index, tcx.defaultness(def_id));
@@ -1920,7 +1924,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
             if of_trait && let Some(trait_ref) = tcx.impl_trait_ref(def_id) {
                 record!(self.tables.impl_trait_ref[def_id] <- trait_ref);
 
-                let trait_ref = trait_ref.subst_identity();
+                let trait_ref = trait_ref.instantiate_identity();
                 let simplified_self_ty =
                     fast_reject::simplify_type(self.tcx, trait_ref.self_ty(), TreatParams::AsCandidateKey);
                 fx_hash_map
diff --git a/compiler/rustc_metadata/src/rmeta/table.rs b/compiler/rustc_metadata/src/rmeta/table.rs
index a4313d79ab1..4287799a8e6 100644
--- a/compiler/rustc_metadata/src/rmeta/table.rs
+++ b/compiler/rustc_metadata/src/rmeta/table.rs
@@ -323,7 +323,7 @@ impl<T> FixedSizeEncoding for Option<LazyValue<T>> {
 impl<T> LazyArray<T> {
     #[inline]
     fn write_to_bytes_impl(self, b: &mut [u8; 8]) {
-        let ([position_bytes, meta_bytes],[])= b.as_chunks_mut::<4>() else { panic!() };
+        let ([position_bytes, meta_bytes], []) = b.as_chunks_mut::<4>() else { panic!() };
 
         let position = self.position.get();
         let position: u32 = position.try_into().unwrap();
@@ -346,7 +346,7 @@ impl<T> FixedSizeEncoding for LazyArray<T> {
 
     #[inline]
     fn from_bytes(b: &[u8; 8]) -> Self {
-        let ([position_bytes, meta_bytes],[])= b.as_chunks::<4>() else { panic!() };
+        let ([position_bytes, meta_bytes], []) = b.as_chunks::<4>() else { panic!() };
         if *meta_bytes == [0; 4] {
             return Default::default();
         }
@@ -365,7 +365,7 @@ impl<T> FixedSizeEncoding for Option<LazyArray<T>> {
 
     #[inline]
     fn from_bytes(b: &[u8; 8]) -> Self {
-        let ([position_bytes, meta_bytes],[])= b.as_chunks::<4>() else { panic!() };
+        let ([position_bytes, meta_bytes], []) = b.as_chunks::<4>() else { panic!() };
         LazyArray::from_bytes_impl(position_bytes, meta_bytes)
     }
 
diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs
index 6bb8e632dbe..1fd68dc5cb2 100644
--- a/compiler/rustc_middle/src/hir/map/mod.rs
+++ b/compiler/rustc_middle/src/hir/map/mod.rs
@@ -1103,6 +1103,33 @@ impl<'hir> Map<'hir> {
             _ => None,
         }
     }
+
+    pub fn maybe_get_struct_pattern_shorthand_field(&self, expr: &Expr<'_>) -> Option<Symbol> {
+        let local = match expr {
+            Expr {
+                kind:
+                    ExprKind::Path(QPath::Resolved(
+                        None,
+                        Path {
+                            res: def::Res::Local(_), segments: [PathSegment { ident, .. }], ..
+                        },
+                    )),
+                ..
+            } => Some(ident),
+            _ => None,
+        }?;
+
+        match self.find_parent(expr.hir_id)? {
+            Node::ExprField(field) => {
+                if field.ident.name == local.name && field.is_shorthand {
+                    return Some(local.name);
+                }
+            }
+            _ => {}
+        }
+
+        None
+    }
 }
 
 impl<'hir> intravisit::Map<'hir> for Map<'hir> {
diff --git a/compiler/rustc_middle/src/infer/canonical.rs b/compiler/rustc_middle/src/infer/canonical.rs
index d5e8330b3f6..81823118ab8 100644
--- a/compiler/rustc_middle/src/infer/canonical.rs
+++ b/compiler/rustc_middle/src/infer/canonical.rs
@@ -23,7 +23,7 @@
 
 use crate::infer::MemberConstraint;
 use crate::mir::ConstraintCategory;
-use crate::ty::subst::GenericArg;
+use crate::ty::GenericArg;
 use crate::ty::{self, BoundVar, List, Region, Ty, TyCtxt};
 use rustc_macros::HashStable;
 use smallvec::SmallVec;
@@ -63,7 +63,7 @@ impl<'tcx> ty::TypeFoldable<TyCtxt<'tcx>> for CanonicalVarInfos<'tcx> {
 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TyDecodable, TyEncodable)]
 #[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
 pub struct CanonicalVarValues<'tcx> {
-    pub var_values: ty::SubstsRef<'tcx>,
+    pub var_values: ty::GenericArgsRef<'tcx>,
 }
 
 impl CanonicalVarValues<'_> {
@@ -429,7 +429,7 @@ impl<'tcx> CanonicalVarValues<'tcx> {
         infos: CanonicalVarInfos<'tcx>,
     ) -> CanonicalVarValues<'tcx> {
         CanonicalVarValues {
-            var_values: tcx.mk_substs_from_iter(infos.iter().enumerate().map(
+            var_values: tcx.mk_args_from_iter(infos.iter().enumerate().map(
                 |(i, info)| -> ty::GenericArg<'tcx> {
                     match info.kind {
                         CanonicalVarKind::Ty(_) | CanonicalVarKind::PlaceholderTy(_) => {
diff --git a/compiler/rustc_middle/src/infer/mod.rs b/compiler/rustc_middle/src/infer/mod.rs
index 2db59f37f40..493bb8a6823 100644
--- a/compiler/rustc_middle/src/infer/mod.rs
+++ b/compiler/rustc_middle/src/infer/mod.rs
@@ -15,7 +15,7 @@ use rustc_span::Span;
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
 #[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
 pub struct MemberConstraint<'tcx> {
-    /// The `DefId` and substs of the opaque type causing this constraint.
+    /// The `DefId` and args of the opaque type causing this constraint.
     /// Used for error reporting.
     pub key: OpaqueTypeKey<'tcx>,
 
diff --git a/compiler/rustc_middle/src/lint.rs b/compiler/rustc_middle/src/lint.rs
index 81c1ae4f630..20230217afc 100644
--- a/compiler/rustc_middle/src/lint.rs
+++ b/compiler/rustc_middle/src/lint.rs
@@ -169,26 +169,6 @@ impl TyCtxt<'_> {
     pub fn lint_level_at_node(self, lint: &'static Lint, id: HirId) -> (Level, LintLevelSource) {
         self.shallow_lint_levels_on(id.owner).lint_level_id_at_node(self, LintId::of(lint), id)
     }
-
-    /// Walks upwards from `id` to find a node which might change lint levels with attributes.
-    /// It stops at `bound` and just returns it if reached.
-    pub fn maybe_lint_level_root_bounded(self, mut id: HirId, bound: HirId) -> HirId {
-        let hir = self.hir();
-        loop {
-            if id == bound {
-                return bound;
-            }
-
-            if hir.attrs(id).iter().any(|attr| Level::from_attr(attr).is_some()) {
-                return id;
-            }
-            let next = hir.parent_id(id);
-            if next == id {
-                bug!("lint traversal reached the root of the crate");
-            }
-            id = next;
-        }
-    }
 }
 
 /// This struct represents a lint expectation and holds all required information
diff --git a/compiler/rustc_middle/src/middle/exported_symbols.rs b/compiler/rustc_middle/src/middle/exported_symbols.rs
index 9041da9a060..f19812619b2 100644
--- a/compiler/rustc_middle/src/middle/exported_symbols.rs
+++ b/compiler/rustc_middle/src/middle/exported_symbols.rs
@@ -1,4 +1,4 @@
-use crate::ty::subst::SubstsRef;
+use crate::ty::GenericArgsRef;
 use crate::ty::{self, Ty, TyCtxt};
 use rustc_hir::def_id::{DefId, LOCAL_CRATE};
 use rustc_macros::HashStable;
@@ -41,7 +41,7 @@ pub struct SymbolExportInfo {
 #[derive(Eq, PartialEq, Debug, Copy, Clone, TyEncodable, TyDecodable, HashStable)]
 pub enum ExportedSymbol<'tcx> {
     NonGeneric(DefId),
-    Generic(DefId, SubstsRef<'tcx>),
+    Generic(DefId, GenericArgsRef<'tcx>),
     DropGlue(Ty<'tcx>),
     ThreadLocalShim(DefId),
     NoDefId(ty::SymbolName<'tcx>),
@@ -53,15 +53,15 @@ impl<'tcx> ExportedSymbol<'tcx> {
     pub fn symbol_name_for_local_instance(&self, tcx: TyCtxt<'tcx>) -> ty::SymbolName<'tcx> {
         match *self {
             ExportedSymbol::NonGeneric(def_id) => tcx.symbol_name(ty::Instance::mono(tcx, def_id)),
-            ExportedSymbol::Generic(def_id, substs) => {
-                tcx.symbol_name(ty::Instance::new(def_id, substs))
+            ExportedSymbol::Generic(def_id, args) => {
+                tcx.symbol_name(ty::Instance::new(def_id, args))
             }
             ExportedSymbol::DropGlue(ty) => {
                 tcx.symbol_name(ty::Instance::resolve_drop_in_place(tcx, ty))
             }
             ExportedSymbol::ThreadLocalShim(def_id) => tcx.symbol_name(ty::Instance {
                 def: ty::InstanceDef::ThreadLocalShim(def_id),
-                substs: ty::InternalSubsts::empty(),
+                args: ty::GenericArgs::empty(),
             }),
             ExportedSymbol::NoDefId(symbol_name) => symbol_name,
         }
diff --git a/compiler/rustc_middle/src/middle/region.rs b/compiler/rustc_middle/src/middle/region.rs
index 10712e14686..c50c5e6f701 100644
--- a/compiler/rustc_middle/src/middle/region.rs
+++ b/compiler/rustc_middle/src/middle/region.rs
@@ -10,7 +10,7 @@ use crate::ty::TyCtxt;
 use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_hir as hir;
-use rustc_hir::Node;
+use rustc_hir::{HirIdMap, Node};
 use rustc_macros::HashStable;
 use rustc_query_system::ich::StableHashingContext;
 use rustc_span::{Span, DUMMY_SP};
@@ -228,7 +228,7 @@ pub struct ScopeTree {
     /// and not the enclosing *statement*. Expressions that are not present in this
     /// table are not rvalue candidates. The set of rvalue candidates is computed
     /// during type check based on a traversal of the AST.
-    pub rvalue_candidates: FxHashMap<hir::HirId, RvalueCandidateType>,
+    pub rvalue_candidates: HirIdMap<RvalueCandidateType>,
 
     /// If there are any `yield` nested within a scope, this map
     /// stores the `Span` of the last one and its index in the
diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs
index 2435bc59ec0..372452ea29a 100644
--- a/compiler/rustc_middle/src/mir/interpret/error.rs
+++ b/compiler/rustc_middle/src/mir/interpret/error.rs
@@ -22,7 +22,7 @@ pub enum ErrorHandled {
     /// *guaranteed* to fail. Warnings/lints *must not* produce `Reported`.
     Reported(ReportedErrorInfo),
     /// Don't emit an error, the evaluation failed because the MIR was generic
-    /// and the substs didn't fully monomorphize it.
+    /// and the args didn't fully monomorphize it.
     TooGeneric,
 }
 
diff --git a/compiler/rustc_middle/src/mir/interpret/mod.rs b/compiler/rustc_middle/src/mir/interpret/mod.rs
index 2d2cfee1b21..fbd667a87fe 100644
--- a/compiler/rustc_middle/src/mir/interpret/mod.rs
+++ b/compiler/rustc_middle/src/mir/interpret/mod.rs
@@ -138,7 +138,7 @@ use rustc_target::abi::{AddressSpace, Endian, HasDataLayout};
 
 use crate::mir;
 use crate::ty::codec::{TyDecoder, TyEncoder};
-use crate::ty::subst::GenericArgKind;
+use crate::ty::GenericArgKind;
 use crate::ty::{self, Instance, Ty, TyCtxt};
 
 pub use self::error::{
@@ -559,7 +559,7 @@ impl<'tcx> TyCtxt<'tcx> {
         // However, formatting code relies on function identity (see #58320), so we only do
         // this for generic functions. Lifetime parameters are ignored.
         let is_generic = instance
-            .substs
+            .args
             .into_iter()
             .any(|kind| !matches!(kind.unpack(), GenericArgKind::Lifetime(_)));
         if is_generic {
diff --git a/compiler/rustc_middle/src/mir/interpret/queries.rs b/compiler/rustc_middle/src/mir/interpret/queries.rs
index 9c97431f361..c9db0e7c11d 100644
--- a/compiler/rustc_middle/src/mir/interpret/queries.rs
+++ b/compiler/rustc_middle/src/mir/interpret/queries.rs
@@ -2,8 +2,8 @@ use super::{ErrorHandled, EvalToConstValueResult, EvalToValTreeResult, GlobalId}
 
 use crate::mir;
 use crate::query::{TyCtxtAt, TyCtxtEnsure};
-use crate::ty::subst::InternalSubsts;
 use crate::ty::visit::TypeVisitableExt;
+use crate::ty::GenericArgs;
 use crate::ty::{self, TyCtxt};
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::DefId;
@@ -20,8 +20,8 @@ impl<'tcx> TyCtxt<'tcx> {
         // to be used. So we can't use `Instance::mono`, instead we feed unresolved substitutions
         // into `const_eval` which will return `ErrorHandled::ToGeneric` if any of them are
         // encountered.
-        let substs = InternalSubsts::identity_for_item(self, def_id);
-        let instance = ty::Instance::new(def_id, substs);
+        let args = GenericArgs::identity_for_item(self, def_id);
+        let instance = ty::Instance::new(def_id, args);
         let cid = GlobalId { instance, promoted: None };
         let param_env = self.param_env(def_id).with_reveal_all_normalized(self);
         self.const_eval_global_id(param_env, cid, None)
@@ -48,14 +48,14 @@ impl<'tcx> TyCtxt<'tcx> {
         //
         // When trying to evaluate constants containing inference variables,
         // use `Infcx::const_eval_resolve` instead.
-        if ct.substs.has_non_region_infer() {
+        if ct.args.has_non_region_infer() {
             bug!("did not expect inference variables here");
         }
 
         match ty::Instance::resolve(
             self, param_env,
             // FIXME: maybe have a separate version for resolving mir::UnevaluatedConst?
-            ct.def, ct.substs,
+            ct.def, ct.args,
         ) {
             Ok(Some(instance)) => {
                 let cid = GlobalId { instance, promoted: ct.promoted };
@@ -79,11 +79,11 @@ impl<'tcx> TyCtxt<'tcx> {
         //
         // When trying to evaluate constants containing inference variables,
         // use `Infcx::const_eval_resolve` instead.
-        if ct.substs.has_non_region_infer() {
+        if ct.args.has_non_region_infer() {
             bug!("did not expect inference variables here");
         }
 
-        match ty::Instance::resolve(self, param_env, ct.def, ct.substs) {
+        match ty::Instance::resolve(self, param_env, ct.def, ct.args) {
             Ok(Some(instance)) => {
                 let cid = GlobalId { instance, promoted: None };
                 self.const_eval_global_id_for_typeck(param_env, cid, span).inspect(|_| {
@@ -94,7 +94,7 @@ impl<'tcx> TyCtxt<'tcx> {
                     // @lcnr believes that successfully evaluating even though there are
                     // used generic parameters is a bug of evaluation, so checking for it
                     // here does feel somewhat sensible.
-                    if !self.features().generic_const_exprs && ct.substs.has_non_region_param() {
+                    if !self.features().generic_const_exprs && ct.args.has_non_region_param() {
                         let def_kind = self.def_kind(instance.def_id());
                         assert!(
                             matches!(
@@ -221,8 +221,8 @@ impl<'tcx> TyCtxtEnsure<'tcx> {
         // to be used. So we can't use `Instance::mono`, instead we feed unresolved substitutions
         // into `const_eval` which will return `ErrorHandled::ToGeneric` if any of them are
         // encountered.
-        let substs = InternalSubsts::identity_for_item(self.tcx, def_id);
-        let instance = ty::Instance::new(def_id, substs);
+        let args = GenericArgs::identity_for_item(self.tcx, def_id);
+        let instance = ty::Instance::new(def_id, args);
         let cid = GlobalId { instance, promoted: None };
         let param_env =
             self.tcx.param_env(def_id).with_reveal_all_normalized(self.tcx).with_const();
diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs
index 28c50587800..97f53a59fd6 100644
--- a/compiler/rustc_middle/src/mir/mod.rs
+++ b/compiler/rustc_middle/src/mir/mod.rs
@@ -12,7 +12,7 @@ use crate::ty::print::{FmtPrinter, Printer};
 use crate::ty::visit::TypeVisitableExt;
 use crate::ty::{self, List, Ty, TyCtxt};
 use crate::ty::{AdtDef, InstanceDef, ScalarInt, UserTypeAnnotationIndex};
-use crate::ty::{GenericArg, InternalSubsts, SubstsRef};
+use crate::ty::{GenericArg, GenericArgs, GenericArgsRef};
 
 use rustc_data_structures::captures::Captures;
 use rustc_errors::{DiagnosticArgValue, DiagnosticMessage, ErrorGuaranteed, IntoDiagnosticArg};
@@ -1905,15 +1905,15 @@ impl<'tcx> Debug for Operand<'tcx> {
 
 impl<'tcx> Operand<'tcx> {
     /// Convenience helper to make a constant that refers to the fn
-    /// with given `DefId` and substs. Since this is used to synthesize
+    /// with given `DefId` and args. Since this is used to synthesize
     /// MIR, assumes `user_ty` is None.
     pub fn function_handle(
         tcx: TyCtxt<'tcx>,
         def_id: DefId,
-        substs: impl IntoIterator<Item = GenericArg<'tcx>>,
+        args: impl IntoIterator<Item = GenericArg<'tcx>>,
         span: Span,
     ) -> Self {
-        let ty = Ty::new_fn_def(tcx, def_id, substs);
+        let ty = Ty::new_fn_def(tcx, def_id, args);
         Operand::Constant(Box::new(Constant {
             span,
             user_ty: None,
@@ -1981,9 +1981,9 @@ impl<'tcx> Operand<'tcx> {
     ///
     /// While this is unlikely in general, it's the normal case of what you'll
     /// find as the `func` in a [`TerminatorKind::Call`].
-    pub fn const_fn_def(&self) -> Option<(DefId, SubstsRef<'tcx>)> {
+    pub fn const_fn_def(&self) -> Option<(DefId, GenericArgsRef<'tcx>)> {
         let const_ty = self.constant()?.literal.ty();
-        if let ty::FnDef(def_id, substs) = *const_ty.kind() { Some((def_id, substs)) } else { None }
+        if let ty::FnDef(def_id, args) = *const_ty.kind() { Some((def_id, args)) } else { None }
     }
 }
 
@@ -2137,12 +2137,12 @@ impl<'tcx> Debug for Rvalue<'tcx> {
                         }
                     }
 
-                    AggregateKind::Adt(adt_did, variant, substs, _user_ty, _) => {
+                    AggregateKind::Adt(adt_did, variant, args, _user_ty, _) => {
                         ty::tls::with(|tcx| {
                             let variant_def = &tcx.adt_def(adt_did).variant(variant);
-                            let substs = tcx.lift(substs).expect("could not lift for printing");
+                            let args = tcx.lift(args).expect("could not lift for printing");
                             let name = FmtPrinter::new(tcx, Namespace::ValueNS)
-                                .print_def_path(variant_def.def_id, substs)?
+                                .print_def_path(variant_def.def_id, args)?
                                 .into_buffer();
 
                             match variant_def.ctor_kind() {
@@ -2159,10 +2159,10 @@ impl<'tcx> Debug for Rvalue<'tcx> {
                         })
                     }
 
-                    AggregateKind::Closure(def_id, substs) => ty::tls::with(|tcx| {
+                    AggregateKind::Closure(def_id, args) => ty::tls::with(|tcx| {
                         let name = if tcx.sess.opts.unstable_opts.span_free_formats {
-                            let substs = tcx.lift(substs).unwrap();
-                            format!("[closure@{}]", tcx.def_path_str_with_substs(def_id, substs),)
+                            let args = tcx.lift(args).unwrap();
+                            format!("[closure@{}]", tcx.def_path_str_with_args(def_id, args),)
                         } else {
                             let span = tcx.def_span(def_id);
                             format!(
@@ -2493,7 +2493,7 @@ impl<'tcx> ConstantKind<'tcx> {
         };
         debug!("expr.kind: {:?}", expr.kind);
 
-        let ty = tcx.type_of(def).subst_identity();
+        let ty = tcx.type_of(def).instantiate_identity();
         debug!(?ty);
 
         // FIXME(const_generics): We currently have to special case parameters because `min_const_generics`
@@ -2521,23 +2521,22 @@ impl<'tcx> ConstantKind<'tcx> {
         }
 
         let hir_id = tcx.hir().local_def_id_to_hir_id(def);
-        let parent_substs = if let Some(parent_hir_id) = tcx.hir().opt_parent_id(hir_id)
+        let parent_args = 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)
+            GenericArgs::identity_for_item(tcx, parent_did)
         } else {
             List::empty()
         };
-        debug!(?parent_substs);
+        debug!(?parent_args);
 
         let did = def.to_def_id();
-        let child_substs = InternalSubsts::identity_for_item(tcx, did);
-        let substs =
-            tcx.mk_substs_from_iter(parent_substs.into_iter().chain(child_substs.into_iter()));
-        debug!(?substs);
+        let child_args = GenericArgs::identity_for_item(tcx, did);
+        let args = tcx.mk_args_from_iter(parent_args.into_iter().chain(child_args.into_iter()));
+        debug!(?args);
 
         let span = tcx.def_span(def);
-        let uneval = UnevaluatedConst::new(did, substs);
+        let uneval = UnevaluatedConst::new(did, args);
         debug!(?span, ?param_env);
 
         match tcx.const_eval_resolve(param_env, uneval, Some(span)) {
@@ -2552,7 +2551,7 @@ impl<'tcx> ConstantKind<'tcx> {
                 Self::Unevaluated(
                     UnevaluatedConst {
                         def: did,
-                        substs: InternalSubsts::identity_for_item(tcx, did),
+                        args: GenericArgs::identity_for_item(tcx, did),
                         promoted: None,
                     },
                     ty,
@@ -2578,7 +2577,7 @@ impl<'tcx> ConstantKind<'tcx> {
 #[derive(Hash, HashStable, TypeFoldable, TypeVisitable)]
 pub struct UnevaluatedConst<'tcx> {
     pub def: DefId,
-    pub substs: SubstsRef<'tcx>,
+    pub args: GenericArgsRef<'tcx>,
     pub promoted: Option<Promoted>,
 }
 
@@ -2586,14 +2585,14 @@ impl<'tcx> UnevaluatedConst<'tcx> {
     #[inline]
     pub fn shrink(self) -> ty::UnevaluatedConst<'tcx> {
         assert_eq!(self.promoted, None);
-        ty::UnevaluatedConst { def: self.def, substs: self.substs }
+        ty::UnevaluatedConst { def: self.def, args: self.args }
     }
 }
 
 impl<'tcx> UnevaluatedConst<'tcx> {
     #[inline]
-    pub fn new(def: DefId, substs: SubstsRef<'tcx>) -> UnevaluatedConst<'tcx> {
-        UnevaluatedConst { def, substs, promoted: Default::default() }
+    pub fn new(def: DefId, args: GenericArgsRef<'tcx>) -> UnevaluatedConst<'tcx> {
+        UnevaluatedConst { def, args, promoted: Default::default() }
     }
 }
 
@@ -2906,15 +2905,15 @@ fn pretty_print_const_value<'tcx>(
                         ty::Adt(def, _) if def.variants().is_empty() => {
                             fmt.write_str(&format!("{{unreachable(): {}}}", ty))?;
                         }
-                        ty::Adt(def, substs) => {
+                        ty::Adt(def, args) => {
                             let variant_idx = contents
                                 .variant
                                 .expect("destructed mir constant of adt without variant idx");
                             let variant_def = &def.variant(variant_idx);
-                            let substs = tcx.lift(substs).unwrap();
+                            let args = tcx.lift(args).unwrap();
                             let mut cx = FmtPrinter::new(tcx, Namespace::ValueNS);
                             cx.print_alloc_ids = true;
-                            let cx = cx.print_value_path(variant_def.def_id, substs)?;
+                            let cx = cx.print_value_path(variant_def.def_id, args)?;
                             fmt.write_str(&cx.into_buffer())?;
 
                             match variant_def.ctor_kind() {
diff --git a/compiler/rustc_middle/src/mir/mono.rs b/compiler/rustc_middle/src/mir/mono.rs
index ca735d52314..ca3cd943d3d 100644
--- a/compiler/rustc_middle/src/mir/mono.rs
+++ b/compiler/rustc_middle/src/mir/mono.rs
@@ -1,5 +1,5 @@
 use crate::dep_graph::{DepNode, WorkProduct, WorkProductId};
-use crate::ty::{subst::InternalSubsts, Instance, InstanceDef, SymbolName, TyCtxt};
+use crate::ty::{GenericArgs, Instance, InstanceDef, SymbolName, TyCtxt};
 use rustc_attr::InlineAttr;
 use rustc_data_structures::base_n;
 use rustc_data_structures::fingerprint::Fingerprint;
@@ -71,7 +71,7 @@ impl<'tcx> MonoItem<'tcx> {
 
     pub fn is_generic_fn(&self) -> bool {
         match *self {
-            MonoItem::Fn(ref instance) => instance.substs.non_erasable_generics().next().is_some(),
+            MonoItem::Fn(ref instance) => instance.args.non_erasable_generics().next().is_some(),
             MonoItem::Static(..) | MonoItem::GlobalAsm(..) => false,
         }
     }
@@ -168,14 +168,14 @@ impl<'tcx> MonoItem<'tcx> {
     /// which will never be accessed) in its place.
     pub fn is_instantiable(&self, tcx: TyCtxt<'tcx>) -> bool {
         debug!("is_instantiable({:?})", self);
-        let (def_id, substs) = match *self {
-            MonoItem::Fn(ref instance) => (instance.def_id(), instance.substs),
-            MonoItem::Static(def_id) => (def_id, InternalSubsts::empty()),
+        let (def_id, args) = match *self {
+            MonoItem::Fn(ref instance) => (instance.def_id(), instance.args),
+            MonoItem::Static(def_id) => (def_id, GenericArgs::empty()),
             // global asm never has predicates
             MonoItem::GlobalAsm(..) => return true,
         };
 
-        !tcx.subst_and_check_impossible_predicates((def_id, &substs))
+        !tcx.subst_and_check_impossible_predicates((def_id, &args))
     }
 
     pub fn local_span(&self, tcx: TyCtxt<'tcx>) -> Option<Span> {
@@ -216,7 +216,7 @@ impl<'tcx> fmt::Display for MonoItem<'tcx> {
         match *self {
             MonoItem::Fn(instance) => write!(f, "fn {}", instance),
             MonoItem::Static(def_id) => {
-                write!(f, "static {}", Instance::new(def_id, InternalSubsts::empty()))
+                write!(f, "static {}", Instance::new(def_id, GenericArgs::empty()))
             }
             MonoItem::GlobalAsm(..) => write!(f, "global_asm"),
         }
diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs
index ffa7a5400d3..8cbab31451b 100644
--- a/compiler/rustc_middle/src/mir/pretty.rs
+++ b/compiler/rustc_middle/src/mir/pretty.rs
@@ -477,7 +477,7 @@ impl<'tcx> Visitor<'tcx> for ExtraComments<'tcx> {
                 ConstantKind::Ty(ct) => match ct.kind() {
                     ty::ConstKind::Param(p) => format!("Param({})", p),
                     ty::ConstKind::Unevaluated(uv) => {
-                        format!("Unevaluated({}, {:?})", self.tcx.def_path_str(uv.def), uv.substs,)
+                        format!("Unevaluated({}, {:?})", self.tcx.def_path_str(uv.def), uv.args,)
                     }
                     ty::ConstKind::Value(val) => format!("Value({})", fmt_valtree(&val)),
                     ty::ConstKind::Error(_) => "Error".to_string(),
@@ -491,7 +491,7 @@ impl<'tcx> Visitor<'tcx> for ExtraComments<'tcx> {
                     format!(
                         "Unevaluated({}, {:?}, {:?})",
                         self.tcx.def_path_str(uv.def),
-                        uv.substs,
+                        uv.args,
                         uv.promoted,
                     )
                 }
@@ -512,16 +512,16 @@ impl<'tcx> Visitor<'tcx> for ExtraComments<'tcx> {
         self.super_rvalue(rvalue, location);
         if let Rvalue::Aggregate(kind, _) = rvalue {
             match **kind {
-                AggregateKind::Closure(def_id, substs) => {
+                AggregateKind::Closure(def_id, args) => {
                     self.push("closure");
                     self.push(&format!("+ def_id: {:?}", def_id));
-                    self.push(&format!("+ substs: {:#?}", substs));
+                    self.push(&format!("+ args: {:#?}", args));
                 }
 
-                AggregateKind::Generator(def_id, substs, movability) => {
+                AggregateKind::Generator(def_id, args, movability) => {
                     self.push("generator");
                     self.push(&format!("+ def_id: {:?}", def_id));
-                    self.push(&format!("+ substs: {:#?}", substs));
+                    self.push(&format!("+ args: {:#?}", args));
                     self.push(&format!("+ movability: {:?}", movability));
                 }
 
diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs
index 613b132ff2d..e8cb9860ee5 100644
--- a/compiler/rustc_middle/src/mir/query.rs
+++ b/compiler/rustc_middle/src/mir/query.rs
@@ -194,7 +194,7 @@ impl Debug for GeneratorLayout<'_> {
         }
         impl Debug for GenVariantPrinter {
             fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
-                let variant_name = ty::GeneratorSubsts::variant_name(self.0);
+                let variant_name = ty::GeneratorArgs::variant_name(self.0);
                 if fmt.alternate() {
                     write!(fmt, "{:9}({:?})", variant_name, self.0)
                 } else {
@@ -265,10 +265,10 @@ pub struct ConstQualifs {
 /// `UniversalRegions::closure_mapping`.) Note the free regions in the
 /// closure's signature and captures are erased.
 ///
-/// Example: If type check produces a closure with the closure substs:
+/// Example: If type check produces a closure with the closure args:
 ///
 /// ```text
-/// ClosureSubsts = [
+/// ClosureArgs = [
 ///     'a,                                         // From the parent.
 ///     'b,
 ///     i8,                                         // the "closure kind"
@@ -280,7 +280,7 @@ pub struct ConstQualifs {
 /// We would "renumber" each free region to a unique vid, as follows:
 ///
 /// ```text
-/// ClosureSubsts = [
+/// ClosureArgs = [
 ///     '1,                                         // From the parent.
 ///     '2,
 ///     i8,                                         // the "closure kind"
diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs
index 8c8efc36a2f..be27bf75dbd 100644
--- a/compiler/rustc_middle/src/mir/syntax.rs
+++ b/compiler/rustc_middle/src/mir/syntax.rs
@@ -8,7 +8,7 @@ use super::{BasicBlock, Constant, Local, SwitchTargets, UserTypeProjection};
 use crate::mir::coverage::{CodeRegion, CoverageKind};
 use crate::traits::Reveal;
 use crate::ty::adjustment::PointerCoercion;
-use crate::ty::subst::SubstsRef;
+use crate::ty::GenericArgsRef;
 use crate::ty::{self, List, Ty};
 use crate::ty::{Region, UserTypeAnnotationIndex};
 
@@ -1268,10 +1268,10 @@ pub enum AggregateKind<'tcx> {
     /// active field number and is present only for union expressions
     /// -- e.g., for a union expression `SomeUnion { c: .. }`, the
     /// active field index would identity the field `c`
-    Adt(DefId, VariantIdx, SubstsRef<'tcx>, Option<UserTypeAnnotationIndex>, Option<FieldIdx>),
+    Adt(DefId, VariantIdx, GenericArgsRef<'tcx>, Option<UserTypeAnnotationIndex>, Option<FieldIdx>),
 
-    Closure(DefId, SubstsRef<'tcx>),
-    Generator(DefId, SubstsRef<'tcx>, hir::Movability),
+    Closure(DefId, GenericArgsRef<'tcx>),
+    Generator(DefId, GenericArgsRef<'tcx>, hir::Movability),
 }
 
 #[derive(Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)]
diff --git a/compiler/rustc_middle/src/mir/tcx.rs b/compiler/rustc_middle/src/mir/tcx.rs
index 8618a531527..f79697936d2 100644
--- a/compiler/rustc_middle/src/mir/tcx.rs
+++ b/compiler/rustc_middle/src/mir/tcx.rs
@@ -35,7 +35,7 @@ impl<'tcx> PlaceTy<'tcx> {
     #[instrument(level = "debug", skip(tcx), ret)]
     pub fn field_ty(self, tcx: TyCtxt<'tcx>, f: FieldIdx) -> Ty<'tcx> {
         match self.ty.kind() {
-            ty::Adt(adt_def, substs) => {
+            ty::Adt(adt_def, args) => {
                 let variant_def = match self.variant_index {
                     None => adt_def.non_enum_variant(),
                     Some(variant_index) => {
@@ -44,7 +44,7 @@ impl<'tcx> PlaceTy<'tcx> {
                     }
                 };
                 let field_def = &variant_def.fields[f];
-                field_def.ty(tcx, substs)
+                field_def.ty(tcx, args)
             }
             ty::Tuple(tys) => tys[f.index()],
             _ => bug!("extracting field of non-tuple non-adt: {:?}", self),
@@ -198,10 +198,10 @@ impl<'tcx> Rvalue<'tcx> {
                 AggregateKind::Tuple => {
                     Ty::new_tup_from_iter(tcx, ops.iter().map(|op| op.ty(local_decls, tcx)))
                 }
-                AggregateKind::Adt(did, _, substs, _, _) => tcx.type_of(did).subst(tcx, substs),
-                AggregateKind::Closure(did, substs) => Ty::new_closure(tcx, did, substs),
-                AggregateKind::Generator(did, substs, movability) => {
-                    Ty::new_generator(tcx, did, substs, movability)
+                AggregateKind::Adt(did, _, args, _, _) => tcx.type_of(did).instantiate(tcx, args),
+                AggregateKind::Closure(did, args) => Ty::new_closure(tcx, did, args),
+                AggregateKind::Generator(did, args, movability) => {
+                    Ty::new_generator(tcx, did, args, movability)
                 }
             },
             Rvalue::ShallowInitBox(_, ty) => Ty::new_box(tcx, ty),
diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs
index 205dc9ec746..64bc4fa7926 100644
--- a/compiler/rustc_middle/src/mir/visit.rs
+++ b/compiler/rustc_middle/src/mir/visit.rs
@@ -63,7 +63,7 @@
 //! `is_cleanup` above.
 
 use crate::mir::*;
-use crate::ty::subst::SubstsRef;
+use crate::ty::GenericArgsRef;
 use crate::ty::{self, CanonicalUserTypeAnnotation, Ty};
 use rustc_span::Span;
 
@@ -245,12 +245,12 @@ macro_rules! make_mir_visitor {
                 self.super_region(region);
             }
 
-            fn visit_substs(
+            fn visit_args(
                 &mut self,
-                substs: & $($mutability)? SubstsRef<'tcx>,
+                args: & $($mutability)? GenericArgsRef<'tcx>,
                 _: Location,
             ) {
-                self.super_substs(substs);
+                self.super_args(args);
             }
 
             fn visit_local_decl(
@@ -335,7 +335,7 @@ macro_rules! make_mir_visitor {
 
                     self.visit_span($(& $mutability)? *callsite_span);
 
-                    let ty::Instance { def: callee_def, substs: callee_substs } = callee;
+                    let ty::Instance { def: callee_def, args: callee_args } = callee;
                     match callee_def {
                         ty::InstanceDef::Item(_def_id) => {}
 
@@ -355,7 +355,7 @@ macro_rules! make_mir_visitor {
                             self.visit_ty($(& $mutability)? *ty, TyContext::Location(location));
                         }
                     }
-                    self.visit_substs(callee_substs, location);
+                    self.visit_args(callee_args, location);
                 }
                 if let Some(inlined_parent_scope) = inlined_parent_scope {
                     self.visit_source_scope($(& $mutability)? *inlined_parent_scope);
@@ -721,24 +721,24 @@ macro_rules! make_mir_visitor {
                             AggregateKind::Adt(
                                 _adt_def,
                                 _variant_index,
-                                substs,
-                                _user_substs,
+                                args,
+                                _user_args,
                                 _active_field_index
                             ) => {
-                                self.visit_substs(substs, location);
+                                self.visit_args(args, location);
                             }
                             AggregateKind::Closure(
                                 _,
-                                closure_substs
+                                closure_args
                             ) => {
-                                self.visit_substs(closure_substs, location);
+                                self.visit_args(closure_args, location);
                             }
                             AggregateKind::Generator(
                                 _,
-                                generator_substs,
+                                generator_args,
                                 _movability,
                             ) => {
-                                self.visit_substs(generator_substs, location);
+                                self.visit_args(generator_args, location);
                             }
                         }
 
@@ -933,7 +933,7 @@ macro_rules! make_mir_visitor {
             fn super_region(&mut self, _region: $(& $mutability)? ty::Region<'tcx>) {
             }
 
-            fn super_substs(&mut self, _substs: & $($mutability)? SubstsRef<'tcx>) {
+            fn super_args(&mut self, _args: & $($mutability)? GenericArgsRef<'tcx>) {
             }
 
             // Convenience methods
diff --git a/compiler/rustc_middle/src/query/keys.rs b/compiler/rustc_middle/src/query/keys.rs
index 28e699cd269..a8aec3096d5 100644
--- a/compiler/rustc_middle/src/query/keys.rs
+++ b/compiler/rustc_middle/src/query/keys.rs
@@ -6,8 +6,8 @@ use crate::mir::interpret::ConstValue;
 use crate::traits;
 use crate::ty::fast_reject::SimplifiedType;
 use crate::ty::layout::{TyAndLayout, ValidityRequirement};
-use crate::ty::subst::{GenericArg, SubstsRef};
 use crate::ty::{self, Ty, TyCtxt};
+use crate::ty::{GenericArg, GenericArgsRef};
 use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
 use rustc_hir::hir_id::{HirId, OwnerId};
 use rustc_query_system::query::{DefaultCacheSelector, SingleCacheSelector, VecCacheSelector};
@@ -286,7 +286,7 @@ impl Key for (DefId, SimplifiedType) {
     }
 }
 
-impl<'tcx> Key for SubstsRef<'tcx> {
+impl<'tcx> Key for GenericArgsRef<'tcx> {
     type CacheSelector = DefaultCacheSelector<Self>;
 
     fn default_span(&self, _: TyCtxt<'_>) -> Span {
@@ -294,7 +294,7 @@ impl<'tcx> Key for SubstsRef<'tcx> {
     }
 }
 
-impl<'tcx> Key for (DefId, SubstsRef<'tcx>) {
+impl<'tcx> Key for (DefId, GenericArgsRef<'tcx>) {
     type CacheSelector = DefaultCacheSelector<Self>;
 
     fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
@@ -310,7 +310,7 @@ impl<'tcx> Key for (ty::UnevaluatedConst<'tcx>, ty::UnevaluatedConst<'tcx>) {
     }
 }
 
-impl<'tcx> Key for (LocalDefId, DefId, SubstsRef<'tcx>) {
+impl<'tcx> Key for (LocalDefId, DefId, GenericArgsRef<'tcx>) {
     type CacheSelector = DefaultCacheSelector<Self>;
 
     fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
@@ -487,7 +487,7 @@ impl Key for (Symbol, u32, u32) {
     }
 }
 
-impl<'tcx> Key for (DefId, Ty<'tcx>, SubstsRef<'tcx>, ty::ParamEnv<'tcx>) {
+impl<'tcx> Key for (DefId, Ty<'tcx>, GenericArgsRef<'tcx>, ty::ParamEnv<'tcx>) {
     type CacheSelector = DefaultCacheSelector<Self>;
 
     fn default_span(&self, _tcx: TyCtxt<'_>) -> Span {
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index a059590e6ad..45fa82ba68a 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -44,7 +44,6 @@ use crate::traits::{
 };
 use crate::ty::fast_reject::SimplifiedType;
 use crate::ty::layout::ValidityRequirement;
-use crate::ty::subst::{GenericArg, SubstsRef};
 use crate::ty::util::AlwaysRequiresDrop;
 use crate::ty::GeneratorDiagnosticData;
 use crate::ty::TyCtxtFeed;
@@ -52,6 +51,7 @@ use crate::ty::{
     self, print::describe_as_module, CrateInherentImpls, ParamEnvAnd, Ty, TyCtxt,
     UnusedGenericParams,
 };
+use crate::ty::{GenericArg, GenericArgsRef};
 use rustc_arena::TypedArena;
 use rustc_ast as ast;
 use rustc_ast::expand::{allocator::AllocatorKind, StrippedCfgItem};
@@ -1032,7 +1032,7 @@ rustc_queries! {
     }
 
     /// Obtain all the calls into other local functions
-    query mir_inliner_callees(key: ty::InstanceDef<'tcx>) -> &'tcx [(DefId, SubstsRef<'tcx>)] {
+    query mir_inliner_callees(key: ty::InstanceDef<'tcx>) -> &'tcx [(DefId, GenericArgsRef<'tcx>)] {
         fatal_cycle
         desc { |tcx|
             "computing all local function calls in `{}`",
@@ -1537,7 +1537,7 @@ rustc_queries! {
     /// added or removed in any upstream crate. Instead use the narrower
     /// `upstream_monomorphizations_for`, `upstream_drop_glue_for`, or, even
     /// better, `Instance::upstream_monomorphization()`.
-    query upstream_monomorphizations(_: ()) -> &'tcx DefIdMap<FxHashMap<SubstsRef<'tcx>, CrateNum>> {
+    query upstream_monomorphizations(_: ()) -> &'tcx DefIdMap<FxHashMap<GenericArgsRef<'tcx>, CrateNum>> {
         arena_cache
         desc { "collecting available upstream monomorphizations" }
     }
@@ -1550,7 +1550,7 @@ rustc_queries! {
     /// You likely want to call `Instance::upstream_monomorphization()`
     /// instead of invoking this query directly.
     query upstream_monomorphizations_for(def_id: DefId)
-        -> Option<&'tcx FxHashMap<SubstsRef<'tcx>, CrateNum>>
+        -> Option<&'tcx FxHashMap<GenericArgsRef<'tcx>, CrateNum>>
     {
         desc { |tcx|
             "collecting available upstream monomorphizations for `{}`",
@@ -1560,7 +1560,7 @@ rustc_queries! {
     }
 
     /// Returns the upstream crate that exports drop-glue for the given
-    /// type (`substs` is expected to be a single-item list containing the
+    /// type (`args` is expected to be a single-item list containing the
     /// type one wants drop-glue for).
     ///
     /// This is a subset of `upstream_monomorphizations_for` in order to
@@ -1574,8 +1574,8 @@ rustc_queries! {
     /// NOTE: This query could easily be extended to also support other
     ///       common functions that have are large set of monomorphizations
     ///       (like `Clone::clone` for example).
-    query upstream_drop_glue_for(substs: SubstsRef<'tcx>) -> Option<CrateNum> {
-        desc { "available upstream drop-glue for `{:?}`", substs }
+    query upstream_drop_glue_for(args: GenericArgsRef<'tcx>) -> Option<CrateNum> {
+        desc { "available upstream drop-glue for `{:?}`", args }
     }
 
     /// Returns a list of all `extern` blocks of a crate.
@@ -2053,7 +2053,7 @@ rustc_queries! {
         desc { "normalizing `{:?}`", goal.value.value.value }
     }
 
-    query subst_and_check_impossible_predicates(key: (DefId, SubstsRef<'tcx>)) -> bool {
+    query subst_and_check_impossible_predicates(key: (DefId, GenericArgsRef<'tcx>)) -> bool {
         desc { |tcx|
             "checking impossible substituted predicates: `{}`",
             tcx.def_path_str(key.0)
@@ -2104,16 +2104,16 @@ rustc_queries! {
     }
 
     /// Attempt to resolve the given `DefId` to an `Instance`, for the
-    /// given generics args (`SubstsRef`), returning one of:
+    /// given generics args (`GenericArgsRef`), returning one of:
     ///  * `Ok(Some(instance))` on success
-    ///  * `Ok(None)` when the `SubstsRef` are still too generic,
+    ///  * `Ok(None)` when the `GenericArgsRef` are still too generic,
     ///    and therefore don't allow finding the final `Instance`
     ///  * `Err(ErrorGuaranteed)` when the `Instance` resolution process
     ///    couldn't complete due to errors elsewhere - this is distinct
     ///    from `Ok(None)` to avoid misleading diagnostics when an error
     ///    has already been/will be emitted, for the original cause
     query resolve_instance(
-        key: ty::ParamEnvAnd<'tcx, (DefId, SubstsRef<'tcx>)>
+        key: ty::ParamEnvAnd<'tcx, (DefId, GenericArgsRef<'tcx>)>
     ) -> Result<Option<ty::Instance<'tcx>>, ErrorGuaranteed> {
         desc { "resolving instance `{}`", ty::Instance::new(key.value.0, key.value.1) }
     }
diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs
index e9af5070e5e..e070b054720 100644
--- a/compiler/rustc_middle/src/thir.rs
+++ b/compiler/rustc_middle/src/thir.rs
@@ -19,8 +19,8 @@ use rustc_middle::middle::region;
 use rustc_middle::mir::interpret::AllocId;
 use rustc_middle::mir::{self, BinOp, BorrowKind, FakeReadCause, Mutability, UnOp};
 use rustc_middle::ty::adjustment::PointerCoercion;
-use rustc_middle::ty::subst::SubstsRef;
-use rustc_middle::ty::{self, AdtDef, FnSig, List, Ty, UpvarSubsts};
+use rustc_middle::ty::GenericArgsRef;
+use rustc_middle::ty::{self, AdtDef, FnSig, List, Ty, UpvarArgs};
 use rustc_middle::ty::{CanonicalUserType, CanonicalUserTypeAnnotation};
 use rustc_span::def_id::LocalDefId;
 use rustc_span::{sym, Span, Symbol, DUMMY_SP};
@@ -150,9 +150,9 @@ pub struct AdtExpr<'tcx> {
     pub adt_def: AdtDef<'tcx>,
     /// The variant of the ADT.
     pub variant_index: VariantIdx,
-    pub substs: SubstsRef<'tcx>,
+    pub args: GenericArgsRef<'tcx>,
 
-    /// Optional user-given substs: for something like `let x =
+    /// Optional user-given args: for something like `let x =
     /// Bar::<T> { ... }`.
     pub user_ty: UserTy<'tcx>,
 
@@ -164,7 +164,7 @@ pub struct AdtExpr<'tcx> {
 #[derive(Clone, Debug, HashStable)]
 pub struct ClosureExpr<'tcx> {
     pub closure_id: LocalDefId,
-    pub substs: UpvarSubsts<'tcx>,
+    pub args: UpvarArgs<'tcx>,
     pub upvars: Box<[ExprId]>,
     pub movability: Option<hir::Movability>,
     pub fake_reads: Vec<(ExprId, FakeReadCause, hir::HirId)>,
@@ -418,7 +418,7 @@ pub enum ExprKind<'tcx> {
     /// An inline `const` block, e.g. `const {}`.
     ConstBlock {
         did: DefId,
-        substs: SubstsRef<'tcx>,
+        args: GenericArgsRef<'tcx>,
     },
     /// An array literal constructed from one repeated element, e.g. `[1; 5]`.
     Repeat {
@@ -466,7 +466,7 @@ pub enum ExprKind<'tcx> {
     /// Associated constants and named constants
     NamedConst {
         def_id: DefId,
-        substs: SubstsRef<'tcx>,
+        args: GenericArgsRef<'tcx>,
         user_ty: UserTy<'tcx>,
     },
     ConstParam {
@@ -714,7 +714,7 @@ pub enum PatKind<'tcx> {
     /// multiple variants.
     Variant {
         adt_def: AdtDef<'tcx>,
-        substs: SubstsRef<'tcx>,
+        args: GenericArgsRef<'tcx>,
         variant_index: VariantIdx,
         subpatterns: Vec<FieldPat<'tcx>>,
     },
diff --git a/compiler/rustc_middle/src/thir/visit.rs b/compiler/rustc_middle/src/thir/visit.rs
index 14bc1ac0ce7..55ec17423ec 100644
--- a/compiler/rustc_middle/src/thir/visit.rs
+++ b/compiler/rustc_middle/src/thir/visit.rs
@@ -101,7 +101,7 @@ pub fn walk_expr<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, expr: &Exp
             }
         }
         Become { value } => visitor.visit_expr(&visitor.thir()[value]),
-        ConstBlock { did: _, substs: _ } => {}
+        ConstBlock { did: _, args: _ } => {}
         Repeat { value, count: _ } => {
             visitor.visit_expr(&visitor.thir()[value]);
         }
@@ -115,7 +115,7 @@ pub fn walk_expr<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, expr: &Exp
             ref base,
             adt_def: _,
             variant_index: _,
-            substs: _,
+            args: _,
             user_ty: _,
         }) => {
             for field in &**fields {
@@ -130,7 +130,7 @@ pub fn walk_expr<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, expr: &Exp
         }
         Closure(box ClosureExpr {
             closure_id: _,
-            substs: _,
+            args: _,
             upvars: _,
             movability: _,
             fake_reads: _,
@@ -138,7 +138,7 @@ pub fn walk_expr<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, expr: &Exp
         Literal { lit: _, neg: _ } => {}
         NonHirLiteral { lit: _, user_ty: _ } => {}
         ZstLiteral { user_ty: _ } => {}
-        NamedConst { def_id: _, substs: _, user_ty: _ } => {}
+        NamedConst { def_id: _, args: _, user_ty: _ } => {}
         ConstParam { param: _, def_id: _ } => {}
         StaticRef { alloc_id: _, ty: _, def_id: _ } => {}
         InlineAsm(box InlineAsmExpr { ref operands, template: _, options: _, line_spans: _ }) => {
@@ -227,7 +227,7 @@ pub fn walk_pat<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, pat: &Pat<'
             name: _,
         } => visitor.visit_pat(&subpattern),
         Binding { .. } | Wild => {}
-        Variant { subpatterns, adt_def: _, substs: _, variant_index: _ } | Leaf { subpatterns } => {
+        Variant { subpatterns, adt_def: _, args: _, variant_index: _ } | Leaf { subpatterns } => {
             for subpattern in subpatterns {
                 visitor.visit_pat(&subpattern.pattern);
             }
diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs
index c7d2e4c22d2..b7ffed57a0b 100644
--- a/compiler/rustc_middle/src/traits/mod.rs
+++ b/compiler/rustc_middle/src/traits/mod.rs
@@ -12,7 +12,7 @@ pub mod util;
 use crate::infer::canonical::Canonical;
 use crate::mir::ConstraintCategory;
 use crate::ty::abstract_const::NotConstEvaluatable;
-use crate::ty::subst::SubstsRef;
+use crate::ty::GenericArgsRef;
 use crate::ty::{self, AdtKind, Ty, TyCtxt};
 
 use rustc_data_structures::sync::Lrc;
@@ -199,7 +199,7 @@ impl<'tcx> ObligationCause<'tcx> {
 pub struct UnifyReceiverContext<'tcx> {
     pub assoc_item: ty::AssocItem,
     pub param_env: ty::ParamEnv<'tcx>,
-    pub substs: SubstsRef<'tcx>,
+    pub args: GenericArgsRef<'tcx>,
 }
 
 #[derive(Clone, PartialEq, Eq, Lift, Default, HashStable)]
@@ -696,7 +696,7 @@ impl<'tcx, N> ImplSource<'tcx, N> {
         match self {
             ImplSource::UserDefined(i) => ImplSource::UserDefined(ImplSourceUserDefinedData {
                 impl_def_id: i.impl_def_id,
-                substs: i.substs,
+                args: i.args,
                 nested: i.nested.into_iter().map(f).collect(),
             }),
             ImplSource::Param(n, ct) => ImplSource::Param(n.into_iter().map(f).collect(), ct),
@@ -729,7 +729,7 @@ impl<'tcx, N> ImplSource<'tcx, N> {
 #[derive(TypeFoldable, TypeVisitable)]
 pub struct ImplSourceUserDefinedData<'tcx, N> {
     pub impl_def_id: DefId,
-    pub substs: SubstsRef<'tcx>,
+    pub args: GenericArgsRef<'tcx>,
     pub nested: Vec<N>,
 }
 
diff --git a/compiler/rustc_middle/src/traits/query.rs b/compiler/rustc_middle/src/traits/query.rs
index 60a38747fdf..950a59e9695 100644
--- a/compiler/rustc_middle/src/traits/query.rs
+++ b/compiler/rustc_middle/src/traits/query.rs
@@ -8,7 +8,7 @@
 use crate::error::DropCheckOverflow;
 use crate::infer::canonical::{Canonical, QueryResponse};
 use crate::ty::error::TypeError;
-use crate::ty::subst::GenericArg;
+use crate::ty::GenericArg;
 use crate::ty::{self, Ty, TyCtxt};
 use rustc_span::source_map::Span;
 
@@ -132,7 +132,7 @@ impl<'tcx> DropckOutlivesResult<'tcx> {
 pub struct DropckConstraint<'tcx> {
     /// Types that are required to be alive in order for this
     /// type to be valid for destruction.
-    pub outlives: Vec<ty::subst::GenericArg<'tcx>>,
+    pub outlives: Vec<ty::GenericArg<'tcx>>,
 
     /// Types that could not be resolved: projections and params.
     pub dtorck_types: Vec<Ty<'tcx>>,
diff --git a/compiler/rustc_middle/src/traits/solve/inspect.rs b/compiler/rustc_middle/src/traits/solve/inspect.rs
index 527afa005b9..8698cf86022 100644
--- a/compiler/rustc_middle/src/traits/solve/inspect.rs
+++ b/compiler/rustc_middle/src/traits/solve/inspect.rs
@@ -32,7 +32,7 @@ pub enum GoalEvaluationKind<'tcx> {
 }
 impl Debug for GoalEvaluation<'_> {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-        ProofTreeFormatter { f, on_newline: true }.format_goal_evaluation(self)
+        ProofTreeFormatter::new(f).format_goal_evaluation(self)
     }
 }
 
@@ -43,7 +43,7 @@ pub struct AddedGoalsEvaluation<'tcx> {
 }
 impl Debug for AddedGoalsEvaluation<'_> {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-        ProofTreeFormatter { f, on_newline: true }.format_nested_goal_evaluation(self)
+        ProofTreeFormatter::new(f).format_nested_goal_evaluation(self)
     }
 }
 
@@ -58,7 +58,7 @@ pub struct GoalEvaluationStep<'tcx> {
 }
 impl Debug for GoalEvaluationStep<'_> {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-        ProofTreeFormatter { f, on_newline: true }.format_evaluation_step(self)
+        ProofTreeFormatter::new(f).format_evaluation_step(self)
     }
 }
 
@@ -78,6 +78,6 @@ pub enum CandidateKind<'tcx> {
 }
 impl Debug for GoalCandidate<'_> {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-        ProofTreeFormatter { f, on_newline: true }.format_candidate(self)
+        ProofTreeFormatter::new(f).format_candidate(self)
     }
 }
diff --git a/compiler/rustc_middle/src/traits/solve/inspect/format.rs b/compiler/rustc_middle/src/traits/solve/inspect/format.rs
index 2ee625674fa..f19f1189e44 100644
--- a/compiler/rustc_middle/src/traits/solve/inspect/format.rs
+++ b/compiler/rustc_middle/src/traits/solve/inspect/format.rs
@@ -1,11 +1,19 @@
 use super::*;
 
 pub(super) struct ProofTreeFormatter<'a, 'b> {
-    pub(super) f: &'a mut (dyn Write + 'b),
-    pub(super) on_newline: bool,
+    f: &'a mut (dyn Write + 'b),
 }
 
-impl Write for ProofTreeFormatter<'_, '_> {
+/// A formatter which adds 4 spaces of indentation to its input before
+/// passing it on to its nested formatter.
+///
+/// We can use this for arbitrary levels of indentation by nesting it.
+struct Indentor<'a, 'b> {
+    f: &'a mut (dyn Write + 'b),
+    on_newline: bool,
+}
+
+impl Write for Indentor<'_, '_> {
     fn write_str(&mut self, s: &str) -> std::fmt::Result {
         for line in s.split_inclusive("\n") {
             if self.on_newline {
@@ -19,49 +27,52 @@ impl Write for ProofTreeFormatter<'_, '_> {
     }
 }
 
-impl ProofTreeFormatter<'_, '_> {
-    fn nested(&mut self) -> ProofTreeFormatter<'_, '_> {
-        ProofTreeFormatter { f: self, on_newline: true }
+impl<'a, 'b> ProofTreeFormatter<'a, 'b> {
+    pub(super) fn new(f: &'a mut (dyn Write + 'b)) -> Self {
+        ProofTreeFormatter { f }
     }
 
-    pub(super) fn format_goal_evaluation(&mut self, goal: &GoalEvaluation<'_>) -> std::fmt::Result {
-        let f = &mut *self.f;
+    fn nested<F, R>(&mut self, func: F) -> R
+    where
+        F: FnOnce(&mut ProofTreeFormatter<'_, '_>) -> R,
+    {
+        func(&mut ProofTreeFormatter { f: &mut Indentor { f: self.f, on_newline: true } })
+    }
 
+    pub(super) fn format_goal_evaluation(&mut self, goal: &GoalEvaluation<'_>) -> std::fmt::Result {
         let goal_text = match goal.is_normalizes_to_hack {
             IsNormalizesToHack::Yes => "NORMALIZES-TO HACK GOAL",
             IsNormalizesToHack::No => "GOAL",
         };
 
-        writeln!(f, "{}: {:?}", goal_text, goal.uncanonicalized_goal,)?;
-        writeln!(f, "CANONICALIZED: {:?}", goal.canonicalized_goal)?;
+        writeln!(self.f, "{}: {:?}", goal_text, goal.uncanonicalized_goal)?;
+        writeln!(self.f, "CANONICALIZED: {:?}", goal.canonicalized_goal)?;
 
         match &goal.kind {
             GoalEvaluationKind::CacheHit(CacheHit::Global) => {
-                writeln!(f, "GLOBAL CACHE HIT: {:?}", goal.result)
+                writeln!(self.f, "GLOBAL CACHE HIT: {:?}", goal.result)
             }
             GoalEvaluationKind::CacheHit(CacheHit::Provisional) => {
-                writeln!(f, "PROVISIONAL CACHE HIT: {:?}", goal.result)
+                writeln!(self.f, "PROVISIONAL CACHE HIT: {:?}", goal.result)
             }
             GoalEvaluationKind::Uncached { revisions } => {
                 for (n, step) in revisions.iter().enumerate() {
-                    let f = &mut *self.f;
-                    writeln!(f, "REVISION {n}: {:?}", step.result)?;
-                    let mut f = self.nested();
-                    f.format_evaluation_step(step)?;
+                    writeln!(self.f, "REVISION {n}: {:?}", step.result)?;
+                    self.nested(|this| this.format_evaluation_step(step))?;
                 }
-
-                let f = &mut *self.f;
-                writeln!(f, "RESULT: {:?}", goal.result)
+                writeln!(self.f, "RESULT: {:?}", goal.result)
             }
         }?;
 
         if goal.returned_goals.len() > 0 {
-            let f = &mut *self.f;
-            writeln!(f, "NESTED GOALS ADDED TO CALLER: [")?;
-            let mut f = self.nested();
-            for goal in goal.returned_goals.iter() {
-                writeln!(f, "ADDED GOAL: {:?},", goal)?;
-            }
+            writeln!(self.f, "NESTED GOALS ADDED TO CALLER: [")?;
+            self.nested(|this| {
+                for goal in goal.returned_goals.iter() {
+                    writeln!(this.f, "ADDED GOAL: {:?},", goal)?;
+                }
+                Ok(())
+            })?;
+
             writeln!(self.f, "]")?;
         }
 
@@ -72,58 +83,53 @@ impl ProofTreeFormatter<'_, '_> {
         &mut self,
         evaluation_step: &GoalEvaluationStep<'_>,
     ) -> std::fmt::Result {
-        let f = &mut *self.f;
-        writeln!(f, "INSTANTIATED: {:?}", evaluation_step.instantiated_goal)?;
+        writeln!(self.f, "INSTANTIATED: {:?}", evaluation_step.instantiated_goal)?;
 
         for candidate in &evaluation_step.candidates {
-            let mut f = self.nested();
-            f.format_candidate(candidate)?;
+            self.nested(|this| this.format_candidate(candidate))?;
         }
-        for nested_goal_evaluation in &evaluation_step.nested_goal_evaluations {
-            let mut f = self.nested();
-            f.format_nested_goal_evaluation(nested_goal_evaluation)?;
+        for nested in &evaluation_step.nested_goal_evaluations {
+            self.nested(|this| this.format_nested_goal_evaluation(nested))?;
         }
 
         Ok(())
     }
 
     pub(super) fn format_candidate(&mut self, candidate: &GoalCandidate<'_>) -> std::fmt::Result {
-        let f = &mut *self.f;
-
         match &candidate.kind {
             CandidateKind::NormalizedSelfTyAssembly => {
-                writeln!(f, "NORMALIZING SELF TY FOR ASSEMBLY:")
+                writeln!(self.f, "NORMALIZING SELF TY FOR ASSEMBLY:")
             }
             CandidateKind::Candidate { name, result } => {
-                writeln!(f, "CANDIDATE {}: {:?}", name, result)
+                writeln!(self.f, "CANDIDATE {}: {:?}", name, result)
             }
         }?;
 
-        let mut f = self.nested();
-        for candidate in &candidate.candidates {
-            f.format_candidate(candidate)?;
-        }
-        for nested_evaluations in &candidate.nested_goal_evaluations {
-            f.format_nested_goal_evaluation(nested_evaluations)?;
-        }
-
-        Ok(())
+        self.nested(|this| {
+            for candidate in &candidate.candidates {
+                this.format_candidate(candidate)?;
+            }
+            for nested in &candidate.nested_goal_evaluations {
+                this.format_nested_goal_evaluation(nested)?;
+            }
+            Ok(())
+        })
     }
 
     pub(super) fn format_nested_goal_evaluation(
         &mut self,
         nested_goal_evaluation: &AddedGoalsEvaluation<'_>,
     ) -> std::fmt::Result {
-        let f = &mut *self.f;
-        writeln!(f, "TRY_EVALUATE_ADDED_GOALS: {:?}", nested_goal_evaluation.result)?;
+        writeln!(self.f, "TRY_EVALUATE_ADDED_GOALS: {:?}", nested_goal_evaluation.result)?;
 
         for (n, revision) in nested_goal_evaluation.evaluations.iter().enumerate() {
-            let f = &mut *self.f;
-            writeln!(f, "REVISION {n}")?;
-            let mut f = self.nested();
-            for goal_evaluation in revision {
-                f.format_goal_evaluation(goal_evaluation)?;
-            }
+            writeln!(self.f, "REVISION {n}")?;
+            self.nested(|this| {
+                for goal_evaluation in revision {
+                    this.format_goal_evaluation(goal_evaluation)?;
+                }
+                Ok(())
+            })?;
         }
 
         Ok(())
diff --git a/compiler/rustc_middle/src/traits/specialization_graph.rs b/compiler/rustc_middle/src/traits/specialization_graph.rs
index dc2cd203560..18a57b6181a 100644
--- a/compiler/rustc_middle/src/traits/specialization_graph.rs
+++ b/compiler/rustc_middle/src/traits/specialization_graph.rs
@@ -259,7 +259,9 @@ pub fn ancestors(
 
     if let Some(reported) = specialization_graph.has_errored {
         Err(reported)
-    } else if let Err(reported) = tcx.type_of(start_from_impl).subst_identity().error_reported() {
+    } else if let Err(reported) =
+        tcx.type_of(start_from_impl).instantiate_identity().error_reported()
+    {
         Err(reported)
     } else {
         Ok(Ancestors {
diff --git a/compiler/rustc_middle/src/traits/structural_impls.rs b/compiler/rustc_middle/src/traits/structural_impls.rs
index a703e3c9562..e2cd118500b 100644
--- a/compiler/rustc_middle/src/traits/structural_impls.rs
+++ b/compiler/rustc_middle/src/traits/structural_impls.rs
@@ -26,8 +26,8 @@ impl<'tcx, N: fmt::Debug> fmt::Debug for traits::ImplSourceUserDefinedData<'tcx,
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         write!(
             f,
-            "ImplSourceUserDefinedData(impl_def_id={:?}, substs={:?}, nested={:?})",
-            self.impl_def_id, self.substs, self.nested
+            "ImplSourceUserDefinedData(impl_def_id={:?}, args={:?}, nested={:?})",
+            self.impl_def_id, self.args, self.nested
         )
     }
 }
diff --git a/compiler/rustc_middle/src/ty/abstract_const.rs b/compiler/rustc_middle/src/ty/abstract_const.rs
index ffee7ba28c3..0364a620810 100644
--- a/compiler/rustc_middle/src/ty/abstract_const.rs
+++ b/compiler/rustc_middle/src/ty/abstract_const.rs
@@ -55,8 +55,8 @@ impl<'tcx> TyCtxt<'tcx> {
                     ty::ConstKind::Unevaluated(uv) => match self.tcx.thir_abstract_const(uv.def) {
                         Err(e) => ty::Const::new_error(self.tcx, e, c.ty()),
                         Ok(Some(bac)) => {
-                            let substs = self.tcx.erase_regions(uv.substs);
-                            let bac = bac.subst(self.tcx, substs);
+                            let args = self.tcx.erase_regions(uv.args);
+                            let bac = bac.instantiate(self.tcx, args);
                             return bac.fold_with(self);
                         }
                         Ok(None) => c,
diff --git a/compiler/rustc_middle/src/ty/assoc.rs b/compiler/rustc_middle/src/ty/assoc.rs
index cce609c261e..f77a8c6712e 100644
--- a/compiler/rustc_middle/src/ty/assoc.rs
+++ b/compiler/rustc_middle/src/ty/assoc.rs
@@ -84,14 +84,22 @@ impl AssocItem {
                 // late-bound regions, and we don't want method signatures to show up
                 // `as for<'r> fn(&'r MyType)`. Pretty-printing handles late-bound
                 // regions just fine, showing `fn(&MyType)`.
-                tcx.fn_sig(self.def_id).subst_identity().skip_binder().to_string()
+                tcx.fn_sig(self.def_id).instantiate_identity().skip_binder().to_string()
             }
             ty::AssocKind::Type => format!("type {};", self.name),
             ty::AssocKind::Const => {
-                format!("const {}: {:?};", self.name, tcx.type_of(self.def_id).subst_identity())
+                format!(
+                    "const {}: {:?};",
+                    self.name,
+                    tcx.type_of(self.def_id).instantiate_identity()
+                )
             }
         }
     }
+
+    pub fn is_impl_trait_in_trait(&self) -> bool {
+        self.opt_rpitit_info.is_some()
+    }
 }
 
 #[derive(Copy, Clone, PartialEq, Debug, HashStable, Eq, Hash, Encodable, Decodable)]
diff --git a/compiler/rustc_middle/src/ty/closure.rs b/compiler/rustc_middle/src/ty/closure.rs
index bc927374549..91eefa2c125 100644
--- a/compiler/rustc_middle/src/ty/closure.rs
+++ b/compiler/rustc_middle/src/ty/closure.rs
@@ -6,9 +6,10 @@ use crate::{mir, ty};
 use std::fmt::Write;
 
 use crate::query::Providers;
-use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
+use rustc_data_structures::fx::FxIndexMap;
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::{self as hir, LangItem};
+use rustc_span::def_id::LocalDefIdMap;
 use rustc_span::symbol::Ident;
 use rustc_span::{Span, Symbol};
 
@@ -56,12 +57,9 @@ pub enum UpvarCapture {
     ByRef(BorrowKind),
 }
 
-pub type UpvarListMap = FxHashMap<DefId, FxIndexMap<hir::HirId, UpvarId>>;
-pub type UpvarCaptureMap = FxHashMap<UpvarId, UpvarCapture>;
-
 /// Given the closure DefId this map provides a map of root variables to minimum
 /// set of `CapturedPlace`s that need to be tracked to support all captures of that closure.
-pub type MinCaptureInformationMap<'tcx> = FxHashMap<LocalDefId, RootVariableMinCaptureList<'tcx>>;
+pub type MinCaptureInformationMap<'tcx> = LocalDefIdMap<RootVariableMinCaptureList<'tcx>>;
 
 /// Part of `MinCaptureInformationMap`; Maps a root variable to the list of `CapturedPlace`.
 /// Used to track the minimum set of `Place`s that need to be captured to support all
diff --git a/compiler/rustc_middle/src/ty/codec.rs b/compiler/rustc_middle/src/ty/codec.rs
index 6adbb44a153..b4f4f9bef8e 100644
--- a/compiler/rustc_middle/src/ty/codec.rs
+++ b/compiler/rustc_middle/src/ty/codec.rs
@@ -13,7 +13,7 @@ use crate::mir::{
     interpret::{AllocId, ConstAllocation},
 };
 use crate::traits;
-use crate::ty::subst::SubstsRef;
+use crate::ty::GenericArgsRef;
 use crate::ty::{self, AdtDef, Ty};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_middle::ty::TyCtxt;
@@ -254,12 +254,12 @@ impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for ty::Clause<'tcx> {
     }
 }
 
-impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for SubstsRef<'tcx> {
+impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for GenericArgsRef<'tcx> {
     fn decode(decoder: &mut D) -> Self {
         let len = decoder.read_usize();
         let tcx = decoder.interner();
-        tcx.mk_substs_from_iter(
-            (0..len).map::<ty::subst::GenericArg<'tcx>, _>(|_| Decodable::decode(decoder)),
+        tcx.mk_args_from_iter(
+            (0..len).map::<ty::GenericArg<'tcx>, _>(|_| Decodable::decode(decoder)),
         )
     }
 }
diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs
index 1cbfe99f87f..bf9f5846ed9 100644
--- a/compiler/rustc_middle/src/ty/consts.rs
+++ b/compiler/rustc_middle/src/ty/consts.rs
@@ -1,6 +1,6 @@
 use crate::middle::resolve_bound_vars as rbv;
 use crate::mir::interpret::{AllocId, ConstValue, LitToConstInput, Scalar};
-use crate::ty::{self, InternalSubsts, ParamEnv, ParamEnvAnd, Ty, TyCtxt, TypeVisitableExt};
+use crate::ty::{self, GenericArgs, ParamEnv, ParamEnvAnd, Ty, TyCtxt, TypeVisitableExt};
 use rustc_data_structures::intern::Interned;
 use rustc_error_messages::MultiSpan;
 use rustc_hir as hir;
@@ -171,7 +171,7 @@ impl<'tcx> Const<'tcx> {
                 tcx,
                 ty::UnevaluatedConst {
                     def: def.to_def_id(),
-                    substs: InternalSubsts::identity_for_item(tcx, def.to_def_id()),
+                    args: GenericArgs::identity_for_item(tcx, def.to_def_id()),
                 },
                 ty,
             ),
@@ -225,7 +225,7 @@ impl<'tcx> Const<'tcx> {
             )) => {
                 // Use the type from the param's definition, since we can resolve it,
                 // not the expected parameter type from WithOptConstParam.
-                let param_ty = tcx.type_of(def_id).subst_identity();
+                let param_ty = tcx.type_of(def_id).instantiate_identity();
                 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
@@ -406,14 +406,14 @@ impl<'tcx> Const<'tcx> {
             // any region variables.
 
             // HACK(eddyb) when the query key would contain inference variables,
-            // attempt using identity substs and `ParamEnv` instead, that will succeed
+            // attempt using identity args and `ParamEnv` instead, that will succeed
             // when the expression doesn't depend on any parameters.
             // FIXME(eddyb, skinny121) pass `InferCtxt` into here when it's available, so that
             // we can call `infcx.const_eval_resolve` which handles inference variables.
             let param_env_and = if (param_env, unevaluated).has_non_region_infer() {
                 tcx.param_env(unevaluated.def).and(ty::UnevaluatedConst {
                     def: unevaluated.def,
-                    substs: InternalSubsts::identity_for_item(tcx, unevaluated.def),
+                    args: GenericArgs::identity_for_item(tcx, unevaluated.def),
                 })
             } else {
                 tcx.erase_regions(param_env)
@@ -430,8 +430,8 @@ impl<'tcx> Const<'tcx> {
                 EvalMode::Typeck => {
                     match tcx.const_eval_resolve_for_typeck(param_env, unevaluated, None) {
                         // NOTE(eddyb) `val` contains no lifetimes/types/consts,
-                        // and we use the original type, so nothing from `substs`
-                        // (which may be identity substs, see above),
+                        // and we use the original type, so nothing from `args`
+                        // (which may be identity args, see above),
                         // can leak through `val` into the const we return.
                         Ok(val) => Some(Ok(EvalResult::ValTree(val?))),
                         Err(ErrorHandled::TooGeneric) => None,
@@ -441,8 +441,8 @@ impl<'tcx> Const<'tcx> {
                 EvalMode::Mir => {
                     match tcx.const_eval_resolve(param_env, unevaluated.expand(), None) {
                         // NOTE(eddyb) `val` contains no lifetimes/types/consts,
-                        // and we use the original type, so nothing from `substs`
-                        // (which may be identity substs, see above),
+                        // and we use the original type, so nothing from `args`
+                        // (which may be identity args, see above),
                         // can leak through `val` into the const we return.
                         Ok(val) => Some(Ok(EvalResult::ConstVal(val))),
                         Err(ErrorHandled::TooGeneric) => None,
diff --git a/compiler/rustc_middle/src/ty/consts/int.rs b/compiler/rustc_middle/src/ty/consts/int.rs
index 1e43fab457e..624195cfb28 100644
--- a/compiler/rustc_middle/src/ty/consts/int.rs
+++ b/compiler/rustc_middle/src/ty/consts/int.rs
@@ -418,7 +418,7 @@ impl TryFrom<ScalarInt> for char {
 
     #[inline]
     fn try_from(int: ScalarInt) -> Result<Self, Self::Error> {
-        let Ok(bits) = int.to_bits(Size::from_bytes(std::mem::size_of::<char>())) else  {
+        let Ok(bits) = int.to_bits(Size::from_bytes(std::mem::size_of::<char>())) else {
             return Err(CharTryFromScalarInt);
         };
         match char::from_u32(bits.try_into().unwrap()) {
diff --git a/compiler/rustc_middle/src/ty/consts/kind.rs b/compiler/rustc_middle/src/ty/consts/kind.rs
index 5f2b6d42bf8..6c76075c214 100644
--- a/compiler/rustc_middle/src/ty/consts/kind.rs
+++ b/compiler/rustc_middle/src/ty/consts/kind.rs
@@ -1,7 +1,7 @@
 use super::Const;
 use crate::mir;
 use crate::ty::abstract_const::CastKind;
-use crate::ty::subst::SubstsRef;
+use crate::ty::GenericArgsRef;
 use crate::ty::{self, List, Ty};
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_hir::def_id::DefId;
@@ -12,7 +12,7 @@ use rustc_macros::HashStable;
 #[derive(Hash, HashStable, TypeFoldable, TypeVisitable)]
 pub struct UnevaluatedConst<'tcx> {
     pub def: DefId,
-    pub substs: SubstsRef<'tcx>,
+    pub args: GenericArgsRef<'tcx>,
 }
 
 impl rustc_errors::IntoDiagnosticArg for UnevaluatedConst<'_> {
@@ -24,14 +24,14 @@ impl rustc_errors::IntoDiagnosticArg for UnevaluatedConst<'_> {
 impl<'tcx> UnevaluatedConst<'tcx> {
     #[inline]
     pub fn expand(self) -> mir::UnevaluatedConst<'tcx> {
-        mir::UnevaluatedConst { def: self.def, substs: self.substs, promoted: None }
+        mir::UnevaluatedConst { def: self.def, args: self.args, promoted: None }
     }
 }
 
 impl<'tcx> UnevaluatedConst<'tcx> {
     #[inline]
-    pub fn new(def: DefId, substs: SubstsRef<'tcx>) -> UnevaluatedConst<'tcx> {
-        UnevaluatedConst { def, substs }
+    pub fn new(def: DefId, args: GenericArgsRef<'tcx>) -> UnevaluatedConst<'tcx> {
+        UnevaluatedConst { def, args }
     }
 }
 
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 6990fbbb634..8bb13edbe95 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -30,7 +30,7 @@ use crate::ty::{
     Predicate, PredicateKind, Region, RegionKind, ReprOptions, TraitObjectVisitor, Ty, TyKind,
     TyVid, TypeAndMut, Visibility,
 };
-use crate::ty::{GenericArg, InternalSubsts, SubstsRef};
+use crate::ty::{GenericArg, GenericArgs, GenericArgsRef};
 use rustc_ast::{self as ast, attr};
 use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
@@ -84,7 +84,7 @@ use std::ops::{Bound, Deref};
 #[allow(rustc::usage_of_ty_tykind)]
 impl<'tcx> Interner for TyCtxt<'tcx> {
     type AdtDef = ty::AdtDef<'tcx>;
-    type SubstsRef = ty::SubstsRef<'tcx>;
+    type GenericArgsRef = ty::GenericArgsRef<'tcx>;
     type DefId = DefId;
     type Binder<T> = Binder<'tcx, T>;
     type Ty = Ty<'tcx>;
@@ -142,7 +142,7 @@ pub struct CtxtInterners<'tcx> {
     // they're accessed quite often.
     type_: InternedSet<'tcx, WithCachedTypeInfo<TyKind<'tcx>>>,
     const_lists: InternedSet<'tcx, List<ty::Const<'tcx>>>,
-    substs: InternedSet<'tcx, InternalSubsts<'tcx>>,
+    args: InternedSet<'tcx, GenericArgs<'tcx>>,
     type_lists: InternedSet<'tcx, List<Ty<'tcx>>>,
     canonical_var_infos: InternedSet<'tcx, List<CanonicalVarInfo<'tcx>>>,
     region: InternedSet<'tcx, RegionKind<'tcx>>,
@@ -167,7 +167,7 @@ impl<'tcx> CtxtInterners<'tcx> {
             arena,
             type_: Default::default(),
             const_lists: Default::default(),
-            substs: Default::default(),
+            args: Default::default(),
             type_lists: Default::default(),
             region: Default::default(),
             poly_existential_predicates: Default::default(),
@@ -682,7 +682,7 @@ impl<'tcx> TyCtxt<'tcx> {
 
     /// Creates a type context and call the closure with a `TyCtxt` reference
     /// to the context. The closure enforces that the type context and any interned
-    /// value (types, substs, etc.) can only be used while `ty::tls` has a valid
+    /// value (types, args, etc.) can only be used while `ty::tls` has a valid
     /// reference to the context, to allow formatting values that need it.
     pub fn create_global_ctxt(
         s: &'tcx Session,
@@ -1083,7 +1083,7 @@ impl<'tcx> TyCtxt<'tcx> {
             _ => return None,
         }
 
-        let ret_ty = self.type_of(scope_def_id).subst_identity();
+        let ret_ty = self.type_of(scope_def_id).instantiate_identity();
         match ret_ty.kind() {
             ty::FnDef(_, _) => {
                 let sig = ret_ty.fn_sig(self);
@@ -1125,7 +1125,7 @@ impl<'tcx> TyCtxt<'tcx> {
             self,
             self.lifetimes.re_static,
             self.type_of(self.require_lang_item(LangItem::PanicLocation, None))
-                .subst(self, self.mk_substs(&[self.lifetimes.re_static.into()])),
+                .instantiate(self, self.mk_args(&[self.lifetimes.re_static.into()])),
         )
     }
 
@@ -1168,7 +1168,7 @@ impl<'tcx> TyCtxt<'tcx> {
 /// A trait implemented for all `X<'a>` types that can be safely and
 /// efficiently converted to `X<'tcx>` as long as they are part of the
 /// provided `TyCtxt<'tcx>`.
-/// This can be done, for example, for `Ty<'tcx>` or `SubstsRef<'tcx>`
+/// This can be done, for example, for `Ty<'tcx>` or `GenericArgsRef<'tcx>`
 /// by looking them up in their respective interners.
 ///
 /// However, this is still not the best implementation as it does
@@ -1234,8 +1234,8 @@ nop_list_lift! {canonical_var_infos; CanonicalVarInfo<'a> => CanonicalVarInfo<'t
 nop_list_lift! {projs; ProjectionKind => ProjectionKind}
 nop_list_lift! {bound_variable_kinds; ty::BoundVariableKind => ty::BoundVariableKind}
 
-// This is the impl for `&'a InternalSubsts<'a>`.
-nop_list_lift! {substs; GenericArg<'a> => GenericArg<'tcx>}
+// This is the impl for `&'a GenericArgs<'a>`.
+nop_list_lift! {args; GenericArg<'a> => GenericArg<'tcx>}
 
 CloneLiftImpls! {
     Constness,
@@ -1347,7 +1347,7 @@ impl<'tcx> TyCtxt<'tcx> {
                     Foreign
                 )?;
 
-                writeln!(fmt, "InternalSubsts interner: #{}", self.0.interners.substs.len())?;
+                writeln!(fmt, "GenericArgs interner: #{}", self.0.interners.args.len())?;
                 writeln!(fmt, "Region interner: #{}", self.0.interners.region.len())?;
                 writeln!(
                     fmt,
@@ -1503,7 +1503,7 @@ macro_rules! slice_interners {
 // should be used when possible, because it's faster.
 slice_interners!(
     const_lists: pub mk_const_list(Const<'tcx>),
-    substs: pub mk_substs(GenericArg<'tcx>),
+    args: pub mk_args(GenericArg<'tcx>),
     type_lists: pub mk_type_list(Ty<'tcx>),
     canonical_var_infos: pub mk_canonical_var_infos(CanonicalVarInfo<'tcx>),
     poly_existential_predicates: intern_poly_existential_predicates(PolyExistentialPredicate<'tcx>),
@@ -1617,12 +1617,12 @@ impl<'tcx> TyCtxt<'tcx> {
     }
 
     #[inline(always)]
-    pub(crate) fn check_and_mk_substs(
+    pub(crate) fn check_and_mk_args(
         self,
         _def_id: DefId,
-        substs: impl IntoIterator<Item: Into<GenericArg<'tcx>>>,
-    ) -> SubstsRef<'tcx> {
-        let substs = substs.into_iter().map(Into::into);
+        args: impl IntoIterator<Item: Into<GenericArg<'tcx>>>,
+    ) -> GenericArgsRef<'tcx> {
+        let args = args.into_iter().map(Into::into);
         #[cfg(debug_assertions)]
         {
             let generics = self.generics_of(_def_id);
@@ -1638,12 +1638,12 @@ impl<'tcx> TyCtxt<'tcx> {
             };
             assert_eq!(
                 (n, Some(n)),
-                substs.size_hint(),
+                args.size_hint(),
                 "wrong number of generic parameters for {_def_id:?}: {:?}",
-                substs.collect::<Vec<_>>(),
+                args.collect::<Vec<_>>(),
             );
         }
-        self.mk_substs_from_iter(substs)
+        self.mk_args_from_iter(args)
     }
 
     #[inline]
@@ -1801,12 +1801,12 @@ impl<'tcx> TyCtxt<'tcx> {
         T::collect_and_apply(iter, |xs| self.mk_type_list(xs))
     }
 
-    pub fn mk_substs_from_iter<I, T>(self, iter: I) -> T::Output
+    pub fn mk_args_from_iter<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.mk_substs(xs))
+        T::collect_and_apply(iter, |xs| self.mk_args(xs))
     }
 
     pub fn mk_canonical_var_infos_from_iter<I, T>(self, iter: I) -> T::Output
@@ -1833,21 +1833,21 @@ impl<'tcx> TyCtxt<'tcx> {
         T::collect_and_apply(iter, |xs| self.mk_fields(xs))
     }
 
-    pub fn mk_substs_trait(
+    pub fn mk_args_trait(
         self,
         self_ty: Ty<'tcx>,
         rest: impl IntoIterator<Item = GenericArg<'tcx>>,
-    ) -> SubstsRef<'tcx> {
-        self.mk_substs_from_iter(iter::once(self_ty.into()).chain(rest))
+    ) -> GenericArgsRef<'tcx> {
+        self.mk_args_from_iter(iter::once(self_ty.into()).chain(rest))
     }
 
     pub fn mk_alias_ty(
         self,
         def_id: DefId,
-        substs: impl IntoIterator<Item: Into<GenericArg<'tcx>>>,
+        args: impl IntoIterator<Item: Into<GenericArg<'tcx>>>,
     ) -> ty::AliasTy<'tcx> {
-        let substs = self.check_and_mk_substs(def_id, substs);
-        ty::AliasTy { def_id, substs, _use_mk_alias_ty_instead: () }
+        let args = self.check_and_mk_args(def_id, args);
+        ty::AliasTy { def_id, args, _use_mk_alias_ty_instead: () }
     }
 
     pub fn mk_bound_variable_kinds_from_iter<I, T>(self, iter: I) -> T::Output
diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs
index a0b17c374e4..905e855896e 100644
--- a/compiler/rustc_middle/src/ty/diagnostics.rs
+++ b/compiler/rustc_middle/src/ty/diagnostics.rs
@@ -71,7 +71,7 @@ impl<'tcx> Ty<'tcx> {
     /// ADTs with no type arguments.
     pub fn is_simple_text(self) -> bool {
         match self.kind() {
-            Adt(_, substs) => substs.non_erasable_generics().next().is_none(),
+            Adt(_, args) => args.non_erasable_generics().next().is_none(),
             Ref(_, ty, _) => ty.is_simple_text(),
             _ => self.is_simple_ty(),
         }
@@ -491,7 +491,7 @@ 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();
+                let parent_ty = self.tcx.type_of(parent).instantiate_identity();
                 if let DefKind::TyAlias | DefKind::AssocTy = self.tcx.def_kind(parent)
                     && let Alias(Opaque, AliasTy { def_id: parent_opaque_def_id, .. }) = *parent_ty.kind()
                     && parent_opaque_def_id == def_id
@@ -558,8 +558,8 @@ impl<'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for MakeSuggestableFolder<'tcx> {
         let t = match *t.kind() {
             Infer(InferTy::TyVar(_)) if self.infer_suggestable => t,
 
-            FnDef(def_id, substs) => {
-                Ty::new_fn_ptr(self.tcx, self.tcx.fn_sig(def_id).subst(self.tcx, substs))
+            FnDef(def_id, args) => {
+                Ty::new_fn_ptr(self.tcx, self.tcx.fn_sig(def_id).instantiate(self.tcx, args))
             }
 
             // FIXME(compiler-errors): We could replace these with infer, I guess.
@@ -575,7 +575,7 @@ 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();
+                let parent_ty = self.tcx.type_of(parent).instantiate_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, .. }) = *parent_ty.kind()
                     && parent_opaque_def_id == def_id
diff --git a/compiler/rustc_middle/src/ty/fast_reject.rs b/compiler/rustc_middle/src/ty/fast_reject.rs
index 76f61d9ac9c..e86ff4d26aa 100644
--- a/compiler/rustc_middle/src/ty/fast_reject.rs
+++ b/compiler/rustc_middle/src/ty/fast_reject.rs
@@ -1,6 +1,6 @@
 use crate::mir::Mutability;
-use crate::ty::subst::GenericArgKind;
-use crate::ty::{self, SubstsRef, Ty, TyCtxt, TypeVisitableExt};
+use crate::ty::GenericArgKind;
+use crate::ty::{self, GenericArgsRef, Ty, TyCtxt, TypeVisitableExt};
 use rustc_hir::def_id::DefId;
 use std::fmt::Debug;
 use std::hash::Hash;
@@ -188,12 +188,12 @@ pub struct DeepRejectCtxt {
 }
 
 impl DeepRejectCtxt {
-    pub fn substs_refs_may_unify<'tcx>(
+    pub fn args_refs_may_unify<'tcx>(
         self,
-        obligation_substs: SubstsRef<'tcx>,
-        impl_substs: SubstsRef<'tcx>,
+        obligation_args: GenericArgsRef<'tcx>,
+        impl_args: GenericArgsRef<'tcx>,
     ) -> bool {
-        iter::zip(obligation_substs, impl_substs).all(|(obl, imp)| {
+        iter::zip(obligation_args, impl_args).all(|(obl, imp)| {
             match (obl.unpack(), imp.unpack()) {
                 // We don't fast reject based on regions for now.
                 (GenericArgKind::Lifetime(_), GenericArgKind::Lifetime(_)) => true,
@@ -258,9 +258,9 @@ impl DeepRejectCtxt {
                 }
                 _ => false,
             },
-            ty::Adt(obl_def, obl_substs) => match k {
-                &ty::Adt(impl_def, impl_substs) => {
-                    obl_def == impl_def && self.substs_refs_may_unify(obl_substs, impl_substs)
+            ty::Adt(obl_def, obl_args) => match k {
+                &ty::Adt(impl_def, impl_args) => {
+                    obl_def == impl_def && self.args_refs_may_unify(obl_args, impl_args)
                 }
                 _ => false,
             },
diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs
index ff391794703..bbd4a623330 100644
--- a/compiler/rustc_middle/src/ty/flags.rs
+++ b/compiler/rustc_middle/src/ty/flags.rs
@@ -1,5 +1,5 @@
-use crate::ty::subst::{GenericArg, GenericArgKind};
 use crate::ty::{self, InferConst, Ty, TypeFlags};
+use crate::ty::{GenericArg, GenericArgKind};
 use std::slice;
 
 #[derive(Debug)]
@@ -105,48 +105,48 @@ impl FlagComputation {
                 self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE);
             }
 
-            ty::Generator(_, substs, _) => {
-                let substs = substs.as_generator();
+            ty::Generator(_, args, _) => {
+                let args = args.as_generator();
                 let should_remove_further_specializable =
                     !self.flags.contains(TypeFlags::STILL_FURTHER_SPECIALIZABLE);
-                self.add_substs(substs.parent_substs());
+                self.add_args(args.parent_args());
                 if should_remove_further_specializable {
                     self.flags -= TypeFlags::STILL_FURTHER_SPECIALIZABLE;
                 }
 
-                self.add_ty(substs.resume_ty());
-                self.add_ty(substs.return_ty());
-                self.add_ty(substs.witness());
-                self.add_ty(substs.yield_ty());
-                self.add_ty(substs.tupled_upvars_ty());
+                self.add_ty(args.resume_ty());
+                self.add_ty(args.return_ty());
+                self.add_ty(args.witness());
+                self.add_ty(args.yield_ty());
+                self.add_ty(args.tupled_upvars_ty());
             }
 
             &ty::GeneratorWitness(ts) => {
                 self.bound_computation(ts, |flags, ts| flags.add_tys(ts));
             }
 
-            ty::GeneratorWitnessMIR(_, substs) => {
+            ty::GeneratorWitnessMIR(_, args) => {
                 let should_remove_further_specializable =
                     !self.flags.contains(TypeFlags::STILL_FURTHER_SPECIALIZABLE);
-                self.add_substs(substs);
+                self.add_args(args);
                 if should_remove_further_specializable {
                     self.flags -= TypeFlags::STILL_FURTHER_SPECIALIZABLE;
                 }
                 self.add_flags(TypeFlags::HAS_TY_GENERATOR);
             }
 
-            &ty::Closure(_, substs) => {
-                let substs = substs.as_closure();
+            &ty::Closure(_, args) => {
+                let args = args.as_closure();
                 let should_remove_further_specializable =
                     !self.flags.contains(TypeFlags::STILL_FURTHER_SPECIALIZABLE);
-                self.add_substs(substs.parent_substs());
+                self.add_args(args.parent_args());
                 if should_remove_further_specializable {
                     self.flags -= TypeFlags::STILL_FURTHER_SPECIALIZABLE;
                 }
 
-                self.add_ty(substs.sig_as_fn_ptr_ty());
-                self.add_ty(substs.kind_ty());
-                self.add_ty(substs.tupled_upvars_ty());
+                self.add_ty(args.sig_as_fn_ptr_ty());
+                self.add_ty(args.kind_ty());
+                self.add_ty(args.tupled_upvars_ty());
             }
 
             &ty::Bound(debruijn, _) => {
@@ -172,8 +172,8 @@ impl FlagComputation {
                 }
             }
 
-            &ty::Adt(_, substs) => {
-                self.add_substs(substs);
+            &ty::Adt(_, args) => {
+                self.add_args(args);
             }
 
             &ty::Alias(kind, data) => {
@@ -189,7 +189,7 @@ impl FlagComputation {
             &ty::Dynamic(obj, r, _) => {
                 for predicate in obj.iter() {
                     self.bound_computation(predicate, |computation, predicate| match predicate {
-                        ty::ExistentialPredicate::Trait(tr) => computation.add_substs(tr.substs),
+                        ty::ExistentialPredicate::Trait(tr) => computation.add_args(tr.args),
                         ty::ExistentialPredicate::Projection(p) => {
                             computation.add_existential_projection(&p);
                         }
@@ -220,8 +220,8 @@ impl FlagComputation {
                 self.add_tys(types);
             }
 
-            &ty::FnDef(_, substs) => {
-                self.add_substs(substs);
+            &ty::FnDef(_, args) => {
+                self.add_args(args);
             }
 
             &ty::FnPtr(fn_sig) => self.bound_computation(fn_sig, |computation, fn_sig| {
@@ -238,7 +238,7 @@ impl FlagComputation {
     fn add_predicate_atom(&mut self, atom: ty::PredicateKind<'_>) {
         match atom {
             ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_pred)) => {
-                self.add_substs(trait_pred.trait_ref.substs);
+                self.add_args(trait_pred.trait_ref.args);
             }
             ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(
                 a,
@@ -274,11 +274,11 @@ impl FlagComputation {
                 self.add_term(term);
             }
             ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(arg)) => {
-                self.add_substs(slice::from_ref(&arg));
+                self.add_args(slice::from_ref(&arg));
             }
             ty::PredicateKind::ObjectSafe(_def_id) => {}
-            ty::PredicateKind::ClosureKind(_def_id, substs, _kind) => {
-                self.add_substs(substs);
+            ty::PredicateKind::ClosureKind(_def_id, args, _kind) => {
+                self.add_args(args);
             }
             ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(uv)) => {
                 self.add_const(uv);
@@ -317,7 +317,7 @@ impl FlagComputation {
         self.add_ty(c.ty());
         match c.kind() {
             ty::ConstKind::Unevaluated(uv) => {
-                self.add_substs(uv.substs);
+                self.add_args(uv.args);
                 self.add_flags(TypeFlags::HAS_CT_PROJECTION);
             }
             ty::ConstKind::Infer(infer) => {
@@ -365,7 +365,7 @@ impl FlagComputation {
     }
 
     fn add_existential_projection(&mut self, projection: &ty::ExistentialProjection<'_>) {
-        self.add_substs(projection.substs);
+        self.add_args(projection.args);
         match projection.term.unpack() {
             ty::TermKind::Ty(ty) => self.add_ty(ty),
             ty::TermKind::Const(ct) => self.add_const(ct),
@@ -373,11 +373,11 @@ impl FlagComputation {
     }
 
     fn add_alias_ty(&mut self, alias_ty: ty::AliasTy<'_>) {
-        self.add_substs(alias_ty.substs);
+        self.add_args(alias_ty.args);
     }
 
-    fn add_substs(&mut self, substs: &[GenericArg<'_>]) {
-        for kind in substs {
+    fn add_args(&mut self, args: &[GenericArg<'_>]) {
+        for kind in args {
             match kind.unpack() {
                 GenericArgKind::Type(ty) => self.add_ty(ty),
                 GenericArgKind::Lifetime(lt) => self.add_region(lt),
diff --git a/compiler/rustc_middle/src/ty/subst.rs b/compiler/rustc_middle/src/ty/generic_args.rs
index e1a58b97557..12af8456494 100644
--- a/compiler/rustc_middle/src/ty/subst.rs
+++ b/compiler/rustc_middle/src/ty/generic_args.rs
@@ -1,8 +1,8 @@
-// Type substitutions.
+// Generic arguments.
 
 use crate::ty::codec::{TyDecoder, TyEncoder};
 use crate::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeFolder, TypeSuperFoldable};
-use crate::ty::sty::{ClosureSubsts, GeneratorSubsts, InlineConstSubsts};
+use crate::ty::sty::{ClosureArgs, GeneratorArgs, InlineConstArgs};
 use crate::ty::visit::{TypeVisitable, TypeVisitableExt, TypeVisitor};
 use crate::ty::{self, Lift, List, ParamConst, Ty, TyCtxt};
 
@@ -174,7 +174,7 @@ impl<'tcx> GenericArg<'tcx> {
     }
 
     /// Unpack the `GenericArg` as a type when it is known certainly to be a type.
-    /// This is true in cases where `Substs` is used in places where the kinds are known
+    /// This is true in cases where `GenericArgs` is used in places where the kinds are known
     /// to be limited (e.g. in tuples, where the only parameters are type parameters).
     pub fn expect_ty(self) -> Ty<'tcx> {
         self.as_type().unwrap_or_else(|| bug!("expected a type, but found another kind"))
@@ -241,13 +241,13 @@ impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for GenericArg<'tcx> {
     }
 }
 
-/// List of generic arguments that are gonna be used to substitute generic parameters.
-pub type InternalSubsts<'tcx> = List<GenericArg<'tcx>>;
+/// List of generic arguments that are gonna be used to replace generic parameters.
+pub type GenericArgs<'tcx> = List<GenericArg<'tcx>>;
 
-pub type SubstsRef<'tcx> = &'tcx InternalSubsts<'tcx>;
+pub type GenericArgsRef<'tcx> = &'tcx GenericArgs<'tcx>;
 
-impl<'tcx> InternalSubsts<'tcx> {
-    /// Converts substs to a type list.
+impl<'tcx> GenericArgs<'tcx> {
+    /// Converts generic args to a type list.
     ///
     /// # Panics
     ///
@@ -255,66 +255,71 @@ impl<'tcx> InternalSubsts<'tcx> {
     pub fn into_type_list(&self, tcx: TyCtxt<'tcx>) -> &'tcx List<Ty<'tcx>> {
         tcx.mk_type_list_from_iter(self.iter().map(|arg| match arg.unpack() {
             GenericArgKind::Type(ty) => ty,
-            _ => bug!("`into_type_list` called on substs with non-types"),
+            _ => bug!("`into_type_list` called on generic arg with non-types"),
         }))
     }
 
-    /// Interpret these substitutions as the substitutions of a closure type.
-    /// Closure substitutions have a particular structure controlled by the
+    /// Interpret these generic args as the args of a closure type.
+    /// Closure args have a particular structure controlled by the
     /// compiler that encodes information like the signature and closure kind;
-    /// see `ty::ClosureSubsts` struct for more comments.
-    pub fn as_closure(&'tcx self) -> ClosureSubsts<'tcx> {
-        ClosureSubsts { substs: self }
+    /// see `ty::ClosureArgs` struct for more comments.
+    pub fn as_closure(&'tcx self) -> ClosureArgs<'tcx> {
+        ClosureArgs { args: self }
     }
 
-    /// Interpret these substitutions as the substitutions of a generator type.
-    /// Generator substitutions have a particular structure controlled by the
+    /// Interpret these generic args as the args of a generator type.
+    /// Generator args have a particular structure controlled by the
     /// compiler that encodes information like the signature and generator kind;
-    /// see `ty::GeneratorSubsts` struct for more comments.
-    pub fn as_generator(&'tcx self) -> GeneratorSubsts<'tcx> {
-        GeneratorSubsts { substs: self }
+    /// see `ty::GeneratorArgs` struct for more comments.
+    pub fn as_generator(&'tcx self) -> GeneratorArgs<'tcx> {
+        GeneratorArgs { args: self }
     }
 
-    /// Interpret these substitutions as the substitutions of an inline const.
-    /// Inline const substitutions have a particular structure controlled by the
+    /// Interpret these generic args as the args of an inline const.
+    /// Inline const args have a particular structure controlled by the
     /// compiler that encodes information like the inferred type;
-    /// see `ty::InlineConstSubsts` struct for more comments.
-    pub fn as_inline_const(&'tcx self) -> InlineConstSubsts<'tcx> {
-        InlineConstSubsts { substs: self }
+    /// see `ty::InlineConstArgs` struct for more comments.
+    pub fn as_inline_const(&'tcx self) -> InlineConstArgs<'tcx> {
+        InlineConstArgs { args: self }
     }
 
-    /// Creates an `InternalSubsts` that maps each generic parameter to itself.
-    pub fn identity_for_item(tcx: TyCtxt<'tcx>, def_id: impl Into<DefId>) -> SubstsRef<'tcx> {
+    /// Creates an `GenericArgs` that maps each generic parameter to itself.
+    pub fn identity_for_item(tcx: TyCtxt<'tcx>, def_id: impl Into<DefId>) -> GenericArgsRef<'tcx> {
         Self::for_item(tcx, def_id.into(), |param, _| tcx.mk_param_from_def(param))
     }
 
-    /// Creates an `InternalSubsts` for generic parameter definitions,
+    /// Creates an `GenericArgs` for generic parameter definitions,
     /// by calling closures to obtain each kind.
-    /// The closures get to observe the `InternalSubsts` as they're
+    /// The closures get to observe the `GenericArgs` as they're
     /// being built, which can be used to correctly
-    /// substitute defaults of generic parameters.
-    pub fn for_item<F>(tcx: TyCtxt<'tcx>, def_id: DefId, mut mk_kind: F) -> SubstsRef<'tcx>
+    /// replace defaults of generic parameters.
+    pub fn for_item<F>(tcx: TyCtxt<'tcx>, def_id: DefId, mut mk_kind: F) -> GenericArgsRef<'tcx>
     where
         F: FnMut(&ty::GenericParamDef, &[GenericArg<'tcx>]) -> GenericArg<'tcx>,
     {
         let defs = tcx.generics_of(def_id);
         let count = defs.count();
-        let mut substs = SmallVec::with_capacity(count);
-        Self::fill_item(&mut substs, tcx, defs, &mut mk_kind);
-        tcx.mk_substs(&substs)
+        let mut args = SmallVec::with_capacity(count);
+        Self::fill_item(&mut args, tcx, defs, &mut mk_kind);
+        tcx.mk_args(&args)
     }
 
-    pub fn extend_to<F>(&self, tcx: TyCtxt<'tcx>, def_id: DefId, mut mk_kind: F) -> SubstsRef<'tcx>
+    pub fn extend_to<F>(
+        &self,
+        tcx: TyCtxt<'tcx>,
+        def_id: DefId,
+        mut mk_kind: F,
+    ) -> GenericArgsRef<'tcx>
     where
         F: FnMut(&ty::GenericParamDef, &[GenericArg<'tcx>]) -> GenericArg<'tcx>,
     {
-        Self::for_item(tcx, def_id, |param, substs| {
-            self.get(param.index as usize).cloned().unwrap_or_else(|| mk_kind(param, substs))
+        Self::for_item(tcx, def_id, |param, args| {
+            self.get(param.index as usize).cloned().unwrap_or_else(|| mk_kind(param, args))
         })
     }
 
     pub fn fill_item<F>(
-        substs: &mut SmallVec<[GenericArg<'tcx>; 8]>,
+        args: &mut SmallVec<[GenericArg<'tcx>; 8]>,
         tcx: TyCtxt<'tcx>,
         defs: &ty::Generics,
         mk_kind: &mut F,
@@ -323,38 +328,38 @@ impl<'tcx> InternalSubsts<'tcx> {
     {
         if let Some(def_id) = defs.parent {
             let parent_defs = tcx.generics_of(def_id);
-            Self::fill_item(substs, tcx, parent_defs, mk_kind);
+            Self::fill_item(args, tcx, parent_defs, mk_kind);
         }
-        Self::fill_single(substs, defs, mk_kind)
+        Self::fill_single(args, defs, mk_kind)
     }
 
     pub fn fill_single<F>(
-        substs: &mut SmallVec<[GenericArg<'tcx>; 8]>,
+        args: &mut SmallVec<[GenericArg<'tcx>; 8]>,
         defs: &ty::Generics,
         mk_kind: &mut F,
     ) where
         F: FnMut(&ty::GenericParamDef, &[GenericArg<'tcx>]) -> GenericArg<'tcx>,
     {
-        substs.reserve(defs.params.len());
+        args.reserve(defs.params.len());
         for param in &defs.params {
-            let kind = mk_kind(param, substs);
-            assert_eq!(param.index as usize, substs.len(), "{substs:#?}, {defs:#?}");
-            substs.push(kind);
+            let kind = mk_kind(param, args);
+            assert_eq!(param.index as usize, args.len(), "{args:#?}, {defs:#?}");
+            args.push(kind);
         }
     }
 
-    // Extend an `original_substs` list to the full number of substs expected by `def_id`,
+    // Extend an `original_args` list to the full number of args expected by `def_id`,
     // filling in the missing parameters with error ty/ct or 'static regions.
     pub fn extend_with_error(
         tcx: TyCtxt<'tcx>,
         def_id: DefId,
-        original_substs: &[GenericArg<'tcx>],
-    ) -> SubstsRef<'tcx> {
-        ty::InternalSubsts::for_item(tcx, def_id, |def, substs| {
-            if let Some(subst) = original_substs.get(def.index as usize) {
-                *subst
+        original_args: &[GenericArg<'tcx>],
+    ) -> GenericArgsRef<'tcx> {
+        ty::GenericArgs::for_item(tcx, def_id, |def, args| {
+            if let Some(arg) = original_args.get(def.index as usize) {
+                *arg
             } else {
-                def.to_error(tcx, substs)
+                def.to_error(tcx, args)
             }
         })
     }
@@ -410,9 +415,9 @@ impl<'tcx> InternalSubsts<'tcx> {
         self.type_at(def.index as usize).into()
     }
 
-    /// Transform from substitutions for a child of `source_ancestor`
-    /// (e.g., a trait or impl) to substitutions for the same child
-    /// in a different item, with `target_substs` as the base for
+    /// Transform from generic args for a child of `source_ancestor`
+    /// (e.g., a trait or impl) to args for the same child
+    /// in a different item, with `target_args` as the base for
     /// the target impl/trait, with the source child-specific
     /// parameters (e.g., method parameters) on top of that base.
     ///
@@ -423,23 +428,23 @@ impl<'tcx> InternalSubsts<'tcx> {
     /// impl<U> X<U> for U { fn f<V>() {} }
     /// ```
     ///
-    /// * If `self` is `[Self, S, T]`: the identity substs of `f` in the trait.
+    /// * If `self` is `[Self, S, T]`: the identity args of `f` in the trait.
     /// * If `source_ancestor` is the def_id of the trait.
-    /// * If `target_substs` is `[U]`, the substs for the impl.
-    /// * Then we will return `[U, T]`, the subst for `f` in the impl that
+    /// * If `target_args` is `[U]`, the args for the impl.
+    /// * Then we will return `[U, T]`, the arg for `f` in the impl that
     ///   are needed for it to match the trait.
     pub fn rebase_onto(
         &self,
         tcx: TyCtxt<'tcx>,
         source_ancestor: DefId,
-        target_substs: SubstsRef<'tcx>,
-    ) -> SubstsRef<'tcx> {
+        target_args: GenericArgsRef<'tcx>,
+    ) -> GenericArgsRef<'tcx> {
         let defs = tcx.generics_of(source_ancestor);
-        tcx.mk_substs_from_iter(target_substs.iter().chain(self.iter().skip(defs.params.len())))
+        tcx.mk_args_from_iter(target_args.iter().chain(self.iter().skip(defs.params.len())))
     }
 
-    pub fn truncate_to(&self, tcx: TyCtxt<'tcx>, generics: &ty::Generics) -> SubstsRef<'tcx> {
-        tcx.mk_substs_from_iter(self.iter().take(generics.count()))
+    pub fn truncate_to(&self, tcx: TyCtxt<'tcx>, generics: &ty::Generics) -> GenericArgsRef<'tcx> {
+        tcx.mk_args_from_iter(self.iter().take(generics.count()))
     }
 
     pub fn host_effect_param(&'tcx self) -> Option<ty::Const<'tcx>> {
@@ -447,7 +452,7 @@ impl<'tcx> InternalSubsts<'tcx> {
     }
 }
 
-impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for SubstsRef<'tcx> {
+impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for GenericArgsRef<'tcx> {
     fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
         self,
         folder: &mut F,
@@ -456,16 +461,12 @@ impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for SubstsRef<'tcx> {
         // common length lists, to avoid the overhead of `SmallVec` creation.
         // The match arms are in order of frequency. The 1, 2, and 0 cases are
         // typically hit in 90--99.99% of cases. When folding doesn't change
-        // the substs, it's faster to reuse the existing substs rather than
-        // calling `mk_substs`.
+        // the args, it's faster to reuse the existing args rather than
+        // calling `mk_args`.
         match self.len() {
             1 => {
                 let param0 = self[0].try_fold_with(folder)?;
-                if param0 == self[0] {
-                    Ok(self)
-                } else {
-                    Ok(folder.interner().mk_substs(&[param0]))
-                }
+                if param0 == self[0] { Ok(self) } else { Ok(folder.interner().mk_args(&[param0])) }
             }
             2 => {
                 let param0 = self[0].try_fold_with(folder)?;
@@ -473,11 +474,11 @@ impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for SubstsRef<'tcx> {
                 if param0 == self[0] && param1 == self[1] {
                     Ok(self)
                 } else {
-                    Ok(folder.interner().mk_substs(&[param0, param1]))
+                    Ok(folder.interner().mk_args(&[param0, param1]))
                 }
             }
             0 => Ok(self),
-            _ => ty::util::fold_list(self, folder, |tcx, v| tcx.mk_substs(v)),
+            _ => ty::util::fold_list(self, folder, |tcx, v| tcx.mk_args(v)),
         }
     }
 }
@@ -487,7 +488,7 @@ impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for &'tcx ty::List<Ty<'tcx>> {
         self,
         folder: &mut F,
     ) -> Result<Self, F::Error> {
-        // This code is fairly hot, though not as hot as `SubstsRef`.
+        // This code is fairly hot, though not as hot as `GenericArgsRef`.
         //
         // When compiling stage 2, I get the following results:
         //
@@ -525,18 +526,18 @@ impl<'tcx, T: TypeVisitable<TyCtxt<'tcx>>> TypeVisitable<TyCtxt<'tcx>> for &'tcx
 }
 
 /// Similar to [`super::Binder`] except that it tracks early bound generics, i.e. `struct Foo<T>(T)`
-/// needs `T` substituted immediately. This type primarily exists to avoid forgetting to call
-/// `subst`.
+/// needs `T` instantiated immediately. This type primarily exists to avoid forgetting to call
+/// `instantiate`.
 ///
-/// If you don't have anything to `subst`, you may be looking for
-/// [`subst_identity`](EarlyBinder::subst_identity) or [`skip_binder`](EarlyBinder::skip_binder).
+/// If you don't have anything to `instantiate`, you may be looking for
+/// [`instantiate_identity`](EarlyBinder::instantiate_identity) or [`skip_binder`](EarlyBinder::skip_binder).
 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
 #[derive(Encodable, Decodable, HashStable)]
 pub struct EarlyBinder<T> {
     value: T,
 }
 
-/// For early binders, you should first call `subst` before using any visitors.
+/// For early binders, you should first call `instantiate` before using any visitors.
 impl<'tcx, T> !TypeFoldable<TyCtxt<'tcx>> for ty::EarlyBinder<T> {}
 impl<'tcx, T> !TypeVisitable<TyCtxt<'tcx>> for ty::EarlyBinder<T> {}
 
@@ -580,7 +581,7 @@ impl<T> EarlyBinder<T> {
     /// This can be used to extract data that does not depend on generic parameters
     /// (e.g., getting the `DefId` of the inner value or getting the number of
     /// arguments of an `FnSig`). Otherwise, consider using
-    /// [`subst_identity`](EarlyBinder::subst_identity).
+    /// [`instantiate_identity`](EarlyBinder::instantiate_identity).
     ///
     /// To skip the binder on `x: &EarlyBinder<T>` to obtain `&T`, leverage
     /// [`EarlyBinder::as_ref`](EarlyBinder::as_ref): `x.as_ref().skip_binder()`.
@@ -609,35 +610,31 @@ impl<'tcx, 's, I: IntoIterator> EarlyBinder<I>
 where
     I::Item: TypeFoldable<TyCtxt<'tcx>>,
 {
-    pub fn subst_iter(
-        self,
-        tcx: TyCtxt<'tcx>,
-        substs: &'s [GenericArg<'tcx>],
-    ) -> SubstIter<'s, 'tcx, I> {
-        SubstIter { it: self.value.into_iter(), tcx, substs }
+    pub fn arg_iter(self, tcx: TyCtxt<'tcx>, args: &'s [GenericArg<'tcx>]) -> ArgIter<'s, 'tcx, I> {
+        ArgIter { it: self.value.into_iter(), tcx, args }
     }
 
-    /// Similar to [`subst_identity`](EarlyBinder::subst_identity),
+    /// Similar to [`instantiate_identity`](EarlyBinder::instantiate_identity),
     /// but on an iterator of `TypeFoldable` values.
-    pub fn subst_identity_iter(self) -> I::IntoIter {
+    pub fn instantiate_identity_iter(self) -> I::IntoIter {
         self.value.into_iter()
     }
 }
 
-pub struct SubstIter<'s, 'tcx, I: IntoIterator> {
+pub struct ArgIter<'s, 'tcx, I: IntoIterator> {
     it: I::IntoIter,
     tcx: TyCtxt<'tcx>,
-    substs: &'s [GenericArg<'tcx>],
+    args: &'s [GenericArg<'tcx>],
 }
 
-impl<'tcx, I: IntoIterator> Iterator for SubstIter<'_, 'tcx, I>
+impl<'tcx, I: IntoIterator> Iterator for ArgIter<'_, 'tcx, I>
 where
     I::Item: TypeFoldable<TyCtxt<'tcx>>,
 {
     type Item = I::Item;
 
     fn next(&mut self) -> Option<Self::Item> {
-        Some(EarlyBinder { value: self.it.next()? }.subst(self.tcx, self.substs))
+        Some(EarlyBinder { value: self.it.next()? }.instantiate(self.tcx, self.args))
     }
 
     fn size_hint(&self) -> (usize, Option<usize>) {
@@ -645,17 +642,17 @@ where
     }
 }
 
-impl<'tcx, I: IntoIterator> DoubleEndedIterator for SubstIter<'_, 'tcx, I>
+impl<'tcx, I: IntoIterator> DoubleEndedIterator for ArgIter<'_, 'tcx, I>
 where
     I::IntoIter: DoubleEndedIterator,
     I::Item: TypeFoldable<TyCtxt<'tcx>>,
 {
     fn next_back(&mut self) -> Option<Self::Item> {
-        Some(EarlyBinder { value: self.it.next_back()? }.subst(self.tcx, self.substs))
+        Some(EarlyBinder { value: self.it.next_back()? }.instantiate(self.tcx, self.args))
     }
 }
 
-impl<'tcx, I: IntoIterator> ExactSizeIterator for SubstIter<'_, 'tcx, I>
+impl<'tcx, I: IntoIterator> ExactSizeIterator for ArgIter<'_, 'tcx, I>
 where
     I::IntoIter: ExactSizeIterator,
     I::Item: TypeFoldable<TyCtxt<'tcx>>,
@@ -667,28 +664,30 @@ where
     I::Item: Deref,
     <I::Item as Deref>::Target: Copy + TypeFoldable<TyCtxt<'tcx>>,
 {
-    pub fn subst_iter_copied(
+    pub fn arg_iter_copied(
         self,
         tcx: TyCtxt<'tcx>,
-        substs: &'s [GenericArg<'tcx>],
-    ) -> SubstIterCopied<'s, 'tcx, I> {
-        SubstIterCopied { it: self.value.into_iter(), tcx, substs }
+        args: &'s [GenericArg<'tcx>],
+    ) -> ArgIterCopied<'s, 'tcx, I> {
+        ArgIterCopied { it: self.value.into_iter(), tcx, args }
     }
 
-    /// Similar to [`subst_identity`](EarlyBinder::subst_identity),
+    /// Similar to [`instantiate_identity`](EarlyBinder::instantiate_identity),
     /// but on an iterator of values that deref to a `TypeFoldable`.
-    pub fn subst_identity_iter_copied(self) -> impl Iterator<Item = <I::Item as Deref>::Target> {
+    pub fn instantiate_identity_iter_copied(
+        self,
+    ) -> impl Iterator<Item = <I::Item as Deref>::Target> {
         self.value.into_iter().map(|v| *v)
     }
 }
 
-pub struct SubstIterCopied<'a, 'tcx, I: IntoIterator> {
+pub struct ArgIterCopied<'a, 'tcx, I: IntoIterator> {
     it: I::IntoIter,
     tcx: TyCtxt<'tcx>,
-    substs: &'a [GenericArg<'tcx>],
+    args: &'a [GenericArg<'tcx>],
 }
 
-impl<'tcx, I: IntoIterator> Iterator for SubstIterCopied<'_, 'tcx, I>
+impl<'tcx, I: IntoIterator> Iterator for ArgIterCopied<'_, 'tcx, I>
 where
     I::Item: Deref,
     <I::Item as Deref>::Target: Copy + TypeFoldable<TyCtxt<'tcx>>,
@@ -696,7 +695,7 @@ where
     type Item = <I::Item as Deref>::Target;
 
     fn next(&mut self) -> Option<Self::Item> {
-        self.it.next().map(|value| EarlyBinder { value: *value }.subst(self.tcx, self.substs))
+        self.it.next().map(|value| EarlyBinder { value: *value }.instantiate(self.tcx, self.args))
     }
 
     fn size_hint(&self) -> (usize, Option<usize>) {
@@ -704,18 +703,20 @@ where
     }
 }
 
-impl<'tcx, I: IntoIterator> DoubleEndedIterator for SubstIterCopied<'_, 'tcx, I>
+impl<'tcx, I: IntoIterator> DoubleEndedIterator for ArgIterCopied<'_, 'tcx, I>
 where
     I::IntoIter: DoubleEndedIterator,
     I::Item: Deref,
     <I::Item as Deref>::Target: Copy + TypeFoldable<TyCtxt<'tcx>>,
 {
     fn next_back(&mut self) -> Option<Self::Item> {
-        self.it.next_back().map(|value| EarlyBinder { value: *value }.subst(self.tcx, self.substs))
+        self.it
+            .next_back()
+            .map(|value| EarlyBinder { value: *value }.instantiate(self.tcx, self.args))
     }
 }
 
-impl<'tcx, I: IntoIterator> ExactSizeIterator for SubstIterCopied<'_, 'tcx, I>
+impl<'tcx, I: IntoIterator> ExactSizeIterator for ArgIterCopied<'_, 'tcx, I>
 where
     I::IntoIter: ExactSizeIterator,
     I::Item: Deref,
@@ -746,20 +747,20 @@ impl<T: Iterator> Iterator for EarlyBinderIter<T> {
 }
 
 impl<'tcx, T: TypeFoldable<TyCtxt<'tcx>>> ty::EarlyBinder<T> {
-    pub fn subst(self, tcx: TyCtxt<'tcx>, substs: &[GenericArg<'tcx>]) -> T {
-        let mut folder = SubstFolder { tcx, substs, binders_passed: 0 };
+    pub fn instantiate(self, tcx: TyCtxt<'tcx>, args: &[GenericArg<'tcx>]) -> T {
+        let mut folder = ArgFolder { tcx, args, binders_passed: 0 };
         self.value.fold_with(&mut folder)
     }
 
-    /// Makes the identity substitution `T0 => T0, ..., TN => TN`.
+    /// Makes the identity replacement `T0 => T0, ..., TN => TN`.
     /// Conceptually, this converts universally bound variables into placeholders
     /// when inside of a given item.
     ///
     /// For example, consider `for<T> fn foo<T>(){ .. }`:
     /// - Outside of `foo`, `T` is bound (represented by the presence of `EarlyBinder`).
     /// - Inside of the body of `foo`, we treat `T` as a placeholder by calling
-    /// `subst_identity` to discharge the `EarlyBinder`.
-    pub fn subst_identity(self) -> T {
+    /// `instantiate_identity` to discharge the `EarlyBinder`.
+    pub fn instantiate_identity(self) -> T {
         self.value
     }
 
@@ -772,15 +773,15 @@ impl<'tcx, T: TypeFoldable<TyCtxt<'tcx>>> ty::EarlyBinder<T> {
 ///////////////////////////////////////////////////////////////////////////
 // The actual substitution engine itself is a type folder.
 
-struct SubstFolder<'a, 'tcx> {
+struct ArgFolder<'a, 'tcx> {
     tcx: TyCtxt<'tcx>,
-    substs: &'a [GenericArg<'tcx>],
+    args: &'a [GenericArg<'tcx>],
 
     /// Number of region binders we have passed through while doing the substitution
     binders_passed: u32,
 }
 
-impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for SubstFolder<'a, 'tcx> {
+impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for ArgFolder<'a, 'tcx> {
     #[inline]
     fn interner(&self) -> TyCtxt<'tcx> {
         self.tcx
@@ -799,12 +800,12 @@ impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for SubstFolder<'a, 'tcx> {
     fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
         #[cold]
         #[inline(never)]
-        fn region_param_out_of_range(data: ty::EarlyBoundRegion, substs: &[GenericArg<'_>]) -> ! {
+        fn region_param_out_of_range(data: ty::EarlyBoundRegion, args: &[GenericArg<'_>]) -> ! {
             bug!(
-                "Region parameter out of range when substituting in region {} (index={}, substs = {:?})",
+                "Region parameter out of range when substituting in region {} (index={}, args = {:?})",
                 data.name,
                 data.index,
-                substs,
+                args,
             )
         }
 
@@ -826,11 +827,11 @@ impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for SubstFolder<'a, 'tcx> {
         // the specialized routine `ty::replace_late_regions()`.
         match *r {
             ty::ReEarlyBound(data) => {
-                let rk = self.substs.get(data.index as usize).map(|k| k.unpack());
+                let rk = self.args.get(data.index as usize).map(|k| k.unpack());
                 match rk {
                     Some(GenericArgKind::Lifetime(lt)) => self.shift_region_through_binders(lt),
                     Some(other) => region_param_invalid(data, other),
-                    None => region_param_out_of_range(data, self.substs),
+                    None => region_param_out_of_range(data, self.args),
                 }
             }
             ty::ReLateBound(..)
@@ -863,10 +864,10 @@ impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for SubstFolder<'a, 'tcx> {
     }
 }
 
-impl<'a, 'tcx> SubstFolder<'a, 'tcx> {
+impl<'a, 'tcx> ArgFolder<'a, 'tcx> {
     fn ty_for_param(&self, p: ty::ParamTy, source_ty: Ty<'tcx>) -> Ty<'tcx> {
-        // Look up the type in the substitutions. It really should be in there.
-        let opt_ty = self.substs.get(p.index as usize).map(|k| k.unpack());
+        // Look up the type in the args. It really should be in there.
+        let opt_ty = self.args.get(p.index as usize).map(|k| k.unpack());
         let ty = match opt_ty {
             Some(GenericArgKind::Type(ty)) => ty,
             Some(kind) => self.type_param_expected(p, source_ty, kind),
@@ -880,12 +881,12 @@ impl<'a, 'tcx> SubstFolder<'a, 'tcx> {
     #[inline(never)]
     fn type_param_expected(&self, p: ty::ParamTy, ty: Ty<'tcx>, kind: GenericArgKind<'tcx>) -> ! {
         bug!(
-            "expected type for `{:?}` ({:?}/{}) but found {:?} when substituting, substs={:?}",
+            "expected type for `{:?}` ({:?}/{}) but found {:?} when substituting, args={:?}",
             p,
             ty,
             p.index,
             kind,
-            self.substs,
+            self.args,
         )
     }
 
@@ -893,17 +894,17 @@ impl<'a, 'tcx> SubstFolder<'a, 'tcx> {
     #[inline(never)]
     fn type_param_out_of_range(&self, p: ty::ParamTy, ty: Ty<'tcx>) -> ! {
         bug!(
-            "type parameter `{:?}` ({:?}/{}) out of range when substituting, substs={:?}",
+            "type parameter `{:?}` ({:?}/{}) out of range when substituting, args={:?}",
             p,
             ty,
             p.index,
-            self.substs,
+            self.args,
         )
     }
 
     fn const_for_param(&self, p: ParamConst, source_ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
-        // Look up the const in the substitutions. It really should be in there.
-        let opt_ct = self.substs.get(p.index as usize).map(|k| k.unpack());
+        // Look up the const in the args. It really should be in there.
+        let opt_ct = self.args.get(p.index as usize).map(|k| k.unpack());
         let ct = match opt_ct {
             Some(GenericArgKind::Const(ct)) => ct,
             Some(kind) => self.const_param_expected(p, source_ct, kind),
@@ -922,12 +923,12 @@ impl<'a, 'tcx> SubstFolder<'a, 'tcx> {
         kind: GenericArgKind<'tcx>,
     ) -> ! {
         bug!(
-            "expected const for `{:?}` ({:?}/{}) but found {:?} when substituting substs={:?}",
+            "expected const for `{:?}` ({:?}/{}) but found {:?} when substituting args={:?}",
             p,
             ct,
             p.index,
             kind,
-            self.substs,
+            self.args,
         )
     }
 
@@ -935,11 +936,11 @@ impl<'a, 'tcx> SubstFolder<'a, 'tcx> {
     #[inline(never)]
     fn const_param_out_of_range(&self, p: ty::ParamConst, ct: ty::Const<'tcx>) -> ! {
         bug!(
-            "const parameter `{:?}` ({:?}/{}) out of range when substituting substs={:?}",
+            "const parameter `{:?}` ({:?}/{}) out of range when substituting args={:?}",
             p,
             ct,
             p.index,
-            self.substs,
+            self.args,
         )
     }
 
@@ -1011,13 +1012,13 @@ impl<'a, 'tcx> SubstFolder<'a, 'tcx> {
     }
 }
 
-/// Stores the user-given substs to reach some fully qualified path
+/// Stores the user-given args to reach some fully qualified path
 /// (e.g., `<T>::Item` or `<T as Trait>::Item`).
 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
 #[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
-pub struct UserSubsts<'tcx> {
-    /// The substitutions for the item as given by the user.
-    pub substs: SubstsRef<'tcx>,
+pub struct UserArgs<'tcx> {
+    /// The args for the item as given by the user.
+    pub args: GenericArgsRef<'tcx>,
 
     /// The self type, in the case of a `<T>::Item` path (when applied
     /// to an inherent impl). See `UserSelfTy` below.
@@ -1037,7 +1038,7 @@ pub struct UserSubsts<'tcx> {
 /// when you then have a path like `<Foo<&'static u32>>::method`,
 /// this struct would carry the `DefId` of the impl along with the
 /// self type `Foo<u32>`. Then we can instantiate the parameters of
-/// the impl (with the substs from `UserSubsts`) and apply those to
+/// the impl (with the args from `UserArgs`) and apply those to
 /// the self type, giving `Foo<?A>`. Finally, we unify that with
 /// the self type here, which contains `?A` to be `&'static u32`
 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs
index 6c7125c4cb7..338590717d0 100644
--- a/compiler/rustc_middle/src/ty/generics.rs
+++ b/compiler/rustc_middle/src/ty/generics.rs
@@ -1,5 +1,5 @@
 use crate::ty;
-use crate::ty::{EarlyBinder, SubstsRef};
+use crate::ty::{EarlyBinder, GenericArgsRef};
 use rustc_ast as ast;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_hir::def_id::DefId;
@@ -97,14 +97,14 @@ impl GenericParamDef {
     pub fn to_error<'tcx>(
         &self,
         tcx: TyCtxt<'tcx>,
-        preceding_substs: &[ty::GenericArg<'tcx>],
+        preceding_args: &[ty::GenericArg<'tcx>],
     ) -> ty::GenericArg<'tcx> {
         match &self.kind {
             ty::GenericParamDefKind::Lifetime => ty::Region::new_error_misc(tcx).into(),
             ty::GenericParamDefKind::Type { .. } => Ty::new_misc_error(tcx).into(),
             ty::GenericParamDefKind::Const { .. } => ty::Const::new_misc_error(
                 tcx,
-                tcx.type_of(self.def_id).subst(tcx, preceding_substs),
+                tcx.type_of(self.def_id).instantiate(tcx, preceding_args),
             )
             .into(),
         }
@@ -136,7 +136,7 @@ pub struct Generics {
     pub has_self: bool,
     pub has_late_bound_regions: Option<Span>,
 
-    // The index of the host effect when substituted. (i.e. might be index to parent substs)
+    // The index of the host effect when substituted. (i.e. might be index to parent args)
     pub host_effect_index: Option<usize>,
 }
 
@@ -278,14 +278,14 @@ impl<'tcx> Generics {
         })
     }
 
-    /// Returns the substs corresponding to the generic parameters
+    /// Returns the args corresponding to the generic parameters
     /// of this item, excluding `Self`.
     ///
     /// **This should only be used for diagnostics purposes.**
-    pub fn own_substs_no_defaults(
+    pub fn own_args_no_defaults(
         &'tcx self,
         tcx: TyCtxt<'tcx>,
-        substs: &'tcx [ty::GenericArg<'tcx>],
+        args: &'tcx [ty::GenericArg<'tcx>],
     ) -> &'tcx [ty::GenericArg<'tcx>] {
         let mut own_params = self.parent_count..self.count();
         if self.has_self && self.parent.is_none() {
@@ -304,22 +304,22 @@ impl<'tcx> Generics {
             .rev()
             .take_while(|param| {
                 param.default_value(tcx).is_some_and(|default| {
-                    default.subst(tcx, substs) == substs[param.index as usize]
+                    default.instantiate(tcx, args) == args[param.index as usize]
                 })
             })
             .count();
 
-        &substs[own_params]
+        &args[own_params]
     }
 
-    /// Returns the substs corresponding to the generic parameters of this item, excluding `Self`.
+    /// Returns the args corresponding to the generic parameters of this item, excluding `Self`.
     ///
     /// **This should only be used for diagnostics purposes.**
-    pub fn own_substs(
+    pub fn own_args(
         &'tcx self,
-        substs: &'tcx [ty::GenericArg<'tcx>],
+        args: &'tcx [ty::GenericArg<'tcx>],
     ) -> &'tcx [ty::GenericArg<'tcx>] {
-        let own = &substs[self.parent_count..][..self.params.len()];
+        let own = &args[self.parent_count..][..self.params.len()];
         if self.has_self && self.parent.is_none() { &own[1..] } else { &own }
     }
 }
@@ -335,19 +335,19 @@ impl<'tcx> GenericPredicates<'tcx> {
     pub fn instantiate(
         &self,
         tcx: TyCtxt<'tcx>,
-        substs: SubstsRef<'tcx>,
+        args: GenericArgsRef<'tcx>,
     ) -> InstantiatedPredicates<'tcx> {
         let mut instantiated = InstantiatedPredicates::empty();
-        self.instantiate_into(tcx, &mut instantiated, substs);
+        self.instantiate_into(tcx, &mut instantiated, args);
         instantiated
     }
 
     pub fn instantiate_own(
         &self,
         tcx: TyCtxt<'tcx>,
-        substs: SubstsRef<'tcx>,
+        args: GenericArgsRef<'tcx>,
     ) -> impl Iterator<Item = (Clause<'tcx>, Span)> + DoubleEndedIterator + ExactSizeIterator {
-        EarlyBinder::bind(self.predicates).subst_iter_copied(tcx, substs)
+        EarlyBinder::bind(self.predicates).arg_iter_copied(tcx, args)
     }
 
     #[instrument(level = "debug", skip(self, tcx))]
@@ -355,14 +355,14 @@ impl<'tcx> GenericPredicates<'tcx> {
         &self,
         tcx: TyCtxt<'tcx>,
         instantiated: &mut InstantiatedPredicates<'tcx>,
-        substs: SubstsRef<'tcx>,
+        args: GenericArgsRef<'tcx>,
     ) {
         if let Some(def_id) = self.parent {
-            tcx.predicates_of(def_id).instantiate_into(tcx, instantiated, substs);
+            tcx.predicates_of(def_id).instantiate_into(tcx, instantiated, args);
         }
-        instantiated
-            .predicates
-            .extend(self.predicates.iter().map(|(p, _)| EarlyBinder::bind(*p).subst(tcx, substs)));
+        instantiated.predicates.extend(
+            self.predicates.iter().map(|(p, _)| EarlyBinder::bind(*p).instantiate(tcx, args)),
+        );
         instantiated.spans.extend(self.predicates.iter().map(|(_, sp)| *sp));
     }
 
diff --git a/compiler/rustc_middle/src/ty/impls_ty.rs b/compiler/rustc_middle/src/ty/impls_ty.rs
index 02baa395c3c..b03874a90e8 100644
--- a/compiler/rustc_middle/src/ty/impls_ty.rs
+++ b/compiler/rustc_middle/src/ty/impls_ty.rs
@@ -67,7 +67,7 @@ impl<'a> ToStableHashKey<StableHashingContext<'a>> for SimplifiedType {
     }
 }
 
-impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for ty::subst::GenericArg<'tcx> {
+impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for ty::GenericArg<'tcx> {
     fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
         self.unpack().hash_stable(hcx, hasher);
     }
diff --git a/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs b/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs
index 295cb146461..f278cace99d 100644
--- a/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs
+++ b/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs
@@ -19,7 +19,7 @@ pub enum InhabitedPredicate<'tcx> {
     /// type has restricted visibility.
     NotInModule(DefId),
     /// Inhabited if some generic type is inhabited.
-    /// These are replaced by calling [`Self::subst`].
+    /// These are replaced by calling [`Self::instantiate`].
     GenericType(Ty<'tcx>),
     /// A AND B
     And(&'tcx [InhabitedPredicate<'tcx>; 2]),
@@ -162,14 +162,14 @@ impl<'tcx> InhabitedPredicate<'tcx> {
     }
 
     /// Replaces generic types with its corresponding predicate
-    pub fn subst(self, tcx: TyCtxt<'tcx>, substs: ty::SubstsRef<'tcx>) -> Self {
-        self.subst_opt(tcx, substs).unwrap_or(self)
+    pub fn instantiate(self, tcx: TyCtxt<'tcx>, args: ty::GenericArgsRef<'tcx>) -> Self {
+        self.instantiate_opt(tcx, args).unwrap_or(self)
     }
 
-    fn subst_opt(self, tcx: TyCtxt<'tcx>, substs: ty::SubstsRef<'tcx>) -> Option<Self> {
+    fn instantiate_opt(self, tcx: TyCtxt<'tcx>, args: ty::GenericArgsRef<'tcx>) -> Option<Self> {
         match self {
             Self::ConstIsZero(c) => {
-                let c = ty::EarlyBinder::bind(c).subst(tcx, substs);
+                let c = ty::EarlyBinder::bind(c).instantiate(tcx, args);
                 let pred = match c.try_to_target_usize(tcx) {
                     Some(0) => Self::True,
                     Some(1..) => Self::False,
@@ -178,17 +178,17 @@ impl<'tcx> InhabitedPredicate<'tcx> {
                 Some(pred)
             }
             Self::GenericType(t) => {
-                Some(ty::EarlyBinder::bind(t).subst(tcx, substs).inhabited_predicate(tcx))
+                Some(ty::EarlyBinder::bind(t).instantiate(tcx, args).inhabited_predicate(tcx))
             }
-            Self::And(&[a, b]) => match a.subst_opt(tcx, substs) {
-                None => b.subst_opt(tcx, substs).map(|b| a.and(tcx, b)),
+            Self::And(&[a, b]) => match a.instantiate_opt(tcx, args) {
+                None => b.instantiate_opt(tcx, args).map(|b| a.and(tcx, b)),
                 Some(InhabitedPredicate::False) => Some(InhabitedPredicate::False),
-                Some(a) => Some(a.and(tcx, b.subst_opt(tcx, substs).unwrap_or(b))),
+                Some(a) => Some(a.and(tcx, b.instantiate_opt(tcx, args).unwrap_or(b))),
             },
-            Self::Or(&[a, b]) => match a.subst_opt(tcx, substs) {
-                None => b.subst_opt(tcx, substs).map(|b| a.or(tcx, b)),
+            Self::Or(&[a, b]) => match a.instantiate_opt(tcx, args) {
+                None => b.instantiate_opt(tcx, args).map(|b| a.or(tcx, b)),
                 Some(InhabitedPredicate::True) => Some(InhabitedPredicate::True),
-                Some(a) => Some(a.or(tcx, b.subst_opt(tcx, substs).unwrap_or(b))),
+                Some(a) => Some(a.or(tcx, b.instantiate_opt(tcx, args).unwrap_or(b))),
             },
             _ => None,
         }
diff --git a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs
index b92d84152b4..4dac6891b30 100644
--- a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs
+++ b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs
@@ -58,7 +58,7 @@ pub(crate) fn provide(providers: &mut Providers) {
 }
 
 /// Returns an `InhabitedPredicate` that is generic over type parameters and
-/// requires calling [`InhabitedPredicate::subst`]
+/// requires calling [`InhabitedPredicate::instantiate`]
 fn inhabited_predicate_adt(tcx: TyCtxt<'_>, def_id: DefId) -> InhabitedPredicate<'_> {
     if let Some(def_id) = def_id.as_local() {
         if matches!(tcx.representability(def_id), ty::Representability::Infinite) {
@@ -87,7 +87,7 @@ impl<'tcx> VariantDef {
         InhabitedPredicate::all(
             tcx,
             self.fields.iter().map(|field| {
-                let pred = tcx.type_of(field.did).subst_identity().inhabited_predicate(tcx);
+                let pred = tcx.type_of(field.did).instantiate_identity().inhabited_predicate(tcx);
                 if adt.is_enum() {
                     return pred;
                 }
@@ -114,8 +114,8 @@ impl<'tcx> Ty<'tcx> {
             Never => InhabitedPredicate::False,
             Param(_) | Alias(ty::Projection, _) => InhabitedPredicate::GenericType(self),
             // FIXME(inherent_associated_types): Most likely we can just map to `GenericType` like above.
-            // However it's unclear if the substs passed to `InhabitedPredicate::subst` are of the correct
-            // format, i.e. don't contain parent substs. If you hit this case, please verify this beforehand.
+            // However it's unclear if the args passed to `InhabitedPredicate::instantiate` are of the correct
+            // format, i.e. don't contain parent args. If you hit this case, please verify this beforehand.
             Alias(ty::Inherent, _) => {
                 bug!("unimplemented: inhabitedness checking for inherent projections")
             }
@@ -189,7 +189,7 @@ impl<'tcx> Ty<'tcx> {
 /// N.B. this query should only be called through `Ty::inhabited_predicate`
 fn inhabited_predicate_type<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> InhabitedPredicate<'tcx> {
     match *ty.kind() {
-        Adt(adt, substs) => tcx.inhabited_predicate_adt(adt.did()).subst(tcx, substs),
+        Adt(adt, args) => tcx.inhabited_predicate_adt(adt.did()).instantiate(tcx, args),
 
         Tuple(tys) => {
             InhabitedPredicate::all(tcx, tys.iter().map(|ty| ty.inhabited_predicate(tcx)))
diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs
index ae57e954ff4..48e88daa890 100644
--- a/compiler/rustc_middle/src/ty/instance.rs
+++ b/compiler/rustc_middle/src/ty/instance.rs
@@ -1,7 +1,7 @@
 use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use crate::ty::print::{FmtPrinter, Printer};
 use crate::ty::{self, Ty, TyCtxt, TypeFoldable, TypeSuperFoldable};
-use crate::ty::{EarlyBinder, InternalSubsts, SubstsRef, TypeVisitableExt};
+use crate::ty::{EarlyBinder, GenericArgs, GenericArgsRef, TypeVisitableExt};
 use rustc_errors::ErrorGuaranteed;
 use rustc_hir::def::Namespace;
 use rustc_hir::def_id::{CrateNum, DefId};
@@ -16,13 +16,13 @@ use std::fmt;
 /// A monomorphized `InstanceDef`.
 ///
 /// Monomorphization happens on-the-fly and no monomorphized MIR is ever created. Instead, this type
-/// simply couples a potentially generic `InstanceDef` with some substs, and codegen and const eval
+/// simply couples a potentially generic `InstanceDef` with some args, and codegen and const eval
 /// will do all required substitution as they run.
 #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable)]
 #[derive(HashStable, Lift, TypeFoldable, TypeVisitable)]
 pub struct Instance<'tcx> {
     pub def: InstanceDef<'tcx>,
-    pub substs: SubstsRef<'tcx>,
+    pub args: GenericArgsRef<'tcx>,
 }
 
 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
@@ -115,7 +115,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.args, param_env, ty)
     }
 
     /// Finds a crate that contains a monomorphization of this instance that
@@ -139,13 +139,13 @@ impl<'tcx> Instance<'tcx> {
         }
 
         // If this a non-generic instance, it cannot be a shared monomorphization.
-        self.substs.non_erasable_generics().next()?;
+        self.args.non_erasable_generics().next()?;
 
         match self.def {
             InstanceDef::Item(def) => tcx
                 .upstream_monomorphizations_for(def)
-                .and_then(|monos| monos.get(&self.substs).cloned()),
-            InstanceDef::DropGlue(_, Some(_)) => tcx.upstream_drop_glue_for(self.substs),
+                .and_then(|monos| monos.get(&self.args).cloned()),
+            InstanceDef::DropGlue(_, Some(_)) => tcx.upstream_drop_glue_for(self.args),
             _ => None,
         }
     }
@@ -265,8 +265,8 @@ impl<'tcx> InstanceDef<'tcx> {
     }
 
     /// Returns `true` when the MIR body associated with this instance should be monomorphized
-    /// by its users (e.g. codegen or miri) by substituting the `substs` from `Instance` (see
-    /// `Instance::substs_for_mir_body`).
+    /// by its users (e.g. codegen or miri) by substituting the `args` from `Instance` (see
+    /// `Instance::args_for_mir_body`).
     ///
     /// Otherwise, returns `false` only for some kinds of shims where the construction of the MIR
     /// body should perform necessary substitutions.
@@ -294,10 +294,10 @@ fn fmt_instance(
     type_length: rustc_session::Limit,
 ) -> fmt::Result {
     ty::tls::with(|tcx| {
-        let substs = tcx.lift(instance.substs).expect("could not lift for printing");
+        let args = tcx.lift(instance.args).expect("could not lift for printing");
 
         let s = FmtPrinter::new_with_limit(tcx, Namespace::ValueNS, type_length)
-            .print_def_path(instance.def_id(), substs)?
+            .print_def_path(instance.def_id(), args)?
             .into_buffer();
         f.write_str(&s)
     })?;
@@ -333,18 +333,18 @@ impl<'tcx> fmt::Display for Instance<'tcx> {
 }
 
 impl<'tcx> Instance<'tcx> {
-    pub fn new(def_id: DefId, substs: SubstsRef<'tcx>) -> Instance<'tcx> {
+    pub fn new(def_id: DefId, args: GenericArgsRef<'tcx>) -> Instance<'tcx> {
         assert!(
-            !substs.has_escaping_bound_vars(),
-            "substs of instance {:?} not normalized for codegen: {:?}",
+            !args.has_escaping_bound_vars(),
+            "args of instance {:?} not normalized for codegen: {:?}",
             def_id,
-            substs
+            args
         );
-        Instance { def: InstanceDef::Item(def_id), substs }
+        Instance { def: InstanceDef::Item(def_id), args }
     }
 
     pub fn mono(tcx: TyCtxt<'tcx>, def_id: DefId) -> Instance<'tcx> {
-        let substs = InternalSubsts::for_item(tcx, def_id, |param, _| match param.kind {
+        let args = GenericArgs::for_item(tcx, def_id, |param, _| match param.kind {
             ty::GenericParamDefKind::Lifetime => tcx.lifetimes.re_erased.into(),
             ty::GenericParamDefKind::Type { .. } => {
                 bug!("Instance::mono: {:?} has type parameters", def_id)
@@ -354,7 +354,7 @@ impl<'tcx> Instance<'tcx> {
             }
         });
 
-        Instance::new(def_id, substs)
+        Instance::new(def_id, args)
     }
 
     #[inline]
@@ -362,7 +362,7 @@ impl<'tcx> Instance<'tcx> {
         self.def.def_id()
     }
 
-    /// Resolves a `(def_id, substs)` pair to an (optional) instance -- most commonly,
+    /// Resolves a `(def_id, args)` pair to an (optional) instance -- most commonly,
     /// this is used to find the precise code that will run for a trait method invocation,
     /// if known.
     ///
@@ -390,29 +390,29 @@ impl<'tcx> Instance<'tcx> {
         tcx: TyCtxt<'tcx>,
         param_env: ty::ParamEnv<'tcx>,
         def_id: DefId,
-        substs: SubstsRef<'tcx>,
+        args: GenericArgsRef<'tcx>,
     ) -> Result<Option<Instance<'tcx>>, ErrorGuaranteed> {
         // All regions in the result of this query are erased, so it's
         // fine to erase all of the input regions.
 
-        // HACK(eddyb) erase regions in `substs` first, so that `param_env.and(...)`
+        // HACK(eddyb) erase regions in `args` first, so that `param_env.and(...)`
         // below is more likely to ignore the bounds in scope (e.g. if the only
-        // generic parameters mentioned by `substs` were lifetime ones).
-        let substs = tcx.erase_regions(substs);
-        tcx.resolve_instance(tcx.erase_regions(param_env.and((def_id, substs))))
+        // generic parameters mentioned by `args` were lifetime ones).
+        let args = tcx.erase_regions(args);
+        tcx.resolve_instance(tcx.erase_regions(param_env.and((def_id, args))))
     }
 
     pub fn expect_resolve(
         tcx: TyCtxt<'tcx>,
         param_env: ty::ParamEnv<'tcx>,
         def_id: DefId,
-        substs: SubstsRef<'tcx>,
+        args: GenericArgsRef<'tcx>,
     ) -> Instance<'tcx> {
-        match ty::Instance::resolve(tcx, param_env, def_id, substs) {
+        match ty::Instance::resolve(tcx, param_env, def_id, args) {
             Ok(Some(instance)) => instance,
             instance => bug!(
                 "failed to resolve instance for {}: {instance:#?}",
-                tcx.def_path_str_with_substs(def_id, substs)
+                tcx.def_path_str_with_args(def_id, args)
             ),
         }
     }
@@ -421,12 +421,12 @@ impl<'tcx> Instance<'tcx> {
         tcx: TyCtxt<'tcx>,
         param_env: ty::ParamEnv<'tcx>,
         def_id: DefId,
-        substs: SubstsRef<'tcx>,
+        args: GenericArgsRef<'tcx>,
     ) -> Option<Instance<'tcx>> {
-        debug!("resolve(def_id={:?}, substs={:?})", def_id, substs);
+        debug!("resolve(def_id={:?}, args={:?})", def_id, args);
         // Use either `resolve_closure` or `resolve_for_vtable`
         assert!(!tcx.is_closure(def_id), "Called `resolve_for_fn_ptr` on closure: {:?}", def_id);
-        Instance::resolve(tcx, param_env, def_id, substs).ok().flatten().map(|mut resolved| {
+        Instance::resolve(tcx, param_env, def_id, args).ok().flatten().map(|mut resolved| {
             match resolved.def {
                 InstanceDef::Item(def) if resolved.def.requires_caller_location(tcx) => {
                     debug!(" => fn pointer created for function with #[track_caller]");
@@ -447,18 +447,18 @@ impl<'tcx> Instance<'tcx> {
         tcx: TyCtxt<'tcx>,
         param_env: ty::ParamEnv<'tcx>,
         def_id: DefId,
-        substs: SubstsRef<'tcx>,
+        args: GenericArgsRef<'tcx>,
     ) -> Option<Instance<'tcx>> {
-        debug!("resolve_for_vtable(def_id={:?}, substs={:?})", def_id, substs);
-        let fn_sig = tcx.fn_sig(def_id).subst_identity();
+        debug!("resolve_for_vtable(def_id={:?}, args={:?})", def_id, args);
+        let fn_sig = tcx.fn_sig(def_id).instantiate_identity();
         let is_vtable_shim = !fn_sig.inputs().skip_binder().is_empty()
             && fn_sig.input(0).skip_binder().is_param(0)
             && tcx.generics_of(def_id).has_self;
         if is_vtable_shim {
             debug!(" => associated item with unsizeable self: Self");
-            Some(Instance { def: InstanceDef::VTableShim(def_id), substs })
+            Some(Instance { def: InstanceDef::VTableShim(def_id), args })
         } else {
-            Instance::resolve(tcx, param_env, def_id, substs).ok().flatten().map(|mut resolved| {
+            Instance::resolve(tcx, param_env, def_id, args).ok().flatten().map(|mut resolved| {
                 match resolved.def {
                     InstanceDef::Item(def) => {
                         // We need to generate a shim when we cannot guarantee that
@@ -489,12 +489,12 @@ impl<'tcx> Instance<'tcx> {
                         {
                             if tcx.is_closure(def) {
                                 debug!(" => vtable fn pointer created for closure with #[track_caller]: {:?} for method {:?} {:?}",
-                                       def, def_id, substs);
+                                       def, def_id, args);
 
                                 // Create a shim for the `FnOnce/FnMut/Fn` method we are calling
                                 // - unlike functions, invoking a closure always goes through a
                                 // trait.
-                                resolved = Instance { def: InstanceDef::ReifyShim(def_id), substs };
+                                resolved = Instance { def: InstanceDef::ReifyShim(def_id), args };
                             } else {
                                 debug!(
                                     " => vtable fn pointer created for function with #[track_caller]: {:?}", def
@@ -518,28 +518,28 @@ impl<'tcx> Instance<'tcx> {
     pub fn resolve_closure(
         tcx: TyCtxt<'tcx>,
         def_id: DefId,
-        substs: ty::SubstsRef<'tcx>,
+        args: ty::GenericArgsRef<'tcx>,
         requested_kind: ty::ClosureKind,
     ) -> Option<Instance<'tcx>> {
-        let actual_kind = substs.as_closure().kind();
+        let actual_kind = args.as_closure().kind();
 
         match needs_fn_once_adapter_shim(actual_kind, requested_kind) {
-            Ok(true) => Instance::fn_once_adapter_instance(tcx, def_id, substs),
-            _ => Some(Instance::new(def_id, substs)),
+            Ok(true) => Instance::fn_once_adapter_instance(tcx, def_id, args),
+            _ => Some(Instance::new(def_id, args)),
         }
     }
 
     pub fn resolve_drop_in_place(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> ty::Instance<'tcx> {
         let def_id = tcx.require_lang_item(LangItem::DropInPlace, None);
-        let substs = tcx.mk_substs(&[ty.into()]);
-        Instance::expect_resolve(tcx, ty::ParamEnv::reveal_all(), def_id, substs)
+        let args = tcx.mk_args(&[ty.into()]);
+        Instance::expect_resolve(tcx, ty::ParamEnv::reveal_all(), def_id, args)
     }
 
     #[instrument(level = "debug", skip(tcx), ret)]
     pub fn fn_once_adapter_instance(
         tcx: TyCtxt<'tcx>,
         closure_did: DefId,
-        substs: ty::SubstsRef<'tcx>,
+        args: ty::GenericArgsRef<'tcx>,
     ) -> Option<Instance<'tcx>> {
         let fn_once = tcx.require_lang_item(LangItem::FnOnce, None);
         let call_once = tcx
@@ -552,30 +552,30 @@ impl<'tcx> Instance<'tcx> {
             tcx.codegen_fn_attrs(closure_did).flags.contains(CodegenFnAttrFlags::TRACK_CALLER);
         let def = ty::InstanceDef::ClosureOnceShim { call_once, track_caller };
 
-        let self_ty = Ty::new_closure(tcx, closure_did, substs);
+        let self_ty = Ty::new_closure(tcx, closure_did, args);
 
-        let sig = substs.as_closure().sig();
+        let sig = args.as_closure().sig();
         let sig =
             tcx.try_normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), sig).ok()?;
         assert_eq!(sig.inputs().len(), 1);
-        let substs = tcx.mk_substs_trait(self_ty, [sig.inputs()[0].into()]);
+        let args = tcx.mk_args_trait(self_ty, [sig.inputs()[0].into()]);
 
         debug!(?self_ty, ?sig);
-        Some(Instance { def, substs })
+        Some(Instance { def, args })
     }
 
     /// Depending on the kind of `InstanceDef`, the MIR body associated with an
     /// instance is expressed in terms of the generic parameters of `self.def_id()`, and in other
     /// cases the MIR body is expressed in terms of the types found in the substitution array.
     /// In the former case, we want to substitute those generic types and replace them with the
-    /// values from the substs when monomorphizing the function body. But in the latter case, we
+    /// values from the args when monomorphizing the function body. But in the latter case, we
     /// don't want to do that substitution, since it has already been done effectively.
     ///
-    /// This function returns `Some(substs)` in the former case and `None` otherwise -- i.e., if
+    /// This function returns `Some(args)` in the former case and `None` otherwise -- i.e., if
     /// this function returns `None`, then the MIR body does not require substitution during
     /// codegen.
-    fn substs_for_mir_body(&self) -> Option<SubstsRef<'tcx>> {
-        self.def.has_polymorphic_mir_body().then_some(self.substs)
+    fn args_for_mir_body(&self) -> Option<GenericArgsRef<'tcx>> {
+        self.def.has_polymorphic_mir_body().then_some(self.args)
     }
 
     pub fn subst_mir<T>(&self, tcx: TyCtxt<'tcx>, v: EarlyBinder<&T>) -> T
@@ -583,10 +583,10 @@ impl<'tcx> Instance<'tcx> {
         T: TypeFoldable<TyCtxt<'tcx>> + Copy,
     {
         let v = v.map_bound(|v| *v);
-        if let Some(substs) = self.substs_for_mir_body() {
-            v.subst(tcx, substs)
+        if let Some(args) = self.args_for_mir_body() {
+            v.instantiate(tcx, args)
         } else {
-            v.subst_identity()
+            v.instantiate_identity()
         }
     }
 
@@ -600,8 +600,8 @@ impl<'tcx> Instance<'tcx> {
     where
         T: TypeFoldable<TyCtxt<'tcx>> + Clone,
     {
-        if let Some(substs) = self.substs_for_mir_body() {
-            tcx.subst_and_normalize_erasing_regions(substs, param_env, v)
+        if let Some(args) = self.args_for_mir_body() {
+            tcx.subst_and_normalize_erasing_regions(args, param_env, v)
         } else {
             tcx.normalize_erasing_regions(param_env, v.skip_binder())
         }
@@ -617,14 +617,14 @@ impl<'tcx> Instance<'tcx> {
     where
         T: TypeFoldable<TyCtxt<'tcx>> + Clone,
     {
-        if let Some(substs) = self.substs_for_mir_body() {
-            tcx.try_subst_and_normalize_erasing_regions(substs, param_env, v)
+        if let Some(args) = self.args_for_mir_body() {
+            tcx.try_subst_and_normalize_erasing_regions(args, param_env, v)
         } else {
             tcx.try_normalize_erasing_regions(param_env, v.skip_binder())
         }
     }
 
-    /// Returns a new `Instance` where generic parameters in `instance.substs` are replaced by
+    /// Returns a new `Instance` where generic parameters in `instance.args` are replaced by
     /// identity parameters if they are determined to be unused in `instance.def`.
     pub fn polymorphize(self, tcx: TyCtxt<'tcx>) -> Self {
         debug!("polymorphize: running polymorphization analysis");
@@ -632,18 +632,18 @@ impl<'tcx> Instance<'tcx> {
             return self;
         }
 
-        let polymorphized_substs = polymorphize(tcx, self.def, self.substs);
-        debug!("polymorphize: self={:?} polymorphized_substs={:?}", self, polymorphized_substs);
-        Self { def: self.def, substs: polymorphized_substs }
+        let polymorphized_args = polymorphize(tcx, self.def, self.args);
+        debug!("polymorphize: self={:?} polymorphized_args={:?}", self, polymorphized_args);
+        Self { def: self.def, args: polymorphized_args }
     }
 }
 
 fn polymorphize<'tcx>(
     tcx: TyCtxt<'tcx>,
     instance: ty::InstanceDef<'tcx>,
-    substs: SubstsRef<'tcx>,
-) -> SubstsRef<'tcx> {
-    debug!("polymorphize({:?}, {:?})", instance, substs);
+    args: GenericArgsRef<'tcx>,
+) -> GenericArgsRef<'tcx> {
+    debug!("polymorphize({:?}, {:?})", instance, args);
     let unused = tcx.unused_generic_params(instance);
     debug!("polymorphize: unused={:?}", unused);
 
@@ -653,9 +653,9 @@ fn polymorphize<'tcx>(
     // multiple mono items (and eventually symbol clashes).
     let def_id = instance.def_id();
     let upvars_ty = if tcx.is_closure(def_id) {
-        Some(substs.as_closure().tupled_upvars_ty())
+        Some(args.as_closure().tupled_upvars_ty())
     } else if tcx.type_of(def_id).skip_binder().is_generator() {
-        Some(substs.as_generator().tupled_upvars_ty())
+        Some(args.as_generator().tupled_upvars_ty())
     } else {
         None
     };
@@ -674,22 +674,22 @@ fn polymorphize<'tcx>(
         fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
             debug!("fold_ty: ty={:?}", ty);
             match *ty.kind() {
-                ty::Closure(def_id, substs) => {
-                    let polymorphized_substs =
-                        polymorphize(self.tcx, ty::InstanceDef::Item(def_id), substs);
-                    if substs == polymorphized_substs {
+                ty::Closure(def_id, args) => {
+                    let polymorphized_args =
+                        polymorphize(self.tcx, ty::InstanceDef::Item(def_id), args);
+                    if args == polymorphized_args {
                         ty
                     } else {
-                        Ty::new_closure(self.tcx, def_id, polymorphized_substs)
+                        Ty::new_closure(self.tcx, def_id, polymorphized_args)
                     }
                 }
-                ty::Generator(def_id, substs, movability) => {
-                    let polymorphized_substs =
-                        polymorphize(self.tcx, ty::InstanceDef::Item(def_id), substs);
-                    if substs == polymorphized_substs {
+                ty::Generator(def_id, args, movability) => {
+                    let polymorphized_args =
+                        polymorphize(self.tcx, ty::InstanceDef::Item(def_id), args);
+                    if args == polymorphized_args {
                         ty
                     } else {
-                        Ty::new_generator(self.tcx, def_id, polymorphized_substs, movability)
+                        Ty::new_generator(self.tcx, def_id, polymorphized_args, movability)
                     }
                 }
                 _ => ty.super_fold_with(self),
@@ -697,7 +697,7 @@ fn polymorphize<'tcx>(
         }
     }
 
-    InternalSubsts::for_item(tcx, def_id, |param, _| {
+    GenericArgs::for_item(tcx, def_id, |param, _| {
         let is_unused = unused.is_unused(param.index);
         debug!("polymorphize: param={:?} is_unused={:?}", param, is_unused);
         match param.kind {
@@ -706,7 +706,7 @@ fn polymorphize<'tcx>(
                 // ..and has upvars..
                 has_upvars &&
                 // ..and this param has the same type as the tupled upvars..
-                upvars_ty == Some(substs[param.index as usize].expect_ty()) => {
+                upvars_ty == Some(args[param.index as usize].expect_ty()) => {
                     // ..then double-check that polymorphization marked it used..
                     debug_assert!(!is_unused);
                     // ..and polymorphize any closures/generators captured as upvars.
@@ -725,7 +725,7 @@ fn polymorphize<'tcx>(
                     tcx.mk_param_from_def(param),
 
             // Otherwise, use the parameter as before.
-            _ => substs[param.index as usize],
+            _ => args[param.index as usize],
         }
     })
 }
diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs
index d95b05ef754..62805d1e8b5 100644
--- a/compiler/rustc_middle/src/ty/layout.rs
+++ b/compiler/rustc_middle/src/ty/layout.rs
@@ -374,7 +374,7 @@ impl<'tcx> SizeSkeleton<'tcx> {
                 }
             }
 
-            ty::Adt(def, substs) => {
+            ty::Adt(def, args) => {
                 // Only newtypes and enums w/ nullable pointer optimization.
                 if def.is_union() || def.variants().is_empty() || def.variants().len() > 2 {
                     return Err(err);
@@ -385,7 +385,7 @@ impl<'tcx> SizeSkeleton<'tcx> {
                     let i = VariantIdx::from_usize(i);
                     let fields =
                         def.variant(i).fields.iter().map(|field| {
-                            SizeSkeleton::compute(field.ty(tcx, substs), tcx, param_env)
+                            SizeSkeleton::compute(field.ty(tcx, args), tcx, param_env)
                         });
                     let mut ptr = None;
                     for field in fields {
@@ -755,6 +755,8 @@ where
                     largest_niche: None,
                     align: tcx.data_layout.i8_align,
                     size: Size::ZERO,
+                    max_repr_align: None,
+                    unadjusted_abi_align: tcx.data_layout.i8_align.abi,
                 })
             }
 
@@ -861,9 +863,9 @@ where
                         // offers better information than `std::ptr::metadata::VTable`,
                         // and we rely on this layout information to trigger a panic in
                         // `std::mem::uninitialized::<&dyn Trait>()`, for example.
-                        if let ty::Adt(def, substs) = metadata.kind()
+                        if let ty::Adt(def, args) = metadata.kind()
                             && Some(def.did()) == tcx.lang_items().dyn_metadata()
-                            && substs.type_at(0).is_trait()
+                            && args.type_at(0).is_trait()
                         {
                             mk_dyn_vtable()
                         } else {
@@ -885,16 +887,15 @@ where
                 ty::Str => TyMaybeWithLayout::Ty(tcx.types.u8),
 
                 // Tuples, generators and closures.
-                ty::Closure(_, ref substs) => field_ty_or_layout(
-                    TyAndLayout { ty: substs.as_closure().tupled_upvars_ty(), ..this },
+                ty::Closure(_, ref args) => field_ty_or_layout(
+                    TyAndLayout { ty: args.as_closure().tupled_upvars_ty(), ..this },
                     cx,
                     i,
                 ),
 
-                ty::Generator(def_id, ref substs, _) => match this.variants {
+                ty::Generator(def_id, ref args, _) => match this.variants {
                     Variants::Single { index } => TyMaybeWithLayout::Ty(
-                        substs
-                            .as_generator()
+                        args.as_generator()
                             .state_tys(def_id, tcx)
                             .nth(index.as_usize())
                             .unwrap()
@@ -905,18 +906,18 @@ where
                         if i == tag_field {
                             return TyMaybeWithLayout::TyAndLayout(tag_layout(tag));
                         }
-                        TyMaybeWithLayout::Ty(substs.as_generator().prefix_tys().nth(i).unwrap())
+                        TyMaybeWithLayout::Ty(args.as_generator().prefix_tys().nth(i).unwrap())
                     }
                 },
 
                 ty::Tuple(tys) => TyMaybeWithLayout::Ty(tys[i]),
 
                 // ADTs.
-                ty::Adt(def, substs) => {
+                ty::Adt(def, args) => {
                     match this.variants {
                         Variants::Single { index } => {
                             let field = &def.variant(index).fields[FieldIdx::from_usize(i)];
-                            TyMaybeWithLayout::Ty(field.ty(tcx, substs))
+                            TyMaybeWithLayout::Ty(field.ty(tcx, args))
                         }
 
                         // Discriminant field for enums (where applicable).
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 519bdb01623..0411890ab51 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -28,6 +28,7 @@ use crate::ty::fast_reject::SimplifiedType;
 use crate::ty::util::Discr;
 pub use adt::*;
 pub use assoc::*;
+pub use generic_args::*;
 pub use generics::*;
 use rustc_ast as ast;
 use rustc_ast::node_id::NodeMap;
@@ -54,7 +55,6 @@ use rustc_span::{ExpnId, ExpnKind, Span};
 use rustc_target::abi::{Align, FieldIdx, Integer, IntegerType, VariantIdx};
 pub use rustc_target::abi::{ReprFlags, ReprOptions};
 pub use rustc_type_ir::{DebugWithInfcx, InferCtxtLike, OptWithInfcx};
-pub use subst::*;
 pub use vtable::*;
 
 use std::fmt::Debug;
@@ -82,8 +82,7 @@ pub use self::binding::BindingMode::*;
 pub use self::closure::{
     is_ancestor_or_same_capture, place_to_string_for_capture, BorrowKind, CaptureInfo,
     CapturedPlace, ClosureKind, ClosureTypeInfo, MinCaptureInformationMap, MinCaptureList,
-    RootVariableMinCaptureList, UpvarCapture, UpvarCaptureMap, UpvarId, UpvarListMap, UpvarPath,
-    CAPTURE_STRUCT_LOCAL,
+    RootVariableMinCaptureList, UpvarCapture, UpvarId, UpvarPath, CAPTURE_STRUCT_LOCAL,
 };
 pub use self::consts::{
     Const, ConstData, ConstInt, Expr, InferConst, ScalarInt, UnevaluatedConst, ValTree,
@@ -98,12 +97,12 @@ pub use self::rvalue_scopes::RvalueScopes;
 pub use self::sty::BoundRegionKind::*;
 pub use self::sty::{
     AliasTy, Article, Binder, BoundRegion, BoundRegionKind, BoundTy, BoundTyKind, BoundVar,
-    BoundVariableKind, CanonicalPolyFnSig, ClosureSubsts, ClosureSubstsParts, ConstKind, ConstVid,
+    BoundVariableKind, CanonicalPolyFnSig, ClosureArgs, ClosureArgsParts, ConstKind, ConstVid,
     EarlyBoundRegion, ExistentialPredicate, ExistentialProjection, ExistentialTraitRef, FnSig,
-    FreeRegion, GenSig, GeneratorSubsts, GeneratorSubstsParts, InlineConstSubsts,
-    InlineConstSubstsParts, ParamConst, ParamTy, PolyExistentialPredicate,
-    PolyExistentialProjection, PolyExistentialTraitRef, PolyFnSig, PolyGenSig, PolyTraitRef,
-    Region, RegionKind, RegionVid, TraitRef, TyKind, TypeAndMut, UpvarSubsts, VarianceDiagInfo,
+    FreeRegion, GenSig, GeneratorArgs, GeneratorArgsParts, InlineConstArgs, InlineConstArgsParts,
+    ParamConst, ParamTy, PolyExistentialPredicate, PolyExistentialProjection,
+    PolyExistentialTraitRef, PolyFnSig, PolyGenSig, PolyTraitRef, Region, RegionKind, RegionVid,
+    TraitRef, TyKind, TypeAndMut, UpvarArgs, VarianceDiagInfo,
 };
 pub use self::trait_def::TraitDef;
 pub use self::typeck_results::{
@@ -127,7 +126,6 @@ pub mod layout;
 pub mod normalize_erasing_regions;
 pub mod print;
 pub mod relate;
-pub mod subst;
 pub mod trait_def;
 pub mod util;
 pub mod visit;
@@ -141,6 +139,7 @@ mod consts;
 mod context;
 mod diagnostics;
 mod erase_regions;
+mod generic_args;
 mod generics;
 mod impls_ty;
 mod instance;
@@ -149,7 +148,7 @@ mod opaque_types;
 mod parameterized;
 mod rvalue_scopes;
 mod structural_impls;
-#[cfg_attr(not(bootstrap), allow(hidden_glob_reexports))]
+#[allow(hidden_glob_reexports)]
 mod sty;
 mod typeck_results;
 
@@ -677,9 +676,9 @@ pub enum PredicateKind<'tcx> {
     ObjectSafe(DefId),
 
     /// No direct syntax. May be thought of as `where T: FnFoo<...>`
-    /// for some substitutions `...` and `T` being a closure type.
+    /// for some generic args `...` and `T` being a closure type.
     /// Satisfied (or refuted) once we know the closure's kind.
-    ClosureKind(DefId, SubstsRef<'tcx>, ClosureKind),
+    ClosureKind(DefId, GenericArgsRef<'tcx>, ClosureKind),
 
     /// `T1 <: T2`
     ///
@@ -814,15 +813,15 @@ impl<'tcx> Clause<'tcx> {
         // this trick achieves that).
 
         // Working through the second example:
-        // trait_ref: for<'x> T: Foo1<'^0.0>; substs: [T, '^0.0]
-        // predicate: for<'b> Self: Bar1<'a, '^0.0>; substs: [Self, 'a, '^0.0]
+        // trait_ref: for<'x> T: Foo1<'^0.0>; args: [T, '^0.0]
+        // predicate: for<'b> Self: Bar1<'a, '^0.0>; args: [Self, 'a, '^0.0]
         // We want to end up with:
         //     for<'x, 'b> T: Bar1<'^0.0, '^0.1>
         // To do this:
         // 1) We must shift all bound vars in predicate by the length
         //    of trait ref's bound vars. So, we would end up with predicate like
         //    Self: Bar1<'a, '^0.1>
-        // 2) We can then apply the trait substs to this, ending up with
+        // 2) We can then apply the trait args to this, ending up with
         //    T: Bar1<'^0.0, '^0.1>
         // 3) Finally, to create the final bound vars, we concatenate the bound
         //    vars of the trait ref with those of the predicate:
@@ -834,7 +833,7 @@ impl<'tcx> Clause<'tcx> {
         let shifted_pred =
             tcx.shift_bound_var_indices(trait_bound_vars.len(), bound_pred.skip_binder());
         // 2) Self: Bar1<'a, '^0.1> -> T: Bar1<'^0.0, '^0.1>
-        let new = EarlyBinder::bind(shifted_pred).subst(tcx, trait_ref.skip_binder().substs);
+        let new = EarlyBinder::bind(shifted_pred).instantiate(tcx, trait_ref.skip_binder().args);
         // 3) ['x] + ['b] -> ['x, 'b]
         let bound_vars =
             tcx.mk_bound_variable_kinds_from_iter(trait_bound_vars.iter().chain(pred_bound_vars));
@@ -1080,7 +1079,7 @@ impl<'tcx> Term<'tcx> {
                 _ => None,
             },
             TermKind::Const(ct) => match ct.kind() {
-                ConstKind::Unevaluated(uv) => Some(tcx.mk_alias_ty(uv.def, uv.substs)),
+                ConstKind::Unevaluated(uv) => Some(tcx.mk_alias_ty(uv.def, uv.args)),
                 _ => None,
             },
         }
@@ -1559,7 +1558,7 @@ impl<'a, 'tcx> IntoIterator for &'a InstantiatedPredicates<'tcx> {
 #[derive(TypeFoldable, TypeVisitable)]
 pub struct OpaqueTypeKey<'tcx> {
     pub def_id: LocalDefId,
-    pub substs: SubstsRef<'tcx>,
+    pub args: GenericArgsRef<'tcx>,
 }
 
 #[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable, HashStable, TyEncodable, TyDecodable)]
@@ -1630,21 +1629,21 @@ impl<'tcx> OpaqueHiddenType<'tcx> {
         // typeck errors have subpar spans for opaque types, so delay error reporting until borrowck.
         ignore_errors: bool,
     ) -> Self {
-        let OpaqueTypeKey { def_id, substs } = opaque_type_key;
+        let OpaqueTypeKey { def_id, args } = opaque_type_key;
 
-        // Use substs to build up a reverse map from regions to their
+        // Use args to build up a reverse map from regions to their
         // identity mappings. This is necessary because of `impl
         // Trait` lifetimes are computed by replacing existing
         // lifetimes with 'static and remapping only those used in the
         // `impl Trait` return type, resulting in the parameters
         // shifting.
-        let id_substs = InternalSubsts::identity_for_item(tcx, def_id);
-        debug!(?id_substs);
+        let id_args = GenericArgs::identity_for_item(tcx, def_id);
+        debug!(?id_args);
 
-        // This zip may have several times the same lifetime in `substs` paired with a different
-        // lifetime from `id_substs`. Simply `collect`ing the iterator is the correct behaviour:
+        // This zip may have several times the same lifetime in `args` paired with a different
+        // lifetime from `id_args`. Simply `collect`ing the iterator is the correct behaviour:
         // it will pick the last one, which is the one we introduced in the impl-trait desugaring.
-        let map = substs.iter().zip(id_substs).collect();
+        let map = args.iter().zip(id_args).collect();
         debug!("map = {:#?}", map);
 
         // Convert the type from the function into a type valid outside
@@ -2165,10 +2164,10 @@ impl Hash for FieldDef {
 }
 
 impl<'tcx> FieldDef {
-    /// Returns the type of this field. The resulting type is not normalized. The `subst` is
+    /// Returns the type of this field. The resulting type is not normalized. The `arg` is
     /// typically obtained via the second field of [`TyKind::Adt`].
-    pub fn ty(&self, tcx: TyCtxt<'tcx>, subst: SubstsRef<'tcx>) -> Ty<'tcx> {
-        tcx.type_of(self.did).subst(tcx, subst)
+    pub fn ty(&self, tcx: TyCtxt<'tcx>, arg: GenericArgsRef<'tcx>) -> Ty<'tcx> {
+        tcx.type_of(self.did).instantiate(tcx, arg)
     }
 
     /// Computes the `Ident` of this variant by looking up the `Span`
@@ -2392,8 +2391,8 @@ impl<'tcx> TyCtxt<'tcx> {
         let impl_trait_ref2 = self.impl_trait_ref(def_id2);
         // If either trait impl references an error, they're allowed to overlap,
         // as one of them essentially doesn't exist.
-        if impl_trait_ref1.is_some_and(|tr| tr.subst_identity().references_error())
-            || impl_trait_ref2.is_some_and(|tr| tr.subst_identity().references_error())
+        if impl_trait_ref1.is_some_and(|tr| tr.instantiate_identity().references_error())
+            || impl_trait_ref2.is_some_and(|tr| tr.instantiate_identity().references_error())
         {
             return Some(ImplOverlapKind::Permitted { marker: false });
         }
@@ -2713,12 +2712,16 @@ impl<'tcx> TyCtxt<'tcx> {
             return false;
         }
 
-        let Some(item) = self.opt_associated_item(def_id) else { return false; };
+        let Some(item) = self.opt_associated_item(def_id) else {
+            return false;
+        };
         if item.container != ty::AssocItemContainer::ImplContainer {
             return false;
         }
 
-        let Some(trait_item_def_id) = item.trait_item_def_id else { return false; };
+        let Some(trait_item_def_id) = item.trait_item_def_id else {
+            return false;
+        };
 
         return !self
             .associated_types_for_impl_traits_in_associated_fn(trait_item_def_id)
diff --git a/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs b/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs
index a0c8d299f48..3c2c4483c73 100644
--- a/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs
+++ b/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs
@@ -9,7 +9,7 @@
 
 use crate::traits::query::NoSolution;
 use crate::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeFolder};
-use crate::ty::{self, EarlyBinder, SubstsRef, Ty, TyCtxt, TypeVisitableExt};
+use crate::ty::{self, EarlyBinder, GenericArgsRef, Ty, TyCtxt, TypeVisitableExt};
 
 #[derive(Debug, Copy, Clone, HashStable, TyEncodable, TyDecodable)]
 pub enum NormalizationError<'tcx> {
@@ -137,7 +137,7 @@ impl<'tcx> TyCtxt<'tcx> {
     /// use `try_subst_and_normalize_erasing_regions` instead.
     pub fn subst_and_normalize_erasing_regions<T>(
         self,
-        param_substs: SubstsRef<'tcx>,
+        param_args: GenericArgsRef<'tcx>,
         param_env: ty::ParamEnv<'tcx>,
         value: EarlyBinder<T>,
     ) -> T
@@ -146,12 +146,12 @@ impl<'tcx> TyCtxt<'tcx> {
     {
         debug!(
             "subst_and_normalize_erasing_regions(\
-             param_substs={:?}, \
+             param_args={:?}, \
              value={:?}, \
              param_env={:?})",
-            param_substs, value, param_env,
+            param_args, value, param_env,
         );
-        let substituted = value.subst(self, param_substs);
+        let substituted = value.instantiate(self, param_args);
         self.normalize_erasing_regions(param_env, substituted)
     }
 
@@ -161,7 +161,7 @@ impl<'tcx> TyCtxt<'tcx> {
     /// not assume that normalization succeeds.
     pub fn try_subst_and_normalize_erasing_regions<T>(
         self,
-        param_substs: SubstsRef<'tcx>,
+        param_args: GenericArgsRef<'tcx>,
         param_env: ty::ParamEnv<'tcx>,
         value: EarlyBinder<T>,
     ) -> Result<T, NormalizationError<'tcx>>
@@ -170,12 +170,12 @@ impl<'tcx> TyCtxt<'tcx> {
     {
         debug!(
             "subst_and_normalize_erasing_regions(\
-             param_substs={:?}, \
+             param_args={:?}, \
              value={:?}, \
              param_env={:?})",
-            param_substs, value, param_env,
+            param_args, value, param_env,
         );
-        let substituted = value.subst(self, param_substs);
+        let substituted = value.instantiate(self, param_args);
         self.try_normalize_erasing_regions(param_env, substituted)
     }
 }
diff --git a/compiler/rustc_middle/src/ty/opaque_types.rs b/compiler/rustc_middle/src/ty/opaque_types.rs
index b10921eff08..7ae8be2dab3 100644
--- a/compiler/rustc_middle/src/ty/opaque_types.rs
+++ b/compiler/rustc_middle/src/ty/opaque_types.rs
@@ -1,7 +1,7 @@
 use crate::error::ConstNotUsedTraitAlias;
 use crate::ty::fold::{TypeFolder, TypeSuperFoldable};
-use crate::ty::subst::{GenericArg, GenericArgKind};
 use crate::ty::{self, Ty, TyCtxt, TypeFoldable};
+use crate::ty::{GenericArg, GenericArgKind};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_span::def_id::DefId;
 use rustc_span::Span;
@@ -49,11 +49,11 @@ impl<'tcx> ReverseMapper<'tcx> {
         kind.fold_with(self)
     }
 
-    fn fold_closure_substs(
+    fn fold_closure_args(
         &mut self,
         def_id: DefId,
-        substs: ty::SubstsRef<'tcx>,
-    ) -> ty::SubstsRef<'tcx> {
+        args: ty::GenericArgsRef<'tcx>,
+    ) -> ty::GenericArgsRef<'tcx> {
         // I am a horrible monster and I pray for death. When
         // we encounter a closure here, it is always a closure
         // from within the function that we are currently
@@ -79,7 +79,7 @@ impl<'tcx> ReverseMapper<'tcx> {
         // during codegen.
 
         let generics = self.tcx.generics_of(def_id);
-        self.tcx.mk_substs_from_iter(substs.iter().enumerate().map(|(index, kind)| {
+        self.tcx.mk_args_from_iter(args.iter().enumerate().map(|(index, kind)| {
             if index < generics.parent_count {
                 // Accommodate missing regions in the parent kinds...
                 self.fold_kind_no_missing_regions_error(kind)
@@ -148,19 +148,19 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ReverseMapper<'tcx> {
 
     fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
         match *ty.kind() {
-            ty::Closure(def_id, substs) => {
-                let substs = self.fold_closure_substs(def_id, substs);
-                Ty::new_closure(self.tcx, def_id, substs)
+            ty::Closure(def_id, args) => {
+                let args = self.fold_closure_args(def_id, args);
+                Ty::new_closure(self.tcx, def_id, args)
             }
 
-            ty::Generator(def_id, substs, movability) => {
-                let substs = self.fold_closure_substs(def_id, substs);
-                Ty::new_generator(self.tcx, def_id, substs, movability)
+            ty::Generator(def_id, args, movability) => {
+                let args = self.fold_closure_args(def_id, args);
+                Ty::new_generator(self.tcx, def_id, args, movability)
             }
 
-            ty::GeneratorWitnessMIR(def_id, substs) => {
-                let substs = self.fold_closure_substs(def_id, substs);
-                Ty::new_generator_witness_mir(self.tcx, def_id, substs)
+            ty::GeneratorWitnessMIR(def_id, args) => {
+                let args = self.fold_closure_args(def_id, args);
+                Ty::new_generator_witness_mir(self.tcx, def_id, args)
             }
 
             ty::Param(param) => {
diff --git a/compiler/rustc_middle/src/ty/print/mod.rs b/compiler/rustc_middle/src/ty/print/mod.rs
index 2de0a3f75dc..83a75d0c6b9 100644
--- a/compiler/rustc_middle/src/ty/print/mod.rs
+++ b/compiler/rustc_middle/src/ty/print/mod.rs
@@ -42,19 +42,19 @@ pub trait Printer<'tcx>: Sized {
     fn print_def_path(
         self,
         def_id: DefId,
-        substs: &'tcx [GenericArg<'tcx>],
+        args: &'tcx [GenericArg<'tcx>],
     ) -> Result<Self::Path, Self::Error> {
-        self.default_print_def_path(def_id, substs)
+        self.default_print_def_path(def_id, args)
     }
 
     fn print_impl_path(
         self,
         impl_def_id: DefId,
-        substs: &'tcx [GenericArg<'tcx>],
+        args: &'tcx [GenericArg<'tcx>],
         self_ty: Ty<'tcx>,
         trait_ref: Option<ty::TraitRef<'tcx>>,
     ) -> Result<Self::Path, Self::Error> {
-        self.default_print_impl_path(impl_def_id, substs, self_ty, trait_ref)
+        self.default_print_impl_path(impl_def_id, args, self_ty, trait_ref)
     }
 
     fn print_region(self, region: ty::Region<'tcx>) -> Result<Self::Region, Self::Error>;
@@ -102,7 +102,7 @@ pub trait Printer<'tcx>: Sized {
     fn default_print_def_path(
         self,
         def_id: DefId,
-        substs: &'tcx [GenericArg<'tcx>],
+        args: &'tcx [GenericArg<'tcx>],
     ) -> Result<Self::Path, Self::Error> {
         let key = self.tcx().def_key(def_id);
         debug!(?key);
@@ -117,25 +117,28 @@ pub trait Printer<'tcx>: Sized {
                 let generics = self.tcx().generics_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() {
+                let (self_ty, impl_trait_ref) = if args.len() >= generics.count() {
                     (
-                        self_ty.subst(self.tcx(), substs),
-                        impl_trait_ref.map(|i| i.subst(self.tcx(), substs)),
+                        self_ty.instantiate(self.tcx(), args),
+                        impl_trait_ref.map(|i| i.instantiate(self.tcx(), args)),
                     )
                 } else {
-                    (self_ty.subst_identity(), impl_trait_ref.map(|i| i.subst_identity()))
+                    (
+                        self_ty.instantiate_identity(),
+                        impl_trait_ref.map(|i| i.instantiate_identity()),
+                    )
                 };
-                self.print_impl_path(def_id, substs, self_ty, impl_trait_ref)
+                self.print_impl_path(def_id, args, self_ty, impl_trait_ref)
             }
 
             _ => {
                 let parent_def_id = DefId { index: key.parent.unwrap(), ..def_id };
 
-                let mut parent_substs = substs;
+                let mut parent_args = args;
                 let mut trait_qualify_parent = false;
-                if !substs.is_empty() {
+                if !args.is_empty() {
                     let generics = self.tcx().generics_of(def_id);
-                    parent_substs = &substs[..generics.parent_count.min(substs.len())];
+                    parent_args = &args[..generics.parent_count.min(args.len())];
 
                     match key.disambiguated_data.data {
                         // Closures' own generics are only captures, don't print them.
@@ -148,10 +151,10 @@ pub trait Printer<'tcx>: Sized {
                         // If we have any generic arguments to print, we do that
                         // on top of the same path, but without its own generics.
                         _ => {
-                            if !generics.params.is_empty() && substs.len() >= generics.count() {
-                                let args = generics.own_substs_no_defaults(self.tcx(), substs);
+                            if !generics.params.is_empty() && args.len() >= generics.count() {
+                                let args = generics.own_args_no_defaults(self.tcx(), args);
                                 return self.path_generic_args(
-                                    |cx| cx.print_def_path(def_id, parent_substs),
+                                    |cx| cx.print_def_path(def_id, parent_args),
                                     args,
                                 );
                             }
@@ -162,7 +165,7 @@ pub trait Printer<'tcx>: Sized {
                     // logic, instead of doing it when printing the child.
                     trait_qualify_parent = generics.has_self
                         && generics.parent == Some(parent_def_id)
-                        && parent_substs.len() == generics.parent_count
+                        && parent_args.len() == generics.parent_count
                         && self.tcx().generics_of(parent_def_id).parent_count == 0;
                 }
 
@@ -172,11 +175,11 @@ pub trait Printer<'tcx>: Sized {
                             let trait_ref = ty::TraitRef::new(
                                 cx.tcx(),
                                 parent_def_id,
-                                parent_substs.iter().copied(),
+                                parent_args.iter().copied(),
                             );
                             cx.path_qualified(trait_ref.self_ty(), Some(trait_ref))
                         } else {
-                            cx.print_def_path(parent_def_id, parent_substs)
+                            cx.print_def_path(parent_def_id, parent_args)
                         }
                     },
                     &key.disambiguated_data,
@@ -188,7 +191,7 @@ pub trait Printer<'tcx>: Sized {
     fn default_print_impl_path(
         self,
         impl_def_id: DefId,
-        _substs: &'tcx [GenericArg<'tcx>],
+        _args: &'tcx [GenericArg<'tcx>],
         self_ty: Ty<'tcx>,
         impl_trait_ref: Option<ty::TraitRef<'tcx>>,
     ) -> Result<Self::Path, Self::Error> {
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index 96cf36eb996..3591acdea56 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -224,9 +224,9 @@ pub trait PrettyPrinter<'tcx>:
     fn print_value_path(
         self,
         def_id: DefId,
-        substs: &'tcx [GenericArg<'tcx>],
+        args: &'tcx [GenericArg<'tcx>],
     ) -> Result<Self::Path, Self::Error> {
-        self.print_def_path(def_id, substs)
+        self.print_def_path(def_id, args)
     }
 
     fn in_binder<T>(self, value: &ty::Binder<'tcx, T>) -> Result<Self, Self::Error>
@@ -679,12 +679,12 @@ pub trait PrettyPrinter<'tcx>:
                 }
                 p!(")")
             }
-            ty::FnDef(def_id, substs) => {
+            ty::FnDef(def_id, args) => {
                 if with_no_queries() {
-                    p!(print_def_path(def_id, substs));
+                    p!(print_def_path(def_id, args));
                 } else {
-                    let sig = self.tcx().fn_sig(def_id).subst(self.tcx(), substs);
-                    p!(print(sig), " {{", print_value_path(def_id, substs), "}}");
+                    let sig = self.tcx().fn_sig(def_id).instantiate(self.tcx(), args);
+                    p!(print(sig), " {{", print_value_path(def_id, args), "}}");
                 }
             }
             ty::FnPtr(ref bare_fn) => p!(print(bare_fn)),
@@ -715,8 +715,8 @@ pub trait PrettyPrinter<'tcx>:
                     false => p!(write("{s}")),
                 },
             },
-            ty::Adt(def, substs) => {
-                p!(print_def_path(def.did(), substs));
+            ty::Adt(def, args) => {
+                p!(print_def_path(def.did(), args));
             }
             ty::Dynamic(data, r, repr) => {
                 let print_r = self.should_print_region(r);
@@ -739,7 +739,7 @@ pub trait PrettyPrinter<'tcx>:
                 if !(self.should_print_verbose() || with_no_queries())
                     && self.tcx().is_impl_trait_in_trait(data.def_id)
                 {
-                    return self.pretty_print_opaque_impl_type(data.def_id, data.substs);
+                    return self.pretty_print_opaque_impl_type(data.def_id, data.args);
                 } else {
                     p!(print(data))
                 }
@@ -751,7 +751,7 @@ pub trait PrettyPrinter<'tcx>:
                     false => p!(write("{name}")),
                 },
             },
-            ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
+            ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) => {
                 // We use verbose printing in 'NO_QUERIES' mode, to
                 // avoid needing to call `predicates_of`. This should
                 // only affect certain debug messages (e.g. messages printed
@@ -759,7 +759,7 @@ pub trait PrettyPrinter<'tcx>:
                 // and should have no effect on any compiler output.
                 if self.should_print_verbose() {
                     // FIXME(eddyb) print this with `print_def_path`.
-                    p!(write("Opaque({:?}, {:?})", def_id, substs));
+                    p!(write("Opaque({:?}, {:?})", def_id, args));
                     return Ok(self);
                 }
 
@@ -769,17 +769,17 @@ 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).subst_identity().kind()
+                            *self.tcx().type_of(parent).instantiate_identity().kind()
                         {
                             if d == def_id {
                                 // If the type alias directly starts with the `impl` of the
                                 // opaque type we're printing, then skip the `::{opaque#1}`.
-                                p!(print_def_path(parent, substs));
+                                p!(print_def_path(parent, args));
                                 return Ok(self);
                             }
                         }
                         // Complex opaque type, e.g. `type Foo = (i32, impl Debug);`
-                        p!(print_def_path(def_id, substs));
+                        p!(print_def_path(def_id, args));
                         return Ok(self);
                     }
                     _ => {
@@ -787,13 +787,13 @@ pub trait PrettyPrinter<'tcx>:
                             p!(print_def_path(def_id, &[]));
                             return Ok(self);
                         } else {
-                            return self.pretty_print_opaque_impl_type(def_id, substs);
+                            return self.pretty_print_opaque_impl_type(def_id, args);
                         }
                     }
                 }
             }
             ty::Str => p!("str"),
-            ty::Generator(did, substs, movability) => {
+            ty::Generator(did, args, movability) => {
                 p!(write("["));
                 let generator_kind = self.tcx().generator_kind(did).unwrap();
                 let should_print_movability =
@@ -818,20 +818,20 @@ pub trait PrettyPrinter<'tcx>:
                             self.tcx().sess.source_map().span_to_embeddable_string(span)
                         ));
                     } else {
-                        p!(write("@"), print_def_path(did, substs));
+                        p!(write("@"), print_def_path(did, args));
                     }
                 } else {
-                    p!(print_def_path(did, substs));
+                    p!(print_def_path(did, args));
                     p!(" upvar_tys=(");
-                    if !substs.as_generator().is_valid() {
+                    if !args.as_generator().is_valid() {
                         p!("unavailable");
                     } else {
-                        self = self.comma_sep(substs.as_generator().upvar_tys())?;
+                        self = self.comma_sep(args.as_generator().upvar_tys())?;
                     }
                     p!(")");
 
-                    if substs.as_generator().is_valid() {
-                        p!(" ", print(substs.as_generator().witness()));
+                    if args.as_generator().is_valid() {
+                        p!(" ", print(args.as_generator().witness()));
                     }
                 }
 
@@ -840,7 +840,7 @@ pub trait PrettyPrinter<'tcx>:
             ty::GeneratorWitness(types) => {
                 p!(in_binder(&types));
             }
-            ty::GeneratorWitnessMIR(did, substs) => {
+            ty::GeneratorWitnessMIR(did, args) => {
                 p!(write("["));
                 if !self.tcx().sess.verbose() {
                     p!("generator witness");
@@ -854,22 +854,22 @@ pub trait PrettyPrinter<'tcx>:
                             self.tcx().sess.source_map().span_to_embeddable_string(span)
                         ));
                     } else {
-                        p!(write("@"), print_def_path(did, substs));
+                        p!(write("@"), print_def_path(did, args));
                     }
                 } else {
-                    p!(print_def_path(did, substs));
+                    p!(print_def_path(did, args));
                 }
 
                 p!("]")
             }
-            ty::Closure(did, substs) => {
+            ty::Closure(did, args) => {
                 p!(write("["));
                 if !self.should_print_verbose() {
                     p!(write("closure"));
                     // FIXME(eddyb) should use `def_span`.
                     if let Some(did) = did.as_local() {
                         if self.tcx().sess.opts.unstable_opts.span_free_formats {
-                            p!("@", print_def_path(did.to_def_id(), substs));
+                            p!("@", print_def_path(did.to_def_id(), args));
                         } else {
                             let span = self.tcx().def_span(did);
                             let preference = if FORCE_TRIMMED_PATH.with(|flag| flag.get()) {
@@ -885,21 +885,21 @@ pub trait PrettyPrinter<'tcx>:
                             ));
                         }
                     } else {
-                        p!(write("@"), print_def_path(did, substs));
+                        p!(write("@"), print_def_path(did, args));
                     }
                 } else {
-                    p!(print_def_path(did, substs));
-                    if !substs.as_closure().is_valid() {
-                        p!(" closure_substs=(unavailable)");
-                        p!(write(" substs={:?}", substs));
+                    p!(print_def_path(did, args));
+                    if !args.as_closure().is_valid() {
+                        p!(" closure_args=(unavailable)");
+                        p!(write(" args={:?}", args));
                     } else {
-                        p!(" closure_kind_ty=", print(substs.as_closure().kind_ty()));
+                        p!(" closure_kind_ty=", print(args.as_closure().kind_ty()));
                         p!(
                             " closure_sig_as_fn_ptr_ty=",
-                            print(substs.as_closure().sig_as_fn_ptr_ty())
+                            print(args.as_closure().sig_as_fn_ptr_ty())
                         );
                         p!(" upvar_tys=(");
-                        self = self.comma_sep(substs.as_closure().upvar_tys())?;
+                        self = self.comma_sep(args.as_closure().upvar_tys())?;
                         p!(")");
                     }
                 }
@@ -915,7 +915,7 @@ pub trait PrettyPrinter<'tcx>:
     fn pretty_print_opaque_impl_type(
         mut self,
         def_id: DefId,
-        substs: &'tcx ty::List<ty::GenericArg<'tcx>>,
+        args: &'tcx ty::List<ty::GenericArg<'tcx>>,
     ) -> Result<Self::Type, Self::Error> {
         let tcx = self.tcx();
 
@@ -928,7 +928,7 @@ pub trait PrettyPrinter<'tcx>:
         let mut is_sized = false;
         let mut lifetimes = SmallVec::<[ty::Region<'tcx>; 1]>::new();
 
-        for (predicate, _) in bounds.subst_iter_copied(tcx, substs) {
+        for (predicate, _) in bounds.arg_iter_copied(tcx, args) {
             let bound_predicate = predicate.kind();
 
             match bound_predicate.skip_binder() {
@@ -978,9 +978,9 @@ pub trait PrettyPrinter<'tcx>:
                 define_scoped_cx!(cx);
                 // Get the (single) generic ty (the args) of this FnOnce trait ref.
                 let generics = tcx.generics_of(trait_ref.def_id);
-                let args = generics.own_substs_no_defaults(tcx, trait_ref.substs);
+                let own_args = generics.own_args_no_defaults(tcx, trait_ref.args);
 
-                match (entry.return_ty, args[0].expect_ty()) {
+                match (entry.return_ty, own_args[0].expect_ty()) {
                     // We can only print `impl Fn() -> ()` if we have a tuple of args and we recorded
                     // a return type.
                     (Some(return_ty), arg_tys) if matches!(arg_tys.kind(), ty::Tuple(_)) => {
@@ -1044,12 +1044,12 @@ pub trait PrettyPrinter<'tcx>:
                 p!(print(trait_ref.print_only_trait_name()));
 
                 let generics = tcx.generics_of(trait_ref.def_id);
-                let args = generics.own_substs_no_defaults(tcx, trait_ref.substs);
+                let own_args = generics.own_args_no_defaults(tcx, trait_ref.args);
 
-                if !args.is_empty() || !assoc_items.is_empty() {
+                if !own_args.is_empty() || !assoc_items.is_empty() {
                     let mut first = true;
 
-                    for ty in args {
+                    for ty in own_args {
                         if first {
                             p!("<");
                             first = false;
@@ -1068,8 +1068,8 @@ pub trait PrettyPrinter<'tcx>:
                             && assoc.trait_container(tcx) == tcx.lang_items().gen_trait()
                             && assoc.name == rustc_span::sym::Return
                         {
-                            if let ty::Generator(_, substs, _) = substs.type_at(0).kind() {
-                                let return_ty = substs.as_generator().return_ty();
+                            if let ty::Generator(_, args, _) = args.type_at(0).kind() {
+                                let return_ty = args.as_generator().return_ty();
                                 if !return_ty.is_ty_var() {
                                     return_ty.into()
                                 } else {
@@ -1182,7 +1182,7 @@ pub trait PrettyPrinter<'tcx>:
                     &def_key.disambiguated_data,
                 )
             },
-            &alias_ty.substs[1..],
+            &alias_ty.args[1..],
         )
     }
 
@@ -1211,7 +1211,7 @@ pub trait PrettyPrinter<'tcx>:
                 // Special-case `Fn(...) -> ...` and re-sugar it.
                 let fn_trait_kind = cx.tcx().fn_trait_kind_from_def_id(principal.def_id);
                 if !cx.should_print_verbose() && fn_trait_kind.is_some() {
-                    if let ty::Tuple(tys) = principal.substs.type_at(0).kind() {
+                    if let ty::Tuple(tys) = principal.args.type_at(0).kind() {
                         let mut projections = predicates.projection_bounds();
                         if let (Some(proj), None) = (projections.next(), projections.next()) {
                             p!(pretty_fn_sig(
@@ -1234,7 +1234,7 @@ pub trait PrettyPrinter<'tcx>:
                     let args = cx
                         .tcx()
                         .generics_of(principal.def_id)
-                        .own_substs_no_defaults(cx.tcx(), principal.substs);
+                        .own_args_no_defaults(cx.tcx(), principal.args);
 
                     let mut projections = predicates.projection_bounds();
 
@@ -1341,10 +1341,10 @@ pub trait PrettyPrinter<'tcx>:
         }
 
         match ct.kind() {
-            ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, substs }) => {
+            ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, args }) => {
                 match self.tcx().def_kind(def) {
                     DefKind::Const | DefKind::AssocConst => {
-                        p!(print_value_path(def, substs))
+                        p!(print_value_path(def, args))
                     }
                     DefKind::AnonConst => {
                         if def.is_local()
@@ -1449,7 +1449,7 @@ pub trait PrettyPrinter<'tcx>:
                     self.tcx().try_get_global_alloc(alloc_id)
                 {
                     self = self.typed_value(
-                        |this| this.print_value_path(instance.def_id(), instance.substs),
+                        |this| this.print_value_path(instance.def_id(), instance.args),
                         |this| this.print_type(ty),
                         " as ",
                     )?;
@@ -1619,11 +1619,11 @@ pub trait PrettyPrinter<'tcx>:
                             ": ",
                         )?;
                     }
-                    ty::Adt(def, substs) => {
+                    ty::Adt(def, args) => {
                         let variant_idx =
                             contents.variant.expect("destructed const of adt without variant idx");
                         let variant_def = &def.variant(variant_idx);
-                        p!(print_value_path(variant_def.def_id, substs));
+                        p!(print_value_path(variant_def.def_id, args));
                         match variant_def.ctor_kind() {
                             Some(CtorKind::Const) => {}
                             Some(CtorKind::Fn) => {
@@ -1673,7 +1673,7 @@ pub trait PrettyPrinter<'tcx>:
 
     fn pretty_closure_as_impl(
         mut self,
-        closure: ty::ClosureSubsts<'tcx>,
+        closure: ty::ClosureArgs<'tcx>,
     ) -> Result<Self::Const, Self::Error> {
         let sig = closure.sig();
         let kind = closure.kind_ty().to_opt_closure_kind().unwrap_or(ty::ClosureKind::Fn);
@@ -1798,29 +1798,29 @@ impl<'t> TyCtxt<'t> {
     /// Returns a string identifying this `DefId`. This string is
     /// suitable for user output.
     pub fn def_path_str(self, def_id: impl IntoQueryParam<DefId>) -> String {
-        self.def_path_str_with_substs(def_id, &[])
+        self.def_path_str_with_args(def_id, &[])
     }
 
-    pub fn def_path_str_with_substs(
+    pub fn def_path_str_with_args(
         self,
         def_id: impl IntoQueryParam<DefId>,
-        substs: &'t [GenericArg<'t>],
+        args: &'t [GenericArg<'t>],
     ) -> String {
         let def_id = def_id.into_query_param();
         let ns = guess_def_namespace(self, def_id);
         debug!("def_path_str: def_id={:?}, ns={:?}", def_id, ns);
-        FmtPrinter::new(self, ns).print_def_path(def_id, substs).unwrap().into_buffer()
+        FmtPrinter::new(self, ns).print_def_path(def_id, args).unwrap().into_buffer()
     }
 
-    pub fn value_path_str_with_substs(
+    pub fn value_path_str_with_args(
         self,
         def_id: impl IntoQueryParam<DefId>,
-        substs: &'t [GenericArg<'t>],
+        args: &'t [GenericArg<'t>],
     ) -> String {
         let def_id = def_id.into_query_param();
         let ns = guess_def_namespace(self, def_id);
         debug!("value_path_str: def_id={:?}, ns={:?}", def_id, ns);
-        FmtPrinter::new(self, ns).print_value_path(def_id, substs).unwrap().into_buffer()
+        FmtPrinter::new(self, ns).print_value_path(def_id, args).unwrap().into_buffer()
     }
 }
 
@@ -1847,11 +1847,11 @@ impl<'tcx> Printer<'tcx> for FmtPrinter<'_, 'tcx> {
     fn print_def_path(
         mut self,
         def_id: DefId,
-        substs: &'tcx [GenericArg<'tcx>],
+        args: &'tcx [GenericArg<'tcx>],
     ) -> Result<Self::Path, Self::Error> {
         define_scoped_cx!(self);
 
-        if substs.is_empty() {
+        if args.is_empty() {
             match self.try_print_trimmed_def_path(def_id)? {
                 (cx, true) => return Ok(cx),
                 (cx, false) => self = cx,
@@ -1900,7 +1900,7 @@ impl<'tcx> Printer<'tcx> for FmtPrinter<'_, 'tcx> {
             }
         }
 
-        self.default_print_def_path(def_id, substs)
+        self.default_print_def_path(def_id, args)
     }
 
     fn print_region(self, region: ty::Region<'tcx>) -> Result<Self::Region, Self::Error> {
@@ -2044,10 +2044,10 @@ impl<'tcx> PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx> {
     fn print_value_path(
         mut self,
         def_id: DefId,
-        substs: &'tcx [GenericArg<'tcx>],
+        args: &'tcx [GenericArg<'tcx>],
     ) -> Result<Self::Path, Self::Error> {
         let was_in_value = std::mem::replace(&mut self.in_value, true);
-        self = self.print_def_path(def_id, substs)?;
+        self = self.print_def_path(def_id, args)?;
         self.in_value = was_in_value;
 
         Ok(self)
@@ -2695,7 +2695,7 @@ impl<'tcx> ty::PolyTraitPredicate<'tcx> {
 
 #[derive(Debug, Copy, Clone, Lift)]
 pub struct PrintClosureAsImpl<'tcx> {
-    pub closure: ty::ClosureSubsts<'tcx>,
+    pub closure: ty::ClosureArgs<'tcx>,
 }
 
 forward_display_to_print! {
@@ -2771,7 +2771,7 @@ define_print_and_forward_display! {
     }
 
     TraitRefPrintOnlyTraitPath<'tcx> {
-        p!(print_def_path(self.0.def_id, self.0.substs));
+        p!(print_def_path(self.0.def_id, self.0.args));
     }
 
     TraitRefPrintOnlyTraitName<'tcx> {
@@ -2842,7 +2842,7 @@ define_print_and_forward_display! {
         if let DefKind::Impl { of_trait: false } = cx.tcx().def_kind(cx.tcx().parent(self.def_id)) {
             p!(pretty_print_inherent_projection(self))
         } else {
-            p!(print_def_path(self.def_id, self.substs));
+            p!(print_def_path(self.def_id, self.args));
         }
     }
 
@@ -2891,7 +2891,7 @@ define_print_and_forward_display! {
             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!(
+            ty::PredicateKind::ClosureKind(closure_def_id, _closure_args, kind) => p!(
                 "the closure `",
                 print_value_path(closure_def_id, &[]),
                 write("` implements the trait `{}`", kind)
diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs
index 54dedf31d9f..bf9adabdab1 100644
--- a/compiler/rustc_middle/src/ty/relate.rs
+++ b/compiler/rustc_middle/src/ty/relate.rs
@@ -6,7 +6,7 @@
 
 use crate::ty::error::{ExpectedFound, TypeError};
 use crate::ty::{self, Expr, ImplSubject, Term, TermKind, Ty, TyCtxt, TypeFoldable};
-use crate::ty::{GenericArg, GenericArgKind, SubstsRef};
+use crate::ty::{GenericArg, GenericArgKind, GenericArgsRef};
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_target::spec::abi;
@@ -43,23 +43,23 @@ pub trait TypeRelation<'tcx>: Sized {
         Relate::relate(self, a, b)
     }
 
-    /// Relate the two substitutions for the given item. The default
+    /// Relate the two args for the given item. The default
     /// is to look up the variance for the item and proceed
     /// accordingly.
-    fn relate_item_substs(
+    fn relate_item_args(
         &mut self,
         item_def_id: DefId,
-        a_subst: SubstsRef<'tcx>,
-        b_subst: SubstsRef<'tcx>,
-    ) -> RelateResult<'tcx, SubstsRef<'tcx>> {
+        a_arg: GenericArgsRef<'tcx>,
+        b_arg: GenericArgsRef<'tcx>,
+    ) -> RelateResult<'tcx, GenericArgsRef<'tcx>> {
         debug!(
-            "relate_item_substs(item_def_id={:?}, a_subst={:?}, b_subst={:?})",
-            item_def_id, a_subst, b_subst
+            "relate_item_args(item_def_id={:?}, a_arg={:?}, b_arg={:?})",
+            item_def_id, a_arg, b_arg
         );
 
         let tcx = self.tcx();
         let opt_variances = tcx.variances_of(item_def_id);
-        relate_substs_with_variances(self, item_def_id, opt_variances, a_subst, b_subst, true)
+        relate_args_with_variances(self, item_def_id, opt_variances, a_arg, b_arg, true)
     }
 
     /// Switch variance for the purpose of relating `a` and `b`.
@@ -134,31 +134,32 @@ pub fn relate_type_and_mut<'tcx, R: TypeRelation<'tcx>>(
 }
 
 #[inline]
-pub fn relate_substs<'tcx, R: TypeRelation<'tcx>>(
+pub fn relate_args<'tcx, R: TypeRelation<'tcx>>(
     relation: &mut R,
-    a_subst: SubstsRef<'tcx>,
-    b_subst: SubstsRef<'tcx>,
-) -> RelateResult<'tcx, SubstsRef<'tcx>> {
-    relation.tcx().mk_substs_from_iter(iter::zip(a_subst, b_subst).map(|(a, b)| {
+    a_arg: GenericArgsRef<'tcx>,
+    b_arg: GenericArgsRef<'tcx>,
+) -> RelateResult<'tcx, GenericArgsRef<'tcx>> {
+    relation.tcx().mk_args_from_iter(iter::zip(a_arg, b_arg).map(|(a, b)| {
         relation.relate_with_variance(ty::Invariant, ty::VarianceDiagInfo::default(), a, b)
     }))
 }
 
-pub fn relate_substs_with_variances<'tcx, R: TypeRelation<'tcx>>(
+pub fn relate_args_with_variances<'tcx, R: TypeRelation<'tcx>>(
     relation: &mut R,
     ty_def_id: DefId,
     variances: &[ty::Variance],
-    a_subst: SubstsRef<'tcx>,
-    b_subst: SubstsRef<'tcx>,
+    a_arg: GenericArgsRef<'tcx>,
+    b_arg: GenericArgsRef<'tcx>,
     fetch_ty_for_diag: bool,
-) -> RelateResult<'tcx, SubstsRef<'tcx>> {
+) -> RelateResult<'tcx, GenericArgsRef<'tcx>> {
     let tcx = relation.tcx();
 
     let mut cached_ty = None;
-    let params = iter::zip(a_subst, b_subst).enumerate().map(|(i, (a, b))| {
+    let params = iter::zip(a_arg, b_arg).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.type_of(ty_def_id).subst(tcx, a_subst));
+            let ty =
+                *cached_ty.get_or_insert_with(|| tcx.type_of(ty_def_id).instantiate(tcx, a_arg));
             ty::VarianceDiagInfo::Invariant { ty, param_index: i.try_into().unwrap() }
         } else {
             ty::VarianceDiagInfo::default()
@@ -166,7 +167,7 @@ pub fn relate_substs_with_variances<'tcx, R: TypeRelation<'tcx>>(
         relation.relate_with_variance(variance, variance_info, a, b)
     });
 
-    tcx.mk_substs_from_iter(params)
+    tcx.mk_args_from_iter(params)
 }
 
 impl<'tcx> Relate<'tcx> for ty::FnSig<'tcx> {
@@ -272,8 +273,8 @@ impl<'tcx> Relate<'tcx> for ty::AliasTy<'tcx> {
         if a.def_id != b.def_id {
             Err(TypeError::ProjectionMismatched(expected_found(relation, a.def_id, b.def_id)))
         } else {
-            let substs = relation.relate(a.substs, b.substs)?;
-            Ok(relation.tcx().mk_alias_ty(a.def_id, substs))
+            let args = relation.relate(a.args, b.args)?;
+            Ok(relation.tcx().mk_alias_ty(a.def_id, args))
         }
     }
 }
@@ -293,13 +294,13 @@ impl<'tcx> Relate<'tcx> for ty::ExistentialProjection<'tcx> {
                 a.term,
                 b.term,
             )?;
-            let substs = relation.relate_with_variance(
+            let args = relation.relate_with_variance(
                 ty::Invariant,
                 ty::VarianceDiagInfo::default(),
-                a.substs,
-                b.substs,
+                a.args,
+                b.args,
             )?;
-            Ok(ty::ExistentialProjection { def_id: a.def_id, substs, term })
+            Ok(ty::ExistentialProjection { def_id: a.def_id, args, term })
         }
     }
 }
@@ -314,8 +315,8 @@ impl<'tcx> Relate<'tcx> for ty::TraitRef<'tcx> {
         if a.def_id != b.def_id {
             Err(TypeError::Traits(expected_found(relation, a.def_id, b.def_id)))
         } else {
-            let substs = relate_substs(relation, a.substs, b.substs)?;
-            Ok(ty::TraitRef::new(relation.tcx(), a.def_id, substs))
+            let args = relate_args(relation, a.args, b.args)?;
+            Ok(ty::TraitRef::new(relation.tcx(), a.def_id, args))
         }
     }
 }
@@ -330,8 +331,8 @@ impl<'tcx> Relate<'tcx> for ty::ExistentialTraitRef<'tcx> {
         if a.def_id != b.def_id {
             Err(TypeError::Traits(expected_found(relation, a.def_id, b.def_id)))
         } else {
-            let substs = relate_substs(relation, a.substs, b.substs)?;
-            Ok(ty::ExistentialTraitRef { def_id: a.def_id, substs })
+            let args = relate_args(relation, a.args, b.args)?;
+            Ok(ty::ExistentialTraitRef { def_id: a.def_id, args })
         }
     }
 }
@@ -426,9 +427,9 @@ pub fn structurally_relate_tys<'tcx, R: TypeRelation<'tcx>>(
 
         (ty::Placeholder(p1), ty::Placeholder(p2)) if p1 == p2 => Ok(a),
 
-        (&ty::Adt(a_def, a_substs), &ty::Adt(b_def, b_substs)) if a_def == b_def => {
-            let substs = relation.relate_item_substs(a_def.did(), a_substs, b_substs)?;
-            Ok(Ty::new_adt(tcx, a_def, substs))
+        (&ty::Adt(a_def, a_args), &ty::Adt(b_def, b_args)) if a_def == b_def => {
+            let args = relation.relate_item_args(a_def.did(), a_args, b_args)?;
+            Ok(Ty::new_adt(tcx, a_def, args))
         }
 
         (&ty::Foreign(a_id), &ty::Foreign(b_id)) if a_id == b_id => Ok(Ty::new_foreign(tcx, a_id)),
@@ -442,14 +443,14 @@ pub fn structurally_relate_tys<'tcx, R: TypeRelation<'tcx>>(
             Ok(Ty::new_dynamic(tcx, relation.relate(a_obj, b_obj)?, region_bound, a_repr))
         }
 
-        (&ty::Generator(a_id, a_substs, movability), &ty::Generator(b_id, b_substs, _))
+        (&ty::Generator(a_id, a_args, movability), &ty::Generator(b_id, b_args, _))
             if a_id == b_id =>
         {
             // All Generator types with the same id represent
             // the (anonymous) type of the same generator expression. So
             // all of their regions should be equated.
-            let substs = relation.relate(a_substs, b_substs)?;
-            Ok(Ty::new_generator(tcx, a_id, substs, movability))
+            let args = relation.relate(a_args, b_args)?;
+            Ok(Ty::new_generator(tcx, a_id, args, movability))
         }
 
         (&ty::GeneratorWitness(a_types), &ty::GeneratorWitness(b_types)) => {
@@ -462,22 +463,22 @@ pub fn structurally_relate_tys<'tcx, R: TypeRelation<'tcx>>(
             Ok(Ty::new_generator_witness(tcx, types))
         }
 
-        (&ty::GeneratorWitnessMIR(a_id, a_substs), &ty::GeneratorWitnessMIR(b_id, b_substs))
+        (&ty::GeneratorWitnessMIR(a_id, a_args), &ty::GeneratorWitnessMIR(b_id, b_args))
             if a_id == b_id =>
         {
             // All GeneratorWitness types with the same id represent
             // the (anonymous) type of the same generator expression. So
             // all of their regions should be equated.
-            let substs = relation.relate(a_substs, b_substs)?;
-            Ok(Ty::new_generator_witness_mir(tcx, a_id, substs))
+            let args = relation.relate(a_args, b_args)?;
+            Ok(Ty::new_generator_witness_mir(tcx, a_id, args))
         }
 
-        (&ty::Closure(a_id, a_substs), &ty::Closure(b_id, b_substs)) if a_id == b_id => {
+        (&ty::Closure(a_id, a_args), &ty::Closure(b_id, b_args)) if a_id == b_id => {
             // All Closure types with the same id represent
             // the (anonymous) type of the same closure expression. So
             // all of their regions should be equated.
-            let substs = relation.relate(a_substs, b_substs)?;
-            Ok(Ty::new_closure(tcx, a_id, &substs))
+            let args = relation.relate(a_args, b_args)?;
+            Ok(Ty::new_closure(tcx, a_id, &args))
         }
 
         (&ty::RawPtr(a_mt), &ty::RawPtr(b_mt)) => {
@@ -535,11 +536,9 @@ pub fn structurally_relate_tys<'tcx, R: TypeRelation<'tcx>>(
             }
         }
 
-        (&ty::FnDef(a_def_id, a_substs), &ty::FnDef(b_def_id, b_substs))
-            if a_def_id == b_def_id =>
-        {
-            let substs = relation.relate_item_substs(a_def_id, a_substs, b_substs)?;
-            Ok(Ty::new_fn_def(tcx, a_def_id, substs))
+        (&ty::FnDef(a_def_id, a_args), &ty::FnDef(b_def_id, b_args)) if a_def_id == b_def_id => {
+            let args = relation.relate_item_args(a_def_id, a_args, b_args)?;
+            Ok(Ty::new_fn_def(tcx, a_def_id, args))
         }
 
         (&ty::FnPtr(a_fty), &ty::FnPtr(b_fty)) => {
@@ -547,22 +546,22 @@ pub fn structurally_relate_tys<'tcx, R: TypeRelation<'tcx>>(
             Ok(Ty::new_fn_ptr(tcx, fty))
         }
 
-        // The substs of opaque types may not all be invariant, so we have
+        // The args of opaque types may not all be invariant, so we have
         // to treat them separately from other aliases.
         (
-            &ty::Alias(ty::Opaque, ty::AliasTy { def_id: a_def_id, substs: a_substs, .. }),
-            &ty::Alias(ty::Opaque, ty::AliasTy { def_id: b_def_id, substs: b_substs, .. }),
+            &ty::Alias(ty::Opaque, ty::AliasTy { def_id: a_def_id, args: a_args, .. }),
+            &ty::Alias(ty::Opaque, ty::AliasTy { def_id: b_def_id, args: b_args, .. }),
         ) if a_def_id == b_def_id => {
             let opt_variances = tcx.variances_of(a_def_id);
-            let substs = relate_substs_with_variances(
+            let args = relate_args_with_variances(
                 relation,
                 a_def_id,
                 opt_variances,
-                a_substs,
-                b_substs,
+                a_args,
+                b_args,
                 false, // do not fetch `type_of(a_def_id)`, as it will cause a cycle
             )?;
-            Ok(Ty::new_opaque(tcx, a_def_id, substs))
+            Ok(Ty::new_opaque(tcx, a_def_id, args))
         }
 
         // Alias tend to mostly already be handled downstream due to normalization.
@@ -618,15 +617,15 @@ pub fn structurally_relate_consts<'tcx, R: TypeRelation<'tcx>>(
         // be stabilized.
         (ty::ConstKind::Unevaluated(au), ty::ConstKind::Unevaluated(bu)) if au.def == bu.def => {
             assert_eq!(a.ty(), b.ty());
-            let substs = relation.relate_with_variance(
+            let args = relation.relate_with_variance(
                 ty::Variance::Invariant,
                 ty::VarianceDiagInfo::default(),
-                au.substs,
-                bu.substs,
+                au.args,
+                bu.args,
             )?;
             return Ok(ty::Const::new_unevaluated(
                 tcx,
-                ty::UnevaluatedConst { def: au.def, substs },
+                ty::UnevaluatedConst { def: au.def, args },
                 a.ty(),
             ));
         }
@@ -640,7 +639,7 @@ pub fn structurally_relate_consts<'tcx, R: TypeRelation<'tcx>>(
             // FIXME(generic_const_exprs): relating the `ty()`s is a little weird since it is supposed to
             // ICE If they mismatch. Unfortunately `ConstKind::Expr` is a little special and can be thought
             // of as being generic over the argument types, however this is implicit so these types don't get
-            // related when we relate the substs of the item this const arg is for.
+            // related when we relate the args of the item this const arg is for.
             let expr = match (ae, be) {
                 (Expr::Binop(a_op, al, ar), Expr::Binop(b_op, bl, br)) if a_op == b_op => {
                     r.relate(al.ty(), bl.ty())?;
@@ -714,35 +713,35 @@ impl<'tcx> Relate<'tcx> for &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>> {
     }
 }
 
-impl<'tcx> Relate<'tcx> for ty::ClosureSubsts<'tcx> {
+impl<'tcx> Relate<'tcx> for ty::ClosureArgs<'tcx> {
     fn relate<R: TypeRelation<'tcx>>(
         relation: &mut R,
-        a: ty::ClosureSubsts<'tcx>,
-        b: ty::ClosureSubsts<'tcx>,
-    ) -> RelateResult<'tcx, ty::ClosureSubsts<'tcx>> {
-        let substs = relate_substs(relation, a.substs, b.substs)?;
-        Ok(ty::ClosureSubsts { substs })
+        a: ty::ClosureArgs<'tcx>,
+        b: ty::ClosureArgs<'tcx>,
+    ) -> RelateResult<'tcx, ty::ClosureArgs<'tcx>> {
+        let args = relate_args(relation, a.args, b.args)?;
+        Ok(ty::ClosureArgs { args })
     }
 }
 
-impl<'tcx> Relate<'tcx> for ty::GeneratorSubsts<'tcx> {
+impl<'tcx> Relate<'tcx> for ty::GeneratorArgs<'tcx> {
     fn relate<R: TypeRelation<'tcx>>(
         relation: &mut R,
-        a: ty::GeneratorSubsts<'tcx>,
-        b: ty::GeneratorSubsts<'tcx>,
-    ) -> RelateResult<'tcx, ty::GeneratorSubsts<'tcx>> {
-        let substs = relate_substs(relation, a.substs, b.substs)?;
-        Ok(ty::GeneratorSubsts { substs })
+        a: ty::GeneratorArgs<'tcx>,
+        b: ty::GeneratorArgs<'tcx>,
+    ) -> RelateResult<'tcx, ty::GeneratorArgs<'tcx>> {
+        let args = relate_args(relation, a.args, b.args)?;
+        Ok(ty::GeneratorArgs { args })
     }
 }
 
-impl<'tcx> Relate<'tcx> for SubstsRef<'tcx> {
+impl<'tcx> Relate<'tcx> for GenericArgsRef<'tcx> {
     fn relate<R: TypeRelation<'tcx>>(
         relation: &mut R,
-        a: SubstsRef<'tcx>,
-        b: SubstsRef<'tcx>,
-    ) -> RelateResult<'tcx, SubstsRef<'tcx>> {
-        relate_substs(relation, a, b)
+        a: GenericArgsRef<'tcx>,
+        b: GenericArgsRef<'tcx>,
+    ) -> RelateResult<'tcx, GenericArgsRef<'tcx>> {
+        relate_args(relation, a, b)
     }
 }
 
diff --git a/compiler/rustc_middle/src/ty/rvalue_scopes.rs b/compiler/rustc_middle/src/ty/rvalue_scopes.rs
index e79b79a25ae..17eabec257e 100644
--- a/compiler/rustc_middle/src/ty/rvalue_scopes.rs
+++ b/compiler/rustc_middle/src/ty/rvalue_scopes.rs
@@ -1,12 +1,12 @@
 use crate::middle::region::{Scope, ScopeData, ScopeTree};
-use rustc_data_structures::fx::FxHashMap;
 use rustc_hir as hir;
+use rustc_hir::ItemLocalMap;
 
 /// `RvalueScopes` is a mapping from sub-expressions to _extended_ lifetime as determined by
 /// rules laid out in `rustc_hir_analysis::check::rvalue_scopes`.
 #[derive(TyEncodable, TyDecodable, Clone, Debug, Default, Eq, PartialEq, HashStable)]
 pub struct RvalueScopes {
-    map: FxHashMap<hir::ItemLocalId, Option<Scope>>,
+    map: ItemLocalMap<Option<Scope>>,
 }
 
 impl RvalueScopes {
diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs
index c82ce9112fc..9d380a58d9f 100644
--- a/compiler/rustc_middle/src/ty/structural_impls.rs
+++ b/compiler/rustc_middle/src/ty/structural_impls.rs
@@ -222,8 +222,8 @@ impl<'tcx> fmt::Debug for ty::PredicateKind<'tcx> {
             ty::PredicateKind::ObjectSafe(trait_def_id) => {
                 write!(f, "ObjectSafe({:?})", trait_def_id)
             }
-            ty::PredicateKind::ClosureKind(closure_def_id, closure_substs, kind) => {
-                write!(f, "ClosureKind({:?}, {:?}, {:?})", closure_def_id, closure_substs, kind)
+            ty::PredicateKind::ClosureKind(closure_def_id, closure_args, kind) => {
+                write!(f, "ClosureKind({:?}, {:?}, {:?})", closure_def_id, closure_args, kind)
             }
             ty::PredicateKind::ConstEquate(c1, c2) => write!(f, "ConstEquate({:?}, {:?})", c1, c2),
             ty::PredicateKind::Ambiguous => write!(f, "Ambiguous"),
@@ -245,7 +245,7 @@ impl<'tcx> DebugWithInfcx<TyCtxt<'tcx>> for AliasTy<'tcx> {
         f: &mut core::fmt::Formatter<'_>,
     ) -> core::fmt::Result {
         f.debug_struct("AliasTy")
-            .field("substs", &this.map(|data| data.substs))
+            .field("args", &this.map(|data| data.args))
             .field("def_id", &this.data.def_id)
             .finish()
     }
@@ -322,7 +322,7 @@ impl<'tcx> DebugWithInfcx<TyCtxt<'tcx>> for ty::UnevaluatedConst<'tcx> {
     ) -> core::fmt::Result {
         f.debug_struct("UnevaluatedConst")
             .field("def", &this.data.def)
-            .field("substs", &this.wrap(this.data.substs))
+            .field("args", &this.wrap(this.data.args))
             .finish()
     }
 }
@@ -695,26 +695,26 @@ impl<'tcx> TypeSuperFoldable<TyCtxt<'tcx>> for Ty<'tcx> {
             ty::RawPtr(tm) => ty::RawPtr(tm.try_fold_with(folder)?),
             ty::Array(typ, sz) => ty::Array(typ.try_fold_with(folder)?, sz.try_fold_with(folder)?),
             ty::Slice(typ) => ty::Slice(typ.try_fold_with(folder)?),
-            ty::Adt(tid, substs) => ty::Adt(tid, substs.try_fold_with(folder)?),
+            ty::Adt(tid, args) => ty::Adt(tid, args.try_fold_with(folder)?),
             ty::Dynamic(trait_ty, region, representation) => ty::Dynamic(
                 trait_ty.try_fold_with(folder)?,
                 region.try_fold_with(folder)?,
                 representation,
             ),
             ty::Tuple(ts) => ty::Tuple(ts.try_fold_with(folder)?),
-            ty::FnDef(def_id, substs) => ty::FnDef(def_id, substs.try_fold_with(folder)?),
+            ty::FnDef(def_id, args) => ty::FnDef(def_id, args.try_fold_with(folder)?),
             ty::FnPtr(f) => ty::FnPtr(f.try_fold_with(folder)?),
             ty::Ref(r, ty, mutbl) => {
                 ty::Ref(r.try_fold_with(folder)?, ty.try_fold_with(folder)?, mutbl)
             }
-            ty::Generator(did, substs, movability) => {
-                ty::Generator(did, substs.try_fold_with(folder)?, movability)
+            ty::Generator(did, args, movability) => {
+                ty::Generator(did, args.try_fold_with(folder)?, movability)
             }
             ty::GeneratorWitness(types) => ty::GeneratorWitness(types.try_fold_with(folder)?),
-            ty::GeneratorWitnessMIR(did, substs) => {
-                ty::GeneratorWitnessMIR(did, substs.try_fold_with(folder)?)
+            ty::GeneratorWitnessMIR(did, args) => {
+                ty::GeneratorWitnessMIR(did, args.try_fold_with(folder)?)
             }
-            ty::Closure(did, substs) => ty::Closure(did, substs.try_fold_with(folder)?),
+            ty::Closure(did, args) => ty::Closure(did, args.try_fold_with(folder)?),
             ty::Alias(kind, data) => ty::Alias(kind, data.try_fold_with(folder)?),
 
             ty::Bool
@@ -748,22 +748,22 @@ impl<'tcx> TypeSuperVisitable<TyCtxt<'tcx>> for Ty<'tcx> {
                 sz.visit_with(visitor)
             }
             ty::Slice(typ) => typ.visit_with(visitor),
-            ty::Adt(_, substs) => substs.visit_with(visitor),
+            ty::Adt(_, args) => args.visit_with(visitor),
             ty::Dynamic(ref trait_ty, ref reg, _) => {
                 trait_ty.visit_with(visitor)?;
                 reg.visit_with(visitor)
             }
             ty::Tuple(ts) => ts.visit_with(visitor),
-            ty::FnDef(_, substs) => substs.visit_with(visitor),
+            ty::FnDef(_, args) => args.visit_with(visitor),
             ty::FnPtr(ref f) => f.visit_with(visitor),
             ty::Ref(r, ty, _) => {
                 r.visit_with(visitor)?;
                 ty.visit_with(visitor)
             }
-            ty::Generator(_did, ref substs, _) => substs.visit_with(visitor),
+            ty::Generator(_did, ref args, _) => args.visit_with(visitor),
             ty::GeneratorWitness(ref types) => types.visit_with(visitor),
-            ty::GeneratorWitnessMIR(_did, ref substs) => substs.visit_with(visitor),
-            ty::Closure(_did, ref substs) => substs.visit_with(visitor),
+            ty::GeneratorWitnessMIR(_did, ref args) => args.visit_with(visitor),
+            ty::Closure(_did, ref args) => args.visit_with(visitor),
             ty::Alias(_, ref data) => data.visit_with(visitor),
 
             ty::Bool
@@ -943,7 +943,7 @@ impl<'tcx> TypeSuperVisitable<TyCtxt<'tcx>> for ty::UnevaluatedConst<'tcx> {
         &self,
         visitor: &mut V,
     ) -> ControlFlow<V::BreakTy> {
-        self.substs.visit_with(visitor)
+        self.args.visit_with(visitor)
     }
 }
 
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index 9f4515b95e7..66d8a79de42 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -3,13 +3,13 @@
 #![allow(rustc::usage_of_ty_tykind)]
 
 use crate::infer::canonical::Canonical;
-use crate::ty::subst::{GenericArg, InternalSubsts, SubstsRef};
 use crate::ty::visit::ValidateBoundVars;
 use crate::ty::InferTy::*;
 use crate::ty::{
     self, AdtDef, Discr, Term, Ty, TyCtxt, TypeFlags, TypeSuperVisitable, TypeVisitable,
     TypeVisitableExt, TypeVisitor,
 };
+use crate::ty::{GenericArg, GenericArgs, GenericArgsRef};
 use crate::ty::{List, ParamEnv};
 use hir::def::DefKind;
 use polonius_engine::Atom;
@@ -218,7 +218,7 @@ impl<'tcx> Article for TyKind<'tcx> {
 ///
 /// ## Generators
 ///
-/// Generators are handled similarly in `GeneratorSubsts`. The set of
+/// Generators are handled similarly in `GeneratorArgs`. The set of
 /// type parameters is similar, but `CK` and `CS` are replaced by the
 /// following type parameters:
 ///
@@ -231,33 +231,30 @@ impl<'tcx> Article for TyKind<'tcx> {
 ///   completion of the generator.
 /// * `GW`: The "generator witness".
 #[derive(Copy, Clone, PartialEq, Eq, Debug, TypeFoldable, TypeVisitable, Lift)]
-pub struct ClosureSubsts<'tcx> {
+pub struct ClosureArgs<'tcx> {
     /// Lifetime and type parameters from the enclosing function,
     /// concatenated with a tuple containing the types of the upvars.
     ///
     /// These are separated out because codegen wants to pass them around
     /// when monomorphizing.
-    pub substs: SubstsRef<'tcx>,
+    pub args: GenericArgsRef<'tcx>,
 }
 
 /// Struct returned by `split()`.
-pub struct ClosureSubstsParts<'tcx, T> {
-    pub parent_substs: &'tcx [GenericArg<'tcx>],
+pub struct ClosureArgsParts<'tcx, T> {
+    pub parent_args: &'tcx [GenericArg<'tcx>],
     pub closure_kind_ty: T,
     pub closure_sig_as_fn_ptr_ty: T,
     pub tupled_upvars_ty: T,
 }
 
-impl<'tcx> ClosureSubsts<'tcx> {
-    /// Construct `ClosureSubsts` from `ClosureSubstsParts`, containing `Substs`
+impl<'tcx> ClosureArgs<'tcx> {
+    /// Construct `ClosureArgs` from `ClosureArgsParts`, containing `Args`
     /// for the closure parent, alongside additional closure-specific components.
-    pub fn new(
-        tcx: TyCtxt<'tcx>,
-        parts: ClosureSubstsParts<'tcx, Ty<'tcx>>,
-    ) -> ClosureSubsts<'tcx> {
-        ClosureSubsts {
-            substs: tcx.mk_substs_from_iter(
-                parts.parent_substs.iter().copied().chain(
+    pub fn new(tcx: TyCtxt<'tcx>, parts: ClosureArgsParts<'tcx, Ty<'tcx>>) -> ClosureArgs<'tcx> {
+        ClosureArgs {
+            args: tcx.mk_args_from_iter(
+                parts.parent_args.iter().copied().chain(
                     [parts.closure_kind_ty, parts.closure_sig_as_fn_ptr_ty, parts.tupled_upvars_ty]
                         .iter()
                         .map(|&ty| ty.into()),
@@ -266,38 +263,34 @@ impl<'tcx> ClosureSubsts<'tcx> {
         }
     }
 
-    /// Divides the closure substs into their respective components.
-    /// The ordering assumed here must match that used by `ClosureSubsts::new` above.
-    fn split(self) -> ClosureSubstsParts<'tcx, GenericArg<'tcx>> {
-        match self.substs[..] {
-            [
-                ref parent_substs @ ..,
-                closure_kind_ty,
-                closure_sig_as_fn_ptr_ty,
-                tupled_upvars_ty,
-            ] => ClosureSubstsParts {
-                parent_substs,
-                closure_kind_ty,
-                closure_sig_as_fn_ptr_ty,
-                tupled_upvars_ty,
-            },
-            _ => bug!("closure substs missing synthetics"),
+    /// Divides the closure args into their respective components.
+    /// The ordering assumed here must match that used by `ClosureArgs::new` above.
+    fn split(self) -> ClosureArgsParts<'tcx, GenericArg<'tcx>> {
+        match self.args[..] {
+            [ref parent_args @ .., closure_kind_ty, closure_sig_as_fn_ptr_ty, tupled_upvars_ty] => {
+                ClosureArgsParts {
+                    parent_args,
+                    closure_kind_ty,
+                    closure_sig_as_fn_ptr_ty,
+                    tupled_upvars_ty,
+                }
+            }
+            _ => bug!("closure args missing synthetics"),
         }
     }
 
     /// Returns `true` only if enough of the synthetic types are known to
-    /// allow using all of the methods on `ClosureSubsts` without panicking.
+    /// allow using all of the methods on `ClosureArgs` without panicking.
     ///
     /// Used primarily by `ty::print::pretty` to be able to handle closure
     /// types that haven't had their synthetic types substituted in.
     pub fn is_valid(self) -> bool {
-        self.substs.len() >= 3
-            && matches!(self.split().tupled_upvars_ty.expect_ty().kind(), Tuple(_))
+        self.args.len() >= 3 && matches!(self.split().tupled_upvars_ty.expect_ty().kind(), Tuple(_))
     }
 
     /// Returns the substitutions of the closure's parent.
-    pub fn parent_substs(self) -> &'tcx [GenericArg<'tcx>] {
-        self.split().parent_substs
+    pub fn parent_args(self) -> &'tcx [GenericArg<'tcx>] {
+        self.split().parent_args
     }
 
     /// Returns an iterator over the list of types of captured paths by the closure.
@@ -323,7 +316,7 @@ impl<'tcx> ClosureSubsts<'tcx> {
 
     /// Returns the closure kind for this closure; may return a type
     /// variable during inference. To get the closure kind during
-    /// inference, use `infcx.closure_kind(substs)`.
+    /// inference, use `infcx.closure_kind(args)`.
     pub fn kind_ty(self) -> Ty<'tcx> {
         self.split().closure_kind_ty.expect_ty()
     }
@@ -331,7 +324,7 @@ impl<'tcx> ClosureSubsts<'tcx> {
     /// Returns the `fn` pointer type representing the closure signature for this
     /// closure.
     // FIXME(eddyb) this should be unnecessary, as the shallowly resolved
-    // type is known at the time of the creation of `ClosureSubsts`,
+    // type is known at the time of the creation of `ClosureArgs`,
     // see `rustc_hir_analysis::check::closure`.
     pub fn sig_as_fn_ptr_ty(self) -> Ty<'tcx> {
         self.split().closure_sig_as_fn_ptr_ty.expect_ty()
@@ -360,14 +353,14 @@ impl<'tcx> ClosureSubsts<'tcx> {
     }
 }
 
-/// Similar to `ClosureSubsts`; see the above documentation for more.
+/// Similar to `ClosureArgs`; see the above documentation for more.
 #[derive(Copy, Clone, PartialEq, Eq, Debug, TypeFoldable, TypeVisitable, Lift)]
-pub struct GeneratorSubsts<'tcx> {
-    pub substs: SubstsRef<'tcx>,
+pub struct GeneratorArgs<'tcx> {
+    pub args: GenericArgsRef<'tcx>,
 }
 
-pub struct GeneratorSubstsParts<'tcx, T> {
-    pub parent_substs: &'tcx [GenericArg<'tcx>],
+pub struct GeneratorArgsParts<'tcx, T> {
+    pub parent_args: &'tcx [GenericArg<'tcx>],
     pub resume_ty: T,
     pub yield_ty: T,
     pub return_ty: T,
@@ -375,16 +368,16 @@ pub struct GeneratorSubstsParts<'tcx, T> {
     pub tupled_upvars_ty: T,
 }
 
-impl<'tcx> GeneratorSubsts<'tcx> {
-    /// Construct `GeneratorSubsts` from `GeneratorSubstsParts`, containing `Substs`
+impl<'tcx> GeneratorArgs<'tcx> {
+    /// Construct `GeneratorArgs` from `GeneratorArgsParts`, containing `Args`
     /// for the generator parent, alongside additional generator-specific components.
     pub fn new(
         tcx: TyCtxt<'tcx>,
-        parts: GeneratorSubstsParts<'tcx, Ty<'tcx>>,
-    ) -> GeneratorSubsts<'tcx> {
-        GeneratorSubsts {
-            substs: tcx.mk_substs_from_iter(
-                parts.parent_substs.iter().copied().chain(
+        parts: GeneratorArgsParts<'tcx, Ty<'tcx>>,
+    ) -> GeneratorArgs<'tcx> {
+        GeneratorArgs {
+            args: tcx.mk_args_from_iter(
+                parts.parent_args.iter().copied().chain(
                     [
                         parts.resume_ty,
                         parts.yield_ty,
@@ -399,13 +392,13 @@ impl<'tcx> GeneratorSubsts<'tcx> {
         }
     }
 
-    /// Divides the generator substs into their respective components.
-    /// The ordering assumed here must match that used by `GeneratorSubsts::new` above.
-    fn split(self) -> GeneratorSubstsParts<'tcx, GenericArg<'tcx>> {
-        match self.substs[..] {
-            [ref parent_substs @ .., resume_ty, yield_ty, return_ty, witness, tupled_upvars_ty] => {
-                GeneratorSubstsParts {
-                    parent_substs,
+    /// Divides the generator args into their respective components.
+    /// The ordering assumed here must match that used by `GeneratorArgs::new` above.
+    fn split(self) -> GeneratorArgsParts<'tcx, GenericArg<'tcx>> {
+        match self.args[..] {
+            [ref parent_args @ .., resume_ty, yield_ty, return_ty, witness, tupled_upvars_ty] => {
+                GeneratorArgsParts {
+                    parent_args,
                     resume_ty,
                     yield_ty,
                     return_ty,
@@ -413,23 +406,22 @@ impl<'tcx> GeneratorSubsts<'tcx> {
                     tupled_upvars_ty,
                 }
             }
-            _ => bug!("generator substs missing synthetics"),
+            _ => bug!("generator args missing synthetics"),
         }
     }
 
     /// Returns `true` only if enough of the synthetic types are known to
-    /// allow using all of the methods on `GeneratorSubsts` without panicking.
+    /// allow using all of the methods on `GeneratorArgs` without panicking.
     ///
     /// Used primarily by `ty::print::pretty` to be able to handle generator
     /// types that haven't had their synthetic types substituted in.
     pub fn is_valid(self) -> bool {
-        self.substs.len() >= 5
-            && matches!(self.split().tupled_upvars_ty.expect_ty().kind(), Tuple(_))
+        self.args.len() >= 5 && matches!(self.split().tupled_upvars_ty.expect_ty().kind(), Tuple(_))
     }
 
     /// Returns the substitutions of the generator's parent.
-    pub fn parent_substs(self) -> &'tcx [GenericArg<'tcx>] {
-        self.split().parent_substs
+    pub fn parent_args(self) -> &'tcx [GenericArg<'tcx>] {
+        self.split().parent_args
     }
 
     /// This describes the types that can be contained in a generator.
@@ -498,7 +490,7 @@ impl<'tcx> GeneratorSubsts<'tcx> {
     }
 }
 
-impl<'tcx> GeneratorSubsts<'tcx> {
+impl<'tcx> GeneratorArgs<'tcx> {
     /// Generator has not been resumed yet.
     pub const UNRESUMED: usize = 0;
     /// Generator has returned or is completed.
@@ -577,7 +569,7 @@ impl<'tcx> GeneratorSubsts<'tcx> {
         let layout = tcx.generator_layout(def_id).unwrap();
         layout.variant_fields.iter().map(move |variant| {
             variant.iter().map(move |field| {
-                ty::EarlyBinder::bind(layout.field_tys[*field].ty).subst(tcx, self.substs)
+                ty::EarlyBinder::bind(layout.field_tys[*field].ty).instantiate(tcx, self.args)
             })
         })
     }
@@ -591,20 +583,20 @@ impl<'tcx> GeneratorSubsts<'tcx> {
 }
 
 #[derive(Debug, Copy, Clone, HashStable)]
-pub enum UpvarSubsts<'tcx> {
-    Closure(SubstsRef<'tcx>),
-    Generator(SubstsRef<'tcx>),
+pub enum UpvarArgs<'tcx> {
+    Closure(GenericArgsRef<'tcx>),
+    Generator(GenericArgsRef<'tcx>),
 }
 
-impl<'tcx> UpvarSubsts<'tcx> {
+impl<'tcx> UpvarArgs<'tcx> {
     /// Returns an iterator over the list of types of captured paths by the closure/generator.
     /// In case there was a type error in figuring out the types of the captured path, an
     /// empty iterator is returned.
     #[inline]
     pub fn upvar_tys(self) -> impl Iterator<Item = Ty<'tcx>> + 'tcx {
         let tupled_tys = match self {
-            UpvarSubsts::Closure(substs) => substs.as_closure().tupled_upvars_ty(),
-            UpvarSubsts::Generator(substs) => substs.as_generator().tupled_upvars_ty(),
+            UpvarArgs::Closure(args) => args.as_closure().tupled_upvars_ty(),
+            UpvarArgs::Generator(args) => args.as_generator().tupled_upvars_ty(),
         };
 
         match tupled_tys.kind() {
@@ -620,8 +612,8 @@ impl<'tcx> UpvarSubsts<'tcx> {
     #[inline]
     pub fn tupled_upvars_ty(self) -> Ty<'tcx> {
         match self {
-            UpvarSubsts::Closure(substs) => substs.as_closure().tupled_upvars_ty(),
-            UpvarSubsts::Generator(substs) => substs.as_generator().tupled_upvars_ty(),
+            UpvarArgs::Closure(args) => args.as_closure().tupled_upvars_ty(),
+            UpvarArgs::Generator(args) => args.as_generator().tupled_upvars_ty(),
         }
     }
 }
@@ -638,46 +630,46 @@ impl<'tcx> UpvarSubsts<'tcx> {
 ///
 /// When the inline const is instantiated, `R` is substituted as the actual inferred
 /// type of the constant. The reason that `R` is represented as an extra type parameter
-/// is the same reason that [`ClosureSubsts`] have `CS` and `U` as type parameters:
+/// is the same reason that [`ClosureArgs`] have `CS` and `U` as type parameters:
 /// inline const can reference lifetimes that are internal to the creating function.
 #[derive(Copy, Clone, Debug)]
-pub struct InlineConstSubsts<'tcx> {
+pub struct InlineConstArgs<'tcx> {
     /// Generic parameters from the enclosing item,
     /// concatenated with the inferred type of the constant.
-    pub substs: SubstsRef<'tcx>,
+    pub args: GenericArgsRef<'tcx>,
 }
 
 /// Struct returned by `split()`.
-pub struct InlineConstSubstsParts<'tcx, T> {
-    pub parent_substs: &'tcx [GenericArg<'tcx>],
+pub struct InlineConstArgsParts<'tcx, T> {
+    pub parent_args: &'tcx [GenericArg<'tcx>],
     pub ty: T,
 }
 
-impl<'tcx> InlineConstSubsts<'tcx> {
-    /// Construct `InlineConstSubsts` from `InlineConstSubstsParts`.
+impl<'tcx> InlineConstArgs<'tcx> {
+    /// Construct `InlineConstArgs` from `InlineConstArgsParts`.
     pub fn new(
         tcx: TyCtxt<'tcx>,
-        parts: InlineConstSubstsParts<'tcx, Ty<'tcx>>,
-    ) -> InlineConstSubsts<'tcx> {
-        InlineConstSubsts {
-            substs: tcx.mk_substs_from_iter(
-                parts.parent_substs.iter().copied().chain(std::iter::once(parts.ty.into())),
+        parts: InlineConstArgsParts<'tcx, Ty<'tcx>>,
+    ) -> InlineConstArgs<'tcx> {
+        InlineConstArgs {
+            args: tcx.mk_args_from_iter(
+                parts.parent_args.iter().copied().chain(std::iter::once(parts.ty.into())),
             ),
         }
     }
 
-    /// Divides the inline const substs into their respective components.
-    /// The ordering assumed here must match that used by `InlineConstSubsts::new` above.
-    fn split(self) -> InlineConstSubstsParts<'tcx, GenericArg<'tcx>> {
-        match self.substs[..] {
-            [ref parent_substs @ .., ty] => InlineConstSubstsParts { parent_substs, ty },
-            _ => bug!("inline const substs missing synthetics"),
+    /// Divides the inline const args into their respective components.
+    /// The ordering assumed here must match that used by `InlineConstArgs::new` above.
+    fn split(self) -> InlineConstArgsParts<'tcx, GenericArg<'tcx>> {
+        match self.args[..] {
+            [ref parent_args @ .., ty] => InlineConstArgsParts { parent_args, ty },
+            _ => bug!("inline const args missing synthetics"),
         }
     }
 
     /// Returns the substitutions of the inline const's parent.
-    pub fn parent_substs(self) -> &'tcx [GenericArg<'tcx>] {
-        self.split().parent_substs
+    pub fn parent_args(self) -> &'tcx [GenericArg<'tcx>] {
+        self.split().parent_args
     }
 
     /// Returns the type of this inline const.
@@ -748,10 +740,9 @@ impl<'tcx> PolyExistentialPredicate<'tcx> {
                     ty::TraitRef::new(tcx, did, [self_ty])
                 } else {
                     // If this is an ill-formed auto trait, then synthesize
-                    // new error substs for the missing generics.
-                    let err_substs =
-                        ty::InternalSubsts::extend_with_error(tcx, did, &[self_ty.into()]);
-                    ty::TraitRef::new(tcx, did, err_substs)
+                    // new error args for the missing generics.
+                    let err_args = ty::GenericArgs::extend_with_error(tcx, did, &[self_ty.into()]);
+                    ty::TraitRef::new(tcx, did, err_args)
                 };
                 self.rebind(trait_ref).without_const().to_predicate(tcx)
             }
@@ -827,7 +818,7 @@ impl<'tcx> List<ty::PolyExistentialPredicate<'tcx>> {
 /// T: Foo<U>
 /// ```
 /// This would be represented by a trait-reference where the `DefId` is the
-/// `DefId` for the trait `Foo` and the substs define `T` as parameter 0,
+/// `DefId` for the trait `Foo` and the args define `T` as parameter 0,
 /// and `U` as parameter 1.
 ///
 /// Trait references also appear in object types like `Foo<U>`, but in
@@ -836,7 +827,7 @@ impl<'tcx> List<ty::PolyExistentialPredicate<'tcx>> {
 #[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
 pub struct TraitRef<'tcx> {
     pub def_id: DefId,
-    pub substs: SubstsRef<'tcx>,
+    pub args: GenericArgsRef<'tcx>,
     /// This field exists to prevent the creation of `TraitRef` without
     /// calling [`TraitRef::new`].
     pub(super) _use_trait_ref_new_instead: (),
@@ -846,42 +837,42 @@ impl<'tcx> TraitRef<'tcx> {
     pub fn new(
         tcx: TyCtxt<'tcx>,
         trait_def_id: DefId,
-        substs: impl IntoIterator<Item: Into<GenericArg<'tcx>>>,
+        args: impl IntoIterator<Item: Into<GenericArg<'tcx>>>,
     ) -> Self {
-        let substs = tcx.check_and_mk_substs(trait_def_id, substs);
-        Self { def_id: trait_def_id, substs, _use_trait_ref_new_instead: () }
+        let args = tcx.check_and_mk_args(trait_def_id, args);
+        Self { def_id: trait_def_id, args, _use_trait_ref_new_instead: () }
     }
 
     pub fn from_lang_item(
         tcx: TyCtxt<'tcx>,
         trait_lang_item: LangItem,
         span: Span,
-        substs: impl IntoIterator<Item: Into<ty::GenericArg<'tcx>>>,
+        args: impl IntoIterator<Item: Into<ty::GenericArg<'tcx>>>,
     ) -> Self {
         let trait_def_id = tcx.require_lang_item(trait_lang_item, Some(span));
-        Self::new(tcx, trait_def_id, substs)
+        Self::new(tcx, trait_def_id, args)
     }
 
     pub fn from_method(
         tcx: TyCtxt<'tcx>,
         trait_id: DefId,
-        substs: SubstsRef<'tcx>,
+        args: GenericArgsRef<'tcx>,
     ) -> ty::TraitRef<'tcx> {
         let defs = tcx.generics_of(trait_id);
-        ty::TraitRef::new(tcx, trait_id, tcx.mk_substs(&substs[..defs.params.len()]))
+        ty::TraitRef::new(tcx, trait_id, tcx.mk_args(&args[..defs.params.len()]))
     }
 
     /// Returns a `TraitRef` of the form `P0: Foo<P1..Pn>` where `Pi`
     /// are the parameters defined on trait.
     pub fn identity(tcx: TyCtxt<'tcx>, def_id: DefId) -> TraitRef<'tcx> {
-        ty::TraitRef::new(tcx, def_id, InternalSubsts::identity_for_item(tcx, def_id))
+        ty::TraitRef::new(tcx, def_id, GenericArgs::identity_for_item(tcx, def_id))
     }
 
     pub fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self {
         ty::TraitRef::new(
             tcx,
             self.def_id,
-            [self_ty.into()].into_iter().chain(self.substs.iter().skip(1)),
+            [self_ty.into()].into_iter().chain(self.args.iter().skip(1)),
         )
     }
 
@@ -899,7 +890,7 @@ impl<'tcx> TraitRef<'tcx> {
 
     #[inline]
     pub fn self_ty(&self) -> Ty<'tcx> {
-        self.substs.type_at(0)
+        self.args.type_at(0)
     }
 }
 
@@ -932,7 +923,7 @@ impl<'tcx> IntoDiagnosticArg for TraitRef<'tcx> {
 #[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
 pub struct ExistentialTraitRef<'tcx> {
     pub def_id: DefId,
-    pub substs: SubstsRef<'tcx>,
+    pub args: GenericArgsRef<'tcx>,
 }
 
 impl<'tcx> ExistentialTraitRef<'tcx> {
@@ -941,11 +932,11 @@ impl<'tcx> ExistentialTraitRef<'tcx> {
         trait_ref: ty::TraitRef<'tcx>,
     ) -> ty::ExistentialTraitRef<'tcx> {
         // Assert there is a Self.
-        trait_ref.substs.type_at(0);
+        trait_ref.args.type_at(0);
 
         ty::ExistentialTraitRef {
             def_id: trait_ref.def_id,
-            substs: tcx.mk_substs(&trait_ref.substs[1..]),
+            args: tcx.mk_args(&trait_ref.args[1..]),
         }
     }
 
@@ -957,7 +948,7 @@ impl<'tcx> ExistentialTraitRef<'tcx> {
         // otherwise the escaping vars would be captured by the binder
         // debug_assert!(!self_ty.has_escaping_bound_vars());
 
-        ty::TraitRef::new(tcx, self.def_id, [self_ty.into()].into_iter().chain(self.substs.iter()))
+        ty::TraitRef::new(tcx, self.def_id, [self_ty.into()].into_iter().chain(self.args.iter()))
     }
 }
 
@@ -1226,7 +1217,7 @@ pub struct AliasTy<'tcx> {
     ///
     /// For RPIT the substitutions are for the generics of the function,
     /// while for TAIT it is used for the generic parameters of the alias.
-    pub substs: SubstsRef<'tcx>,
+    pub args: GenericArgsRef<'tcx>,
 
     /// The `DefId` of the `TraitItem` or `ImplItem` for the associated type `N` depending on whether
     /// this is a projection or an inherent projection or the `DefId` of the `OpaqueType` item if
@@ -1264,11 +1255,11 @@ impl<'tcx> AliasTy<'tcx> {
 /// The following methods work only with associated type projections.
 impl<'tcx> AliasTy<'tcx> {
     pub fn self_ty(self) -> Ty<'tcx> {
-        self.substs.type_at(0)
+        self.args.type_at(0)
     }
 
     pub fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self {
-        tcx.mk_alias_ty(self.def_id, [self_ty.into()].into_iter().chain(self.substs.iter().skip(1)))
+        tcx.mk_alias_ty(self.def_id, [self_ty.into()].into_iter().chain(self.args.iter().skip(1)))
     }
 }
 
@@ -1281,10 +1272,10 @@ impl<'tcx> AliasTy<'tcx> {
         }
     }
 
-    /// Extracts the underlying trait reference and own substs from this projection.
+    /// Extracts the underlying trait reference and own args from this projection.
     /// For example, if this is a projection of `<T as StreamingIterator>::Item<'a>`,
-    /// then this function would return a `T: StreamingIterator` trait reference and `['a]` as the own substs
-    pub fn trait_ref_and_own_substs(
+    /// then this function would return a `T: StreamingIterator` trait reference and `['a]` as the own args
+    pub fn trait_ref_and_own_args(
         self,
         tcx: TyCtxt<'tcx>,
     ) -> (ty::TraitRef<'tcx>, &'tcx [ty::GenericArg<'tcx>]) {
@@ -1292,8 +1283,8 @@ impl<'tcx> AliasTy<'tcx> {
         let trait_def_id = self.trait_def_id(tcx);
         let trait_generics = tcx.generics_of(trait_def_id);
         (
-            ty::TraitRef::new(tcx, trait_def_id, self.substs.truncate_to(tcx, trait_generics)),
-            &self.substs[trait_generics.count()..],
+            ty::TraitRef::new(tcx, trait_def_id, self.args.truncate_to(tcx, trait_generics)),
+            &self.args[trait_generics.count()..],
         )
     }
 
@@ -1301,18 +1292,18 @@ impl<'tcx> AliasTy<'tcx> {
     /// For example, if this is a projection of `<T as Iterator>::Item`,
     /// then this function would return a `T: Iterator` trait reference.
     ///
-    /// WARNING: This will drop the substs for generic associated types
-    /// consider calling [Self::trait_ref_and_own_substs] to get those
+    /// WARNING: This will drop the args for generic associated types
+    /// consider calling [Self::trait_ref_and_own_args] to get those
     /// as well.
     pub fn trait_ref(self, tcx: TyCtxt<'tcx>) -> ty::TraitRef<'tcx> {
         let def_id = self.trait_def_id(tcx);
-        ty::TraitRef::new(tcx, def_id, self.substs.truncate_to(tcx, tcx.generics_of(def_id)))
+        ty::TraitRef::new(tcx, def_id, self.args.truncate_to(tcx, tcx.generics_of(def_id)))
     }
 }
 
 /// The following methods work only with inherent associated type projections.
 impl<'tcx> AliasTy<'tcx> {
-    /// Transform the substitutions to have the given `impl` substs as the base and the GAT substs on top of that.
+    /// Transform the substitutions to have the given `impl` args as the base and the GAT args on top of that.
     ///
     /// Does the following transformation:
     ///
@@ -1322,14 +1313,14 @@ impl<'tcx> AliasTy<'tcx> {
     ///     I_i impl subst
     ///     P_j GAT subst
     /// ```
-    pub fn rebase_substs_onto_impl(
+    pub fn rebase_args_onto_impl(
         self,
-        impl_substs: ty::SubstsRef<'tcx>,
+        impl_args: ty::GenericArgsRef<'tcx>,
         tcx: TyCtxt<'tcx>,
-    ) -> ty::SubstsRef<'tcx> {
+    ) -> ty::GenericArgsRef<'tcx> {
         debug_assert_eq!(self.kind(tcx), ty::Inherent);
 
-        tcx.mk_substs_from_iter(impl_substs.into_iter().chain(self.substs.into_iter().skip(1)))
+        tcx.mk_args_from_iter(impl_args.into_iter().chain(self.args.into_iter().skip(1)))
     }
 }
 
@@ -1649,7 +1640,7 @@ impl From<BoundVar> for BoundTy {
 #[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
 pub struct ExistentialProjection<'tcx> {
     pub def_id: DefId,
-    pub substs: SubstsRef<'tcx>,
+    pub args: GenericArgsRef<'tcx>,
     pub term: Term<'tcx>,
 }
 
@@ -1663,8 +1654,8 @@ impl<'tcx> ExistentialProjection<'tcx> {
     pub fn trait_ref(&self, tcx: TyCtxt<'tcx>) -> ty::ExistentialTraitRef<'tcx> {
         let def_id = tcx.parent(self.def_id);
         let subst_count = tcx.generics_of(def_id).count() - 1;
-        let substs = tcx.mk_substs(&self.substs[..subst_count]);
-        ty::ExistentialTraitRef { def_id, substs }
+        let args = tcx.mk_args(&self.args[..subst_count]);
+        ty::ExistentialTraitRef { def_id, args }
     }
 
     pub fn with_self_ty(
@@ -1677,7 +1668,7 @@ impl<'tcx> ExistentialProjection<'tcx> {
 
         ty::ProjectionPredicate {
             projection_ty: tcx
-                .mk_alias_ty(self.def_id, [self_ty.into()].into_iter().chain(self.substs)),
+                .mk_alias_ty(self.def_id, [self_ty.into()].into_iter().chain(self.args)),
             term: self.term,
         }
     }
@@ -1687,11 +1678,11 @@ impl<'tcx> ExistentialProjection<'tcx> {
         projection_predicate: ty::ProjectionPredicate<'tcx>,
     ) -> Self {
         // Assert there is a Self.
-        projection_predicate.projection_ty.substs.type_at(0);
+        projection_predicate.projection_ty.args.type_at(0);
 
         Self {
             def_id: projection_predicate.projection_ty.def_id,
-            substs: tcx.mk_substs(&projection_predicate.projection_ty.substs[1..]),
+            args: tcx.mk_args(&projection_predicate.projection_ty.args[1..]),
             term: projection_predicate.term,
         }
     }
@@ -1979,8 +1970,8 @@ impl<'tcx> Ty<'tcx> {
     }
 
     #[inline]
-    pub fn new_opaque(tcx: TyCtxt<'tcx>, def_id: DefId, substs: SubstsRef<'tcx>) -> Ty<'tcx> {
-        Ty::new_alias(tcx, ty::Opaque, tcx.mk_alias_ty(def_id, substs))
+    pub fn new_opaque(tcx: TyCtxt<'tcx>, def_id: DefId, args: GenericArgsRef<'tcx>) -> Ty<'tcx> {
+        Ty::new_alias(tcx, ty::Opaque, tcx.mk_alias_ty(def_id, args))
     }
 
     /// Constructs a `TyKind::Error` type with current `ErrorGuaranteed`
@@ -2072,8 +2063,8 @@ impl<'tcx> Ty<'tcx> {
     }
 
     #[inline]
-    pub fn new_adt(tcx: TyCtxt<'tcx>, def: AdtDef<'tcx>, substs: SubstsRef<'tcx>) -> Ty<'tcx> {
-        Ty::new(tcx, Adt(def, substs))
+    pub fn new_adt(tcx: TyCtxt<'tcx>, def: AdtDef<'tcx>, args: GenericArgsRef<'tcx>) -> Ty<'tcx> {
+        Ty::new(tcx, Adt(def, args))
     }
 
     #[inline]
@@ -2117,10 +2108,10 @@ impl<'tcx> Ty<'tcx> {
     pub fn new_fn_def(
         tcx: TyCtxt<'tcx>,
         def_id: DefId,
-        substs: impl IntoIterator<Item: Into<GenericArg<'tcx>>>,
+        args: impl IntoIterator<Item: Into<GenericArg<'tcx>>>,
     ) -> Ty<'tcx> {
-        let substs = tcx.check_and_mk_substs(def_id, substs);
-        Ty::new(tcx, FnDef(def_id, substs))
+        let args = tcx.check_and_mk_args(def_id, args);
+        Ty::new(tcx, FnDef(def_id, args))
     }
 
     #[inline]
@@ -2142,38 +2133,38 @@ impl<'tcx> Ty<'tcx> {
     pub fn new_projection(
         tcx: TyCtxt<'tcx>,
         item_def_id: DefId,
-        substs: impl IntoIterator<Item: Into<GenericArg<'tcx>>>,
+        args: impl IntoIterator<Item: Into<GenericArg<'tcx>>>,
     ) -> Ty<'tcx> {
-        Ty::new_alias(tcx, ty::Projection, tcx.mk_alias_ty(item_def_id, substs))
+        Ty::new_alias(tcx, ty::Projection, tcx.mk_alias_ty(item_def_id, args))
     }
 
     #[inline]
     pub fn new_closure(
         tcx: TyCtxt<'tcx>,
         def_id: DefId,
-        closure_substs: SubstsRef<'tcx>,
+        closure_args: GenericArgsRef<'tcx>,
     ) -> Ty<'tcx> {
         debug_assert_eq!(
-            closure_substs.len(),
+            closure_args.len(),
             tcx.generics_of(tcx.typeck_root_def_id(def_id)).count() + 3,
             "closure constructed with incorrect substitutions"
         );
-        Ty::new(tcx, Closure(def_id, closure_substs))
+        Ty::new(tcx, Closure(def_id, closure_args))
     }
 
     #[inline]
     pub fn new_generator(
         tcx: TyCtxt<'tcx>,
         def_id: DefId,
-        generator_substs: SubstsRef<'tcx>,
+        generator_args: GenericArgsRef<'tcx>,
         movability: hir::Movability,
     ) -> Ty<'tcx> {
         debug_assert_eq!(
-            generator_substs.len(),
+            generator_args.len(),
             tcx.generics_of(tcx.typeck_root_def_id(def_id)).count() + 5,
             "generator constructed with incorrect number of substitutions"
         );
-        Ty::new(tcx, Generator(def_id, generator_substs, movability))
+        Ty::new(tcx, Generator(def_id, generator_args, movability))
     }
 
     #[inline]
@@ -2188,9 +2179,9 @@ impl<'tcx> Ty<'tcx> {
     pub fn new_generator_witness_mir(
         tcx: TyCtxt<'tcx>,
         id: DefId,
-        substs: SubstsRef<'tcx>,
+        args: GenericArgsRef<'tcx>,
     ) -> Ty<'tcx> {
-        Ty::new(tcx, GeneratorWitnessMIR(id, substs))
+        Ty::new(tcx, GeneratorWitnessMIR(id, args))
     }
 
     // misc
@@ -2214,19 +2205,18 @@ impl<'tcx> Ty<'tcx> {
 
     fn new_generic_adt(tcx: TyCtxt<'tcx>, wrapper_def_id: DefId, ty_param: Ty<'tcx>) -> Ty<'tcx> {
         let adt_def = tcx.adt_def(wrapper_def_id);
-        let substs =
-            InternalSubsts::for_item(tcx, wrapper_def_id, |param, substs| match param.kind {
-                GenericParamDefKind::Lifetime | GenericParamDefKind::Const { .. } => bug!(),
-                GenericParamDefKind::Type { has_default, .. } => {
-                    if param.index == 0 {
-                        ty_param.into()
-                    } else {
-                        assert!(has_default);
-                        tcx.type_of(param.def_id).subst(tcx, substs).into()
-                    }
+        let args = GenericArgs::for_item(tcx, wrapper_def_id, |param, args| match param.kind {
+            GenericParamDefKind::Lifetime | GenericParamDefKind::Const { .. } => bug!(),
+            GenericParamDefKind::Type { has_default, .. } => {
+                if param.index == 0 {
+                    ty_param.into()
+                } else {
+                    assert!(has_default);
+                    tcx.type_of(param.def_id).instantiate(tcx, args).into()
                 }
-            });
-        Ty::new(tcx, Adt(adt_def, substs))
+            }
+        });
+        Ty::new(tcx, Adt(adt_def, args))
     }
 
     #[inline]
@@ -2257,8 +2247,8 @@ impl<'tcx> Ty<'tcx> {
     pub fn new_task_context(tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
         let context_did = tcx.require_lang_item(LangItem::Context, None);
         let context_adt_ref = tcx.adt_def(context_did);
-        let context_substs = tcx.mk_substs(&[tcx.lifetimes.re_erased.into()]);
-        let context_ty = Ty::new_adt(tcx, context_adt_ref, context_substs);
+        let context_args = tcx.mk_args(&[tcx.lifetimes.re_erased.into()]);
+        let context_ty = Ty::new_adt(tcx, context_adt_ref, context_args);
         Ty::new_mut_ref(tcx, tcx.lifetimes.re_erased, context_ty)
     }
 }
@@ -2382,10 +2372,10 @@ impl<'tcx> Ty<'tcx> {
 
     pub fn simd_size_and_type(self, tcx: TyCtxt<'tcx>) -> (u64, Ty<'tcx>) {
         match self.kind() {
-            Adt(def, substs) => {
+            Adt(def, args) => {
                 assert!(def.repr().simd(), "`simd_size_and_type` called on non-SIMD type");
                 let variant = def.non_enum_variant();
-                let f0_ty = variant.fields[FieldIdx::from_u32(0)].ty(tcx, substs);
+                let f0_ty = variant.fields[FieldIdx::from_u32(0)].ty(tcx, args);
 
                 match f0_ty.kind() {
                     // If the first field is an array, we assume it is the only field and its
@@ -2446,7 +2436,7 @@ impl<'tcx> Ty<'tcx> {
     /// Panics if called on any type other than `Box<T>`.
     pub fn boxed_ty(self) -> Ty<'tcx> {
         match self.kind() {
-            Adt(def, substs) if def.is_box() => substs.type_at(0),
+            Adt(def, args) if def.is_box() => args.type_at(0),
             _ => bug!("`boxed_ty` is called on non-box type {:?}", self),
         }
     }
@@ -2610,14 +2600,14 @@ impl<'tcx> Ty<'tcx> {
 
     pub fn fn_sig(self, tcx: TyCtxt<'tcx>) -> PolyFnSig<'tcx> {
         match self.kind() {
-            FnDef(def_id, substs) => tcx.fn_sig(*def_id).subst(tcx, substs),
+            FnDef(def_id, args) => tcx.fn_sig(*def_id).instantiate(tcx, args),
             FnPtr(f) => *f,
             Error(_) => {
                 // ignore errors (#54954)
                 ty::Binder::dummy(FnSig::fake())
             }
             Closure(..) => bug!(
-                "to get the signature of a closure, use `substs.as_closure().sig()` not `fn_sig()`",
+                "to get the signature of a closure, use `args.as_closure().sig()` not `fn_sig()`",
             ),
             _ => bug!("Ty::fn_sig() called on non-fn type: {:?}", self),
         }
@@ -2651,7 +2641,7 @@ impl<'tcx> Ty<'tcx> {
     #[inline]
     pub fn tuple_fields(self) -> &'tcx List<Ty<'tcx>> {
         match self.kind() {
-            Tuple(substs) => substs,
+            Tuple(args) => args,
             _ => bug!("tuple_fields called on non-tuple"),
         }
     }
@@ -2663,8 +2653,8 @@ impl<'tcx> Ty<'tcx> {
     pub fn variant_range(self, tcx: TyCtxt<'tcx>) -> Option<Range<VariantIdx>> {
         match self.kind() {
             TyKind::Adt(adt, _) => Some(adt.variant_range()),
-            TyKind::Generator(def_id, substs, _) => {
-                Some(substs.as_generator().variant_range(*def_id, tcx))
+            TyKind::Generator(def_id, args, _) => {
+                Some(args.as_generator().variant_range(*def_id, tcx))
             }
             _ => None,
         }
@@ -2689,8 +2679,8 @@ impl<'tcx> Ty<'tcx> {
             TyKind::Adt(adt, _) if adt.is_enum() => {
                 Some(adt.discriminant_for_variant(tcx, variant_index))
             }
-            TyKind::Generator(def_id, substs, _) => {
-                Some(substs.as_generator().discriminant_for_variant(*def_id, tcx, variant_index))
+            TyKind::Generator(def_id, args, _) => {
+                Some(args.as_generator().discriminant_for_variant(*def_id, tcx, variant_index))
             }
             _ => None,
         }
@@ -2700,13 +2690,13 @@ impl<'tcx> Ty<'tcx> {
     pub fn discriminant_ty(self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
         match self.kind() {
             ty::Adt(adt, _) if adt.is_enum() => adt.repr().discr_type().to_ty(tcx),
-            ty::Generator(_, substs, _) => substs.as_generator().discr_ty(tcx),
+            ty::Generator(_, args, _) => args.as_generator().discr_ty(tcx),
 
             ty::Param(_) | ty::Alias(..) | ty::Infer(ty::TyVar(_)) => {
                 let assoc_items = tcx.associated_item_def_ids(
                     tcx.require_lang_item(hir::LangItem::DiscriminantKind, None),
                 );
-                Ty::new_projection(tcx, assoc_items[0], tcx.mk_substs(&[self.into()]))
+                Ty::new_projection(tcx, assoc_items[0], tcx.mk_args(&[self.into()]))
             }
 
             ty::Bool
@@ -2779,7 +2769,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.type_of(dyn_metadata).subst(tcx, &[tail.into()]), false)
+                (tcx.type_of(dyn_metadata).instantiate(tcx, &[tail.into()]), false)
             },
 
             // type parameters only have unit metadata if they're sized, so return true
@@ -2796,7 +2786,7 @@ impl<'tcx> Ty<'tcx> {
     }
 
     /// When we create a closure, we record its kind (i.e., what trait
-    /// it implements) into its `ClosureSubsts` using a type
+    /// it implements) into its `ClosureArgs` using a type
     /// parameter. This is kind of a phantom type, except that the
     /// most convenient thing for us to are the integral types. This
     /// function converts such a special type into the closure
@@ -2859,7 +2849,7 @@ impl<'tcx> Ty<'tcx> {
 
             ty::Tuple(tys) => tys.iter().all(|ty| ty.is_trivially_sized(tcx)),
 
-            ty::Adt(def, _substs) => def.sized_constraint(tcx).skip_binder().is_empty(),
+            ty::Adt(def, _args) => def.sized_constraint(tcx).skip_binder().is_empty(),
 
             ty::Alias(..) | ty::Param(_) | ty::Placeholder(..) => false,
 
diff --git a/compiler/rustc_middle/src/ty/trait_def.rs b/compiler/rustc_middle/src/ty/trait_def.rs
index 98c70e330f1..6e55e7915c9 100644
--- a/compiler/rustc_middle/src/ty/trait_def.rs
+++ b/compiler/rustc_middle/src/ty/trait_def.rs
@@ -236,7 +236,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).subst_identity();
+        let impl_self_ty = tcx.type_of(impl_def_id).instantiate_identity();
         if impl_self_ty.references_error() {
             continue;
         }
diff --git a/compiler/rustc_middle/src/ty/typeck_results.rs b/compiler/rustc_middle/src/ty/typeck_results.rs
index e85afeb4b6e..327cd0a5d7b 100644
--- a/compiler/rustc_middle/src/ty/typeck_results.rs
+++ b/compiler/rustc_middle/src/ty/typeck_results.rs
@@ -4,11 +4,13 @@ use crate::{
     traits::ObligationCause,
     ty::{
         self, tls, BindingMode, BoundVar, CanonicalPolyFnSig, ClosureSizeProfileData,
-        GenericArgKind, InternalSubsts, SubstsRef, Ty, UserSubsts,
+        GenericArgKind, GenericArgs, GenericArgsRef, Ty, UserArgs,
     },
 };
-use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
-use rustc_data_structures::unord::{UnordItems, UnordSet};
+use rustc_data_structures::{
+    fx::FxIndexMap,
+    unord::{ExtendUnord, UnordItems, UnordSet},
+};
 use rustc_errors::ErrorGuaranteed;
 use rustc_hir as hir;
 use rustc_hir::{
@@ -51,7 +53,7 @@ pub struct TypeckResults<'tcx> {
     /// of this node. This only applies to nodes that refer to entities
     /// parameterized by type parameters, such as generic fns, types, or
     /// other items.
-    node_substs: ItemLocalMap<SubstsRef<'tcx>>,
+    node_args: ItemLocalMap<GenericArgsRef<'tcx>>,
 
     /// This will either store the canonicalized types provided by the user
     /// or the substitutions that the user explicitly gave (if any) attached
@@ -180,7 +182,7 @@ pub struct TypeckResults<'tcx> {
     /// we never capture `t`. This becomes an issue when we build MIR as we require
     /// information on `t` in order to create place `t.0` and `t.1`. We can solve this
     /// issue by fake reading `t`.
-    pub closure_fake_reads: FxHashMap<LocalDefId, Vec<(HirPlace<'tcx>, FakeReadCause, hir::HirId)>>,
+    pub closure_fake_reads: LocalDefIdMap<Vec<(HirPlace<'tcx>, FakeReadCause, hir::HirId)>>,
 
     /// Tracks the rvalue scoping rules which defines finer scoping for rvalue expressions
     /// by applying extended parameter rules.
@@ -194,7 +196,7 @@ pub struct TypeckResults<'tcx> {
     /// Stores the predicates that apply on generator witness types.
     /// formatting modified file tests/ui/generator/retain-resume-ref.rs
     pub generator_interior_predicates:
-        FxHashMap<LocalDefId, Vec<(ty::Predicate<'tcx>, ObligationCause<'tcx>)>>,
+        LocalDefIdMap<Vec<(ty::Predicate<'tcx>, ObligationCause<'tcx>)>>,
 
     /// We sometimes treat byte string literals (which are of type `&[u8; N]`)
     /// as `&[u8]`, depending on the pattern in which they are used.
@@ -204,7 +206,7 @@ pub struct TypeckResults<'tcx> {
 
     /// Contains the data for evaluating the effect of feature `capture_disjoint_fields`
     /// on closure size.
-    pub closure_size_eval: FxHashMap<LocalDefId, ClosureSizeProfileData<'tcx>>,
+    pub closure_size_eval: LocalDefIdMap<ClosureSizeProfileData<'tcx>>,
 
     /// Container types and field indices of `offset_of!` expressions
     offset_of_data: ItemLocalMap<(Ty<'tcx>, Vec<FieldIdx>)>,
@@ -262,7 +264,7 @@ impl<'tcx> TypeckResults<'tcx> {
             user_provided_types: Default::default(),
             user_provided_sigs: Default::default(),
             node_types: Default::default(),
-            node_substs: Default::default(),
+            node_args: Default::default(),
             adjustments: Default::default(),
             pat_binding_modes: Default::default(),
             pat_adjustments: Default::default(),
@@ -382,18 +384,18 @@ impl<'tcx> TypeckResults<'tcx> {
         self.node_types.get(&id.local_id).cloned()
     }
 
-    pub fn node_substs_mut(&mut self) -> LocalTableInContextMut<'_, SubstsRef<'tcx>> {
-        LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.node_substs }
+    pub fn node_args_mut(&mut self) -> LocalTableInContextMut<'_, GenericArgsRef<'tcx>> {
+        LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.node_args }
     }
 
-    pub fn node_substs(&self, id: hir::HirId) -> SubstsRef<'tcx> {
+    pub fn node_args(&self, id: hir::HirId) -> GenericArgsRef<'tcx> {
         validate_hir_id_for_typeck_results(self.hir_owner, id);
-        self.node_substs.get(&id.local_id).cloned().unwrap_or_else(|| InternalSubsts::empty())
+        self.node_args.get(&id.local_id).cloned().unwrap_or_else(|| GenericArgs::empty())
     }
 
-    pub fn node_substs_opt(&self, id: hir::HirId) -> Option<SubstsRef<'tcx>> {
+    pub fn node_args_opt(&self, id: hir::HirId) -> Option<GenericArgsRef<'tcx>> {
         validate_hir_id_for_typeck_results(self.hir_owner, id);
-        self.node_substs.get(&id.local_id).cloned()
+        self.node_args.get(&id.local_id).cloned()
     }
 
     /// Returns the type of a pattern as a monotype. Like [`expr_ty`], this function
@@ -633,7 +635,7 @@ impl<'a, V> LocalTableInContextMut<'a, V> {
         &mut self,
         items: UnordItems<(hir::HirId, V), impl Iterator<Item = (hir::HirId, V)>>,
     ) {
-        self.data.extend(items.map(|(id, value)| {
+        self.data.extend_unord(items.map(|(id, value)| {
             validate_hir_id_for_typeck_results(self.hir_owner, id);
             (id.local_id, value)
         }))
@@ -668,12 +670,12 @@ impl<'tcx> CanonicalUserType<'tcx> {
     pub fn is_identity(&self) -> bool {
         match self.value {
             UserType::Ty(_) => false,
-            UserType::TypeOf(_, user_substs) => {
-                if user_substs.user_self_ty.is_some() {
+            UserType::TypeOf(_, user_args) => {
+                if user_args.user_self_ty.is_some() {
                     return false;
                 }
 
-                iter::zip(user_substs.substs, BoundVar::new(0)..).all(|(kind, cvar)| {
+                iter::zip(user_args.args, BoundVar::new(0)..).all(|(kind, cvar)| {
                     match kind.unpack() {
                         GenericArgKind::Type(ty) => match ty.kind() {
                             ty::Bound(debruijn, b) => {
@@ -718,5 +720,5 @@ pub enum UserType<'tcx> {
 
     /// The canonical type is the result of `type_of(def_id)` with the
     /// given substitutions applied.
-    TypeOf(DefId, UserSubsts<'tcx>),
+    TypeOf(DefId, UserArgs<'tcx>),
 }
diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs
index e2e4a2dbdc8..b4852ab8881 100644
--- a/compiler/rustc_middle/src/ty/util.rs
+++ b/compiler/rustc_middle/src/ty/util.rs
@@ -7,7 +7,7 @@ use crate::ty::{
     self, FallibleTypeFolder, ToPredicate, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable,
     TypeVisitableExt,
 };
-use crate::ty::{GenericArgKind, SubstsRef};
+use crate::ty::{GenericArgKind, GenericArgsRef};
 use rustc_apfloat::Float as _;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::stable_hasher::{Hash128, HashStable, StableHasher};
@@ -226,14 +226,14 @@ impl<'tcx> TyCtxt<'tcx> {
                 return Ty::new_error(self, reported);
             }
             match *ty.kind() {
-                ty::Adt(def, substs) => {
+                ty::Adt(def, args) => {
                     if !def.is_struct() {
                         break;
                     }
                     match def.non_enum_variant().tail_opt() {
                         Some(field) => {
                             f();
-                            ty = field.ty(self, substs);
+                            ty = field.ty(self, args);
                         }
                         None => break,
                     }
@@ -301,12 +301,12 @@ impl<'tcx> TyCtxt<'tcx> {
         let (mut a, mut b) = (source, target);
         loop {
             match (&a.kind(), &b.kind()) {
-                (&ty::Adt(a_def, a_substs), &ty::Adt(b_def, b_substs))
+                (&ty::Adt(a_def, a_args), &ty::Adt(b_def, b_args))
                     if a_def == b_def && a_def.is_struct() =>
                 {
                     if let Some(f) = a_def.non_enum_variant().tail_opt() {
-                        a = f.ty(self, a_substs);
-                        b = f.ty(self, b_substs);
+                        a = f.ty(self, a_args);
+                        b = f.ty(self, b_args);
                     } else {
                         break;
                     }
@@ -349,7 +349,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).subst_identity();
+        let ty = self.type_of(adt_did).instantiate_identity();
         let mut dtor_candidate = None;
         self.for_each_relevant_impl(drop_trait, ty, |impl_did| {
             if validate(self, impl_did).is_err() {
@@ -358,7 +358,8 @@ impl<'tcx> TyCtxt<'tcx> {
             }
 
             let Some(item_id) = self.associated_item_def_ids(impl_did).first() else {
-                self.sess.delay_span_bug(self.def_span(impl_did), "Drop impl without drop function");
+                self.sess
+                    .delay_span_bug(self.def_span(impl_did), "Drop impl without drop function");
                 return;
             };
 
@@ -383,7 +384,7 @@ impl<'tcx> TyCtxt<'tcx> {
     /// Note that this returns only the constraints for the
     /// destructor of `def` itself. For the destructors of the
     /// contents, you need `adt_dtorck_constraint`.
-    pub fn destructor_constraints(self, def: ty::AdtDef<'tcx>) -> Vec<ty::subst::GenericArg<'tcx>> {
+    pub fn destructor_constraints(self, def: ty::AdtDef<'tcx>) -> Vec<ty::GenericArg<'tcx>> {
         let dtor = match def.destructor(self) {
             None => {
                 debug!("destructor_constraints({:?}) - no dtor", def.did());
@@ -400,7 +401,7 @@ impl<'tcx> TyCtxt<'tcx> {
         // must be live.
 
         // We need to return the list of parameters from the ADTs
-        // generics/substs that correspond to impure parameters on the
+        // generics/args that correspond to impure parameters on the
         // impl's generics. This is a bit ugly, but conceptually simple:
         //
         // Suppose our ADT looks like the following
@@ -412,21 +413,21 @@ impl<'tcx> TyCtxt<'tcx> {
         //     impl<#[may_dangle] P0, P1, P2> Drop for S<P1, P2, P0>
         //
         // We want to return the parameters (X, Y). For that, we match
-        // up the item-substs <X, Y, Z> with the substs on the impl ADT,
-        // <P1, P2, P0>, and then look up which of the impl substs refer to
+        // up the item-args <X, Y, Z> with the args on the impl ADT,
+        // <P1, P2, P0>, and then look up which of the impl args refer to
         // parameters marked as pure.
 
-        let impl_substs = match *self.type_of(impl_def_id).subst_identity().kind() {
-            ty::Adt(def_, substs) if def_ == def => substs,
+        let impl_args = match *self.type_of(impl_def_id).instantiate_identity().kind() {
+            ty::Adt(def_, args) if def_ == def => args,
             _ => bug!(),
         };
 
-        let item_substs = match *self.type_of(def.did()).subst_identity().kind() {
-            ty::Adt(def_, substs) if def_ == def => substs,
+        let item_args = match *self.type_of(def.did()).instantiate_identity().kind() {
+            ty::Adt(def_, args) if def_ == def => args,
             _ => bug!(),
         };
 
-        let result = iter::zip(item_substs, impl_substs)
+        let result = iter::zip(item_args, impl_args)
             .filter(|&(_, k)| {
                 match k.unpack() {
                     GenericArgKind::Lifetime(region) => match region.kind() {
@@ -459,12 +460,12 @@ impl<'tcx> TyCtxt<'tcx> {
     /// Checks whether each generic argument is simply a unique generic parameter.
     pub fn uses_unique_generic_params(
         self,
-        substs: SubstsRef<'tcx>,
+        args: GenericArgsRef<'tcx>,
         ignore_regions: CheckRegions,
     ) -> Result<(), NotUniqueParam<'tcx>> {
         let mut seen = GrowableBitSet::default();
         let mut seen_late = FxHashSet::default();
-        for arg in substs {
+        for arg in args {
             match arg.unpack() {
                 GenericArgKind::Lifetime(lt) => match (ignore_regions, lt.kind()) {
                     (CheckRegions::Bound, ty::ReLateBound(di, reg)) => {
@@ -510,10 +511,10 @@ impl<'tcx> TyCtxt<'tcx> {
     /// for better caching.
     pub fn uses_unique_placeholders_ignoring_regions(
         self,
-        substs: SubstsRef<'tcx>,
+        args: GenericArgsRef<'tcx>,
     ) -> Result<(), NotUniqueParam<'tcx>> {
         let mut seen = GrowableBitSet::default();
-        for arg in substs {
+        for arg in args {
             match arg.unpack() {
                 // Ignore regions, since we can't resolve those in a canonicalized
                 // query in the trait solver.
@@ -594,7 +595,7 @@ impl<'tcx> TyCtxt<'tcx> {
         def_id
     }
 
-    /// Given the `DefId` and substs a closure, creates the type of
+    /// Given the `DefId` and args a closure, creates the type of
     /// `self` argument that the closure expects. For example, for a
     /// `Fn` closure, this would return a reference type `&T` where
     /// `T = closure_ty`.
@@ -607,11 +608,11 @@ impl<'tcx> TyCtxt<'tcx> {
     pub fn closure_env_ty(
         self,
         closure_def_id: DefId,
-        closure_substs: SubstsRef<'tcx>,
+        closure_args: GenericArgsRef<'tcx>,
         env_region: ty::Region<'tcx>,
     ) -> Option<Ty<'tcx>> {
-        let closure_ty = Ty::new_closure(self, closure_def_id, closure_substs);
-        let closure_kind_ty = closure_substs.as_closure().kind_ty();
+        let closure_ty = Ty::new_closure(self, closure_def_id, closure_args);
+        let closure_kind_ty = closure_args.as_closure().kind_ty();
         let closure_kind = closure_kind_ty.to_opt_closure_kind()?;
         let env_ty = match closure_kind {
             ty::ClosureKind::Fn => Ty::new_imm_ref(self, env_region, closure_ty),
@@ -654,7 +655,7 @@ impl<'tcx> TyCtxt<'tcx> {
 
     /// Returns the type a reference to the thread local takes in MIR.
     pub fn thread_local_ptr_ty(self, def_id: DefId) -> Ty<'tcx> {
-        let static_ty = self.type_of(def_id).subst_identity();
+        let static_ty = self.type_of(def_id).instantiate_identity();
         if self.is_mutable_static(def_id) {
             Ty::new_mut_ptr(self, static_ty)
         } else if self.is_foreign_item(def_id) {
@@ -670,7 +671,7 @@ impl<'tcx> TyCtxt<'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).subst_identity(),
+            self.type_of(def_id).instantiate_identity(),
         );
 
         // Make sure that accesses to unsafe statics end up using raw pointers.
@@ -719,7 +720,7 @@ impl<'tcx> TyCtxt<'tcx> {
     pub fn try_expand_impl_trait_type(
         self,
         def_id: DefId,
-        substs: SubstsRef<'tcx>,
+        args: GenericArgsRef<'tcx>,
     ) -> Result<Ty<'tcx>, Ty<'tcx>> {
         let mut visitor = OpaqueTypeExpander {
             seen_opaque_tys: FxHashSet::default(),
@@ -732,7 +733,7 @@ impl<'tcx> TyCtxt<'tcx> {
             tcx: self,
         };
 
-        let expanded_type = visitor.expand_opaque_ty(def_id, substs).unwrap();
+        let expanded_type = visitor.expand_opaque_ty(def_id, args).unwrap();
         if visitor.found_recursion { Err(expanded_type) } else { Ok(expanded_type) }
     }
 
@@ -799,7 +800,7 @@ struct OpaqueTypeExpander<'tcx> {
     seen_opaque_tys: FxHashSet<DefId>,
     // Cache of all expansions we've seen so far. This is a critical
     // optimization for some large types produced by async fn trees.
-    expanded_cache: FxHashMap<(DefId, SubstsRef<'tcx>), Ty<'tcx>>,
+    expanded_cache: FxHashMap<(DefId, GenericArgsRef<'tcx>), Ty<'tcx>>,
     primary_def_id: Option<DefId>,
     found_recursion: bool,
     found_any_recursion: bool,
@@ -812,19 +813,19 @@ struct OpaqueTypeExpander<'tcx> {
 }
 
 impl<'tcx> OpaqueTypeExpander<'tcx> {
-    fn expand_opaque_ty(&mut self, def_id: DefId, substs: SubstsRef<'tcx>) -> Option<Ty<'tcx>> {
+    fn expand_opaque_ty(&mut self, def_id: DefId, args: GenericArgsRef<'tcx>) -> Option<Ty<'tcx>> {
         if self.found_any_recursion {
             return None;
         }
-        let substs = substs.fold_with(self);
+        let args = args.fold_with(self);
         if !self.check_recursion || self.seen_opaque_tys.insert(def_id) {
-            let expanded_ty = match self.expanded_cache.get(&(def_id, substs)) {
+            let expanded_ty = match self.expanded_cache.get(&(def_id, args)) {
                 Some(expanded_ty) => *expanded_ty,
                 None => {
                     let generic_ty = self.tcx.type_of(def_id);
-                    let concrete_ty = generic_ty.subst(self.tcx, substs);
+                    let concrete_ty = generic_ty.instantiate(self.tcx, args);
                     let expanded_ty = self.fold_ty(concrete_ty);
-                    self.expanded_cache.insert((def_id, substs), expanded_ty);
+                    self.expanded_cache.insert((def_id, args), expanded_ty);
                     expanded_ty
                 }
             };
@@ -841,21 +842,21 @@ impl<'tcx> OpaqueTypeExpander<'tcx> {
         }
     }
 
-    fn expand_generator(&mut self, def_id: DefId, substs: SubstsRef<'tcx>) -> Option<Ty<'tcx>> {
+    fn expand_generator(&mut self, def_id: DefId, args: GenericArgsRef<'tcx>) -> Option<Ty<'tcx>> {
         if self.found_any_recursion {
             return None;
         }
-        let substs = substs.fold_with(self);
+        let args = args.fold_with(self);
         if !self.check_recursion || self.seen_opaque_tys.insert(def_id) {
-            let expanded_ty = match self.expanded_cache.get(&(def_id, substs)) {
+            let expanded_ty = match self.expanded_cache.get(&(def_id, args)) {
                 Some(expanded_ty) => *expanded_ty,
                 None => {
                     for bty in self.tcx.generator_hidden_types(def_id) {
-                        let hidden_ty = bty.subst(self.tcx, substs);
+                        let hidden_ty = bty.instantiate(self.tcx, args);
                         self.fold_ty(hidden_ty);
                     }
-                    let expanded_ty = Ty::new_generator_witness_mir(self.tcx, def_id, substs);
-                    self.expanded_cache.insert((def_id, substs), expanded_ty);
+                    let expanded_ty = Ty::new_generator_witness_mir(self.tcx, def_id, args);
+                    self.expanded_cache.insert((def_id, args), expanded_ty);
                     expanded_ty
                 }
             };
@@ -879,16 +880,16 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for OpaqueTypeExpander<'tcx> {
     }
 
     fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
-        let mut t = if let ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) = *t.kind() {
-            self.expand_opaque_ty(def_id, substs).unwrap_or(t)
+        let mut t = if let ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) = *t.kind() {
+            self.expand_opaque_ty(def_id, args).unwrap_or(t)
         } else if t.has_opaque_types() || t.has_generators() {
             t.super_fold_with(self)
         } else {
             t
         };
         if self.expand_generators {
-            if let ty::GeneratorWitnessMIR(def_id, substs) = *t.kind() {
-                t = self.expand_generator(def_id, substs).unwrap_or(t);
+            if let ty::GeneratorWitnessMIR(def_id, args) = *t.kind() {
+                t = self.expand_generator(def_id, args).unwrap_or(t);
             }
         }
         t
diff --git a/compiler/rustc_middle/src/ty/walk.rs b/compiler/rustc_middle/src/ty/walk.rs
index 04a635a6803..7c3d9ed390a 100644
--- a/compiler/rustc_middle/src/ty/walk.rs
+++ b/compiler/rustc_middle/src/ty/walk.rs
@@ -1,8 +1,8 @@
 //! An iterator over the type substructure.
 //! WARNING: this does not keep track of the region depth.
 
-use crate::ty::subst::{GenericArg, GenericArgKind};
 use crate::ty::{self, Ty};
+use crate::ty::{GenericArg, GenericArgKind};
 use rustc_data_structures::sso::SsoHashSet;
 use smallvec::SmallVec;
 
@@ -166,33 +166,33 @@ fn push_inner<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent: GenericArg<'tcx>)
                 stack.push(lt.into());
             }
             ty::Alias(_, data) => {
-                stack.extend(data.substs.iter().rev());
+                stack.extend(data.args.iter().rev());
             }
             ty::Dynamic(obj, lt, _) => {
                 stack.push(lt.into());
                 stack.extend(obj.iter().rev().flat_map(|predicate| {
-                    let (substs, opt_ty) = match predicate.skip_binder() {
-                        ty::ExistentialPredicate::Trait(tr) => (tr.substs, None),
-                        ty::ExistentialPredicate::Projection(p) => (p.substs, Some(p.term)),
+                    let (args, opt_ty) = match predicate.skip_binder() {
+                        ty::ExistentialPredicate::Trait(tr) => (tr.args, None),
+                        ty::ExistentialPredicate::Projection(p) => (p.args, Some(p.term)),
                         ty::ExistentialPredicate::AutoTrait(_) =>
                         // Empty iterator
                         {
-                            (ty::InternalSubsts::empty(), None)
+                            (ty::GenericArgs::empty(), None)
                         }
                     };
 
-                    substs.iter().rev().chain(opt_ty.map(|term| match term.unpack() {
+                    args.iter().rev().chain(opt_ty.map(|term| match term.unpack() {
                         ty::TermKind::Ty(ty) => ty.into(),
                         ty::TermKind::Const(ct) => ct.into(),
                     }))
                 }));
             }
-            ty::Adt(_, substs)
-            | ty::Closure(_, substs)
-            | ty::Generator(_, substs, _)
-            | ty::GeneratorWitnessMIR(_, substs)
-            | ty::FnDef(_, substs) => {
-                stack.extend(substs.iter().rev());
+            ty::Adt(_, args)
+            | ty::Closure(_, args)
+            | ty::Generator(_, args, _)
+            | ty::GeneratorWitnessMIR(_, args)
+            | ty::FnDef(_, args) => {
+                stack.extend(args.iter().rev());
             }
             ty::Tuple(ts) => stack.extend(ts.iter().rev().map(GenericArg::from)),
             ty::GeneratorWitness(ts) => {
@@ -233,7 +233,7 @@ fn push_inner<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent: GenericArg<'tcx>)
                 },
 
                 ty::ConstKind::Unevaluated(ct) => {
-                    stack.extend(ct.substs.iter().rev());
+                    stack.extend(ct.args.iter().rev());
                 }
             }
         }
diff --git a/compiler/rustc_middle/src/util/call_kind.rs b/compiler/rustc_middle/src/util/call_kind.rs
index 98d55ea6d40..4e2a2c6ae0a 100644
--- a/compiler/rustc_middle/src/util/call_kind.rs
+++ b/compiler/rustc_middle/src/util/call_kind.rs
@@ -2,7 +2,7 @@
 //! as well as errors when attempting to call a non-const function in a const
 //! context.
 
-use crate::ty::subst::SubstsRef;
+use crate::ty::GenericArgsRef;
 use crate::ty::{AssocItemContainer, Instance, ParamEnv, Ty, TyCtxt};
 use rustc_hir::def_id::DefId;
 use rustc_hir::{lang_items, LangItem};
@@ -43,7 +43,7 @@ pub enum CallKind<'tcx> {
         self_arg: Option<Ident>,
         desugaring: Option<(CallDesugaringKind, Ty<'tcx>)>,
         method_did: DefId,
-        method_substs: SubstsRef<'tcx>,
+        method_args: GenericArgsRef<'tcx>,
     },
     /// A call to `Fn(..)::call(..)`, desugared from `my_closure(a, b, c)`
     FnCall { fn_trait_id: DefId, self_ty: Ty<'tcx> },
@@ -63,7 +63,7 @@ pub fn call_kind<'tcx>(
     tcx: TyCtxt<'tcx>,
     param_env: ParamEnv<'tcx>,
     method_did: DefId,
-    method_substs: SubstsRef<'tcx>,
+    method_args: GenericArgsRef<'tcx>,
     fn_call_span: Span,
     from_hir_call: bool,
     self_arg: Option<Ident>,
@@ -92,19 +92,19 @@ pub fn call_kind<'tcx>(
     // an FnOnce call, an operator (e.g. `<<`), or a
     // deref coercion.
     let kind = if let Some(trait_id) = fn_call {
-        Some(CallKind::FnCall { fn_trait_id: trait_id, self_ty: method_substs.type_at(0) })
+        Some(CallKind::FnCall { fn_trait_id: trait_id, self_ty: method_args.type_at(0) })
     } else if let Some(trait_id) = operator {
-        Some(CallKind::Operator { self_arg, trait_id, self_ty: method_substs.type_at(0) })
+        Some(CallKind::Operator { self_arg, trait_id, self_ty: method_args.type_at(0) })
     } else if is_deref {
         let deref_target = tcx.get_diagnostic_item(sym::deref_target).and_then(|deref_target| {
-            Instance::resolve(tcx, param_env, deref_target, method_substs).transpose()
+            Instance::resolve(tcx, param_env, deref_target, method_args).transpose()
         });
         if let Some(Ok(instance)) = deref_target {
             let deref_target_ty = instance.ty(tcx, param_env);
             Some(CallKind::DerefCoercion {
                 deref_target: tcx.def_span(instance.def_id()),
                 deref_target_ty,
-                self_ty: method_substs.type_at(0),
+                self_ty: method_args.type_at(0),
             })
         } else {
             None
@@ -119,24 +119,24 @@ pub fn call_kind<'tcx>(
         let desugaring = if Some(method_did) == tcx.lang_items().into_iter_fn()
             && fn_call_span.desugaring_kind() == Some(DesugaringKind::ForLoop)
         {
-            Some((CallDesugaringKind::ForLoopIntoIter, method_substs.type_at(0)))
+            Some((CallDesugaringKind::ForLoopIntoIter, method_args.type_at(0)))
         } else if fn_call_span.desugaring_kind() == Some(DesugaringKind::QuestionMark) {
             if Some(method_did) == tcx.lang_items().branch_fn() {
-                Some((CallDesugaringKind::QuestionBranch, method_substs.type_at(0)))
+                Some((CallDesugaringKind::QuestionBranch, method_args.type_at(0)))
             } else if Some(method_did) == tcx.lang_items().from_residual_fn() {
-                Some((CallDesugaringKind::QuestionFromResidual, method_substs.type_at(0)))
+                Some((CallDesugaringKind::QuestionFromResidual, method_args.type_at(0)))
             } else {
                 None
             }
         } else if Some(method_did) == tcx.lang_items().from_output_fn()
             && fn_call_span.desugaring_kind() == Some(DesugaringKind::TryBlock)
         {
-            Some((CallDesugaringKind::TryBlockFromOutput, method_substs.type_at(0)))
+            Some((CallDesugaringKind::TryBlockFromOutput, method_args.type_at(0)))
         } else if fn_call_span.is_desugaring(DesugaringKind::Await) {
-            Some((CallDesugaringKind::Await, method_substs.type_at(0)))
+            Some((CallDesugaringKind::Await, method_args.type_at(0)))
         } else {
             None
         };
-        CallKind::Normal { self_arg, desugaring, method_did, method_substs }
+        CallKind::Normal { self_arg, desugaring, method_did, method_args }
     })
 }
diff --git a/compiler/rustc_middle/src/util/find_self_call.rs b/compiler/rustc_middle/src/util/find_self_call.rs
index 0eab0adf07e..1b845334c49 100644
--- a/compiler/rustc_middle/src/util/find_self_call.rs
+++ b/compiler/rustc_middle/src/util/find_self_call.rs
@@ -1,5 +1,5 @@
 use crate::mir::*;
-use crate::ty::subst::SubstsRef;
+use crate::ty::GenericArgsRef;
 use crate::ty::{self, TyCtxt};
 use rustc_span::def_id::DefId;
 
@@ -11,21 +11,21 @@ pub fn find_self_call<'tcx>(
     body: &Body<'tcx>,
     local: Local,
     block: BasicBlock,
-) -> Option<(DefId, SubstsRef<'tcx>)> {
+) -> Option<(DefId, GenericArgsRef<'tcx>)> {
     debug!("find_self_call(local={:?}): terminator={:?}", local, &body[block].terminator);
     if let Some(Terminator { kind: TerminatorKind::Call { func, args, .. }, .. }) =
         &body[block].terminator
     {
         debug!("find_self_call: func={:?}", func);
         if let Operand::Constant(box Constant { literal, .. }) = func {
-            if let ty::FnDef(def_id, substs) = *literal.ty().kind() {
+            if let ty::FnDef(def_id, fn_args) = *literal.ty().kind() {
                 if let Some(ty::AssocItem { fn_has_self_parameter: true, .. }) =
                     tcx.opt_associated_item(def_id)
                 {
-                    debug!("find_self_call: args={:?}", args);
+                    debug!("find_self_call: args={:?}", fn_args);
                     if let [Operand::Move(self_place) | Operand::Copy(self_place), ..] = **args {
                         if self_place.as_local() == Some(local) {
-                            return Some((def_id, substs));
+                            return Some((def_id, fn_args));
                         }
                     }
                 }
diff --git a/compiler/rustc_mir_build/src/build/custom/parse.rs b/compiler/rustc_mir_build/src/build/custom/parse.rs
index 803207d9dc6..c494929cbff 100644
--- a/compiler/rustc_mir_build/src/build/custom/parse.rs
+++ b/compiler/rustc_mir_build/src/build/custom/parse.rs
@@ -241,9 +241,7 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
             });
         }
 
-        let Some(trailing) = block.expr else {
-            return Err(self.expr_error(expr_id, "terminator"))
-        };
+        let Some(trailing) = block.expr else { return Err(self.expr_error(expr_id, "terminator")) };
         let span = self.thir[trailing].span;
         let terminator = self.parse_terminator(trailing)?;
         data.terminator = Some(Terminator {
diff --git a/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs b/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs
index 4cb9d7babe1..295cddb1e15 100644
--- a/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs
+++ b/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs
@@ -78,7 +78,7 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
                 span,
                 item_description: "no arms".to_string(),
                 expected: "at least one arm".to_string(),
-            })
+            });
         };
 
         let otherwise = &self.thir[*otherwise];
@@ -87,7 +87,7 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
                 span: otherwise.span,
                 item_description: format!("{:?}", otherwise.pattern.kind),
                 expected: "wildcard pattern".to_string(),
-            })
+            });
         };
         let otherwise = self.parse_block(otherwise.body)?;
 
@@ -100,7 +100,7 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
                     span: arm.pattern.span,
                     item_description: format!("{:?}", arm.pattern.kind),
                     expected: "constant pattern".to_string(),
-                })
+                });
             };
             values.push(value.eval_bits(self.tcx, self.param_env, arm.pattern.ty));
             targets.push(self.parse_block(arm.body)?);
@@ -192,12 +192,12 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
                     fields.iter().map(|e| self.parse_operand(*e)).collect::<Result<_, _>>()?
                 ))
             },
-            ExprKind::Adt(box AdtExpr{ adt_def, variant_index, substs, fields, .. }) => {
+            ExprKind::Adt(box AdtExpr{ adt_def, variant_index, args, fields, .. }) => {
                 let is_union = adt_def.is_union();
                 let active_field_index = is_union.then(|| fields[0].name);
 
                 Ok(Rvalue::Aggregate(
-                    Box::new(AggregateKind::Adt(adt_def.did(), *variant_index, substs, None, active_field_index)),
+                    Box::new(AggregateKind::Adt(adt_def.did(), *variant_index, args, None, active_field_index)),
                     fields.iter().map(|f| self.parse_operand(f.expr)).collect::<Result<_, _>>()?
                 ))
             },
diff --git a/compiler/rustc_mir_build/src/build/expr/as_constant.rs b/compiler/rustc_mir_build/src/build/expr/as_constant.rs
index 3fe751ae0a5..aaa37446e24 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_constant.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_constant.rs
@@ -75,10 +75,10 @@ pub fn as_constant_inner<'tcx>(
 
             Constant { span, user_ty, literal }
         }
-        ExprKind::NamedConst { def_id, substs, ref user_ty } => {
+        ExprKind::NamedConst { def_id, args, ref user_ty } => {
             let user_ty = user_ty.as_ref().and_then(push_cuta);
 
-            let uneval = mir::UnevaluatedConst::new(def_id, substs);
+            let uneval = mir::UnevaluatedConst::new(def_id, args);
             let literal = ConstantKind::Unevaluated(uneval, ty);
 
             Constant { user_ty, span, literal }
@@ -89,8 +89,8 @@ pub fn as_constant_inner<'tcx>(
 
             Constant { user_ty: None, span, literal }
         }
-        ExprKind::ConstBlock { did: def_id, substs } => {
-            let uneval = mir::UnevaluatedConst::new(def_id, substs);
+        ExprKind::ConstBlock { did: def_id, args } => {
+            let uneval = mir::UnevaluatedConst::new(def_id, args);
             let literal = ConstantKind::Unevaluated(uneval, ty);
 
             Constant { user_ty: None, span, literal }
diff --git a/compiler/rustc_mir_build/src/build/expr/as_place.rs b/compiler/rustc_mir_build/src/build/expr/as_place.rs
index 60acd279f9e..c122230b841 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_place.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_place.rs
@@ -175,11 +175,8 @@ fn to_upvars_resolved_place_builder<'tcx>(
     projection: &[PlaceElem<'tcx>],
 ) -> Option<PlaceBuilder<'tcx>> {
     let Some((capture_index, capture)) =
-        find_capture_matching_projections(
-            &cx.upvars,
-            var_hir_id,
-            &projection,
-        ) else {
+        find_capture_matching_projections(&cx.upvars, var_hir_id, &projection)
+    else {
         let closure_span = cx.tcx.def_span(closure_def_id);
         if !enable_precise_capture(closure_span) {
             bug!(
@@ -189,10 +186,7 @@ fn to_upvars_resolved_place_builder<'tcx>(
                 projection
             )
         } else {
-            debug!(
-                "No associated capture found for {:?}[{:#?}]",
-                var_hir_id, projection,
-            );
+            debug!("No associated capture found for {:?}[{:#?}]", var_hir_id, projection,);
         }
         return None;
     };
diff --git a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
index 32ffb990be6..7817c3d0d80 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
@@ -16,7 +16,7 @@ use rustc_middle::mir::*;
 use rustc_middle::thir::*;
 use rustc_middle::ty::cast::{mir_cast_kind, CastTy};
 use rustc_middle::ty::layout::IntegerExt;
-use rustc_middle::ty::{self, Ty, UpvarSubsts};
+use rustc_middle::ty::{self, Ty, UpvarArgs};
 use rustc_span::Span;
 
 impl<'a, 'tcx> Builder<'a, 'tcx> {
@@ -382,7 +382,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             }
             ExprKind::Closure(box ClosureExpr {
                 closure_id,
-                substs,
+                args,
                 ref upvars,
                 movability,
                 ref fake_reads,
@@ -470,19 +470,15 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     })
                     .collect();
 
-                let result = match substs {
-                    UpvarSubsts::Generator(substs) => {
+                let result = match args {
+                    UpvarArgs::Generator(args) => {
                         // We implicitly set the discriminant to 0. See
                         // librustc_mir/transform/deaggregator.rs for details.
                         let movability = movability.unwrap();
-                        Box::new(AggregateKind::Generator(
-                            closure_id.to_def_id(),
-                            substs,
-                            movability,
-                        ))
+                        Box::new(AggregateKind::Generator(closure_id.to_def_id(), args, movability))
                     }
-                    UpvarSubsts::Closure(substs) => {
-                        Box::new(AggregateKind::Closure(closure_id.to_def_id(), substs))
+                    UpvarArgs::Closure(args) => {
+                        Box::new(AggregateKind::Closure(closure_id.to_def_id(), args))
                     }
                 };
                 block.and(Rvalue::Aggregate(result, operands))
diff --git a/compiler/rustc_mir_build/src/build/expr/into.rs b/compiler/rustc_mir_build/src/build/expr/into.rs
index e30fdcbbe18..c750727903f 100644
--- a/compiler/rustc_mir_build/src/build/expr/into.rs
+++ b/compiler/rustc_mir_build/src/build/expr/into.rs
@@ -317,7 +317,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             ExprKind::Adt(box AdtExpr {
                 adt_def,
                 variant_index,
-                substs,
+                args,
                 ref user_ty,
                 ref fields,
                 ref base,
@@ -382,7 +382,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 let adt = Box::new(AggregateKind::Adt(
                     adt_def.did(),
                     variant_index,
-                    substs,
+                    args,
                     user_ty,
                     active_field_index,
                 ));
diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs
index 10770213c9a..6f14891cb78 100644
--- a/compiler/rustc_mir_build/src/build/matches/mod.rs
+++ b/compiler/rustc_mir_build/src/build/matches/mod.rs
@@ -607,9 +607,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     // };
                     // ```
                     if let Some(place) = initializer.try_to_place(self) {
-                        let LocalInfo::User(BindingForm::Var(
-                            VarBindingForm { opt_match_place: Some((ref mut match_place, _)), .. },
-                        )) = **self.local_decls[local].local_info.as_mut().assert_crate_local() else {
+                        let LocalInfo::User(BindingForm::Var(VarBindingForm {
+                            opt_match_place: Some((ref mut match_place, _)),
+                            ..
+                        })) = **self.local_decls[local].local_info.as_mut().assert_crate_local()
+                        else {
                             bug!("Let binding to non-user variable.")
                         };
                         *match_place = Some(place);
@@ -804,7 +806,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 }
             }
 
-            PatKind::Variant { adt_def, substs: _, variant_index, ref subpatterns } => {
+            PatKind::Variant { adt_def, args: _, variant_index, ref subpatterns } => {
                 for subpattern in subpatterns {
                     let subpattern_user_ty =
                         pattern_user_ty.clone().variant(adt_def, variant_index, subpattern.field);
diff --git a/compiler/rustc_mir_build/src/build/matches/simplify.rs b/compiler/rustc_mir_build/src/build/matches/simplify.rs
index f6b1955fdec..17ac1f4e0ce 100644
--- a/compiler/rustc_mir_build/src/build/matches/simplify.rs
+++ b/compiler/rustc_mir_build/src/build/matches/simplify.rs
@@ -259,13 +259,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 }
             }
 
-            PatKind::Variant { adt_def, substs, variant_index, ref subpatterns } => {
+            PatKind::Variant { adt_def, args, variant_index, ref subpatterns } => {
                 let irrefutable = adt_def.variants().iter_enumerated().all(|(i, v)| {
                     i == variant_index || {
                         self.tcx.features().exhaustive_patterns
                             && !v
                                 .inhabited_predicate(self.tcx, adt_def)
-                                .subst(self.tcx, substs)
+                                .instantiate(self.tcx, args)
                                 .apply_ignore_module(self.tcx, self.param_env)
                     }
                 }) && (adt_def.did().is_local()
diff --git a/compiler/rustc_mir_build/src/build/matches/test.rs b/compiler/rustc_mir_build/src/build/matches/test.rs
index e6806177dec..275878a3919 100644
--- a/compiler/rustc_mir_build/src/build/matches/test.rs
+++ b/compiler/rustc_mir_build/src/build/matches/test.rs
@@ -30,7 +30,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     /// It is a bug to call this with a not-fully-simplified pattern.
     pub(super) fn test<'pat>(&mut self, match_pair: &MatchPair<'pat, 'tcx>) -> Test<'tcx> {
         match match_pair.pattern.kind {
-            PatKind::Variant { adt_def, substs: _, variant_index: _, subpatterns: _ } => Test {
+            PatKind::Variant { adt_def, args: _, variant_index: _, subpatterns: _ } => Test {
                 span: match_pair.pattern.span,
                 kind: TestKind::Switch {
                     adt_def,
@@ -88,7 +88,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         switch_ty: Ty<'tcx>,
         options: &mut FxIndexMap<ConstantKind<'tcx>, u128>,
     ) -> bool {
-        let Some(match_pair) = candidate.match_pairs.iter().find(|mp| mp.place == *test_place) else {
+        let Some(match_pair) = candidate.match_pairs.iter().find(|mp| mp.place == *test_place)
+        else {
             return false;
         };
 
@@ -126,7 +127,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         candidate: &Candidate<'pat, 'tcx>,
         variants: &mut BitSet<VariantIdx>,
     ) -> bool {
-        let Some(match_pair) = candidate.match_pairs.iter().find(|mp| mp.place == *test_place) else {
+        let Some(match_pair) = candidate.match_pairs.iter().find(|mp| mp.place == *test_place)
+        else {
             return false;
         };
 
@@ -865,7 +867,7 @@ fn trait_method<'tcx>(
     tcx: TyCtxt<'tcx>,
     trait_def_id: DefId,
     method_name: Symbol,
-    substs: impl IntoIterator<Item: Into<GenericArg<'tcx>>>,
+    args: impl IntoIterator<Item: Into<GenericArg<'tcx>>>,
 ) -> ConstantKind<'tcx> {
     // The unhygienic comparison here is acceptable because this is only
     // used on known traits.
@@ -875,7 +877,7 @@ fn trait_method<'tcx>(
         .find(|item| item.kind == ty::AssocKind::Fn)
         .expect("trait method not found");
 
-    let method_ty = Ty::new_fn_def(tcx, item.def_id, substs);
+    let method_ty = Ty::new_fn_def(tcx, item.def_id, args);
 
     ConstantKind::zero_sized(method_ty)
 }
diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs
index d828e71c7ac..17295fe1d34 100644
--- a/compiler/rustc_mir_build/src/build/mod.rs
+++ b/compiler/rustc_mir_build/src/build/mod.rs
@@ -10,6 +10,7 @@ use rustc_hir as hir;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::{GeneratorKind, Node};
+use rustc_index::bit_set::GrowableBitSet;
 use rustc_index::{Idx, IndexSlice, IndexVec};
 use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
 use rustc_middle::hir::place::PlaceBase as HirPlaceBase;
@@ -215,6 +216,14 @@ struct Builder<'a, 'tcx> {
     unit_temp: Option<Place<'tcx>>,
 
     var_debug_info: Vec<VarDebugInfo<'tcx>>,
+
+    // A cache for `maybe_lint_level_roots_bounded`. That function is called
+    // repeatedly, and each time it effectively traces a path through a tree
+    // structure from a node towards the root, doing an attribute check on each
+    // node along the way. This cache records which nodes trace all the way to
+    // the root (most of them do) and saves us from retracing many sub-paths
+    // many times, and rechecking many nodes.
+    lint_level_roots_cache: GrowableBitSet<hir::ItemLocalId>,
 }
 
 type CaptureMap<'tcx> = SortedIndexMultiMap<usize, hir::HirId, Capture<'tcx>>;
@@ -473,7 +482,7 @@ fn construct_fn<'tcx>(
     let (yield_ty, return_ty) = if generator_kind.is_some() {
         let gen_ty = arguments[thir::UPVAR_ENV_PARAM].ty;
         let gen_sig = match gen_ty.kind() {
-            ty::Generator(_, gen_substs, ..) => gen_substs.as_generator().sig(),
+            ty::Generator(_, gen_args, ..) => gen_args.as_generator().sig(),
             _ => {
                 span_bug!(span, "generator w/o generator type: {:?}", gen_ty)
             }
@@ -618,11 +627,9 @@ fn construct_error(tcx: TyCtxt<'_>, def: LocalDefId, err: ErrorGuaranteed) -> Bo
     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).subst_identity();
+            let ty = tcx.type_of(def).instantiate_identity();
             match ty.kind() {
-                ty::Closure(_, substs) => {
-                    1 + substs.as_closure().sig().inputs().skip_binder().len()
-                }
+                ty::Closure(_, args) => 1 + args.as_closure().sig().inputs().skip_binder().len(),
                 ty::Generator(..) => 2,
                 _ => bug!("expected closure or generator, found {ty:?}"),
             }
@@ -725,6 +732,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             var_indices: Default::default(),
             unit_temp: None,
             var_debug_info: vec![],
+            lint_level_roots_cache: GrowableBitSet::new_empty(),
         };
 
         assert_eq!(builder.cfg.start_new_block(), START_BLOCK);
@@ -768,9 +776,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             closure_ty = *ty;
         }
 
-        let upvar_substs = match closure_ty.kind() {
-            ty::Closure(_, substs) => ty::UpvarSubsts::Closure(substs),
-            ty::Generator(_, substs, _) => ty::UpvarSubsts::Generator(substs),
+        let upvar_args = match closure_ty.kind() {
+            ty::Closure(_, args) => ty::UpvarArgs::Closure(args),
+            ty::Generator(_, args, _) => ty::UpvarArgs::Generator(args),
             _ => return,
         };
 
@@ -779,7 +787,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         // with the closure's DefId. Here, we run through that vec of UpvarIds for
         // the given closure and use the necessary information to create upvar
         // debuginfo and to fill `self.upvars`.
-        let capture_tys = upvar_substs.upvar_tys();
+        let capture_tys = upvar_args.upvar_tys();
 
         let tcx = self.tcx;
         self.upvars = tcx
diff --git a/compiler/rustc_mir_build/src/build/scope.rs b/compiler/rustc_mir_build/src/build/scope.rs
index 72374102c8c..a96288a11e5 100644
--- a/compiler/rustc_mir_build/src/build/scope.rs
+++ b/compiler/rustc_mir_build/src/build/scope.rs
@@ -90,8 +90,8 @@ use rustc_index::{IndexSlice, IndexVec};
 use rustc_middle::middle::region;
 use rustc_middle::mir::*;
 use rustc_middle::thir::{Expr, LintLevel};
-
 use rustc_middle::ty::Ty;
+use rustc_session::lint::Level;
 use rustc_span::{Span, DUMMY_SP};
 
 #[derive(Debug)]
@@ -760,20 +760,25 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     ) {
         let (current_root, parent_root) =
             if self.tcx.sess.opts.unstable_opts.maximal_hir_to_mir_coverage {
-                // Some consumers of rustc need to map MIR locations back to HIR nodes. Currently the
-                // the only part of rustc that tracks MIR -> HIR is the `SourceScopeLocalData::lint_root`
-                // field that tracks lint levels for MIR locations. Normally the number of source scopes
-                // is limited to the set of nodes with lint annotations. The -Zmaximal-hir-to-mir-coverage
-                // flag changes this behavior to maximize the number of source scopes, increasing the
-                // granularity of the MIR->HIR mapping.
+                // Some consumers of rustc need to map MIR locations back to HIR nodes. Currently
+                // the the only part of rustc that tracks MIR -> HIR is the
+                // `SourceScopeLocalData::lint_root` field that tracks lint levels for MIR
+                // locations. Normally the number of source scopes is limited to the set of nodes
+                // with lint annotations. The -Zmaximal-hir-to-mir-coverage flag changes this
+                // behavior to maximize the number of source scopes, increasing the granularity of
+                // the MIR->HIR mapping.
                 (current_id, parent_id)
             } else {
-                // Use `maybe_lint_level_root_bounded` with `self.hir_id` as a bound
-                // to avoid adding Hir dependencies on our parents.
-                // We estimate the true lint roots here to avoid creating a lot of source scopes.
+                // Use `maybe_lint_level_root_bounded` to avoid adding Hir dependencies on our
+                // parents. We estimate the true lint roots here to avoid creating a lot of source
+                // scopes.
                 (
-                    self.tcx.maybe_lint_level_root_bounded(current_id, self.hir_id),
-                    self.tcx.maybe_lint_level_root_bounded(parent_id, self.hir_id),
+                    self.maybe_lint_level_root_bounded(current_id),
+                    if parent_id == self.hir_id {
+                        parent_id // this is very common
+                    } else {
+                        self.maybe_lint_level_root_bounded(parent_id)
+                    },
                 )
             };
 
@@ -783,6 +788,50 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         }
     }
 
+    /// Walks upwards from `orig_id` to find a node which might change lint levels with attributes.
+    /// It stops at `self.hir_id` and just returns it if reached.
+    fn maybe_lint_level_root_bounded(&mut self, orig_id: HirId) -> HirId {
+        // This assertion lets us just store `ItemLocalId` in the cache, rather
+        // than the full `HirId`.
+        assert_eq!(orig_id.owner, self.hir_id.owner);
+
+        let mut id = orig_id;
+        let hir = self.tcx.hir();
+        loop {
+            if id == self.hir_id {
+                // This is a moderately common case, mostly hit for previously unseen nodes.
+                break;
+            }
+
+            if hir.attrs(id).iter().any(|attr| Level::from_attr(attr).is_some()) {
+                // This is a rare case. It's for a node path that doesn't reach the root due to an
+                // intervening lint level attribute. This result doesn't get cached.
+                return id;
+            }
+
+            let next = hir.parent_id(id);
+            if next == id {
+                bug!("lint traversal reached the root of the crate");
+            }
+            id = next;
+
+            // This lookup is just an optimization; it can be removed without affecting
+            // functionality. It might seem strange to see this at the end of this loop, but the
+            // `orig_id` passed in to this function is almost always previously unseen, for which a
+            // lookup will be a miss. So we only do lookups for nodes up the parent chain, where
+            // cache lookups have a very high hit rate.
+            if self.lint_level_roots_cache.contains(id.local_id) {
+                break;
+            }
+        }
+
+        // `orig_id` traced to `self_id`; record this fact. If `orig_id` is a leaf node it will
+        // rarely (never?) subsequently be searched for, but it's hard to know if that is the case.
+        // The performance wins from the cache all come from caching non-leaf nodes.
+        self.lint_level_roots_cache.insert(orig_id.local_id);
+        self.hir_id
+    }
+
     /// Creates a new source scope, nested in the current one.
     pub(crate) fn new_source_scope(
         &mut self,
diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs
index 6b2b140fa25..8b4ff9bb868 100644
--- a/compiler/rustc_mir_build/src/check_unsafety.rs
+++ b/compiler/rustc_mir_build/src/check_unsafety.rs
@@ -383,7 +383,7 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
             ExprKind::Adt(box AdtExpr {
                 adt_def,
                 variant_index: _,
-                substs: _,
+                args: _,
                 user_ty: _,
                 fields: _,
                 base: _,
@@ -393,14 +393,14 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
             },
             ExprKind::Closure(box ClosureExpr {
                 closure_id,
-                substs: _,
+                args: _,
                 upvars: _,
                 movability: _,
                 fake_reads: _,
             }) => {
                 self.visit_inner_body(closure_id);
             }
-            ExprKind::ConstBlock { did, substs: _ } => {
+            ExprKind::ConstBlock { did, args: _ } => {
                 let def_id = did.expect_local();
                 self.visit_inner_body(def_id);
             }
@@ -712,9 +712,7 @@ pub fn thir_check_unsafety(tcx: TyCtxt<'_>, def: LocalDefId) {
         return;
     }
 
-    let Ok((thir, expr)) = tcx.thir_body(def) else {
-        return
-    };
+    let Ok((thir, expr)) = tcx.thir_body(def) else { return };
     let thir = &thir.borrow();
     // If `thir` is empty, a type error occurred, skip this body.
     if thir.exprs.is_empty() {
diff --git a/compiler/rustc_mir_build/src/lints.rs b/compiler/rustc_mir_build/src/lints.rs
index 8e41957af0e..3f0cc69ec59 100644
--- a/compiler/rustc_mir_build/src/lints.rs
+++ b/compiler/rustc_mir_build/src/lints.rs
@@ -4,8 +4,8 @@ use rustc_data_structures::graph::iterate::{
 };
 use rustc_hir::def::DefKind;
 use rustc_middle::mir::{self, BasicBlock, BasicBlocks, Body, Operand, TerminatorKind};
-use rustc_middle::ty::subst::{GenericArg, InternalSubsts};
 use rustc_middle::ty::{self, Instance, TyCtxt};
+use rustc_middle::ty::{GenericArg, GenericArgs};
 use rustc_session::lint::builtin::UNCONDITIONAL_RECURSION;
 use rustc_span::Span;
 use std::ops::ControlFlow;
@@ -14,16 +14,16 @@ pub(crate) fn check<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) {
     let def_id = body.source.def_id().expect_local();
 
     if let DefKind::Fn | DefKind::AssocFn = tcx.def_kind(def_id) {
-        // If this is trait/impl method, extract the trait's substs.
-        let trait_substs = match tcx.trait_of_item(def_id.to_def_id()) {
+        // If this is trait/impl method, extract the trait's args.
+        let trait_args = match tcx.trait_of_item(def_id.to_def_id()) {
             Some(trait_def_id) => {
-                let trait_substs_count = tcx.generics_of(trait_def_id).count();
-                &InternalSubsts::identity_for_item(tcx, def_id)[..trait_substs_count]
+                let trait_args_count = tcx.generics_of(trait_def_id).count();
+                &GenericArgs::identity_for_item(tcx, def_id)[..trait_args_count]
             }
             _ => &[],
         };
 
-        let mut vis = Search { tcx, body, reachable_recursive_calls: vec![], trait_substs };
+        let mut vis = Search { tcx, body, reachable_recursive_calls: vec![], trait_args };
         if let Some(NonRecursive) =
             TriColorDepthFirstSearch::new(&body.basic_blocks).run_from_start(&mut vis)
         {
@@ -51,7 +51,7 @@ struct NonRecursive;
 struct Search<'mir, 'tcx> {
     tcx: TyCtxt<'tcx>,
     body: &'mir Body<'tcx>,
-    trait_substs: &'tcx [GenericArg<'tcx>],
+    trait_args: &'tcx [GenericArg<'tcx>],
 
     reachable_recursive_calls: Vec<Span>,
 }
@@ -59,7 +59,7 @@ struct Search<'mir, 'tcx> {
 impl<'mir, 'tcx> Search<'mir, 'tcx> {
     /// Returns `true` if `func` refers to the function we are searching in.
     fn is_recursive_call(&self, func: &Operand<'tcx>, args: &[Operand<'tcx>]) -> bool {
-        let Search { tcx, body, trait_substs, .. } = *self;
+        let Search { tcx, body, trait_args, .. } = *self;
         // Resolving function type to a specific instance that is being called is expensive. To
         // avoid the cost we check the number of arguments first, which is sufficient to reject
         // most of calls as non-recursive.
@@ -70,23 +70,23 @@ impl<'mir, 'tcx> Search<'mir, 'tcx> {
         let param_env = tcx.param_env(caller);
 
         let func_ty = func.ty(body, tcx);
-        if let ty::FnDef(callee, substs) = *func_ty.kind() {
-            let normalized_substs = tcx.normalize_erasing_regions(param_env, substs);
-            let (callee, call_substs) = if let Ok(Some(instance)) =
-                Instance::resolve(tcx, param_env, callee, normalized_substs)
+        if let ty::FnDef(callee, args) = *func_ty.kind() {
+            let normalized_args = tcx.normalize_erasing_regions(param_env, args);
+            let (callee, call_args) = if let Ok(Some(instance)) =
+                Instance::resolve(tcx, param_env, callee, normalized_args)
             {
-                (instance.def_id(), instance.substs)
+                (instance.def_id(), instance.args)
             } else {
-                (callee, normalized_substs)
+                (callee, normalized_args)
             };
 
             // FIXME(#57965): Make this work across function boundaries
 
-            // If this is a trait fn, the substs on the trait have to match, or we might be
+            // If this is a trait fn, the args on the trait have to match, or we might be
             // calling into an entirely different method (for example, a call from the default
             // method in the trait to `<A as Trait<B>>::method`, where `A` and/or `B` are
             // specific types).
-            return callee == caller && &call_substs[..trait_substs.len()] == trait_substs;
+            return callee == caller && &call_args[..trait_args.len()] == trait_args;
         }
 
         false
diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs
index accc02b5987..711a9126c04 100644
--- a/compiler/rustc_mir_build/src/thir/cx/expr.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs
@@ -15,9 +15,9 @@ use rustc_middle::thir::*;
 use rustc_middle::ty::adjustment::{
     Adjust, Adjustment, AutoBorrow, AutoBorrowMutability, PointerCoercion,
 };
-use rustc_middle::ty::subst::InternalSubsts;
+use rustc_middle::ty::GenericArgs;
 use rustc_middle::ty::{
-    self, AdtKind, InlineConstSubsts, InlineConstSubstsParts, ScalarInt, Ty, UpvarSubsts, UserType,
+    self, AdtKind, InlineConstArgs, InlineConstArgsParts, ScalarInt, Ty, UpvarArgs, UserType,
 };
 use rustc_span::{sym, Span};
 use rustc_target::abi::{FieldIdx, FIRST_VARIANT};
@@ -210,7 +210,7 @@ impl<'tcx> Cx<'tcx> {
 
             let res = self.typeck_results().qpath_res(qpath, source.hir_id);
             let ty = self.typeck_results().node_type(source.hir_id);
-            let ty::Adt(adt_def, substs) = ty.kind() else {
+            let ty::Adt(adt_def, args) = ty.kind() else {
                 return ExprKind::Cast { source: self.mirror_expr(source) };
             };
 
@@ -242,7 +242,7 @@ impl<'tcx> Cx<'tcx> {
                 // in case we are offsetting from a computed discriminant
                 // and not the beginning of discriminants (which is always `0`)
                 Some(did) => {
-                    let kind = ExprKind::NamedConst { def_id: did, substs, user_ty: None };
+                    let kind = ExprKind::NamedConst { def_id: did, args, user_ty: None };
                     let lhs =
                         self.thir.exprs.push(Expr { temp_lifetime, ty: discr_ty, span, kind });
                     let bin = ExprKind::Binary { op: BinOp::Add, lhs, rhs: offset };
@@ -372,7 +372,7 @@ impl<'tcx> Cx<'tcx> {
                         None
                     };
                     if let Some((adt_def, index)) = adt_data {
-                        let substs = self.typeck_results().node_substs(fun.hir_id);
+                        let node_args = self.typeck_results().node_args(fun.hir_id);
                         let user_provided_types = self.typeck_results().user_provided_types();
                         let user_ty =
                             user_provided_types.get(fun.hir_id).copied().map(|mut u_ty| {
@@ -393,7 +393,7 @@ impl<'tcx> Cx<'tcx> {
                             .collect();
                         ExprKind::Adt(Box::new(AdtExpr {
                             adt_def,
-                            substs,
+                            args: node_args,
                             variant_index: index,
                             fields: field_refs,
                             user_ty,
@@ -511,7 +511,7 @@ impl<'tcx> Cx<'tcx> {
             }
 
             hir::ExprKind::Struct(ref qpath, ref fields, ref base) => match expr_ty.kind() {
-                ty::Adt(adt, substs) => match adt.adt_kind() {
+                ty::Adt(adt, args) => match adt.adt_kind() {
                     AdtKind::Struct | AdtKind::Union => {
                         let user_provided_types = self.typeck_results().user_provided_types();
                         let user_ty = user_provided_types.get(expr.hir_id).copied().map(Box::new);
@@ -519,7 +519,7 @@ impl<'tcx> Cx<'tcx> {
                         ExprKind::Adt(Box::new(AdtExpr {
                             adt_def: *adt,
                             variant_index: FIRST_VARIANT,
-                            substs,
+                            args,
                             user_ty,
                             fields: self.field_refs(fields),
                             base: base.map(|base| FruInfo {
@@ -546,7 +546,7 @@ impl<'tcx> Cx<'tcx> {
                                 ExprKind::Adt(Box::new(AdtExpr {
                                     adt_def: *adt,
                                     variant_index: index,
-                                    substs,
+                                    args,
                                     user_ty,
                                     fields: self.field_refs(fields),
                                     base: None,
@@ -565,10 +565,10 @@ impl<'tcx> Cx<'tcx> {
 
             hir::ExprKind::Closure { .. } => {
                 let closure_ty = self.typeck_results().expr_ty(expr);
-                let (def_id, substs, movability) = match *closure_ty.kind() {
-                    ty::Closure(def_id, substs) => (def_id, UpvarSubsts::Closure(substs), None),
-                    ty::Generator(def_id, substs, movability) => {
-                        (def_id, UpvarSubsts::Generator(substs), Some(movability))
+                let (def_id, args, movability) = match *closure_ty.kind() {
+                    ty::Closure(def_id, args) => (def_id, UpvarArgs::Closure(args), None),
+                    ty::Generator(def_id, args, movability) => {
+                        (def_id, UpvarArgs::Generator(args), Some(movability))
                     }
                     _ => {
                         span_bug!(expr.span, "closure expr w/o closure type: {:?}", closure_ty);
@@ -580,7 +580,7 @@ impl<'tcx> Cx<'tcx> {
                     .tcx
                     .closure_captures(def_id)
                     .iter()
-                    .zip(substs.upvar_tys())
+                    .zip(args.upvar_tys())
                     .map(|(captured_place, ty)| {
                         let upvars = self.capture_upvar(expr, captured_place, ty);
                         self.thir.exprs.push(upvars)
@@ -601,7 +601,7 @@ impl<'tcx> Cx<'tcx> {
 
                 ExprKind::Closure(Box::new(ClosureExpr {
                     closure_id: def_id,
-                    substs,
+                    args,
                     upvars,
                     movability,
                     fake_reads,
@@ -684,13 +684,11 @@ impl<'tcx> Cx<'tcx> {
                 let ty = self.typeck_results().node_type(anon_const.hir_id);
                 let did = anon_const.def_id.to_def_id();
                 let typeck_root_def_id = tcx.typeck_root_def_id(did);
-                let parent_substs =
-                    tcx.erase_regions(InternalSubsts::identity_for_item(tcx, typeck_root_def_id));
-                let substs =
-                    InlineConstSubsts::new(tcx, InlineConstSubstsParts { parent_substs, ty })
-                        .substs;
+                let parent_args =
+                    tcx.erase_regions(GenericArgs::identity_for_item(tcx, typeck_root_def_id));
+                let args = InlineConstArgs::new(tcx, InlineConstArgsParts { parent_args, ty }).args;
 
-                ExprKind::ConstBlock { did, substs }
+                ExprKind::ConstBlock { did, args }
             }
             // Now comes the rote stuff:
             hir::ExprKind::Repeat(ref v, _) => {
@@ -809,12 +807,12 @@ impl<'tcx> Cx<'tcx> {
         Expr { temp_lifetime, ty: expr_ty, span: expr.span, kind }
     }
 
-    fn user_substs_applied_to_res(
+    fn user_args_applied_to_res(
         &mut self,
         hir_id: hir::HirId,
         res: Res,
     ) -> Option<Box<ty::CanonicalUserType<'tcx>>> {
-        debug!("user_substs_applied_to_res: res={:?}", res);
+        debug!("user_args_applied_to_res: res={:?}", res);
         let user_provided_type = match res {
             // A reference to something callable -- e.g., a fn, method, or
             // a tuple-struct or tuple-variant. This has the type of a
@@ -832,15 +830,15 @@ impl<'tcx> Cx<'tcx> {
             // this variant -- but with the substitutions given by the
             // user.
             Res::Def(DefKind::Ctor(_, CtorKind::Const), _) => {
-                self.user_substs_applied_to_ty_of_hir_id(hir_id).map(Box::new)
+                self.user_args_applied_to_ty_of_hir_id(hir_id).map(Box::new)
             }
 
             // `Self` is used in expression as a tuple struct constructor or a unit struct constructor
-            Res::SelfCtor(_) => self.user_substs_applied_to_ty_of_hir_id(hir_id).map(Box::new),
+            Res::SelfCtor(_) => self.user_args_applied_to_ty_of_hir_id(hir_id).map(Box::new),
 
-            _ => bug!("user_substs_applied_to_res: unexpected res {:?} at {:?}", res, hir_id),
+            _ => bug!("user_args_applied_to_res: unexpected res {:?} at {:?}", res, hir_id),
         };
-        debug!("user_substs_applied_to_res: user_provided_type={:?}", user_provided_type);
+        debug!("user_args_applied_to_res: user_provided_type={:?}", user_provided_type);
         user_provided_type
     }
 
@@ -859,13 +857,13 @@ impl<'tcx> Cx<'tcx> {
                     self.typeck_results().type_dependent_def(expr.hir_id).unwrap_or_else(|| {
                         span_bug!(expr.span, "no type-dependent def for method callee")
                     });
-                let user_ty = self.user_substs_applied_to_res(expr.hir_id, Res::Def(kind, def_id));
+                let user_ty = self.user_args_applied_to_res(expr.hir_id, Res::Def(kind, def_id));
                 debug!("method_callee: user_ty={:?}", user_ty);
                 (
                     Ty::new_fn_def(
                         self.tcx(),
                         def_id,
-                        self.typeck_results().node_substs(expr.hir_id),
+                        self.typeck_results().node_args(expr.hir_id),
                     ),
                     user_ty,
                 )
@@ -892,14 +890,14 @@ impl<'tcx> Cx<'tcx> {
     }
 
     fn convert_path_expr(&mut self, expr: &'tcx hir::Expr<'tcx>, res: Res) -> ExprKind<'tcx> {
-        let substs = self.typeck_results().node_substs(expr.hir_id);
+        let args = self.typeck_results().node_args(expr.hir_id);
         match res {
             // A regular function, constructor function or a constant.
             Res::Def(DefKind::Fn, _)
             | Res::Def(DefKind::AssocFn, _)
             | Res::Def(DefKind::Ctor(_, CtorKind::Fn), _)
             | Res::SelfCtor(_) => {
-                let user_ty = self.user_substs_applied_to_res(expr.hir_id, res);
+                let user_ty = self.user_args_applied_to_res(expr.hir_id, res);
                 ExprKind::ZstLiteral { user_ty }
             }
 
@@ -914,8 +912,8 @@ impl<'tcx> Cx<'tcx> {
             }
 
             Res::Def(DefKind::Const, def_id) | Res::Def(DefKind::AssocConst, def_id) => {
-                let user_ty = self.user_substs_applied_to_res(expr.hir_id, res);
-                ExprKind::NamedConst { def_id, substs, user_ty }
+                let user_ty = self.user_args_applied_to_res(expr.hir_id, res);
+                ExprKind::NamedConst { def_id, args, user_ty }
             }
 
             Res::Def(DefKind::Ctor(_, CtorKind::Const), def_id) => {
@@ -926,10 +924,10 @@ impl<'tcx> Cx<'tcx> {
                 match ty.kind() {
                     // A unit struct/variant which is used as a value.
                     // We return a completely different ExprKind here to account for this special case.
-                    ty::Adt(adt_def, substs) => ExprKind::Adt(Box::new(AdtExpr {
+                    ty::Adt(adt_def, args) => ExprKind::Adt(Box::new(AdtExpr {
                         adt_def: *adt_def,
                         variant_index: adt_def.variant_index_with_ctor_id(def_id),
-                        substs,
+                        args,
                         user_ty,
                         fields: Box::new([]),
                         base: None,
diff --git a/compiler/rustc_mir_build/src/thir/cx/mod.rs b/compiler/rustc_mir_build/src/thir/cx/mod.rs
index e09e22af761..d98cc76adfb 100644
--- a/compiler/rustc_mir_build/src/thir/cx/mod.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/mod.rs
@@ -122,7 +122,7 @@ impl<'tcx> Cx<'tcx> {
             DefKind::Closure => {
                 let closure_ty = self.typeck_results.node_type(owner_id);
 
-                let ty::Closure(closure_def_id, closure_substs) = *closure_ty.kind() else {
+                let ty::Closure(closure_def_id, closure_args) = *closure_ty.kind() else {
                     bug!("closure expr does not have closure type: {:?}", closure_ty);
                 };
 
@@ -134,7 +134,7 @@ impl<'tcx> Cx<'tcx> {
                 };
                 let env_region = ty::Region::new_late_bound(self.tcx, ty::INNERMOST, br);
                 let closure_env_ty =
-                    self.tcx.closure_env_ty(closure_def_id, closure_substs, env_region).unwrap();
+                    self.tcx.closure_env_ty(closure_def_id, closure_args, env_region).unwrap();
                 let liberated_closure_env_ty = self.tcx.erase_late_bound_regions(
                     ty::Binder::bind_with_vars(closure_env_ty, bound_vars),
                 );
@@ -186,7 +186,7 @@ impl<'tcx> Cx<'tcx> {
 
                 self.tcx
                     .type_of(va_list_did)
-                    .subst(self.tcx, &[self.tcx.lifetimes.re_erased.into()])
+                    .instantiate(self.tcx, &[self.tcx.lifetimes.re_erased.into()])
             } else {
                 fn_sig.inputs()[index]
             };
diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
index ef60f08bf02..38c866c50a2 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
@@ -501,12 +501,12 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
         let witness_1_is_privately_uninhabited =
             if cx.tcx.features().exhaustive_patterns
                 && let Some(witness_1) = witnesses.get(0)
-                && let ty::Adt(adt, substs) = witness_1.ty().kind()
+                && let ty::Adt(adt, args) = witness_1.ty().kind()
                 && adt.is_enum()
                 && let Constructor::Variant(variant_index) = witness_1.ctor()
             {
                 let variant = adt.variant(*variant_index);
-                let inhabited = variant.inhabited_predicate(cx.tcx, *adt).subst(cx.tcx, substs);
+                let inhabited = variant.inhabited_predicate(cx.tcx, *adt).instantiate(cx.tcx, args);
                 assert!(inhabited.apply(cx.tcx, cx.param_env, cx.module));
                 !inhabited.apply_ignore_module(cx.tcx, cx.param_env)
             } else {
@@ -942,7 +942,9 @@ fn maybe_point_at_variant<'a, 'p: 'a, 'tcx: 'a>(
 /// This analysis is *not* subsumed by NLL.
 fn check_borrow_conflicts_in_at_patterns<'tcx>(cx: &MatchVisitor<'_, '_, 'tcx>, pat: &Pat<'tcx>) {
     // Extract `sub` in `binding @ sub`.
-    let PatKind::Binding { name, mode, ty, subpattern: Some(box ref sub), .. } = pat.kind else { return };
+    let PatKind::Binding { name, mode, ty, subpattern: Some(box ref sub), .. } = pat.kind else {
+        return;
+    };
 
     let is_binding_by_move = |ty: Ty<'tcx>| !ty.is_copy_modulo_regions(cx.tcx, cx.param_env);
 
diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
index 050b01294b4..251c6b4b6da 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
@@ -332,20 +332,20 @@ impl<'tcx> ConstToPat<'tcx> {
                 tcx.sess.emit_err(err);
                 PatKind::Wild
             }
-            ty::Adt(adt_def, substs) if adt_def.is_enum() => {
+            ty::Adt(adt_def, args) if adt_def.is_enum() => {
                 let (&variant_index, fields) = cv.unwrap_branch().split_first().unwrap();
                 let variant_index =
                     VariantIdx::from_u32(variant_index.unwrap_leaf().try_to_u32().ok().unwrap());
                 PatKind::Variant {
                     adt_def: *adt_def,
-                    substs,
+                    args,
                     variant_index,
                     subpatterns: self.field_pats(
                         fields.iter().copied().zip(
                             adt_def.variants()[variant_index]
                                 .fields
                                 .iter()
-                                .map(|field| field.ty(self.tcx(), substs)),
+                                .map(|field| field.ty(self.tcx(), args)),
                         ),
                     )?,
                 }
@@ -354,9 +354,9 @@ impl<'tcx> ConstToPat<'tcx> {
                 subpatterns: self
                     .field_pats(cv.unwrap_branch().iter().copied().zip(fields.iter()))?,
             },
-            ty::Adt(def, substs) => PatKind::Leaf {
+            ty::Adt(def, args) => PatKind::Leaf {
                 subpatterns: self.field_pats(cv.unwrap_branch().iter().copied().zip(
-                    def.non_enum_variant().fields.iter().map(|field| field.ty(self.tcx(), substs)),
+                    def.non_enum_variant().fields.iter().map(|field| field.ty(self.tcx(), args)),
                 ))?,
             },
             ty::Slice(elem_ty) => PatKind::Slice {
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 9df6d2f43ad..4228597cdc9 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs
@@ -922,7 +922,7 @@ impl<'tcx> SplitWildcard<'tcx> {
                 let kind = if cx.is_uninhabited(*sub_ty) { FixedLen(0) } else { VarLen(0, 0) };
                 smallvec![Slice(Slice::new(None, kind))]
             }
-            ty::Adt(def, substs) if def.is_enum() => {
+            ty::Adt(def, args) if def.is_enum() => {
                 // If the enum is declared as `#[non_exhaustive]`, we treat it as if it had an
                 // additional "unknown" constructor.
                 // There is no point in enumerating all possible variants, because the user can't
@@ -950,21 +950,19 @@ impl<'tcx> SplitWildcard<'tcx> {
                 let is_secretly_empty =
                     def.variants().is_empty() && !is_exhaustive_pat_feature && !pcx.is_top_level;
 
-                let mut ctors: SmallVec<[_; 1]> = def
-                    .variants()
-                    .iter_enumerated()
-                    .filter(|(_, v)| {
-                        // If `exhaustive_patterns` is enabled, we exclude variants known to be
-                        // uninhabited.
-                        !is_exhaustive_pat_feature
-                            || v.inhabited_predicate(cx.tcx, *def).subst(cx.tcx, substs).apply(
-                                cx.tcx,
-                                cx.param_env,
-                                cx.module,
-                            )
-                    })
-                    .map(|(idx, _)| Variant(idx))
-                    .collect();
+                let mut ctors: SmallVec<[_; 1]> =
+                    def.variants()
+                        .iter_enumerated()
+                        .filter(|(_, v)| {
+                            // If `exhaustive_patterns` is enabled, we exclude variants known to be
+                            // uninhabited.
+                            !is_exhaustive_pat_feature
+                                || v.inhabited_predicate(cx.tcx, *def)
+                                    .instantiate(cx.tcx, args)
+                                    .apply(cx.tcx, cx.param_env, cx.module)
+                        })
+                        .map(|(idx, _)| Variant(idx))
+                        .collect();
 
                 if is_secretly_empty || is_declared_nonexhaustive {
                     ctors.push(NonExhaustive);
@@ -1156,12 +1154,12 @@ impl<'p, 'tcx> Fields<'p, 'tcx> {
         ty: Ty<'tcx>,
         variant: &'a VariantDef,
     ) -> impl Iterator<Item = (FieldIdx, Ty<'tcx>)> + Captures<'a> + Captures<'p> {
-        let ty::Adt(adt, substs) = ty.kind() else { bug!() };
+        let ty::Adt(adt, args) = ty.kind() else { bug!() };
         // Whether we must not match the fields of this variant exhaustively.
         let is_non_exhaustive = variant.is_field_list_non_exhaustive() && !adt.did().is_local();
 
         variant.fields.iter().enumerate().filter_map(move |(i, field)| {
-            let ty = field.ty(cx.tcx, substs);
+            let ty = field.ty(cx.tcx, args);
             // `field.ty()` doesn't normalize after substituting.
             let ty = cx.tcx.normalize_erasing_regions(cx.param_env, ty);
             let is_visible = adt.is_enum() || field.vis.is_accessible_from(cx.module, cx.tcx);
@@ -1183,11 +1181,11 @@ impl<'p, 'tcx> Fields<'p, 'tcx> {
             Single | Variant(_) => match pcx.ty.kind() {
                 ty::Tuple(fs) => Fields::wildcards_from_tys(pcx.cx, fs.iter(), pcx.span),
                 ty::Ref(_, rty, _) => Fields::wildcards_from_tys(pcx.cx, once(*rty), pcx.span),
-                ty::Adt(adt, substs) => {
+                ty::Adt(adt, args) => {
                     if adt.is_box() {
                         // The only legal patterns of type `Box` (outside `std`) are `_` and box
                         // patterns. If we're here we can assume this is a box pattern.
-                        Fields::wildcards_from_tys(pcx.cx, once(substs.type_at(0)), pcx.span)
+                        Fields::wildcards_from_tys(pcx.cx, once(args.type_at(0)), pcx.span)
                     } else {
                         let variant = &adt.variant(constructor.variant_index_for_adt(*adt));
                         let tys = Fields::list_variant_nonhidden_fields(pcx.cx, pcx.ty, variant)
@@ -1294,7 +1292,7 @@ impl<'p, 'tcx> DeconstructedPat<'p, 'tcx> {
                         }
                         fields = Fields::from_iter(cx, wilds);
                     }
-                    ty::Adt(adt, substs) if adt.is_box() => {
+                    ty::Adt(adt, args) if adt.is_box() => {
                         // The only legal patterns of type `Box` (outside `std`) are `_` and box
                         // patterns. If we're here we can assume this is a box pattern.
                         // FIXME(Nadrieril): A `Box` can in theory be matched either with `Box(_,
@@ -1311,7 +1309,7 @@ impl<'p, 'tcx> DeconstructedPat<'p, 'tcx> {
                         let pat = if let Some(pat) = pattern {
                             mkpat(&pat.pattern)
                         } else {
-                            DeconstructedPat::wildcard(substs.type_at(0), pat.span)
+                            DeconstructedPat::wildcard(args.type_at(0), pat.span)
                         };
                         ctor = Single;
                         fields = Fields::singleton(cx, pat);
@@ -1437,7 +1435,7 @@ impl<'p, 'tcx> DeconstructedPat<'p, 'tcx> {
                     // the pattern is a box pattern.
                     PatKind::Deref { subpattern: subpatterns.next().unwrap() }
                 }
-                ty::Adt(adt_def, substs) => {
+                ty::Adt(adt_def, args) => {
                     let variant_index = self.ctor.variant_index_for_adt(*adt_def);
                     let variant = &adt_def.variant(variant_index);
                     let subpatterns = Fields::list_variant_nonhidden_fields(cx, self.ty, variant)
@@ -1446,7 +1444,7 @@ impl<'p, 'tcx> DeconstructedPat<'p, 'tcx> {
                         .collect();
 
                     if adt_def.is_enum() {
-                        PatKind::Variant { adt_def: *adt_def, substs, variant_index, subpatterns }
+                        PatKind::Variant { adt_def: *adt_def, args, variant_index, subpatterns }
                     } else {
                         PatKind::Leaf { subpatterns }
                     }
diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
index 60099592784..3c3cbbf3614 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
@@ -23,10 +23,10 @@ use rustc_middle::mir::interpret::{
 use rustc_middle::mir::{self, ConstantKind, UserTypeProjection};
 use rustc_middle::mir::{BorrowKind, Mutability};
 use rustc_middle::thir::{Ascription, BindingMode, FieldPat, LocalVarId, Pat, PatKind, PatRange};
-use rustc_middle::ty::subst::{GenericArg, SubstsRef};
 use rustc_middle::ty::CanonicalUserTypeAnnotation;
 use rustc_middle::ty::TypeVisitableExt;
 use rustc_middle::ty::{self, AdtDef, Region, Ty, TyCtxt, UserType};
+use rustc_middle::ty::{GenericArg, GenericArgsRef};
 use rustc_span::{Span, Symbol};
 use rustc_target::abi::FieldIdx;
 
@@ -416,8 +416,8 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
                 let enum_id = self.tcx.parent(variant_id);
                 let adt_def = self.tcx.adt_def(enum_id);
                 if adt_def.is_enum() {
-                    let substs = match ty.kind() {
-                        ty::Adt(_, substs) | ty::FnDef(_, substs) => substs,
+                    let args = match ty.kind() {
+                        ty::Adt(_, args) | ty::FnDef(_, args) => args,
                         ty::Error(_) => {
                             // Avoid ICE (#50585)
                             return PatKind::Wild;
@@ -426,7 +426,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
                     };
                     PatKind::Variant {
                         adt_def,
-                        substs,
+                        args,
                         variant_index: adt_def.variant_index_with_id(variant_id),
                         subpatterns,
                     }
@@ -460,7 +460,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
             }
         };
 
-        if let Some(user_ty) = self.user_substs_applied_to_ty_of_hir_id(hir_id) {
+        if let Some(user_ty) = self.user_args_applied_to_ty_of_hir_id(hir_id) {
             debug!("lower_variant_or_leaf: kind={:?} user_ty={:?} span={:?}", kind, user_ty, span);
             let annotation = CanonicalUserTypeAnnotation {
                 user_ty: Box::new(user_ty),
@@ -496,13 +496,13 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
         // Use `Reveal::All` here because patterns are always monomorphic even if their function
         // isn't.
         let param_env_reveal_all = self.param_env.with_reveal_all_normalized(self.tcx);
-        // N.B. There is no guarantee that substs collected in typeck results are fully normalized,
+        // N.B. There is no guarantee that args collected in typeck results are fully normalized,
         // so they need to be normalized in order to pass to `Instance::resolve`, which will ICE
         // if given unnormalized types.
-        let substs = self
+        let args = self
             .tcx
-            .normalize_erasing_regions(param_env_reveal_all, self.typeck_results.node_substs(id));
-        let instance = match ty::Instance::resolve(self.tcx, param_env_reveal_all, def_id, substs) {
+            .normalize_erasing_regions(param_env_reveal_all, self.typeck_results.node_args(id));
+        let instance = match ty::Instance::resolve(self.tcx, param_env_reveal_all, def_id, args) {
             Ok(Some(i)) => i,
             Ok(None) => {
                 // It should be assoc consts if there's no error but we cannot resolve it.
@@ -617,16 +617,14 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
         }
 
         let typeck_root_def_id = tcx.typeck_root_def_id(def_id.to_def_id());
-        let parent_substs =
-            tcx.erase_regions(ty::InternalSubsts::identity_for_item(tcx, typeck_root_def_id));
-        let substs =
-            ty::InlineConstSubsts::new(tcx, ty::InlineConstSubstsParts { parent_substs, ty })
-                .substs;
+        let parent_args =
+            tcx.erase_regions(ty::GenericArgs::identity_for_item(tcx, typeck_root_def_id));
+        let args = ty::InlineConstArgs::new(tcx, ty::InlineConstArgsParts { parent_args, ty }).args;
 
-        let uneval = mir::UnevaluatedConst { def: def_id.to_def_id(), substs, promoted: None };
-        debug_assert!(!substs.has_free_regions());
+        let uneval = mir::UnevaluatedConst { def: def_id.to_def_id(), args, promoted: None };
+        debug_assert!(!args.has_free_regions());
 
-        let ct = ty::UnevaluatedConst { def: def_id.to_def_id(), substs: substs };
+        let ct = ty::UnevaluatedConst { def: def_id.to_def_id(), args: args };
         // First try using a valtree in order to destructure the constant into a pattern.
         if let Ok(Some(valtree)) =
             self.tcx.const_eval_resolve_for_typeck(self.param_env, ct, Some(span))
@@ -754,7 +752,7 @@ macro_rules! ClonePatternFoldableImpls {
 ClonePatternFoldableImpls! { <'tcx>
     Span, FieldIdx, Mutability, Symbol, LocalVarId, usize,
     Region<'tcx>, Ty<'tcx>, BindingMode, AdtDef<'tcx>,
-    SubstsRef<'tcx>, &'tcx GenericArg<'tcx>, UserType<'tcx>,
+    GenericArgsRef<'tcx>, &'tcx GenericArg<'tcx>, UserType<'tcx>,
     UserTypeProjection, CanonicalUserTypeAnnotation<'tcx>
 }
 
@@ -804,10 +802,10 @@ impl<'tcx> PatternFoldable<'tcx> for PatKind<'tcx> {
                     is_primary,
                 }
             }
-            PatKind::Variant { adt_def, substs, variant_index, ref subpatterns } => {
+            PatKind::Variant { adt_def, args, variant_index, ref subpatterns } => {
                 PatKind::Variant {
                     adt_def: adt_def.fold_with(folder),
-                    substs: substs.fold_with(folder),
+                    args: args.fold_with(folder),
                     variant_index,
                     subpatterns: subpatterns.fold_with(folder),
                 }
diff --git a/compiler/rustc_mir_build/src/thir/print.rs b/compiler/rustc_mir_build/src/thir/print.rs
index 8d7c624a805..903dbeeadfa 100644
--- a/compiler/rustc_mir_build/src/thir/print.rs
+++ b/compiler/rustc_mir_build/src/thir/print.rs
@@ -427,10 +427,10 @@ impl<'a, 'tcx> ThirPrinter<'a, 'tcx> {
                 self.print_expr(*value, depth_lvl + 2);
                 print_indented!(self, "}", depth_lvl);
             }
-            ConstBlock { did, substs } => {
+            ConstBlock { did, args } => {
                 print_indented!(self, "ConstBlock {", depth_lvl);
                 print_indented!(self, format!("did: {:?}", did), depth_lvl + 1);
-                print_indented!(self, format!("substs: {:?}", substs), depth_lvl + 1);
+                print_indented!(self, format!("args: {:?}", args), depth_lvl + 1);
                 print_indented!(self, "}", depth_lvl);
             }
             Repeat { value, count } => {
@@ -499,11 +499,11 @@ impl<'a, 'tcx> ThirPrinter<'a, 'tcx> {
             ZstLiteral { user_ty } => {
                 print_indented!(self, format!("ZstLiteral(user_ty: {:?})", user_ty), depth_lvl);
             }
-            NamedConst { def_id, substs, user_ty } => {
+            NamedConst { def_id, args, user_ty } => {
                 print_indented!(self, "NamedConst {", depth_lvl);
                 print_indented!(self, format!("def_id: {:?}", def_id), depth_lvl + 1);
                 print_indented!(self, format!("user_ty: {:?}", user_ty), depth_lvl + 1);
-                print_indented!(self, format!("substs: {:?}", substs), depth_lvl + 1);
+                print_indented!(self, format!("args: {:?}", args), depth_lvl + 1);
                 print_indented!(self, "}", depth_lvl);
             }
             ConstParam { param, def_id } => {
@@ -560,7 +560,7 @@ impl<'a, 'tcx> ThirPrinter<'a, 'tcx> {
             format!("variant_index: {:?}", adt_expr.variant_index),
             depth_lvl + 1
         );
-        print_indented!(self, format!("substs: {:?}", adt_expr.substs), depth_lvl + 1);
+        print_indented!(self, format!("args: {:?}", adt_expr.args), depth_lvl + 1);
         print_indented!(self, format!("user_ty: {:?}", adt_expr.user_ty), depth_lvl + 1);
 
         for (i, field_expr) in adt_expr.fields.iter().enumerate() {
@@ -662,11 +662,11 @@ impl<'a, 'tcx> ThirPrinter<'a, 'tcx> {
 
                 print_indented!(self, "}", depth_lvl + 1);
             }
-            PatKind::Variant { adt_def, substs, variant_index, subpatterns } => {
+            PatKind::Variant { adt_def, args, variant_index, subpatterns } => {
                 print_indented!(self, "Variant {", depth_lvl + 1);
                 print_indented!(self, "adt_def: ", depth_lvl + 2);
                 self.print_adt_def(*adt_def, depth_lvl + 3);
-                print_indented!(self, format!("substs: {:?}", substs), depth_lvl + 2);
+                print_indented!(self, format!("args: {:?}", args), depth_lvl + 2);
                 print_indented!(self, format!("variant_index: {:?}", variant_index), depth_lvl + 2);
 
                 if subpatterns.len() > 0 {
@@ -784,11 +784,11 @@ impl<'a, 'tcx> ThirPrinter<'a, 'tcx> {
     }
 
     fn print_closure_expr(&mut self, expr: &ClosureExpr<'tcx>, depth_lvl: usize) {
-        let ClosureExpr { closure_id, substs, upvars, movability, fake_reads } = expr;
+        let ClosureExpr { closure_id, args, upvars, movability, fake_reads } = expr;
 
         print_indented!(self, "ClosureExpr {", depth_lvl);
         print_indented!(self, format!("closure_id: {:?}", closure_id), depth_lvl + 1);
-        print_indented!(self, format!("substs: {:?}", substs), depth_lvl + 1);
+        print_indented!(self, format!("args: {:?}", args), depth_lvl + 1);
 
         if upvars.len() > 0 {
             print_indented!(self, "upvars: [", depth_lvl + 1);
diff --git a/compiler/rustc_mir_build/src/thir/util.rs b/compiler/rustc_mir_build/src/thir/util.rs
index c58ed1ac0b8..9106b4d33fc 100644
--- a/compiler/rustc_mir_build/src/thir/util.rs
+++ b/compiler/rustc_mir_build/src/thir/util.rs
@@ -9,7 +9,7 @@ pub(crate) trait UserAnnotatedTyHelpers<'tcx> {
     /// Looks up the type associated with this hir-id and applies the
     /// user-given substitutions; the hir-id must map to a suitable
     /// type.
-    fn user_substs_applied_to_ty_of_hir_id(
+    fn user_args_applied_to_ty_of_hir_id(
         &self,
         hir_id: hir::HirId,
     ) -> Option<CanonicalUserType<'tcx>> {
diff --git a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs
index 0540a5e943b..1d7d905c937 100644
--- a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs
+++ b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs
@@ -4,8 +4,8 @@ use rustc_index::Idx;
 use rustc_middle::mir::patch::MirPatch;
 use rustc_middle::mir::*;
 use rustc_middle::traits::Reveal;
-use rustc_middle::ty::subst::SubstsRef;
 use rustc_middle::ty::util::IntTypeExt;
+use rustc_middle::ty::GenericArgsRef;
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_target::abi::{FieldIdx, VariantIdx, FIRST_VARIANT};
 use std::{fmt, iter};
@@ -263,7 +263,7 @@ where
         base_place: Place<'tcx>,
         variant_path: D::Path,
         variant: &'tcx ty::VariantDef,
-        substs: SubstsRef<'tcx>,
+        args: GenericArgsRef<'tcx>,
     ) -> Vec<(Place<'tcx>, Option<D::Path>)> {
         variant
             .fields
@@ -276,7 +276,7 @@ where
 
                 assert_eq!(self.elaborator.param_env().reveal(), Reveal::All);
                 let field_ty =
-                    tcx.normalize_erasing_regions(self.elaborator.param_env(), f.ty(tcx, substs));
+                    tcx.normalize_erasing_regions(self.elaborator.param_env(), f.ty(tcx, args));
 
                 (tcx.mk_place_field(base_place, field, field_ty), subpath)
             })
@@ -414,16 +414,16 @@ where
     fn open_drop_for_box_contents(
         &mut self,
         adt: ty::AdtDef<'tcx>,
-        substs: SubstsRef<'tcx>,
+        args: GenericArgsRef<'tcx>,
         succ: BasicBlock,
         unwind: Unwind,
     ) -> BasicBlock {
         // drop glue is sent straight to codegen
         // box cannot be directly dereferenced
-        let unique_ty = adt.non_enum_variant().fields[FieldIdx::new(0)].ty(self.tcx(), substs);
+        let unique_ty = adt.non_enum_variant().fields[FieldIdx::new(0)].ty(self.tcx(), args);
         let unique_variant = unique_ty.ty_adt_def().unwrap().non_enum_variant();
-        let nonnull_ty = unique_variant.fields[FieldIdx::from_u32(0)].ty(self.tcx(), substs);
-        let ptr_ty = Ty::new_imm_ptr(self.tcx(), substs[0].expect_ty());
+        let nonnull_ty = unique_variant.fields[FieldIdx::from_u32(0)].ty(self.tcx(), args);
+        let ptr_ty = Ty::new_imm_ptr(self.tcx(), args[0].expect_ty());
 
         let unique_place = self.tcx().mk_place_field(self.place, FieldIdx::new(0), unique_ty);
         let nonnull_place = self.tcx().mk_place_field(unique_place, FieldIdx::new(0), nonnull_ty);
@@ -436,7 +436,11 @@ where
     }
 
     #[instrument(level = "debug", ret)]
-    fn open_drop_for_adt(&mut self, adt: ty::AdtDef<'tcx>, substs: SubstsRef<'tcx>) -> BasicBlock {
+    fn open_drop_for_adt(
+        &mut self,
+        adt: ty::AdtDef<'tcx>,
+        args: GenericArgsRef<'tcx>,
+    ) -> BasicBlock {
         if adt.variants().is_empty() {
             return self.elaborator.patch().new_block(BasicBlockData {
                 statements: vec![],
@@ -453,7 +457,7 @@ where
         let contents_drop = if skip_contents {
             (self.succ, self.unwind)
         } else {
-            self.open_drop_for_adt_contents(adt, substs)
+            self.open_drop_for_adt_contents(adt, args)
         };
 
         if adt.is_box() {
@@ -463,7 +467,7 @@ where
                 .1
                 .map(|unwind| self.destructor_call_block((unwind, Unwind::InCleanup)));
 
-            self.open_drop_for_box_contents(adt, substs, succ, unwind)
+            self.open_drop_for_box_contents(adt, args, succ, unwind)
         } else if adt.has_dtor(self.tcx()) {
             self.destructor_call_block(contents_drop)
         } else {
@@ -474,7 +478,7 @@ where
     fn open_drop_for_adt_contents(
         &mut self,
         adt: ty::AdtDef<'tcx>,
-        substs: SubstsRef<'tcx>,
+        args: GenericArgsRef<'tcx>,
     ) -> (BasicBlock, Unwind) {
         let (succ, unwind) = self.drop_ladder_bottom();
         if !adt.is_enum() {
@@ -482,18 +486,18 @@ where
                 self.place,
                 self.path,
                 &adt.variant(FIRST_VARIANT),
-                substs,
+                args,
             );
             self.drop_ladder(fields, succ, unwind)
         } else {
-            self.open_drop_for_multivariant(adt, substs, succ, unwind)
+            self.open_drop_for_multivariant(adt, args, succ, unwind)
         }
     }
 
     fn open_drop_for_multivariant(
         &mut self,
         adt: ty::AdtDef<'tcx>,
-        substs: SubstsRef<'tcx>,
+        args: GenericArgsRef<'tcx>,
         succ: BasicBlock,
         unwind: Unwind,
     ) -> (BasicBlock, Unwind) {
@@ -515,7 +519,7 @@ where
                     self.place,
                     ProjectionElem::Downcast(Some(variant.name), variant_index),
                 );
-                let fields = self.move_paths_for_fields(base_place, variant_path, &variant, substs);
+                let fields = self.move_paths_for_fields(base_place, variant_path, &variant, args);
                 values.push(discr.val);
                 if let Unwind::To(unwind) = unwind {
                     // We can't use the half-ladder from the original
@@ -550,7 +554,7 @@ where
                 let have_field_with_drop_glue = variant
                     .fields
                     .iter()
-                    .any(|field| field.ty(tcx, substs).needs_drop(tcx, param_env));
+                    .any(|field| field.ty(tcx, args).needs_drop(tcx, param_env));
                 if have_field_with_drop_glue {
                     have_otherwise_with_drop_glue = true;
                 }
@@ -856,8 +860,8 @@ where
     fn open_drop(&mut self) -> BasicBlock {
         let ty = self.place_ty(self.place);
         match ty.kind() {
-            ty::Closure(_, substs) => {
-                let tys: Vec<_> = substs.as_closure().upvar_tys().collect();
+            ty::Closure(_, args) => {
+                let tys: Vec<_> = args.as_closure().upvar_tys().collect();
                 self.open_drop_for_tuple(&tys)
             }
             // Note that `elaborate_drops` only drops the upvars of a generator,
@@ -866,12 +870,12 @@ where
             // This should only happen for the self argument on the resume function.
             // It effectively only contains upvars until the generator transformation runs.
             // See librustc_body/transform/generator.rs for more details.
-            ty::Generator(_, substs, _) => {
-                let tys: Vec<_> = substs.as_generator().upvar_tys().collect();
+            ty::Generator(_, args, _) => {
+                let tys: Vec<_> = args.as_generator().upvar_tys().collect();
                 self.open_drop_for_tuple(&tys)
             }
             ty::Tuple(fields) => self.open_drop_for_tuple(fields),
-            ty::Adt(def, substs) => self.open_drop_for_adt(*def, substs),
+            ty::Adt(def, args) => self.open_drop_for_adt(*def, args),
             ty::Dynamic(..) => self.complete_drop(self.succ, self.unwind),
             ty::Array(ety, size) => {
                 let size = size.try_eval_target_usize(self.tcx(), self.elaborator.param_env());
diff --git a/compiler/rustc_mir_dataflow/src/impls/mod.rs b/compiler/rustc_mir_dataflow/src/impls/mod.rs
index cb74bea724a..633b99a332b 100644
--- a/compiler/rustc_mir_dataflow/src/impls/mod.rs
+++ b/compiler/rustc_mir_dataflow/src/impls/mod.rs
@@ -321,7 +321,9 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeInitializedPlaces<'_, 'tcx> {
 
         // Mark all places as "maybe init" if they are mutably borrowed. See #90752.
         for_each_mut_borrow(statement, location, |place| {
-            let LookupResult::Exact(mpi) = self.move_data().rev_lookup.find(place.as_ref()) else { return };
+            let LookupResult::Exact(mpi) = self.move_data().rev_lookup.find(place.as_ref()) else {
+                return;
+            };
             on_all_children_bits(self.tcx, self.body, self.move_data(), mpi, |child| {
                 trans.gen(child);
             })
@@ -343,7 +345,9 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeInitializedPlaces<'_, 'tcx> {
         }
 
         for_each_mut_borrow(terminator, location, |place| {
-            let LookupResult::Exact(mpi) = self.move_data().rev_lookup.find(place.as_ref()) else { return };
+            let LookupResult::Exact(mpi) = self.move_data().rev_lookup.find(place.as_ref()) else {
+                return;
+            };
             on_all_children_bits(self.tcx, self.body, self.move_data(), mpi, |child| {
                 trans.gen(child);
             })
diff --git a/compiler/rustc_mir_dataflow/src/rustc_peek.rs b/compiler/rustc_mir_dataflow/src/rustc_peek.rs
index 156231c3ae1..775c522b476 100644
--- a/compiler/rustc_mir_dataflow/src/rustc_peek.rs
+++ b/compiler/rustc_mir_dataflow/src/rustc_peek.rs
@@ -190,14 +190,14 @@ impl PeekCall {
         if let mir::TerminatorKind::Call { func: Operand::Constant(func), args, .. } =
             &terminator.kind
         {
-            if let ty::FnDef(def_id, substs) = *func.literal.ty().kind() {
+            if let ty::FnDef(def_id, fn_args) = *func.literal.ty().kind() {
                 let name = tcx.item_name(def_id);
                 if !tcx.is_intrinsic(def_id) || name != sym::rustc_peek {
                     return None;
                 }
 
-                assert_eq!(args.len(), 1);
-                let kind = PeekCallKind::from_arg_ty(substs.type_at(0));
+                assert_eq!(fn_args.len(), 1);
+                let kind = PeekCallKind::from_arg_ty(fn_args.type_at(0));
                 let arg = match &args[0] {
                     Operand::Copy(place) | Operand::Move(place) => {
                         if let Some(local) = place.as_local() {
diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs
index 5693e5a4a71..fd6b1dc5c07 100644
--- a/compiler/rustc_mir_dataflow/src/value_analysis.rs
+++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs
@@ -999,14 +999,14 @@ pub fn iter_fields<'tcx>(
                 f(None, field.into(), ty);
             }
         }
-        ty::Adt(def, substs) => {
+        ty::Adt(def, args) => {
             if def.is_union() {
                 return;
             }
             for (v_index, v_def) in def.variants().iter_enumerated() {
                 let variant = if def.is_struct() { None } else { Some(v_index) };
                 for (f_index, f_def) in v_def.fields.iter().enumerate() {
-                    let field_ty = f_def.ty(tcx, substs);
+                    let field_ty = f_def.ty(tcx, args);
                     let field_ty = tcx
                         .try_normalize_erasing_regions(param_env, field_ty)
                         .unwrap_or_else(|_| tcx.erase_regions(field_ty));
@@ -1014,8 +1014,8 @@ pub fn iter_fields<'tcx>(
                 }
             }
         }
-        ty::Closure(_, substs) => {
-            iter_fields(substs.as_closure().tupled_upvars_ty(), tcx, param_env, f);
+        ty::Closure(_, args) => {
+            iter_fields(args.as_closure().tupled_upvars_ty(), tcx, param_env, f);
         }
         _ => (),
     }
diff --git a/compiler/rustc_mir_transform/src/check_unsafety.rs b/compiler/rustc_mir_transform/src/check_unsafety.rs
index 70812761e88..58e9786ec1a 100644
--- a/compiler/rustc_mir_transform/src/check_unsafety.rs
+++ b/compiler/rustc_mir_transform/src/check_unsafety.rs
@@ -1,4 +1,4 @@
-use rustc_data_structures::unord::{UnordItems, UnordSet};
+use rustc_data_structures::unord::{ExtendUnord, UnordItems, UnordSet};
 use rustc_hir as hir;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{DefId, LocalDefId};
diff --git a/compiler/rustc_mir_transform/src/const_prop.rs b/compiler/rustc_mir_transform/src/const_prop.rs
index f3ac679f97b..6437a227d47 100644
--- a/compiler/rustc_mir_transform/src/const_prop.rs
+++ b/compiler/rustc_mir_transform/src/const_prop.rs
@@ -14,7 +14,7 @@ use rustc_middle::mir::visit::{
 };
 use rustc_middle::mir::*;
 use rustc_middle::ty::layout::{LayoutError, LayoutOf, LayoutOfHelpers, TyAndLayout};
-use rustc_middle::ty::InternalSubsts;
+use rustc_middle::ty::GenericArgs;
 use rustc_middle::ty::{self, ConstKind, Instance, ParamEnv, Ty, TyCtxt, TypeVisitableExt};
 use rustc_span::{def_id::DefId, Span, DUMMY_SP};
 use rustc_target::abi::{self, Align, HasDataLayout, Size, TargetDataLayout};
@@ -87,7 +87,7 @@ impl<'tcx> MirPass<'tcx> for ConstProp {
             return;
         }
 
-        let is_generator = tcx.type_of(def_id.to_def_id()).subst_identity().is_generator();
+        let is_generator = tcx.type_of(def_id.to_def_id()).instantiate_identity().is_generator();
         // FIXME(welseywiser) const prop doesn't work on generators because of query cycles
         // computing their layout.
         if is_generator {
@@ -338,7 +338,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
         tcx: TyCtxt<'tcx>,
     ) -> ConstPropagator<'mir, 'tcx> {
         let def_id = body.source.def_id();
-        let substs = &InternalSubsts::identity_for_item(tcx, def_id);
+        let args = &GenericArgs::identity_for_item(tcx, def_id);
         let param_env = tcx.param_env_reveal_all_normalized(def_id);
 
         let can_const_prop = CanConstProp::check(tcx, param_env, body);
@@ -350,7 +350,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
         );
 
         let ret_layout = ecx
-            .layout_of(body.bound_return_ty().subst(tcx, substs))
+            .layout_of(body.bound_return_ty().instantiate(tcx, args))
             .ok()
             // Don't bother allocating memory for large values.
             // I don't know how return types can seem to be unsized but this happens in the
@@ -366,7 +366,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
             .into();
 
         ecx.push_stack_frame(
-            Instance::new(def_id, substs),
+            Instance::new(def_id, args),
             dummy_body,
             &ret,
             StackPopCleanup::Root { cleanup: false },
diff --git a/compiler/rustc_mir_transform/src/const_prop_lint.rs b/compiler/rustc_mir_transform/src/const_prop_lint.rs
index 759650fe4db..01b945afda6 100644
--- a/compiler/rustc_mir_transform/src/const_prop_lint.rs
+++ b/compiler/rustc_mir_transform/src/const_prop_lint.rs
@@ -16,7 +16,7 @@ use rustc_index::bit_set::BitSet;
 use rustc_middle::mir::visit::Visitor;
 use rustc_middle::mir::*;
 use rustc_middle::ty::layout::{LayoutError, LayoutOf, LayoutOfHelpers, TyAndLayout};
-use rustc_middle::ty::InternalSubsts;
+use rustc_middle::ty::GenericArgs;
 use rustc_middle::ty::{
     self, ConstInt, Instance, ParamEnv, ScalarInt, Ty, TyCtxt, TypeVisitableExt,
 };
@@ -55,7 +55,7 @@ impl<'tcx> MirLint<'tcx> for ConstProp {
             return;
         }
 
-        let is_generator = tcx.type_of(def_id.to_def_id()).subst_identity().is_generator();
+        let is_generator = tcx.type_of(def_id.to_def_id()).instantiate_identity().is_generator();
         // FIXME(welseywiser) const prop doesn't work on generators because of query cycles
         // computing their layout.
         if is_generator {
@@ -171,7 +171,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
         tcx: TyCtxt<'tcx>,
     ) -> ConstPropagator<'mir, 'tcx> {
         let def_id = body.source.def_id();
-        let substs = &InternalSubsts::identity_for_item(tcx, def_id);
+        let args = &GenericArgs::identity_for_item(tcx, def_id);
         let param_env = tcx.param_env_reveal_all_normalized(def_id);
 
         let can_const_prop = CanConstProp::check(tcx, param_env, body);
@@ -183,7 +183,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
         );
 
         let ret_layout = ecx
-            .layout_of(body.bound_return_ty().subst(tcx, substs))
+            .layout_of(body.bound_return_ty().instantiate(tcx, args))
             .ok()
             // Don't bother allocating memory for large values.
             // I don't know how return types can seem to be unsized but this happens in the
@@ -199,7 +199,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
             .into();
 
         ecx.push_stack_frame(
-            Instance::new(def_id, substs),
+            Instance::new(def_id, args),
             dummy_body,
             &ret,
             StackPopCleanup::Root { cleanup: false },
diff --git a/compiler/rustc_mir_transform/src/copy_prop.rs b/compiler/rustc_mir_transform/src/copy_prop.rs
index 3df459dfa79..47d9f52bfb5 100644
--- a/compiler/rustc_mir_transform/src/copy_prop.rs
+++ b/compiler/rustc_mir_transform/src/copy_prop.rs
@@ -76,9 +76,11 @@ fn fully_moved_locals(ssa: &SsaLocals, body: &Body<'_>) -> BitSet<Local> {
     let mut fully_moved = BitSet::new_filled(body.local_decls.len());
 
     for (_, rvalue, _) in ssa.assignments(body) {
-        let (Rvalue::Use(Operand::Copy(place) | Operand::Move(place)) | Rvalue::CopyForDeref(place))
-            = rvalue
-        else { continue };
+        let (Rvalue::Use(Operand::Copy(place) | Operand::Move(place))
+        | Rvalue::CopyForDeref(place)) = rvalue
+        else {
+            continue;
+        };
 
         let Some(rhs) = place.as_local() else { continue };
         if !ssa.is_ssa(rhs) {
diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs
index 5b6cbb5577c..7d7588fcaec 100644
--- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs
+++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs
@@ -281,7 +281,7 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'_, 'tcx> {
 
             let FlatSet::Elem(choice) = discr_value else {
                 // Do nothing if we don't know which branch will be taken.
-                return
+                return;
             };
 
             if target.value.map(|n| n == choice).unwrap_or(!handled) {
diff --git a/compiler/rustc_mir_transform/src/deduce_param_attrs.rs b/compiler/rustc_mir_transform/src/deduce_param_attrs.rs
index a133c9d4782..60ca3dfb2da 100644
--- a/compiler/rustc_mir_transform/src/deduce_param_attrs.rs
+++ b/compiler/rustc_mir_transform/src/deduce_param_attrs.rs
@@ -166,7 +166,7 @@ pub fn deduced_param_attrs<'tcx>(
 
     // 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).subst_identity();
+    let fn_ty = tcx.type_of(def_id).instantiate_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 a31551cf619..b73b72c3192 100644
--- a/compiler/rustc_mir_transform/src/dest_prop.rs
+++ b/compiler/rustc_mir_transform/src/dest_prop.rs
@@ -218,9 +218,9 @@ impl<'tcx> MirPass<'tcx> for DestinationPropagation {
                 if merged_locals.contains(*src) {
                     continue;
                 }
-                let Some(dest) =
-                    candidates.iter().find(|dest| !merged_locals.contains(**dest)) else {
-                        continue;
+                let Some(dest) = candidates.iter().find(|dest| !merged_locals.contains(**dest))
+                else {
+                    continue;
                 };
                 if !tcx.consider_optimizing(|| {
                     format!("{} round {}", tcx.def_path_str(def_id), round_count)
@@ -601,9 +601,7 @@ impl WriteInfo {
         rhs: &Operand<'tcx>,
         body: &Body<'tcx>,
     ) {
-        let Some(rhs) = rhs.place() else {
-            return
-        };
+        let Some(rhs) = rhs.place() else { return };
         if let Some(pair) = places_to_candidate_pair(lhs, rhs, body) {
             self.skip_pair = Some(pair);
         }
diff --git a/compiler/rustc_mir_transform/src/early_otherwise_branch.rs b/compiler/rustc_mir_transform/src/early_otherwise_branch.rs
index 8a7b027ddda..319fb4eaf3e 100644
--- a/compiler/rustc_mir_transform/src/early_otherwise_branch.rs
+++ b/compiler/rustc_mir_transform/src/early_otherwise_branch.rs
@@ -107,9 +107,7 @@ impl<'tcx> MirPass<'tcx> for EarlyOtherwiseBranch {
         for i in 0..body.basic_blocks.len() {
             let bbs = &*body.basic_blocks;
             let parent = BasicBlock::from_usize(i);
-            let Some(opt_data) = evaluate_candidate(tcx, body, parent) else {
-                continue
-            };
+            let Some(opt_data) = evaluate_candidate(tcx, body, parent) else { continue };
 
             if !tcx.consider_optimizing(|| format!("EarlyOtherwiseBranch {:?}", &opt_data)) {
                 break;
@@ -119,10 +117,9 @@ impl<'tcx> MirPass<'tcx> for EarlyOtherwiseBranch {
 
             should_cleanup = true;
 
-            let TerminatorKind::SwitchInt {
-                discr: parent_op,
-                targets: parent_targets
-            } = &bbs[parent].terminator().kind else {
+            let TerminatorKind::SwitchInt { discr: parent_op, targets: parent_targets } =
+                &bbs[parent].terminator().kind
+            else {
                 unreachable!()
             };
             // Always correct since we can only switch on `Copy` types
@@ -168,7 +165,8 @@ impl<'tcx> MirPass<'tcx> for EarlyOtherwiseBranch {
             );
 
             let eq_new_targets = parent_targets.iter().map(|(value, child)| {
-                let TerminatorKind::SwitchInt{ targets, .. } = &bbs[child].terminator().kind else {
+                let TerminatorKind::SwitchInt { targets, .. } = &bbs[child].terminator().kind
+                else {
                     unreachable!()
                 };
                 (value, targets.target_for_value(value))
@@ -311,11 +309,9 @@ fn evaluate_candidate<'tcx>(
     parent: BasicBlock,
 ) -> Option<OptimizationData<'tcx>> {
     let bbs = &body.basic_blocks;
-    let TerminatorKind::SwitchInt {
-        targets,
-        discr: parent_discr,
-    } = &bbs[parent].terminator().kind else {
-        return None
+    let TerminatorKind::SwitchInt { targets, discr: parent_discr } = &bbs[parent].terminator().kind
+    else {
+        return None;
     };
     let parent_ty = parent_discr.ty(body.local_decls(), tcx);
     let parent_dest = {
@@ -332,18 +328,16 @@ fn evaluate_candidate<'tcx>(
     };
     let (_, child) = targets.iter().next()?;
     let child_terminator = &bbs[child].terminator();
-    let TerminatorKind::SwitchInt {
-        targets: child_targets,
-        discr: child_discr,
-    } = &child_terminator.kind else {
-        return None
+    let TerminatorKind::SwitchInt { targets: child_targets, discr: child_discr } =
+        &child_terminator.kind
+    else {
+        return None;
     };
     let child_ty = child_discr.ty(body.local_decls(), tcx);
     if child_ty != parent_ty {
         return None;
     }
-    let Some(StatementKind::Assign(boxed))
-        = &bbs[child].statements.first().map(|x| &x.kind) else {
+    let Some(StatementKind::Assign(boxed)) = &bbs[child].statements.first().map(|x| &x.kind) else {
         return None;
     };
     let (_, Rvalue::Discriminant(child_place)) = &**boxed else {
@@ -383,12 +377,8 @@ fn verify_candidate_branch<'tcx>(
         return false;
     }
     // ...assign the discriminant of `place` in that statement
-    let StatementKind::Assign(boxed) = &branch.statements[0].kind else {
-        return false
-    };
-    let (discr_place, Rvalue::Discriminant(from_place)) = &**boxed else {
-        return false
-    };
+    let StatementKind::Assign(boxed) = &branch.statements[0].kind else { return false };
+    let (discr_place, Rvalue::Discriminant(from_place)) = &**boxed else { return false };
     if *from_place != place {
         return false;
     }
@@ -397,8 +387,9 @@ fn verify_candidate_branch<'tcx>(
         return false;
     }
     // ...terminate on a `SwitchInt` that invalidates that local
-    let TerminatorKind::SwitchInt{ discr: switch_op, targets, .. } = &branch.terminator().kind else {
-        return false
+    let TerminatorKind::SwitchInt { discr: switch_op, targets, .. } = &branch.terminator().kind
+    else {
+        return false;
     };
     if *switch_op != Operand::Move(*discr_place) {
         return false;
diff --git a/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs b/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs
index cc0d7d51b60..e51f771e00d 100644
--- a/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs
+++ b/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs
@@ -18,9 +18,9 @@ pub fn build_ptr_tys<'tcx>(
     unique_did: DefId,
     nonnull_did: DefId,
 ) -> (Ty<'tcx>, Ty<'tcx>, Ty<'tcx>) {
-    let substs = tcx.mk_substs(&[pointee.into()]);
-    let unique_ty = tcx.type_of(unique_did).subst(tcx, substs);
-    let nonnull_ty = tcx.type_of(nonnull_did).subst(tcx, substs);
+    let args = tcx.mk_args(&[pointee.into()]);
+    let unique_ty = tcx.type_of(unique_did).instantiate(tcx, args);
+    let nonnull_ty = tcx.type_of(nonnull_did).instantiate(tcx, args);
     let ptr_ty = Ty::new_imm_ptr(tcx, pointee);
 
     (unique_ty, nonnull_ty, ptr_ty)
@@ -95,7 +95,8 @@ impl<'tcx> MirPass<'tcx> for ElaborateBoxDerefs {
             let unique_did =
                 tcx.adt_def(def_id).non_enum_variant().fields[FieldIdx::from_u32(0)].did;
 
-            let Some(nonnull_def) = tcx.type_of(unique_did).subst_identity().ty_adt_def() else {
+            let Some(nonnull_def) = tcx.type_of(unique_did).instantiate_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/function_item_references.rs b/compiler/rustc_mir_transform/src/function_item_references.rs
index 0b41e57be3b..fdf6ab33c82 100644
--- a/compiler/rustc_mir_transform/src/function_item_references.rs
+++ b/compiler/rustc_mir_transform/src/function_item_references.rs
@@ -2,7 +2,7 @@ use itertools::Itertools;
 use rustc_hir::def_id::DefId;
 use rustc_middle::mir::visit::Visitor;
 use rustc_middle::mir::*;
-use rustc_middle::ty::{self, EarlyBinder, SubstsRef, Ty, TyCtxt};
+use rustc_middle::ty::{self, EarlyBinder, GenericArgsRef, Ty, TyCtxt};
 use rustc_session::lint::builtin::FUNCTION_ITEM_REFERENCES;
 use rustc_span::{symbol::sym, Span};
 use rustc_target::spec::abi::Abi;
@@ -40,20 +40,19 @@ impl<'tcx> Visitor<'tcx> for FunctionItemRefChecker<'_, 'tcx> {
         {
             let source_info = *self.body.source_info(location);
             let func_ty = func.ty(self.body, self.tcx);
-            if let ty::FnDef(def_id, substs_ref) = *func_ty.kind() {
+            if let ty::FnDef(def_id, args_ref) = *func_ty.kind() {
                 // Handle calls to `transmute`
                 if self.tcx.is_diagnostic_item(sym::transmute, def_id) {
                     let arg_ty = args[0].ty(self.body, self.tcx);
                     for inner_ty in arg_ty.walk().filter_map(|arg| arg.as_type()) {
-                        if let Some((fn_id, fn_substs)) =
-                            FunctionItemRefChecker::is_fn_ref(inner_ty)
+                        if let Some((fn_id, fn_args)) = FunctionItemRefChecker::is_fn_ref(inner_ty)
                         {
                             let span = self.nth_arg_span(&args, 0);
-                            self.emit_lint(fn_id, fn_substs, source_info, span);
+                            self.emit_lint(fn_id, fn_args, source_info, span);
                         }
                     }
                 } else {
-                    self.check_bound_args(def_id, substs_ref, &args, source_info);
+                    self.check_bound_args(def_id, args_ref, &args, source_info);
                 }
             }
         }
@@ -63,11 +62,11 @@ impl<'tcx> Visitor<'tcx> for FunctionItemRefChecker<'_, 'tcx> {
 
 impl<'tcx> FunctionItemRefChecker<'_, 'tcx> {
     /// Emits a lint for function reference arguments bound by `fmt::Pointer` in calls to the
-    /// function defined by `def_id` with the substitutions `substs_ref`.
+    /// function defined by `def_id` with the substitutions `args_ref`.
     fn check_bound_args(
         &self,
         def_id: DefId,
-        substs_ref: SubstsRef<'tcx>,
+        args_ref: GenericArgsRef<'tcx>,
         args: &[Operand<'tcx>],
         source_info: SourceInfo,
     ) {
@@ -76,15 +75,17 @@ impl<'tcx> FunctionItemRefChecker<'_, 'tcx> {
         for bound in bounds {
             if let Some(bound_ty) = self.is_pointer_trait(bound) {
                 // Get the argument types as they appear in the function signature.
-                let arg_defs = self.tcx.fn_sig(def_id).subst_identity().skip_binder().inputs();
+                let arg_defs =
+                    self.tcx.fn_sig(def_id).instantiate_identity().skip_binder().inputs();
                 for (arg_num, arg_def) in arg_defs.iter().enumerate() {
                     // For all types reachable from the argument type in the fn sig
                     for inner_ty in arg_def.walk().filter_map(|arg| arg.as_type()) {
                         // If the inner type matches the type bound by `Pointer`
                         if inner_ty == bound_ty {
                             // Do a substitution using the parameters from the callsite
-                            let subst_ty = EarlyBinder::bind(inner_ty).subst(self.tcx, substs_ref);
-                            if let Some((fn_id, fn_substs)) =
+                            let subst_ty =
+                                EarlyBinder::bind(inner_ty).instantiate(self.tcx, args_ref);
+                            if let Some((fn_id, fn_args)) =
                                 FunctionItemRefChecker::is_fn_ref(subst_ty)
                             {
                                 let mut span = self.nth_arg_span(args, arg_num);
@@ -94,7 +95,7 @@ impl<'tcx> FunctionItemRefChecker<'_, 'tcx> {
                                     let callsite_ctxt = span.source_callsite().ctxt();
                                     span = span.with_ctxt(callsite_ctxt);
                                 }
-                                self.emit_lint(fn_id, fn_substs, source_info, span);
+                                self.emit_lint(fn_id, fn_args, source_info, span);
                             }
                         }
                     }
@@ -115,8 +116,8 @@ impl<'tcx> FunctionItemRefChecker<'_, 'tcx> {
     }
 
     /// If a type is a reference or raw pointer to the anonymous type of a function definition,
-    /// returns that function's `DefId` and `SubstsRef`.
-    fn is_fn_ref(ty: Ty<'tcx>) -> Option<(DefId, SubstsRef<'tcx>)> {
+    /// returns that function's `DefId` and `GenericArgsRef`.
+    fn is_fn_ref(ty: Ty<'tcx>) -> Option<(DefId, GenericArgsRef<'tcx>)> {
         let referent_ty = match ty.kind() {
             ty::Ref(_, referent_ty, _) => Some(referent_ty),
             ty::RawPtr(ty_and_mut) => Some(&ty_and_mut.ty),
@@ -124,8 +125,8 @@ impl<'tcx> FunctionItemRefChecker<'_, 'tcx> {
         };
         referent_ty
             .map(|ref_ty| {
-                if let ty::FnDef(def_id, substs_ref) = *ref_ty.kind() {
-                    Some((def_id, substs_ref))
+                if let ty::FnDef(def_id, args_ref) = *ref_ty.kind() {
+                    Some((def_id, args_ref))
                 } else {
                     None
                 }
@@ -145,7 +146,7 @@ impl<'tcx> FunctionItemRefChecker<'_, 'tcx> {
     fn emit_lint(
         &self,
         fn_id: DefId,
-        fn_substs: SubstsRef<'tcx>,
+        fn_args: GenericArgsRef<'tcx>,
         source_info: SourceInfo,
         span: Span,
     ) {
@@ -155,7 +156,7 @@ impl<'tcx> FunctionItemRefChecker<'_, 'tcx> {
             .assert_crate_local()
             .lint_root;
         // FIXME: use existing printing routines to print the function signature
-        let fn_sig = self.tcx.fn_sig(fn_id).subst(self.tcx, fn_substs);
+        let fn_sig = self.tcx.fn_sig(fn_id).instantiate(self.tcx, fn_args);
         let unsafety = fn_sig.unsafety().prefix_str();
         let abi = match fn_sig.abi() {
             Abi::Rust => String::from(""),
@@ -167,8 +168,8 @@ impl<'tcx> FunctionItemRefChecker<'_, 'tcx> {
             }
         };
         let ident = self.tcx.item_name(fn_id).to_ident_string();
-        let ty_params = fn_substs.types().map(|ty| format!("{}", ty));
-        let const_params = fn_substs.consts().map(|c| format!("{}", c));
+        let ty_params = fn_args.types().map(|ty| format!("{}", ty));
+        let const_params = fn_args.consts().map(|c| format!("{}", c));
         let params = ty_params.chain(const_params).join(", ");
         let num_args = fn_sig.inputs().map_bound(|inputs| inputs.len()).skip_binder();
         let variadic = if fn_sig.c_variadic() { ", ..." } else { "" };
diff --git a/compiler/rustc_mir_transform/src/generator.rs b/compiler/rustc_mir_transform/src/generator.rs
index 264bc61f1b3..eaeaff69cf3 100644
--- a/compiler/rustc_mir_transform/src/generator.rs
+++ b/compiler/rustc_mir_transform/src/generator.rs
@@ -65,7 +65,7 @@ use rustc_middle::mir::dump_mir;
 use rustc_middle::mir::visit::{MutVisitor, PlaceContext, Visitor};
 use rustc_middle::mir::*;
 use rustc_middle::ty::{self, AdtDef, Ty, TyCtxt};
-use rustc_middle::ty::{GeneratorSubsts, SubstsRef};
+use rustc_middle::ty::{GeneratorArgs, GenericArgsRef};
 use rustc_mir_dataflow::impls::{
     MaybeBorrowedLocals, MaybeLiveLocals, MaybeRequiresStorage, MaybeStorageLive,
 };
@@ -194,11 +194,11 @@ fn replace_base<'tcx>(place: &mut Place<'tcx>, new_base: Place<'tcx>, tcx: TyCtx
 const SELF_ARG: Local = Local::from_u32(1);
 
 /// Generator has not been resumed yet.
-const UNRESUMED: usize = GeneratorSubsts::UNRESUMED;
+const UNRESUMED: usize = GeneratorArgs::UNRESUMED;
 /// Generator has returned / is completed.
-const RETURNED: usize = GeneratorSubsts::RETURNED;
+const RETURNED: usize = GeneratorArgs::RETURNED;
 /// Generator has panicked and is poisoned.
-const POISONED: usize = GeneratorSubsts::POISONED;
+const POISONED: usize = GeneratorArgs::POISONED;
 
 /// Number of variants to reserve in generator state. Corresponds to
 /// `UNRESUMED` (beginning of a generator) and `RETURNED`/`POISONED`
@@ -223,7 +223,7 @@ struct TransformVisitor<'tcx> {
     tcx: TyCtxt<'tcx>,
     is_async_kind: bool,
     state_adt_ref: AdtDef<'tcx>,
-    state_substs: SubstsRef<'tcx>,
+    state_args: GenericArgsRef<'tcx>,
 
     // The type of the discriminant in the generator struct
     discr_ty: Ty<'tcx>,
@@ -265,7 +265,7 @@ impl<'tcx> TransformVisitor<'tcx> {
             (false, true) => 1,  // Poll::Pending
         });
 
-        let kind = AggregateKind::Adt(self.state_adt_ref.did(), idx, self.state_substs, None, None);
+        let kind = AggregateKind::Adt(self.state_adt_ref.did(), idx, self.state_args, None, None);
 
         // `Poll::Pending`
         if self.is_async_kind && idx == VariantIdx::new(1) {
@@ -431,8 +431,8 @@ fn make_generator_state_argument_pinned<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body
 
     let pin_did = tcx.require_lang_item(LangItem::Pin, Some(body.span));
     let pin_adt_ref = tcx.adt_def(pin_did);
-    let substs = tcx.mk_substs(&[ref_gen_ty.into()]);
-    let pin_ref_gen_ty = Ty::new_adt(tcx, pin_adt_ref, substs);
+    let args = tcx.mk_args(&[ref_gen_ty.into()]);
+    let pin_ref_gen_ty = Ty::new_adt(tcx, pin_adt_ref, args);
 
     // Replace the by ref generator argument
     body.local_decls.raw[1].ty = pin_ref_gen_ty;
@@ -1431,7 +1431,7 @@ pub(crate) fn mir_generator_witnesses<'tcx>(
     // The first argument is the generator type passed by value
     let gen_ty = body.local_decls[ty::CAPTURE_STRUCT_LOCAL].ty;
 
-    // Get the interior types and substs which typeck computed
+    // Get the interior types and args which typeck computed
     let movable = match *gen_ty.kind() {
         ty::Generator(_, _, movability) => movability == hir::Movability::Movable,
         ty::Error(_) => return None,
@@ -1465,14 +1465,14 @@ impl<'tcx> MirPass<'tcx> for StateTransform {
         // The first argument is the generator type passed by value
         let gen_ty = body.local_decls.raw[1].ty;
 
-        // Get the discriminant type and substs which typeck computed
+        // Get the discriminant type and args which typeck computed
         let (discr_ty, upvars, interior, movable) = match *gen_ty.kind() {
-            ty::Generator(_, substs, movability) => {
-                let substs = substs.as_generator();
+            ty::Generator(_, args, movability) => {
+                let args = args.as_generator();
                 (
-                    substs.discr_ty(tcx),
-                    substs.upvar_tys().collect::<Vec<_>>(),
-                    substs.witness(),
+                    args.discr_ty(tcx),
+                    args.upvar_tys().collect::<Vec<_>>(),
+                    args.witness(),
                     movability == hir::Movability::Movable,
                 )
             }
@@ -1483,20 +1483,20 @@ impl<'tcx> MirPass<'tcx> for StateTransform {
         };
 
         let is_async_kind = matches!(body.generator_kind(), Some(GeneratorKind::Async(_)));
-        let (state_adt_ref, state_substs) = if is_async_kind {
+        let (state_adt_ref, state_args) = if is_async_kind {
             // Compute Poll<return_ty>
             let poll_did = tcx.require_lang_item(LangItem::Poll, None);
             let poll_adt_ref = tcx.adt_def(poll_did);
-            let poll_substs = tcx.mk_substs(&[body.return_ty().into()]);
-            (poll_adt_ref, poll_substs)
+            let poll_args = tcx.mk_args(&[body.return_ty().into()]);
+            (poll_adt_ref, poll_args)
         } else {
             // Compute GeneratorState<yield_ty, return_ty>
             let state_did = tcx.require_lang_item(LangItem::GeneratorState, None);
             let state_adt_ref = tcx.adt_def(state_did);
-            let state_substs = tcx.mk_substs(&[yield_ty.into(), body.return_ty().into()]);
-            (state_adt_ref, state_substs)
+            let state_args = tcx.mk_args(&[yield_ty.into(), body.return_ty().into()]);
+            (state_adt_ref, state_args)
         };
-        let ret_ty = Ty::new_adt(tcx, state_adt_ref, state_substs);
+        let ret_ty = Ty::new_adt(tcx, state_adt_ref, state_args);
 
         // We rename RETURN_PLACE which has type mir.return_ty to new_ret_local
         // RETURN_PLACE then is a fresh unused local with type ret_ty.
@@ -1570,7 +1570,7 @@ impl<'tcx> MirPass<'tcx> for StateTransform {
             tcx,
             is_async_kind,
             state_adt_ref,
-            state_substs,
+            state_args,
             remap,
             storage_liveness,
             always_live_locals,
@@ -1763,7 +1763,9 @@ fn check_suspend_tys<'tcx>(tcx: TyCtxt<'tcx>, layout: &GeneratorLayout<'tcx>, bo
             debug!(?decl);
 
             if !decl.ignore_for_traits && linted_tys.insert(decl.ty) {
-                let Some(hir_id) = decl.source_info.scope.lint_root(&body.source_scopes) else { continue };
+                let Some(hir_id) = decl.source_info.scope.lint_root(&body.source_scopes) else {
+                    continue;
+                };
 
                 check_must_not_suspend_ty(
                     tcx,
diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs
index 240beabfc1a..7860cf76247 100644
--- a/compiler/rustc_mir_transform/src/inline.rs
+++ b/compiler/rustc_mir_transform/src/inline.rs
@@ -105,7 +105,7 @@ struct Inliner<'tcx> {
     /// Caller codegen attributes.
     codegen_fn_attrs: &'tcx CodegenFnAttrs,
     /// Stack of inlined instances.
-    /// We only check the `DefId` and not the substs because we want to
+    /// We only check the `DefId` and not the args because we want to
     /// avoid inlining cases of polymorphic recursion.
     /// The number of `DefId`s is finite, so checking history is enough
     /// to ensure that we do not loop endlessly while inlining.
@@ -329,11 +329,11 @@ impl<'tcx> Inliner<'tcx> {
         let terminator = bb_data.terminator();
         if let TerminatorKind::Call { ref func, target, fn_span, .. } = terminator.kind {
             let func_ty = func.ty(caller_body, self.tcx);
-            if let ty::FnDef(def_id, substs) = *func_ty.kind() {
-                // To resolve an instance its substs have to be fully normalized.
-                let substs = self.tcx.try_normalize_erasing_regions(self.param_env, substs).ok()?;
+            if let ty::FnDef(def_id, args) = *func_ty.kind() {
+                // To resolve an instance its args have to be fully normalized.
+                let args = self.tcx.try_normalize_erasing_regions(self.param_env, args).ok()?;
                 let callee =
-                    Instance::resolve(self.tcx, self.param_env, def_id, substs).ok().flatten()?;
+                    Instance::resolve(self.tcx, self.param_env, def_id, args).ok().flatten()?;
 
                 if let InstanceDef::Virtual(..) | InstanceDef::Intrinsic(_) = callee.def {
                     return None;
@@ -343,7 +343,7 @@ impl<'tcx> Inliner<'tcx> {
                     return None;
                 }
 
-                let fn_sig = self.tcx.fn_sig(def_id).subst(self.tcx, substs);
+                let fn_sig = self.tcx.fn_sig(def_id).instantiate(self.tcx, args);
                 let source_info = SourceInfo { span: fn_span, ..terminator.source_info };
 
                 return Some(CallSite { callee, fn_sig, block: bb, target, source_info });
@@ -368,7 +368,7 @@ impl<'tcx> Inliner<'tcx> {
         // inlining. This is to ensure that the final crate doesn't have MIR that
         // reference unexported symbols
         if callsite.callee.def_id().is_local() {
-            let is_generic = callsite.callee.substs.non_erasable_generics().next().is_some();
+            let is_generic = callsite.callee.args.non_erasable_generics().next().is_some();
             if !is_generic && !callee_attrs.requests_inline() {
                 return Err("not exported");
             }
@@ -855,8 +855,8 @@ 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.type_of(def_id).subst(self.tcx, substs).kind()
+                &ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) => {
+                    self.tcx.type_of(def_id).instantiate(self.tcx, args).kind()
                 }
                 kind => kind,
             };
@@ -869,23 +869,23 @@ impl<'tcx> Visitor<'tcx> for CostChecker<'_, 'tcx> {
                     };
                     check_equal(self, *f_ty);
                 }
-                ty::Adt(adt_def, substs) => {
+                ty::Adt(adt_def, args) => {
                     let var = parent_ty.variant_index.unwrap_or(FIRST_VARIANT);
                     let Some(field) = adt_def.variant(var).fields.get(f) else {
                         self.validation = Err("malformed MIR");
                         return;
                     };
-                    check_equal(self, field.ty(self.tcx, substs));
+                    check_equal(self, field.ty(self.tcx, args));
                 }
-                ty::Closure(_, substs) => {
-                    let substs = substs.as_closure();
-                    let Some(f_ty) = substs.upvar_tys().nth(f.as_usize()) else {
+                ty::Closure(_, args) => {
+                    let args = args.as_closure();
+                    let Some(f_ty) = args.upvar_tys().nth(f.as_usize()) else {
                         self.validation = Err("malformed MIR");
                         return;
                     };
                     check_equal(self, f_ty);
                 }
-                &ty::Generator(def_id, substs, _) => {
+                &ty::Generator(def_id, args, _) => {
                     let f_ty = if let Some(var) = parent_ty.variant_index {
                         let gen_body = if def_id == self.callee_body.source.def_id() {
                             self.callee_body
@@ -910,7 +910,7 @@ impl<'tcx> Visitor<'tcx> for CostChecker<'_, 'tcx> {
 
                         f_ty.ty
                     } else {
-                        let Some(f_ty) = substs.as_generator().prefix_tys().nth(f.index()) else {
+                        let Some(f_ty) = args.as_generator().prefix_tys().nth(f.index()) else {
                             self.validation = Err("malformed MIR");
                             return;
                         };
@@ -1130,10 +1130,10 @@ fn try_instance_mir<'tcx>(
 ) -> Result<&'tcx Body<'tcx>, &'static str> {
     match instance {
         ty::InstanceDef::DropGlue(_, Some(ty)) => match ty.kind() {
-            ty::Adt(def, substs) => {
+            ty::Adt(def, args) => {
                 let fields = def.all_fields();
                 for field in fields {
-                    let field_ty = field.ty(tcx, substs);
+                    let field_ty = field.ty(tcx, args);
                     if field_ty.has_param() && field_ty.has_projections() {
                         return Err("cannot build drop shim for polymorphic type");
                     }
diff --git a/compiler/rustc_mir_transform/src/inline/cycle.rs b/compiler/rustc_mir_transform/src/inline/cycle.rs
index 8a10445f837..822634129fc 100644
--- a/compiler/rustc_mir_transform/src/inline/cycle.rs
+++ b/compiler/rustc_mir_transform/src/inline/cycle.rs
@@ -3,7 +3,7 @@ use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_middle::mir::TerminatorKind;
 use rustc_middle::ty::TypeVisitableExt;
-use rustc_middle::ty::{self, subst::SubstsRef, InstanceDef, TyCtxt};
+use rustc_middle::ty::{self, GenericArgsRef, InstanceDef, TyCtxt};
 use rustc_session::Limit;
 
 // FIXME: check whether it is cheaper to precompute the entire call graph instead of invoking
@@ -43,16 +43,16 @@ pub(crate) fn mir_callgraph_reachable<'tcx>(
         recursion_limit: Limit,
     ) -> bool {
         trace!(%caller);
-        for &(callee, substs) in tcx.mir_inliner_callees(caller.def) {
-            let Ok(substs) = caller.try_subst_mir_and_normalize_erasing_regions(
+        for &(callee, args) in tcx.mir_inliner_callees(caller.def) {
+            let Ok(args) = caller.try_subst_mir_and_normalize_erasing_regions(
                 tcx,
                 param_env,
-                ty::EarlyBinder::bind(substs),
+                ty::EarlyBinder::bind(args),
             ) else {
-                trace!(?caller, ?param_env, ?substs, "cannot normalize, skipping");
+                trace!(?caller, ?param_env, ?args, "cannot normalize, skipping");
                 continue;
             };
-            let Ok(Some(callee)) = ty::Instance::resolve(tcx, param_env, callee, substs) else {
+            let Ok(Some(callee)) = ty::Instance::resolve(tcx, param_env, callee, args) else {
                 trace!(?callee, "cannot resolve, skipping");
                 continue;
             };
@@ -147,7 +147,7 @@ pub(crate) fn mir_callgraph_reachable<'tcx>(
 pub(crate) fn mir_inliner_callees<'tcx>(
     tcx: TyCtxt<'tcx>,
     instance: ty::InstanceDef<'tcx>,
-) -> &'tcx [(DefId, SubstsRef<'tcx>)] {
+) -> &'tcx [(DefId, GenericArgsRef<'tcx>)] {
     let steal;
     let guard;
     let body = match (instance, instance.def_id().as_local()) {
@@ -165,7 +165,7 @@ pub(crate) fn mir_inliner_callees<'tcx>(
         if let TerminatorKind::Call { func, .. } = &terminator.kind {
             let ty = func.ty(&body.local_decls, tcx);
             let call = match ty.kind() {
-                ty::FnDef(def_id, substs) => (*def_id, *substs),
+                ty::FnDef(def_id, args) => (*def_id, *args),
                 _ => continue,
             };
             calls.insert(call);
diff --git a/compiler/rustc_mir_transform/src/instsimplify.rs b/compiler/rustc_mir_transform/src/instsimplify.rs
index e4dc617620e..a430f8da35c 100644
--- a/compiler/rustc_mir_transform/src/instsimplify.rs
+++ b/compiler/rustc_mir_transform/src/instsimplify.rs
@@ -5,7 +5,7 @@ use crate::MirPass;
 use rustc_hir::Mutability;
 use rustc_middle::mir::*;
 use rustc_middle::ty::layout::ValidityRequirement;
-use rustc_middle::ty::{self, ParamEnv, SubstsRef, Ty, TyCtxt};
+use rustc_middle::ty::{self, GenericArgsRef, ParamEnv, Ty, TyCtxt};
 use rustc_span::symbol::Symbol;
 use rustc_target::abi::FieldIdx;
 
@@ -163,14 +163,14 @@ impl<'tcx> InstSimplifyContext<'tcx, '_> {
                 }
 
                 // Transmuting a transparent struct/union to a field's type is a projection
-                if let ty::Adt(adt_def, substs) = operand_ty.kind()
+                if let ty::Adt(adt_def, args) = operand_ty.kind()
                     && adt_def.repr().transparent()
                     && (adt_def.is_struct() || adt_def.is_union())
                     && let Some(place) = operand.place()
                 {
                     let variant = adt_def.non_enum_variant();
                     for (i, field) in variant.fields.iter().enumerate() {
-                        let field_ty = field.ty(self.tcx, substs);
+                        let field_ty = field.ty(self.tcx, args);
                         if field_ty == *cast_ty {
                             let place = place.project_deeper(&[ProjectionElem::Field(FieldIdx::from_usize(i), *cast_ty)], self.tcx);
                             let operand = if operand.is_move() { Operand::Move(place) } else { Operand::Copy(place) };
@@ -189,22 +189,22 @@ impl<'tcx> InstSimplifyContext<'tcx, '_> {
         statements: &mut Vec<Statement<'tcx>>,
     ) {
         let TerminatorKind::Call { func, args, destination, target, .. } = &mut terminator.kind
-        else { return };
+        else {
+            return;
+        };
 
         // It's definitely not a clone if there are multiple arguments
         if args.len() != 1 {
             return;
         }
 
-        let Some(destination_block) = *target
-        else { return };
+        let Some(destination_block) = *target else { return };
 
         // Only bother looking more if it's easy to know what we're calling
-        let Some((fn_def_id, fn_substs)) = func.const_fn_def()
-        else { return };
+        let Some((fn_def_id, fn_args)) = func.const_fn_def() else { return };
 
         // Clone needs one subst, so we can cheaply rule out other stuff
-        if fn_substs.len() != 1 {
+        if fn_args.len() != 1 {
             return;
         }
 
@@ -212,8 +212,7 @@ impl<'tcx> InstSimplifyContext<'tcx, '_> {
         // doing DefId lookups to figure out what we're actually calling.
         let arg_ty = args[0].ty(self.local_decls, self.tcx);
 
-        let ty::Ref(_region, inner_ty, Mutability::Not) = *arg_ty.kind()
-        else { return };
+        let ty::Ref(_region, inner_ty, Mutability::Not) = *arg_ty.kind() else { return };
 
         if !inner_ty.is_trivially_pure_clone_copy() {
             return;
@@ -227,15 +226,14 @@ impl<'tcx> InstSimplifyContext<'tcx, '_> {
         if !self.tcx.consider_optimizing(|| {
             format!(
                 "InstSimplify - Call: {:?} SourceInfo: {:?}",
-                (fn_def_id, fn_substs),
+                (fn_def_id, fn_args),
                 terminator.source_info
             )
         }) {
             return;
         }
 
-        let Some(arg_place) = args.pop().unwrap().place()
-        else { return };
+        let Some(arg_place) = args.pop().unwrap().place() else { return };
 
         statements.push(Statement {
             source_info: terminator.source_info,
@@ -254,17 +252,21 @@ impl<'tcx> InstSimplifyContext<'tcx, '_> {
         terminator: &mut Terminator<'tcx>,
         _statements: &mut Vec<Statement<'tcx>>,
     ) {
-        let TerminatorKind::Call { func, target, .. } = &mut terminator.kind  else { return; };
-        let Some(target_block) = target else { return; };
+        let TerminatorKind::Call { func, target, .. } = &mut terminator.kind else {
+            return;
+        };
+        let Some(target_block) = target else {
+            return;
+        };
         let func_ty = func.ty(self.local_decls, self.tcx);
-        let Some((intrinsic_name, substs)) = resolve_rust_intrinsic(self.tcx, func_ty) else {
+        let Some((intrinsic_name, args)) = resolve_rust_intrinsic(self.tcx, func_ty) else {
             return;
         };
         // The intrinsics we are interested in have one generic parameter
-        if substs.is_empty() {
+        if args.is_empty() {
             return;
         }
-        let ty = substs.type_at(0);
+        let ty = args.type_at(0);
 
         let known_is_valid = intrinsic_assert_panics(self.tcx, self.param_env, ty, intrinsic_name);
         match known_is_valid {
@@ -295,10 +297,10 @@ fn intrinsic_assert_panics<'tcx>(
 fn resolve_rust_intrinsic<'tcx>(
     tcx: TyCtxt<'tcx>,
     func_ty: Ty<'tcx>,
-) -> Option<(Symbol, SubstsRef<'tcx>)> {
-    if let ty::FnDef(def_id, substs) = *func_ty.kind() {
+) -> Option<(Symbol, GenericArgsRef<'tcx>)> {
+    if let ty::FnDef(def_id, args) = *func_ty.kind() {
         if tcx.is_intrinsic(def_id) {
-            return Some((tcx.item_name(def_id), substs));
+            return Some((tcx.item_name(def_id), args));
         }
     }
     None
diff --git a/compiler/rustc_mir_transform/src/large_enums.rs b/compiler/rustc_mir_transform/src/large_enums.rs
index 8ed4706e172..19108dabdf4 100644
--- a/compiler/rustc_mir_transform/src/large_enums.rs
+++ b/compiler/rustc_mir_transform/src/large_enums.rs
@@ -48,7 +48,7 @@ impl EnumSizeOpt {
         alloc_cache: &mut FxHashMap<Ty<'tcx>, AllocId>,
     ) -> Option<(AdtDef<'tcx>, usize, AllocId)> {
         let adt_def = match ty.kind() {
-            ty::Adt(adt_def, _substs) if adt_def.is_enum() => adt_def,
+            ty::Adt(adt_def, _args) if adt_def.is_enum() => adt_def,
             _ => return None,
         };
         let layout = tcx.layout_of(param_env.and(ty)).ok()?;
diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs
index fa8257cf984..d419329f2d6 100644
--- a/compiler/rustc_mir_transform/src/lib.rs
+++ b/compiler/rustc_mir_transform/src/lib.rs
@@ -553,6 +553,7 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
             &normalize_array_len::NormalizeArrayLen, // has to run after `slice::len` lowering
             &const_goto::ConstGoto,
             &remove_unneeded_drops::RemoveUnneededDrops,
+            &ref_prop::ReferencePropagation,
             &sroa::ScalarReplacementOfAggregates,
             &match_branches::MatchBranchSimplification,
             // inst combine is after MatchBranchSimplification to clean up Ne(_1, false)
@@ -560,7 +561,6 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
             &instsimplify::InstSimplify,
             &simplify::SimplifyLocals::BeforeConstProp,
             &copy_prop::CopyProp,
-            &ref_prop::ReferencePropagation,
             // Perform `SeparateConstSwitch` after SSA-based analyses, as cloning blocks may
             // destroy the SSA property. It should still happen before const-propagation, so the
             // latter pass will leverage the created opportunities.
diff --git a/compiler/rustc_mir_transform/src/lower_intrinsics.rs b/compiler/rustc_mir_transform/src/lower_intrinsics.rs
index ce98e9b0c84..d1ecfe9f851 100644
--- a/compiler/rustc_mir_transform/src/lower_intrinsics.rs
+++ b/compiler/rustc_mir_transform/src/lower_intrinsics.rs
@@ -2,7 +2,7 @@
 
 use crate::{errors, MirPass};
 use rustc_middle::mir::*;
-use rustc_middle::ty::subst::SubstsRef;
+use rustc_middle::ty::GenericArgsRef;
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_span::symbol::{sym, Symbol};
 use rustc_span::Span;
@@ -19,7 +19,8 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics {
                 &mut terminator.kind
             {
                 let func_ty = func.ty(local_decls, tcx);
-                let Some((intrinsic_name, substs)) = resolve_rust_intrinsic(tcx, func_ty) else {
+                let Some((intrinsic_name, generic_args)) = resolve_rust_intrinsic(tcx, func_ty)
+                else {
                     continue;
                 };
                 match intrinsic_name {
@@ -149,7 +150,7 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics {
                     }
                     sym::size_of | sym::min_align_of => {
                         if let Some(target) = *target {
-                            let tp_ty = substs.type_at(0);
+                            let tp_ty = generic_args.type_at(0);
                             let null_op = match intrinsic_name {
                                 sym::size_of => NullOp::SizeOf,
                                 sym::min_align_of => NullOp::AlignOf,
@@ -251,7 +252,9 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics {
                         if let (Some(target), Some(arg)) = (*target, args[0].place()) {
                             let ty::RawPtr(ty::TypeAndMut { ty: dest_ty, .. }) =
                                 destination.ty(local_decls, tcx).ty.kind()
-                            else { bug!(); };
+                            else {
+                                bug!();
+                            };
 
                             block.statements.push(Statement {
                                 source_info: terminator.source_info,
@@ -315,10 +318,10 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics {
 fn resolve_rust_intrinsic<'tcx>(
     tcx: TyCtxt<'tcx>,
     func_ty: Ty<'tcx>,
-) -> Option<(Symbol, SubstsRef<'tcx>)> {
-    if let ty::FnDef(def_id, substs) = *func_ty.kind() {
+) -> Option<(Symbol, GenericArgsRef<'tcx>)> {
+    if let ty::FnDef(def_id, args) = *func_ty.kind() {
         if tcx.is_intrinsic(def_id) {
-            return Some((tcx.item_name(def_id), substs));
+            return Some((tcx.item_name(def_id), args));
         }
     }
     None
diff --git a/compiler/rustc_mir_transform/src/ref_prop.rs b/compiler/rustc_mir_transform/src/ref_prop.rs
index bbd9f76ba5c..c17c791f9c3 100644
--- a/compiler/rustc_mir_transform/src/ref_prop.rs
+++ b/compiler/rustc_mir_transform/src/ref_prop.rs
@@ -71,7 +71,7 @@ pub struct ReferencePropagation;
 
 impl<'tcx> MirPass<'tcx> for ReferencePropagation {
     fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
-        sess.mir_opt_level() >= 4
+        sess.mir_opt_level() >= 2
     }
 
     #[instrument(level = "trace", skip(self, tcx, body))]
@@ -355,7 +355,10 @@ impl<'tcx> MutVisitor<'tcx> for Replacer<'tcx> {
     }
 
     fn visit_var_debug_info(&mut self, debuginfo: &mut VarDebugInfo<'tcx>) {
-        if let VarDebugInfoContents::Place(ref mut place) = debuginfo.value
+        // If the debuginfo is a pointer to another place:
+        // - if it's a reborrow, see through it;
+        // - if it's a direct borrow, increase `debuginfo.references`.
+        while let VarDebugInfoContents::Place(ref mut place) = debuginfo.value
             && place.projection.is_empty()
             && let Value::Pointer(target, _) = self.targets[place.local]
             && target.projection.iter().all(|p| p.can_use_in_debuginfo())
@@ -369,28 +372,37 @@ impl<'tcx> MutVisitor<'tcx> for Replacer<'tcx> {
                 debuginfo.references = references;
                 *place = target;
                 self.any_replacement = true;
+            } else {
+                break
             }
         }
+
+        // Simplify eventual projections left inside `debuginfo`.
+        self.super_var_debug_info(debuginfo);
     }
 
     fn visit_place(&mut self, place: &mut Place<'tcx>, ctxt: PlaceContext, loc: Location) {
-        if place.projection.first() != Some(&PlaceElem::Deref) {
-            return;
-        }
-
         loop {
-            if let Value::Pointer(target, _) = self.targets[place.local] {
-                let perform_opt = matches!(ctxt, PlaceContext::NonUse(_))
-                    || self.allowed_replacements.contains(&(target.local, loc));
-
-                if perform_opt {
-                    *place = target.project_deeper(&place.projection[1..], self.tcx);
-                    self.any_replacement = true;
-                    continue;
+            if place.projection.first() != Some(&PlaceElem::Deref) {
+                return;
+            }
+
+            let Value::Pointer(target, _) = self.targets[place.local] else { return };
+
+            let perform_opt = match ctxt {
+                PlaceContext::NonUse(NonUseContext::VarDebugInfo) => {
+                    target.projection.iter().all(|p| p.can_use_in_debuginfo())
                 }
+                PlaceContext::NonUse(_) => true,
+                _ => self.allowed_replacements.contains(&(target.local, loc)),
+            };
+
+            if !perform_opt {
+                return;
             }
 
-            break;
+            *place = target.project_deeper(&place.projection[1..], self.tcx);
+            self.any_replacement = true;
         }
     }
 
diff --git a/compiler/rustc_mir_transform/src/remove_uninit_drops.rs b/compiler/rustc_mir_transform/src/remove_uninit_drops.rs
index 283931de043..6f9edd07d73 100644
--- a/compiler/rustc_mir_transform/src/remove_uninit_drops.rs
+++ b/compiler/rustc_mir_transform/src/remove_uninit_drops.rs
@@ -1,6 +1,6 @@
 use rustc_index::bit_set::ChunkedBitSet;
 use rustc_middle::mir::{Body, TerminatorKind};
-use rustc_middle::ty::subst::SubstsRef;
+use rustc_middle::ty::GenericArgsRef;
 use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt, VariantDef};
 use rustc_mir_dataflow::impls::MaybeInitializedPlaces;
 use rustc_mir_dataflow::move_paths::{LookupResult, MoveData, MovePathIndex};
@@ -38,8 +38,7 @@ impl<'tcx> MirPass<'tcx> for RemoveUninitDrops {
         let mut to_remove = vec![];
         for (bb, block) in body.basic_blocks.iter_enumerated() {
             let terminator = block.terminator();
-            let TerminatorKind::Drop { place, .. } = &terminator.kind
-            else { continue };
+            let TerminatorKind::Drop { place, .. } = &terminator.kind else { continue };
 
             maybe_inits.seek_before_primary_effect(body.terminator_loc(bb));
 
@@ -64,9 +63,9 @@ impl<'tcx> MirPass<'tcx> for RemoveUninitDrops {
         for bb in to_remove {
             let block = &mut body.basic_blocks_mut()[bb];
 
-            let TerminatorKind::Drop { target, .. }
-                = &block.terminator().kind
-            else { unreachable!() };
+            let TerminatorKind::Drop { target, .. } = &block.terminator().kind else {
+                unreachable!()
+            };
 
             // Replace block terminator with `Goto`.
             block.terminator_mut().kind = TerminatorKind::Goto { target: *target };
@@ -99,7 +98,7 @@ fn is_needs_drop_and_init<'tcx>(
     // This pass is only needed for const-checking, so it doesn't handle as many cases as
     // `DropCtxt::open_drop`, since they aren't relevant in a const-context.
     match ty.kind() {
-        ty::Adt(adt, substs) => {
+        ty::Adt(adt, args) => {
             let dont_elaborate = adt.is_union() || adt.is_manually_drop() || adt.has_dtor(tcx);
             if dont_elaborate {
                 return true;
@@ -119,7 +118,7 @@ fn is_needs_drop_and_init<'tcx>(
                     let downcast =
                         move_path_children_matching(move_data, mpi, |x| x.is_downcast_to(vid));
                     let Some(dc_mpi) = downcast else {
-                        return variant_needs_drop(tcx, param_env, substs, variant);
+                        return variant_needs_drop(tcx, param_env, args, variant);
                     };
 
                     dc_mpi
@@ -131,7 +130,7 @@ fn is_needs_drop_and_init<'tcx>(
                     .fields
                     .iter()
                     .enumerate()
-                    .map(|(f, field)| (FieldIdx::from_usize(f), field.ty(tcx, substs), mpi))
+                    .map(|(f, field)| (FieldIdx::from_usize(f), field.ty(tcx, args), mpi))
                     .any(field_needs_drop_and_init)
             })
         }
@@ -149,11 +148,11 @@ fn is_needs_drop_and_init<'tcx>(
 fn variant_needs_drop<'tcx>(
     tcx: TyCtxt<'tcx>,
     param_env: ParamEnv<'tcx>,
-    substs: SubstsRef<'tcx>,
+    args: GenericArgsRef<'tcx>,
     variant: &VariantDef,
 ) -> bool {
     variant.fields.iter().any(|field| {
-        let f_ty = field.ty(tcx, substs);
+        let f_ty = field.ty(tcx, args);
         f_ty.needs_drop(tcx, param_env)
     })
 }
diff --git a/compiler/rustc_mir_transform/src/remove_zsts.rs b/compiler/rustc_mir_transform/src/remove_zsts.rs
index 1f37f03cff1..1ba9ad87537 100644
--- a/compiler/rustc_mir_transform/src/remove_zsts.rs
+++ b/compiler/rustc_mir_transform/src/remove_zsts.rs
@@ -15,7 +15,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()).subst_identity().is_generator() {
+        if tcx.type_of(body.source.def_id()).instantiate_identity().is_generator() {
             return;
         }
         let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id());
diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs
index b176db3c9e0..5e8ba4f544c 100644
--- a/compiler/rustc_mir_transform/src/shim.rs
+++ b/compiler/rustc_mir_transform/src/shim.rs
@@ -3,8 +3,8 @@ use rustc_hir::def_id::DefId;
 use rustc_hir::lang_items::LangItem;
 use rustc_middle::mir::*;
 use rustc_middle::query::Providers;
-use rustc_middle::ty::InternalSubsts;
-use rustc_middle::ty::{self, EarlyBinder, GeneratorSubsts, Ty, TyCtxt};
+use rustc_middle::ty::GenericArgs;
+use rustc_middle::ty::{self, EarlyBinder, GeneratorArgs, Ty, TyCtxt};
 use rustc_target::abi::{FieldIdx, VariantIdx, FIRST_VARIANT};
 
 use rustc_index::{Idx, IndexVec};
@@ -69,9 +69,9 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> Body<'
         ty::InstanceDef::DropGlue(def_id, ty) => {
             // FIXME(#91576): Drop shims for generators aren't subject to the MIR passes at the end
             // of this function. Is this intentional?
-            if let Some(ty::Generator(gen_def_id, substs, _)) = ty.map(Ty::kind) {
+            if let Some(ty::Generator(gen_def_id, args, _)) = ty.map(Ty::kind) {
                 let body = tcx.optimized_mir(*gen_def_id).generator_drop().unwrap();
-                let body = EarlyBinder::bind(body.clone()).subst(tcx, substs);
+                let body = EarlyBinder::bind(body.clone()).instantiate(tcx, args);
                 debug!("make_shim({:?}) = {:?}", instance, body);
                 return body;
             }
@@ -160,12 +160,12 @@ fn build_drop_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, ty: Option<Ty<'tcx>>)
 
     assert!(!matches!(ty, Some(ty) if ty.is_generator()));
 
-    let substs = if let Some(ty) = ty {
-        tcx.mk_substs(&[ty.into()])
+    let args = if let Some(ty) = ty {
+        tcx.mk_args(&[ty.into()])
     } else {
-        InternalSubsts::identity_for_item(tcx, def_id)
+        GenericArgs::identity_for_item(tcx, def_id)
     };
-    let sig = tcx.fn_sig(def_id).subst(tcx, substs);
+    let sig = tcx.fn_sig(def_id).instantiate(tcx, args);
     let sig = tcx.erase_late_bound_regions(sig);
     let span = tcx.def_span(def_id);
 
@@ -377,12 +377,10 @@ fn build_clone_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, self_ty: Ty<'tcx>) -
 
     match self_ty.kind() {
         _ if is_copy => builder.copy_shim(),
-        ty::Closure(_, substs) => {
-            builder.tuple_like_shim(dest, src, substs.as_closure().upvar_tys())
-        }
+        ty::Closure(_, args) => builder.tuple_like_shim(dest, src, args.as_closure().upvar_tys()),
         ty::Tuple(..) => builder.tuple_like_shim(dest, src, self_ty.tuple_fields()),
-        ty::Generator(gen_def_id, substs, hir::Movability::Movable) => {
-            builder.generator_shim(dest, src, *gen_def_id, substs.as_generator())
+        ty::Generator(gen_def_id, args, hir::Movability::Movable) => {
+            builder.generator_shim(dest, src, *gen_def_id, args.as_generator())
         }
         _ => bug!("clone shim for `{:?}` which is not `Copy` and is not an aggregate", self_ty),
     };
@@ -404,7 +402,7 @@ impl<'tcx> CloneShimBuilder<'tcx> {
         // we must subst the self_ty because it's
         // otherwise going to be TySelf and we can't index
         // or access fields of a Place of type TySelf.
-        let sig = tcx.fn_sig(def_id).subst(tcx, &[self_ty.into()]);
+        let sig = tcx.fn_sig(def_id).instantiate(tcx, &[self_ty.into()]);
         let sig = tcx.erase_late_bound_regions(sig);
         let span = tcx.def_span(def_id);
 
@@ -587,17 +585,17 @@ impl<'tcx> CloneShimBuilder<'tcx> {
         dest: Place<'tcx>,
         src: Place<'tcx>,
         gen_def_id: DefId,
-        substs: GeneratorSubsts<'tcx>,
+        args: GeneratorArgs<'tcx>,
     ) {
         self.block(vec![], TerminatorKind::Goto { target: self.block_index_offset(3) }, false);
         let unwind = self.block(vec![], TerminatorKind::Resume, true);
         // This will get overwritten with a switch once we know the target blocks
         let switch = self.block(vec![], TerminatorKind::Unreachable, false);
-        let unwind = self.clone_fields(dest, src, switch, unwind, substs.upvar_tys());
+        let unwind = self.clone_fields(dest, src, switch, unwind, args.upvar_tys());
         let target = self.block(vec![], TerminatorKind::Return, false);
         let unreachable = self.block(vec![], TerminatorKind::Unreachable, false);
-        let mut cases = Vec::with_capacity(substs.state_tys(gen_def_id, self.tcx).count());
-        for (index, state_tys) in substs.state_tys(gen_def_id, self.tcx).enumerate() {
+        let mut cases = Vec::with_capacity(args.state_tys(gen_def_id, self.tcx).count());
+        for (index, state_tys) in args.state_tys(gen_def_id, self.tcx).enumerate() {
             let variant_index = VariantIdx::new(index);
             let dest = self.tcx.mk_place_downcast_unnamed(dest, variant_index);
             let src = self.tcx.mk_place_downcast_unnamed(src, variant_index);
@@ -613,7 +611,7 @@ impl<'tcx> CloneShimBuilder<'tcx> {
             cases.push((index as u128, start_block));
             let _final_cleanup_block = self.clone_fields(dest, src, target, unwind, state_tys);
         }
-        let discr_ty = substs.discr_ty(self.tcx);
+        let discr_ty = args.discr_ty(self.tcx);
         let temp = self.make_place(Mutability::Mut, discr_ty);
         let rvalue = Rvalue::Discriminant(src);
         let statement = self.make_statement(StatementKind::Assign(Box::new((temp, rvalue))));
@@ -642,7 +640,7 @@ fn build_call_shim<'tcx>(
     // `FnPtrShim` contains the fn pointer type that a call shim is being built for - this is used
     // to substitute into the signature of the shim. It is not necessary for users of this
     // MIR body to perform further substitutions (see `InstanceDef::has_polymorphic_mir_body`).
-    let (sig_substs, untuple_args) = if let ty::InstanceDef::FnPtrShim(_, ty) = instance {
+    let (sig_args, untuple_args) = if let ty::InstanceDef::FnPtrShim(_, ty) = instance {
         let sig = tcx.erase_late_bound_regions(ty.fn_sig(tcx));
 
         let untuple_args = sig.inputs();
@@ -659,11 +657,11 @@ fn build_call_shim<'tcx>(
     let sig = tcx.fn_sig(def_id);
     let sig = sig.map_bound(|sig| tcx.erase_late_bound_regions(sig));
 
-    assert_eq!(sig_substs.is_some(), !instance.has_polymorphic_mir_body());
-    let mut sig = if let Some(sig_substs) = sig_substs {
-        sig.subst(tcx, &sig_substs)
+    assert_eq!(sig_args.is_some(), !instance.has_polymorphic_mir_body());
+    let mut sig = if let Some(sig_args) = sig_args {
+        sig.instantiate(tcx, &sig_args)
     } else {
-        sig.subst_identity()
+        sig.instantiate_identity()
     };
 
     if let CallKind::Indirect(fnty) = call_kind {
@@ -751,7 +749,7 @@ fn build_call_shim<'tcx>(
 
         // `FnDef` call with optional receiver.
         CallKind::Direct(def_id) => {
-            let ty = tcx.type_of(def_id).subst_identity();
+            let ty = tcx.type_of(def_id).instantiate_identity();
             (
                 Operand::Constant(Box::new(Constant {
                     span,
@@ -868,12 +866,12 @@ pub fn build_adt_ctor(tcx: TyCtxt<'_>, ctor_id: DefId) -> Body<'_> {
     // Normalize the sig.
     let sig = tcx
         .fn_sig(ctor_id)
-        .subst_identity()
+        .instantiate_identity()
         .no_bound_vars()
         .expect("LBR in ADT constructor signature");
     let sig = tcx.normalize_erasing_regions(param_env, sig);
 
-    let ty::Adt(adt_def, substs) = sig.output().kind() else {
+    let ty::Adt(adt_def, args) = sig.output().kind() else {
         bug!("unexpected type for ADT ctor {:?}", sig.output());
     };
 
@@ -896,7 +894,7 @@ pub fn build_adt_ctor(tcx: TyCtxt<'_>, ctor_id: DefId) -> Body<'_> {
     // return;
     debug!("build_ctor: variant_index={:?}", variant_index);
 
-    let kind = AggregateKind::Adt(adt_def.did(), variant_index, substs, None, None);
+    let kind = AggregateKind::Adt(adt_def.did(), variant_index, args, None, None);
     let variant = adt_def.variant(variant_index);
     let statement = Statement {
         kind: StatementKind::Assign(Box::new((
@@ -941,7 +939,7 @@ pub fn build_adt_ctor(tcx: TyCtxt<'_>, ctor_id: DefId) -> Body<'_> {
 fn build_fn_ptr_addr_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, self_ty: Ty<'tcx>) -> Body<'tcx> {
     assert!(matches!(self_ty.kind(), ty::FnPtr(..)), "expected fn ptr, found {self_ty}");
     let span = tcx.def_span(def_id);
-    let Some(sig) = tcx.fn_sig(def_id).subst(tcx, &[self_ty.into()]).no_bound_vars() else {
+    let Some(sig) = tcx.fn_sig(def_id).instantiate(tcx, &[self_ty.into()]).no_bound_vars() else {
         span_bug!(span, "FnPtr::addr with bound vars for `{self_ty}`");
     };
     let locals = local_decls_for_sig(&sig, span);
diff --git a/compiler/rustc_mir_transform/src/simplify.rs b/compiler/rustc_mir_transform/src/simplify.rs
index e59219321b7..b7a51cfd619 100644
--- a/compiler/rustc_mir_transform/src/simplify.rs
+++ b/compiler/rustc_mir_transform/src/simplify.rs
@@ -199,7 +199,8 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> {
         let last = current;
         *start = last;
         while let Some((current, mut terminator)) = terminators.pop() {
-            let Terminator { kind: TerminatorKind::Goto { ref mut target }, .. } = terminator else {
+            let Terminator { kind: TerminatorKind::Goto { ref mut target }, .. } = terminator
+            else {
                 unreachable!();
             };
             *changed |= *target != last;
diff --git a/compiler/rustc_mir_transform/src/sroa.rs b/compiler/rustc_mir_transform/src/sroa.rs
index 881a1547c52..e66ae8ff884 100644
--- a/compiler/rustc_mir_transform/src/sroa.rs
+++ b/compiler/rustc_mir_transform/src/sroa.rs
@@ -20,7 +20,7 @@ impl<'tcx> MirPass<'tcx> for ScalarReplacementOfAggregates {
         debug!(def_id = ?body.source.def_id());
 
         // Avoid query cycles (generators require optimized MIR for layout).
-        if tcx.type_of(body.source.def_id()).subst_identity().is_generator() {
+        if tcx.type_of(body.source.def_id()).instantiate_identity().is_generator() {
             return;
         }
 
@@ -64,7 +64,7 @@ fn escaping_locals<'tcx>(
         if ty.is_union() || ty.is_enum() {
             return true;
         }
-        if let ty::Adt(def, _substs) = ty.kind() {
+        if let ty::Adt(def, _args) = ty.kind() {
             if def.repr().flags.contains(ReprFlags::IS_SIMD) {
                 // Exclude #[repr(simd)] types so that they are not de-optimized into an array
                 return true;
@@ -161,7 +161,9 @@ struct ReplacementMap<'tcx> {
 
 impl<'tcx> ReplacementMap<'tcx> {
     fn replace_place(&self, tcx: TyCtxt<'tcx>, place: PlaceRef<'tcx>) -> Option<Place<'tcx>> {
-        let &[PlaceElem::Field(f, _), ref rest @ ..] = place.projection else { return None; };
+        let &[PlaceElem::Field(f, _), ref rest @ ..] = place.projection else {
+            return None;
+        };
         let fields = self.fragments[place.local].as_ref()?;
         let (_, new_local) = fields[f]?;
         Some(Place { local: new_local, projection: tcx.mk_place_elems(&rest) })
diff --git a/compiler/rustc_mir_transform/src/ssa.rs b/compiler/rustc_mir_transform/src/ssa.rs
index 8dc2dfe13bd..04bc461c815 100644
--- a/compiler/rustc_mir_transform/src/ssa.rs
+++ b/compiler/rustc_mir_transform/src/ssa.rs
@@ -266,9 +266,11 @@ fn compute_copy_classes(ssa: &mut SsaLocals, body: &Body<'_>) {
     let mut copies = IndexVec::from_fn_n(|l| l, body.local_decls.len());
 
     for (local, rvalue, _) in ssa.assignments(body) {
-        let (Rvalue::Use(Operand::Copy(place) | Operand::Move(place)) | Rvalue::CopyForDeref(place))
-            = rvalue
-        else { continue };
+        let (Rvalue::Use(Operand::Copy(place) | Operand::Move(place))
+        | Rvalue::CopyForDeref(place)) = rvalue
+        else {
+            continue;
+        };
 
         let Some(rhs) = place.as_local() else { continue };
         let local_ty = body.local_decls()[local].ty;
diff --git a/compiler/rustc_mir_transform/src/uninhabited_enum_branching.rs b/compiler/rustc_mir_transform/src/uninhabited_enum_branching.rs
index 5389b9f52eb..092bcb5c979 100644
--- a/compiler/rustc_mir_transform/src/uninhabited_enum_branching.rs
+++ b/compiler/rustc_mir_transform/src/uninhabited_enum_branching.rs
@@ -105,7 +105,8 @@ impl<'tcx> MirPass<'tcx> for UninhabitedEnumBranching {
         for bb in body.basic_blocks.indices() {
             trace!("processing block {:?}", bb);
 
-            let Some(discriminant_ty) = get_switched_on_type(&body.basic_blocks[bb], tcx, body) else {
+            let Some(discriminant_ty) = get_switched_on_type(&body.basic_blocks[bb], tcx, body)
+            else {
                 continue;
             };
 
diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs
index 242269e9d1a..5b678d4ba78 100644
--- a/compiler/rustc_monomorphize/src/collector.rs
+++ b/compiler/rustc_monomorphize/src/collector.rs
@@ -178,11 +178,11 @@ use rustc_middle::mir::{self, Local, Location};
 use rustc_middle::query::TyCtxtAt;
 use rustc_middle::ty::adjustment::{CustomCoerceUnsized, PointerCoercion};
 use rustc_middle::ty::print::with_no_trimmed_paths;
-use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts};
 use rustc_middle::ty::{
     self, GenericParamDefKind, Instance, InstanceDef, Ty, TyCtxt, TypeFoldable, TypeVisitableExt,
     VtblEntry,
 };
+use rustc_middle::ty::{GenericArgKind, GenericArgs};
 use rustc_middle::{middle::codegen_fn_attrs::CodegenFnAttrFlags, mir::visit::TyContext};
 use rustc_session::config::EntryFnType;
 use rustc_session::lint::builtin::LARGE_ASSIGNMENTS;
@@ -393,7 +393,7 @@ fn collect_items_rec<'tcx>(
                     starting_item.span,
                     MonoItem::Fn(Instance {
                         def: InstanceDef::ThreadLocalShim(def_id),
-                        substs: InternalSubsts::empty(),
+                        args: GenericArgs::empty(),
                     }),
                 ));
             }
@@ -555,7 +555,7 @@ fn check_recursion_limit<'tcx>(
 
 fn check_type_length_limit<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) {
     let type_length = instance
-        .substs
+        .args
         .iter()
         .flat_map(|arg| arg.walk())
         .filter(|arg| match arg.unpack() {
@@ -659,11 +659,11 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> {
                 let source_ty = operand.ty(self.body, self.tcx);
                 let source_ty = self.monomorphize(source_ty);
                 match *source_ty.kind() {
-                    ty::Closure(def_id, substs) => {
+                    ty::Closure(def_id, args) => {
                         let instance = Instance::resolve_closure(
                             self.tcx,
                             def_id,
-                            substs,
+                            args,
                             ty::ClosureKind::FnOnce,
                         )
                         .expect("failed to normalize and resolve closure during codegen");
@@ -875,12 +875,11 @@ fn visit_fn_use<'tcx>(
     source: Span,
     output: &mut MonoItems<'tcx>,
 ) {
-    if let ty::FnDef(def_id, substs) = *ty.kind() {
+    if let ty::FnDef(def_id, args) = *ty.kind() {
         let instance = if is_direct_call {
-            ty::Instance::expect_resolve(tcx, ty::ParamEnv::reveal_all(), def_id, substs)
+            ty::Instance::expect_resolve(tcx, ty::ParamEnv::reveal_all(), def_id, args)
         } else {
-            match ty::Instance::resolve_for_fn_ptr(tcx, ty::ParamEnv::reveal_all(), def_id, substs)
-            {
+            match ty::Instance::resolve_for_fn_ptr(tcx, ty::ParamEnv::reveal_all(), def_id, args) {
                 Some(instance) => instance,
                 _ => bug!("failed to resolve instance for {ty}"),
             }
@@ -1043,7 +1042,7 @@ fn find_vtable_types_for_unsizing<'tcx>(
         // T as dyn* Trait
         (_, &ty::Dynamic(_, _, ty::DynStar)) => ptr_vtable(source_ty, target_ty),
 
-        (&ty::Adt(source_adt_def, source_substs), &ty::Adt(target_adt_def, target_substs)) => {
+        (&ty::Adt(source_adt_def, source_args), &ty::Adt(target_adt_def, target_args)) => {
             assert_eq!(source_adt_def, target_adt_def);
 
             let CustomCoerceUnsized::Struct(coerce_index) =
@@ -1059,8 +1058,8 @@ fn find_vtable_types_for_unsizing<'tcx>(
 
             find_vtable_types_for_unsizing(
                 tcx,
-                source_fields[coerce_index].ty(*tcx, source_substs),
-                target_fields[coerce_index].ty(*tcx, target_substs),
+                source_fields[coerce_index].ty(*tcx, source_args),
+                target_fields[coerce_index].ty(*tcx, target_args),
             )
         }
         _ => bug!(
@@ -1245,7 +1244,7 @@ impl<'v> RootCollector<'_, 'v> {
             self.tcx,
             ty::ParamEnv::reveal_all(),
             start_def_id,
-            self.tcx.mk_substs(&[main_ret_ty.into()]),
+            self.tcx.mk_args(&[main_ret_ty.into()]),
         )
         .unwrap()
         .unwrap();
@@ -1292,8 +1291,8 @@ fn create_mono_items_for_default_impls<'tcx>(
             )
         }
     };
-    let impl_substs = InternalSubsts::for_item(tcx, item.owner_id.to_def_id(), only_region_params);
-    let trait_ref = trait_ref.subst(tcx, impl_substs);
+    let impl_args = GenericArgs::for_item(tcx, item.owner_id.to_def_id(), only_region_params);
+    let trait_ref = trait_ref.instantiate(tcx, impl_args);
 
     // Unlike 'lazy' monomorphization that begins by collecting items transitively
     // called by `main` or other global items, when eagerly monomorphizing impl
@@ -1304,7 +1303,7 @@ fn create_mono_items_for_default_impls<'tcx>(
     // consider higher-ranked predicates such as `for<'a> &'a mut [u8]: Copy` to
     // be trivially false. We must now check that the impl has no impossible-to-satisfy
     // predicates.
-    if tcx.subst_and_check_impossible_predicates((item.owner_id.to_def_id(), impl_substs)) {
+    if tcx.subst_and_check_impossible_predicates((item.owner_id.to_def_id(), impl_args)) {
         return;
     }
 
@@ -1322,8 +1321,8 @@ fn create_mono_items_for_default_impls<'tcx>(
 
         // As mentioned above, the method is legal to eagerly instantiate if it
         // only has lifetime substitutions. This is validated by
-        let substs = trait_ref.substs.extend_to(tcx, method.def_id, only_region_params);
-        let instance = ty::Instance::expect_resolve(tcx, param_env, method.def_id, substs);
+        let args = trait_ref.args.extend_to(tcx, method.def_id, only_region_params);
+        let instance = ty::Instance::expect_resolve(tcx, param_env, method.def_id, args);
 
         let mono_item = create_fn_mono_item(tcx, instance, DUMMY_SP);
         if mono_item.node.is_instantiable(tcx) && should_codegen_locally(tcx, &instance) {
diff --git a/compiler/rustc_monomorphize/src/partitioning.rs b/compiler/rustc_monomorphize/src/partitioning.rs
index da76cf2236c..391666554bb 100644
--- a/compiler/rustc_monomorphize/src/partitioning.rs
+++ b/compiler/rustc_monomorphize/src/partitioning.rs
@@ -572,7 +572,7 @@ fn characteristic_def_id_of_mono_item<'tcx>(
             // DefId, we use the location of the impl after all.
 
             if tcx.trait_of_item(def_id).is_some() {
-                let self_ty = instance.substs.type_at(0);
+                let self_ty = instance.args.type_at(0);
                 // This is a default implementation of a trait method.
                 return characteristic_def_id_of_type(self_ty).or(Some(def_id));
             }
@@ -592,7 +592,7 @@ fn characteristic_def_id_of_mono_item<'tcx>(
                 if !tcx.sess.opts.unstable_opts.polymorphize || !instance.has_param() {
                     // This is a method within an impl, find out what the self-type is:
                     let impl_self_ty = tcx.subst_and_normalize_erasing_regions(
-                        instance.substs,
+                        instance.args,
                         ty::ParamEnv::reveal_all(),
                         tcx.type_of(impl_def_id),
                     );
@@ -745,7 +745,7 @@ fn mono_item_visibility<'tcx>(
         return Visibility::Hidden;
     }
 
-    let is_generic = instance.substs.non_erasable_generics().next().is_some();
+    let is_generic = instance.args.non_erasable_generics().next().is_some();
 
     // Upstream `DefId` instances get different handling than local ones.
     let Some(def_id) = def_id.as_local() else {
diff --git a/compiler/rustc_monomorphize/src/polymorphize.rs b/compiler/rustc_monomorphize/src/polymorphize.rs
index aa2ce65e4cc..d31bf2072b1 100644
--- a/compiler/rustc_monomorphize/src/polymorphize.rs
+++ b/compiler/rustc_monomorphize/src/polymorphize.rs
@@ -14,9 +14,8 @@ use rustc_middle::mir::{
 use rustc_middle::query::Providers;
 use rustc_middle::ty::{
     self,
-    subst::SubstsRef,
     visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor},
-    Const, Ty, TyCtxt, UnusedGenericParams,
+    Const, GenericArgsRef, Ty, TyCtxt, UnusedGenericParams,
 };
 use rustc_span::symbol::sym;
 use std::ops::ControlFlow;
@@ -229,12 +228,12 @@ struct MarkUsedGenericParams<'a, 'tcx> {
 impl<'a, 'tcx> MarkUsedGenericParams<'a, 'tcx> {
     /// Invoke `unused_generic_params` on a body contained within the current item (e.g.
     /// a closure, generator or constant).
-    #[instrument(level = "debug", skip(self, def_id, substs))]
-    fn visit_child_body(&mut self, def_id: DefId, substs: SubstsRef<'tcx>) {
+    #[instrument(level = "debug", skip(self, def_id, args))]
+    fn visit_child_body(&mut self, def_id: DefId, args: GenericArgsRef<'tcx>) {
         let instance = ty::InstanceDef::Item(def_id);
         let unused = self.tcx.unused_generic_params(instance);
         debug!(?self.unused_parameters, ?unused);
-        for (i, arg) in substs.iter().enumerate() {
+        for (i, arg) in args.iter().enumerate() {
             let i = i.try_into().unwrap();
             if unused.is_used(i) {
                 arg.visit_with(self);
@@ -252,9 +251,9 @@ impl<'a, 'tcx> Visitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> {
             if matches!(def_kind, DefKind::Closure | DefKind::Generator) {
                 // Skip visiting the closure/generator that is currently being processed. This only
                 // happens because the first argument to the closure is a reference to itself and
-                // that will call `visit_substs`, resulting in each generic parameter captured being
+                // that will call `visit_args`, resulting in each generic parameter captured being
                 // considered used by default.
-                debug!("skipping closure substs");
+                debug!("skipping closure args");
                 return;
             }
         }
@@ -267,12 +266,12 @@ impl<'a, 'tcx> Visitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> {
             ConstantKind::Ty(c) => {
                 c.visit_with(self);
             }
-            ConstantKind::Unevaluated(mir::UnevaluatedConst { def, substs: _, promoted }, ty) => {
+            ConstantKind::Unevaluated(mir::UnevaluatedConst { def, args: _, promoted }, ty) => {
                 // Avoid considering `T` unused when constants are of the form:
                 //   `<Self as Foo<T>>::foo::promoted[p]`
                 if let Some(p) = promoted {
                     if self.def_id == def && !self.tcx.generics_of(def).has_self {
-                        // If there is a promoted, don't look at the substs - since it will always contain
+                        // If there is a promoted, don't look at the args - since it will always contain
                         // the generic parameters, instead, traverse the promoted MIR.
                         let promoted = self.tcx.promoted_mir(def);
                         self.visit_body(&promoted[p]);
@@ -303,10 +302,10 @@ impl<'a, 'tcx> TypeVisitor<TyCtxt<'tcx>> for MarkUsedGenericParams<'a, 'tcx> {
                 self.unused_parameters.mark_used(param.index);
                 ControlFlow::Continue(())
             }
-            ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, substs })
+            ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, args })
                 if matches!(self.tcx.def_kind(def), DefKind::AnonConst) =>
             {
-                self.visit_child_body(def, substs);
+                self.visit_child_body(def, args);
                 ControlFlow::Continue(())
             }
             _ => c.super_visit_with(self),
@@ -320,7 +319,7 @@ impl<'a, 'tcx> TypeVisitor<TyCtxt<'tcx>> for MarkUsedGenericParams<'a, 'tcx> {
         }
 
         match *ty.kind() {
-            ty::Closure(def_id, substs) | ty::Generator(def_id, substs, ..) => {
+            ty::Closure(def_id, args) | ty::Generator(def_id, args, ..) => {
                 debug!(?def_id);
                 // Avoid cycle errors with generators.
                 if def_id == self.def_id {
@@ -329,7 +328,7 @@ impl<'a, 'tcx> TypeVisitor<TyCtxt<'tcx>> for MarkUsedGenericParams<'a, 'tcx> {
 
                 // Consider any generic parameters used by any closures/generators as used in the
                 // parent.
-                self.visit_child_body(def_id, substs);
+                self.visit_child_body(def_id, args);
                 ControlFlow::Continue(())
             }
             ty::Param(param) => {
diff --git a/compiler/rustc_monomorphize/src/util.rs b/compiler/rustc_monomorphize/src/util.rs
index f6a80b0431f..a3433d3d13d 100644
--- a/compiler/rustc_monomorphize/src/util.rs
+++ b/compiler/rustc_monomorphize/src/util.rs
@@ -27,12 +27,12 @@ pub(crate) fn dump_closure_profile<'tcx>(tcx: TyCtxt<'tcx>, closure_instance: In
             typeck_results.closure_size_eval[&closure_def_id];
 
         let before_feature_tys = tcx.subst_and_normalize_erasing_regions(
-            closure_instance.substs,
+            closure_instance.args,
             param_env,
             ty::EarlyBinder::bind(before_feature_tys),
         );
         let after_feature_tys = tcx.subst_and_normalize_erasing_regions(
-            closure_instance.substs,
+            closure_instance.args,
             param_env,
             ty::EarlyBinder::bind(after_feature_tys),
         );
diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs
index 0ce6a570d25..8455803ad0c 100644
--- a/compiler/rustc_parse/src/parser/diagnostics.rs
+++ b/compiler/rustc_parse/src/parser/diagnostics.rs
@@ -1434,8 +1434,9 @@ impl<'a> Parser<'a> {
                 self.inc_dec_standalone_suggest(kind, spans).emit_verbose(&mut err)
             }
             IsStandalone::Subexpr => {
-                let Ok(base_src) = self.span_to_snippet(base.span)
-                else { return help_base_case(err, base) };
+                let Ok(base_src) = self.span_to_snippet(base.span) else {
+                    return help_base_case(err, base);
+                };
                 match kind.fixity {
                     UnaryFixity::Pre => {
                         self.prefix_inc_dec_suggest(base_src, kind, spans).emit(&mut err)
diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs
index c23420661fa..e4d843b7c8b 100644
--- a/compiler/rustc_parse/src/parser/mod.rs
+++ b/compiler/rustc_parse/src/parser/mod.rs
@@ -1289,7 +1289,9 @@ impl<'a> Parser<'a> {
 
         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!() };
+            let TokenTree::Delimited(dspan, delim, tokens) = self.parse_token_tree() else {
+                unreachable!()
+            };
 
             DelimArgs { dspan, delim: MacDelimiter::from_token(delim).unwrap(), tokens }
         })
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index f48900c3c52..ee14ffa6da8 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -1432,9 +1432,9 @@ impl CheckAttrVisitor<'_> {
         };
 
         let Some(ItemLike::Item(Item {
-            kind: ItemKind::Fn(FnSig { decl, .. }, generics, _),
-            ..
-        }))  = item else {
+            kind: ItemKind::Fn(FnSig { decl, .. }, generics, _), ..
+        })) = item
+        else {
             bug!("should be a function item");
         };
 
@@ -2106,8 +2106,12 @@ impl CheckAttrVisitor<'_> {
         }
 
         let tcx = self.tcx;
-        let Some(token_stream_def_id) = tcx.get_diagnostic_item(sym::TokenStream) else { return; };
-        let Some(token_stream) = tcx.type_of(token_stream_def_id).no_bound_vars() else { return; };
+        let Some(token_stream_def_id) = tcx.get_diagnostic_item(sym::TokenStream) else {
+            return;
+        };
+        let Some(token_stream) = tcx.type_of(token_stream_def_id).no_bound_vars() else {
+            return;
+        };
 
         let def_id = hir_id.expect_owner().def_id;
         let param_env = ty::ParamEnv::empty();
@@ -2116,10 +2120,10 @@ impl CheckAttrVisitor<'_> {
         let ocx = ObligationCtxt::new(&infcx);
 
         let span = tcx.def_span(def_id);
-        let fresh_substs = infcx.fresh_substs_for_item(span, def_id.to_def_id());
+        let fresh_args = infcx.fresh_args_for_item(span, def_id.to_def_id());
         let sig = tcx.liberate_late_bound_regions(
             def_id.to_def_id(),
-            tcx.fn_sig(def_id).subst(tcx, fresh_substs),
+            tcx.fn_sig(def_id).instantiate(tcx, fresh_args),
         );
 
         let mut cause = ObligationCause::misc(span, def_id);
diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs
index d5ac1cd9ce3..fbe6fc3bee4 100644
--- a/compiler/rustc_passes/src/dead.rs
+++ b/compiler/rustc_passes/src/dead.rs
@@ -276,7 +276,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
             }
 
             // Avoid accessing the HIR for the synthesized associated type generated for RPITITs.
-            if self.tcx.opt_rpitit_info(id.to_def_id()).is_some() {
+            if self.tcx.is_impl_trait_in_trait(id.to_def_id()) {
                 self.live_symbols.insert(id);
                 continue;
             }
@@ -304,7 +304,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
             if let Some(trait_of) = self.tcx.trait_id_of_impl(impl_of)
                 && self.tcx.has_attr(trait_of, sym::rustc_trivial_field_reads)
             {
-                let trait_ref = self.tcx.impl_trait_ref(impl_of).unwrap().subst_identity();
+                let trait_ref = self.tcx.impl_trait_ref(impl_of).unwrap().instantiate_identity();
                 if let ty::Adt(adt_def, _) = trait_ref.self_ty().kind()
                     && let Some(adt_def_id) = adt_def.did().as_local()
                 {
@@ -353,7 +353,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).subst_identity();
+                    let self_ty = self.tcx.type_of(item).instantiate_identity();
                     match *self_ty.kind() {
                         ty::Adt(def, _) => self.check_def_id(def.did()),
                         ty::Foreign(did) => self.check_def_id(did),
@@ -707,7 +707,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).subst_identity();
+        let field_type = self.tcx.type_of(field.did).instantiate_identity();
         if field_type.is_phantom_data() {
             return ShouldWarnAboutField::No;
         }
diff --git a/compiler/rustc_passes/src/layout_test.rs b/compiler/rustc_passes/src/layout_test.rs
index 098107f8f23..794dbda3688 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).subst_identity();
+    let ty = tcx.type_of(item_def_id).instantiate_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/liveness.rs b/compiler/rustc_passes/src/liveness.rs
index 803ca05b202..89c6704e416 100644
--- a/compiler/rustc_passes/src/liveness.rs
+++ b/compiler/rustc_passes/src/liveness.rs
@@ -747,7 +747,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
 
         let ty = self.typeck_results.node_type(hir_id);
         match ty.kind() {
-            ty::Closure(_def_id, substs) => match substs.as_closure().kind() {
+            ty::Closure(_def_id, args) => match args.as_closure().kind() {
                 ty::ClosureKind::Fn => {}
                 ty::ClosureKind::FnMut => {}
                 ty::ClosureKind::FnOnce => return succ,
@@ -1683,12 +1683,16 @@ impl<'tcx> Liveness<'_, 'tcx> {
         opt_body: Option<&hir::Body<'_>>,
     ) -> Vec<errors::UnusedVariableStringInterp> {
         let mut suggs = Vec::new();
-        let Some(opt_body) = opt_body else { return suggs; };
+        let Some(opt_body) = opt_body else {
+            return suggs;
+        };
         let mut visitor = CollectLitsVisitor { lit_exprs: vec![] };
         intravisit::walk_body(&mut visitor, opt_body);
         for lit_expr in visitor.lit_exprs {
             let hir::ExprKind::Lit(litx) = &lit_expr.kind else { continue };
-            let rustc_ast::LitKind::Str(syb, _) = litx.node else{ continue; };
+            let rustc_ast::LitKind::Str(syb, _) = litx.node else {
+                continue;
+            };
             let name_str: &str = syb.as_str();
             let name_pa = format!("{{{name}}}");
             if name_str.contains(&name_pa) {
diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs
index b81b7ad6013..25a3d38c144 100644
--- a/compiler/rustc_passes/src/stability.rs
+++ b/compiler/rustc_passes/src/stability.rs
@@ -856,7 +856,9 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> {
 /// See issue #94972 for details on why this is a special case
 fn is_unstable_reexport(tcx: TyCtxt<'_>, id: hir::HirId) -> bool {
     // Get the LocalDefId so we can lookup the item to check the kind.
-    let Some(owner) = id.as_owner() else { return false; };
+    let Some(owner) = id.as_owner() else {
+        return false;
+    };
     let def_id = owner.def_id;
 
     let Some(stab) = tcx.stability().local_stability(def_id) else {
diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs
index fe23506b878..e2827252509 100644
--- a/compiler/rustc_privacy/src/lib.rs
+++ b/compiler/rustc_privacy/src/lib.rs
@@ -28,7 +28,7 @@ use rustc_middle::hir::nested_filter;
 use rustc_middle::middle::privacy::{EffectiveVisibilities, EffectiveVisibility, Level};
 use rustc_middle::query::Providers;
 use rustc_middle::span_bug;
-use rustc_middle::ty::subst::InternalSubsts;
+use rustc_middle::ty::GenericArgs;
 use rustc_middle::ty::{self, Const, GenericParamDefKind};
 use rustc_middle::ty::{TraitRef, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor};
 use rustc_session::lint;
@@ -129,19 +129,19 @@ where
     V: DefIdVisitor<'tcx> + ?Sized,
 {
     fn visit_trait(&mut self, trait_ref: TraitRef<'tcx>) -> ControlFlow<V::BreakTy> {
-        let TraitRef { def_id, substs, .. } = trait_ref;
+        let TraitRef { def_id, args, .. } = trait_ref;
         self.def_id_visitor.visit_def_id(def_id, "trait", &trait_ref.print_only_trait_path())?;
-        if V::SHALLOW { ControlFlow::Continue(()) } else { substs.visit_with(self) }
+        if V::SHALLOW { ControlFlow::Continue(()) } else { args.visit_with(self) }
     }
 
     fn visit_projection_ty(&mut self, projection: ty::AliasTy<'tcx>) -> ControlFlow<V::BreakTy> {
         let tcx = self.def_id_visitor.tcx();
-        let (trait_ref, assoc_substs) = projection.trait_ref_and_own_substs(tcx);
+        let (trait_ref, assoc_args) = projection.trait_ref_and_own_args(tcx);
         self.visit_trait(trait_ref)?;
         if V::SHALLOW {
             ControlFlow::Continue(())
         } else {
-            assoc_substs.iter().try_for_each(|subst| subst.visit_with(self))
+            assoc_args.iter().try_for_each(|subst| subst.visit_with(self))
         }
     }
 
@@ -178,7 +178,7 @@ where
 
     fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<V::BreakTy> {
         let tcx = self.def_id_visitor.tcx();
-        // InternalSubsts are not visited here because they are visited below
+        // GenericArgs are not visited here because they are visited below
         // in `super_visit_with`.
         match *ty.kind() {
             ty::Adt(ty::AdtDef(Interned(&ty::AdtDefData { did: def_id, .. }, _)), ..)
@@ -194,16 +194,16 @@ where
                 // Something like `fn() -> Priv {my_func}` is considered a private type even if
                 // `my_func` is public, so we need to visit signatures.
                 if let ty::FnDef(..) = ty.kind() {
-                    // FIXME: this should probably use `substs` from `FnDef`
-                    tcx.fn_sig(def_id).subst_identity().visit_with(self)?;
+                    // FIXME: this should probably use `args` from `FnDef`
+                    tcx.fn_sig(def_id).instantiate_identity().visit_with(self)?;
                 }
-                // Inherent static methods don't have self type in substs.
+                // Inherent static methods don't have self type in args.
                 // Something like `fn() {my_method}` type of the method
                 // `impl Pub<Priv> { pub fn my_method() {} }` is considered a private type,
                 // 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).subst_identity().visit_with(self)?;
+                        tcx.type_of(impl_def_id).instantiate_identity().visit_with(self)?;
                     }
                 }
             }
@@ -219,7 +219,7 @@ where
                     // free type aliases, but this isn't done yet.
                     return ControlFlow::Continue(());
                 }
-                // This will also visit substs if necessary, so we don't need to recurse.
+                // This will also visit args if necessary, so we don't need to recurse.
                 return self.visit_projection_ty(proj);
             }
             ty::Alias(ty::Inherent, data) => {
@@ -238,11 +238,11 @@ where
                     &LazyDefPathStr { def_id: data.def_id, tcx },
                 )?;
 
-                // This will also visit substs if necessary, so we don't need to recurse.
+                // This will also visit args if necessary, so we don't need to recurse.
                 return if V::SHALLOW {
                     ControlFlow::Continue(())
                 } else {
-                    data.substs.iter().try_for_each(|subst| subst.visit_with(self))
+                    data.args.iter().try_for_each(|subst| subst.visit_with(self))
                 };
             }
             ty::Dynamic(predicates, ..) => {
@@ -253,10 +253,10 @@ where
                         ty::ExistentialPredicate::Trait(trait_ref) => trait_ref,
                         ty::ExistentialPredicate::Projection(proj) => proj.trait_ref(tcx),
                         ty::ExistentialPredicate::AutoTrait(def_id) => {
-                            ty::ExistentialTraitRef { def_id, substs: InternalSubsts::empty() }
+                            ty::ExistentialTraitRef { def_id, args: GenericArgs::empty() }
                         }
                     };
-                    let ty::ExistentialTraitRef { def_id, substs: _ } = trait_ref;
+                    let ty::ExistentialTraitRef { def_id, args: _ } = trait_ref;
                     self.def_id_visitor.visit_def_id(def_id, "trait", &trait_ref)?;
                 }
             }
@@ -357,9 +357,9 @@ trait VisibilityLike: Sized {
         effective_visibilities: &EffectiveVisibilities,
     ) -> Self {
         let mut find = FindMin::<_, SHALLOW> { tcx, effective_visibilities, min: Self::MAX };
-        find.visit(tcx.type_of(def_id).subst_identity());
+        find.visit(tcx.type_of(def_id).instantiate_identity());
         if let Some(trait_ref) = tcx.impl_trait_ref(def_id) {
-            find.visit_trait(trait_ref.subst_identity());
+            find.visit_trait(trait_ref.instantiate_identity());
         }
         find.min
     }
@@ -727,7 +727,7 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> {
                 // Type inference is very smart sometimes. It can make an impl reachable even some
                 // components of its type or trait are unreachable. E.g. methods of
                 // `impl ReachableTrait<UnreachableTy> for ReachableTy<UnreachableTy> { ... }`
-                // can be usable from other crates (#57264). So we skip substs when calculating
+                // can be usable from other crates (#57264). So we skip args when calculating
                 // reachability and consider an impl reachable if its "shallow" type and trait are
                 // reachable.
                 //
@@ -823,13 +823,15 @@ impl ReachEverythingInTheInterfaceVisitor<'_, '_> {
                 GenericParamDefKind::Lifetime => {}
                 GenericParamDefKind::Type { has_default, .. } => {
                     if has_default {
-                        self.visit(self.ev.tcx.type_of(param.def_id).subst_identity());
+                        self.visit(self.ev.tcx.type_of(param.def_id).instantiate_identity());
                     }
                 }
                 GenericParamDefKind::Const { has_default } => {
-                    self.visit(self.ev.tcx.type_of(param.def_id).subst_identity());
+                    self.visit(self.ev.tcx.type_of(param.def_id).instantiate_identity());
                     if has_default {
-                        self.visit(self.ev.tcx.const_param_default(param.def_id).subst_identity());
+                        self.visit(
+                            self.ev.tcx.const_param_default(param.def_id).instantiate_identity(),
+                        );
                     }
                 }
             }
@@ -843,13 +845,13 @@ impl ReachEverythingInTheInterfaceVisitor<'_, '_> {
     }
 
     fn ty(&mut self) -> &mut Self {
-        self.visit(self.ev.tcx.type_of(self.item_def_id).subst_identity());
+        self.visit(self.ev.tcx.type_of(self.item_def_id).instantiate_identity());
         self
     }
 
     fn trait_ref(&mut self) -> &mut Self {
         if let Some(trait_ref) = self.ev.tcx.impl_trait_ref(self.item_def_id) {
-            self.visit_trait(trait_ref.subst_identity());
+            self.visit_trait(trait_ref.instantiate_identity());
         }
         self
     }
@@ -1124,7 +1126,7 @@ impl<'tcx> TypePrivacyVisitor<'tcx> {
         let typeck_results = self.typeck_results();
         let result: ControlFlow<()> = try {
             self.visit(typeck_results.node_type(id))?;
-            self.visit(typeck_results.node_substs(id))?;
+            self.visit(typeck_results.node_args(id))?;
             if let Some(adjustments) = typeck_results.adjustments().get(id) {
                 adjustments.iter().try_for_each(|adjustment| self.visit(adjustment.target))?;
             }
@@ -1259,7 +1261,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).subst_identity()).is_break() {
+                    if self.visit(self.tcx.type_of(def_id).instantiate_identity()).is_break() {
                         return;
                     }
                 } else {
@@ -1736,12 +1738,12 @@ impl SearchInterfaceForPrivateItemsVisitor<'_> {
                 GenericParamDefKind::Lifetime => {}
                 GenericParamDefKind::Type { has_default, .. } => {
                     if has_default {
-                        self.visit(self.tcx.type_of(param.def_id).subst_identity());
+                        self.visit(self.tcx.type_of(param.def_id).instantiate_identity());
                     }
                 }
                 // FIXME(generic_const_exprs): May want to look inside const here
                 GenericParamDefKind::Const { .. } => {
-                    self.visit(self.tcx.type_of(param.def_id).subst_identity());
+                    self.visit(self.tcx.type_of(param.def_id).instantiate_identity());
                 }
             }
         }
@@ -1768,7 +1770,7 @@ impl SearchInterfaceForPrivateItemsVisitor<'_> {
 
     fn ty(&mut self) -> &mut Self {
         self.in_primary_interface = true;
-        self.visit(self.tcx.type_of(self.item_def_id).subst_identity());
+        self.visit(self.tcx.type_of(self.item_def_id).instantiate_identity());
         self
     }
 
diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs
index d37fe783bba..526fc9c3aa5 100644
--- a/compiler/rustc_resolve/src/imports.rs
+++ b/compiler/rustc_resolve/src/imports.rs
@@ -1300,9 +1300,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         let ImportKind::Glob { id, is_prelude, .. } = import.kind else { unreachable!() };
 
         let ModuleOrUniformRoot::Module(module) = import.imported_module.get().unwrap() else {
-            self.tcx.sess.create_err(CannotGlobImportAllCrates {
-                span: import.span,
-            }).emit();
+            self.tcx.sess.create_err(CannotGlobImportAllCrates { span: import.span }).emit();
             return;
         };
 
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index f6c7aecf8b0..846a1ffe09b 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -1361,7 +1361,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
 
     fn visit_generic_params(&mut self, params: &'ast [GenericParam], add_self_upper: bool) {
         // For type parameter defaults, we have to ban access
-        // to following type parameters, as the InternalSubsts can only
+        // to following type parameters, as the GenericArgs can only
         // provide previous type parameters as they're built. We
         // put all the parameters on the ban list and then remove
         // them one by one as they are processed and become available.
@@ -2460,8 +2460,11 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
         F: FnOnce(&mut Self),
     {
         debug!("with_generic_param_rib");
-        let LifetimeRibKind::Generics { binder, span: generics_span, kind: generics_kind, .. }
-            = lifetime_kind else { panic!() };
+        let LifetimeRibKind::Generics { binder, span: generics_span, kind: generics_kind, .. } =
+            lifetime_kind
+        else {
+            panic!()
+        };
 
         let mut function_type_rib = Rib::new(kind);
         let mut function_value_rib = Rib::new(kind);
@@ -2972,7 +2975,9 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
         F: FnOnce(Ident, String, Option<Symbol>) -> ResolutionError<'a>,
     {
         // If there is a TraitRef in scope for an impl, then the method must be in the trait.
-        let Some((module, _)) = self.current_trait_ref else { return; };
+        let Some((module, _)) = self.current_trait_ref else {
+            return;
+        };
         ident.span.normalize_to_macros_2_0_and_adjust(module.expansion);
         let key = BindingKey::new(ident, ns);
         let mut binding = self.r.resolution(module, key).try_borrow().ok().and_then(|r| r.binding);
@@ -3917,11 +3922,15 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
             };
             if res == unqualified_result {
                 let lint = lint::builtin::UNUSED_QUALIFICATIONS;
-                self.r.lint_buffer.buffer_lint(
+                self.r.lint_buffer.buffer_lint_with_diagnostic(
                     lint,
                     finalize.node_id,
                     finalize.path_span,
                     "unnecessary qualification",
+                    lint::BuiltinLintDiagnostics::UnusedQualifications {
+                        path_span: finalize.path_span,
+                        unqualified_path: path.last().unwrap().ident
+                    }
                 )
             }
         }
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index 78ef72a7e34..753a1adc66d 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -446,20 +446,29 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
         err: &mut Diagnostic,
         base_error: &BaseError,
     ) {
-        let Some(ty) = self.diagnostic_metadata.current_type_path else { return; };
-        let TyKind::Path(_, path) = &ty.kind else { return; };
+        let Some(ty) = self.diagnostic_metadata.current_type_path else {
+            return;
+        };
+        let TyKind::Path(_, path) = &ty.kind else {
+            return;
+        };
         for segment in &path.segments {
-            let Some(params) = &segment.args else { continue; };
-            let ast::GenericArgs::AngleBracketed(ref params) = params.deref() else { continue; };
+            let Some(params) = &segment.args else {
+                continue;
+            };
+            let ast::GenericArgs::AngleBracketed(ref params) = params.deref() else {
+                continue;
+            };
             for param in &params.args {
-                let ast::AngleBracketedArg::Constraint(constraint) = param else { continue; };
+                let ast::AngleBracketedArg::Constraint(constraint) = param else {
+                    continue;
+                };
                 let ast::AssocConstraintKind::Bound { bounds } = &constraint.kind else {
                     continue;
                 };
                 for bound in bounds {
-                    let ast::GenericBound::Trait(trait_ref, ast::TraitBoundModifier::None)
-                        = bound else
-                    {
+                    let ast::GenericBound::Trait(trait_ref, ast::TraitBoundModifier::None) = bound
+                    else {
                         continue;
                     };
                     if base_error.span == trait_ref.span {
@@ -1148,7 +1157,11 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
                     &poly_trait_ref.trait_ref.path.segments[..]
                 {
                     if ident.span == span {
-                        let Some(new_where_bound_predicate) = mk_where_bound_predicate(path, poly_trait_ref, ty) else { return false; };
+                        let Some(new_where_bound_predicate) =
+                            mk_where_bound_predicate(path, poly_trait_ref, ty)
+                        else {
+                            return false;
+                        };
                         err.span_suggestion_verbose(
                             *where_span,
                             format!("constrain the associated type to `{}`", ident),
@@ -1831,7 +1844,8 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
             None,
         ) {
             Some(found) => {
-                let Some(sugg) = names.into_iter().find(|suggestion| suggestion.candidate == found) else {
+                let Some(sugg) = names.into_iter().find(|suggestion| suggestion.candidate == found)
+                else {
                     return TypoCandidate::None;
                 };
                 if found == name {
@@ -2677,7 +2691,9 @@ fn mk_where_bound_predicate(
     use rustc_span::DUMMY_SP;
     let modified_segments = {
         let mut segments = path.segments.clone();
-        let [preceding @ .., second_last, last] = segments.as_mut_slice() else { return None; };
+        let [preceding @ .., second_last, last] = segments.as_mut_slice() else {
+            return None;
+        };
         let mut segments = ThinVec::from(preceding);
 
         let added_constraint = ast::AngleBracketedArg::Constraint(ast::AssocConstraint {
diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs
index da3d86a4718..faa672db59c 100644
--- a/compiler/rustc_resolve/src/lib.rs
+++ b/compiler/rustc_resolve/src/lib.rs
@@ -1871,7 +1871,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
             } else {
                 let crate_id = if finalize {
                     let Some(crate_id) =
-                        self.crate_loader(|c| c.process_path_extern(ident.name, ident.span)) else { return Some(self.dummy_binding); };
+                        self.crate_loader(|c| c.process_path_extern(ident.name, ident.span))
+                    else {
+                        return Some(self.dummy_binding);
+                    };
                     crate_id
                 } else {
                     self.crate_loader(|c| c.maybe_process_path_extern(ident.name))?
diff --git a/compiler/rustc_smir/src/lib.rs b/compiler/rustc_smir/src/lib.rs
index 8450bb73119..6ebba56c76d 100644
--- a/compiler/rustc_smir/src/lib.rs
+++ b/compiler/rustc_smir/src/lib.rs
@@ -1,6 +1,6 @@
 //! The WIP stable interface to rustc internals.
 //!
-//! For more information see https://github.com/rust-lang/project-stable-mir
+//! For more information see <https://github.com/rust-lang/project-stable-mir>
 //!
 //! # Note
 //!
@@ -14,6 +14,7 @@
 #![feature(local_key_cell_methods)]
 #![feature(ptr_metadata)]
 #![feature(type_alias_impl_trait)] // Used to define opaque types.
+#![feature(intra_doc_pointers)]
 
 // Declare extern rustc_* crates to enable building this crate separately from the compiler.
 #[cfg(not(feature = "default"))]
diff --git a/compiler/rustc_smir/src/rustc_internal/mod.rs b/compiler/rustc_smir/src/rustc_internal/mod.rs
index 87e0b211556..527d5220564 100644
--- a/compiler/rustc_smir/src/rustc_internal/mod.rs
+++ b/compiler/rustc_smir/src/rustc_internal/mod.rs
@@ -27,21 +27,33 @@ pub fn crate_item(did: DefId) -> stable_mir::CrateItem {
     with_tables(|t| t.crate_item(did))
 }
 
+pub fn adt_def(did: DefId) -> stable_mir::ty::AdtDef {
+    with_tables(|t| t.adt_def(did))
+}
+
 impl<'tcx> Tables<'tcx> {
     pub fn item_def_id(&self, item: &stable_mir::CrateItem) -> DefId {
         self.def_ids[item.0]
     }
 
     pub fn crate_item(&mut self, did: DefId) -> stable_mir::CrateItem {
+        stable_mir::CrateItem(self.create_def_id(did))
+    }
+
+    pub fn adt_def(&mut self, did: DefId) -> stable_mir::ty::AdtDef {
+        stable_mir::ty::AdtDef(self.create_def_id(did))
+    }
+
+    fn create_def_id(&mut self, did: DefId) -> stable_mir::DefId {
         // FIXME: this becomes inefficient when we have too many ids
         for (i, &d) in self.def_ids.iter().enumerate() {
             if d == did {
-                return stable_mir::CrateItem(i);
+                return i;
             }
         }
         let id = self.def_ids.len();
         self.def_ids.push(did);
-        stable_mir::CrateItem(id)
+        id
     }
 }
 
diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs
index f22c620021e..6af6cfe58f1 100644
--- a/compiler/rustc_smir/src/rustc_smir/mod.rs
+++ b/compiler/rustc_smir/src/rustc_smir/mod.rs
@@ -8,7 +8,7 @@
 //! For now, we are developing everything inside `rustc`, thus, we keep this module private.
 
 use crate::rustc_internal::{self, opaque};
-use crate::stable_mir::ty::{FloatTy, IntTy, RigidTy, TyKind, UintTy};
+use crate::stable_mir::ty::{AdtSubsts, FloatTy, GenericArgKind, IntTy, RigidTy, TyKind, UintTy};
 use crate::stable_mir::{self, Context};
 use rustc_middle::mir;
 use rustc_middle::ty::{self, Ty, TyCtxt};
@@ -94,21 +94,38 @@ impl<'tcx> Tables<'tcx> {
                 ty::FloatTy::F32 => TyKind::RigidTy(RigidTy::Float(FloatTy::F32)),
                 ty::FloatTy::F64 => TyKind::RigidTy(RigidTy::Float(FloatTy::F64)),
             },
-            ty::Adt(_, _) => todo!(),
+            ty::Adt(adt_def, substs) => TyKind::RigidTy(RigidTy::Adt(
+                rustc_internal::adt_def(adt_def.did()),
+                AdtSubsts(
+                    substs
+                        .iter()
+                        .map(|arg| match arg.unpack() {
+                            ty::GenericArgKind::Lifetime(region) => {
+                                GenericArgKind::Lifetime(opaque(&region))
+                            }
+                            ty::GenericArgKind::Type(ty) => {
+                                GenericArgKind::Type(self.intern_ty(ty))
+                            }
+                            ty::GenericArgKind::Const(const_) => {
+                                GenericArgKind::Const(opaque(&const_))
+                            }
+                        })
+                        .collect(),
+                ),
+            )),
             ty::Foreign(_) => todo!(),
-            ty::Str => todo!(),
-            ty::Array(_, _) => todo!(),
-            ty::Slice(_) => todo!(),
+            ty::Str => TyKind::RigidTy(RigidTy::Str),
+            ty::Array(ty, constant) => {
+                TyKind::RigidTy(RigidTy::Array(self.intern_ty(*ty), opaque(constant)))
+            }
+            ty::Slice(ty) => TyKind::RigidTy(RigidTy::Slice(self.intern_ty(*ty))),
             ty::RawPtr(_) => todo!(),
             ty::Ref(_, _, _) => todo!(),
             ty::FnDef(_, _) => todo!(),
             ty::FnPtr(_) => todo!(),
-            ty::Placeholder(..) => todo!(),
             ty::Dynamic(_, _, _) => todo!(),
             ty::Closure(_, _) => todo!(),
             ty::Generator(_, _, _) => todo!(),
-            ty::GeneratorWitness(_) => todo!(),
-            ty::GeneratorWitnessMIR(_, _) => todo!(),
             ty::Never => todo!(),
             ty::Tuple(fields) => TyKind::RigidTy(RigidTy::Tuple(
                 fields.iter().map(|ty| self.intern_ty(ty)).collect(),
@@ -116,8 +133,13 @@ impl<'tcx> Tables<'tcx> {
             ty::Alias(_, _) => todo!(),
             ty::Param(_) => todo!(),
             ty::Bound(_, _) => todo!(),
-            ty::Infer(_) => todo!(),
-            ty::Error(_) => todo!(),
+            ty::Placeholder(..)
+            | ty::GeneratorWitness(_)
+            | ty::GeneratorWitnessMIR(_, _)
+            | ty::Infer(_)
+            | ty::Error(_) => {
+                unreachable!();
+            }
         }
     }
 
@@ -147,13 +169,6 @@ pub(crate) trait Stable {
     fn stable(&self) -> Self::T;
 }
 
-impl Stable for DefId {
-    type T = stable_mir::CrateItem;
-    fn stable(&self) -> Self::T {
-        rustc_internal::crate_item(*self)
-    }
-}
-
 impl<'tcx> Stable for mir::Statement<'tcx> {
     type T = stable_mir::mir::Statement;
     fn stable(&self) -> Self::T {
@@ -188,7 +203,9 @@ impl<'tcx> Stable for mir::Rvalue<'tcx> {
             Ref(region, kind, place) => {
                 stable_mir::mir::Rvalue::Ref(opaque(region), kind.stable(), place.stable())
             }
-            ThreadLocalRef(def_id) => stable_mir::mir::Rvalue::ThreadLocalRef(def_id.stable()),
+            ThreadLocalRef(def_id) => {
+                stable_mir::mir::Rvalue::ThreadLocalRef(rustc_internal::crate_item(*def_id))
+            }
             AddressOf(mutability, place) => {
                 stable_mir::mir::Rvalue::AddressOf(mutability.stable(), place.stable())
             }
diff --git a/compiler/rustc_smir/src/stable_mir/mir/body.rs b/compiler/rustc_smir/src/stable_mir/mir/body.rs
index fa3b0d6c559..02ac907f09a 100644
--- a/compiler/rustc_smir/src/stable_mir/mir/body.rs
+++ b/compiler/rustc_smir/src/stable_mir/mir/body.rs
@@ -185,9 +185,9 @@ pub enum Rvalue {
     /// [#91095]. Note too that the value of the discriminant is not the same thing as the
     /// variant index; use [`discriminant_for_variant`] to convert.
     ///
-    /// [`discriminant_ty`]: crate::ty::Ty::discriminant_ty
+    /// [`discriminant_ty`]: rustc_middle::ty::Ty::discriminant_ty
     /// [#91095]: https://github.com/rust-lang/rust/issues/91095
-    /// [`discriminant_for_variant`]: crate::ty::Ty::discriminant_for_variant
+    /// [`discriminant_for_variant`]: rustc_middle::ty::Ty::discriminant_for_variant
     Discriminant(Place),
 
     /// Yields the length of the place, as a `usize`.
diff --git a/compiler/rustc_smir/src/stable_mir/ty.rs b/compiler/rustc_smir/src/stable_mir/ty.rs
index 3181af46e9c..e9f17f92c04 100644
--- a/compiler/rustc_smir/src/stable_mir/ty.rs
+++ b/compiler/rustc_smir/src/stable_mir/ty.rs
@@ -1,4 +1,5 @@
-use super::with;
+use super::{with, DefId};
+use crate::rustc_internal::Opaque;
 
 #[derive(Copy, Clone, Debug)]
 pub struct Ty(pub usize);
@@ -9,6 +10,9 @@ impl Ty {
     }
 }
 
+type Const = Opaque;
+type Region = Opaque;
+
 #[derive(Clone, Debug)]
 pub enum TyKind {
     RigidTy(RigidTy),
@@ -21,6 +25,10 @@ pub enum RigidTy {
     Int(IntTy),
     Uint(UintTy),
     Float(FloatTy),
+    Adt(AdtDef, AdtSubsts),
+    Str,
+    Array(Ty, Const),
+    Slice(Ty),
     Tuple(Vec<Ty>),
 }
 
@@ -49,3 +57,18 @@ pub enum FloatTy {
     F32,
     F64,
 }
+
+#[derive(Clone, PartialEq, Eq, Debug)]
+pub struct AdtDef(pub(crate) DefId);
+
+#[derive(Clone, Debug)]
+pub struct AdtSubsts(pub Vec<GenericArgKind>);
+
+#[derive(Clone, Debug)]
+pub enum GenericArgKind {
+    // FIXME add proper region
+    Lifetime(Region),
+    Type(Ty),
+    // FIXME add proper const
+    Const(Const),
+}
diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs
index 3bb9c4920c4..5c56337d1e0 100644
--- a/compiler/rustc_span/src/lib.rs
+++ b/compiler/rustc_span/src/lib.rs
@@ -2159,7 +2159,8 @@ where
         // If this is not an empty or invalid span, we want to hash the last
         // position that belongs to it, as opposed to hashing the first
         // position past it.
-        let Some((file, line_lo, col_lo, line_hi, col_hi)) = ctx.span_data_to_lines_and_cols(&span) else {
+        let Some((file, line_lo, col_lo, line_hi, col_hi)) = ctx.span_data_to_lines_and_cols(&span)
+        else {
             Hash::hash(&TAG_INVALID_SPAN, hasher);
             return;
         };
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index d655276a991..4fc440ef947 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -1280,7 +1280,7 @@ symbols! {
         rustc_dummy,
         rustc_dump_env_program_clauses,
         rustc_dump_program_clauses,
-        rustc_dump_user_substs,
+        rustc_dump_user_args,
         rustc_dump_vtable,
         rustc_effective_visibility,
         rustc_error,
diff --git a/compiler/rustc_symbol_mangling/src/legacy.rs b/compiler/rustc_symbol_mangling/src/legacy.rs
index ec7032cd3bf..3a33568084c 100644
--- a/compiler/rustc_symbol_mangling/src/legacy.rs
+++ b/compiler/rustc_symbol_mangling/src/legacy.rs
@@ -2,8 +2,8 @@ use rustc_data_structures::stable_hasher::{Hash64, HashStable, StableHasher};
 use rustc_hir::def_id::CrateNum;
 use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData};
 use rustc_middle::ty::print::{PrettyPrinter, Print, Printer};
-use rustc_middle::ty::subst::{GenericArg, GenericArgKind};
 use rustc_middle::ty::{self, Instance, Ty, TyCtxt, TypeVisitableExt};
+use rustc_middle::ty::{GenericArg, GenericArgKind};
 use rustc_middle::util::common::record_time;
 
 use std::fmt::{self, Write};
@@ -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).subst_identity();
+                instance_ty = tcx.type_of(ty_def_id).instantiate_identity();
                 debug!(?instance_ty);
                 break;
             }
@@ -58,7 +58,7 @@ pub(super) fn mangle<'tcx>(
             def_id,
             if let ty::InstanceDef::DropGlue(_, _) = instance.def {
                 // Add the name of the dropped type to the symbol name
-                &*instance.substs
+                &*instance.args
             } else {
                 &[]
             },
@@ -95,8 +95,8 @@ fn get_symbol_hash<'tcx>(
     instantiating_crate: Option<CrateNum>,
 ) -> Hash64 {
     let def_id = instance.def_id();
-    let substs = instance.substs;
-    debug!("get_symbol_hash(def_id={:?}, parameters={:?})", def_id, substs);
+    let args = instance.args;
+    debug!("get_symbol_hash(def_id={:?}, parameters={:?})", def_id, args);
 
     tcx.with_stable_hashing_context(|mut hcx| {
         let mut hasher = StableHasher::new();
@@ -122,7 +122,7 @@ fn get_symbol_hash<'tcx>(
                 }
 
                 // also include any type parameters (for generic items)
-                substs.hash_stable(hcx, &mut hasher);
+                args.hash_stable(hcx, &mut hasher);
 
                 if let Some(instantiating_crate) = instantiating_crate {
                     tcx.def_path_hash(instantiating_crate.as_def_id())
@@ -219,10 +219,10 @@ impl<'tcx> Printer<'tcx> for &mut SymbolPrinter<'tcx> {
     fn print_type(mut self, ty: Ty<'tcx>) -> Result<Self::Type, Self::Error> {
         match *ty.kind() {
             // Print all nominal types as paths (unlike `pretty_print_type`).
-            ty::FnDef(def_id, substs)
-            | ty::Alias(ty::Projection | ty::Opaque, ty::AliasTy { def_id, substs, .. })
-            | ty::Closure(def_id, substs)
-            | ty::Generator(def_id, substs, _) => self.print_def_path(def_id, substs),
+            ty::FnDef(def_id, args)
+            | ty::Alias(ty::Projection | ty::Opaque, ty::AliasTy { def_id, args, .. })
+            | ty::Closure(def_id, args)
+            | ty::Generator(def_id, args, _) => self.print_def_path(def_id, args),
 
             // The `pretty_print_type` formatting of array size depends on
             // -Zverbose flag, so we cannot reuse it here.
diff --git a/compiler/rustc_symbol_mangling/src/lib.rs b/compiler/rustc_symbol_mangling/src/lib.rs
index 692542da78e..22fd1f09f3a 100644
--- a/compiler/rustc_symbol_mangling/src/lib.rs
+++ b/compiler/rustc_symbol_mangling/src/lib.rs
@@ -108,7 +108,7 @@ use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;
 use rustc_middle::mir::mono::{InstantiationMode, MonoItem};
 use rustc_middle::query::Providers;
-use rustc_middle::ty::subst::SubstsRef;
+use rustc_middle::ty::GenericArgsRef;
 use rustc_middle::ty::{self, Instance, TyCtxt};
 use rustc_session::config::SymbolManglingVersion;
 
@@ -144,7 +144,7 @@ fn symbol_name_provider<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> ty
         // This closure determines the instantiating crate for instances that
         // need an instantiating-crate-suffix for their symbol name, in order
         // to differentiate between local copies.
-        if is_generic(instance.substs) {
+        if is_generic(instance.args) {
             // For generics we might find re-usable upstream instances. If there
             // is one, we rely on the symbol being instantiated locally.
             instance.upstream_monomorphization(tcx).unwrap_or(LOCAL_CRATE)
@@ -174,9 +174,9 @@ fn compute_symbol_name<'tcx>(
     compute_instantiating_crate: impl FnOnce() -> CrateNum,
 ) -> String {
     let def_id = instance.def_id();
-    let substs = instance.substs;
+    let args = instance.args;
 
-    debug!("symbol_name(def_id={:?}, substs={:?})", def_id, substs);
+    debug!("symbol_name(def_id={:?}, args={:?})", def_id, args);
 
     if let Some(def_id) = def_id.as_local() {
         if tcx.proc_macro_decls_static(()) == Some(def_id) {
@@ -246,7 +246,7 @@ fn compute_symbol_name<'tcx>(
     // the ID of the instantiating crate. This avoids symbol conflicts
     // in case the same instances is emitted in two crates of the same
     // project.
-    let avoid_cross_crate_conflicts = is_generic(substs) || is_globally_shared_function;
+    let avoid_cross_crate_conflicts = is_generic(args) || is_globally_shared_function;
 
     let instantiating_crate = avoid_cross_crate_conflicts.then(compute_instantiating_crate);
 
@@ -278,6 +278,6 @@ fn compute_symbol_name<'tcx>(
     symbol
 }
 
-fn is_generic(substs: SubstsRef<'_>) -> bool {
-    substs.non_erasable_generics().next().is_some()
+fn is_generic(args: GenericArgsRef<'_>) -> bool {
+    args.non_erasable_generics().next().is_some()
 }
diff --git a/compiler/rustc_symbol_mangling/src/test.rs b/compiler/rustc_symbol_mangling/src/test.rs
index 985b2210745..eddfd0df318 100644
--- a/compiler/rustc_symbol_mangling/src/test.rs
+++ b/compiler/rustc_symbol_mangling/src/test.rs
@@ -7,7 +7,7 @@
 use crate::errors::{Kind, TestOutput};
 use rustc_hir::def_id::LocalDefId;
 use rustc_middle::ty::print::with_no_trimmed_paths;
-use rustc_middle::ty::{subst::InternalSubsts, Instance, TyCtxt};
+use rustc_middle::ty::{GenericArgs, Instance, TyCtxt};
 use rustc_span::symbol::{sym, Symbol};
 
 const SYMBOL_NAME: Symbol = sym::rustc_symbol_name;
@@ -57,7 +57,7 @@ impl SymbolNamesTest<'_> {
             let def_id = def_id.to_def_id();
             let instance = Instance::new(
                 def_id,
-                tcx.erase_regions(InternalSubsts::identity_for_item(tcx, def_id)),
+                tcx.erase_regions(GenericArgs::identity_for_item(tcx, def_id)),
             );
             let mangled = tcx.symbol_name(instance);
             tcx.sess.emit_err(TestOutput {
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 3b46275ec41..4a938ff938a 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
@@ -11,11 +11,11 @@ use core::fmt::Display;
 use rustc_data_structures::base_n;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_hir as hir;
-use rustc_middle::ty::subst::{GenericArg, GenericArgKind, SubstsRef};
 use rustc_middle::ty::{
     self, Const, ExistentialPredicate, FloatTy, FnSig, Instance, IntTy, List, Region, RegionKind,
     TermKind, Ty, TyCtxt, UintTy,
 };
+use rustc_middle::ty::{GenericArg, GenericArgKind, GenericArgsRef};
 use rustc_span::def_id::DefId;
 use rustc_span::sym;
 use rustc_target::abi::call::{Conv, FnAbi};
@@ -212,12 +212,12 @@ fn encode_predicate<'tcx>(
         ty::ExistentialPredicate::Trait(trait_ref) => {
             let name = encode_ty_name(tcx, trait_ref.def_id);
             let _ = write!(s, "u{}{}", name.len(), &name);
-            s.push_str(&encode_substs(tcx, trait_ref.substs, dict, options));
+            s.push_str(&encode_args(tcx, trait_ref.args, dict, options));
         }
         ty::ExistentialPredicate::Projection(projection) => {
             let name = encode_ty_name(tcx, projection.def_id);
             let _ = write!(s, "u{}{}", name.len(), &name);
-            s.push_str(&encode_substs(tcx, projection.substs, dict, options));
+            s.push_str(&encode_args(tcx, projection.args, dict, options));
             match projection.term.unpack() {
                 TermKind::Ty(ty) => s.push_str(&encode_ty(tcx, ty, dict, options)),
                 TermKind::Const(c) => s.push_str(&encode_const(tcx, c, dict, options)),
@@ -286,21 +286,21 @@ fn encode_region<'tcx>(
     s
 }
 
-/// Encodes substs using the Itanium C++ ABI with vendor extended type qualifiers and types for Rust
+/// Encodes args using the Itanium C++ ABI with vendor extended type qualifiers and types for Rust
 /// types that are not used at the FFI boundary.
-fn encode_substs<'tcx>(
+fn encode_args<'tcx>(
     tcx: TyCtxt<'tcx>,
-    substs: SubstsRef<'tcx>,
+    args: GenericArgsRef<'tcx>,
     dict: &mut FxHashMap<DictKey<'tcx>, usize>,
     options: EncodeTyOptions,
 ) -> String {
     // [I<subst1..substN>E] as part of vendor extended type
     let mut s = String::new();
-    let substs: Vec<GenericArg<'_>> = substs.iter().collect();
-    if !substs.is_empty() {
+    let args: Vec<GenericArg<'_>> = args.iter().collect();
+    if !args.is_empty() {
         s.push('I');
-        for subst in substs {
-            match subst.unpack() {
+        for arg in args {
+            match arg.unpack() {
                 GenericArgKind::Lifetime(region) => {
                     s.push_str(&encode_region(tcx, region, dict, options));
                 }
@@ -524,7 +524,7 @@ fn encode_ty<'tcx>(
         }
 
         // User-defined types
-        ty::Adt(adt_def, substs) => {
+        ty::Adt(adt_def, args) => {
             let mut s = String::new();
             let def_id = adt_def.did();
             if let Some(cfi_encoding) = tcx.get_attr(def_id, sym::cfi_encoding) {
@@ -570,7 +570,7 @@ fn encode_ty<'tcx>(
                 // <subst>, as vendor extended type.
                 let name = encode_ty_name(tcx, def_id);
                 let _ = write!(s, "u{}{}", name.len(), &name);
-                s.push_str(&encode_substs(tcx, substs, dict, options));
+                s.push_str(&encode_args(tcx, args, dict, options));
                 compress(dict, DictKey::Ty(ty, TyQ::None), &mut s);
             }
             typeid.push_str(&s);
@@ -608,27 +608,27 @@ fn encode_ty<'tcx>(
         }
 
         // Function types
-        ty::FnDef(def_id, substs) | ty::Closure(def_id, substs) => {
+        ty::FnDef(def_id, args) | ty::Closure(def_id, args) => {
             // u<length><name>[I<element-type1..element-typeN>E], where <element-type> is <subst>,
             // as vendor extended type.
             let mut s = String::new();
             let name = encode_ty_name(tcx, *def_id);
             let _ = write!(s, "u{}{}", name.len(), &name);
-            s.push_str(&encode_substs(tcx, substs, dict, options));
+            s.push_str(&encode_args(tcx, args, dict, options));
             compress(dict, DictKey::Ty(ty, TyQ::None), &mut s);
             typeid.push_str(&s);
         }
 
-        ty::Generator(def_id, substs, ..) => {
+        ty::Generator(def_id, args, ..) => {
             // u<length><name>[I<element-type1..element-typeN>E], where <element-type> is <subst>,
             // as vendor extended type.
             let mut s = String::new();
             let name = encode_ty_name(tcx, *def_id);
             let _ = write!(s, "u{}{}", name.len(), &name);
-            // Encode parent substs only
-            s.push_str(&encode_substs(
+            // Encode parent args only
+            s.push_str(&encode_args(
                 tcx,
-                tcx.mk_substs(substs.as_generator().parent_substs()),
+                tcx.mk_args(args.as_generator().parent_args()),
                 dict,
                 options,
             ));
@@ -732,18 +732,18 @@ fn transform_predicates<'tcx>(
     tcx.mk_poly_existential_predicates(&predicates)
 }
 
-/// Transforms substs for being encoded and used in the substitution dictionary.
-fn transform_substs<'tcx>(
+/// Transforms args for being encoded and used in the substitution dictionary.
+fn transform_args<'tcx>(
     tcx: TyCtxt<'tcx>,
-    substs: SubstsRef<'tcx>,
+    args: GenericArgsRef<'tcx>,
     options: TransformTyOptions,
-) -> SubstsRef<'tcx> {
-    let substs = substs.iter().map(|subst| match subst.unpack() {
+) -> GenericArgsRef<'tcx> {
+    let args = args.iter().map(|arg| match arg.unpack() {
         GenericArgKind::Type(ty) if ty.is_c_void(tcx) => Ty::new_unit(tcx).into(),
         GenericArgKind::Type(ty) => transform_ty(tcx, ty, options).into(),
-        _ => subst,
+        _ => arg,
     });
-    tcx.mk_substs_from_iter(substs)
+    tcx.mk_args_from_iter(args)
 }
 
 // Transforms a ty:Ty for being encoded and used in the substitution dictionary. It transforms all
@@ -825,7 +825,7 @@ fn transform_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, options: TransformTyOptio
             ty = Ty::new_slice(tcx, transform_ty(tcx, *ty0, options));
         }
 
-        ty::Adt(adt_def, substs) => {
+        ty::Adt(adt_def, args) => {
             if ty.is_c_void(tcx) {
                 ty = Ty::new_unit(tcx);
             } else if options.contains(TransformTyOptions::GENERALIZE_REPR_C) && adt_def.repr().c()
@@ -840,13 +840,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).subst_identity();
+                    let ty = tcx.type_of(field.did).instantiate_identity();
                     let is_zst =
                         tcx.layout_of(param_env.and(ty)).is_ok_and(|layout| layout.is_zst());
                     !is_zst
                 });
                 if let Some(field) = field {
-                    let ty0 = tcx.type_of(field.did).subst(tcx, substs);
+                    let ty0 = tcx.type_of(field.did).instantiate(tcx, args);
                     // 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.
@@ -864,25 +864,20 @@ fn transform_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, options: TransformTyOptio
                     ty = Ty::new_unit(tcx);
                 }
             } else {
-                ty = Ty::new_adt(tcx, *adt_def, transform_substs(tcx, substs, options));
+                ty = Ty::new_adt(tcx, *adt_def, transform_args(tcx, args, options));
             }
         }
 
-        ty::FnDef(def_id, substs) => {
-            ty = Ty::new_fn_def(tcx, *def_id, transform_substs(tcx, substs, options));
+        ty::FnDef(def_id, args) => {
+            ty = Ty::new_fn_def(tcx, *def_id, transform_args(tcx, args, options));
         }
 
-        ty::Closure(def_id, substs) => {
-            ty = Ty::new_closure(tcx, *def_id, transform_substs(tcx, substs, options));
+        ty::Closure(def_id, args) => {
+            ty = Ty::new_closure(tcx, *def_id, transform_args(tcx, args, options));
         }
 
-        ty::Generator(def_id, substs, movability) => {
-            ty = Ty::new_generator(
-                tcx,
-                *def_id,
-                transform_substs(tcx, substs, options),
-                *movability,
-            );
+        ty::Generator(def_id, args, movability) => {
+            ty = Ty::new_generator(tcx, *def_id, transform_args(tcx, args, options), *movability);
         }
 
         ty::Ref(region, ty0, ..) => {
diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs
index 5e5cc6e4e4a..1846fda7c63 100644
--- a/compiler/rustc_symbol_mangling/src/v0.rs
+++ b/compiler/rustc_symbol_mangling/src/v0.rs
@@ -27,7 +27,7 @@ pub(super) fn mangle<'tcx>(
 ) -> String {
     let def_id = instance.def_id();
     // FIXME(eddyb) this should ideally not be needed.
-    let substs = tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), instance.substs);
+    let args = tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), instance.args);
 
     let prefix = "_R";
     let mut cx = &mut SymbolMangler {
@@ -50,9 +50,9 @@ pub(super) fn mangle<'tcx>(
     };
 
     cx = if let Some(shim_kind) = shim_kind {
-        cx.path_append_ns(|cx| cx.print_def_path(def_id, substs), 'S', 0, shim_kind).unwrap()
+        cx.path_append_ns(|cx| cx.print_def_path(def_id, args), 'S', 0, shim_kind).unwrap()
     } else {
-        cx.print_def_path(def_id, substs).unwrap()
+        cx.print_def_path(def_id, args).unwrap()
     };
     if let Some(instantiating_crate) = instantiating_crate {
         cx = cx.print_def_path(instantiating_crate.as_def_id(), &[]).unwrap();
@@ -245,19 +245,19 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> {
     fn print_def_path(
         mut self,
         def_id: DefId,
-        substs: &'tcx [GenericArg<'tcx>],
+        args: &'tcx [GenericArg<'tcx>],
     ) -> Result<Self::Path, Self::Error> {
-        if let Some(&i) = self.paths.get(&(def_id, substs)) {
+        if let Some(&i) = self.paths.get(&(def_id, args)) {
             return self.print_backref(i);
         }
         let start = self.out.len();
 
-        self = self.default_print_def_path(def_id, substs)?;
+        self = self.default_print_def_path(def_id, args)?;
 
         // Only cache paths that do not refer to an enclosing
         // binder (which would change depending on context).
-        if !substs.iter().any(|k| k.has_escaping_bound_vars()) {
-            self.paths.insert((def_id, substs), start);
+        if !args.iter().any(|k| k.has_escaping_bound_vars()) {
+            self.paths.insert((def_id, args), start);
         }
         Ok(self)
     }
@@ -265,7 +265,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> {
     fn print_impl_path(
         mut self,
         impl_def_id: DefId,
-        substs: &'tcx [GenericArg<'tcx>],
+        args: &'tcx [GenericArg<'tcx>],
         mut self_ty: Ty<'tcx>,
         mut impl_trait_ref: Option<ty::TraitRef<'tcx>>,
     ) -> Result<Self::Path, Self::Error> {
@@ -273,8 +273,8 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> {
         let parent_def_id = DefId { index: key.parent.unwrap(), ..impl_def_id };
 
         let mut param_env = self.tcx.param_env_reveal_all_normalized(impl_def_id);
-        if !substs.is_empty() {
-            param_env = EarlyBinder::bind(param_env).subst(self.tcx, substs);
+        if !args.is_empty() {
+            param_env = EarlyBinder::bind(param_env).instantiate(self.tcx, args);
         }
 
         match &mut impl_trait_ref {
@@ -295,7 +295,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> {
 
         // Encode impl generic params if the substitutions contain parameters (implying
         // polymorphization is enabled) and this isn't an inherent impl.
-        if impl_trait_ref.is_some() && substs.iter().any(|a| a.has_non_region_param()) {
+        if impl_trait_ref.is_some() && args.iter().any(|a| a.has_non_region_param()) {
             self = self.path_generic_args(
                 |this| {
                     this.path_append_ns(
@@ -305,7 +305,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> {
                         "",
                     )
                 },
-                substs,
+                args,
             )?;
         } else {
             self.push_disambiguator(key.disambiguated_data.disambiguator as u64);
@@ -315,7 +315,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> {
         self = self_ty.print(self)?;
 
         if let Some(trait_ref) = impl_trait_ref {
-            self = self.print_def_path(trait_ref.def_id, trait_ref.substs)?;
+            self = self.print_def_path(trait_ref.def_id, trait_ref.args)?;
         }
 
         Ok(self)
@@ -431,12 +431,12 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> {
             }
 
             // Mangle all nominal types as paths.
-            ty::Adt(ty::AdtDef(Interned(&ty::AdtDefData { did: def_id, .. }, _)), substs)
-            | ty::FnDef(def_id, substs)
-            | ty::Alias(ty::Projection | ty::Opaque, ty::AliasTy { def_id, substs, .. })
-            | ty::Closure(def_id, substs)
-            | ty::Generator(def_id, substs, _) => {
-                self = self.print_def_path(def_id, substs)?;
+            ty::Adt(ty::AdtDef(Interned(&ty::AdtDefData { did: def_id, .. }, _)), args)
+            | ty::FnDef(def_id, args)
+            | ty::Alias(ty::Projection | ty::Opaque, ty::AliasTy { def_id, args, .. })
+            | ty::Closure(def_id, args)
+            | ty::Generator(def_id, args, _) => {
+                self = self.print_def_path(def_id, args)?;
             }
             ty::Foreign(def_id) => {
                 self = self.print_def_path(def_id, &[])?;
@@ -537,7 +537,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> {
                         // Use a type that can't appear in defaults of type parameters.
                         let dummy_self = Ty::new_fresh(cx.tcx, 0);
                         let trait_ref = trait_ref.with_self_ty(cx.tcx, dummy_self);
-                        cx = cx.print_def_path(trait_ref.def_id, trait_ref.substs)?;
+                        cx = cx.print_def_path(trait_ref.def_id, trait_ref.args)?;
                     }
                     ty::ExistentialPredicate::Projection(projection) => {
                         let name = cx.tcx.associated_item(projection.def_id).name;
@@ -679,13 +679,13 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> {
                         self.push("T");
                         self = print_field_list(self)?;
                     }
-                    ty::Adt(def, substs) => {
+                    ty::Adt(def, args) => {
                         let variant_idx =
                             contents.variant.expect("destructed const of adt without variant idx");
                         let variant_def = &def.variant(variant_idx);
 
                         self.push("V");
-                        self = self.print_def_path(variant_def.def_id, substs)?;
+                        self = self.print_def_path(variant_def.def_id, args)?;
 
                         match variant_def.ctor_kind() {
                             Some(CtorKind::Const) => {
@@ -750,7 +750,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> {
 
         self.push("Y");
         self = self_ty.print(self)?;
-        self.print_def_path(trait_ref.def_id, trait_ref.substs)
+        self.print_def_path(trait_ref.def_id, trait_ref.args)
     }
 
     fn path_append_impl(
diff --git a/compiler/rustc_target/src/abi/call/aarch64.rs b/compiler/rustc_target/src/abi/call/aarch64.rs
index a84988fa75c..b4c7b0f120f 100644
--- a/compiler/rustc_target/src/abi/call/aarch64.rs
+++ b/compiler/rustc_target/src/abi/call/aarch64.rs
@@ -1,25 +1,15 @@
 use crate::abi::call::{ArgAbi, FnAbi, Reg, RegKind, Uniform};
 use crate::abi::{HasDataLayout, TyAbiInterface};
 
-/// Given integer-types M and register width N (e.g. M=u16 and N=32 bits), the
-/// `ParamExtension` policy specifies how a uM value should be treated when
-/// passed via register or stack-slot of width N. See also rust-lang/rust#97463.
+/// Indicates the variant of the AArch64 ABI we are compiling for.
+/// Used to accommodate Apple and Microsoft's deviations from the usual AAPCS ABI.
+///
+/// Corresponds to Clang's `AArch64ABIInfo::ABIKind`.
 #[derive(Copy, Clone, PartialEq)]
-pub enum ParamExtension {
-    /// Indicates that when passing an i8/i16, either as a function argument or
-    /// as a return value, it must be sign-extended to 32 bits, and likewise a
-    /// u8/u16 must be zero-extended to 32-bits. (This variant is here to
-    /// accommodate Apple's deviation from the usual AArch64 ABI as defined by
-    /// ARM.)
-    ///
-    /// See also: <https://developer.apple.com/documentation/xcode/writing-arm64-code-for-apple-platforms#Pass-Arguments-to-Functions-Correctly>
-    ExtendTo32Bits,
-
-    /// Indicates that no sign- nor zero-extension is performed: if a value of
-    /// type with bitwidth M is passed as function argument or return value,
-    /// then M bits are copied into the least significant M bits, and the
-    /// remaining bits of the register (or word of memory) are untouched.
-    NoExtension,
+pub enum AbiKind {
+    AAPCS,
+    DarwinPCS,
+    Win64,
 }
 
 fn is_homogeneous_aggregate<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>) -> Option<Uniform>
@@ -45,15 +35,17 @@ where
     })
 }
 
-fn classify_ret<'a, Ty, C>(cx: &C, ret: &mut ArgAbi<'a, Ty>, param_policy: ParamExtension)
+fn classify_ret<'a, Ty, C>(cx: &C, ret: &mut ArgAbi<'a, Ty>, kind: AbiKind)
 where
     Ty: TyAbiInterface<'a, C> + Copy,
     C: HasDataLayout,
 {
     if !ret.layout.is_aggregate() {
-        match param_policy {
-            ParamExtension::ExtendTo32Bits => ret.extend_integer_width_to(32),
-            ParamExtension::NoExtension => {}
+        if kind == AbiKind::DarwinPCS {
+            // On Darwin, when returning an i8/i16, it must be sign-extended to 32 bits,
+            // and likewise a u8/u16 must be zero-extended to 32-bits.
+            // See also: <https://developer.apple.com/documentation/xcode/writing-arm64-code-for-apple-platforms#Pass-Arguments-to-Functions-Correctly>
+            ret.extend_integer_width_to(32)
         }
         return;
     }
@@ -70,15 +62,17 @@ where
     ret.make_indirect();
 }
 
-fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>, param_policy: ParamExtension)
+fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>, kind: AbiKind)
 where
     Ty: TyAbiInterface<'a, C> + Copy,
     C: HasDataLayout,
 {
     if !arg.layout.is_aggregate() {
-        match param_policy {
-            ParamExtension::ExtendTo32Bits => arg.extend_integer_width_to(32),
-            ParamExtension::NoExtension => {}
+        if kind == AbiKind::DarwinPCS {
+            // On Darwin, when passing an i8/i16, it must be sign-extended to 32 bits,
+            // and likewise a u8/u16 must be zero-extended to 32-bits.
+            // See also: <https://developer.apple.com/documentation/xcode/writing-arm64-code-for-apple-platforms#Pass-Arguments-to-Functions-Correctly>
+            arg.extend_integer_width_to(32);
         }
         return;
     }
@@ -87,27 +81,39 @@ where
         return;
     }
     let size = arg.layout.size;
-    let bits = size.bits();
-    if bits <= 128 {
-        arg.cast_to(Uniform { unit: Reg::i64(), total: size });
+    let align = if kind == AbiKind::AAPCS {
+        // When passing small aggregates by value, the AAPCS ABI mandates using the unadjusted
+        // alignment of the type (not including `repr(align)`).
+        // This matches behavior of `AArch64ABIInfo::classifyArgumentType` in Clang.
+        // See: <https://github.com/llvm/llvm-project/blob/5e691a1c9b0ad22689d4a434ddf4fed940e58dec/clang/lib/CodeGen/TargetInfo.cpp#L5816-L5823>
+        arg.layout.unadjusted_abi_align
+    } else {
+        arg.layout.align.abi
+    };
+    if size.bits() <= 128 {
+        if align.bits() == 128 {
+            arg.cast_to(Uniform { unit: Reg::i128(), total: size });
+        } else {
+            arg.cast_to(Uniform { unit: Reg::i64(), total: size });
+        }
         return;
     }
     arg.make_indirect();
 }
 
-pub fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>, param_policy: ParamExtension)
+pub fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>, kind: AbiKind)
 where
     Ty: TyAbiInterface<'a, C> + Copy,
     C: HasDataLayout,
 {
     if !fn_abi.ret.is_ignore() {
-        classify_ret(cx, &mut fn_abi.ret, param_policy);
+        classify_ret(cx, &mut fn_abi.ret, kind);
     }
 
     for arg in fn_abi.args.iter_mut() {
         if arg.is_ignore() {
             continue;
         }
-        classify_arg(cx, arg, param_policy);
+        classify_arg(cx, arg, kind);
     }
 }
diff --git a/compiler/rustc_target/src/abi/call/m68k.rs b/compiler/rustc_target/src/abi/call/m68k.rs
index c1e0f54af5f..1d4649ed867 100644
--- a/compiler/rustc_target/src/abi/call/m68k.rs
+++ b/compiler/rustc_target/src/abi/call/m68k.rs
@@ -10,7 +10,7 @@ fn classify_ret<Ty>(ret: &mut ArgAbi<'_, Ty>) {
 
 fn classify_arg<Ty>(arg: &mut ArgAbi<'_, Ty>) {
     if arg.layout.is_aggregate() {
-        arg.make_indirect_byval();
+        arg.make_indirect_byval(None);
     } else {
         arg.extend_integer_width_to(32);
     }
diff --git a/compiler/rustc_target/src/abi/call/mod.rs b/compiler/rustc_target/src/abi/call/mod.rs
index c4abf6f4b5e..03e7b3e7b40 100644
--- a/compiler/rustc_target/src/abi/call/mod.rs
+++ b/compiler/rustc_target/src/abi/call/mod.rs
@@ -494,9 +494,7 @@ impl<'a, Ty> ArgAbi<'a, Ty> {
             .set(ArgAttribute::NonNull)
             .set(ArgAttribute::NoUndef);
         attrs.pointee_size = layout.size;
-        // FIXME(eddyb) We should be doing this, but at least on
-        // i686-pc-windows-msvc, it results in wrong stack offsets.
-        // attrs.pointee_align = Some(layout.align.abi);
+        attrs.pointee_align = Some(layout.align.abi);
 
         let extra_attrs = layout.is_unsized().then_some(ArgAttributes::new());
 
@@ -513,11 +511,19 @@ impl<'a, Ty> ArgAbi<'a, Ty> {
         self.mode = Self::indirect_pass_mode(&self.layout);
     }
 
-    pub fn make_indirect_byval(&mut self) {
+    pub fn make_indirect_byval(&mut self, byval_align: Option<Align>) {
         self.make_indirect();
         match self.mode {
-            PassMode::Indirect { attrs: _, extra_attrs: _, ref mut on_stack } => {
+            PassMode::Indirect { ref mut attrs, extra_attrs: _, ref mut on_stack } => {
                 *on_stack = true;
+
+                // Some platforms, like 32-bit x86, change the alignment of the type when passing
+                // `byval`. Account for that.
+                if let Some(byval_align) = byval_align {
+                    // On all targets with byval align this is currently true, so let's assert it.
+                    debug_assert!(byval_align >= Align::from_bytes(4).unwrap());
+                    attrs.pointee_align = Some(byval_align);
+                }
             }
             _ => unreachable!(),
         }
@@ -644,7 +650,8 @@ impl<'a, Ty> FnAbi<'a, Ty> {
     {
         if abi == spec::abi::Abi::X86Interrupt {
             if let Some(arg) = self.args.first_mut() {
-                arg.make_indirect_byval();
+                // FIXME(pcwalton): This probably should use the x86 `byval` ABI...
+                arg.make_indirect_byval(None);
             }
             return Ok(());
         }
@@ -672,12 +679,14 @@ impl<'a, Ty> FnAbi<'a, Ty> {
                 }
             },
             "aarch64" => {
-                let param_policy = if cx.target_spec().is_like_osx {
-                    aarch64::ParamExtension::ExtendTo32Bits
+                let kind = if cx.target_spec().is_like_osx {
+                    aarch64::AbiKind::DarwinPCS
+                } else if cx.target_spec().is_like_windows {
+                    aarch64::AbiKind::Win64
                 } else {
-                    aarch64::ParamExtension::NoExtension
+                    aarch64::AbiKind::AAPCS
                 };
-                aarch64::compute_abi_info(cx, self, param_policy)
+                aarch64::compute_abi_info(cx, self, kind)
             }
             "amdgpu" => amdgpu::compute_abi_info(cx, self),
             "arm" => arm::compute_abi_info(cx, self),
diff --git a/compiler/rustc_target/src/abi/call/wasm.rs b/compiler/rustc_target/src/abi/call/wasm.rs
index 44427ee5317..0eb2309ecb2 100644
--- a/compiler/rustc_target/src/abi/call/wasm.rs
+++ b/compiler/rustc_target/src/abi/call/wasm.rs
@@ -36,7 +36,7 @@ where
 {
     arg.extend_integer_width_to(32);
     if arg.layout.is_aggregate() && !unwrap_trivial_aggregate(cx, arg) {
-        arg.make_indirect_byval();
+        arg.make_indirect_byval(None);
     }
 }
 
diff --git a/compiler/rustc_target/src/abi/call/x86.rs b/compiler/rustc_target/src/abi/call/x86.rs
index 7c26335dcf4..b738c3133d9 100644
--- a/compiler/rustc_target/src/abi/call/x86.rs
+++ b/compiler/rustc_target/src/abi/call/x86.rs
@@ -1,5 +1,5 @@
 use crate::abi::call::{ArgAttribute, FnAbi, PassMode, Reg, RegKind};
-use crate::abi::{HasDataLayout, TyAbiInterface};
+use crate::abi::{Abi, Align, HasDataLayout, TyAbiInterface, TyAndLayout};
 use crate::spec::HasTargetSpec;
 
 #[derive(PartialEq)]
@@ -53,8 +53,75 @@ where
         if arg.is_ignore() {
             continue;
         }
-        if arg.layout.is_aggregate() {
-            arg.make_indirect_byval();
+
+        // FIXME: MSVC 2015+ will pass the first 3 vector arguments in [XYZ]MM0-2
+        // See https://reviews.llvm.org/D72114 for Clang behavior
+
+        let t = cx.target_spec();
+        let align_4 = Align::from_bytes(4).unwrap();
+        let align_16 = Align::from_bytes(16).unwrap();
+
+        if t.is_like_msvc
+            && arg.layout.is_adt()
+            && let Some(max_repr_align) = arg.layout.max_repr_align
+            && max_repr_align > align_4
+        {
+            // MSVC has special rules for overaligned arguments: https://reviews.llvm.org/D72114.
+            // Summarized here:
+            // - Arguments with _requested_ alignment > 4 are passed indirectly.
+            // - For backwards compatibility, arguments with natural alignment > 4 are still passed
+            //   on stack (via `byval`). For example, this includes `double`, `int64_t`,
+            //   and structs containing them, provided they lack an explicit alignment attribute.
+            assert!(arg.layout.align.abi >= max_repr_align,
+                "abi alignment {:?} less than requested alignment {max_repr_align:?}",
+                arg.layout.align.abi,
+            );
+            arg.make_indirect();
+        } else if arg.layout.is_aggregate() {
+            // We need to compute the alignment of the `byval` argument. The rules can be found in
+            // `X86_32ABIInfo::getTypeStackAlignInBytes` in Clang's `TargetInfo.cpp`. Summarized
+            // here, they are:
+            //
+            // 1. If the natural alignment of the type is <= 4, the alignment is 4.
+            //
+            // 2. Otherwise, on Linux, the alignment of any vector type is the natural alignment.
+            // This doesn't matter here because we only pass aggregates via `byval`, not vectors.
+            //
+            // 3. Otherwise, on Apple platforms, the alignment of anything that contains a vector
+            // type is 16.
+            //
+            // 4. If none of these conditions are true, the alignment is 4.
+
+            fn contains_vector<'a, Ty, C>(cx: &C, layout: TyAndLayout<'a, Ty>) -> bool
+            where
+                Ty: TyAbiInterface<'a, C> + Copy,
+            {
+                match layout.abi {
+                    Abi::Uninhabited | Abi::Scalar(_) | Abi::ScalarPair(..) => false,
+                    Abi::Vector { .. } => true,
+                    Abi::Aggregate { .. } => {
+                        for i in 0..layout.fields.count() {
+                            if contains_vector(cx, layout.field(cx, i)) {
+                                return true;
+                            }
+                        }
+                        false
+                    }
+                }
+            }
+
+            let byval_align = if arg.layout.align.abi < align_4 {
+                // (1.)
+                align_4
+            } else if t.is_like_osx && contains_vector(cx, arg.layout) {
+                // (3.)
+                align_16
+            } else {
+                // (4.)
+                align_4
+            };
+
+            arg.make_indirect_byval(Some(byval_align));
         } else {
             arg.extend_integer_width_to(32);
         }
diff --git a/compiler/rustc_target/src/abi/call/x86_64.rs b/compiler/rustc_target/src/abi/call/x86_64.rs
index b1aefaf0507..d1efe977699 100644
--- a/compiler/rustc_target/src/abi/call/x86_64.rs
+++ b/compiler/rustc_target/src/abi/call/x86_64.rs
@@ -213,7 +213,7 @@ where
         match cls_or_mem {
             Err(Memory) => {
                 if is_arg {
-                    arg.make_indirect_byval();
+                    arg.make_indirect_byval(None);
                 } else {
                     // `sret` parameter thus one less integer register available
                     arg.make_indirect();
diff --git a/compiler/rustc_target/src/lib.rs b/compiler/rustc_target/src/lib.rs
index a7b54766bc6..3307244a217 100644
--- a/compiler/rustc_target/src/lib.rs
+++ b/compiler/rustc_target/src/lib.rs
@@ -12,6 +12,7 @@
 #![feature(associated_type_bounds)]
 #![feature(exhaustive_patterns)]
 #![feature(iter_intersperse)]
+#![feature(let_chains)]
 #![feature(min_specialization)]
 #![feature(never_type)]
 #![feature(rustc_attrs)]
diff --git a/compiler/rustc_trait_selection/src/solve/alias_relate.rs b/compiler/rustc_trait_selection/src/solve/alias_relate.rs
index 422a6ee3442..73362d82306 100644
--- a/compiler/rustc_trait_selection/src/solve/alias_relate.rs
+++ b/compiler/rustc_trait_selection/src/solve/alias_relate.rs
@@ -65,7 +65,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
                     direction,
                     Invert::Yes,
                 ));
-                // Relate via substs
+                // Relate via args
                 let subst_relate_response = self
                     .assemble_subst_relate_candidate(param_env, alias_lhs, alias_rhs, direction);
                 candidates.extend(subst_relate_response);
@@ -153,7 +153,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
         alias_rhs: ty::AliasTy<'tcx>,
         direction: ty::AliasRelationDirection,
     ) -> QueryResult<'tcx> {
-        self.probe_candidate("substs relate").enter(|ecx| {
+        self.probe_candidate("args relate").enter(|ecx| {
             match direction {
                 ty::AliasRelationDirection::Equate => {
                     ecx.eq(param_env, alias_lhs, alias_rhs)?;
diff --git a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs
index 28138054ae5..1e798998895 100644
--- a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs
+++ b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs
@@ -160,8 +160,8 @@ pub(super) trait GoalKind<'tcx>:
         Self::probe_and_match_goal_against_assumption(ecx, goal, assumption, |ecx| {
             let tcx = ecx.tcx();
             let ty::Dynamic(bounds, _, _) = *goal.predicate.self_ty().kind() else {
-                    bug!("expected object type in `consider_object_bound_candidate`");
-                };
+                bug!("expected object type in `consider_object_bound_candidate`");
+            };
             ecx.add_goals(
                 structural_traits::predicates_for_object_candidate(
                     &ecx,
@@ -352,9 +352,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
         candidates: &mut Vec<Candidate<'tcx>>,
     ) {
         let tcx = self.tcx();
-        let &ty::Alias(_, projection_ty) = goal.predicate.self_ty().kind() else {
-            return
-        };
+        let &ty::Alias(_, projection_ty) = goal.predicate.self_ty().kind() else { return };
 
         let normalized_self_candidates: Result<_, NoSolution> =
             self.probe(|_| CandidateKind::NormalizedSelfTyAssembly).enter(|ecx| {
@@ -544,7 +542,8 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
             ty::Alias(ty::Projection | ty::Opaque, alias_ty) => alias_ty,
         };
 
-        for assumption in self.tcx().item_bounds(alias_ty.def_id).subst(self.tcx(), alias_ty.substs)
+        for assumption in
+            self.tcx().item_bounds(alias_ty.def_id).instantiate(self.tcx(), alias_ty.args)
         {
             match G::consider_alias_bound_candidate(self, goal, assumption) {
                 Ok(result) => {
diff --git a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs
index 3bb8cad15ab..3a1302e46ba 100644
--- a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs
+++ b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs
@@ -51,36 +51,36 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_auto_trait<'tcx>(
             Ok(tys.iter().collect())
         }
 
-        ty::Closure(_, ref substs) => Ok(vec![substs.as_closure().tupled_upvars_ty()]),
+        ty::Closure(_, ref args) => Ok(vec![args.as_closure().tupled_upvars_ty()]),
 
-        ty::Generator(_, ref substs, _) => {
-            let generator_substs = substs.as_generator();
-            Ok(vec![generator_substs.tupled_upvars_ty(), generator_substs.witness()])
+        ty::Generator(_, ref args, _) => {
+            let generator_args = args.as_generator();
+            Ok(vec![generator_args.tupled_upvars_ty(), generator_args.witness()])
         }
 
         ty::GeneratorWitness(types) => Ok(ecx.instantiate_binder_with_placeholders(types).to_vec()),
 
-        ty::GeneratorWitnessMIR(def_id, substs) => Ok(ecx
+        ty::GeneratorWitnessMIR(def_id, args) => Ok(ecx
             .tcx()
             .generator_hidden_types(def_id)
             .map(|bty| {
                 ecx.instantiate_binder_with_placeholders(replace_erased_lifetimes_with_bound_vars(
                     tcx,
-                    bty.subst(tcx, substs),
+                    bty.instantiate(tcx, args),
                 ))
             })
             .collect()),
 
         // For `PhantomData<T>`, we pass `T`.
-        ty::Adt(def, substs) if def.is_phantom_data() => Ok(vec![substs.type_at(0)]),
+        ty::Adt(def, args) if def.is_phantom_data() => Ok(vec![args.type_at(0)]),
 
-        ty::Adt(def, substs) => Ok(def.all_fields().map(|f| f.ty(tcx, substs)).collect()),
+        ty::Adt(def, args) => Ok(def.all_fields().map(|f| f.ty(tcx, args)).collect()),
 
-        ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
+        ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) => {
             // 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.type_of(def_id).subst(tcx, substs)])
+            Ok(vec![tcx.type_of(def_id).instantiate(tcx, args)])
         }
     }
 }
@@ -146,9 +146,9 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_sized_trait<'tcx>(
 
         ty::Tuple(tys) => Ok(tys.to_vec()),
 
-        ty::Adt(def, substs) => {
+        ty::Adt(def, args) => {
             let sized_crit = def.sized_constraint(ecx.tcx());
-            Ok(sized_crit.subst_iter_copied(ecx.tcx(), substs).collect())
+            Ok(sized_crit.arg_iter_copied(ecx.tcx(), args).collect())
         }
     }
 }
@@ -192,11 +192,11 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_copy_clone_trait<'tcx>(
 
         ty::Tuple(tys) => Ok(tys.to_vec()),
 
-        ty::Closure(_, substs) => Ok(vec![substs.as_closure().tupled_upvars_ty()]),
+        ty::Closure(_, args) => Ok(vec![args.as_closure().tupled_upvars_ty()]),
 
-        ty::Generator(_, substs, Movability::Movable) => {
+        ty::Generator(_, args, Movability::Movable) => {
             if ecx.tcx().features().generator_clone {
-                let generator = substs.as_generator();
+                let generator = args.as_generator();
                 Ok(vec![generator.tupled_upvars_ty(), generator.witness()])
             } else {
                 Err(NoSolution)
@@ -205,13 +205,13 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_copy_clone_trait<'tcx>(
 
         ty::GeneratorWitness(types) => Ok(ecx.instantiate_binder_with_placeholders(types).to_vec()),
 
-        ty::GeneratorWitnessMIR(def_id, substs) => Ok(ecx
+        ty::GeneratorWitnessMIR(def_id, args) => Ok(ecx
             .tcx()
             .generator_hidden_types(def_id)
             .map(|bty| {
                 ecx.instantiate_binder_with_placeholders(replace_erased_lifetimes_with_bound_vars(
                     ecx.tcx(),
-                    bty.subst(ecx.tcx(), substs),
+                    bty.instantiate(ecx.tcx(), args),
                 ))
             })
             .collect()),
@@ -226,13 +226,13 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_callable<'tcx>(
 ) -> Result<Option<ty::Binder<'tcx, (Ty<'tcx>, Ty<'tcx>)>>, NoSolution> {
     match *self_ty.kind() {
         // keep this in sync with assemble_fn_pointer_candidates until the old solver is removed.
-        ty::FnDef(def_id, substs) => {
+        ty::FnDef(def_id, args) => {
             let sig = tcx.fn_sig(def_id);
             if sig.skip_binder().is_fn_trait_compatible()
                 && tcx.codegen_fn_attrs(def_id).target_features.is_empty()
             {
                 Ok(Some(
-                    sig.subst(tcx, substs)
+                    sig.instantiate(tcx, args)
                         .map_bound(|sig| (Ty::new_tup(tcx, sig.inputs()), sig.output())),
                 ))
             } else {
@@ -247,9 +247,9 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_callable<'tcx>(
                 Err(NoSolution)
             }
         }
-        ty::Closure(_, substs) => {
-            let closure_substs = substs.as_closure();
-            match closure_substs.kind_ty().to_opt_closure_kind() {
+        ty::Closure(_, args) => {
+            let closure_args = args.as_closure();
+            match closure_args.kind_ty().to_opt_closure_kind() {
                 // If the closure's kind doesn't extend the goal kind,
                 // then the closure doesn't implement the trait.
                 Some(closure_kind) => {
@@ -265,7 +265,7 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_callable<'tcx>(
                     }
                 }
             }
-            Ok(Some(closure_substs.sig().map_bound(|sig| (sig.inputs()[0], sig.output()))))
+            Ok(Some(closure_args.sig().map_bound(|sig| (sig.inputs()[0], sig.output()))))
         }
         ty::Bool
         | ty::Char
@@ -347,13 +347,13 @@ pub(in crate::solve) fn predicates_for_object_candidate<'tcx>(
     let tcx = ecx.tcx();
     let mut requirements = vec![];
     requirements.extend(
-        tcx.super_predicates_of(trait_ref.def_id).instantiate(tcx, trait_ref.substs).predicates,
+        tcx.super_predicates_of(trait_ref.def_id).instantiate(tcx, trait_ref.args).predicates,
     );
     for item in tcx.associated_items(trait_ref.def_id).in_definition_order() {
         // FIXME(associated_const_equality): Also add associated consts to
         // the requirements here.
         if item.kind == ty::AssocKind::Type {
-            requirements.extend(tcx.item_bounds(item.def_id).subst_iter(tcx, trait_ref.substs));
+            requirements.extend(tcx.item_bounds(item.def_id).arg_iter(tcx, trait_ref.args));
         }
     }
 
diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs
index 74dfbdddbab..6e0aa08c307 100644
--- a/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs
+++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs
@@ -116,7 +116,8 @@ impl NestedGoals<'_> {
 #[derive(PartialEq, Eq, Debug, Hash, HashStable, Clone, Copy)]
 pub enum GenerateProofTree {
     Yes(UseGlobalCache),
-    No,
+    IfEnabled,
+    Never,
 }
 
 #[derive(PartialEq, Eq, Debug, Hash, HashStable, Clone, Copy)]
@@ -202,7 +203,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
             (&tree, infcx.tcx.sess.opts.unstable_opts.dump_solver_proof_tree)
         {
             let mut lock = std::io::stdout().lock();
-            let _ = lock.write_fmt(format_args!("{tree:?}"));
+            let _ = lock.write_fmt(format_args!("{tree:?}\n"));
             let _ = lock.flush();
         }
 
@@ -430,11 +431,8 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
                 ty::PredicateKind::Coerce(predicate) => {
                     self.compute_coerce_goal(Goal { param_env, predicate })
                 }
-                ty::PredicateKind::ClosureKind(def_id, substs, kind) => self
-                    .compute_closure_kind_goal(Goal {
-                        param_env,
-                        predicate: (def_id, substs, kind),
-                    }),
+                ty::PredicateKind::ClosureKind(def_id, args, kind) => self
+                    .compute_closure_kind_goal(Goal { param_env, predicate: (def_id, args, kind) }),
                 ty::PredicateKind::ObjectSafe(trait_def_id) => {
                     self.compute_object_safe_goal(trait_def_id)
                 }
@@ -774,24 +772,18 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
         self.infcx.resolve_vars_if_possible(value)
     }
 
-    pub(super) fn fresh_substs_for_item(&self, def_id: DefId) -> ty::SubstsRef<'tcx> {
-        self.infcx.fresh_substs_for_item(DUMMY_SP, def_id)
+    pub(super) fn fresh_args_for_item(&self, def_id: DefId) -> ty::GenericArgsRef<'tcx> {
+        self.infcx.fresh_args_for_item(DUMMY_SP, def_id)
     }
 
-    pub(super) fn translate_substs(
+    pub(super) fn translate_args(
         &self,
         param_env: ty::ParamEnv<'tcx>,
         source_impl: DefId,
-        source_substs: ty::SubstsRef<'tcx>,
+        source_args: ty::GenericArgsRef<'tcx>,
         target_node: specialization_graph::Node,
-    ) -> ty::SubstsRef<'tcx> {
-        crate::traits::translate_substs(
-            self.infcx,
-            param_env,
-            source_impl,
-            source_substs,
-            target_node,
-        )
+    ) -> ty::GenericArgsRef<'tcx> {
+        crate::traits::translate_args(self.infcx, param_env, source_impl, source_args, target_node)
     }
 
     pub(super) fn register_ty_outlives(&self, ty: Ty<'tcx>, lt: ty::Region<'tcx>) {
@@ -863,14 +855,14 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
     pub(super) fn add_item_bounds_for_hidden_type(
         &mut self,
         opaque_def_id: DefId,
-        opaque_substs: ty::SubstsRef<'tcx>,
+        opaque_args: ty::GenericArgsRef<'tcx>,
         param_env: ty::ParamEnv<'tcx>,
         hidden_ty: Ty<'tcx>,
     ) {
         let mut obligations = Vec::new();
         self.infcx.add_item_bounds_for_hidden_type(
             opaque_def_id,
-            opaque_substs,
+            opaque_args,
             ObligationCause::dummy(),
             param_env,
             hidden_ty,
@@ -896,13 +888,13 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
                 continue;
             }
             values.extend(self.probe_candidate("opaque type storage").enter(|ecx| {
-                for (a, b) in std::iter::zip(candidate_key.substs, key.substs) {
+                for (a, b) in std::iter::zip(candidate_key.args, key.args) {
                     ecx.eq(param_env, a, b)?;
                 }
                 ecx.eq(param_env, candidate_ty, ty)?;
                 ecx.add_item_bounds_for_hidden_type(
                     candidate_key.def_id.to_def_id(),
-                    candidate_key.substs,
+                    candidate_key.args,
                     param_env,
                     candidate_ty,
                 );
diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs
index 637d458882c..9f58e66d04e 100644
--- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs
+++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs
@@ -111,7 +111,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
     ) -> CanonicalResponse<'tcx> {
         let unconstrained_response = Response {
             var_values: CanonicalVarValues {
-                var_values: self.tcx().mk_substs_from_iter(self.var_values.var_values.iter().map(
+                var_values: self.tcx().mk_args_from_iter(self.var_values.var_values.iter().map(
                     |arg| -> ty::GenericArg<'tcx> {
                         match arg.unpack() {
                             GenericArgKind::Lifetime(_) => self.next_region_infer().into(),
@@ -250,7 +250,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
             }
         }
 
-        let var_values = self.tcx().mk_substs_from_iter(response.variables.iter().enumerate().map(
+        let var_values = self.tcx().mk_args_from_iter(response.variables.iter().enumerate().map(
             |(index, info)| {
                 if info.universe() != ty::UniverseIndex::ROOT {
                     // A variable from inside a binder of the query. While ideally these shouldn't
diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs
index bf6cbef8c3b..a6d118d8cc2 100644
--- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs
+++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs
@@ -1,17 +1,18 @@
 use std::ops::ControlFlow;
 
+use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, InferOk};
 use rustc_infer::traits::util::supertraits;
 use rustc_infer::traits::{
-    Obligation, PolyTraitObligation, PredicateObligation, Selection, SelectionResult,
+    Obligation, PolyTraitObligation, PredicateObligation, Selection, SelectionResult, TraitEngine,
 };
 use rustc_middle::traits::solve::{CanonicalInput, Certainty, Goal};
 use rustc_middle::traits::{
     ImplSource, ImplSourceObjectData, ImplSourceTraitUpcastingData, ImplSourceUserDefinedData,
     ObligationCause, SelectionError,
 };
-use rustc_middle::ty::{self, TyCtxt};
+use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_span::DUMMY_SP;
 
 use crate::solve::assembly::{BuiltinImplSource, Candidate, CandidateSource};
@@ -19,6 +20,8 @@ use crate::solve::eval_ctxt::{EvalCtxt, GenerateProofTree};
 use crate::solve::inspect::ProofTreeBuilder;
 use crate::solve::search_graph::OverflowHandler;
 use crate::traits::vtable::{count_own_vtable_entries, prepare_vtable_segments, VtblSegment};
+use crate::traits::StructurallyNormalizeExt;
+use crate::traits::TraitEngineExt;
 
 pub trait InferCtxtSelectExt<'tcx> {
     fn select_in_new_trait_solver(
@@ -40,7 +43,7 @@ impl<'tcx> InferCtxtSelectExt<'tcx> for InferCtxt<'tcx> {
             self.instantiate_binder_with_placeholders(obligation.predicate),
         );
 
-        let (result, _) = EvalCtxt::enter_root(self, GenerateProofTree::No, |ecx| {
+        let (result, _) = EvalCtxt::enter_root(self, GenerateProofTree::Never, |ecx| {
             let goal = Goal::new(ecx.tcx(), trait_goal.param_env, trait_goal.predicate);
             let (orig_values, canonical_goal) = ecx.canonicalize_goal(goal);
             let mut candidates = ecx.compute_canonical_trait_candidates(canonical_goal);
@@ -113,6 +116,12 @@ impl<'tcx> InferCtxtSelectExt<'tcx> for InferCtxt<'tcx> {
                 ),
             ) => rematch_object(self, goal, nested_obligations),
 
+            (Certainty::Maybe(_), CandidateSource::BuiltinImpl(BuiltinImplSource::Misc))
+                if self.tcx.lang_items().unsize_trait() == Some(goal.predicate.def_id()) =>
+            {
+                rematch_unsize(self, goal, nested_obligations)
+            }
+
             // Technically some builtin impls have nested obligations, but if
             // `Certainty::Yes`, then they should've all been verified and don't
             // need re-checking.
@@ -195,8 +204,9 @@ fn rematch_impl<'tcx>(
     impl_def_id: DefId,
     mut nested: Vec<PredicateObligation<'tcx>>,
 ) -> SelectionResult<'tcx, Selection<'tcx>> {
-    let substs = infcx.fresh_substs_for_item(DUMMY_SP, impl_def_id);
-    let impl_trait_ref = infcx.tcx.impl_trait_ref(impl_def_id).unwrap().subst(infcx.tcx, substs);
+    let args = infcx.fresh_args_for_item(DUMMY_SP, impl_def_id);
+    let impl_trait_ref =
+        infcx.tcx.impl_trait_ref(impl_def_id).unwrap().instantiate(infcx.tcx, args);
 
     nested.extend(
         infcx
@@ -207,12 +217,12 @@ fn rematch_impl<'tcx>(
     );
 
     nested.extend(
-        infcx.tcx.predicates_of(impl_def_id).instantiate(infcx.tcx, substs).into_iter().map(
+        infcx.tcx.predicates_of(impl_def_id).instantiate(infcx.tcx, args).into_iter().map(
             |(pred, _)| Obligation::new(infcx.tcx, ObligationCause::dummy(), goal.param_env, pred),
         ),
     );
 
-    Ok(Some(ImplSource::UserDefined(ImplSourceUserDefinedData { impl_def_id, substs, nested })))
+    Ok(Some(ImplSource::UserDefined(ImplSourceUserDefinedData { impl_def_id, args, nested })))
 }
 
 fn rematch_object<'tcx>(
@@ -220,25 +230,30 @@ fn rematch_object<'tcx>(
     goal: Goal<'tcx, ty::TraitPredicate<'tcx>>,
     mut nested: Vec<PredicateObligation<'tcx>>,
 ) -> SelectionResult<'tcx, Selection<'tcx>> {
-    let self_ty = goal.predicate.self_ty();
-    let ty::Dynamic(data, _, source_kind) = *self_ty.kind()
-    else {
-        bug!()
-    };
-    let source_trait_ref = data.principal().unwrap().with_self_ty(infcx.tcx, self_ty);
-
-    let (is_upcasting, target_trait_ref_unnormalized) = if Some(goal.predicate.def_id())
-        == infcx.tcx.lang_items().unsize_trait()
-    {
-        assert_eq!(source_kind, ty::Dyn, "cannot upcast dyn*");
-        if let ty::Dynamic(data, _, ty::Dyn) = goal.predicate.trait_ref.substs.type_at(1).kind() {
-            (true, data.principal().unwrap().with_self_ty(infcx.tcx, self_ty))
+    let a_ty = structurally_normalize(goal.predicate.self_ty(), infcx, goal.param_env, &mut nested);
+    let ty::Dynamic(data, _, source_kind) = *a_ty.kind() else { bug!() };
+    let source_trait_ref = data.principal().unwrap().with_self_ty(infcx.tcx, a_ty);
+
+    let (is_upcasting, target_trait_ref_unnormalized) =
+        if Some(goal.predicate.def_id()) == infcx.tcx.lang_items().unsize_trait() {
+            assert_eq!(source_kind, ty::Dyn, "cannot upcast dyn*");
+            let b_ty = structurally_normalize(
+                goal.predicate.trait_ref.args.type_at(1),
+                infcx,
+                goal.param_env,
+                &mut nested,
+            );
+            if let ty::Dynamic(data, _, ty::Dyn) = *b_ty.kind() {
+                // FIXME: We also need to ensure that the source lifetime outlives the
+                // target lifetime. This doesn't matter for codegen, though, and only
+                // *really* matters if the goal's certainty is ambiguous.
+                (true, data.principal().unwrap().with_self_ty(infcx.tcx, a_ty))
+            } else {
+                bug!()
+            }
         } else {
-            bug!()
-        }
-    } else {
-        (false, ty::Binder::dummy(goal.predicate.trait_ref))
-    };
+            (false, ty::Binder::dummy(goal.predicate.trait_ref))
+        };
 
     let mut target_trait_ref = None;
     for candidate_trait_ref in supertraits(infcx.tcx, source_trait_ref) {
@@ -305,3 +320,157 @@ fn rematch_object<'tcx>(
         ImplSource::Object(ImplSourceObjectData { vtable_base, nested })
     }))
 }
+
+/// The `Unsize` trait is particularly important to coercion, so we try rematch it.
+/// NOTE: This must stay in sync with `consider_builtin_unsize_candidate` in trait
+/// goal assembly in the solver, both for soundness and in order to avoid ICEs.
+fn rematch_unsize<'tcx>(
+    infcx: &InferCtxt<'tcx>,
+    goal: Goal<'tcx, ty::TraitPredicate<'tcx>>,
+    mut nested: Vec<PredicateObligation<'tcx>>,
+) -> SelectionResult<'tcx, Selection<'tcx>> {
+    let tcx = infcx.tcx;
+    let a_ty = goal.predicate.self_ty();
+    let b_ty = goal.predicate.trait_ref.args.type_at(1);
+
+    match (a_ty.kind(), b_ty.kind()) {
+        (_, &ty::Dynamic(data, region, ty::Dyn)) => {
+            // Check that the type implements all of the predicates of the def-id.
+            // (i.e. the principal, all of the associated types match, and any auto traits)
+            nested.extend(data.iter().map(|pred| {
+                Obligation::new(
+                    infcx.tcx,
+                    ObligationCause::dummy(),
+                    goal.param_env,
+                    pred.with_self_ty(tcx, a_ty),
+                )
+            }));
+            // The type must be Sized to be unsized.
+            let sized_def_id = tcx.require_lang_item(hir::LangItem::Sized, None);
+            nested.push(Obligation::new(
+                infcx.tcx,
+                ObligationCause::dummy(),
+                goal.param_env,
+                ty::TraitRef::new(tcx, sized_def_id, [a_ty]),
+            ));
+            // The type must outlive the lifetime of the `dyn` we're unsizing into.
+            nested.push(Obligation::new(
+                infcx.tcx,
+                ObligationCause::dummy(),
+                goal.param_env,
+                ty::Binder::dummy(ty::OutlivesPredicate(a_ty, region)),
+            ));
+        }
+        // `[T; n]` -> `[T]` unsizing
+        (&ty::Array(a_elem_ty, ..), &ty::Slice(b_elem_ty)) => {
+            nested.extend(
+                infcx
+                    .at(&ObligationCause::dummy(), goal.param_env)
+                    .eq(DefineOpaqueTypes::No, a_elem_ty, b_elem_ty)
+                    .expect("expected rematch to succeed")
+                    .into_obligations(),
+            );
+        }
+        // Struct unsizing `Struct<T>` -> `Struct<U>` where `T: Unsize<U>`
+        (&ty::Adt(a_def, a_args), &ty::Adt(b_def, b_args))
+            if a_def.is_struct() && a_def.did() == b_def.did() =>
+        {
+            let unsizing_params = tcx.unsizing_params_for_adt(a_def.did());
+            // We must be unsizing some type parameters. This also implies
+            // that the struct has a tail field.
+            if unsizing_params.is_empty() {
+                bug!("expected rematch to succeed")
+            }
+
+            let tail_field = a_def
+                .non_enum_variant()
+                .fields
+                .raw
+                .last()
+                .expect("expected unsized ADT to have a tail field");
+            let tail_field_ty = tcx.type_of(tail_field.did);
+
+            let a_tail_ty = tail_field_ty.instantiate(tcx, a_args);
+            let b_tail_ty = tail_field_ty.instantiate(tcx, b_args);
+
+            // Substitute just the unsizing params from B into A. The type after
+            // this substitution must be equal to B. This is so we don't unsize
+            // unrelated type parameters.
+            let new_a_args = tcx.mk_args_from_iter(
+                a_args
+                    .iter()
+                    .enumerate()
+                    .map(|(i, a)| if unsizing_params.contains(i as u32) { b_args[i] } else { a }),
+            );
+            let unsized_a_ty = Ty::new_adt(tcx, a_def, new_a_args);
+
+            nested.extend(
+                infcx
+                    .at(&ObligationCause::dummy(), goal.param_env)
+                    .eq(DefineOpaqueTypes::No, unsized_a_ty, b_ty)
+                    .expect("expected rematch to succeed")
+                    .into_obligations(),
+            );
+
+            // Finally, we require that `TailA: Unsize<TailB>` for the tail field
+            // types.
+            nested.push(Obligation::new(
+                tcx,
+                ObligationCause::dummy(),
+                goal.param_env,
+                ty::TraitRef::new(tcx, goal.predicate.def_id(), [a_tail_ty, b_tail_ty]),
+            ));
+        }
+        // Tuple unsizing `(.., T)` -> `(.., U)` where `T: Unsize<U>`
+        (&ty::Tuple(a_tys), &ty::Tuple(b_tys))
+            if a_tys.len() == b_tys.len() && !a_tys.is_empty() =>
+        {
+            let (a_last_ty, a_rest_tys) = a_tys.split_last().unwrap();
+            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 =
+                Ty::new_tup_from_iter(tcx, a_rest_tys.iter().chain([b_last_ty]).copied());
+            nested.extend(
+                infcx
+                    .at(&ObligationCause::dummy(), goal.param_env)
+                    .eq(DefineOpaqueTypes::No, unsized_a_ty, b_ty)
+                    .expect("expected rematch to succeed")
+                    .into_obligations(),
+            );
+
+            // Similar to ADTs, require that the rest of the fields are equal.
+            nested.push(Obligation::new(
+                tcx,
+                ObligationCause::dummy(),
+                goal.param_env,
+                ty::TraitRef::new(tcx, goal.predicate.def_id(), [*a_last_ty, *b_last_ty]),
+            ));
+        }
+        // FIXME: We *could* ICE here if either:
+        // 1. the certainty is `Certainty::Yes`,
+        // 2. we're in codegen (which should mean `Certainty::Yes`).
+        _ => return Ok(None),
+    }
+
+    Ok(Some(ImplSource::Builtin(nested)))
+}
+
+fn structurally_normalize<'tcx>(
+    ty: Ty<'tcx>,
+    infcx: &InferCtxt<'tcx>,
+    param_env: ty::ParamEnv<'tcx>,
+    nested: &mut Vec<PredicateObligation<'tcx>>,
+) -> Ty<'tcx> {
+    if matches!(ty.kind(), ty::Alias(..)) {
+        let mut engine = <dyn TraitEngine<'tcx>>::new(infcx);
+        let normalized_ty = infcx
+            .at(&ObligationCause::dummy(), param_env)
+            .structurally_normalize(ty, &mut *engine)
+            .expect("normalization shouldn't fail if we got to here");
+        nested.extend(engine.pending_obligations());
+        normalized_ty
+    } else {
+        ty
+    }
+}
diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs
index 88ee14c4db5..f1d3091225c 100644
--- a/compiler/rustc_trait_selection/src/solve/fulfill.rs
+++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs
@@ -57,7 +57,7 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentCtxt<'tcx> {
             .map(|obligation| {
                 let code = infcx.probe(|_| {
                     match infcx
-                        .evaluate_root_goal(obligation.clone().into(), GenerateProofTree::No)
+                        .evaluate_root_goal(obligation.clone().into(), GenerateProofTree::IfEnabled)
                         .0
                     {
                         Ok((_, Certainty::Maybe(MaybeCause::Ambiguity), _)) => {
@@ -96,7 +96,7 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentCtxt<'tcx> {
             for obligation in mem::take(&mut self.obligations) {
                 let goal = obligation.clone().into();
                 let (changed, certainty, nested_goals) =
-                    match infcx.evaluate_root_goal(goal, GenerateProofTree::No).0 {
+                    match infcx.evaluate_root_goal(goal, GenerateProofTree::IfEnabled).0 {
                         Ok(result) => result,
                         Err(NoSolution) => {
                             errors.push(FulfillmentError {
diff --git a/compiler/rustc_trait_selection/src/solve/inspect.rs b/compiler/rustc_trait_selection/src/solve/inspect.rs
index 2d6717fdad9..cda68396321 100644
--- a/compiler/rustc_trait_selection/src/solve/inspect.rs
+++ b/compiler/rustc_trait_selection/src/solve/inspect.rs
@@ -200,30 +200,23 @@ impl<'tcx> ProofTreeBuilder<'tcx> {
         tcx: TyCtxt<'tcx>,
         generate_proof_tree: GenerateProofTree,
     ) -> ProofTreeBuilder<'tcx> {
-        let generate_proof_tree = match (
-            tcx.sess.opts.unstable_opts.dump_solver_proof_tree,
-            tcx.sess.opts.unstable_opts.dump_solver_proof_tree_use_cache,
-            generate_proof_tree,
-        ) {
-            (_, Some(use_cache), GenerateProofTree::Yes(_)) => {
-                GenerateProofTree::Yes(UseGlobalCache::from_bool(use_cache))
-            }
-
-            (DumpSolverProofTree::Always, use_cache, GenerateProofTree::No) => {
-                let use_cache = use_cache.unwrap_or(true);
-                GenerateProofTree::Yes(UseGlobalCache::from_bool(use_cache))
-            }
-
-            (_, None, GenerateProofTree::Yes(_)) => generate_proof_tree,
-            (DumpSolverProofTree::Never, _, _) => generate_proof_tree,
-            (DumpSolverProofTree::OnError, _, _) => generate_proof_tree,
-        };
-
         match generate_proof_tree {
-            GenerateProofTree::No => ProofTreeBuilder::new_noop(),
-            GenerateProofTree::Yes(global_cache_disabled) => {
-                ProofTreeBuilder::new_root(global_cache_disabled)
+            GenerateProofTree::Never => ProofTreeBuilder::new_noop(),
+            GenerateProofTree::IfEnabled => {
+                let opts = &tcx.sess.opts.unstable_opts;
+                match opts.dump_solver_proof_tree {
+                    DumpSolverProofTree::Always => {
+                        let use_cache = opts.dump_solver_proof_tree_use_cache.unwrap_or(true);
+                        ProofTreeBuilder::new_root(UseGlobalCache::from_bool(use_cache))
+                    }
+                    // `OnError` is handled by reevaluating goals in error
+                    // reporting with `GenerateProofTree::Yes`.
+                    DumpSolverProofTree::OnError | DumpSolverProofTree::Never => {
+                        ProofTreeBuilder::new_noop()
+                    }
+                }
             }
+            GenerateProofTree::Yes(use_cache) => ProofTreeBuilder::new_root(use_cache),
         }
     }
 
diff --git a/compiler/rustc_trait_selection/src/solve/mod.rs b/compiler/rustc_trait_selection/src/solve/mod.rs
index 77809d8d2ba..1d9c975a97a 100644
--- a/compiler/rustc_trait_selection/src/solve/mod.rs
+++ b/compiler/rustc_trait_selection/src/solve/mod.rs
@@ -37,7 +37,7 @@ pub use eval_ctxt::{
     EvalCtxt, GenerateProofTree, InferCtxtEvalExt, InferCtxtSelectExt, UseGlobalCache,
 };
 pub use fulfill::FulfillmentCtxt;
-pub(crate) use normalize::deeply_normalize;
+pub(crate) use normalize::{deeply_normalize, deeply_normalize_with_skipped_universes};
 
 #[derive(Debug, Clone, Copy)]
 enum SolverMode {
@@ -123,10 +123,10 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
     #[instrument(level = "debug", skip(self))]
     fn compute_closure_kind_goal(
         &mut self,
-        goal: Goal<'tcx, (DefId, ty::SubstsRef<'tcx>, ty::ClosureKind)>,
+        goal: Goal<'tcx, (DefId, ty::GenericArgsRef<'tcx>, ty::ClosureKind)>,
     ) -> QueryResult<'tcx> {
-        let (_, substs, expected_kind) = goal.predicate;
-        let found_kind = substs.as_closure().kind_ty().to_opt_closure_kind();
+        let (_, args, expected_kind) = goal.predicate;
+        let found_kind = args.as_closure().kind_ty().to_opt_closure_kind();
 
         let Some(found_kind) = found_kind else {
             return self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS);
@@ -266,12 +266,11 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
             return Err(NoSolution);
         }
 
-        let Certainty::Maybe(maybe_cause) = responses.iter().fold(
-            Certainty::AMBIGUOUS,
-            |certainty, response| {
+        let Certainty::Maybe(maybe_cause) =
+            responses.iter().fold(Certainty::AMBIGUOUS, |certainty, response| {
                 certainty.unify_with(response.value.certainty)
-            },
-        ) else {
+            })
+        else {
             bug!("expected flounder response to be ambiguous")
         };
 
diff --git a/compiler/rustc_trait_selection/src/solve/normalize.rs b/compiler/rustc_trait_selection/src/solve/normalize.rs
index c388850d831..f51f4edb933 100644
--- a/compiler/rustc_trait_selection/src/solve/normalize.rs
+++ b/compiler/rustc_trait_selection/src/solve/normalize.rs
@@ -20,8 +20,22 @@ pub(crate) fn deeply_normalize<'tcx, T: TypeFoldable<TyCtxt<'tcx>>>(
     at: At<'_, 'tcx>,
     value: T,
 ) -> Result<T, Vec<FulfillmentError<'tcx>>> {
+    assert!(!value.has_escaping_bound_vars());
+    deeply_normalize_with_skipped_universes(at, value, vec![])
+}
+
+/// Deeply normalize all aliases in `value`. This does not handle inference and expects
+/// its input to be already fully resolved.
+///
+/// Additionally takes a list of universes which represents the binders which have been
+/// entered before passing `value` to the function.
+pub(crate) fn deeply_normalize_with_skipped_universes<'tcx, T: TypeFoldable<TyCtxt<'tcx>>>(
+    at: At<'_, 'tcx>,
+    value: T,
+    universes: Vec<Option<UniverseIndex>>,
+) -> Result<T, Vec<FulfillmentError<'tcx>>> {
     let fulfill_cx = FulfillmentCtxt::new(at.infcx);
-    let mut folder = NormalizationFolder { at, fulfill_cx, depth: 0, universes: Vec::new() };
+    let mut folder = NormalizationFolder { at, fulfill_cx, depth: 0, universes };
 
     value.try_fold_with(&mut folder)
 }
@@ -117,7 +131,7 @@ impl<'tcx> NormalizationFolder<'_, 'tcx> {
             self.at.cause.clone(),
             self.at.param_env,
             ty::Binder::dummy(ty::ProjectionPredicate {
-                projection_ty: tcx.mk_alias_ty(uv.def, uv.substs),
+                projection_ty: tcx.mk_alias_ty(uv.def, uv.args),
                 term: new_infer_ct.into(),
             }),
         );
diff --git a/compiler/rustc_trait_selection/src/solve/opaques.rs b/compiler/rustc_trait_selection/src/solve/opaques.rs
index 16194f5ad69..2e537d1c358 100644
--- a/compiler/rustc_trait_selection/src/solve/opaques.rs
+++ b/compiler/rustc_trait_selection/src/solve/opaques.rs
@@ -26,8 +26,8 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
                 if !self.can_define_opaque_ty(opaque_ty_def_id) {
                     return Err(NoSolution);
                 }
-                // FIXME: This may have issues when the substs contain aliases...
-                match self.tcx().uses_unique_placeholders_ignoring_regions(opaque_ty.substs) {
+                // FIXME: This may have issues when the args contain aliases...
+                match self.tcx().uses_unique_placeholders_ignoring_regions(opaque_ty.args) {
                     Err(NotUniqueParam::NotParam(param)) if param.is_non_region_infer() => {
                         return self.evaluate_added_goals_and_make_canonical_response(
                             Certainty::AMBIGUOUS,
@@ -40,7 +40,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
                 }
                 // Prefer opaques registered already.
                 let opaque_type_key =
-                    ty::OpaqueTypeKey { def_id: opaque_ty_def_id, substs: opaque_ty.substs };
+                    ty::OpaqueTypeKey { def_id: opaque_ty_def_id, args: opaque_ty.args };
                 let matches =
                     self.unify_existing_opaque_tys(goal.param_env, opaque_type_key, expected);
                 if !matches.is_empty() {
@@ -54,7 +54,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
                 self.insert_hidden_type(opaque_type_key, goal.param_env, expected)?;
                 self.add_item_bounds_for_hidden_type(
                     opaque_ty.def_id,
-                    opaque_ty.substs,
+                    opaque_ty.args,
                     goal.param_env,
                     expected,
                 );
@@ -65,7 +65,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
                 // e.g. assigning `impl Copy := NotCopy`
                 self.add_item_bounds_for_hidden_type(
                     opaque_ty.def_id,
-                    opaque_ty.substs,
+                    opaque_ty.args,
                     goal.param_env,
                     expected,
                 );
@@ -73,7 +73,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
             }
             (Reveal::All, _) => {
                 // FIXME: Add an assertion that opaque type storage is empty.
-                let actual = tcx.type_of(opaque_ty.def_id).subst(tcx, opaque_ty.substs);
+                let actual = tcx.type_of(opaque_ty.def_id).instantiate(tcx, opaque_ty.args);
                 self.eq(goal.param_env, expected, actual)?;
                 self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
             }
diff --git a/compiler/rustc_trait_selection/src/solve/project_goals.rs b/compiler/rustc_trait_selection/src/solve/project_goals.rs
index e53b784a756..564451a31ed 100644
--- a/compiler/rustc_trait_selection/src/solve/project_goals.rs
+++ b/compiler/rustc_trait_selection/src/solve/project_goals.rs
@@ -72,7 +72,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
             goal.param_env,
             ty::UnevaluatedConst::new(
                 goal.predicate.projection_ty.def_id,
-                goal.predicate.projection_ty.substs,
+                goal.predicate.projection_ty.args,
             ),
             self.tcx()
                 .type_of(goal.predicate.projection_ty.def_id)
@@ -142,93 +142,92 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
         let goal_trait_ref = goal.predicate.projection_ty.trait_ref(tcx);
         let impl_trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap();
         let drcx = DeepRejectCtxt { treat_obligation_params: TreatParams::ForLookup };
-        if !drcx.substs_refs_may_unify(goal_trait_ref.substs, impl_trait_ref.skip_binder().substs) {
+        if !drcx.args_refs_may_unify(goal_trait_ref.args, impl_trait_ref.skip_binder().args) {
             return Err(NoSolution);
         }
 
-        ecx.probe(
-            |r| CandidateKind::Candidate { name: "impl".into(), result: *r }).enter(
-            |ecx| {
-                let impl_substs = ecx.fresh_substs_for_item(impl_def_id);
-                let impl_trait_ref = impl_trait_ref.subst(tcx, impl_substs);
-
-                ecx.eq(goal.param_env, goal_trait_ref, impl_trait_ref)?;
-
-                let where_clause_bounds = tcx
-                    .predicates_of(impl_def_id)
-                    .instantiate(tcx, impl_substs)
-                    .predicates
-                    .into_iter()
-                    .map(|pred| goal.with(tcx, pred));
-                ecx.add_goals(where_clause_bounds);
-
-                // In case the associated item is hidden due to specialization, we have to
-                // return ambiguity this would otherwise be incomplete, resulting in
-                // unsoundness during coherence (#105782).
-                let Some(assoc_def) = fetch_eligible_assoc_item_def(
-                    ecx,
-                    goal.param_env,
-                    goal_trait_ref,
-                    goal.predicate.def_id(),
-                    impl_def_id
-                )? else {
-                    return ecx.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS);
-                };
-
-                if !assoc_def.item.defaultness(tcx).has_value() {
-                    let guar = tcx.sess.delay_span_bug(
-                        tcx.def_span(assoc_def.item.def_id),
-                        "missing value for assoc item in impl",
-                    );
-                    let error_term = match assoc_def.item.kind {
-                        ty::AssocKind::Const => ty::Const::new_error(tcx,
-                            guar,
-                            tcx.type_of(goal.predicate.def_id())
-                                .subst(tcx, goal.predicate.projection_ty.substs),
-                            )
-                            .into(),
-                        ty::AssocKind::Type => Ty::new_error(tcx,guar).into(),
-                        ty::AssocKind::Fn => unreachable!(),
-                    };
-                    ecx.eq(goal.param_env, goal.predicate.term, error_term)
-                        .expect("expected goal term to be fully unconstrained");
-                    return ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes);
-                }
+        ecx.probe(|r| CandidateKind::Candidate { name: "impl".into(), result: *r }).enter(|ecx| {
+            let impl_args = ecx.fresh_args_for_item(impl_def_id);
+            let impl_trait_ref = impl_trait_ref.instantiate(tcx, impl_args);
+
+            ecx.eq(goal.param_env, goal_trait_ref, impl_trait_ref)?;
+
+            let where_clause_bounds = tcx
+                .predicates_of(impl_def_id)
+                .instantiate(tcx, impl_args)
+                .predicates
+                .into_iter()
+                .map(|pred| goal.with(tcx, pred));
+            ecx.add_goals(where_clause_bounds);
+
+            // In case the associated item is hidden due to specialization, we have to
+            // return ambiguity this would otherwise be incomplete, resulting in
+            // unsoundness during coherence (#105782).
+            let Some(assoc_def) = fetch_eligible_assoc_item_def(
+                ecx,
+                goal.param_env,
+                goal_trait_ref,
+                goal.predicate.def_id(),
+                impl_def_id,
+            )?
+            else {
+                return ecx.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS);
+            };
 
-                // Getting the right substitutions here is complex, e.g. given:
-                // - a goal `<Vec<u32> as Trait<i32>>::Assoc<u64>`
-                // - the applicable impl `impl<T> Trait<i32> for Vec<T>`
-                // - and the impl which defines `Assoc` being `impl<T, U> Trait<U> for Vec<T>`
-                //
-                // We first rebase the goal substs onto the impl, going from `[Vec<u32>, i32, u64]`
-                // to `[u32, u64]`.
-                //
-                // And then map these substs to the substs of the defining impl of `Assoc`, going
-                // from `[u32, u64]` to `[u32, i32, u64]`.
-                let impl_substs_with_gat = goal.predicate.projection_ty.substs.rebase_onto(
-                    tcx,
-                    goal_trait_ref.def_id,
-                    impl_substs,
+            if !assoc_def.item.defaultness(tcx).has_value() {
+                let guar = tcx.sess.delay_span_bug(
+                    tcx.def_span(assoc_def.item.def_id),
+                    "missing value for assoc item in impl",
                 );
-                let substs = ecx.translate_substs(
-                    goal.param_env,
-                    impl_def_id,
-                    impl_substs_with_gat,
-                    assoc_def.defining_node,
-                );
-
-                // Finally we construct the actual value of the associated type.
-                let term = match assoc_def.item.kind {
-                    ty::AssocKind::Type => tcx.type_of(assoc_def.item.def_id).map_bound(|ty| ty.into()),
-                    ty::AssocKind::Const => bug!("associated const projection is not supported yet"),
-                    ty::AssocKind::Fn => unreachable!("we should never project to a fn"),
+                let error_term = match assoc_def.item.kind {
+                    ty::AssocKind::Const => ty::Const::new_error(
+                        tcx,
+                        guar,
+                        tcx.type_of(goal.predicate.def_id())
+                            .instantiate(tcx, goal.predicate.projection_ty.args),
+                    )
+                    .into(),
+                    ty::AssocKind::Type => Ty::new_error(tcx, guar).into(),
+                    ty::AssocKind::Fn => unreachable!(),
                 };
-
-                ecx.eq(goal.param_env, goal.predicate.term, term.subst(tcx, substs))
+                ecx.eq(goal.param_env, goal.predicate.term, error_term)
                     .expect("expected goal term to be fully unconstrained");
-                ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
-            },
-        )
+                return ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes);
+            }
+
+            // Getting the right args here is complex, e.g. given:
+            // - a goal `<Vec<u32> as Trait<i32>>::Assoc<u64>`
+            // - the applicable impl `impl<T> Trait<i32> for Vec<T>`
+            // - and the impl which defines `Assoc` being `impl<T, U> Trait<U> for Vec<T>`
+            //
+            // We first rebase the goal args onto the impl, going from `[Vec<u32>, i32, u64]`
+            // to `[u32, u64]`.
+            //
+            // And then map these args to the args of the defining impl of `Assoc`, going
+            // from `[u32, u64]` to `[u32, i32, u64]`.
+            let impl_args_with_gat = goal.predicate.projection_ty.args.rebase_onto(
+                tcx,
+                goal_trait_ref.def_id,
+                impl_args,
+            );
+            let args = ecx.translate_args(
+                goal.param_env,
+                impl_def_id,
+                impl_args_with_gat,
+                assoc_def.defining_node,
+            );
+
+            // Finally we construct the actual value of the associated type.
+            let term = match assoc_def.item.kind {
+                ty::AssocKind::Type => tcx.type_of(assoc_def.item.def_id).map_bound(|ty| ty.into()),
+                ty::AssocKind::Const => bug!("associated const projection is not supported yet"),
+                ty::AssocKind::Fn => unreachable!("we should never project to a fn"),
+            };
+
+            ecx.eq(goal.param_env, goal.predicate.term, term.instantiate(tcx, args))
+                .expect("expected goal term to be fully unconstrained");
+            ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
+        })
     }
 
     fn consider_auto_trait_candidate(
@@ -350,7 +349,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
                 ty::Dynamic(_, _, _) => {
                     let dyn_metadata = tcx.require_lang_item(LangItem::DynMetadata, None);
                     tcx.type_of(dyn_metadata)
-                        .subst(tcx, &[ty::GenericArg::from(goal.predicate.self_ty())])
+                        .instantiate(tcx, &[ty::GenericArg::from(goal.predicate.self_ty())])
                 }
 
                 ty::Alias(_, _) | ty::Param(_) | ty::Placeholder(..) => {
@@ -365,20 +364,18 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
                     tcx.types.unit
                 }
 
-                ty::Adt(def, substs) if def.is_struct() => {
-                    match def.non_enum_variant().tail_opt() {
-                        None => tcx.types.unit,
-                        Some(field_def) => {
-                            let self_ty = field_def.ty(tcx, substs);
-                            ecx.add_goal(goal.with(
-                                tcx,
-                                ty::Binder::dummy(goal.predicate.with_self_ty(tcx, self_ty)),
-                            ));
-                            return ecx
-                                .evaluate_added_goals_and_make_canonical_response(Certainty::Yes);
-                        }
+                ty::Adt(def, args) if def.is_struct() => match def.non_enum_variant().tail_opt() {
+                    None => tcx.types.unit,
+                    Some(field_def) => {
+                        let self_ty = field_def.ty(tcx, args);
+                        ecx.add_goal(goal.with(
+                            tcx,
+                            ty::Binder::dummy(goal.predicate.with_self_ty(tcx, self_ty)),
+                        ));
+                        return ecx
+                            .evaluate_added_goals_and_make_canonical_response(Certainty::Yes);
                     }
-                }
+                },
                 ty::Adt(_, _) => tcx.types.unit,
 
                 ty::Tuple(elements) => match elements.last() {
@@ -413,7 +410,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
         goal: Goal<'tcx, Self>,
     ) -> QueryResult<'tcx> {
         let self_ty = goal.predicate.self_ty();
-        let ty::Generator(def_id, substs, _) = *self_ty.kind() else {
+        let ty::Generator(def_id, args, _) = *self_ty.kind() else {
             return Err(NoSolution);
         };
 
@@ -423,7 +420,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
             return Err(NoSolution);
         }
 
-        let term = substs.as_generator().return_ty().into();
+        let term = args.as_generator().return_ty().into();
 
         Self::consider_implied_clause(
             ecx,
@@ -444,7 +441,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
         goal: Goal<'tcx, Self>,
     ) -> QueryResult<'tcx> {
         let self_ty = goal.predicate.self_ty();
-        let ty::Generator(def_id, substs, _) = *self_ty.kind() else {
+        let ty::Generator(def_id, args, _) = *self_ty.kind() else {
             return Err(NoSolution);
         };
 
@@ -454,7 +451,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
             return Err(NoSolution);
         }
 
-        let generator = substs.as_generator();
+        let generator = args.as_generator();
 
         let name = tcx.associated_item(goal.predicate.def_id()).name;
         let term = if name == sym::Return {
diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals.rs b/compiler/rustc_trait_selection/src/solve/trait_goals.rs
index ef5f25b1f7f..e7867eead15 100644
--- a/compiler/rustc_trait_selection/src/solve/trait_goals.rs
+++ b/compiler/rustc_trait_selection/src/solve/trait_goals.rs
@@ -39,10 +39,9 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
 
         let impl_trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap();
         let drcx = DeepRejectCtxt { treat_obligation_params: TreatParams::ForLookup };
-        if !drcx.substs_refs_may_unify(
-            goal.predicate.trait_ref.substs,
-            impl_trait_ref.skip_binder().substs,
-        ) {
+        if !drcx
+            .args_refs_may_unify(goal.predicate.trait_ref.args, impl_trait_ref.skip_binder().args)
+        {
             return Err(NoSolution);
         }
 
@@ -63,13 +62,13 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
         };
 
         ecx.probe_candidate("impl").enter(|ecx| {
-            let impl_substs = ecx.fresh_substs_for_item(impl_def_id);
-            let impl_trait_ref = impl_trait_ref.subst(tcx, impl_substs);
+            let impl_args = ecx.fresh_args_for_item(impl_def_id);
+            let impl_trait_ref = impl_trait_ref.instantiate(tcx, impl_args);
 
             ecx.eq(goal.param_env, goal.predicate.trait_ref, impl_trait_ref)?;
             let where_clause_bounds = tcx
                 .predicates_of(impl_def_id)
-                .instantiate(tcx, impl_substs)
+                .instantiate(tcx, impl_args)
                 .predicates
                 .into_iter()
                 .map(|pred| goal.with(tcx, pred));
@@ -164,7 +163,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
         ecx.probe_candidate("trait alias").enter(|ecx| {
             let nested_obligations = tcx
                 .predicates_of(goal.predicate.def_id())
-                .instantiate(tcx, goal.predicate.trait_ref.substs);
+                .instantiate(tcx, goal.predicate.trait_ref.args);
             ecx.add_goals(nested_obligations.predicates.into_iter().map(|p| goal.with(tcx, p)));
             ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
         })
@@ -337,7 +336,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
         }
 
         let self_ty = goal.predicate.self_ty();
-        let ty::Generator(def_id, substs, _) = *self_ty.kind() else {
+        let ty::Generator(def_id, args, _) = *self_ty.kind() else {
             return Err(NoSolution);
         };
 
@@ -347,7 +346,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
             return Err(NoSolution);
         }
 
-        let generator = substs.as_generator();
+        let generator = args.as_generator();
         Self::consider_implied_clause(
             ecx,
             goal,
@@ -369,7 +368,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
 
         let tcx = ecx.tcx();
         let a_ty = goal.predicate.self_ty();
-        let b_ty = goal.predicate.trait_ref.substs.type_at(1);
+        let b_ty = goal.predicate.trait_ref.args.type_at(1);
         if b_ty.is_ty_var() {
             return ecx.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS);
         }
@@ -378,7 +377,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
                 // Trait upcasting, or `dyn Trait + Auto + 'a` -> `dyn Trait + 'b`
                 (&ty::Dynamic(_, _, ty::Dyn), &ty::Dynamic(_, _, ty::Dyn)) => {
                     // Dyn upcasting is handled separately, since due to upcasting,
-                    // when there are two supertraits that differ by substs, we
+                    // when there are two supertraits that differ by args, we
                     // may return more than one query response.
                     Err(NoSolution)
                 }
@@ -415,7 +414,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
                     ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
                 }
                 // Struct unsizing `Struct<T>` -> `Struct<U>` where `T: Unsize<U>`
-                (&ty::Adt(a_def, a_substs), &ty::Adt(b_def, b_substs))
+                (&ty::Adt(a_def, a_args), &ty::Adt(b_def, b_args))
                     if a_def.is_struct() && a_def.did() == b_def.did() =>
                 {
                     let unsizing_params = tcx.unsizing_params_for_adt(a_def.did());
@@ -428,17 +427,17 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
                     let tail_field = a_def.non_enum_variant().tail();
                     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);
+                    let a_tail_ty = tail_field_ty.instantiate(tcx, a_args);
+                    let b_tail_ty = tail_field_ty.instantiate(tcx, b_args);
 
                     // Substitute just the unsizing params from B into A. The type after
                     // this substitution must be equal to B. This is so we don't unsize
                     // unrelated type parameters.
-                    let new_a_substs =
-                        tcx.mk_substs_from_iter(a_substs.iter().enumerate().map(|(i, a)| {
-                            if unsizing_params.contains(i as u32) { b_substs[i] } else { a }
+                    let new_a_args =
+                        tcx.mk_args_from_iter(a_args.iter().enumerate().map(|(i, a)| {
+                            if unsizing_params.contains(i as u32) { b_args[i] } else { a }
                         }));
-                    let unsized_a_ty = Ty::new_adt(tcx, a_def, new_a_substs);
+                    let unsized_a_ty = Ty::new_adt(tcx, a_def, new_a_args);
 
                     // Finally, we require that `TailA: Unsize<TailB>` for the tail field
                     // types.
@@ -484,7 +483,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
         let tcx = ecx.tcx();
 
         let a_ty = goal.predicate.self_ty();
-        let b_ty = goal.predicate.trait_ref.substs.type_at(1);
+        let b_ty = goal.predicate.trait_ref.args.type_at(1);
         let ty::Dynamic(a_data, a_region, ty::Dyn) = *a_ty.kind() else {
             return vec![];
         };
@@ -598,19 +597,17 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
 
         // Erase regions because we compute layouts in `rustc_transmute`,
         // which will ICE for region vars.
-        let substs = ecx.tcx().erase_regions(goal.predicate.trait_ref.substs);
+        let args = ecx.tcx().erase_regions(goal.predicate.trait_ref.args);
 
-        let Some(assume) = rustc_transmute::Assume::from_const(
-            ecx.tcx(),
-            goal.param_env,
-            substs.const_at(3),
-        ) else {
+        let Some(assume) =
+            rustc_transmute::Assume::from_const(ecx.tcx(), goal.param_env, args.const_at(3))
+        else {
             return Err(NoSolution);
         };
 
         let certainty = ecx.is_transmutable(
-            rustc_transmute::Types { dst: substs.type_at(0), src: substs.type_at(1) },
-            substs.type_at(2),
+            rustc_transmute::Types { dst: args.type_at(0), src: args.type_at(1) },
+            args.type_at(2),
             assume,
         )?;
         ecx.evaluate_added_goals_and_make_canonical_response(certainty)
diff --git a/compiler/rustc_trait_selection/src/solve/weak_types.rs b/compiler/rustc_trait_selection/src/solve/weak_types.rs
index b095b54c554..2c176d4cfd6 100644
--- a/compiler/rustc_trait_selection/src/solve/weak_types.rs
+++ b/compiler/rustc_trait_selection/src/solve/weak_types.rs
@@ -12,7 +12,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
         let weak_ty = goal.predicate.projection_ty;
         let expected = goal.predicate.term.ty().expect("no such thing as a const alias");
 
-        let actual = tcx.type_of(weak_ty.def_id).subst(tcx, weak_ty.substs);
+        let actual = tcx.type_of(weak_ty.def_id).instantiate(tcx, weak_ty.args);
         self.eq(goal.param_env, expected, actual)?;
         self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
     }
diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs
index cb38d0ac847..27cd0f99f34 100644
--- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs
+++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs
@@ -152,14 +152,9 @@ impl<'tcx> AutoTraitFinder<'tcx> {
         // traits::project will see that 'T: SomeTrait' is in our ParamEnv, allowing
         // SelectionContext to return it back to us.
 
-        let Some((new_env, user_env)) = self.evaluate_predicates(
-            &infcx,
-            trait_did,
-            ty,
-            orig_env,
-            orig_env,
-            &mut fresh_preds,
-        ) else {
+        let Some((new_env, user_env)) =
+            self.evaluate_predicates(&infcx, trait_did, ty, orig_env, orig_env, &mut fresh_preds)
+        else {
             return AutoTraitResult::NegativeImpl;
         };
 
@@ -329,7 +324,7 @@ impl<'tcx> AutoTraitFinder<'tcx> {
                 }
                 Ok(None) => {}
                 Err(SelectionError::Unimplemented) => {
-                    if self.is_param_no_infer(pred.skip_binder().trait_ref.substs) {
+                    if self.is_param_no_infer(pred.skip_binder().trait_ref.args) {
                         already_visited.remove(&pred);
                         self.add_user_pred(&mut user_computed_preds, pred.to_predicate(self.tcx));
                         predicates.push_back(pred);
@@ -339,7 +334,7 @@ impl<'tcx> AutoTraitFinder<'tcx> {
                              {:?} {:?} {:?}",
                             ty,
                             pred,
-                            pred.skip_binder().trait_ref.substs
+                            pred.skip_binder().trait_ref.args
                         );
                         return None;
                     }
@@ -406,17 +401,17 @@ impl<'tcx> AutoTraitFinder<'tcx> {
             ) = (new_pred.kind().skip_binder(), old_pred.kind().skip_binder())
             {
                 if new_trait.def_id() == old_trait.def_id() {
-                    let new_substs = new_trait.trait_ref.substs;
-                    let old_substs = old_trait.trait_ref.substs;
+                    let new_args = new_trait.trait_ref.args;
+                    let old_args = old_trait.trait_ref.args;
 
-                    if !new_substs.types().eq(old_substs.types()) {
+                    if !new_args.types().eq(old_args.types()) {
                         // We can't compare lifetimes if the types are different,
                         // so skip checking `old_pred`.
                         return true;
                     }
 
                     for (new_region, old_region) in
-                        iter::zip(new_substs.regions(), old_substs.regions())
+                        iter::zip(new_args.regions(), old_args.regions())
                     {
                         match (*new_region, *old_region) {
                             // If both predicates have an `ReLateBound` (a HRTB) in the
@@ -569,8 +564,8 @@ impl<'tcx> AutoTraitFinder<'tcx> {
         finished_map
     }
 
-    fn is_param_no_infer(&self, substs: SubstsRef<'_>) -> bool {
-        self.is_of_param(substs.type_at(0)) && !substs.types().any(|t| t.has_infer_types())
+    fn is_param_no_infer(&self, args: GenericArgsRef<'_>) -> bool {
+        self.is_of_param(args.type_at(0)) && !args.types().any(|t| t.has_infer_types())
     }
 
     pub fn is_of_param(&self, ty: Ty<'_>) -> bool {
@@ -641,7 +636,7 @@ impl<'tcx> AutoTraitFinder<'tcx> {
                     // an inference variable.
                     // Additionally, we check if we've seen this predicate before,
                     // to avoid rendering duplicate bounds to the user.
-                    if self.is_param_no_infer(p.skip_binder().projection_ty.substs)
+                    if self.is_param_no_infer(p.skip_binder().projection_ty.args)
                         && !p.term().skip_binder().has_infer_types()
                         && is_new_pred
                     {
diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs
index 1b1285e1b46..039e4ec9afd 100644
--- a/compiler/rustc_trait_selection/src/traits/coherence.rs
+++ b/compiler/rustc_trait_selection/src/traits/coherence.rs
@@ -96,9 +96,7 @@ pub fn overlapping_impls(
     let impl1_ref = tcx.impl_trait_ref(impl1_def_id);
     let impl2_ref = tcx.impl_trait_ref(impl2_def_id);
     let may_overlap = match (impl1_ref, impl2_ref) {
-        (Some(a), Some(b)) => {
-            drcx.substs_refs_may_unify(a.skip_binder().substs, b.skip_binder().substs)
-        }
+        (Some(a), Some(b)) => drcx.args_refs_may_unify(a.skip_binder().args, b.skip_binder().args),
         (None, None) => {
             let self_ty1 = tcx.type_of(impl1_def_id).skip_binder();
             let self_ty2 = tcx.type_of(impl2_def_id).skip_binder();
@@ -143,15 +141,15 @@ fn with_fresh_ty_vars<'cx, 'tcx>(
     impl_def_id: DefId,
 ) -> ty::ImplHeader<'tcx> {
     let tcx = selcx.tcx();
-    let impl_substs = selcx.infcx.fresh_substs_for_item(DUMMY_SP, impl_def_id);
+    let impl_args = selcx.infcx.fresh_args_for_item(DUMMY_SP, impl_def_id);
 
     let header = ty::ImplHeader {
         impl_def_id,
-        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)),
+        self_ty: tcx.type_of(impl_def_id).instantiate(tcx, impl_args),
+        trait_ref: tcx.impl_trait_ref(impl_def_id).map(|i| i.instantiate(tcx, impl_args)),
         predicates: tcx
             .predicates_of(impl_def_id)
-            .instantiate(tcx, impl_substs)
+            .instantiate(tcx, impl_args)
             .iter()
             .map(|(c, _)| c.as_predicate())
             .collect(),
@@ -353,7 +351,7 @@ fn impl_intersection_has_negative_obligation(
         &infcx,
         ObligationCause::dummy(),
         impl_env,
-        tcx.impl_subject(impl1_def_id).subst_identity(),
+        tcx.impl_subject(impl1_def_id).instantiate_identity(),
     ) {
         Ok(s) => s,
         Err(err) => {
@@ -367,16 +365,16 @@ fn impl_intersection_has_negative_obligation(
 
     // Attempt to prove that impl2 applies, given all of the above.
     let selcx = &mut SelectionContext::new(&infcx);
-    let impl2_substs = infcx.fresh_substs_for_item(DUMMY_SP, impl2_def_id);
+    let impl2_args = infcx.fresh_args_for_item(DUMMY_SP, impl2_def_id);
     let (subject2, normalization_obligations) =
-        impl_subject_and_oblig(selcx, impl_env, impl2_def_id, impl2_substs, |_, _| {
+        impl_subject_and_oblig(selcx, impl_env, impl2_def_id, impl2_args, |_, _| {
             ObligationCause::dummy()
         });
 
     // do the impls unify? If not, then it's not currently possible to prove any
     // obligations about their intersection.
     let Ok(InferOk { obligations: equate_obligations, .. }) =
-        infcx.at(&ObligationCause::dummy(), impl_env).eq(DefineOpaqueTypes::No,subject1, subject2)
+        infcx.at(&ObligationCause::dummy(), impl_env).eq(DefineOpaqueTypes::No, subject1, subject2)
     else {
         debug!("explicit_disjoint: {:?} does not unify with {:?}", subject1, subject2);
         return false;
@@ -437,8 +435,7 @@ fn prove_negated_obligation<'tcx>(
     let body_def_id = body_def_id.as_local().unwrap_or(CRATE_DEF_ID);
 
     let ocx = ObligationCtxt::new(&infcx);
-    let Ok(wf_tys) = ocx.assumed_wf_types(param_env, body_def_id)
-    else {
+    let Ok(wf_tys) = ocx.assumed_wf_types(param_env, body_def_id) else {
         return false;
     };
 
@@ -520,7 +517,7 @@ pub enum OrphanCheckErr<'tcx> {
 pub fn orphan_check(tcx: TyCtxt<'_>, impl_def_id: DefId) -> Result<(), OrphanCheckErr<'_>> {
     // We only except this routine to be invoked on implementations
     // of a trait, not inherent implementations.
-    let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap().subst_identity();
+    let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap().instantiate_identity();
     debug!(?trait_ref);
 
     // If the *trait* is local to the crate, ok.
@@ -729,11 +726,11 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for OrphanChecker<'tcx> {
 
             // For fundamental types, we just look inside of them.
             ty::Ref(_, ty, _) => ty.visit_with(self),
-            ty::Adt(def, substs) => {
+            ty::Adt(def, args) => {
                 if self.def_id_is_local(def.did()) {
                     ControlFlow::Break(OrphanCheckEarlyExit::LocalTy(ty))
                 } else if def.is_fundamental() {
-                    substs.visit_with(self)
+                    args.visit_with(self)
                 } else {
                     self.found_non_local_ty(ty)
                 }
diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
index 8dc13b827e5..3d0d3812d0c 100644
--- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
+++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
@@ -191,7 +191,7 @@ fn satisfied_from_param_env<'tcx>(
             if let ty::ConstKind::Expr(e) = c.kind() {
                 e.visit_with(self)
             } else {
-                // FIXME(generic_const_exprs): This doesn't recurse into `<T as Trait<U>>::ASSOC`'s substs.
+                // FIXME(generic_const_exprs): This doesn't recurse into `<T as Trait<U>>::ASSOC`'s args.
                 // This is currently unobservable as `<T as Trait<{ U + 1 }>>::ASSOC` creates an anon const
                 // with its own `ConstEvaluatable` bound in the param env which we will visit separately.
                 //
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs
index f785c4eaf9d..fd813ca4ecb 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs
@@ -26,8 +26,8 @@ pub fn recompute_applicable_impls<'tcx>(
         let obligation_trait_ref =
             ocx.normalize(&ObligationCause::dummy(), param_env, placeholder_obligation.trait_ref);
 
-        let impl_substs = infcx.fresh_substs_for_item(DUMMY_SP, impl_def_id);
-        let impl_trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap().subst(tcx, impl_substs);
+        let impl_args = infcx.fresh_args_for_item(DUMMY_SP, impl_def_id);
+        let impl_trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap().instantiate(tcx, impl_args);
         let impl_trait_ref = ocx.normalize(&ObligationCause::dummy(), param_env, impl_trait_ref);
 
         if let Err(_) =
@@ -36,7 +36,7 @@ pub fn recompute_applicable_impls<'tcx>(
             return false;
         }
 
-        let impl_predicates = tcx.predicates_of(impl_def_id).instantiate(tcx, impl_substs);
+        let impl_predicates = tcx.predicates_of(impl_def_id).instantiate(tcx, impl_args);
         ocx.register_obligations(impl_predicates.predicates.iter().map(|&predicate| {
             Obligation::new(tcx, ObligationCause::dummy(), param_env, predicate)
         }));
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 4dc06d2bfac..a821d1be64b 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
@@ -1050,8 +1050,8 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                         report_object_safety_error(self.tcx, span, trait_def_id, violations)
                     }
 
-                    ty::PredicateKind::ClosureKind(closure_def_id, closure_substs, kind) => {
-                        let found_kind = self.closure_kind(closure_substs).unwrap();
+                    ty::PredicateKind::ClosureKind(closure_def_id, closure_args, kind) => {
+                        let found_kind = self.closure_kind(closure_args).unwrap();
                         self.report_closure_error(&obligation, closure_def_id, found_kind, kind)
                     }
 
@@ -1627,14 +1627,14 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                     ty::TermKind::Ty(_) => Ty::new_projection(
                         self.tcx,
                         data.projection_ty.def_id,
-                        data.projection_ty.substs,
+                        data.projection_ty.args,
                     )
                     .into(),
                     ty::TermKind::Const(ct) => ty::Const::new_unevaluated(
                         self.tcx,
                         ty::UnevaluatedConst {
                             def: data.projection_ty.def_id,
-                            substs: data.projection_ty.substs,
+                            args: data.projection_ty.args,
                         },
                         ct.ty(),
                     )
@@ -1972,7 +1972,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
             traits.sort();
             traits.dedup();
             // FIXME: this could use a better heuristic, like just checking
-            // that substs[1..] is the same.
+            // that args[1..] is the same.
             let all_traits_equal = traits.len() == 1;
 
             let candidates: Vec<String> = candidates
@@ -2018,7 +2018,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                         || self.tcx.is_automatically_derived(def_id)
                 })
                 .filter_map(|def_id| self.tcx.impl_trait_ref(def_id))
-                .map(ty::EarlyBinder::subst_identity)
+                .map(ty::EarlyBinder::instantiate_identity)
                 .filter(|trait_ref| {
                     let self_ty = trait_ref.self_ty();
                     // Avoid mentioning type parameters.
@@ -2267,7 +2267,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                 // Pick the first substitution that still contains inference variables as the one
                 // we're going to emit an error for. If there are none (see above), fall back to
                 // a more general error.
-                let subst = data.trait_ref.substs.iter().find(|s| s.has_non_region_infer());
+                let subst = data.trait_ref.args.iter().find(|s| s.has_non_region_infer());
 
                 let mut err = if let Some(subst) = subst {
                     self.emit_inference_failure_err(
@@ -2292,7 +2292,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                     &obligation.with(self.tcx, trait_ref),
                 );
                 let has_non_region_infer =
-                    trait_ref.skip_binder().substs.types().any(|t| !t.is_ty_or_numeric_infer());
+                    trait_ref.skip_binder().args.types().any(|t| !t.is_ty_or_numeric_infer());
                 // It doesn't make sense to talk about applicable impls if there are more
                 // than a handful of them.
                 if ambiguities.len() > 1 && ambiguities.len() < 10 && has_non_region_infer {
@@ -2330,7 +2330,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                     self.suggest_fully_qualified_path(&mut err, def_id, span, trait_ref.def_id());
                 }
 
-                if let Some(ty::subst::GenericArgKind::Type(_)) = subst.map(|subst| subst.unpack())
+                if let Some(ty::GenericArgKind::Type(_)) = subst.map(|subst| subst.unpack())
                     && let Some(body_id) = self.tcx.hir().maybe_body_owned_by(obligation.cause.body_id)
                 {
                     let mut expr_finder = FindExprBySpan::new(span);
@@ -2389,7 +2389,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                             // Otherwise, use a placeholder comment for the implementation.
                             let (message, impl_suggestion) = if non_blanket_impl_count == 1 {(
                                 "use the fully-qualified path to the only available implementation".to_string(),
-                                format!("<{} as ", self.tcx.type_of(impl_def_id).subst_identity())
+                                format!("<{} as ", self.tcx.type_of(impl_def_id).instantiate_identity())
                             )} else {(
                                 format!(
                                     "use a fully-qualified path to a specific available implementation ({} found)",
@@ -2466,7 +2466,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                 }
                 let subst = data
                     .projection_ty
-                    .substs
+                    .args
                     .iter()
                     .chain(Some(data.term.into_arg()))
                     .find(|g| g.has_non_region_infer());
@@ -2708,10 +2708,17 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
         err: &mut Diagnostic,
         obligation: &PredicateObligation<'tcx>,
     ) {
-        let ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) = obligation.predicate.kind().skip_binder() else { return; };
+        let ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) =
+            obligation.predicate.kind().skip_binder()
+        else {
+            return;
+        };
         let (ObligationCauseCode::BindingObligation(item_def_id, span)
-        | ObligationCauseCode::ExprBindingObligation(item_def_id, span, ..))
-            = *obligation.cause.code().peel_derives() else { return; };
+        | ObligationCauseCode::ExprBindingObligation(item_def_id, span, ..)) =
+            *obligation.cause.code().peel_derives()
+        else {
+            return;
+        };
         debug!(?pred, ?item_def_id, ?span);
 
         let (Some(node), true) = (
@@ -2822,9 +2829,9 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
             if obligated_types.iter().any(|ot| ot == &self_ty) {
                 return true;
             }
-            if let ty::Adt(def, substs) = self_ty.kind()
-                && let [arg] = &substs[..]
-                && let ty::subst::GenericArgKind::Type(ty) = arg.unpack()
+            if let ty::Adt(def, args) = self_ty.kind()
+                && let [arg] = &args[..]
+                && let ty::GenericArgKind::Type(ty) = arg.unpack()
                 && let ty::Adt(inner_def, _) = ty.kind()
                 && inner_def == def
             {
@@ -2876,14 +2883,20 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
         let trait_ref = self.tcx.erase_regions(self.tcx.erase_late_bound_regions(trait_ref));
 
         let src_and_dst = rustc_transmute::Types {
-            dst: trait_ref.substs.type_at(0),
-            src: trait_ref.substs.type_at(1),
+            dst: trait_ref.args.type_at(0),
+            src: trait_ref.args.type_at(1),
+        };
+        let scope = trait_ref.args.type_at(2);
+        let Some(assume) = rustc_transmute::Assume::from_const(
+            self.infcx.tcx,
+            obligation.param_env,
+            trait_ref.args.const_at(3),
+        ) else {
+            span_bug!(
+                span,
+                "Unable to construct rustc_transmute::Assume where it was previously possible"
+            );
         };
-        let scope = trait_ref.substs.type_at(2);
-        let Some(assume) =
-            rustc_transmute::Assume::from_const(self.infcx.tcx, obligation.param_env, trait_ref.substs.const_at(3)) else {
-                span_bug!(span, "Unable to construct rustc_transmute::Assume where it was previously possible");
-            };
 
         match rustc_transmute::TransmuteTypeEnv::new(self.infcx).is_transmutable(
             obligation.cause,
@@ -2892,8 +2905,8 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
             assume,
         ) {
             Answer::No(reason) => {
-                let dst = trait_ref.substs.type_at(0);
-                let src = trait_ref.substs.type_at(1);
+                let dst = trait_ref.args.type_at(0);
+                let src = trait_ref.args.type_at(1);
                 let err_msg = format!(
                     "`{src}` cannot be safely transmuted into `{dst}` in the defining scope of `{scope}`"
                 );
@@ -3060,7 +3073,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
 
         // Note any argument mismatches
         let given_ty = params.skip_binder();
-        let expected_ty = trait_ref.skip_binder().substs.type_at(1);
+        let expected_ty = trait_ref.skip_binder().args.type_at(1);
         if let ty::Tuple(given) = given_ty.kind()
             && let ty::Tuple(expected) = expected_ty.kind()
         {
@@ -3275,7 +3288,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
 
         let mut not_tupled = false;
 
-        let found = match found_trait_ref.skip_binder().substs.type_at(1).kind() {
+        let found = match found_trait_ref.skip_binder().args.type_at(1).kind() {
             ty::Tuple(ref tys) => vec![ArgKind::empty(); tys.len()],
             _ => {
                 not_tupled = true;
@@ -3283,7 +3296,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
             }
         };
 
-        let expected_ty = expected_trait_ref.skip_binder().substs.type_at(1);
+        let expected_ty = expected_trait_ref.skip_binder().args.type_at(1);
         let expected = match expected_ty.kind() {
             ty::Tuple(ref tys) => {
                 tys.iter().map(|t| ArgKind::from_expected_ty(t, Some(span))).collect()
@@ -3556,7 +3569,7 @@ pub fn dump_proof_tree<'tcx>(o: &Obligation<'tcx, ty::Predicate<'tcx>>, infcx: &
             .1
             .expect("proof tree should have been generated");
         let mut lock = std::io::stdout().lock();
-        let _ = lock.write_fmt(format_args!("{tree:?}"));
+        let _ = lock.write_fmt(format_args!("{tree:?}\n"));
         let _ = lock.flush();
     });
 }
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 b16d2eb5fc1..fbe8d4a6680 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
@@ -6,7 +6,7 @@ use rustc_data_structures::fx::FxHashMap;
 use rustc_errors::{struct_span_err, ErrorGuaranteed};
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
-use rustc_middle::ty::SubstsRef;
+use rustc_middle::ty::GenericArgsRef;
 use rustc_middle::ty::{self, GenericParamDefKind, TyCtxt};
 use rustc_parse_format::{ParseMode, Parser, Piece, Position};
 use rustc_span::symbol::{kw, sym, Symbol};
@@ -25,7 +25,7 @@ pub trait TypeErrCtxtExt<'tcx> {
         &self,
         trait_ref: ty::PolyTraitRef<'tcx>,
         obligation: &PredicateObligation<'tcx>,
-    ) -> Option<(DefId, SubstsRef<'tcx>)>;
+    ) -> Option<(DefId, GenericArgsRef<'tcx>)>;
 
     /*private*/
     fn describe_enclosure(&self, hir_id: hir::HirId) -> Option<&'static str>;
@@ -56,7 +56,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
         &self,
         trait_ref: ty::PolyTraitRef<'tcx>,
         obligation: &PredicateObligation<'tcx>,
-    ) -> Option<(DefId, SubstsRef<'tcx>)> {
+    ) -> Option<(DefId, GenericArgsRef<'tcx>)> {
         let tcx = self.tcx;
         let param_env = obligation.param_env;
         let trait_ref = self.instantiate_binder_with_placeholders(trait_ref);
@@ -66,26 +66,23 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
         let mut fuzzy_match_impls = vec![];
 
         self.tcx.for_each_relevant_impl(trait_ref.def_id, trait_self_ty, |def_id| {
-            let impl_substs = self.fresh_substs_for_item(obligation.cause.span, def_id);
-            let impl_trait_ref = tcx.impl_trait_ref(def_id).unwrap().subst(tcx, impl_substs);
+            let impl_args = self.fresh_args_for_item(obligation.cause.span, def_id);
+            let impl_trait_ref = tcx.impl_trait_ref(def_id).unwrap().instantiate(tcx, impl_args);
 
             let impl_self_ty = impl_trait_ref.self_ty();
 
             if self.can_eq(param_env, trait_self_ty, impl_self_ty) {
-                self_match_impls.push((def_id, impl_substs));
+                self_match_impls.push((def_id, impl_args));
 
-                if iter::zip(
-                    trait_ref.substs.types().skip(1),
-                    impl_trait_ref.substs.types().skip(1),
-                )
-                .all(|(u, v)| self.fuzzy_match_tys(u, v, false).is_some())
+                if iter::zip(trait_ref.args.types().skip(1), impl_trait_ref.args.types().skip(1))
+                    .all(|(u, v)| self.fuzzy_match_tys(u, v, false).is_some())
                 {
-                    fuzzy_match_impls.push((def_id, impl_substs));
+                    fuzzy_match_impls.push((def_id, impl_args));
                 }
             }
         });
 
-        let impl_def_id_and_substs = if self_match_impls.len() == 1 {
+        let impl_def_id_and_args = if self_match_impls.len() == 1 {
             self_match_impls[0]
         } else if fuzzy_match_impls.len() == 1 {
             fuzzy_match_impls[0]
@@ -93,8 +90,8 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
             return None;
         };
 
-        tcx.has_attr(impl_def_id_and_substs.0, sym::rustc_on_unimplemented)
-            .then_some(impl_def_id_and_substs)
+        tcx.has_attr(impl_def_id_and_args.0, sym::rustc_on_unimplemented)
+            .then_some(impl_def_id_and_args)
     }
 
     /// Used to set on_unimplemented's `ItemContext`
@@ -143,9 +140,9 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
         trait_ref: ty::PolyTraitRef<'tcx>,
         obligation: &PredicateObligation<'tcx>,
     ) -> OnUnimplementedNote {
-        let (def_id, substs) = self
+        let (def_id, args) = self
             .impl_similar_to(trait_ref, obligation)
-            .unwrap_or_else(|| (trait_ref.def_id(), trait_ref.skip_binder().substs));
+            .unwrap_or_else(|| (trait_ref.def_id(), trait_ref.skip_binder().args));
         let trait_ref = trait_ref.skip_binder();
 
         let mut flags = vec![];
@@ -192,14 +189,14 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                 // signature with no type arguments resolved
                 flags.push((
                     sym::_Self,
-                    Some(self.tcx.type_of(def.did()).subst_identity().to_string()),
+                    Some(self.tcx.type_of(def.did()).instantiate_identity().to_string()),
                 ));
             }
 
             for param in generics.params.iter() {
                 let value = match param.kind {
                     GenericParamDefKind::Type { .. } | GenericParamDefKind::Const { .. } => {
-                        substs[param.index as usize].to_string()
+                        args[param.index as usize].to_string()
                     }
                     GenericParamDefKind::Lifetime => continue,
                 };
@@ -207,13 +204,13 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                 flags.push((name, Some(value)));
 
                 if let GenericParamDefKind::Type { .. } = param.kind {
-                    let param_ty = substs[param.index as usize].expect_ty();
+                    let param_ty = args[param.index as usize].expect_ty();
                     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()).subst_identity().to_string()),
+                            Some(self.tcx.type_of(def.did()).instantiate_identity().to_string()),
                         ));
                     }
                 }
@@ -249,7 +246,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                     // signature with no type arguments resolved
                     flags.push((
                         sym::_Self,
-                        Some(format!("[{}]", self.tcx.type_of(def.did()).subst_identity())),
+                        Some(format!("[{}]", self.tcx.type_of(def.did()).instantiate_identity())),
                     ));
                 }
                 if aty.is_integral() {
@@ -268,7 +265,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()).subst_identity();
+                    let def_ty = self.tcx.type_of(def.did()).instantiate_identity();
                     flags.push((sym::_Self, Some(format!("[{def_ty}; _]"))));
                     if let Some(n) = len {
                         flags.push((sym::_Self, Some(format!("[{def_ty}; {n}]"))));
@@ -629,7 +626,7 @@ impl<'tcx> OnUnimplementedFormatString {
             .filter_map(|param| {
                 let value = match param.kind {
                     GenericParamDefKind::Type { .. } | GenericParamDefKind::Const { .. } => {
-                        trait_ref.substs[param.index as usize].to_string()
+                        trait_ref.args[param.index as usize].to_string()
                     }
                     GenericParamDefKind::Lifetime => return None,
                 };
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 9ac1ba0275c..073a2a2b1a0 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -30,7 +30,7 @@ use rustc_middle::hir::map;
 use rustc_middle::ty::error::TypeError::{self, Sorts};
 use rustc_middle::ty::{
     self, suggest_arbitrary_trait_bound, suggest_constraining_type_param, AdtKind,
-    GeneratorDiagnosticData, GeneratorInteriorTypeCause, InferTy, InternalSubsts, IsSuggestable,
+    GeneratorDiagnosticData, GeneratorInteriorTypeCause, GenericArgs, InferTy, IsSuggestable,
     ToPredicate, Ty, TyCtxt, TypeAndMut, TypeFoldable, TypeFolder, TypeSuperFoldable,
     TypeVisitableExt, TypeckResults,
 };
@@ -435,7 +435,7 @@ fn suggest_restriction<'tcx>(
 ) {
     if hir_generics.where_clause_span.from_expansion()
         || hir_generics.where_clause_span.desugaring_kind().is_some()
-        || projection.is_some_and(|projection| tcx.opt_rpitit_info(projection.def_id).is_some())
+        || projection.is_some_and(|projection| tcx.is_impl_trait_in_trait(projection.def_id))
     {
         return;
     }
@@ -670,7 +670,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                     // this that we do in `suggest_restriction` and pull the
                     // `impl Trait` into a new generic if it shows up somewhere
                     // else in the predicate.
-                    if !trait_pred.skip_binder().trait_ref.substs[1..]
+                    if !trait_pred.skip_binder().trait_ref.args[1..]
                         .iter()
                         .all(|g| g.is_suggestable(self.tcx, false))
                     {
@@ -752,14 +752,20 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
         trait_pred: ty::PolyTraitPredicate<'tcx>,
     ) -> bool {
         // It only make sense when suggesting dereferences for arguments
-        let ObligationCauseCode::FunctionArgumentObligation { arg_hir_id, call_hir_id, .. } = obligation.cause.code()
-            else { return false; };
-        let Some(typeck_results) = &self.typeck_results
-            else { return false; };
-        let hir::Node::Expr(expr) = self.tcx.hir().get(*arg_hir_id)
-            else { return false; };
-        let Some(arg_ty) = typeck_results.expr_ty_adjusted_opt(expr)
-            else { return false; };
+        let ObligationCauseCode::FunctionArgumentObligation { arg_hir_id, call_hir_id, .. } =
+            obligation.cause.code()
+        else {
+            return false;
+        };
+        let Some(typeck_results) = &self.typeck_results else {
+            return false;
+        };
+        let hir::Node::Expr(expr) = self.tcx.hir().get(*arg_hir_id) else {
+            return false;
+        };
+        let Some(arg_ty) = typeck_results.expr_ty_adjusted_opt(expr) else {
+            return false;
+        };
 
         let span = obligation.cause.span;
         let mut real_trait_pred = trait_pred;
@@ -933,11 +939,11 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
             trait_pred.self_ty(),
         );
 
-        let Some((def_id_or_name, output, inputs)) = self.extract_callable_info(
-            obligation.cause.body_id,
-            obligation.param_env,
-            self_ty,
-        ) else { return false; };
+        let Some((def_id_or_name, output, inputs)) =
+            self.extract_callable_info(obligation.cause.body_id, obligation.param_env, self_ty)
+        else {
+            return false;
+        };
 
         // Remapping bound vars here
         let trait_pred_and_self = trait_pred.map_bound(|trait_pred| (trait_pred, output));
@@ -1035,26 +1041,40 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
             span.remove_mark();
         }
         let mut expr_finder = FindExprBySpan::new(span);
-        let Some(body_id) = self.tcx.hir().maybe_body_owned_by(obligation.cause.body_id) else { return; };
+        let Some(body_id) = self.tcx.hir().maybe_body_owned_by(obligation.cause.body_id) else {
+            return;
+        };
         let body = self.tcx.hir().body(body_id);
         expr_finder.visit_expr(body.value);
-        let Some(expr) = expr_finder.result else { return; };
-        let Some(typeck) = &self.typeck_results else { return; };
-        let Some(ty) = typeck.expr_ty_adjusted_opt(expr) else { return; };
+        let Some(expr) = expr_finder.result else {
+            return;
+        };
+        let Some(typeck) = &self.typeck_results else {
+            return;
+        };
+        let Some(ty) = typeck.expr_ty_adjusted_opt(expr) else {
+            return;
+        };
         if !ty.is_unit() {
             return;
         };
-        let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = expr.kind else { return; };
-        let hir::def::Res::Local(hir_id) = path.res else { return; };
+        let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = expr.kind else {
+            return;
+        };
+        let hir::def::Res::Local(hir_id) = path.res else {
+            return;
+        };
         let Some(hir::Node::Pat(pat)) = self.tcx.hir().find(hir_id) else {
             return;
         };
-        let Some(hir::Node::Local(hir::Local {
-            ty: None,
-            init: Some(init),
-            ..
-        })) = self.tcx.hir().find_parent(pat.hir_id) else { return; };
-        let hir::ExprKind::Block(block, None) = init.kind else { return; };
+        let Some(hir::Node::Local(hir::Local { ty: None, init: Some(init), .. })) =
+            self.tcx.hir().find_parent(pat.hir_id)
+        else {
+            return;
+        };
+        let hir::ExprKind::Block(block, None) = init.kind else {
+            return;
+        };
         if block.expr.is_some() {
             return;
         }
@@ -1062,7 +1082,9 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
             err.span_label(block.span, "this empty block is missing a tail expression");
             return;
         };
-        let hir::StmtKind::Semi(tail_expr) = stmt.kind else { return; };
+        let hir::StmtKind::Semi(tail_expr) = stmt.kind else {
+            return;
+        };
         let Some(ty) = typeck.expr_ty_opt(tail_expr) else {
             err.span_label(block.span, "this block is missing a tail expression");
             return;
@@ -1092,12 +1114,18 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
     ) -> bool {
         let self_ty = self.resolve_vars_if_possible(trait_pred.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 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 };
-        let ObligationCauseCode::FunctionArgumentObligation { arg_hir_id, .. } = obligation.cause.code() else { return false };
+        let ObligationCauseCode::FunctionArgumentObligation { arg_hir_id, .. } =
+            obligation.cause.code()
+        else {
+            return false;
+        };
         let arg_node = self.tcx.hir().get(*arg_hir_id);
-        let Node::Expr(Expr { kind: hir::ExprKind::Path(_), ..}) = arg_node else { return false };
+        let Node::Expr(Expr { kind: hir::ExprKind::Path(_), .. }) = arg_node else { return false };
 
         let clone_trait = self.tcx.require_lang_item(LangItem::Clone, None);
         let has_clone = |ty| {
@@ -1143,24 +1171,33 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
         found: Ty<'tcx>,
     ) -> Option<(DefIdOrName, Ty<'tcx>, Vec<Ty<'tcx>>)> {
         // Autoderef is useful here because sometimes we box callables, etc.
-        let Some((def_id_or_name, output, inputs)) = (self.autoderef_steps)(found).into_iter().find_map(|(found, _)| {
-            match *found.kind() {
-                ty::FnPtr(fn_sig) =>
-                    Some((DefIdOrName::Name("function pointer"), fn_sig.output(), fn_sig.inputs())),
-                ty::FnDef(def_id, _) => {
-                    let fn_sig = found.fn_sig(self.tcx);
-                    Some((DefIdOrName::DefId(def_id), fn_sig.output(), fn_sig.inputs()))
-                }
-                ty::Closure(def_id, substs) => {
-                    let fn_sig = substs.as_closure().sig();
-                    Some((DefIdOrName::DefId(def_id), fn_sig.output(), fn_sig.inputs().map_bound(|inputs| &inputs[1..])))
-                }
-                ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
-                    self.tcx.item_bounds(def_id).subst(self.tcx, substs).iter().find_map(|pred| {
-                        if let ty::ClauseKind::Projection(proj) = pred.kind().skip_binder()
+        let Some((def_id_or_name, output, inputs)) =
+            (self.autoderef_steps)(found).into_iter().find_map(|(found, _)| {
+                match *found.kind() {
+                    ty::FnPtr(fn_sig) => Some((
+                        DefIdOrName::Name("function pointer"),
+                        fn_sig.output(),
+                        fn_sig.inputs(),
+                    )),
+                    ty::FnDef(def_id, _) => {
+                        let fn_sig = found.fn_sig(self.tcx);
+                        Some((DefIdOrName::DefId(def_id), fn_sig.output(), fn_sig.inputs()))
+                    }
+                    ty::Closure(def_id, args) => {
+                        let fn_sig = args.as_closure().sig();
+                        Some((
+                            DefIdOrName::DefId(def_id),
+                            fn_sig.output(),
+                            fn_sig.inputs().map_bound(|inputs| &inputs[1..]),
+                        ))
+                    }
+                    ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) => {
+                        self.tcx.item_bounds(def_id).instantiate(self.tcx, args).iter().find_map(
+                            |pred| {
+                                if let ty::ClauseKind::Projection(proj) = pred.kind().skip_binder()
                         && Some(proj.projection_ty.def_id) == self.tcx.lang_items().fn_once_output()
-                        // args tuple will always be substs[1]
-                        && let ty::Tuple(args) = proj.projection_ty.substs.type_at(1).kind()
+                        // args tuple will always be args[1]
+                        && let ty::Tuple(args) = proj.projection_ty.args.type_at(1).kind()
                         {
                             Some((
                                 DefIdOrName::DefId(def_id),
@@ -1170,14 +1207,15 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                         } else {
                             None
                         }
-                    })
-                }
-                ty::Dynamic(data, _, ty::Dyn) => {
-                    data.iter().find_map(|pred| {
-                        if let ty::ExistentialPredicate::Projection(proj) = pred.skip_binder()
+                            },
+                        )
+                    }
+                    ty::Dynamic(data, _, ty::Dyn) => {
+                        data.iter().find_map(|pred| {
+                            if let ty::ExistentialPredicate::Projection(proj) = pred.skip_binder()
                         && Some(proj.def_id) == self.tcx.lang_items().fn_once_output()
-                        // for existential projection, substs are shifted over by 1
-                        && let ty::Tuple(args) = proj.substs.type_at(0).kind()
+                        // for existential projection, args are shifted over by 1
+                        && let ty::Tuple(args) = proj.args.type_at(0).kind()
                         {
                             Some((
                                 DefIdOrName::Name("trait object"),
@@ -1187,11 +1225,11 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                         } else {
                             None
                         }
-                    })
-                }
-                ty::Param(param) => {
-                    let generics = self.tcx.generics_of(body_id);
-                    let name = if generics.count() > param.index as usize
+                        })
+                    }
+                    ty::Param(param) => {
+                        let generics = self.tcx.generics_of(body_id);
+                        let name = if generics.count() > param.index as usize
                         && let def = generics.param_at(param.index as usize, self.tcx)
                         && matches!(def.kind, ty::GenericParamDefKind::Type { .. })
                         && def.name == param.name
@@ -1200,12 +1238,12 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                     } else {
                         DefIdOrName::Name("type parameter")
                     };
-                    param_env.caller_bounds().iter().find_map(|pred| {
-                        if let ty::ClauseKind::Projection(proj) = pred.kind().skip_binder()
+                        param_env.caller_bounds().iter().find_map(|pred| {
+                            if let ty::ClauseKind::Projection(proj) = pred.kind().skip_binder()
                         && Some(proj.projection_ty.def_id) == self.tcx.lang_items().fn_once_output()
                         && proj.projection_ty.self_ty() == found
-                        // args tuple will always be substs[1]
-                        && let ty::Tuple(args) = proj.projection_ty.substs.type_at(1).kind()
+                        // args tuple will always be args[1]
+                        && let ty::Tuple(args) = proj.projection_ty.args.type_at(1).kind()
                         {
                             Some((
                                 name,
@@ -1215,11 +1253,14 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                         } else {
                             None
                         }
-                    })
+                        })
+                    }
+                    _ => None,
                 }
-                _ => None,
-            }
-        }) else { return None; };
+            })
+        else {
+            return None;
+        };
 
         let output = self.instantiate_binder_with_fresh_vars(
             DUMMY_SP,
@@ -1408,11 +1449,17 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                         // Issue #104961, we need to add parentheses properly for compound expressions
                         // for example, `x.starts_with("hi".to_string() + "you")`
                         // should be `x.starts_with(&("hi".to_string() + "you"))`
-                        let Some(body_id) = self.tcx.hir().maybe_body_owned_by(obligation.cause.body_id) else { return false; };
+                        let Some(body_id) =
+                            self.tcx.hir().maybe_body_owned_by(obligation.cause.body_id)
+                        else {
+                            return false;
+                        };
                         let body = self.tcx.hir().body(body_id);
                         let mut expr_finder = FindExprBySpan::new(span);
                         expr_finder.visit_expr(body.value);
-                        let Some(expr) = expr_finder.result else { return false; };
+                        let Some(expr) = expr_finder.result else {
+                            return false;
+                        };
                         let needs_parens = match expr.kind {
                             // parenthesize if needed (Issue #46756)
                             hir::ExprKind::Cast(_, _) | hir::ExprKind::Binary(_, _, _) => true,
@@ -1463,8 +1510,12 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
         self_ty: Ty<'tcx>,
         target_ty: Ty<'tcx>,
     ) {
-        let ty::Ref(_, object_ty, hir::Mutability::Not) = target_ty.kind() else { return; };
-        let ty::Dynamic(predicates, _, ty::Dyn) = object_ty.kind() else { return; };
+        let ty::Ref(_, object_ty, hir::Mutability::Not) = target_ty.kind() else {
+            return;
+        };
+        let ty::Dynamic(predicates, _, ty::Dyn) = object_ty.kind() else {
+            return;
+        };
         let self_ref_ty = Ty::new_imm_ref(self.tcx, self.tcx.lifetimes.re_erased, self_ty);
 
         for predicate in predicates.iter() {
@@ -1566,7 +1617,9 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
         }
 
         // Maybe suggest removal of borrows from expressions, like in `for i in &&&foo {}`.
-        let Some(mut expr) = expr_finder.result else { return false; };
+        let Some(mut expr) = expr_finder.result else {
+            return false;
+        };
         let mut count = 0;
         let mut suggestions = vec![];
         // Skipping binder here, remapping below
@@ -1646,7 +1699,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                 }
                 if let Some(typeck_results) = &self.typeck_results
                         && let ty = typeck_results.expr_ty_adjusted(base)
-                        && let ty::FnDef(def_id, _substs) = ty.kind()
+                        && let ty::FnDef(def_id, _args) = ty.kind()
                         && let Some(hir::Node::Item(hir::Item { ident, span, vis_span, .. })) =
                             hir.get_if_local(*def_id)
                     {
@@ -1798,7 +1851,9 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
 
     fn return_type_span(&self, obligation: &PredicateObligation<'tcx>) -> Option<Span> {
         let hir = self.tcx.hir();
-        let Some(hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(sig, ..), .. })) = hir.find_by_def_id(obligation.cause.body_id) else {
+        let Some(hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(sig, ..), .. })) =
+            hir.find_by_def_id(obligation.cause.body_id)
+        else {
             return None;
         };
 
@@ -1925,7 +1980,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
             infcx: &InferCtxt<'tcx>,
             trait_ref: ty::PolyTraitRef<'tcx>,
         ) -> Ty<'tcx> {
-            let inputs = trait_ref.skip_binder().substs.type_at(1);
+            let inputs = trait_ref.skip_binder().args.type_at(1);
             let sig = match inputs.kind() {
                 ty::Tuple(inputs) if infcx.tcx.is_fn_trait(trait_ref.def_id()) => {
                     infcx.tcx.mk_fn_sig(
@@ -2006,12 +2061,12 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
         {
             let expected_self =
                 self.tcx.anonymize_bound_vars(pred.kind().rebind(trait_pred.self_ty()));
-            let expected_substs = self
+            let expected_args = self
                 .tcx
-                .anonymize_bound_vars(pred.kind().rebind(trait_pred.trait_ref.substs));
+                .anonymize_bound_vars(pred.kind().rebind(trait_pred.trait_ref.args));
 
             // Find another predicate whose self-type is equal to the expected self type,
-            // but whose substs don't match.
+            // but whose args don't match.
             let other_pred = predicates.into_iter()
                 .enumerate()
                 .find(|(other_idx, (pred, _))| match pred.kind().skip_binder() {
@@ -2024,10 +2079,10 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                                 == self.tcx.anonymize_bound_vars(
                                     pred.kind().rebind(trait_pred.self_ty()),
                                 )
-                            // But the substs don't match (i.e. incompatible args)
-                            && expected_substs
+                            // But the args don't match (i.e. incompatible args)
+                            && expected_args
                                 != self.tcx.anonymize_bound_vars(
-                                    pred.kind().rebind(trait_pred.trait_ref.substs),
+                                    pred.kind().rebind(trait_pred.trait_ref.args),
                                 ) =>
                     {
                         true
@@ -2222,7 +2277,9 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
 
         // Only continue if a generator was found.
         debug!(?generator, ?trait_ref, ?target_ty);
-        let (Some(generator_did), Some(trait_ref), Some(target_ty)) = (generator, trait_ref, target_ty) else {
+        let (Some(generator_did), Some(trait_ref), Some(target_ty)) =
+            (generator, trait_ref, target_ty)
+        else {
             return false;
         };
 
@@ -3013,7 +3070,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                                 }
                                 err.note(msg.trim_end_matches(", ").to_string())
                             }
-                            ty::GeneratorWitnessMIR(def_id, substs) => {
+                            ty::GeneratorWitnessMIR(def_id, args) => {
                                 use std::fmt::Write;
 
                                 // FIXME: this is kind of an unusual format for rustc, can we make it more clear?
@@ -3022,7 +3079,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                                 let mut msg =
                                     "required because it captures the following types: ".to_owned();
                                 for bty in tcx.generator_hidden_types(*def_id) {
-                                    let ty = bty.subst(tcx, substs);
+                                    let ty = bty.instantiate(tcx, args);
                                     write!(msg, "`{}`, ", ty).unwrap();
                                 }
                                 err.note(msg.trim_end_matches(", ").to_string())
@@ -3350,7 +3407,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                     Ty::new_projection(
                         self.tcx,
                         item_def_id,
-                        // Future::Output has no substs
+                        // Future::Output has no args
                         [trait_pred.self_ty()],
                     )
                 });
@@ -3391,7 +3448,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
             _ => return,
         };
         if let ty::Float(_) = trait_ref.skip_binder().self_ty().kind()
-            && let ty::Infer(InferTy::IntVar(_)) = trait_ref.skip_binder().substs.type_at(1).kind()
+            && let ty::Infer(InferTy::IntVar(_)) = trait_ref.skip_binder().args.type_at(1).kind()
         {
             err.span_suggestion_verbose(
                 rhs_span.shrink_to_hi(),
@@ -3411,15 +3468,15 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
         let Some(diagnostic_name) = self.tcx.get_diagnostic_name(trait_pred.def_id()) else {
             return;
         };
-        let (adt, substs) = match trait_pred.skip_binder().self_ty().kind() {
-            ty::Adt(adt, substs) if adt.did().is_local() => (adt, substs),
+        let (adt, args) = match trait_pred.skip_binder().self_ty().kind() {
+            ty::Adt(adt, args) if adt.did().is_local() => (adt, args),
             _ => return,
         };
         let can_derive = {
             let is_derivable_trait = match diagnostic_name {
                 sym::Default => !adt.is_enum(),
                 sym::PartialEq | sym::PartialOrd => {
-                    let rhs_ty = trait_pred.skip_binder().trait_ref.substs.type_at(1);
+                    let rhs_ty = trait_pred.skip_binder().trait_ref.args.type_at(1);
                     trait_pred.skip_binder().self_ty() == rhs_ty
                 }
                 sym::Eq | sym::Ord | sym::Clone | sym::Copy | sym::Hash | sym::Debug => true,
@@ -3428,8 +3485,8 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
             is_derivable_trait &&
                 // Ensure all fields impl the trait.
                 adt.all_fields().all(|field| {
-                    let field_ty = field.ty(self.tcx, substs);
-                    let trait_substs = match diagnostic_name {
+                    let field_ty = field.ty(self.tcx, args);
+                    let trait_args = match diagnostic_name {
                         sym::PartialEq | sym::PartialOrd => {
                             Some(field_ty)
                         }
@@ -3438,7 +3495,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                     let trait_pred = trait_pred.map_bound_ref(|tr| ty::TraitPredicate {
                         trait_ref: ty::TraitRef::new(self.tcx,
                             trait_pred.def_id(),
-                            [field_ty].into_iter().chain(trait_substs),
+                            [field_ty].into_iter().chain(trait_args),
                         ),
                         ..*tr
                     });
@@ -3473,7 +3530,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
     ) {
         if let ObligationCauseCode::ImplDerivedObligation(_) = obligation.cause.code()
             && self.tcx.is_diagnostic_item(sym::SliceIndex, trait_pred.skip_binder().trait_ref.def_id)
-            && let ty::Slice(_) = trait_pred.skip_binder().trait_ref.substs.type_at(1).kind()
+            && let ty::Slice(_) = trait_pred.skip_binder().trait_ref.args.type_at(1).kind()
             && let ty::Ref(_, inner_ty, _) = trait_pred.skip_binder().self_ty().kind()
             && let ty::Uint(ty::UintTy::Usize) = inner_ty.kind()
         {
@@ -3523,8 +3580,8 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
             // trait_pred `S: Sum<<Self as Iterator>::Item>` and predicate `i32: Sum<&()>`
             let mut type_diffs = vec![];
             if let ObligationCauseCode::ExprBindingObligation(def_id, _, _, idx) = parent_code.deref()
-                && let Some(node_substs) = typeck_results.node_substs_opt(call_hir_id)
-                && let where_clauses = self.tcx.predicates_of(def_id).instantiate(self.tcx, node_substs)
+                && let Some(node_args) = typeck_results.node_args_opt(call_hir_id)
+                && let where_clauses = self.tcx.predicates_of(def_id).instantiate(self.tcx, node_args)
                 && let Some(where_pred) = where_clauses.predicates.get(*idx)
             {
                 if let Some(where_pred) = where_pred.as_trait_clause()
@@ -3538,7 +3595,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                     );
 
                     let zipped =
-                        iter::zip(where_pred.trait_ref.substs, failed_pred.trait_ref.substs);
+                        iter::zip(where_pred.trait_ref.args, failed_pred.trait_ref.args);
                     for (expected, actual) in zipped {
                         self.probe(|_| {
                             match self
@@ -3617,7 +3674,9 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
         let Some(typeck_results) = self.typeck_results.as_ref() else { return };
 
         // Make sure we're dealing with the `Option` type.
-        let Some(option_ty_adt) = typeck_results.expr_ty_adjusted(expr).ty_adt_def() else { return };
+        let Some(option_ty_adt) = typeck_results.expr_ty_adjusted(expr).ty_adt_def() else {
+            return;
+        };
         if !tcx.is_diagnostic_item(sym::Option, option_ty_adt.did()) {
             return;
         }
@@ -3627,7 +3686,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
         if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(ty::TraitPredicate { trait_ref, .. }))
             = failed_pred.kind().skip_binder()
             && tcx.is_fn_trait(trait_ref.def_id)
-            && let [self_ty, found_ty] = trait_ref.substs.as_slice()
+            && let [self_ty, found_ty] = trait_ref.args.as_slice()
             && let Some(fn_ty) = self_ty.as_type().filter(|ty| ty.is_fn())
             && let fn_sig @ ty::FnSig {
                 abi: abi::Abi::Rust,
@@ -3647,7 +3706,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
 
             // Extract `<U as Deref>::Target` assoc type and check that it is `T`
             && let Some(deref_target_did) = tcx.lang_items().deref_target()
-            && let projection = Ty::new_projection(tcx,deref_target_did, tcx.mk_substs(&[ty::GenericArg::from(found_ty)]))
+            && let projection = Ty::new_projection(tcx,deref_target_did, tcx.mk_args(&[ty::GenericArg::from(found_ty)]))
             && let InferOk { value: deref_target, obligations } = infcx.at(&ObligationCause::dummy(), param_env).normalize(projection)
             && obligations.iter().all(|obligation| infcx.predicate_must_hold_modulo_regions(obligation))
             && infcx.can_eq(param_env, deref_target, target_ty)
@@ -3749,11 +3808,17 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
         while let Some(assocs_in_method) = assocs.next() {
             let Some(prev_assoc_in_method) = assocs.peek() else {
                 for entry in assocs_in_method {
-                    let Some((span, (assoc, ty))) = entry else { continue; };
-                    if primary_spans.is_empty() || type_diffs.iter().any(|diff| {
-                        let Sorts(expected_found) = diff else { return false; };
-                        self.can_eq(param_env, expected_found.found, ty)
-                    }) {
+                    let Some((span, (assoc, ty))) = entry else {
+                        continue;
+                    };
+                    if primary_spans.is_empty()
+                        || type_diffs.iter().any(|diff| {
+                            let Sorts(expected_found) = diff else {
+                                return false;
+                            };
+                            self.can_eq(param_env, expected_found.found, ty)
+                        })
+                    {
                         // FIXME: this doesn't quite work for `Iterator::collect`
                         // because we have `Vec<i32>` and `()`, but we'd want `i32`
                         // to point at the `.into_iter()` call, but as long as we
@@ -3781,7 +3846,9 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                         let assoc = with_forced_trimmed_paths!(self.tcx.def_path_str(assoc));
                         if !self.can_eq(param_env, ty, *prev_ty) {
                             if type_diffs.iter().any(|diff| {
-                                let Sorts(expected_found) = diff else { return false; };
+                                let Sorts(expected_found) = diff else {
+                                    return false;
+                                };
                                 self.can_eq(param_env, expected_found.found, ty)
                             }) {
                                 primary_spans.push(span);
@@ -3829,15 +3896,19 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
         let ocx = ObligationCtxt::new(self.infcx);
         let mut assocs_in_this_method = Vec::with_capacity(type_diffs.len());
         for diff in type_diffs {
-            let Sorts(expected_found) = diff else { continue; };
-            let ty::Alias(ty::Projection, proj) = expected_found.expected.kind() else { continue; };
+            let Sorts(expected_found) = diff else {
+                continue;
+            };
+            let ty::Alias(ty::Projection, proj) = expected_found.expected.kind() else {
+                continue;
+            };
 
             let origin = TypeVariableOrigin { kind: TypeVariableOriginKind::TypeInference, span };
             let trait_def_id = proj.trait_def_id(self.tcx);
             // Make `Self` be equivalent to the type of the call chain
             // expression we're looking at now, so that we can tell what
             // for example `Iterator::Item` is at this point in the chain.
-            let substs = InternalSubsts::for_item(self.tcx, trait_def_id, |param, _| {
+            let args = GenericArgs::for_item(self.tcx, trait_def_id, |param, _| {
                 match param.kind {
                     ty::GenericParamDefKind::Type { .. } => {
                         if param.index == 0 {
@@ -3855,7 +3926,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
             // This corresponds to `<ExprTy as Iterator>::Item = _`.
             let projection = ty::Binder::dummy(ty::PredicateKind::Clause(
                 ty::ClauseKind::Projection(ty::ProjectionPredicate {
-                    projection_ty: self.tcx.mk_alias_ty(proj.def_id, substs),
+                    projection_ty: self.tcx.mk_alias_ty(proj.def_id, args),
                     term: ty_var.into(),
                 }),
             ));
@@ -3974,7 +4045,9 @@ fn hint_missing_borrow<'tcx>(
     };
 
     // This could be a variant constructor, for example.
-    let Some(fn_decl) = found_node.fn_decl() else { return; };
+    let Some(fn_decl) = found_node.fn_decl() else {
+        return;
+    };
 
     let args = fn_decl.inputs.iter();
 
diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs
index cf9d9315f60..9ddf8a09b58 100644
--- a/compiler/rustc_trait_selection/src/traits/fulfill.rs
+++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs
@@ -8,7 +8,7 @@ use rustc_infer::traits::{PolyTraitObligation, SelectionError, TraitEngine};
 use rustc_middle::mir::interpret::ErrorHandled;
 use rustc_middle::ty::abstract_const::NotConstEvaluatable;
 use rustc_middle::ty::error::{ExpectedFound, TypeError};
-use rustc_middle::ty::subst::SubstsRef;
+use rustc_middle::ty::GenericArgsRef;
 use rustc_middle::ty::{self, Binder, Const, TypeVisitableExt};
 use std::marker::PhantomData;
 
@@ -410,8 +410,8 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
                     }
                 }
 
-                ty::PredicateKind::ClosureKind(_, closure_substs, kind) => {
-                    match self.selcx.infcx.closure_kind(closure_substs) {
+                ty::PredicateKind::ClosureKind(_, closure_args, kind) => {
+                    match self.selcx.infcx.closure_kind(closure_args) {
                         Some(closure_kind) => {
                             if closure_kind.extends(kind) {
                                 ProcessResult::Changed(vec![])
@@ -536,7 +536,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
                                 if let Ok(new_obligations) = infcx
                                     .at(&obligation.cause, obligation.param_env)
                                     .trace(c1, c2)
-                                    .eq(DefineOpaqueTypes::No, a.substs, b.substs)
+                                    .eq(DefineOpaqueTypes::No, a.args, b.args)
                                 {
                                     return ProcessResult::Changed(mk_pending(
                                         new_obligations.into_obligations(),
@@ -559,31 +559,30 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
 
                     let stalled_on = &mut pending_obligation.stalled_on;
 
-                    let mut evaluate = |c: Const<'tcx>| {
-                        if let ty::ConstKind::Unevaluated(unevaluated) = c.kind() {
-                            match self.selcx.infcx.try_const_eval_resolve(
-                                obligation.param_env,
-                                unevaluated,
-                                c.ty(),
-                                Some(obligation.cause.span),
-                            ) {
-                                Ok(val) => Ok(val),
-                                Err(e) => match e {
-                                    ErrorHandled::TooGeneric => {
-                                        stalled_on.extend(
-                                            unevaluated.substs.iter().filter_map(
+                    let mut evaluate =
+                        |c: Const<'tcx>| {
+                            if let ty::ConstKind::Unevaluated(unevaluated) = c.kind() {
+                                match self.selcx.infcx.try_const_eval_resolve(
+                                    obligation.param_env,
+                                    unevaluated,
+                                    c.ty(),
+                                    Some(obligation.cause.span),
+                                ) {
+                                    Ok(val) => Ok(val),
+                                    Err(e) => match e {
+                                        ErrorHandled::TooGeneric => {
+                                            stalled_on.extend(unevaluated.args.iter().filter_map(
                                                 TyOrConstInferVar::maybe_from_generic_arg,
-                                            ),
-                                        );
-                                        Err(ErrorHandled::TooGeneric)
-                                    }
-                                    _ => Err(e),
-                                },
+                                            ));
+                                            Err(ErrorHandled::TooGeneric)
+                                        }
+                                        _ => Err(e),
+                                    },
+                                }
+                            } else {
+                                Ok(c)
                             }
-                        } else {
-                            Ok(c)
-                        }
-                    };
+                        };
 
                     match (evaluate(c1), evaluate(c2)) {
                         (Ok(c1), Ok(c2)) => {
@@ -696,9 +695,9 @@ impl<'a, 'tcx> FulfillProcessor<'a, 'tcx> {
                 // trait selection is because we don't have enough
                 // information about the types in the trait.
                 stalled_on.clear();
-                stalled_on.extend(substs_infer_vars(
+                stalled_on.extend(args_infer_vars(
                     &self.selcx,
-                    trait_obligation.predicate.map_bound(|pred| pred.trait_ref.substs),
+                    trait_obligation.predicate.map_bound(|pred| pred.trait_ref.args),
                 ));
 
                 debug!(
@@ -753,9 +752,9 @@ impl<'a, 'tcx> FulfillProcessor<'a, 'tcx> {
             ProjectAndUnifyResult::Holds(os) => ProcessResult::Changed(mk_pending(os)),
             ProjectAndUnifyResult::FailedNormalization => {
                 stalled_on.clear();
-                stalled_on.extend(substs_infer_vars(
+                stalled_on.extend(args_infer_vars(
                     &self.selcx,
-                    project_obligation.predicate.map_bound(|pred| pred.projection_ty.substs),
+                    project_obligation.predicate.map_bound(|pred| pred.projection_ty.args),
                 ));
                 ProcessResult::Unchanged
             }
@@ -770,14 +769,14 @@ impl<'a, 'tcx> FulfillProcessor<'a, 'tcx> {
     }
 }
 
-/// Returns the set of inference variables contained in `substs`.
-fn substs_infer_vars<'a, 'tcx>(
+/// Returns the set of inference variables contained in `args`.
+fn args_infer_vars<'a, 'tcx>(
     selcx: &SelectionContext<'a, 'tcx>,
-    substs: ty::Binder<'tcx, SubstsRef<'tcx>>,
+    args: ty::Binder<'tcx, GenericArgsRef<'tcx>>,
 ) -> impl Iterator<Item = TyOrConstInferVar<'tcx>> {
     selcx
         .infcx
-        .resolve_vars_if_possible(substs)
+        .resolve_vars_if_possible(args)
         .skip_binder() // ok because this check doesn't care about regions
         .iter()
         .filter(|arg| arg.has_non_region_infer())
diff --git a/compiler/rustc_trait_selection/src/traits/misc.rs b/compiler/rustc_trait_selection/src/traits/misc.rs
index e9cfd63e2ed..ab07b10c65f 100644
--- a/compiler/rustc_trait_selection/src/traits/misc.rs
+++ b/compiler/rustc_trait_selection/src/traits/misc.rs
@@ -43,7 +43,7 @@ pub fn type_allowed_to_implement_copy<'tcx>(
     self_type: Ty<'tcx>,
     parent_cause: ObligationCause<'tcx>,
 ) -> Result<(), CopyImplementationError<'tcx>> {
-    let (adt, substs) = match self_type.kind() {
+    let (adt, args) = match self_type.kind() {
         // These types used to have a builtin impl.
         // Now libcore provides that impl.
         ty::Uint(_)
@@ -56,7 +56,7 @@ pub fn type_allowed_to_implement_copy<'tcx>(
         | ty::Ref(_, _, hir::Mutability::Not)
         | ty::Array(..) => return Ok(()),
 
-        &ty::Adt(adt, substs) => (adt, substs),
+        &ty::Adt(adt, args) => (adt, args),
 
         _ => return Err(CopyImplementationError::NotAnAdt),
     };
@@ -66,7 +66,7 @@ pub fn type_allowed_to_implement_copy<'tcx>(
         param_env,
         self_type,
         adt,
-        substs,
+        args,
         parent_cause,
         hir::LangItem::Copy,
     )
@@ -91,7 +91,7 @@ pub fn type_allowed_to_implement_const_param_ty<'tcx>(
     self_type: Ty<'tcx>,
     parent_cause: ObligationCause<'tcx>,
 ) -> Result<(), ConstParamTyImplementationError<'tcx>> {
-    let (adt, substs) = match self_type.kind() {
+    let (adt, args) = match self_type.kind() {
         // `core` provides these impls.
         ty::Uint(_)
         | ty::Int(_)
@@ -103,7 +103,7 @@ pub fn type_allowed_to_implement_const_param_ty<'tcx>(
         | ty::Ref(.., hir::Mutability::Not)
         | ty::Tuple(_) => return Ok(()),
 
-        &ty::Adt(adt, substs) => (adt, substs),
+        &ty::Adt(adt, args) => (adt, args),
 
         _ => return Err(ConstParamTyImplementationError::NotAnAdtOrBuiltinAllowed),
     };
@@ -113,7 +113,7 @@ pub fn type_allowed_to_implement_const_param_ty<'tcx>(
         param_env,
         self_type,
         adt,
-        substs,
+        args,
         parent_cause,
         hir::LangItem::ConstParamTy,
     )
@@ -128,7 +128,7 @@ pub fn all_fields_implement_trait<'tcx>(
     param_env: ty::ParamEnv<'tcx>,
     self_type: Ty<'tcx>,
     adt: AdtDef<'tcx>,
-    substs: &'tcx List<GenericArg<'tcx>>,
+    args: &'tcx List<GenericArg<'tcx>>,
     parent_cause: ObligationCause<'tcx>,
     lang_item: LangItem,
 ) -> Result<(), Vec<(&'tcx ty::FieldDef, Ty<'tcx>, InfringingFieldsReason<'tcx>)>> {
@@ -141,7 +141,7 @@ pub fn all_fields_implement_trait<'tcx>(
             let infcx = tcx.infer_ctxt().build();
             let ocx = traits::ObligationCtxt::new(&infcx);
 
-            let unnormalized_ty = field.ty(tcx, substs);
+            let unnormalized_ty = field.ty(tcx, args);
             if unnormalized_ty.references_error() {
                 continue;
             }
@@ -154,11 +154,11 @@ pub fn all_fields_implement_trait<'tcx>(
 
             // FIXME(compiler-errors): This gives us better spans for bad
             // projection types like in issue-50480.
-            // If the ADT has substs, point to the cause we are given.
+            // If the ADT has args, point to the cause we are given.
             // If it does not, then this field probably doesn't normalize
             // to begin with, and point to the bad field's span instead.
             let normalization_cause = if field
-                .ty(tcx, traits::InternalSubsts::identity_for_item(tcx, adt.did()))
+                .ty(tcx, traits::GenericArgs::identity_for_item(tcx, adt.did()))
                 .has_non_region_param()
             {
                 parent_cause.clone()
diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs
index 1af8323b6e9..1c145999184 100644
--- a/compiler/rustc_trait_selection/src/traits/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/mod.rs
@@ -13,12 +13,12 @@ mod object_safety;
 pub mod outlives_bounds;
 pub mod project;
 pub mod query;
-#[cfg_attr(not(bootstrap), allow(hidden_glob_reexports))]
+#[allow(hidden_glob_reexports)]
 mod select;
 mod specialize;
 mod structural_match;
 mod structural_normalize;
-#[cfg_attr(not(bootstrap), allow(hidden_glob_reexports))]
+#[allow(hidden_glob_reexports)]
 mod util;
 pub mod vtable;
 pub mod wf;
@@ -32,7 +32,7 @@ use rustc_middle::query::Providers;
 use rustc_middle::ty::fold::TypeFoldable;
 use rustc_middle::ty::visit::{TypeVisitable, TypeVisitableExt};
 use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, TypeFolder, TypeSuperVisitable};
-use rustc_middle::ty::{InternalSubsts, SubstsRef};
+use rustc_middle::ty::{GenericArgs, GenericArgsRef};
 use rustc_span::def_id::DefId;
 use rustc_span::Span;
 
@@ -61,13 +61,13 @@ pub use self::select::{EvaluationResult, IntercrateAmbiguityCause, OverflowError
 pub use self::specialize::specialization_graph::FutureCompatOverlapError;
 pub use self::specialize::specialization_graph::FutureCompatOverlapErrorKind;
 pub use self::specialize::{
-    specialization_graph, translate_substs, translate_substs_with_cause, OverlapError,
+    specialization_graph, translate_args, translate_args_with_cause, OverlapError,
 };
 pub use self::structural_match::search_for_structural_match_violation;
 pub use self::structural_normalize::StructurallyNormalizeExt;
 pub use self::util::elaborate;
 pub use self::util::{
-    check_substs_compatible, supertrait_def_ids, supertraits, transitive_bounds,
+    check_args_compatible, supertrait_def_ids, supertraits, transitive_bounds,
     transitive_bounds_that_define_assoc_item, SupertraitDefIds,
 };
 pub use self::util::{expand_trait_aliases, TraitAliasExpander};
@@ -362,12 +362,9 @@ pub fn normalize_param_env_or_error<'tcx>(
         "normalize_param_env_or_error: predicates=(non-outlives={:?}, outlives={:?})",
         predicates, outlives_predicates
     );
-    let Ok(non_outlives_predicates) = do_normalize_predicates(
-        tcx,
-        cause.clone(),
-        elaborated_env,
-        predicates,
-    ) else {
+    let Ok(non_outlives_predicates) =
+        do_normalize_predicates(tcx, cause.clone(), elaborated_env, predicates)
+    else {
         // An unnormalized env is better than nothing.
         debug!("normalize_param_env_or_error: errored resolving non-outlives predicates");
         return elaborated_env;
@@ -384,12 +381,9 @@ pub fn normalize_param_env_or_error<'tcx>(
         unnormalized_env.reveal(),
         unnormalized_env.constness(),
     );
-    let Ok(outlives_predicates) = do_normalize_predicates(
-        tcx,
-        cause,
-        outlives_env,
-        outlives_predicates,
-    ) else {
+    let Ok(outlives_predicates) =
+        do_normalize_predicates(tcx, cause, outlives_env, outlives_predicates)
+    else {
         // An unnormalized env is better than nothing.
         debug!("normalize_param_env_or_error: errored resolving outlives predicates");
         return elaborated_env;
@@ -460,7 +454,7 @@ pub fn impossible_predicates<'tcx>(tcx: TyCtxt<'tcx>, predicates: Vec<ty::Clause
 
 fn subst_and_check_impossible_predicates<'tcx>(
     tcx: TyCtxt<'tcx>,
-    key: (DefId, SubstsRef<'tcx>),
+    key: (DefId, GenericArgsRef<'tcx>),
 ) -> bool {
     debug!("subst_and_check_impossible_predicates(key={:?})", key);
 
@@ -527,7 +521,7 @@ fn is_impossible_method(tcx: TyCtxt<'_>, (impl_def_id, trait_item_def_id): (DefI
     let impl_trait_ref = tcx
         .impl_trait_ref(impl_def_id)
         .expect("expected impl to correspond to trait")
-        .subst_identity();
+        .instantiate_identity();
     let param_env = tcx.param_env(impl_def_id);
 
     let mut visitor = ReferencesOnlyParentGenerics { tcx, generics, trait_item_def_id };
@@ -537,7 +531,7 @@ fn is_impossible_method(tcx: TyCtxt<'_>, (impl_def_id, trait_item_def_id): (DefI
                 tcx,
                 ObligationCause::dummy_with_span(*span),
                 param_env,
-                ty::EarlyBinder::bind(*pred).subst(tcx, impl_trait_ref.substs),
+                ty::EarlyBinder::bind(*pred).instantiate(tcx, impl_trait_ref.args),
             )
         })
     });
diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs
index c31944c162e..143e8412967 100644
--- a/compiler/rustc_trait_selection/src/traits/object_safety.rs
+++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs
@@ -17,10 +17,10 @@ use rustc_errors::{DelayDm, FatalError, MultiSpan};
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_middle::query::Providers;
-use rustc_middle::ty::subst::{GenericArg, InternalSubsts};
 use rustc_middle::ty::{
     self, EarlyBinder, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor,
 };
+use rustc_middle::ty::{GenericArg, GenericArgs};
 use rustc_middle::ty::{ToPredicate, TypeVisitableExt};
 use rustc_session::lint::builtin::WHERE_CLAUSES_OBJECT_SAFETY;
 use rustc_span::symbol::Symbol;
@@ -270,7 +270,7 @@ fn bounds_reference_self(tcx: TyCtxt<'_>, trait_def_id: DefId) -> SmallVec<[Span
     tcx.associated_items(trait_def_id)
         .in_definition_order()
         .filter(|item| item.kind == ty::AssocKind::Type)
-        .flat_map(|item| tcx.explicit_item_bounds(item.def_id).subst_identity_iter_copied())
+        .flat_map(|item| tcx.explicit_item_bounds(item.def_id).instantiate_identity_iter_copied())
         .filter_map(|c| predicate_references_self(tcx, c))
         .collect()
 }
@@ -284,7 +284,7 @@ fn predicate_references_self<'tcx>(
     match predicate.kind().skip_binder() {
         ty::ClauseKind::Trait(ref data) => {
             // In the case of a trait predicate, we can skip the "self" type.
-            data.trait_ref.substs[1..].iter().any(has_self_ty).then_some(sp)
+            data.trait_ref.args[1..].iter().any(has_self_ty).then_some(sp)
         }
         ty::ClauseKind::Projection(ref data) => {
             // And similarly for projections. This should be redundant with
@@ -302,7 +302,7 @@ fn predicate_references_self<'tcx>(
             //
             // This is ALT2 in issue #56288, see that for discussion of the
             // possible alternatives.
-            data.projection_ty.substs[1..].iter().any(has_self_ty).then_some(sp)
+            data.projection_ty.args[1..].iter().any(has_self_ty).then_some(sp)
         }
         ty::ClauseKind::ConstArgHasType(_ct, ty) => has_self_ty(&ty.into()).then_some(sp),
 
@@ -393,7 +393,7 @@ fn object_safety_violation_for_assoc_item(
         ty::AssocKind::Type => {
             if !tcx.features().generic_associated_types_extended
                 && !tcx.generics_of(item.def_id).params.is_empty()
-                && item.opt_rpitit_info.is_none()
+                && !item.is_impl_trait_in_trait()
             {
                 Some(ObjectSafetyViolation::GAT(item.name, item.ident(tcx).span))
             } else {
@@ -414,7 +414,7 @@ fn virtual_call_violation_for_method<'tcx>(
     trait_def_id: DefId,
     method: ty::AssocItem,
 ) -> Option<MethodViolationCode> {
-    let sig = tcx.fn_sig(method.def_id).subst_identity();
+    let sig = tcx.fn_sig(method.def_id).instantiate_identity();
 
     // The method's first parameter must be named `self`
     if !method.fn_has_self_parameter {
@@ -586,7 +586,7 @@ fn virtual_call_violation_for_method<'tcx>(
             // allowed to have generic parameters so `auto trait Bound<T> {}`
             // would already have reported an error at the definition of the
             // auto trait.
-            if pred_trait_ref.substs.len() != 1 {
+            if pred_trait_ref.args.len() != 1 {
                 tcx.sess.diagnostic().delay_span_bug(
                     span,
                     "auto traits cannot have generic parameters",
@@ -612,11 +612,11 @@ fn receiver_for_self_ty<'tcx>(
     method_def_id: DefId,
 ) -> Ty<'tcx> {
     debug!("receiver_for_self_ty({:?}, {:?}, {:?})", receiver_ty, self_ty, method_def_id);
-    let substs = InternalSubsts::for_item(tcx, method_def_id, |param, _| {
+    let args = GenericArgs::for_item(tcx, method_def_id, |param, _| {
         if param.index == 0 { self_ty.into() } else { tcx.mk_param_from_def(param) }
     });
 
-    let result = EarlyBinder::bind(receiver_ty).subst(tcx, substs);
+    let result = EarlyBinder::bind(receiver_ty).instantiate(tcx, args);
     debug!(
         "receiver_for_self_ty({:?}, {:?}, {:?}) = {:?}",
         receiver_ty, self_ty, method_def_id, result
@@ -751,11 +751,11 @@ fn receiver_is_dispatchable<'tcx>(
         // U: Trait<Arg1, ..., ArgN>
         let trait_predicate = {
             let trait_def_id = method.trait_container(tcx).unwrap();
-            let substs = InternalSubsts::for_item(tcx, trait_def_id, |param, _| {
+            let args = GenericArgs::for_item(tcx, trait_def_id, |param, _| {
                 if param.index == 0 { unsized_self_ty.into() } else { tcx.mk_param_from_def(param) }
             });
 
-            ty::TraitRef::new(tcx, trait_def_id, substs).to_predicate(tcx)
+            ty::TraitRef::new(tcx, trait_def_id, args).to_predicate(tcx)
         };
 
         let caller_bounds =
diff --git a/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs b/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs
index ff55eaf13ad..339baf611f3 100644
--- a/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs
+++ b/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs
@@ -83,7 +83,8 @@ impl<'a, 'tcx: 'a> InferCtxtExt<'a, 'tcx> for InferCtxt<'tcx> {
                 &canonical_var_values,
                 canonical_result,
                 &mut constraints,
-            ) else {
+            )
+        else {
             return vec![];
         };
         assert_eq!(&obligations, &[]);
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index 4ccfb54ff7c..e137ed9cda8 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -1,8 +1,8 @@
 //! Code for projecting associated types out of trait references.
 
-use super::check_substs_compatible;
+use super::check_args_compatible;
 use super::specialization_graph;
-use super::translate_substs;
+use super::translate_args;
 use super::util;
 use super::ImplSourceUserDefinedData;
 use super::MismatchedProjectionTypes;
@@ -524,7 +524,7 @@ impl<'a, 'b, 'tcx> TypeFolder<TyCtxt<'tcx>> for AssocTypeNormalizer<'a, 'b, 'tcx
         // ```
         // for<'a> fn(<T as Foo>::One<'a, Box<dyn Bar<'a, Item=<T as Foo>::Two<'a>>>>)
         // ```
-        // We normalize the substs on the projection before the projecting, but
+        // We normalize the args on the projection before the projecting, but
         // if we're naive, we'll
         //   replace bound vars on inner, project inner, replace placeholders on inner,
         //   replace bound vars on outer, project outer, replace placeholders on outer
@@ -539,7 +539,7 @@ impl<'a, 'b, 'tcx> TypeFolder<TyCtxt<'tcx>> for AssocTypeNormalizer<'a, 'b, 'tcx
         //
         // On the other hand, this does add a bit of complexity, since we only
         // replace bound vars if the current type is a `Projection` and we need
-        // to make sure we don't forget to fold the substs regardless.
+        // to make sure we don't forget to fold the args regardless.
 
         match kind {
             ty::Opaque => {
@@ -558,9 +558,9 @@ impl<'a, 'b, 'tcx> TypeFolder<TyCtxt<'tcx>> for AssocTypeNormalizer<'a, 'b, 'tcx
                             );
                         }
 
-                        let substs = data.substs.fold_with(self);
+                        let args = data.args.fold_with(self);
                         let generic_ty = self.interner().type_of(data.def_id);
-                        let concrete_ty = generic_ty.subst(self.interner(), substs);
+                        let concrete_ty = generic_ty.instantiate(self.interner(), args);
                         self.depth += 1;
                         let folded_ty = self.fold_ty(concrete_ty);
                         self.depth -= 1;
@@ -660,11 +660,8 @@ impl<'a, 'b, 'tcx> TypeFolder<TyCtxt<'tcx>> for AssocTypeNormalizer<'a, 'b, 'tcx
             ty::Weak => {
                 let infcx = self.selcx.infcx;
                 self.obligations.extend(
-                    infcx
-                        .tcx
-                        .predicates_of(data.def_id)
-                        .instantiate_own(infcx.tcx, data.substs)
-                        .map(|(mut predicate, span)| {
+                    infcx.tcx.predicates_of(data.def_id).instantiate_own(infcx.tcx, data.args).map(
+                        |(mut predicate, span)| {
                             if data.has_escaping_bound_vars() {
                                 (predicate, ..) = BoundVarReplacer::replace_bound_vars(
                                     infcx,
@@ -677,9 +674,10 @@ impl<'a, 'b, 'tcx> TypeFolder<TyCtxt<'tcx>> for AssocTypeNormalizer<'a, 'b, 'tcx
                                 ObligationCauseCode::TypeAlias(code, span, data.def_id)
                             });
                             Obligation::new(infcx.tcx, cause, self.param_env, predicate)
-                        }),
+                        },
+                    ),
                 );
-                infcx.tcx.type_of(data.def_id).subst(infcx.tcx, data.substs).fold_with(self)
+                infcx.tcx.type_of(data.def_id).instantiate(infcx.tcx, data.args).fold_with(self)
             }
 
             ty::Inherent if !data.has_escaping_bound_vars() => {
@@ -1337,7 +1335,7 @@ pub fn normalize_inherent_projection<'a, 'b, 'tcx>(
         });
     }
 
-    let substs = compute_inherent_assoc_ty_substs(
+    let args = compute_inherent_assoc_ty_args(
         selcx,
         param_env,
         alias_ty,
@@ -1347,7 +1345,7 @@ pub fn normalize_inherent_projection<'a, 'b, 'tcx>(
     );
 
     // Register the obligations arising from the impl and from the associated type itself.
-    let predicates = tcx.predicates_of(alias_ty.def_id).instantiate(tcx, substs);
+    let predicates = tcx.predicates_of(alias_ty.def_id).instantiate(tcx, args);
     for (predicate, span) in predicates {
         let predicate = normalize_with_depth_to(
             selcx,
@@ -1381,7 +1379,7 @@ pub fn normalize_inherent_projection<'a, 'b, 'tcx>(
         ));
     }
 
-    let ty = tcx.type_of(alias_ty.def_id).subst(tcx, substs);
+    let ty = tcx.type_of(alias_ty.def_id).instantiate(tcx, args);
 
     let mut ty = selcx.infcx.resolve_vars_if_possible(ty);
     if ty.has_projections() {
@@ -1391,20 +1389,20 @@ pub fn normalize_inherent_projection<'a, 'b, 'tcx>(
     ty
 }
 
-pub fn compute_inherent_assoc_ty_substs<'a, 'b, 'tcx>(
+pub fn compute_inherent_assoc_ty_args<'a, 'b, 'tcx>(
     selcx: &'a mut SelectionContext<'b, 'tcx>,
     param_env: ty::ParamEnv<'tcx>,
     alias_ty: ty::AliasTy<'tcx>,
     cause: ObligationCause<'tcx>,
     depth: usize,
     obligations: &mut Vec<PredicateObligation<'tcx>>,
-) -> ty::SubstsRef<'tcx> {
+) -> ty::GenericArgsRef<'tcx> {
     let tcx = selcx.tcx();
 
     let impl_def_id = tcx.parent(alias_ty.def_id);
-    let impl_substs = selcx.infcx.fresh_substs_for_item(cause.span, impl_def_id);
+    let impl_args = selcx.infcx.fresh_args_for_item(cause.span, impl_def_id);
 
-    let impl_ty = tcx.type_of(impl_def_id).subst(tcx, impl_substs);
+    let impl_ty = tcx.type_of(impl_def_id).instantiate(tcx, impl_args);
     let impl_ty =
         normalize_with_depth_to(selcx, param_env, cause.clone(), depth + 1, impl_ty, obligations);
 
@@ -1423,7 +1421,7 @@ pub fn compute_inherent_assoc_ty_substs<'a, 'b, 'tcx>(
         }
     }
 
-    alias_ty.rebase_substs_onto_impl(impl_substs, tcx)
+    alias_ty.rebase_args_onto_impl(impl_args, tcx)
 }
 
 enum Projected<'tcx> {
@@ -1495,20 +1493,18 @@ fn project<'cx, 'tcx>(
         ProjectionCandidateSet::None => {
             let tcx = selcx.tcx();
             let term = match tcx.def_kind(obligation.predicate.def_id) {
-                DefKind::AssocTy => Ty::new_projection(
-                    tcx,
-                    obligation.predicate.def_id,
-                    obligation.predicate.substs,
-                )
-                .into(),
+                DefKind::AssocTy => {
+                    Ty::new_projection(tcx, obligation.predicate.def_id, obligation.predicate.args)
+                        .into()
+                }
                 DefKind::AssocConst => ty::Const::new_unevaluated(
                     tcx,
                     ty::UnevaluatedConst::new(
                         obligation.predicate.def_id,
-                        obligation.predicate.substs,
+                        obligation.predicate.args,
                     ),
                     tcx.type_of(obligation.predicate.def_id)
-                        .subst(tcx, obligation.predicate.substs),
+                        .instantiate(tcx, obligation.predicate.args),
                 )
                 .into(),
                 kind => {
@@ -1567,7 +1563,7 @@ fn assemble_candidates_from_trait_def<'cx, 'tcx>(
     let bounds = match *obligation.predicate.self_ty().kind() {
         // Excluding IATs and type aliases here as they don't have meaningful item bounds.
         ty::Alias(ty::Projection | ty::Opaque, ref data) => {
-            tcx.item_bounds(data.def_id).subst(tcx, data.substs)
+            tcx.item_bounds(data.def_id).instantiate(tcx, data.args)
         }
         ty::Infer(ty::TyVar(_)) => {
             // If the self-type is an inference variable, then it MAY wind up
@@ -2017,12 +2013,12 @@ fn confirm_generator_candidate<'cx, 'tcx>(
     obligation: &ProjectionTyObligation<'tcx>,
     nested: Vec<PredicateObligation<'tcx>>,
 ) -> Progress<'tcx> {
-    let ty::Generator(_, substs, _) =
+    let ty::Generator(_, args, _) =
         selcx.infcx.shallow_resolve(obligation.predicate.self_ty()).kind()
     else {
         unreachable!()
     };
-    let gen_sig = substs.as_generator().poly_sig();
+    let gen_sig = args.as_generator().poly_sig();
     let Normalized { value: gen_sig, obligations } = normalize_with_depth(
         selcx,
         obligation.param_env,
@@ -2054,7 +2050,7 @@ fn confirm_generator_candidate<'cx, 'tcx>(
         };
 
         ty::ProjectionPredicate {
-            projection_ty: tcx.mk_alias_ty(obligation.predicate.def_id, trait_ref.substs),
+            projection_ty: tcx.mk_alias_ty(obligation.predicate.def_id, trait_ref.args),
             term: ty.into(),
         }
     });
@@ -2069,12 +2065,12 @@ fn confirm_future_candidate<'cx, 'tcx>(
     obligation: &ProjectionTyObligation<'tcx>,
     nested: Vec<PredicateObligation<'tcx>>,
 ) -> Progress<'tcx> {
-    let ty::Generator(_, substs, _) =
+    let ty::Generator(_, args, _) =
         selcx.infcx.shallow_resolve(obligation.predicate.self_ty()).kind()
     else {
         unreachable!()
     };
-    let gen_sig = substs.as_generator().poly_sig();
+    let gen_sig = args.as_generator().poly_sig();
     let Normalized { value: gen_sig, obligations } = normalize_with_depth(
         selcx,
         obligation.param_env,
@@ -2098,7 +2094,7 @@ fn confirm_future_candidate<'cx, 'tcx>(
         debug_assert_eq!(tcx.associated_item(obligation.predicate.def_id).name, sym::Output);
 
         ty::ProjectionPredicate {
-            projection_ty: tcx.mk_alias_ty(obligation.predicate.def_id, trait_ref.substs),
+            projection_ty: tcx.mk_alias_ty(obligation.predicate.def_id, trait_ref.args),
             term: return_ty.into(),
         }
     });
@@ -2115,7 +2111,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()]);
+    let args = tcx.mk_args(&[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();
@@ -2155,7 +2151,7 @@ fn confirm_builtin_candidate<'cx, 'tcx>(
     };
 
     let predicate =
-        ty::ProjectionPredicate { projection_ty: tcx.mk_alias_ty(item_def_id, substs), term };
+        ty::ProjectionPredicate { projection_ty: tcx.mk_alias_ty(item_def_id, args), term };
 
     confirm_param_env_candidate(selcx, obligation, ty::Binder::dummy(predicate), false)
         .with_addl_obligations(obligations)
@@ -2187,11 +2183,11 @@ fn confirm_closure_candidate<'cx, 'tcx>(
     obligation: &ProjectionTyObligation<'tcx>,
     nested: Vec<PredicateObligation<'tcx>>,
 ) -> Progress<'tcx> {
-    let ty::Closure(_, substs) = selcx.infcx.shallow_resolve(obligation.predicate.self_ty()).kind()
+    let ty::Closure(_, args) = selcx.infcx.shallow_resolve(obligation.predicate.self_ty()).kind()
     else {
         unreachable!()
     };
-    let closure_sig = substs.as_closure().sig();
+    let closure_sig = args.as_closure().sig();
     let Normalized { value: closure_sig, obligations } = normalize_with_depth(
         selcx,
         obligation.param_env,
@@ -2228,7 +2224,7 @@ fn confirm_callable_candidate<'cx, 'tcx>(
         flag,
     )
     .map_bound(|(trait_ref, ret_type)| ty::ProjectionPredicate {
-        projection_ty: tcx.mk_alias_ty(fn_once_output_def_id, trait_ref.substs),
+        projection_ty: tcx.mk_alias_ty(fn_once_output_def_id, trait_ref.args),
         term: ret_type.into(),
     });
 
@@ -2312,7 +2308,7 @@ fn confirm_impl_candidate<'cx, 'tcx>(
 ) -> Progress<'tcx> {
     let tcx = selcx.tcx();
 
-    let ImplSourceUserDefinedData { impl_def_id, substs, mut nested } = impl_impl_source;
+    let ImplSourceUserDefinedData { impl_def_id, args, mut nested } = impl_impl_source;
     let assoc_item_id = obligation.predicate.def_id;
     let trait_def_id = tcx.trait_id_of_impl(impl_def_id).unwrap();
 
@@ -2336,23 +2332,22 @@ fn confirm_impl_candidate<'cx, 'tcx>(
     // If we're trying to normalize `<Vec<u32> as X>::A<S>` using
     //`impl<T> X for Vec<T> { type A<Y> = Box<Y>; }`, then:
     //
-    // * `obligation.predicate.substs` is `[Vec<u32>, S]`
-    // * `substs` is `[u32]`
-    // * `substs` ends up as `[u32, S]`
-    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);
+    // * `obligation.predicate.args` is `[Vec<u32>, S]`
+    // * `args` is `[u32]`
+    // * `args` ends up as `[u32, S]`
+    let args = obligation.predicate.args.rebase_onto(tcx, trait_def_id, args);
+    let args = translate_args(selcx.infcx, param_env, impl_def_id, args, assoc_ty.defining_node);
     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 did = assoc_ty.item.def_id;
-        let identity_substs = crate::traits::InternalSubsts::identity_for_item(tcx, did);
-        let uv = ty::UnevaluatedConst::new(did, identity_substs);
+        let identity_args = crate::traits::GenericArgs::identity_for_item(tcx, did);
+        let uv = ty::UnevaluatedConst::new(did, identity_args);
         ty.map_bound(|ty| ty::Const::new_unevaluated(tcx, uv, ty).into())
     } else {
         ty.map_bound(|ty| ty.into())
     };
-    if !check_substs_compatible(tcx, assoc_ty.item, substs) {
+    if !check_args_compatible(tcx, assoc_ty.item, args) {
         let err = Ty::new_error_with_message(
             tcx,
             obligation.cause.span,
@@ -2361,7 +2356,7 @@ fn confirm_impl_candidate<'cx, 'tcx>(
         Progress { term: err.into(), obligations: nested }
     } else {
         assoc_ty_own_obligations(selcx, obligation, &mut nested);
-        Progress { term: term.subst(tcx, substs), obligations: nested }
+        Progress { term: term.instantiate(tcx, args), obligations: nested }
     }
 }
 
@@ -2375,7 +2370,7 @@ fn assoc_ty_own_obligations<'cx, 'tcx>(
     let tcx = selcx.tcx();
     let predicates = tcx
         .predicates_of(obligation.predicate.def_id)
-        .instantiate_own(tcx, obligation.predicate.substs);
+        .instantiate_own(tcx, obligation.predicate.args);
     for (predicate, span) in predicates {
         let normalized = normalize_with_depth_to(
             selcx,
diff --git a/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs b/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs
index 709c3f432e6..ef989d8c9d6 100644
--- a/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs
@@ -49,8 +49,8 @@ pub fn trivial_dropck_outlives<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool {
         // (T1..Tn) and closures have same properties as T1..Tn --
         // check if *all* of them are trivial.
         ty::Tuple(tys) => tys.iter().all(|t| trivial_dropck_outlives(tcx, t)),
-        ty::Closure(_, ref substs) => {
-            trivial_dropck_outlives(tcx, substs.as_closure().tupled_upvars_ty())
+        ty::Closure(_, ref args) => {
+            trivial_dropck_outlives(tcx, args.as_closure().tupled_upvars_ty())
         }
 
         ty::Adt(def, _) => {
@@ -237,8 +237,8 @@ pub fn dtorck_constraint_for_ty_inner<'tcx>(
             Ok::<_, NoSolution>(())
         })?,
 
-        ty::Closure(_, substs) => {
-            if !substs.as_closure().is_valid() {
+        ty::Closure(_, args) => {
+            if !args.as_closure().is_valid() {
                 // By the time this code runs, all type variables ought to
                 // be fully resolved.
 
@@ -250,14 +250,14 @@ pub fn dtorck_constraint_for_ty_inner<'tcx>(
             }
 
             rustc_data_structures::stack::ensure_sufficient_stack(|| {
-                for ty in substs.as_closure().upvar_tys() {
+                for ty in args.as_closure().upvar_tys() {
                     dtorck_constraint_for_ty_inner(tcx, span, for_ty, depth + 1, ty, constraints)?;
                 }
                 Ok::<_, NoSolution>(())
             })?
         }
 
-        ty::Generator(_, substs, _movability) => {
+        ty::Generator(_, args, _movability) => {
             // rust-lang/rust#49918: types can be constructed, stored
             // in the interior, and sit idle when generator yields
             // (and is subsequently dropped).
@@ -281,7 +281,7 @@ pub fn dtorck_constraint_for_ty_inner<'tcx>(
             // derived from lifetimes attached to the upvars and resume
             // argument, and we *do* incorporate those here.
 
-            if !substs.as_generator().is_valid() {
+            if !args.as_generator().is_valid() {
                 // By the time this code runs, all type variables ought to
                 // be fully resolved.
                 tcx.sess.delay_span_bug(
@@ -292,28 +292,25 @@ pub fn dtorck_constraint_for_ty_inner<'tcx>(
             }
 
             constraints.outlives.extend(
-                substs
-                    .as_generator()
-                    .upvar_tys()
-                    .map(|t| -> ty::subst::GenericArg<'tcx> { t.into() }),
+                args.as_generator().upvar_tys().map(|t| -> ty::GenericArg<'tcx> { t.into() }),
             );
-            constraints.outlives.push(substs.as_generator().resume_ty().into());
+            constraints.outlives.push(args.as_generator().resume_ty().into());
         }
 
-        ty::Adt(def, substs) => {
+        ty::Adt(def, args) => {
             let DropckConstraint { dtorck_types, outlives, overflows } =
                 tcx.at(span).adt_dtorck_constraint(def.did())?;
             // FIXME: we can try to recursively `dtorck_constraint_on_ty`
             // there, but that needs some way to handle cycles.
             constraints
                 .dtorck_types
-                .extend(dtorck_types.iter().map(|t| EarlyBinder::bind(*t).subst(tcx, substs)));
+                .extend(dtorck_types.iter().map(|t| EarlyBinder::bind(*t).instantiate(tcx, args)));
             constraints
                 .outlives
-                .extend(outlives.iter().map(|t| EarlyBinder::bind(*t).subst(tcx, substs)));
+                .extend(outlives.iter().map(|t| EarlyBinder::bind(*t).instantiate(tcx, args)));
             constraints
                 .overflows
-                .extend(overflows.iter().map(|t| EarlyBinder::bind(*t).subst(tcx, substs)));
+                .extend(overflows.iter().map(|t| EarlyBinder::bind(*t).instantiate(tcx, args)));
         }
 
         // Objects must be alive in order for their destructor
diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs
index 7fe79fd865c..d45cf94f731 100644
--- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs
@@ -61,8 +61,27 @@ impl<'cx, 'tcx> QueryNormalizeExt<'tcx> for At<'cx, 'tcx> {
             self.cause,
         );
 
+        // This is actually a consequence by the way `normalize_erasing_regions` works currently.
+        // Because it needs to call the `normalize_generic_arg_after_erasing_regions`, it folds
+        // through tys and consts in a `TypeFoldable`. Importantly, it skips binders, leaving us
+        // with trying to normalize with escaping bound vars.
+        //
+        // Here, we just add the universes that we *would* have created had we passed through the binders.
+        //
+        // We *could* replace escaping bound vars eagerly here, but it doesn't seem really necessary.
+        // The rest of the code is already set up to be lazy about replacing bound vars,
+        // and only when we actually have to normalize.
+        let universes = if value.has_escaping_bound_vars() {
+            let mut max_visitor =
+                MaxEscapingBoundVarVisitor { outer_index: ty::INNERMOST, escaping: 0 };
+            value.visit_with(&mut max_visitor);
+            vec![None; max_visitor.escaping]
+        } else {
+            vec![]
+        };
+
         if self.infcx.next_trait_solver() {
-            match crate::solve::deeply_normalize(self, value) {
+            match crate::solve::deeply_normalize_with_skipped_universes(self, value, universes) {
                 Ok(value) => return Ok(Normalized { value, obligations: vec![] }),
                 Err(_errors) => {
                     return Err(NoSolution);
@@ -81,27 +100,9 @@ impl<'cx, 'tcx> QueryNormalizeExt<'tcx> for At<'cx, 'tcx> {
             obligations: vec![],
             cache: SsoHashMap::new(),
             anon_depth: 0,
-            universes: vec![],
+            universes,
         };
 
-        // This is actually a consequence by the way `normalize_erasing_regions` works currently.
-        // Because it needs to call the `normalize_generic_arg_after_erasing_regions`, it folds
-        // through tys and consts in a `TypeFoldable`. Importantly, it skips binders, leaving us
-        // with trying to normalize with escaping bound vars.
-        //
-        // Here, we just add the universes that we *would* have created had we passed through the binders.
-        //
-        // We *could* replace escaping bound vars eagerly here, but it doesn't seem really necessary.
-        // The rest of the code is already set up to be lazy about replacing bound vars,
-        // and only when we actually have to normalize.
-        if value.has_escaping_bound_vars() {
-            let mut max_visitor =
-                MaxEscapingBoundVarVisitor { outer_index: ty::INNERMOST, escaping: 0 };
-            value.visit_with(&mut max_visitor);
-            if max_visitor.escaping > 0 {
-                normalizer.universes.extend((0..max_visitor.escaping).map(|_| None));
-            }
-        }
         let result = value.try_fold_with(&mut normalizer);
         info!(
             "normalize::<{}>: result={:?} with {} obligations",
@@ -217,7 +218,7 @@ impl<'cx, 'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for QueryNormalizer<'cx, 'tcx>
         };
 
         // See note in `rustc_trait_selection::traits::project` about why we
-        // wait to fold the substs.
+        // wait to fold the args.
 
         // Wrap this in a closure so we don't accidentally return from the outer function
         let res = match kind {
@@ -227,7 +228,7 @@ impl<'cx, 'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for QueryNormalizer<'cx, 'tcx>
                     Reveal::UserFacing => ty.try_super_fold_with(self)?,
 
                     Reveal::All => {
-                        let substs = data.substs.try_fold_with(self)?;
+                        let args = data.args.try_fold_with(self)?;
                         let recursion_limit = self.interner().recursion_limit();
                         if !recursion_limit.value_within_limit(self.anon_depth) {
                             // A closure or generator may have itself as in its upvars.
@@ -243,14 +244,14 @@ impl<'cx, 'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for QueryNormalizer<'cx, 'tcx>
                         }
 
                         let generic_ty = self.interner().type_of(data.def_id);
-                        let concrete_ty = generic_ty.subst(self.interner(), substs);
+                        let concrete_ty = generic_ty.instantiate(self.interner(), args);
                         self.anon_depth += 1;
                         if concrete_ty == ty {
                             bug!(
-                                "infinite recursion generic_ty: {:#?}, substs: {:#?}, \
+                                "infinite recursion generic_ty: {:#?}, args: {:#?}, \
                                  concrete_ty: {:#?}, ty: {:#?}",
                                 generic_ty,
-                                substs,
+                                args,
                                 concrete_ty,
                                 ty
                             );
diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/ascribe_user_type.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/ascribe_user_type.rs
index 44671a07659..420d6326553 100644
--- a/compiler/rustc_trait_selection/src/traits/query/type_op/ascribe_user_type.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/type_op/ascribe_user_type.rs
@@ -4,7 +4,7 @@ use rustc_hir::def_id::{DefId, CRATE_DEF_ID};
 use rustc_infer::traits::Obligation;
 use rustc_middle::traits::query::NoSolution;
 use rustc_middle::traits::{ObligationCause, ObligationCauseCode};
-use rustc_middle::ty::{self, ParamEnvAnd, Ty, TyCtxt, UserSelfTy, UserSubsts, UserType};
+use rustc_middle::ty::{self, ParamEnvAnd, Ty, TyCtxt, UserArgs, UserSelfTy, UserType};
 
 pub use rustc_middle::traits::query::type_op::AscribeUserType;
 use rustc_span::{Span, DUMMY_SP};
@@ -47,8 +47,8 @@ pub fn type_op_ascribe_user_type_with_span<'tcx>(
     let span = span.unwrap_or(DUMMY_SP);
     match user_ty {
         UserType::Ty(user_ty) => relate_mir_and_user_ty(ocx, param_env, span, mir_ty, user_ty)?,
-        UserType::TypeOf(def_id, user_substs) => {
-            relate_mir_and_user_substs(ocx, param_env, span, mir_ty, def_id, user_substs)?
+        UserType::TypeOf(def_id, user_args) => {
+            relate_mir_and_user_args(ocx, param_env, span, mir_ty, def_id, user_args)?
         }
     };
     Ok(())
@@ -74,20 +74,20 @@ fn relate_mir_and_user_ty<'tcx>(
 }
 
 #[instrument(level = "debug", skip(ocx, param_env, span))]
-fn relate_mir_and_user_substs<'tcx>(
+fn relate_mir_and_user_args<'tcx>(
     ocx: &ObligationCtxt<'_, 'tcx>,
     param_env: ty::ParamEnv<'tcx>,
     span: Span,
     mir_ty: Ty<'tcx>,
     def_id: DefId,
-    user_substs: UserSubsts<'tcx>,
+    user_args: UserArgs<'tcx>,
 ) -> Result<(), NoSolution> {
     let param_env = param_env.without_const();
-    let UserSubsts { user_self_ty, substs } = user_substs;
+    let UserArgs { user_self_ty, args } = user_args;
     let tcx = ocx.infcx.tcx;
     let cause = ObligationCause::dummy_with_span(span);
 
-    let ty = tcx.type_of(def_id).subst(tcx, substs);
+    let ty = tcx.type_of(def_id).instantiate(tcx, args);
     let ty = ocx.normalize(&cause, param_env, ty);
     debug!("relate_type_and_user_type: ty of def-id is {:?}", ty);
 
@@ -98,7 +98,7 @@ fn relate_mir_and_user_substs<'tcx>(
     // Also, normalize the `instantiated_predicates`
     // because otherwise we wind up with duplicate "type
     // outlives" error messages.
-    let instantiated_predicates = tcx.predicates_of(def_id).instantiate(tcx, substs);
+    let instantiated_predicates = tcx.predicates_of(def_id).instantiate(tcx, args);
 
     debug!(?instantiated_predicates);
     for (instantiated_predicate, predicate_span) in instantiated_predicates {
@@ -116,7 +116,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.type_of(impl_def_id).subst(tcx, substs);
+        let impl_self_ty = tcx.type_of(impl_def_id).instantiate(tcx, args);
         let impl_self_ty = ocx.normalize(&cause, param_env, impl_self_ty);
 
         ocx.eq(&cause, param_env, self_ty, impl_self_ty)?;
@@ -128,9 +128,9 @@ fn relate_mir_and_user_substs<'tcx>(
 
     // In addition to proving the predicates, we have to
     // prove that `ty` is well-formed -- this is because
-    // the WF of `ty` is predicated on the substs being
+    // the WF of `ty` is predicated on the args being
     // well-formed, and we haven't proven *that*. We don't
-    // want to prove the WF of types from  `substs` directly because they
+    // want to prove the WF of types from  `args` directly because they
     // haven't been normalized.
     //
     // FIXME(nmatsakis): Well, perhaps we should normalize
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 d5f6aaa7fe9..aa195d70a9f 100644
--- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
@@ -209,7 +209,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         obligation: &PolyTraitObligation<'tcx>,
         candidates: &mut SelectionCandidateSet<'tcx>,
     ) {
-        // Okay to skip binder because the substs on generator types never
+        // Okay to skip binder because the args on generator types never
         // touch bound regions, they just capture the in-scope
         // type/region parameters.
         let self_ty = obligation.self_ty().skip_binder();
@@ -261,14 +261,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             return;
         };
 
-        // Okay to skip binder because the substs on closure types never
+        // Okay to skip binder because the args on closure types never
         // touch bound regions, they just capture the in-scope
         // type/region parameters
         match *obligation.self_ty().skip_binder().kind() {
-            ty::Closure(def_id, closure_substs) => {
+            ty::Closure(def_id, closure_args) => {
                 let is_const = self.tcx().is_const_fn_raw(def_id);
                 debug!(?kind, ?obligation, "assemble_unboxed_candidates");
-                match self.infcx.closure_kind(closure_substs) {
+                match self.infcx.closure_kind(closure_args) {
                     Some(closure_kind) => {
                         debug!(?closure_kind, "assemble_unboxed_candidates");
                         if closure_kind.extends(kind) {
@@ -351,7 +351,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         }
 
         let drcx = DeepRejectCtxt { treat_obligation_params: TreatParams::ForLookup };
-        let obligation_substs = obligation.predicate.skip_binder().trait_ref.substs;
+        let obligation_args = obligation.predicate.skip_binder().trait_ref.args;
         self.tcx().for_each_relevant_impl(
             obligation.predicate.def_id(),
             obligation.predicate.skip_binder().trait_ref.self_ty(),
@@ -360,9 +360,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 // consider a "quick reject". This avoids creating more types
                 // and so forth that we need to.
                 let impl_trait_ref = self.tcx().impl_trait_ref(impl_def_id).unwrap();
-                if !drcx
-                    .substs_refs_may_unify(obligation_substs, impl_trait_ref.skip_binder().substs)
-                {
+                if !drcx.args_refs_may_unify(obligation_args, impl_trait_ref.skip_binder().args) {
                     return;
                 }
                 if self.reject_fn_ptr_impls(
@@ -374,7 +372,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 }
 
                 self.infcx.probe(|_| {
-                    if let Ok(_substs) = self.match_impl(impl_def_id, impl_trait_ref, obligation) {
+                    if let Ok(_args) = self.match_impl(impl_def_id, impl_trait_ref, obligation) {
                         candidates.vec.push(ImplCandidate(impl_def_id));
                     }
                 });
@@ -402,8 +400,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         };
 
         for &(predicate, _) in self.tcx().predicates_of(impl_def_id).predicates {
-            let ty::ClauseKind::Trait(pred)
-                = predicate.kind().skip_binder() else { continue };
+            let ty::ClauseKind::Trait(pred) = predicate.kind().skip_binder() else { continue };
             if fn_ptr_trait != pred.trait_ref.def_id {
                 continue;
             }
@@ -651,7 +648,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             let ty = traits::normalize_projection_type(
                 self,
                 param_env,
-                tcx.mk_alias_ty(tcx.lang_items().deref_target()?, trait_ref.substs),
+                tcx.mk_alias_ty(tcx.lang_items().deref_target()?, trait_ref.args),
                 cause.clone(),
                 0,
                 // We're *intentionally* throwing these away,
@@ -689,7 +686,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             // Don't add any candidates if there are bound regions.
             return;
         };
-        let target = obligation.predicate.skip_binder().trait_ref.substs.type_at(1);
+        let target = obligation.predicate.skip_binder().trait_ref.args.type_at(1);
 
         debug!(?source, ?target, "assemble_candidates_for_unsizing");
 
diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
index 7adc29bbba4..2cb2895b476 100644
--- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
@@ -13,7 +13,7 @@ use rustc_infer::infer::LateBoundRegionConversionTime::HigherRankedType;
 use rustc_infer::infer::{DefineOpaqueTypes, InferOk};
 use rustc_middle::traits::SelectionOutputTypeParameterMismatch;
 use rustc_middle::ty::{
-    self, Binder, GenericParamDefKind, InternalSubsts, SubstsRef, ToPolyTraitRef, ToPredicate,
+    self, Binder, GenericArgs, GenericArgsRef, GenericParamDefKind, ToPolyTraitRef, ToPredicate,
     TraitPredicate, TraitRef, Ty, TyCtxt, TypeVisitableExt,
 };
 use rustc_span::def_id::DefId;
@@ -158,15 +158,16 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             self.infcx.instantiate_binder_with_placeholders(trait_predicate).trait_ref;
         let placeholder_self_ty = placeholder_trait_predicate.self_ty();
         let placeholder_trait_predicate = ty::Binder::dummy(placeholder_trait_predicate);
-        let (def_id, substs) = match *placeholder_self_ty.kind() {
+        let (def_id, args) = match *placeholder_self_ty.kind() {
             // Excluding IATs and type aliases here as they don't have meaningful item bounds.
-            ty::Alias(ty::Projection | ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
-                (def_id, substs)
+            ty::Alias(ty::Projection | ty::Opaque, ty::AliasTy { def_id, args, .. }) => {
+                (def_id, args)
             }
             _ => bug!("projection candidate for unexpected type: {:?}", placeholder_self_ty),
         };
 
-        let candidate_predicate = tcx.item_bounds(def_id).map_bound(|i| i[idx]).subst(tcx, substs);
+        let candidate_predicate =
+            tcx.item_bounds(def_id).map_bound(|i| i[idx]).instantiate(tcx, args);
         let candidate = candidate_predicate
             .as_trait_clause()
             .expect("projection candidate is not a trait predicate")
@@ -190,7 +191,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         })?);
 
         if let ty::Alias(ty::Projection, ..) = placeholder_self_ty.kind() {
-            let predicates = tcx.predicates_of(def_id).instantiate_own(tcx, substs);
+            let predicates = tcx.predicates_of(def_id).instantiate_own(tcx, args);
             for (predicate, _) in predicates {
                 let normalized = normalize_with_depth_to(
                     self,
@@ -298,8 +299,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                     .collect(),
                 Condition::IfTransmutable { src, dst } => {
                     let trait_def_id = obligation.predicate.def_id();
-                    let scope = predicate.trait_ref.substs.type_at(2);
-                    let assume_const = predicate.trait_ref.substs.const_at(3);
+                    let scope = predicate.trait_ref.args.type_at(2);
+                    let assume_const = predicate.trait_ref.args.const_at(3);
                     let make_obl = |from_ty, to_ty| {
                         let trait_ref1 = ty::TraitRef::new(
                             tcx,
@@ -342,19 +343,19 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         let Some(assume) = rustc_transmute::Assume::from_const(
             self.infcx.tcx,
             obligation.param_env,
-            predicate.trait_ref.substs.const_at(3)
+            predicate.trait_ref.args.const_at(3),
         ) else {
             return Err(Unimplemented);
         };
 
-        let dst = predicate.trait_ref.substs.type_at(0);
-        let src = predicate.trait_ref.substs.type_at(1);
+        let dst = predicate.trait_ref.args.type_at(0);
+        let src = predicate.trait_ref.args.type_at(1);
         debug!(?src, ?dst);
         let mut transmute_env = rustc_transmute::TransmuteTypeEnv::new(self.infcx);
         let maybe_transmutable = transmute_env.is_transmutable(
             obligation.cause.clone(),
             rustc_transmute::Types { dst, src },
-            predicate.trait_ref.substs.type_at(2),
+            predicate.trait_ref.args.type_at(2),
             assume,
         );
 
@@ -402,7 +403,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 obligation.recursion_depth + 1,
                 obligation.param_env,
                 trait_def_id,
-                &trait_ref.substs,
+                &trait_ref.args,
                 obligation.predicate,
             );
 
@@ -433,12 +434,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
 
         // First, create the substitutions by matching the impl again,
         // this time not in a probe.
-        let substs = self.rematch_impl(impl_def_id, obligation);
-        debug!(?substs, "impl substs");
+        let args = self.rematch_impl(impl_def_id, obligation);
+        debug!(?args, "impl args");
         ensure_sufficient_stack(|| {
             self.vtable_impl(
                 impl_def_id,
-                substs,
+                args,
                 &obligation.cause,
                 obligation.recursion_depth + 1,
                 obligation.param_env,
@@ -450,33 +451,33 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
     fn vtable_impl(
         &mut self,
         impl_def_id: DefId,
-        substs: Normalized<'tcx, SubstsRef<'tcx>>,
+        args: Normalized<'tcx, GenericArgsRef<'tcx>>,
         cause: &ObligationCause<'tcx>,
         recursion_depth: usize,
         param_env: ty::ParamEnv<'tcx>,
         parent_trait_pred: ty::Binder<'tcx, ty::TraitPredicate<'tcx>>,
     ) -> ImplSourceUserDefinedData<'tcx, PredicateObligation<'tcx>> {
-        debug!(?impl_def_id, ?substs, ?recursion_depth, "vtable_impl");
+        debug!(?impl_def_id, ?args, ?recursion_depth, "vtable_impl");
 
         let mut impl_obligations = self.impl_or_trait_obligations(
             cause,
             recursion_depth,
             param_env,
             impl_def_id,
-            &substs.value,
+            &args.value,
             parent_trait_pred,
         );
 
         debug!(?impl_obligations, "vtable_impl");
 
         // Because of RFC447, the impl-trait-ref and obligations
-        // are sufficient to determine the impl substs, without
+        // are sufficient to determine the impl args, without
         // relying on projections in the impl-trait-ref.
         //
         // e.g., `impl<U: Tr, V: Iterator<Item=U>> Foo<<U as Tr>::T> for V`
-        impl_obligations.extend(substs.obligations);
+        impl_obligations.extend(args.obligations);
 
-        ImplSourceUserDefinedData { impl_def_id, substs: substs.value, nested: impl_obligations }
+        ImplSourceUserDefinedData { impl_def_id, args: args.value, nested: impl_obligations }
     }
 
     fn confirm_object_candidate(
@@ -531,7 +532,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         // will be checked in the code below.
         for super_trait in tcx
             .super_predicates_of(trait_predicate.def_id())
-            .instantiate(tcx, trait_predicate.trait_ref.substs)
+            .instantiate(tcx, trait_predicate.trait_ref.args)
             .predicates
             .into_iter()
         {
@@ -569,68 +570,65 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             // higher-ranked things.
             // Prevent, e.g., `dyn Iterator<Item = str>`.
             for bound in self.tcx().item_bounds(assoc_type).transpose_iter() {
-                let subst_bound =
-                    if defs.count() == 0 {
-                        bound.subst(tcx, trait_predicate.trait_ref.substs)
-                    } else {
-                        let mut substs = smallvec::SmallVec::with_capacity(defs.count());
-                        substs.extend(trait_predicate.trait_ref.substs.iter());
-                        let mut bound_vars: smallvec::SmallVec<[ty::BoundVariableKind; 8]> =
-                            smallvec::SmallVec::with_capacity(
-                                bound.skip_binder().kind().bound_vars().len() + defs.count(),
-                            );
-                        bound_vars.extend(bound.skip_binder().kind().bound_vars().into_iter());
-                        InternalSubsts::fill_single(&mut substs, defs, &mut |param, _| match param
-                            .kind
-                        {
-                            GenericParamDefKind::Type { .. } => {
-                                let kind = ty::BoundTyKind::Param(param.def_id, param.name);
-                                let bound_var = ty::BoundVariableKind::Ty(kind);
-                                bound_vars.push(bound_var);
-                                Ty::new_bound(
-                                    tcx,
-                                    ty::INNERMOST,
-                                    ty::BoundTy {
-                                        var: ty::BoundVar::from_usize(bound_vars.len() - 1),
-                                        kind,
-                                    },
-                                )
-                                .into()
-                            }
-                            GenericParamDefKind::Lifetime => {
-                                let kind = ty::BoundRegionKind::BrNamed(param.def_id, param.name);
-                                let bound_var = ty::BoundVariableKind::Region(kind);
-                                bound_vars.push(bound_var);
-                                ty::Region::new_late_bound(
-                                    tcx,
-                                    ty::INNERMOST,
-                                    ty::BoundRegion {
-                                        var: ty::BoundVar::from_usize(bound_vars.len() - 1),
-                                        kind,
-                                    },
-                                )
-                                .into()
-                            }
-                            GenericParamDefKind::Const { .. } => {
-                                let bound_var = ty::BoundVariableKind::Const;
-                                bound_vars.push(bound_var);
-                                ty::Const::new_bound(
-                                    tcx,
-                                    ty::INNERMOST,
-                                    ty::BoundVar::from_usize(bound_vars.len() - 1),
-                                    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);
-                        let assoc_ty_substs = tcx.mk_substs(&substs);
-                        let bound =
-                            bound.map_bound(|b| b.kind().skip_binder()).subst(tcx, assoc_ty_substs);
-                        ty::Binder::bind_with_vars(bound, bound_vars).to_predicate(tcx)
-                    };
+                let subst_bound = if defs.count() == 0 {
+                    bound.instantiate(tcx, trait_predicate.trait_ref.args)
+                } else {
+                    let mut args = smallvec::SmallVec::with_capacity(defs.count());
+                    args.extend(trait_predicate.trait_ref.args.iter());
+                    let mut bound_vars: smallvec::SmallVec<[ty::BoundVariableKind; 8]> =
+                        smallvec::SmallVec::with_capacity(
+                            bound.skip_binder().kind().bound_vars().len() + defs.count(),
+                        );
+                    bound_vars.extend(bound.skip_binder().kind().bound_vars().into_iter());
+                    GenericArgs::fill_single(&mut args, defs, &mut |param, _| match param.kind {
+                        GenericParamDefKind::Type { .. } => {
+                            let kind = ty::BoundTyKind::Param(param.def_id, param.name);
+                            let bound_var = ty::BoundVariableKind::Ty(kind);
+                            bound_vars.push(bound_var);
+                            Ty::new_bound(
+                                tcx,
+                                ty::INNERMOST,
+                                ty::BoundTy {
+                                    var: ty::BoundVar::from_usize(bound_vars.len() - 1),
+                                    kind,
+                                },
+                            )
+                            .into()
+                        }
+                        GenericParamDefKind::Lifetime => {
+                            let kind = ty::BoundRegionKind::BrNamed(param.def_id, param.name);
+                            let bound_var = ty::BoundVariableKind::Region(kind);
+                            bound_vars.push(bound_var);
+                            ty::Region::new_late_bound(
+                                tcx,
+                                ty::INNERMOST,
+                                ty::BoundRegion {
+                                    var: ty::BoundVar::from_usize(bound_vars.len() - 1),
+                                    kind,
+                                },
+                            )
+                            .into()
+                        }
+                        GenericParamDefKind::Const { .. } => {
+                            let bound_var = ty::BoundVariableKind::Const;
+                            bound_vars.push(bound_var);
+                            ty::Const::new_bound(
+                                tcx,
+                                ty::INNERMOST,
+                                ty::BoundVar::from_usize(bound_vars.len() - 1),
+                                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);
+                    let assoc_ty_args = tcx.mk_args(&args);
+                    let bound =
+                        bound.map_bound(|b| b.kind().skip_binder()).instantiate(tcx, assoc_ty_args);
+                    ty::Binder::bind_with_vars(bound, bound_vars).to_predicate(tcx)
+                };
                 let normalized_bound = normalize_with_depth_to(
                     self,
                     obligation.param_env,
@@ -662,10 +660,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
 
         let tcx = self.tcx();
 
-        let Some(self_ty) = self
-            .infcx
-            .shallow_resolve(obligation.self_ty().no_bound_vars()) else
-        {
+        let Some(self_ty) = self.infcx.shallow_resolve(obligation.self_ty().no_bound_vars()) else {
             // FIXME: Ideally we'd support `for<'a> fn(&'a ()): Fn(&'a ())`,
             // but we do not currently. Luckily, such a bound is not
             // particularly useful, so we don't expect users to write
@@ -688,8 +683,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
 
         if obligation.is_const() && !is_const {
             // function is a trait method
-            if let ty::FnDef(def_id, substs) = self_ty.kind() && let Some(trait_id) = tcx.trait_of_item(*def_id) {
-                let trait_ref = TraitRef::from_method(tcx, trait_id, *substs);
+            if let ty::FnDef(def_id, args) = self_ty.kind() && let Some(trait_id) = tcx.trait_of_item(*def_id) {
+                let trait_ref = TraitRef::from_method(tcx, trait_id, *args);
                 let poly_trait_pred = Binder::dummy(trait_ref).with_constness(ty::BoundConstness::ConstIfConst);
                 let obligation = Obligation::new(tcx, cause.clone(), obligation.param_env, poly_trait_pred);
                 nested.push(obligation);
@@ -721,14 +716,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         let predicate = self.infcx.instantiate_binder_with_placeholders(obligation.predicate);
         let trait_ref = predicate.trait_ref;
         let trait_def_id = trait_ref.def_id;
-        let substs = trait_ref.substs;
+        let args = trait_ref.args;
 
         let trait_obligations = self.impl_or_trait_obligations(
             &obligation.cause,
             obligation.recursion_depth,
             obligation.param_env,
             trait_def_id,
-            &substs,
+            &args,
             obligation.predicate,
         );
 
@@ -741,17 +736,17 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         &mut self,
         obligation: &PolyTraitObligation<'tcx>,
     ) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
-        // Okay to skip binder because the substs on generator types never
+        // Okay to skip binder because the args on generator types never
         // touch bound regions, they just capture the in-scope
         // type/region parameters.
         let self_ty = self.infcx.shallow_resolve(obligation.self_ty().skip_binder());
-        let ty::Generator(generator_def_id, substs, _) = *self_ty.kind() else {
+        let ty::Generator(generator_def_id, args, _) = *self_ty.kind() else {
             bug!("closure candidate for non-closure {:?}", obligation);
         };
 
-        debug!(?obligation, ?generator_def_id, ?substs, "confirm_generator_candidate");
+        debug!(?obligation, ?generator_def_id, ?args, "confirm_generator_candidate");
 
-        let gen_sig = substs.as_generator().poly_sig();
+        let gen_sig = args.as_generator().poly_sig();
 
         // NOTE: The self-type is a generator type and hence is
         // in fact unparameterized (or at least does not reference any
@@ -780,17 +775,17 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         &mut self,
         obligation: &PolyTraitObligation<'tcx>,
     ) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
-        // Okay to skip binder because the substs on generator types never
+        // Okay to skip binder because the args on generator types never
         // touch bound regions, they just capture the in-scope
         // type/region parameters.
         let self_ty = self.infcx.shallow_resolve(obligation.self_ty().skip_binder());
-        let ty::Generator(generator_def_id, substs, _) = *self_ty.kind() else {
+        let ty::Generator(generator_def_id, args, _) = *self_ty.kind() else {
             bug!("closure candidate for non-closure {:?}", obligation);
         };
 
-        debug!(?obligation, ?generator_def_id, ?substs, "confirm_future_candidate");
+        debug!(?obligation, ?generator_def_id, ?args, "confirm_future_candidate");
 
-        let gen_sig = substs.as_generator().poly_sig();
+        let gen_sig = args.as_generator().poly_sig();
 
         let trait_ref = super::util::future_trait_ref_and_outputs(
             self.tcx(),
@@ -816,22 +811,22 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             .fn_trait_kind_from_def_id(obligation.predicate.def_id())
             .unwrap_or_else(|| bug!("closure candidate for non-fn trait {:?}", obligation));
 
-        // Okay to skip binder because the substs on closure types never
+        // Okay to skip binder because the args on closure types never
         // touch bound regions, they just capture the in-scope
         // type/region parameters.
         let self_ty = self.infcx.shallow_resolve(obligation.self_ty().skip_binder());
-        let ty::Closure(closure_def_id, substs) = *self_ty.kind() else {
+        let ty::Closure(closure_def_id, args) = *self_ty.kind() else {
             bug!("closure candidate for non-closure {:?}", obligation);
         };
 
-        let trait_ref = self.closure_trait_ref_unnormalized(obligation, substs);
+        let trait_ref = self.closure_trait_ref_unnormalized(obligation, args);
         let mut nested = self.confirm_poly_trait_refs(obligation, trait_ref)?;
 
         debug!(?closure_def_id, ?trait_ref, ?nested, "confirm closure candidate obligations");
 
         nested.push(obligation.with(
             self.tcx(),
-            ty::Binder::dummy(ty::PredicateKind::ClosureKind(closure_def_id, substs, kind)),
+            ty::Binder::dummy(ty::PredicateKind::ClosureKind(closure_def_id, args, kind)),
         ));
 
         Ok(nested)
@@ -908,7 +903,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         // `assemble_candidates_for_unsizing` should ensure there are no late-bound
         // regions here. See the comment there for more details.
         let source = self.infcx.shallow_resolve(obligation.self_ty().no_bound_vars().unwrap());
-        let target = obligation.predicate.skip_binder().trait_ref.substs.type_at(1);
+        let target = obligation.predicate.skip_binder().trait_ref.args.type_at(1);
         let target = self.infcx.shallow_resolve(target);
 
         debug!(?source, ?target, "confirm_trait_upcasting_unsize_candidate");
@@ -1011,7 +1006,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         // `assemble_candidates_for_unsizing` should ensure there are no late-bound
         // regions here. See the comment there for more details.
         let source = self.infcx.shallow_resolve(obligation.self_ty().no_bound_vars().unwrap());
-        let target = obligation.predicate.skip_binder().trait_ref.substs.type_at(1);
+        let target = obligation.predicate.skip_binder().trait_ref.args.type_at(1);
         let target = self.infcx.shallow_resolve(target);
 
         debug!(?source, ?target, "confirm_builtin_unsize_candidate");
@@ -1119,7 +1114,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             }
 
             // `Struct<T>` -> `Struct<U>`
-            (&ty::Adt(def, substs_a), &ty::Adt(_, substs_b)) => {
+            (&ty::Adt(def, args_a), &ty::Adt(_, args_b)) => {
                 let unsizing_params = tcx.unsizing_params_for_adt(def.did());
                 if unsizing_params.is_empty() {
                     return Err(Unimplemented);
@@ -1136,7 +1131,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                     obligation.param_env,
                     obligation.cause.clone(),
                     obligation.recursion_depth + 1,
-                    tail_field_ty.subst(tcx, substs_a),
+                    tail_field_ty.instantiate(tcx, args_a),
                     &mut nested,
                 );
                 let target_tail = normalize_with_depth_to(
@@ -1144,16 +1139,17 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                     obligation.param_env,
                     obligation.cause.clone(),
                     obligation.recursion_depth + 1,
-                    tail_field_ty.subst(tcx, substs_b),
+                    tail_field_ty.instantiate(tcx, args_b),
                     &mut nested,
                 );
 
                 // Check that the source struct with the target's
                 // unsizing parameters is equal to the target.
-                let substs = tcx.mk_substs_from_iter(substs_a.iter().enumerate().map(|(i, k)| {
-                    if unsizing_params.contains(i as u32) { substs_b[i] } else { k }
-                }));
-                let new_struct = Ty::new_adt(tcx, def, substs);
+                let args =
+                    tcx.mk_args_from_iter(args_a.iter().enumerate().map(|(i, k)| {
+                        if unsizing_params.contains(i as u32) { args_b[i] } else { k }
+                    }));
+                let new_struct = Ty::new_adt(tcx, def, args);
                 let InferOk { obligations, .. } = self
                     .infcx
                     .at(&obligation.cause, obligation.param_env)
@@ -1233,8 +1229,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 trait_pred.trait_ref.def_id = drop_trait;
                 trait_pred
             });
-            let substs = self.rematch_impl(impl_def_id, &new_obligation);
-            debug!(?substs, "impl substs");
+            let args = self.rematch_impl(impl_def_id, &new_obligation);
+            debug!(?args, "impl args");
 
             let cause = obligation.derived_cause(|derived| {
                 ImplDerivedObligation(Box::new(ImplDerivedObligationCause {
@@ -1247,7 +1243,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             let obligations = ensure_sufficient_stack(|| {
                 self.vtable_impl(
                     impl_def_id,
-                    substs,
+                    args,
                     &cause,
                     new_obligation.recursion_depth + 1,
                     new_obligation.param_env,
@@ -1259,7 +1255,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
 
         // We want to confirm the ADT's fields if we have an ADT
         let mut stack = match *self_ty.skip_binder().kind() {
-            ty::Adt(def, substs) => def.all_fields().map(|f| f.ty(tcx, substs)).collect(),
+            ty::Adt(def, args) => def.all_fields().map(|f| f.ty(tcx, args)).collect(),
             _ => vec![self_ty.skip_binder()],
         };
 
@@ -1292,20 +1288,20 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 ty::Tuple(tys) => {
                     stack.extend(tys.iter());
                 }
-                ty::Closure(_, substs) => {
-                    stack.push(substs.as_closure().tupled_upvars_ty());
+                ty::Closure(_, args) => {
+                    stack.push(args.as_closure().tupled_upvars_ty());
                 }
-                ty::Generator(_, substs, _) => {
-                    let generator = substs.as_generator();
+                ty::Generator(_, args, _) => {
+                    let generator = args.as_generator();
                     stack.extend([generator.tupled_upvars_ty(), generator.witness()]);
                 }
                 ty::GeneratorWitness(tys) => {
                     stack.extend(tcx.erase_late_bound_regions(tys).to_vec());
                 }
-                ty::GeneratorWitnessMIR(def_id, substs) => {
+                ty::GeneratorWitnessMIR(def_id, args) => {
                     let tcx = self.tcx();
                     stack.extend(tcx.generator_hidden_types(def_id).map(|bty| {
-                        let ty = bty.subst(tcx, substs);
+                        let ty = bty.instantiate(tcx, args);
                         debug_assert!(!ty.has_late_bound_regions());
                         ty
                     }))
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index 7f31ab75119..56d5d698d90 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -40,7 +40,7 @@ use rustc_middle::mir::interpret::ErrorHandled;
 use rustc_middle::ty::abstract_const::NotConstEvaluatable;
 use rustc_middle::ty::fold::BottomUpFolder;
 use rustc_middle::ty::relate::TypeRelation;
-use rustc_middle::ty::SubstsRef;
+use rustc_middle::ty::GenericArgsRef;
 use rustc_middle::ty::{self, EarlyBinder, PolyProjectionPredicate, ToPolyTraitRef, ToPredicate};
 use rustc_middle::ty::{Ty, TyCtxt, TypeFoldable, TypeVisitableExt};
 use rustc_span::symbol::sym;
@@ -843,8 +843,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                     }
                 }
 
-                ty::PredicateKind::ClosureKind(_, closure_substs, kind) => {
-                    match self.infcx.closure_kind(closure_substs) {
+                ty::PredicateKind::ClosureKind(_, closure_args, kind) => {
+                    match self.infcx.closure_kind(closure_args) {
                         Some(closure_kind) => {
                             if closure_kind.extends(kind) {
                                 Ok(EvaluatedToOk)
@@ -895,7 +895,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                                     .infcx
                                     .at(&obligation.cause, obligation.param_env)
                                     .trace(c1, c2)
-                                    .eq(DefineOpaqueTypes::No, a.substs, b.substs)
+                                    .eq(DefineOpaqueTypes::No, a.args, b.args)
                                 {
                                     return self.evaluate_predicates_recursively(
                                         previous_stack,
@@ -1194,7 +1194,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         // terms of `Fn` etc, but we could probably make this more
         // precise still.
         let unbound_input_types =
-            stack.fresh_trait_pred.skip_binder().trait_ref.substs.types().any(|ty| ty.is_fresh());
+            stack.fresh_trait_pred.skip_binder().trait_ref.args.types().any(|ty| ty.is_fresh());
 
         if unbound_input_types
             && stack.iter().skip(1).any(|prev| {
@@ -1635,9 +1635,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         debug!(?placeholder_trait_predicate);
 
         let tcx = self.infcx.tcx;
-        let (def_id, substs) = match *placeholder_trait_predicate.trait_ref.self_ty().kind() {
-            ty::Alias(ty::Projection | ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
-                (def_id, substs)
+        let (def_id, args) = match *placeholder_trait_predicate.trait_ref.self_ty().kind() {
+            ty::Alias(ty::Projection | ty::Opaque, ty::AliasTy { def_id, args, .. }) => {
+                (def_id, args)
             }
             _ => {
                 span_bug!(
@@ -1648,7 +1648,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 );
             }
         };
-        let bounds = tcx.item_bounds(def_id).subst(tcx, substs);
+        let bounds = tcx.item_bounds(def_id).instantiate(tcx, args);
 
         // The bounds returned by `item_bounds` may contain duplicates after
         // normalization, so try to deduplicate when possible to avoid
@@ -1785,11 +1785,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         if is_match {
             let generics = self.tcx().generics_of(obligation.predicate.def_id);
             // FIXME(generic-associated-types): Addresses aggressive inference in #92917.
-            // If this type is a GAT, and of the GAT substs resolve to something new,
+            // If this type is a GAT, and of the GAT args resolve to something new,
             // that means that we must have newly inferred something about the GAT.
             // We should give up in that case.
             if !generics.params.is_empty()
-                && obligation.predicate.substs[generics.parent_count..]
+                && obligation.predicate.args[generics.parent_count..]
                     .iter()
                     .any(|&p| p.has_non_region_infer() && self.infcx.shallow_resolve(p) != p)
             {
@@ -2127,13 +2127,13 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
                 obligation.predicate.rebind(tys.last().map_or_else(Vec::new, |&last| vec![last])),
             ),
 
-            ty::Adt(def, substs) => {
+            ty::Adt(def, args) => {
                 let sized_crit = def.sized_constraint(self.tcx());
                 // (*) binder moved here
                 Where(
                     obligation
                         .predicate
-                        .rebind(sized_crit.subst_iter_copied(self.tcx(), substs).collect()),
+                        .rebind(sized_crit.arg_iter_copied(self.tcx(), args).collect()),
                 )
             }
 
@@ -2190,20 +2190,20 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
                 Where(obligation.predicate.rebind(tys.iter().collect()))
             }
 
-            ty::Generator(_, substs, hir::Movability::Movable) => {
+            ty::Generator(_, args, hir::Movability::Movable) => {
                 if self.tcx().features().generator_clone {
                     let resolved_upvars =
-                        self.infcx.shallow_resolve(substs.as_generator().tupled_upvars_ty());
+                        self.infcx.shallow_resolve(args.as_generator().tupled_upvars_ty());
                     let resolved_witness =
-                        self.infcx.shallow_resolve(substs.as_generator().witness());
+                        self.infcx.shallow_resolve(args.as_generator().witness());
                     if resolved_upvars.is_ty_var() || resolved_witness.is_ty_var() {
                         // Not yet resolved.
                         Ambiguous
                     } else {
-                        let all = substs
+                        let all = args
                             .as_generator()
                             .upvar_tys()
-                            .chain(iter::once(substs.as_generator().witness()))
+                            .chain(iter::once(args.as_generator().witness()))
                             .collect::<Vec<_>>();
                         Where(obligation.predicate.rebind(all))
                     }
@@ -2227,24 +2227,24 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
                 Where(ty::Binder::bind_with_vars(witness_tys.to_vec(), all_vars))
             }
 
-            ty::GeneratorWitnessMIR(def_id, ref substs) => {
+            ty::GeneratorWitnessMIR(def_id, ref args) => {
                 let hidden_types = bind_generator_hidden_types_above(
                     self.infcx,
                     def_id,
-                    substs,
+                    args,
                     obligation.predicate.bound_vars(),
                 );
                 Where(hidden_types)
             }
 
-            ty::Closure(_, substs) => {
+            ty::Closure(_, args) => {
                 // (*) binder moved here
-                let ty = self.infcx.shallow_resolve(substs.as_closure().tupled_upvars_ty());
+                let ty = self.infcx.shallow_resolve(args.as_closure().tupled_upvars_ty());
                 if let ty::Infer(ty::TyVar(_)) = ty.kind() {
                     // Not yet resolved.
                     Ambiguous
                 } else {
-                    Where(obligation.predicate.rebind(substs.as_closure().upvar_tys().collect()))
+                    Where(obligation.predicate.rebind(args.as_closure().upvar_tys().collect()))
                 }
             }
 
@@ -2321,14 +2321,14 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
                 t.rebind(tys.iter().collect())
             }
 
-            ty::Closure(_, ref substs) => {
-                let ty = self.infcx.shallow_resolve(substs.as_closure().tupled_upvars_ty());
+            ty::Closure(_, ref args) => {
+                let ty = self.infcx.shallow_resolve(args.as_closure().tupled_upvars_ty());
                 t.rebind(vec![ty])
             }
 
-            ty::Generator(_, ref substs, _) => {
-                let ty = self.infcx.shallow_resolve(substs.as_generator().tupled_upvars_ty());
-                let witness = substs.as_generator().witness();
+            ty::Generator(_, ref args, _) => {
+                let ty = self.infcx.shallow_resolve(args.as_generator().tupled_upvars_ty());
+                let witness = args.as_generator().witness();
                 t.rebind([ty].into_iter().chain(iter::once(witness)).collect())
             }
 
@@ -2337,18 +2337,18 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
                 types.map_bound(|types| types.to_vec())
             }
 
-            ty::GeneratorWitnessMIR(def_id, ref substs) => {
-                bind_generator_hidden_types_above(self.infcx, def_id, substs, t.bound_vars())
+            ty::GeneratorWitnessMIR(def_id, ref args) => {
+                bind_generator_hidden_types_above(self.infcx, def_id, args, t.bound_vars())
             }
 
             // For `PhantomData<T>`, we pass `T`.
-            ty::Adt(def, substs) if def.is_phantom_data() => t.rebind(substs.types().collect()),
+            ty::Adt(def, args) if def.is_phantom_data() => t.rebind(args.types().collect()),
 
-            ty::Adt(def, substs) => {
-                t.rebind(def.all_fields().map(|f| f.ty(self.tcx(), substs)).collect())
+            ty::Adt(def, args) => {
+                t.rebind(def.all_fields().map(|f| f.ty(self.tcx(), args)).collect())
             }
 
-            ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
+            ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) => {
                 let ty = self.tcx().type_of(def_id);
                 if ty.skip_binder().references_error() {
                     return Err(SelectionError::OpaqueTypeAutoTraitLeakageUnknown(def_id));
@@ -2356,7 +2356,7 @@ impl<'tcx> SelectionContext<'_, '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![ty.subst(self.tcx(), substs)])
+                t.rebind(vec![ty.instantiate(self.tcx(), args)])
             }
         })
     }
@@ -2428,10 +2428,10 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
         &mut self,
         impl_def_id: DefId,
         obligation: &PolyTraitObligation<'tcx>,
-    ) -> Normalized<'tcx, SubstsRef<'tcx>> {
+    ) -> Normalized<'tcx, GenericArgsRef<'tcx>> {
         let impl_trait_ref = self.tcx().impl_trait_ref(impl_def_id).unwrap();
         match self.match_impl(impl_def_id, impl_trait_ref, obligation) {
-            Ok(substs) => substs,
+            Ok(args) => args,
             Err(()) => {
                 // FIXME: A rematch may fail when a candidate cache hit occurs
                 // on thefreshened form of the trait predicate, but the match
@@ -2447,7 +2447,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
                         impl_def_id, obligation
                     ),
                 );
-                let value = self.infcx.fresh_substs_for_item(obligation.cause.span, impl_def_id);
+                let value = self.infcx.fresh_args_for_item(obligation.cause.span, impl_def_id);
                 let err = Ty::new_error(self.tcx(), guar);
                 let value = value.fold_with(&mut BottomUpFolder {
                     tcx: self.tcx(),
@@ -2466,14 +2466,14 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
         impl_def_id: DefId,
         impl_trait_ref: EarlyBinder<ty::TraitRef<'tcx>>,
         obligation: &PolyTraitObligation<'tcx>,
-    ) -> Result<Normalized<'tcx, SubstsRef<'tcx>>, ()> {
+    ) -> Result<Normalized<'tcx, GenericArgsRef<'tcx>>, ()> {
         let placeholder_obligation =
             self.infcx.instantiate_binder_with_placeholders(obligation.predicate);
         let placeholder_obligation_trait_ref = placeholder_obligation.trait_ref;
 
-        let impl_substs = self.infcx.fresh_substs_for_item(obligation.cause.span, impl_def_id);
+        let impl_args = self.infcx.fresh_args_for_item(obligation.cause.span, impl_def_id);
 
-        let impl_trait_ref = impl_trait_ref.subst(self.tcx(), impl_substs);
+        let impl_trait_ref = impl_trait_ref.instantiate(self.tcx(), impl_args);
         if impl_trait_ref.references_error() {
             return Err(());
         }
@@ -2515,7 +2515,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
             return Err(());
         }
 
-        Ok(Normalized { value: impl_substs, obligations: nested_obligations })
+        Ok(Normalized { value: impl_args, obligations: nested_obligations })
     }
 
     /// Normalize `where_clause_trait_ref` and try to match it against
@@ -2580,9 +2580,9 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
     fn closure_trait_ref_unnormalized(
         &mut self,
         obligation: &PolyTraitObligation<'tcx>,
-        substs: SubstsRef<'tcx>,
+        args: GenericArgsRef<'tcx>,
     ) -> ty::PolyTraitRef<'tcx> {
-        let closure_sig = substs.as_closure().sig();
+        let closure_sig = args.as_closure().sig();
 
         debug!(?closure_sig);
 
@@ -2615,8 +2615,8 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
         cause: &ObligationCause<'tcx>,
         recursion_depth: usize,
         param_env: ty::ParamEnv<'tcx>,
-        def_id: DefId,           // of impl or trait
-        substs: SubstsRef<'tcx>, // for impl or trait
+        def_id: DefId,              // of impl or trait
+        args: GenericArgsRef<'tcx>, // for impl or trait
         parent_trait_pred: ty::Binder<'tcx, ty::TraitPredicate<'tcx>>,
     ) -> Vec<PredicateObligation<'tcx>> {
         let tcx = self.tcx();
@@ -2637,7 +2637,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
         // that order.
         let predicates = tcx.predicates_of(def_id);
         assert_eq!(predicates.parent, None);
-        let predicates = predicates.instantiate_own(tcx, substs);
+        let predicates = predicates.instantiate_own(tcx, args);
         let mut obligations = Vec::with_capacity(predicates.len());
         for (index, (predicate, span)) in predicates.into_iter().enumerate() {
             let cause =
@@ -2990,7 +2990,7 @@ pub enum ProjectionMatchesProjection {
 fn bind_generator_hidden_types_above<'tcx>(
     infcx: &InferCtxt<'tcx>,
     def_id: DefId,
-    substs: ty::SubstsRef<'tcx>,
+    args: ty::GenericArgsRef<'tcx>,
     bound_vars: &ty::List<ty::BoundVariableKind>,
 ) -> ty::Binder<'tcx, Vec<Ty<'tcx>>> {
     let tcx = infcx.tcx;
@@ -3006,7 +3006,7 @@ fn bind_generator_hidden_types_above<'tcx>(
         // Deduplicate tys to avoid repeated work.
         .filter(|bty| seen_tys.insert(*bty))
         .map(|bty| {
-            let mut ty = bty.subst(tcx, substs);
+            let mut ty = bty.instantiate(tcx, args);
 
             // Only remap erased regions if we use them.
             if considering_regions {
diff --git a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
index 96f1287416f..b61b209654c 100644
--- a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
@@ -23,7 +23,7 @@ use rustc_data_structures::fx::FxIndexSet;
 use rustc_errors::{error_code, DelayDm, Diagnostic};
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_middle::ty::{self, ImplSubject, Ty, TyCtxt, TypeVisitableExt};
-use rustc_middle::ty::{InternalSubsts, SubstsRef};
+use rustc_middle::ty::{GenericArgs, GenericArgsRef};
 use rustc_session::lint::builtin::COHERENCE_LEAK_CHECK;
 use rustc_session::lint::builtin::ORDER_DEPENDENT_TRAIT_OBJECTS;
 use rustc_span::{Span, DUMMY_SP};
@@ -48,7 +48,7 @@ pub struct OverlapError<'tcx> {
 /// When we have selected one impl, but are actually using item definitions from
 /// a parent impl providing a default, we need a way to translate between the
 /// type parameters of the two impls. Here the `source_impl` is the one we've
-/// selected, and `source_substs` is a substitution of its generics.
+/// selected, and `source_args` is a substitution of its generics.
 /// And `target_node` is the impl/trait we're actually going to get the
 /// definition from. The resulting substitution will map from `target_node`'s
 /// generics to `source_impl`'s generics as instantiated by `source_subst`.
@@ -76,51 +76,46 @@ pub struct OverlapError<'tcx> {
 /// through associated type projection. We deal with such cases by using
 /// *fulfillment* to relate the two impls, requiring that all projections are
 /// resolved.
-pub fn translate_substs<'tcx>(
+pub fn translate_args<'tcx>(
     infcx: &InferCtxt<'tcx>,
     param_env: ty::ParamEnv<'tcx>,
     source_impl: DefId,
-    source_substs: SubstsRef<'tcx>,
+    source_args: GenericArgsRef<'tcx>,
     target_node: specialization_graph::Node,
-) -> SubstsRef<'tcx> {
-    translate_substs_with_cause(
-        infcx,
-        param_env,
-        source_impl,
-        source_substs,
-        target_node,
-        |_, _| ObligationCause::dummy(),
-    )
+) -> GenericArgsRef<'tcx> {
+    translate_args_with_cause(infcx, param_env, source_impl, source_args, target_node, |_, _| {
+        ObligationCause::dummy()
+    })
 }
 
-/// Like [translate_substs], but obligations from the parent implementation
+/// Like [translate_args], but obligations from the parent implementation
 /// are registered with the provided `ObligationCause`.
 ///
 /// This is for reporting *region* errors from those bounds. Type errors should
 /// not happen because the specialization graph already checks for those, and
 /// will result in an ICE.
-pub fn translate_substs_with_cause<'tcx>(
+pub fn translate_args_with_cause<'tcx>(
     infcx: &InferCtxt<'tcx>,
     param_env: ty::ParamEnv<'tcx>,
     source_impl: DefId,
-    source_substs: SubstsRef<'tcx>,
+    source_args: GenericArgsRef<'tcx>,
     target_node: specialization_graph::Node,
     cause: impl Fn(usize, Span) -> ObligationCause<'tcx>,
-) -> SubstsRef<'tcx> {
+) -> GenericArgsRef<'tcx> {
     debug!(
-        "translate_substs({:?}, {:?}, {:?}, {:?})",
-        param_env, source_impl, source_substs, target_node
+        "translate_args({:?}, {:?}, {:?}, {:?})",
+        param_env, source_impl, source_args, target_node
     );
     let source_trait_ref =
-        infcx.tcx.impl_trait_ref(source_impl).unwrap().subst(infcx.tcx, &source_substs);
+        infcx.tcx.impl_trait_ref(source_impl).unwrap().instantiate(infcx.tcx, &source_args);
 
     // translate the Self and Param parts of the substitution, since those
     // vary across impls
-    let target_substs = match target_node {
+    let target_args = match target_node {
         specialization_graph::Node::Impl(target_impl) => {
             // no need to translate if we're targeting the impl we started with
             if source_impl == target_impl {
-                return source_substs;
+                return source_args;
             }
 
             fulfill_implication(infcx, param_env, source_trait_ref, source_impl, target_impl, cause)
@@ -131,11 +126,11 @@ pub fn translate_substs_with_cause<'tcx>(
                     )
                 })
         }
-        specialization_graph::Node::Trait(..) => source_trait_ref.substs,
+        specialization_graph::Node::Trait(..) => source_trait_ref.args,
     };
 
     // directly inherent the method generics, since those do not vary across impls
-    source_substs.rebase_onto(infcx.tcx, source_impl, target_substs)
+    source_args.rebase_onto(infcx.tcx, source_impl, target_args)
 }
 
 /// Is `impl1` a specialization of `impl2`?
@@ -172,7 +167,7 @@ pub(super) fn specializes(tcx: TyCtxt<'_>, (impl1_def_id, impl2_def_id): (DefId,
 
     // create a parameter environment corresponding to a (placeholder) instantiation of impl1
     let penv = tcx.param_env(impl1_def_id);
-    let impl1_trait_ref = tcx.impl_trait_ref(impl1_def_id).unwrap().subst_identity();
+    let impl1_trait_ref = tcx.impl_trait_ref(impl1_def_id).unwrap().instantiate_identity();
 
     // Create an infcx, taking the predicates of impl1 as assumptions:
     let infcx = tcx.infer_ctxt().build();
@@ -196,7 +191,7 @@ fn fulfill_implication<'tcx>(
     source_impl: DefId,
     target_impl: DefId,
     error_cause: impl Fn(usize, Span) -> ObligationCause<'tcx>,
-) -> Result<SubstsRef<'tcx>, ()> {
+) -> Result<GenericArgsRef<'tcx>, ()> {
     debug!(
         "fulfill_implication({:?}, trait_ref={:?} |- {:?} applies)",
         param_env, source_trait_ref, target_impl
@@ -221,18 +216,16 @@ fn fulfill_implication<'tcx>(
     let source_trait = ImplSubject::Trait(source_trait_ref);
 
     let selcx = &mut SelectionContext::new(&infcx);
-    let target_substs = infcx.fresh_substs_for_item(DUMMY_SP, target_impl);
+    let target_args = infcx.fresh_args_for_item(DUMMY_SP, target_impl);
     let (target_trait, obligations) =
-        util::impl_subject_and_oblig(selcx, param_env, target_impl, target_substs, error_cause);
+        util::impl_subject_and_oblig(selcx, param_env, target_impl, target_args, error_cause);
 
     // do the impls unify? If not, no specialization.
-    let Ok(InferOk { obligations: more_obligations, .. }) =
-        infcx.at(&ObligationCause::dummy(), param_env).eq(DefineOpaqueTypes::No, source_trait, target_trait)
+    let Ok(InferOk { obligations: more_obligations, .. }) = infcx
+        .at(&ObligationCause::dummy(), param_env)
+        .eq(DefineOpaqueTypes::No, source_trait, target_trait)
     else {
-        debug!(
-            "fulfill_implication: {:?} does not unify with {:?}",
-            source_trait, target_trait
-        );
+        debug!("fulfill_implication: {:?} does not unify with {:?}", source_trait, target_trait);
         return Err(());
     };
 
@@ -261,7 +254,7 @@ fn fulfill_implication<'tcx>(
 
     // Now resolve the *substitution* we built for the target earlier, replacing
     // the inference variables inside with whatever we got from fulfillment.
-    Ok(infcx.resolve_vars_if_possible(target_substs))
+    Ok(infcx.resolve_vars_if_possible(target_args))
 }
 
 /// Query provider for `specialization_graph_of`.
@@ -469,21 +462,21 @@ fn report_conflicting_impls<'tcx>(
 pub(crate) fn to_pretty_impl_header(tcx: TyCtxt<'_>, impl_def_id: DefId) -> Option<String> {
     use std::fmt::Write;
 
-    let trait_ref = tcx.impl_trait_ref(impl_def_id)?.subst_identity();
+    let trait_ref = tcx.impl_trait_ref(impl_def_id)?.instantiate_identity();
     let mut w = "impl".to_owned();
 
-    let substs = InternalSubsts::identity_for_item(tcx, impl_def_id);
+    let args = GenericArgs::identity_for_item(tcx, impl_def_id);
 
     // FIXME: Currently only handles ?Sized.
     //        Needs to support ?Move and ?DynSized when they are implemented.
     let mut types_without_default_bounds = FxIndexSet::default();
     let sized_trait = tcx.lang_items().sized_trait();
 
-    if !substs.is_empty() {
-        types_without_default_bounds.extend(substs.types());
+    if !args.is_empty() {
+        types_without_default_bounds.extend(args.types());
         w.push('<');
         w.push_str(
-            &substs
+            &args
                 .iter()
                 .map(|k| k.to_string())
                 .filter(|k| k != "'_")
@@ -497,7 +490,7 @@ pub(crate) fn to_pretty_impl_header(tcx: TyCtxt<'_>, impl_def_id: DefId) -> Opti
         w,
         " {} for {}",
         trait_ref.print_only_trait_path(),
-        tcx.type_of(impl_def_id).subst_identity()
+        tcx.type_of(impl_def_id).instantiate_identity()
     )
     .unwrap();
 
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 aa5c624f471..e9a592bdee7 100644
--- a/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs
+++ b/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs
@@ -180,7 +180,7 @@ impl<'tcx> ChildrenExt<'tcx> for Children {
             if le && !ge {
                 debug!(
                     "descending as child of TraitRef {:?}",
-                    tcx.impl_trait_ref(possible_sibling).unwrap().subst_identity()
+                    tcx.impl_trait_ref(possible_sibling).unwrap().instantiate_identity()
                 );
 
                 // The impl specializes `possible_sibling`.
@@ -188,7 +188,7 @@ impl<'tcx> ChildrenExt<'tcx> for Children {
             } else if ge && !le {
                 debug!(
                     "placing as parent of TraitRef {:?}",
-                    tcx.impl_trait_ref(possible_sibling).unwrap().subst_identity()
+                    tcx.impl_trait_ref(possible_sibling).unwrap().instantiate_identity()
                 );
 
                 replace_children.push(possible_sibling);
diff --git a/compiler/rustc_trait_selection/src/traits/structural_match.rs b/compiler/rustc_trait_selection/src/traits/structural_match.rs
index 420f8c5dceb..0864e4dc841 100644
--- a/compiler/rustc_trait_selection/src/traits/structural_match.rs
+++ b/compiler/rustc_trait_selection/src/traits/structural_match.rs
@@ -62,8 +62,8 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for Search<'tcx> {
     fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
         debug!("Search visiting ty: {:?}", ty);
 
-        let (adt_def, substs) = match *ty.kind() {
-            ty::Adt(adt_def, substs) => (adt_def, substs),
+        let (adt_def, args) = match *ty.kind() {
+            ty::Adt(adt_def, args) => (adt_def, args),
             ty::Param(_) => {
                 return ControlFlow::Break(ty);
             }
@@ -157,15 +157,15 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for Search<'tcx> {
         // instead looks directly at its fields outside
         // this match), so we skip super_visit_with.
         //
-        // (Must not recur on substs for `PhantomData<T>` cf
+        // (Must not recur on args for `PhantomData<T>` cf
         // rust-lang/rust#55028 and rust-lang/rust#55837; but also
-        // want to skip substs when only uses of generic are
+        // want to skip args when only uses of generic are
         // behind unsafe pointers `*const T`/`*mut T`.)
 
         // even though we skip super_visit_with, we must recur on
         // fields of ADT.
         let tcx = self.tcx;
-        adt_def.all_fields().map(|field| field.ty(tcx, substs)).try_for_each(|field_ty| {
+        adt_def.all_fields().map(|field| field.ty(tcx, args)).try_for_each(|field_ty| {
             let ty = self.tcx.normalize_erasing_regions(ty::ParamEnv::empty(), field_ty);
             debug!("structural-match ADT: field_ty={:?}, ty={:?}", field_ty, ty);
             ty.visit_with(self)
diff --git a/compiler/rustc_trait_selection/src/traits/util.rs b/compiler/rustc_trait_selection/src/traits/util.rs
index 302b6cacf2c..7b34908c4be 100644
--- a/compiler/rustc_trait_selection/src/traits/util.rs
+++ b/compiler/rustc_trait_selection/src/traits/util.rs
@@ -4,7 +4,7 @@ use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::Diagnostic;
 use rustc_hir::def_id::DefId;
 use rustc_infer::infer::InferOk;
-use rustc_middle::ty::SubstsRef;
+use rustc_middle::ty::GenericArgsRef;
 use rustc_middle::ty::{self, ImplSubject, ToPredicate, Ty, TyCtxt, TypeVisitableExt};
 use rustc_span::Span;
 use smallvec::SmallVec;
@@ -194,24 +194,24 @@ impl Iterator for SupertraitDefIds<'_> {
 // Other
 ///////////////////////////////////////////////////////////////////////////
 
-/// Instantiate all bound parameters of the impl subject with the given substs,
+/// Instantiate all bound parameters of the impl subject with the given args,
 /// returning the resulting subject and all obligations that arise.
 /// The obligations are closed under normalization.
 pub fn impl_subject_and_oblig<'a, 'tcx>(
     selcx: &mut SelectionContext<'a, 'tcx>,
     param_env: ty::ParamEnv<'tcx>,
     impl_def_id: DefId,
-    impl_substs: SubstsRef<'tcx>,
+    impl_args: GenericArgsRef<'tcx>,
     cause: impl Fn(usize, Span) -> ObligationCause<'tcx>,
 ) -> (ImplSubject<'tcx>, impl Iterator<Item = PredicateObligation<'tcx>>) {
     let subject = selcx.tcx().impl_subject(impl_def_id);
-    let subject = subject.subst(selcx.tcx(), impl_substs);
+    let subject = subject.instantiate(selcx.tcx(), impl_args);
 
     let InferOk { value: subject, obligations: normalization_obligations1 } =
         selcx.infcx.at(&ObligationCause::dummy(), param_env).normalize(subject);
 
     let predicates = selcx.tcx().predicates_of(impl_def_id);
-    let predicates = predicates.instantiate(selcx.tcx(), impl_substs);
+    let predicates = predicates.instantiate(selcx.tcx(), impl_args);
     let InferOk { value: predicates, obligations: normalization_obligations2 } =
         selcx.infcx.at(&ObligationCause::dummy(), param_env).normalize(predicates);
     let impl_obligations = super::predicates_for_generics(cause, param_env, predicates);
@@ -303,13 +303,13 @@ pub enum TupleArgumentsFlag {
     No,
 }
 
-// Verify that the trait item and its implementation have compatible substs lists
-pub fn check_substs_compatible<'tcx>(
+// Verify that the trait item and its implementation have compatible args lists
+pub fn check_args_compatible<'tcx>(
     tcx: TyCtxt<'tcx>,
     assoc_item: ty::AssocItem,
-    substs: ty::SubstsRef<'tcx>,
+    args: ty::GenericArgsRef<'tcx>,
 ) -> bool {
-    fn check_substs_compatible_inner<'tcx>(
+    fn check_args_compatible_inner<'tcx>(
         tcx: TyCtxt<'tcx>,
         generics: &'tcx ty::Generics,
         args: &'tcx [ty::GenericArg<'tcx>],
@@ -322,7 +322,7 @@ pub fn check_substs_compatible<'tcx>(
 
         if let Some(parent) = generics.parent
             && let parent_generics = tcx.generics_of(parent)
-            && !check_substs_compatible_inner(tcx, parent_generics, parent_args) {
+            && !check_args_compatible_inner(tcx, parent_generics, parent_args) {
             return false;
         }
 
@@ -339,7 +339,7 @@ pub fn check_substs_compatible<'tcx>(
     }
 
     let generics = tcx.generics_of(assoc_item.def_id);
-    // Chop off any additional substs (RPITIT) substs
-    let substs = &substs[0..generics.count().min(substs.len())];
-    check_substs_compatible_inner(tcx, generics, substs)
+    // Chop off any additional args (RPITIT) args
+    let args = &args[0..generics.count().min(args.len())];
+    check_args_compatible_inner(tcx, generics, args)
 }
diff --git a/compiler/rustc_trait_selection/src/traits/vtable.rs b/compiler/rustc_trait_selection/src/traits/vtable.rs
index 1f83f1f44bc..78816fed017 100644
--- a/compiler/rustc_trait_selection/src/traits/vtable.rs
+++ b/compiler/rustc_trait_selection/src/traits/vtable.rs
@@ -6,7 +6,7 @@ use rustc_infer::traits::util::PredicateSet;
 use rustc_infer::traits::ImplSource;
 use rustc_middle::query::Providers;
 use rustc_middle::ty::visit::TypeVisitableExt;
-use rustc_middle::ty::InternalSubsts;
+use rustc_middle::ty::GenericArgs;
 use rustc_middle::ty::{self, GenericParamDefKind, ToPredicate, Ty, TyCtxt, VtblEntry};
 use rustc_span::{sym, Span};
 use smallvec::SmallVec;
@@ -241,12 +241,12 @@ fn vtable_entries<'tcx>(
                     debug!("vtable_entries: trait_method={:?}", def_id);
 
                     // The method may have some early-bound lifetimes; add regions for those.
-                    let substs = trait_ref.map_bound(|trait_ref| {
-                        InternalSubsts::for_item(tcx, def_id, |param, _| match param.kind {
+                    let args = trait_ref.map_bound(|trait_ref| {
+                        GenericArgs::for_item(tcx, def_id, |param, _| match param.kind {
                             GenericParamDefKind::Lifetime => tcx.lifetimes.re_erased.into(),
                             GenericParamDefKind::Type { .. }
                             | GenericParamDefKind::Const { .. } => {
-                                trait_ref.substs[param.index as usize]
+                                trait_ref.args[param.index as usize]
                             }
                         })
                     });
@@ -254,14 +254,14 @@ fn vtable_entries<'tcx>(
                     // The trait type may have higher-ranked lifetimes in it;
                     // erase them if they appear, so that we get the type
                     // at some particular call site.
-                    let substs = tcx
-                        .normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), substs);
+                    let args =
+                        tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), args);
 
                     // It's possible that the method relies on where-clauses that
                     // do not hold for this particular set of type parameters.
                     // Note that this method could then never be called, so we
                     // do not want to try and codegen it, in that case (see #23435).
-                    let predicates = tcx.predicates_of(def_id).instantiate_own(tcx, substs);
+                    let predicates = tcx.predicates_of(def_id).instantiate_own(tcx, args);
                     if impossible_predicates(
                         tcx,
                         predicates.map(|(predicate, _)| predicate).collect(),
@@ -274,7 +274,7 @@ fn vtable_entries<'tcx>(
                         tcx,
                         ty::ParamEnv::reveal_all(),
                         def_id,
-                        substs,
+                        args,
                     )
                     .expect("resolution failed during building vtable representation");
                     VtblEntry::Method(instance)
diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs
index d81722ce22a..b327dd2e150 100644
--- a/compiler/rustc_trait_selection/src/traits/wf.rs
+++ b/compiler/rustc_trait_selection/src/traits/wf.rs
@@ -2,8 +2,8 @@ use crate::infer::InferCtxt;
 use crate::traits;
 use rustc_hir as hir;
 use rustc_hir::lang_items::LangItem;
-use rustc_middle::ty::subst::{GenericArg, GenericArgKind, SubstsRef};
 use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
+use rustc_middle::ty::{GenericArg, GenericArgKind, GenericArgsRef};
 use rustc_span::def_id::{DefId, LocalDefId, CRATE_DEF_ID};
 use rustc_span::{Span, DUMMY_SP};
 
@@ -341,7 +341,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
         let trait_ref = &trait_pred.trait_ref;
 
         // Negative trait predicates don't require supertraits to hold, just
-        // that their substs are WF.
+        // that their args are WF.
         if trait_pred.polarity == ty::ImplPolarity::Negative {
             self.compute_negative_trait_pred(trait_ref);
             return;
@@ -349,9 +349,9 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
 
         // if the trait predicate is not const, the wf obligations should not be const as well.
         let obligations = if trait_pred.constness == ty::BoundConstness::NotConst {
-            self.nominal_obligations_without_const(trait_ref.def_id, trait_ref.substs)
+            self.nominal_obligations_without_const(trait_ref.def_id, trait_ref.args)
         } else {
-            self.nominal_obligations(trait_ref.def_id, trait_ref.substs)
+            self.nominal_obligations(trait_ref.def_id, trait_ref.args)
         };
 
         debug!("compute_trait_pred obligations {:?}", obligations);
@@ -383,7 +383,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
 
         self.out.extend(
             trait_ref
-                .substs
+                .args
                 .iter()
                 .enumerate()
                 .filter(|(_, arg)| {
@@ -416,7 +416,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
     // Compute the obligations that are required for `trait_ref` to be WF,
     // given that it is a *negative* trait predicate.
     fn compute_negative_trait_pred(&mut self, trait_ref: &ty::TraitRef<'tcx>) {
-        for arg in trait_ref.substs {
+        for arg in trait_ref.args {
             self.compute(arg);
         }
     }
@@ -427,7 +427,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
         // A projection is well-formed if
         //
         // (a) its predicates hold (*)
-        // (b) its substs are wf
+        // (b) its args are wf
         //
         // (*) The predicates of an associated type include the predicates of
         //     the trait that it's contained in. For example, given
@@ -446,17 +446,17 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
         //     `i32: Copy`
         // ]
         // Projection types do not require const predicates.
-        let obligations = self.nominal_obligations_without_const(data.def_id, data.substs);
+        let obligations = self.nominal_obligations_without_const(data.def_id, data.args);
         self.out.extend(obligations);
 
-        self.compute_projection_substs(data.substs);
+        self.compute_projection_args(data.args);
     }
 
     fn compute_inherent_projection(&mut self, data: ty::AliasTy<'tcx>) {
         // An inherent projection is well-formed if
         //
         // (a) its predicates hold (*)
-        // (b) its substs are wf
+        // (b) its args are wf
         //
         // (*) The predicates of an inherent associated type include the
         //     predicates of the impl that it's contained in.
@@ -464,7 +464,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
         if !data.self_ty().has_escaping_bound_vars() {
             // FIXME(inherent_associated_types): Should this happen inside of a snapshot?
             // FIXME(inherent_associated_types): This is incompatible with the new solver and lazy norm!
-            let substs = traits::project::compute_inherent_assoc_ty_substs(
+            let args = traits::project::compute_inherent_assoc_ty_args(
                 &mut traits::SelectionContext::new(self.infcx),
                 self.param_env,
                 data,
@@ -473,22 +473,21 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
                 &mut self.out,
             );
             // Inherent projection types do not require const predicates.
-            let obligations = self.nominal_obligations_without_const(data.def_id, substs);
+            let obligations = self.nominal_obligations_without_const(data.def_id, args);
             self.out.extend(obligations);
         }
 
-        self.compute_projection_substs(data.substs);
+        self.compute_projection_args(data.args);
     }
 
-    fn compute_projection_substs(&mut self, substs: SubstsRef<'tcx>) {
+    fn compute_projection_args(&mut self, args: GenericArgsRef<'tcx>) {
         let tcx = self.tcx();
         let cause = self.cause(traits::WellFormed(None));
         let param_env = self.param_env;
         let depth = self.recursion_depth;
 
         self.out.extend(
-            substs
-                .iter()
+            args.iter()
                 .filter(|arg| {
                     matches!(arg.unpack(), GenericArgKind::Type(..) | GenericArgKind::Const(..))
                 })
@@ -541,7 +540,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
                     match ct.kind() {
                         ty::ConstKind::Unevaluated(uv) => {
                             if !ct.has_escaping_bound_vars() {
-                                let obligations = self.nominal_obligations(uv.def, uv.substs);
+                                let obligations = self.nominal_obligations(uv.def, uv.args);
                                 self.out.extend(obligations);
 
                                 let predicate = ty::Binder::dummy(ty::PredicateKind::Clause(
@@ -661,14 +660,14 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
                     self.compute_inherent_projection(data);
                 }
 
-                ty::Adt(def, substs) => {
+                ty::Adt(def, args) => {
                     // WfNominalType
-                    let obligations = self.nominal_obligations(def.did(), substs);
+                    let obligations = self.nominal_obligations(def.did(), args);
                     self.out.extend(obligations);
                 }
 
-                ty::FnDef(did, substs) => {
-                    let obligations = self.nominal_obligations_without_const(did, substs);
+                ty::FnDef(did, args) => {
+                    let obligations = self.nominal_obligations_without_const(did, args);
                     self.out.extend(obligations);
                 }
 
@@ -688,7 +687,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
                     }
                 }
 
-                ty::Generator(did, substs, ..) => {
+                ty::Generator(did, args, ..) => {
                     // Walk ALL the types in the generator: this will
                     // include the upvar types as well as the yield
                     // type. Note that this is mildly distinct from
@@ -696,11 +695,11 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
                     // about the signature of the closure. We don't
                     // have the problem of implied bounds here since
                     // generators don't take arguments.
-                    let obligations = self.nominal_obligations(did, substs);
+                    let obligations = self.nominal_obligations(did, args);
                     self.out.extend(obligations);
                 }
 
-                ty::Closure(did, substs) => {
+                ty::Closure(did, args) => {
                     // Only check the upvar types for WF, not the rest
                     // of the types within. This is needed because we
                     // capture the signature and it may not be WF
@@ -723,7 +722,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
                     // fn(&'a T) }`, as discussed in #25860.
                     walker.skip_current_subtree(); // subtree handled below
                     // FIXME(eddyb) add the type to `walker` instead of recursing.
-                    self.compute(substs.as_closure().tupled_upvars_ty().into());
+                    self.compute(args.as_closure().tupled_upvars_ty().into());
                     // Note that we cannot skip the generic types
                     // types. Normally, within the fn
                     // body where they are created, the generics will
@@ -739,7 +738,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
                     // can cause compiler crashes when the user abuses unsafe
                     // code to procure such a closure.
                     // See tests/ui/type-alias-impl-trait/wf_check_closures.rs
-                    let obligations = self.nominal_obligations(did, substs);
+                    let obligations = self.nominal_obligations(did, args);
                     self.out.extend(obligations);
                 }
 
@@ -748,18 +747,18 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
                     // types appearing in the fn signature
                 }
 
-                ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
+                ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) => {
                     // All of the requirements on type parameters
                     // have already been checked for `impl Trait` in
                     // return position. We do need to check type-alias-impl-trait though.
                     if self.tcx().is_type_alias_impl_trait(def_id) {
-                        let obligations = self.nominal_obligations(def_id, substs);
+                        let obligations = self.nominal_obligations(def_id, args);
                         self.out.extend(obligations);
                     }
                 }
 
-                ty::Alias(ty::Weak, ty::AliasTy { def_id, substs, .. }) => {
-                    let obligations = self.nominal_obligations(def_id, substs);
+                ty::Alias(ty::Weak, ty::AliasTy { def_id, args, .. }) => {
+                    let obligations = self.nominal_obligations(def_id, args);
                     self.out.extend(obligations);
                 }
 
@@ -826,7 +825,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
     fn nominal_obligations_inner(
         &mut self,
         def_id: DefId,
-        substs: SubstsRef<'tcx>,
+        args: GenericArgsRef<'tcx>,
         remap_constness: bool,
     ) -> Vec<traits::PredicateObligation<'tcx>> {
         let predicates = self.tcx().predicates_of(def_id);
@@ -837,7 +836,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
             origins.extend(iter::repeat(parent).take(head.predicates.len()));
         }
 
-        let predicates = predicates.instantiate(self.tcx(), substs);
+        let predicates = predicates.instantiate(self.tcx(), args);
         trace!("{:#?}", predicates);
         debug_assert_eq!(predicates.predicates.len(), origins.len());
 
@@ -867,17 +866,17 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
     fn nominal_obligations(
         &mut self,
         def_id: DefId,
-        substs: SubstsRef<'tcx>,
+        args: GenericArgsRef<'tcx>,
     ) -> Vec<traits::PredicateObligation<'tcx>> {
-        self.nominal_obligations_inner(def_id, substs, false)
+        self.nominal_obligations_inner(def_id, args, false)
     }
 
     fn nominal_obligations_without_const(
         &mut self,
         def_id: DefId,
-        substs: SubstsRef<'tcx>,
+        args: GenericArgsRef<'tcx>,
     ) -> Vec<traits::PredicateObligation<'tcx>> {
-        self.nominal_obligations_inner(def_id, substs, true)
+        self.nominal_obligations_inner(def_id, args, true)
     }
 
     fn from_object_ty(
diff --git a/compiler/rustc_traits/src/dropck_outlives.rs b/compiler/rustc_traits/src/dropck_outlives.rs
index f35c14eeac8..074764f0c4e 100644
--- a/compiler/rustc_traits/src/dropck_outlives.rs
+++ b/compiler/rustc_traits/src/dropck_outlives.rs
@@ -4,7 +4,7 @@ use rustc_infer::infer::canonical::{Canonical, QueryResponse};
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_middle::query::Providers;
 use rustc_middle::traits::query::{DropckConstraint, DropckOutlivesResult};
-use rustc_middle::ty::InternalSubsts;
+use rustc_middle::ty::GenericArgs;
 use rustc_middle::ty::TyCtxt;
 use rustc_trait_selection::infer::InferCtxtBuilderExt;
 use rustc_trait_selection::traits::query::dropck_outlives::{
@@ -41,11 +41,11 @@ pub(crate) fn adt_dtorck_constraint(
     } else if def.is_phantom_data() {
         // The first generic parameter here is guaranteed to be a type because it's
         // `PhantomData`.
-        let substs = InternalSubsts::identity_for_item(tcx, def_id);
-        assert_eq!(substs.len(), 1);
+        let args = GenericArgs::identity_for_item(tcx, def_id);
+        assert_eq!(args.len(), 1);
         let result = DropckConstraint {
             outlives: vec![],
-            dtorck_types: vec![substs.type_at(0)],
+            dtorck_types: vec![args.type_at(0)],
             overflows: vec![],
         };
         debug!("dtorck_constraint: {:?} => {:?}", def, result);
@@ -54,7 +54,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).subst_identity();
+        let fty = tcx.type_of(field.did).instantiate_identity();
         dtorck_constraint_for_ty_inner(tcx, span, fty, 0, fty, &mut result)?;
     }
     result.outlives.extend(tcx.destructor_constraints(def));
diff --git a/compiler/rustc_traits/src/normalize_projection_ty.rs b/compiler/rustc_traits/src/normalize_projection_ty.rs
index 83828f177bc..0dbac56b47d 100644
--- a/compiler/rustc_traits/src/normalize_projection_ty.rs
+++ b/compiler/rustc_traits/src/normalize_projection_ty.rs
@@ -58,7 +58,7 @@ fn normalize_weak_ty<'tcx>(
     tcx.infer_ctxt().enter_canonical_trait_query(
         &goal,
         |ocx, ParamEnvAnd { param_env, value: goal }| {
-            let obligations = tcx.predicates_of(goal.def_id).instantiate_own(tcx, goal.substs).map(
+            let obligations = tcx.predicates_of(goal.def_id).instantiate_own(tcx, goal.args).map(
                 |(predicate, span)| {
                     traits::Obligation::new(
                         tcx,
@@ -69,7 +69,7 @@ fn normalize_weak_ty<'tcx>(
                 },
             );
             ocx.register_obligations(obligations);
-            let normalized_ty = tcx.type_of(goal.def_id).subst(tcx, goal.substs);
+            let normalized_ty = tcx.type_of(goal.def_id).instantiate(tcx, goal.args);
             Ok(NormalizationResult { normalized_ty })
         },
     )
diff --git a/compiler/rustc_transmute/src/layout/tree.rs b/compiler/rustc_transmute/src/layout/tree.rs
index be434eb7d00..8bd26818256 100644
--- a/compiler/rustc_transmute/src/layout/tree.rs
+++ b/compiler/rustc_transmute/src/layout/tree.rs
@@ -175,8 +175,8 @@ pub(crate) mod rustc {
     use rustc_middle::ty::layout::LayoutError;
     use rustc_middle::ty::util::Discr;
     use rustc_middle::ty::AdtDef;
+    use rustc_middle::ty::GenericArgsRef;
     use rustc_middle::ty::ParamEnv;
-    use rustc_middle::ty::SubstsRef;
     use rustc_middle::ty::VariantDef;
     use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
     use rustc_span::ErrorGuaranteed;
@@ -297,7 +297,7 @@ pub(crate) mod rustc {
                         .fold(Tree::unit(), |tree, elt| tree.then(elt)))
                 }
 
-                ty::Adt(adt_def, substs_ref) => {
+                ty::Adt(adt_def, args_ref) => {
                     use rustc_middle::ty::AdtKind;
 
                     // If the layout is ill-specified, halt.
@@ -316,7 +316,7 @@ pub(crate) mod rustc {
                         AdtKind::Struct => Self::from_repr_c_variant(
                             ty,
                             *adt_def,
-                            substs_ref,
+                            args_ref,
                             &layout_summary,
                             None,
                             adt_def.non_enum_variant(),
@@ -330,7 +330,7 @@ pub(crate) mod rustc {
                                 tree = tree.or(Self::from_repr_c_variant(
                                     ty,
                                     *adt_def,
-                                    substs_ref,
+                                    args_ref,
                                     &layout_summary,
                                     Some(discr),
                                     adt_def.variant(idx),
@@ -351,7 +351,7 @@ pub(crate) mod rustc {
                             let mut tree = Tree::uninhabited();
 
                             for field in adt_def.all_fields() {
-                                let variant_ty = field.ty(tcx, substs_ref);
+                                let variant_ty = field.ty(tcx, args_ref);
                                 let variant_layout = layout_of(tcx, variant_ty)?;
                                 let padding_needed = ty_layout.size() - variant_layout.size();
                                 let variant = Self::def(Def::Field(field))
@@ -383,7 +383,7 @@ pub(crate) mod rustc {
         fn from_repr_c_variant(
             ty: Ty<'tcx>,
             adt_def: AdtDef<'tcx>,
-            substs_ref: SubstsRef<'tcx>,
+            args_ref: GenericArgsRef<'tcx>,
             layout_summary: &LayoutSummary,
             discr: Option<Discr<'tcx>>,
             variant_def: &'tcx VariantDef,
@@ -427,7 +427,7 @@ pub(crate) mod rustc {
             // Next come fields.
             let fields_span = trace_span!("treeifying fields").entered();
             for field_def in variant_def.fields.iter() {
-                let field_ty = field_def.ty(tcx, substs_ref);
+                let field_ty = field_def.ty(tcx, args_ref);
                 let _span = trace_span!("treeifying field", field = ?field_ty).entered();
 
                 // begin with the field's visibility
diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs
index 55484f5c72e..d0a7414b4ff 100644
--- a/compiler/rustc_ty_utils/src/abi.rs
+++ b/compiler/rustc_ty_utils/src/abi.rs
@@ -51,12 +51,12 @@ fn fn_sig_for_fn_abi<'tcx>(
             //
             // We normalize the `fn_sig` again after substituting at a later point.
             let mut sig = match *ty.kind() {
-                ty::FnDef(def_id, substs) => tcx
+                ty::FnDef(def_id, args) => tcx
                     .fn_sig(def_id)
                     .map_bound(|fn_sig| {
                         tcx.normalize_erasing_regions(tcx.param_env(def_id), fn_sig)
                     })
-                    .subst(tcx, substs),
+                    .instantiate(tcx, args),
                 _ => unreachable!(),
             };
 
@@ -71,8 +71,8 @@ fn fn_sig_for_fn_abi<'tcx>(
             }
             sig
         }
-        ty::Closure(def_id, substs) => {
-            let sig = substs.as_closure().sig();
+        ty::Closure(def_id, args) => {
+            let sig = args.as_closure().sig();
 
             let bound_vars = tcx.mk_bound_variable_kinds_from_iter(
                 sig.bound_vars().iter().chain(iter::once(ty::BoundVariableKind::Region(ty::BrEnv))),
@@ -82,7 +82,7 @@ fn fn_sig_for_fn_abi<'tcx>(
                 kind: ty::BoundRegionKind::BrEnv,
             };
             let env_region = ty::Region::new_late_bound(tcx, ty::INNERMOST, br);
-            let env_ty = tcx.closure_env_ty(def_id, substs, env_region).unwrap();
+            let env_ty = tcx.closure_env_ty(def_id, args, env_region).unwrap();
 
             let sig = sig.skip_binder();
             ty::Binder::bind_with_vars(
@@ -96,8 +96,8 @@ fn fn_sig_for_fn_abi<'tcx>(
                 bound_vars,
             )
         }
-        ty::Generator(did, substs, _) => {
-            let sig = substs.as_generator().poly_sig();
+        ty::Generator(did, args, _) => {
+            let sig = args.as_generator().poly_sig();
 
             let bound_vars = tcx.mk_bound_variable_kinds_from_iter(
                 sig.bound_vars().iter().chain(iter::once(ty::BoundVariableKind::Region(ty::BrEnv))),
@@ -111,8 +111,8 @@ fn fn_sig_for_fn_abi<'tcx>(
 
             let pin_did = tcx.require_lang_item(LangItem::Pin, None);
             let pin_adt_ref = tcx.adt_def(pin_did);
-            let pin_substs = tcx.mk_substs(&[env_ty.into()]);
-            let env_ty = Ty::new_adt(tcx, pin_adt_ref, pin_substs);
+            let pin_args = tcx.mk_args(&[env_ty.into()]);
+            let env_ty = Ty::new_adt(tcx, pin_adt_ref, pin_args);
 
             let sig = sig.skip_binder();
             // The `FnSig` and the `ret_ty` here is for a generators main
@@ -123,8 +123,8 @@ fn fn_sig_for_fn_abi<'tcx>(
                 // The signature should be `Future::poll(_, &mut Context<'_>) -> Poll<Output>`
                 let poll_did = tcx.require_lang_item(LangItem::Poll, None);
                 let poll_adt_ref = tcx.adt_def(poll_did);
-                let poll_substs = tcx.mk_substs(&[sig.return_ty.into()]);
-                let ret_ty = Ty::new_adt(tcx, poll_adt_ref, poll_substs);
+                let poll_args = tcx.mk_args(&[sig.return_ty.into()]);
+                let ret_ty = Ty::new_adt(tcx, poll_adt_ref, poll_args);
 
                 // We have to replace the `ResumeTy` that is used for type and borrow checking
                 // with `&mut Context<'_>` which is used in codegen.
@@ -145,8 +145,8 @@ fn fn_sig_for_fn_abi<'tcx>(
                 // The signature should be `Generator::resume(_, Resume) -> GeneratorState<Yield, Return>`
                 let state_did = tcx.require_lang_item(LangItem::GeneratorState, None);
                 let state_adt_ref = tcx.adt_def(state_did);
-                let state_substs = tcx.mk_substs(&[sig.yield_ty.into(), sig.return_ty.into()]);
-                let ret_ty = Ty::new_adt(tcx, state_adt_ref, state_substs);
+                let state_args = tcx.mk_args(&[sig.yield_ty.into(), sig.return_ty.into()]);
+                let ret_ty = Ty::new_adt(tcx, state_adt_ref, state_args);
 
                 (sig.resume_ty, ret_ty)
             };
diff --git a/compiler/rustc_ty_utils/src/assoc.rs b/compiler/rustc_ty_utils/src/assoc.rs
index 7e22ef89ed3..4a544232174 100644
--- a/compiler/rustc_ty_utils/src/assoc.rs
+++ b/compiler/rustc_ty_utils/src/assoc.rs
@@ -5,7 +5,7 @@ use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId};
 use rustc_hir::definitions::DefPathData;
 use rustc_hir::intravisit::{self, Visitor};
 use rustc_middle::query::Providers;
-use rustc_middle::ty::{self, ImplTraitInTraitData, InternalSubsts, Ty, TyCtxt};
+use rustc_middle::ty::{self, GenericArgs, ImplTraitInTraitData, Ty, TyCtxt};
 use rustc_span::symbol::kw;
 
 pub fn provide(providers: &mut Providers) {
@@ -215,7 +215,9 @@ fn associated_types_for_impl_traits_in_associated_fn(
         }
 
         DefKind::Impl { .. } => {
-            let Some(trait_fn_def_id) = tcx.associated_item(fn_def_id).trait_item_def_id else { return &[] };
+            let Some(trait_fn_def_id) = tcx.associated_item(fn_def_id).trait_item_def_id else {
+                return &[];
+            };
 
             tcx.arena.alloc_from_iter(
                 tcx.associated_types_for_impl_traits_in_associated_fn(trait_fn_def_id).iter().map(
@@ -288,7 +290,7 @@ fn associated_type_for_impl_trait_in_trait(
     trait_assoc_ty.type_of(ty::EarlyBinder::bind(Ty::new_opaque(
         tcx,
         opaque_ty_def_id.to_def_id(),
-        InternalSubsts::identity_for_item(tcx, opaque_ty_def_id),
+        GenericArgs::identity_for_item(tcx, opaque_ty_def_id),
     )));
 
     trait_assoc_ty.is_type_alias_impl_trait(false);
diff --git a/compiler/rustc_ty_utils/src/consts.rs b/compiler/rustc_ty_utils/src/consts.rs
index 426c98012b3..5f754d90b6d 100644
--- a/compiler/rustc_ty_utils/src/consts.rs
+++ b/compiler/rustc_ty_utils/src/consts.rs
@@ -42,7 +42,7 @@ pub(crate) fn destructure_const<'tcx>(
             (field_consts, None)
         }
         ty::Adt(def, _) if def.variants().is_empty() => bug!("unreachable"),
-        ty::Adt(def, substs) => {
+        ty::Adt(def, args) => {
             let (variant_idx, branches) = if def.is_enum() {
                 let (head, rest) = branches.split_first().unwrap();
                 (VariantIdx::from_u32(head.unwrap_leaf().try_to_u32().unwrap()), rest)
@@ -53,7 +53,7 @@ pub(crate) fn destructure_const<'tcx>(
             let mut field_consts = Vec::with_capacity(fields.len());
 
             for (field, field_valtree) in iter::zip(fields, branches) {
-                let field_ty = field.ty(tcx, substs);
+                let field_ty = field.ty(tcx, args);
                 let field_const = ty::Const::new_value(tcx, *field_valtree, field_ty);
                 field_consts.push(field_const);
             }
@@ -133,8 +133,8 @@ fn recurse_build<'tcx>(
             let val = ty::ValTree::zst();
             ty::Const::new_value(tcx, val, node.ty)
         }
-        &ExprKind::NamedConst { def_id, substs, user_ty: _ } => {
-            let uneval = ty::UnevaluatedConst::new(def_id, substs);
+        &ExprKind::NamedConst { def_id, args, user_ty: _ } => {
+            let uneval = ty::UnevaluatedConst::new(def_id, args);
             ty::Const::new_unevaluated(tcx, uneval, node.ty)
         }
         ExprKind::ConstParam { param, .. } => ty::Const::new_param(tcx, *param, node.ty),
@@ -306,8 +306,9 @@ impl<'a, 'tcx> IsThirPolymorphic<'a, 'tcx> {
         }
 
         match expr.kind {
-            thir::ExprKind::NamedConst { substs, .. }
-            | thir::ExprKind::ConstBlock { substs, .. } => substs.has_non_region_param(),
+            thir::ExprKind::NamedConst { args, .. } | thir::ExprKind::ConstBlock { args, .. } => {
+                args.has_non_region_param()
+            }
             thir::ExprKind::ConstParam { .. } => true,
             thir::ExprKind::Repeat { value, count } => {
                 self.visit_expr(&self.thir()[value]);
diff --git a/compiler/rustc_ty_utils/src/implied_bounds.rs b/compiler/rustc_ty_utils/src/implied_bounds.rs
index 2822595a8a7..be063a097c0 100644
--- a/compiler/rustc_ty_utils/src/implied_bounds.rs
+++ b/compiler/rustc_ty_utils/src/implied_bounds.rs
@@ -13,7 +13,7 @@ pub fn provide(providers: &mut Providers) {
 fn assumed_wf_types<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx [(Ty<'tcx>, Span)] {
     match tcx.def_kind(def_id) {
         DefKind::Fn => {
-            let sig = tcx.fn_sig(def_id).subst_identity();
+            let sig = tcx.fn_sig(def_id).instantiate_identity();
             let liberated_sig = tcx.liberate_late_bound_regions(def_id.to_def_id(), sig);
             tcx.arena.alloc_from_iter(itertools::zip_eq(
                 liberated_sig.inputs_and_output,
@@ -21,7 +21,7 @@ fn assumed_wf_types<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx [(Ty<'
             ))
         }
         DefKind::AssocFn => {
-            let sig = tcx.fn_sig(def_id).subst_identity();
+            let sig = tcx.fn_sig(def_id).instantiate_identity();
             let liberated_sig = tcx.liberate_late_bound_regions(def_id.to_def_id(), sig);
             let mut assumed_wf_types: Vec<_> =
                 tcx.assumed_wf_types(tcx.local_parent(def_id)).into();
@@ -35,8 +35,8 @@ fn assumed_wf_types<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx [(Ty<'
             // Trait arguments and the self type for trait impls or only the self type for
             // inherent impls.
             let tys = match tcx.impl_trait_ref(def_id) {
-                Some(trait_ref) => trait_ref.skip_binder().substs.types().collect(),
-                None => vec![tcx.type_of(def_id).subst_identity()],
+                Some(trait_ref) => trait_ref.skip_binder().args.types().collect(),
+                None => vec![tcx.type_of(def_id).instantiate_identity()],
             };
 
             let mut impl_spans = impl_spans(tcx, def_id);
diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs
index 1d93a79e591..16b1836ba9f 100644
--- a/compiler/rustc_ty_utils/src/instance.rs
+++ b/compiler/rustc_ty_utils/src/instance.rs
@@ -3,19 +3,19 @@ use rustc_hir::def_id::DefId;
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_middle::query::Providers;
 use rustc_middle::traits::CodegenObligationError;
-use rustc_middle::ty::subst::SubstsRef;
+use rustc_middle::ty::GenericArgsRef;
 use rustc_middle::ty::{self, Instance, TyCtxt, TypeVisitableExt};
 use rustc_span::sym;
 use rustc_trait_selection::traits;
-use traits::{translate_substs, Reveal};
+use traits::{translate_args, Reveal};
 
 use crate::errors::UnexpectedFnPtrAssociatedItem;
 
 fn resolve_instance<'tcx>(
     tcx: TyCtxt<'tcx>,
-    key: ty::ParamEnvAnd<'tcx, (DefId, SubstsRef<'tcx>)>,
+    key: ty::ParamEnvAnd<'tcx, (DefId, GenericArgsRef<'tcx>)>,
 ) -> Result<Option<Instance<'tcx>>, ErrorGuaranteed> {
-    let (param_env, (def, substs)) = key.into_parts();
+    let (param_env, (def, args)) = key.into_parts();
 
     let result = if let Some(trait_def_id) = tcx.trait_of_item(def) {
         debug!(" => associated item, attempting to find impl in param_env {:#?}", param_env);
@@ -24,19 +24,19 @@ fn resolve_instance<'tcx>(
             def,
             param_env,
             trait_def_id,
-            tcx.normalize_erasing_regions(param_env, substs),
+            tcx.normalize_erasing_regions(param_env, args),
         )
     } else {
         let ty = tcx.type_of(def);
-        let item_type = tcx.subst_and_normalize_erasing_regions(substs, param_env, ty);
+        let item_type = tcx.subst_and_normalize_erasing_regions(args, param_env, ty);
 
         let def = match *item_type.kind() {
             ty::FnDef(def_id, ..) if tcx.is_intrinsic(def_id) => {
                 debug!(" => intrinsic");
                 ty::InstanceDef::Intrinsic(def)
             }
-            ty::FnDef(def_id, substs) if Some(def_id) == tcx.lang_items().drop_in_place_fn() => {
-                let ty = substs.type_at(0);
+            ty::FnDef(def_id, args) if Some(def_id) == tcx.lang_items().drop_in_place_fn() => {
+                let ty = args.type_at(0);
 
                 if ty.needs_drop(tcx, param_env) {
                     debug!(" => nontrivial drop glue");
@@ -63,7 +63,7 @@ fn resolve_instance<'tcx>(
                 ty::InstanceDef::Item(def)
             }
         };
-        Ok(Some(Instance { def, substs }))
+        Ok(Some(Instance { def, args }))
     };
     debug!("inner_resolve_instance: result={:?}", result);
     result
@@ -74,11 +74,11 @@ fn resolve_associated_item<'tcx>(
     trait_item_id: DefId,
     param_env: ty::ParamEnv<'tcx>,
     trait_id: DefId,
-    rcvr_substs: SubstsRef<'tcx>,
+    rcvr_args: GenericArgsRef<'tcx>,
 ) -> Result<Option<Instance<'tcx>>, ErrorGuaranteed> {
-    debug!(?trait_item_id, ?param_env, ?trait_id, ?rcvr_substs, "resolve_associated_item");
+    debug!(?trait_item_id, ?param_env, ?trait_id, ?rcvr_args, "resolve_associated_item");
 
-    let trait_ref = ty::TraitRef::from_method(tcx, trait_id, rcvr_substs);
+    let trait_ref = ty::TraitRef::from_method(tcx, trait_id, rcvr_args);
 
     let vtbl = match tcx.codegen_select_candidate((param_env, trait_ref)) {
         Ok(vtbl) => vtbl,
@@ -102,9 +102,9 @@ fn resolve_associated_item<'tcx>(
         traits::ImplSource::UserDefined(impl_data) => {
             debug!(
                 "resolving ImplSource::UserDefined: {:?}, {:?}, {:?}, {:?}",
-                param_env, trait_item_id, rcvr_substs, impl_data
+                param_env, trait_item_id, rcvr_args, impl_data
             );
-            assert!(!rcvr_substs.has_infer());
+            assert!(!rcvr_args.has_infer());
             assert!(!trait_ref.has_infer());
 
             let trait_def_id = tcx.trait_id_of_impl(impl_data.impl_def_id).unwrap();
@@ -117,15 +117,15 @@ fn resolve_associated_item<'tcx>(
                 });
             let infcx = tcx.infer_ctxt().build();
             let param_env = param_env.with_reveal_all_normalized(tcx);
-            let substs = rcvr_substs.rebase_onto(tcx, trait_def_id, impl_data.substs);
-            let substs = translate_substs(
+            let args = rcvr_args.rebase_onto(tcx, trait_def_id, impl_data.args);
+            let args = translate_args(
                 &infcx,
                 param_env,
                 impl_data.impl_def_id,
-                substs,
+                args,
                 leaf_def.defining_node,
             );
-            let substs = infcx.tcx.erase_regions(substs);
+            let args = infcx.tcx.erase_regions(args);
 
             // Since this is a trait item, we need to see if the item is either a trait default item
             // or a specialization because we can't resolve those unless we can `Reveal::All`.
@@ -159,7 +159,7 @@ fn resolve_associated_item<'tcx>(
                 return Err(guard);
             }
 
-            let substs = tcx.erase_regions(substs);
+            let args = tcx.erase_regions(args);
 
             // Check if we just resolved an associated `const` declaration from
             // a `trait` to an associated `const` definition in an `impl`, where
@@ -175,14 +175,11 @@ fn resolve_associated_item<'tcx>(
                 ))?;
             }
 
-            Some(ty::Instance::new(leaf_def.item.def_id, substs))
+            Some(ty::Instance::new(leaf_def.item.def_id, args))
         }
         traits::ImplSource::Object(ref data) => {
             traits::get_vtable_index_of_object_method(tcx, data, trait_item_id).map(|index| {
-                Instance {
-                    def: ty::InstanceDef::Virtual(trait_item_id, index),
-                    substs: rcvr_substs,
-                }
+                Instance { def: ty::InstanceDef::Virtual(trait_item_id, index), args: rcvr_args }
             })
         }
         traits::ImplSource::Builtin(..) => {
@@ -205,14 +202,14 @@ fn resolve_associated_item<'tcx>(
 
                     Some(Instance {
                         def: ty::InstanceDef::CloneShim(trait_item_id, self_ty),
-                        substs: rcvr_substs,
+                        args: rcvr_args,
                     })
                 } else {
                     assert_eq!(name, sym::clone_from);
 
                     // Use the default `fn clone_from` from `trait Clone`.
-                    let substs = tcx.erase_regions(rcvr_substs);
-                    Some(ty::Instance::new(trait_item_id, substs))
+                    let args = tcx.erase_regions(rcvr_args);
+                    Some(ty::Instance::new(trait_item_id, args))
                 }
             } else if Some(trait_ref.def_id) == lang_items.fn_ptr_trait() {
                 if lang_items.fn_ptr_addr() == Some(trait_item_id) {
@@ -222,7 +219,7 @@ fn resolve_associated_item<'tcx>(
                     }
                     Some(Instance {
                         def: ty::InstanceDef::FnPtrAddrShim(trait_item_id, self_ty),
-                        substs: rcvr_substs,
+                        args: rcvr_args,
                     })
                 } else {
                     tcx.sess.emit_fatal(UnexpectedFnPtrAssociatedItem {
@@ -230,20 +227,20 @@ fn resolve_associated_item<'tcx>(
                     })
                 }
             } else if Some(trait_ref.def_id) == lang_items.future_trait() {
-                let ty::Generator(generator_def_id, substs, _) = *rcvr_substs.type_at(0).kind() else {
+                let ty::Generator(generator_def_id, args, _) = *rcvr_args.type_at(0).kind() else {
                     bug!()
                 };
                 if Some(trait_item_id) == tcx.lang_items().future_poll_fn() {
                     // `Future::poll` is generated by the compiler.
-                    Some(Instance { def: ty::InstanceDef::Item(generator_def_id), substs: substs })
+                    Some(Instance { def: ty::InstanceDef::Item(generator_def_id), args: args })
                 } else {
                     // All other methods are default methods of the `Future` trait.
                     // (this assumes that `ImplSource::Builtin` is only used for methods on `Future`)
                     debug_assert!(tcx.defaultness(trait_item_id).has_value());
-                    Some(Instance::new(trait_item_id, rcvr_substs))
+                    Some(Instance::new(trait_item_id, rcvr_args))
                 }
             } else if Some(trait_ref.def_id) == lang_items.gen_trait() {
-                let ty::Generator(generator_def_id, substs, _) = *rcvr_substs.type_at(0).kind() else {
+                let ty::Generator(generator_def_id, args, _) = *rcvr_args.type_at(0).kind() else {
                     bug!()
                 };
                 if cfg!(debug_assertions) && tcx.item_name(trait_item_id) != sym::resume {
@@ -257,7 +254,7 @@ fn resolve_associated_item<'tcx>(
                         tcx.item_name(trait_item_id)
                     )
                 }
-                Some(Instance { def: ty::InstanceDef::Item(generator_def_id), substs })
+                Some(Instance { def: ty::InstanceDef::Item(generator_def_id), args })
             } else if tcx.fn_trait_kind_from_def_id(trait_ref.def_id).is_some() {
                 // FIXME: This doesn't check for malformed libcore that defines, e.g.,
                 // `trait Fn { fn call_once(&self) { .. } }`. This is mostly for extension
@@ -275,14 +272,14 @@ fn resolve_associated_item<'tcx>(
                         tcx.item_name(trait_item_id)
                     )
                 }
-                match *rcvr_substs.type_at(0).kind() {
-                    ty::Closure(closure_def_id, substs) => {
+                match *rcvr_args.type_at(0).kind() {
+                    ty::Closure(closure_def_id, args) => {
                         let trait_closure_kind = tcx.fn_trait_kind_from_def_id(trait_id).unwrap();
-                        Instance::resolve_closure(tcx, closure_def_id, substs, trait_closure_kind)
+                        Instance::resolve_closure(tcx, closure_def_id, args, trait_closure_kind)
                     }
                     ty::FnDef(..) | ty::FnPtr(..) => Some(Instance {
-                        def: ty::InstanceDef::FnPtrShim(trait_item_id, rcvr_substs.type_at(0)),
-                        substs: rcvr_substs,
+                        def: ty::InstanceDef::FnPtrShim(trait_item_id, rcvr_args.type_at(0)),
+                        args: rcvr_args,
                     }),
                     _ => bug!(
                         "no built-in definition for `{trait_ref}::{}` for non-fn type",
diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs
index b67cd96a734..b840ff184e0 100644
--- a/compiler/rustc_ty_utils/src/layout.rs
+++ b/compiler/rustc_ty_utils/src/layout.rs
@@ -8,7 +8,7 @@ use rustc_middle::ty::layout::{
     IntegerExt, LayoutCx, LayoutError, LayoutOf, TyAndLayout, MAX_SIMD_LANES,
 };
 use rustc_middle::ty::{
-    self, subst::SubstsRef, AdtDef, EarlyBinder, ReprOptions, Ty, TyCtxt, TypeVisitableExt,
+    self, AdtDef, EarlyBinder, GenericArgsRef, ReprOptions, Ty, TyCtxt, TypeVisitableExt,
 };
 use rustc_session::{DataTypeKind, FieldInfo, FieldKind, SizeKind, VariantInfo};
 use rustc_span::symbol::Symbol;
@@ -258,6 +258,8 @@ fn layout_of_uncached<'tcx>(
                 largest_niche,
                 align: element.align,
                 size,
+                max_repr_align: None,
+                unadjusted_abi_align: element.align.abi,
             })
         }
         ty::Slice(element) => {
@@ -269,6 +271,8 @@ fn layout_of_uncached<'tcx>(
                 largest_niche: None,
                 align: element.align,
                 size: Size::ZERO,
+                max_repr_align: None,
+                unadjusted_abi_align: element.align.abi,
             })
         }
         ty::Str => tcx.mk_layout(LayoutS {
@@ -278,6 +282,8 @@ fn layout_of_uncached<'tcx>(
             largest_niche: None,
             align: dl.i8_align,
             size: Size::ZERO,
+            max_repr_align: None,
+            unadjusted_abi_align: dl.i8_align.abi,
         }),
 
         // Odd unit types.
@@ -299,10 +305,10 @@ fn layout_of_uncached<'tcx>(
             tcx.mk_layout(unit)
         }
 
-        ty::Generator(def_id, substs, _) => generator_layout(cx, ty, def_id, substs)?,
+        ty::Generator(def_id, args, _) => generator_layout(cx, ty, def_id, args)?,
 
-        ty::Closure(_, ref substs) => {
-            let tys = substs.as_closure().upvar_tys();
+        ty::Closure(_, ref args) => {
+            let tys = args.as_closure().upvar_tys();
             univariant(
                 &tys.map(|ty| Ok(cx.layout_of(ty)?.layout)).try_collect::<IndexVec<_, _>>()?,
                 &ReprOptions::default(),
@@ -322,7 +328,7 @@ fn layout_of_uncached<'tcx>(
         }
 
         // SIMD vector types.
-        ty::Adt(def, substs) if def.repr().simd() => {
+        ty::Adt(def, args) if def.repr().simd() => {
             if !def.is_struct() {
                 // Should have yielded E0517 by now.
                 tcx.sess.delay_span_bug(
@@ -349,12 +355,12 @@ fn layout_of_uncached<'tcx>(
             }
 
             // Type of the first ADT field:
-            let f0_ty = fields[FieldIdx::from_u32(0)].ty(tcx, substs);
+            let f0_ty = fields[FieldIdx::from_u32(0)].ty(tcx, args);
 
             // Heterogeneous SIMD vectors are not supported:
             // (should be caught by typeck)
             for fi in fields {
-                if fi.ty(tcx, substs) != f0_ty {
+                if fi.ty(tcx, args) != f0_ty {
                     tcx.sess.delay_span_bug(
                         DUMMY_SP,
                         "#[repr(simd)] was applied to an ADT with heterogeneous field type",
@@ -431,11 +437,13 @@ fn layout_of_uncached<'tcx>(
                 largest_niche: e_ly.largest_niche,
                 size,
                 align,
+                max_repr_align: None,
+                unadjusted_abi_align: align.abi,
             })
         }
 
         // ADTs.
-        ty::Adt(def, substs) => {
+        ty::Adt(def, args) => {
             // Cache the field layouts.
             let variants = def
                 .variants()
@@ -443,7 +451,7 @@ fn layout_of_uncached<'tcx>(
                 .map(|v| {
                     v.fields
                         .iter()
-                        .map(|field| Ok(cx.layout_of(field.ty(tcx, substs))?.layout))
+                        .map(|field| Ok(cx.layout_of(field.ty(tcx, args))?.layout))
                         .try_collect::<IndexVec<_, _>>()
                 })
                 .try_collect::<IndexVec<VariantIdx, _>>()?;
@@ -482,7 +490,7 @@ fn layout_of_uncached<'tcx>(
             let maybe_unsized = def.is_struct()
                 && def.non_enum_variant().tail_opt().is_some_and(|last_field| {
                     let param_env = tcx.param_env(def.did());
-                    !tcx.type_of(last_field.did).subst_identity().is_sized(tcx, param_env)
+                    !tcx.type_of(last_field.did).instantiate_identity().is_sized(tcx, param_env)
                 });
 
             let Some(layout) = cx.layout_of_struct_or_enum(
@@ -502,7 +510,7 @@ fn layout_of_uncached<'tcx>(
             // If the struct tail is sized and can be unsized, check that unsizing doesn't move the fields around.
             if cfg!(debug_assertions)
                 && maybe_unsized
-                && def.non_enum_variant().tail().ty(tcx, substs).is_sized(tcx, cx.param_env)
+                && def.non_enum_variant().tail().ty(tcx, args).is_sized(tcx, cx.param_env)
             {
                 let mut variants = variants;
                 let tail_replacement = cx.layout_of(Ty::new_slice(tcx, tcx.types.u8)).unwrap();
@@ -525,8 +533,13 @@ fn layout_of_uncached<'tcx>(
                 let FieldsShape::Arbitrary { offsets: sized_offsets, .. } = &layout.fields else {
                     bug!("unexpected FieldsShape for sized layout of {ty:?}: {:?}", layout.fields);
                 };
-                let FieldsShape::Arbitrary { offsets: unsized_offsets, .. } = &unsized_layout.fields else {
-                    bug!("unexpected FieldsShape for unsized layout of {ty:?}: {:?}", unsized_layout.fields);
+                let FieldsShape::Arbitrary { offsets: unsized_offsets, .. } =
+                    &unsized_layout.fields
+                else {
+                    bug!(
+                        "unexpected FieldsShape for unsized layout of {ty:?}: {:?}",
+                        unsized_layout.fields
+                    );
                 };
 
                 let (sized_tail, sized_fields) = sized_offsets.raw.split_last().unwrap();
@@ -691,11 +704,11 @@ fn generator_layout<'tcx>(
     cx: &LayoutCx<'tcx, TyCtxt<'tcx>>,
     ty: Ty<'tcx>,
     def_id: hir::def_id::DefId,
-    substs: SubstsRef<'tcx>,
+    args: GenericArgsRef<'tcx>,
 ) -> Result<Layout<'tcx>, &'tcx LayoutError<'tcx>> {
     use SavedLocalEligibility::*;
     let tcx = cx.tcx;
-    let subst_field = |ty: Ty<'tcx>| EarlyBinder::bind(ty).subst(tcx, substs);
+    let subst_field = |ty: Ty<'tcx>| EarlyBinder::bind(ty).instantiate(tcx, args);
 
     let Some(info) = tcx.generator_layout(def_id) else {
         return Err(error(cx, LayoutError::Unknown(ty)));
@@ -705,7 +718,7 @@ fn generator_layout<'tcx>(
     // Build a prefix layout, including "promoting" all ineligible
     // locals as part of the prefix. We compute the layout of all of
     // these fields at once to get optimal packing.
-    let tag_index = substs.as_generator().prefix_tys().count();
+    let tag_index = args.as_generator().prefix_tys().count();
 
     // `info.variant_fields` already accounts for the reserved variants, so no need to add them.
     let max_discr = (info.variant_fields.len() - 1) as u128;
@@ -721,7 +734,7 @@ fn generator_layout<'tcx>(
         .map(|local| subst_field(info.field_tys[local].ty))
         .map(|ty| Ty::new_maybe_uninit(tcx, ty))
         .map(|ty| Ok(cx.layout_of(ty)?.layout));
-    let prefix_layouts = substs
+    let prefix_layouts = args
         .as_generator()
         .prefix_tys()
         .map(|ty| Ok(cx.layout_of(ty)?.layout))
@@ -879,6 +892,8 @@ fn generator_layout<'tcx>(
         largest_niche: prefix.largest_niche,
         size,
         align,
+        max_repr_align: None,
+        unadjusted_abi_align: align.abi,
     });
     debug!("generator layout ({:?}): {:#?}", ty, layout);
     Ok(layout)
@@ -929,11 +944,11 @@ fn record_layout_for_printing_outlined<'tcx>(
             record(adt_kind.into(), adt_packed, opt_discr_size, variant_infos);
         }
 
-        ty::Generator(def_id, substs, _) => {
+        ty::Generator(def_id, args, _) => {
             debug!("print-type-size t: `{:?}` record generator", layout.ty);
             // Generators always have a begin/poisoned/end state with additional suspend points
             let (variant_infos, opt_discr_size) =
-                variant_info_for_generator(cx, layout, def_id, substs);
+                variant_info_for_generator(cx, layout, def_id, args);
             record(DataTypeKind::Generator, false, opt_discr_size, variant_infos);
         }
 
@@ -1023,7 +1038,7 @@ fn variant_info_for_generator<'tcx>(
     cx: &LayoutCx<'tcx, TyCtxt<'tcx>>,
     layout: TyAndLayout<'tcx>,
     def_id: DefId,
-    substs: ty::SubstsRef<'tcx>,
+    args: ty::GenericArgsRef<'tcx>,
 ) -> (Vec<VariantInfo>, Option<Size>) {
     let Variants::Multiple { tag, ref tag_encoding, tag_field, .. } = layout.variants else {
         return (vec![], None);
@@ -1033,7 +1048,7 @@ fn variant_info_for_generator<'tcx>(
     let upvar_names = cx.tcx.closure_saved_names_of_captured_variables(def_id);
 
     let mut upvars_size = Size::ZERO;
-    let upvar_fields: Vec<_> = substs
+    let upvar_fields: Vec<_> = args
         .as_generator()
         .upvar_tys()
         .zip(upvar_names)
@@ -1108,7 +1123,7 @@ fn variant_info_for_generator<'tcx>(
             }
 
             VariantInfo {
-                name: Some(Symbol::intern(&ty::GeneratorSubsts::variant_name(variant_idx))),
+                name: Some(Symbol::intern(&ty::GeneratorArgs::variant_name(variant_idx))),
                 kind: SizeKind::Exact,
                 size: variant_size.bytes(),
                 align: variant_layout.align.abi.bytes(),
diff --git a/compiler/rustc_ty_utils/src/layout_sanity_check.rs b/compiler/rustc_ty_utils/src/layout_sanity_check.rs
index c4a4cda6801..8633334381a 100644
--- a/compiler/rustc_ty_utils/src/layout_sanity_check.rs
+++ b/compiler/rustc_ty_utils/src/layout_sanity_check.rs
@@ -52,7 +52,7 @@ pub(super) fn sanity_check_layout<'tcx>(
         let mut fields = non_zst_fields(cx, layout);
         let Some(first) = fields.next() else {
             // No fields here, so this could be a primitive or enum -- either way it's not a newtype around a thing
-            return *layout
+            return *layout;
         };
         if fields.next().is_none() {
             let (offset, first) = first;
@@ -77,7 +77,7 @@ pub(super) fn sanity_check_layout<'tcx>(
                 Abi::Uninhabited | Abi::Aggregate { .. },
                 "ABI unexpectedly missing alignment and/or size in {layout:#?}"
             );
-            return
+            return;
         };
         assert_eq!(
             layout.layout.align().abi,
diff --git a/compiler/rustc_ty_utils/src/needs_drop.rs b/compiler/rustc_ty_utils/src/needs_drop.rs
index 9d593dc5e04..3e6dfc1304f 100644
--- a/compiler/rustc_ty_utils/src/needs_drop.rs
+++ b/compiler/rustc_ty_utils/src/needs_drop.rs
@@ -3,8 +3,8 @@
 use rustc_data_structures::fx::FxHashSet;
 use rustc_hir::def_id::DefId;
 use rustc_middle::query::Providers;
-use rustc_middle::ty::subst::SubstsRef;
 use rustc_middle::ty::util::{needs_drop_components, AlwaysRequiresDrop};
+use rustc_middle::ty::GenericArgsRef;
 use rustc_middle::ty::{self, EarlyBinder, Ty, TyCtxt};
 use rustc_session::Limit;
 use rustc_span::{sym, DUMMY_SP};
@@ -80,7 +80,7 @@ impl<'tcx, F> NeedsDropTypes<'tcx, F> {
 
 impl<'tcx, F, I> Iterator for NeedsDropTypes<'tcx, F>
 where
-    F: Fn(ty::AdtDef<'tcx>, SubstsRef<'tcx>) -> NeedsDropResult<I>,
+    F: Fn(ty::AdtDef<'tcx>, GenericArgsRef<'tcx>) -> NeedsDropResult<I>,
     I: Iterator<Item = Ty<'tcx>>,
 {
     type Item = NeedsDropResult<Ty<'tcx>>;
@@ -119,15 +119,15 @@ where
 
                     _ if component.is_copy_modulo_regions(tcx, self.param_env) => (),
 
-                    ty::Closure(_, substs) => {
-                        queue_type(self, substs.as_closure().tupled_upvars_ty());
+                    ty::Closure(_, args) => {
+                        queue_type(self, args.as_closure().tupled_upvars_ty());
                     }
 
-                    ty::Generator(def_id, substs, _) => {
-                        let substs = substs.as_generator();
-                        queue_type(self, substs.tupled_upvars_ty());
+                    ty::Generator(def_id, args, _) => {
+                        let args = args.as_generator();
+                        queue_type(self, args.tupled_upvars_ty());
 
-                        let witness = substs.witness();
+                        let witness = args.witness();
                         let interior_tys = match witness.kind() {
                             &ty::GeneratorWitness(tys) => tcx.erase_late_bound_regions(tys),
                             _ => {
@@ -147,8 +147,8 @@ where
                     // Check for a `Drop` impl and whether this is a union or
                     // `ManuallyDrop`. If it's a struct or enum without a `Drop`
                     // impl then check whether the field types need `Drop`.
-                    ty::Adt(adt_def, substs) => {
-                        let tys = match (self.adt_components)(adt_def, substs) {
+                    ty::Adt(adt_def, args) => {
+                        let tys = match (self.adt_components)(adt_def, args) {
                             Err(e) => return Some(Err(e)),
                             Ok(tys) => tys,
                         };
@@ -210,7 +210,7 @@ fn drop_tys_helper<'tcx>(
             match subty.kind() {
                 ty::Adt(adt_id, subst) => {
                     for subty in tcx.adt_drop_tys(adt_id.did())? {
-                        vec.push(EarlyBinder::bind(subty).subst(tcx, subst));
+                        vec.push(EarlyBinder::bind(subty).instantiate(tcx, subst));
                     }
                 }
                 _ => vec.push(subty),
@@ -219,7 +219,7 @@ fn drop_tys_helper<'tcx>(
         })
     }
 
-    let adt_components = move |adt_def: ty::AdtDef<'tcx>, substs: SubstsRef<'tcx>| {
+    let adt_components = move |adt_def: ty::AdtDef<'tcx>, args: GenericArgsRef<'tcx>| {
         if adt_def.is_manually_drop() {
             debug!("drop_tys_helper: `{:?}` is manually drop", adt_def);
             Ok(Vec::new())
@@ -235,7 +235,7 @@ fn drop_tys_helper<'tcx>(
                     // Since the destructor is insignificant, we just want to make sure all of
                     // the passed in type parameters are also insignificant.
                     // Eg: Vec<T> dtor is insignificant when T=i32 but significant when T=Mutex.
-                    Ok(substs.types().collect())
+                    Ok(args.types().collect())
                 }
             }
         } else if adt_def.is_union() {
@@ -243,8 +243,8 @@ fn drop_tys_helper<'tcx>(
             Ok(Vec::new())
         } else {
             let field_tys = adt_def.all_fields().map(|field| {
-                let r = tcx.type_of(field.did).subst(tcx, substs);
-                debug!("drop_tys_helper: Subst into {:?} with {:?} getting {:?}", field, substs, r);
+                let r = tcx.type_of(field.did).instantiate(tcx, args);
+                debug!("drop_tys_helper: Subst into {:?} with {:?} getting {:?}", field, args, r);
                 r
             });
             if only_significant {
@@ -295,10 +295,10 @@ fn adt_drop_tys<'tcx>(
     // significant.
     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)`
+    // `tcx.type_of(def_id)` identical to `tcx.make_adt(def, identity_args)`
     drop_tys_helper(
         tcx,
-        tcx.type_of(def_id).subst_identity(),
+        tcx.type_of(def_id).instantiate_identity(),
         tcx.param_env(def_id),
         adt_has_dtor,
         false,
@@ -307,7 +307,7 @@ fn adt_drop_tys<'tcx>(
     .map(|components| tcx.mk_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
+// a `tcx.make_ty(def, identity_args)` and as such it is legal to substitute the generic parameters
 // of the ADT into the outputted `ty`s.
 fn adt_significant_drop_tys(
     tcx: TyCtxt<'_>,
@@ -315,7 +315,7 @@ fn adt_significant_drop_tys(
 ) -> Result<&ty::List<Ty<'_>>, AlwaysRequiresDrop> {
     drop_tys_helper(
         tcx,
-        tcx.type_of(def_id).subst_identity(), // identical to `tcx.make_adt(def, identity_substs)`
+        tcx.type_of(def_id).instantiate_identity(), // identical to `tcx.make_adt(def, identity_args)`
         tcx.param_env(def_id),
         adt_consider_insignificant_dtor(tcx),
         true,
diff --git a/compiler/rustc_ty_utils/src/opaque_types.rs b/compiler/rustc_ty_utils/src/opaque_types.rs
index 87dfacc4c2d..06a30677d20 100644
--- a/compiler/rustc_ty_utils/src/opaque_types.rs
+++ b/compiler/rustc_ty_utils/src/opaque_types.rs
@@ -7,7 +7,7 @@ use rustc_middle::ty::util::{CheckRegions, NotUniqueParam};
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_middle::ty::{TypeSuperVisitable, TypeVisitable, TypeVisitor};
 use rustc_span::Span;
-use rustc_trait_selection::traits::check_substs_compatible;
+use rustc_trait_selection::traits::check_args_compatible;
 use std::ops::ControlFlow;
 
 use crate::errors::{DuplicateArg, NotParam};
@@ -45,7 +45,7 @@ impl<'tcx> OpaqueTypeCollector<'tcx> {
     fn parent_trait_ref(&self) -> Option<ty::TraitRef<'tcx>> {
         let parent = self.parent()?;
         if matches!(self.tcx.def_kind(parent), DefKind::Impl { .. }) {
-            Some(self.tcx.impl_trait_ref(parent)?.subst_identity())
+            Some(self.tcx.impl_trait_ref(parent)?.instantiate_identity())
         } else {
             None
         }
@@ -159,19 +159,19 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeCollector<'tcx> {
 
                 self.opaques.push(alias_ty.def_id.expect_local());
 
-                match self.tcx.uses_unique_generic_params(alias_ty.substs, CheckRegions::Bound) {
+                match self.tcx.uses_unique_generic_params(alias_ty.args, CheckRegions::Bound) {
                     Ok(()) => {
                         // FIXME: implement higher kinded lifetime bounds on nested opaque types. They are not
                         // supported at all, so this is sound to do, but once we want to support them, you'll
                         // start seeing the error below.
 
                         // Collect opaque types nested within the associated type bounds of this opaque type.
-                        // We use identity substs here, because we already know that the opaque type uses
+                        // We use identity args here, because we already know that the opaque type uses
                         // only generic parameters, and thus substituting would not give us more information.
                         for (pred, span) in self
                             .tcx
                             .explicit_item_bounds(alias_ty.def_id)
-                            .subst_identity_iter_copied()
+                            .instantiate_identity_iter_copied()
                         {
                             trace!(?pred);
                             self.visit_spanned(span, pred);
@@ -196,7 +196,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeCollector<'tcx> {
             ty::Alias(ty::Weak, alias_ty) if alias_ty.def_id.is_local() => {
                 self.tcx
                     .type_of(alias_ty.def_id)
-                    .subst(self.tcx, alias_ty.substs)
+                    .instantiate(self.tcx, alias_ty.args)
                     .visit_with(self)?;
             }
             ty::Alias(ty::Projection, alias_ty) => {
@@ -222,22 +222,22 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeCollector<'tcx> {
                                 continue;
                             }
 
-                            let impl_substs = alias_ty.substs.rebase_onto(
+                            let impl_args = alias_ty.args.rebase_onto(
                                 self.tcx,
                                 parent_trait_ref.def_id,
-                                ty::InternalSubsts::identity_for_item(self.tcx, parent),
+                                ty::GenericArgs::identity_for_item(self.tcx, parent),
                             );
 
-                            if check_substs_compatible(self.tcx, assoc, impl_substs) {
+                            if check_args_compatible(self.tcx, assoc, impl_args) {
                                 return self
                                     .tcx
                                     .type_of(assoc.def_id)
-                                    .subst(self.tcx, impl_substs)
+                                    .instantiate(self.tcx, impl_args)
                                     .visit_with(self);
                             } else {
                                 self.tcx.sess.delay_span_bug(
                                     self.tcx.def_span(assoc.def_id),
-                                    "item had incorrect substs",
+                                    "item had incorrect args",
                                 );
                             }
                         }
@@ -250,15 +250,15 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeCollector<'tcx> {
                 }
                 for variant in def.variants().iter() {
                     for field in variant.fields.iter() {
-                        // Don't use the `ty::Adt` substs, we either
-                        // * found the opaque in the substs
+                        // Don't use the `ty::Adt` args, we either
+                        // * found the opaque in the args
                         // * will find the opaque in the unsubstituted fields
                         // The only other situation that can occur is that after substituting,
                         // some projection resolves to an opaque that we would have otherwise
                         // not found. While we could substitute and walk those, that would mean we
                         // would have to walk all substitutions of an Adt, which can quickly
                         // degenerate into looking at an exponential number of types.
-                        let ty = self.tcx.type_of(field.did).subst_identity();
+                        let ty = self.tcx.type_of(field.did).instantiate_identity();
                         self.visit_spanned(self.tcx.def_span(field.did), ty);
                     }
                 }
@@ -276,7 +276,7 @@ fn opaque_types_defined_by<'tcx>(tcx: TyCtxt<'tcx>, item: LocalDefId) -> &'tcx [
     match kind {
         // Walk over the signature of the function-like to find the opaques.
         DefKind::AssocFn | DefKind::Fn => {
-            let ty_sig = tcx.fn_sig(item).subst_identity();
+            let ty_sig = tcx.fn_sig(item).instantiate_identity();
             let hir_sig = tcx.hir().get_by_def_id(item).fn_sig().unwrap();
             // Walk over the inputs and outputs manually in order to get good spans for them.
             collector.visit_spanned(hir_sig.decl.output.span(), ty_sig.output());
@@ -291,15 +291,15 @@ fn opaque_types_defined_by<'tcx>(tcx: TyCtxt<'tcx>, item: LocalDefId) -> &'tcx [
                 Some(ty) => ty.span,
                 _ => tcx.def_span(item),
             };
-            collector.visit_spanned(span, tcx.type_of(item).subst_identity());
+            collector.visit_spanned(span, tcx.type_of(item).instantiate_identity());
             collector.collect_body_and_predicate_taits();
         }
         // We're also doing this for `AssocTy` for the wf checks in `check_opaque_meets_bounds`
         DefKind::TyAlias | DefKind::AssocTy => {
-            tcx.type_of(item).subst_identity().visit_with(&mut collector);
+            tcx.type_of(item).instantiate_identity().visit_with(&mut collector);
         }
         DefKind::OpaqueTy => {
-            for (pred, span) in tcx.explicit_item_bounds(item).subst_identity_iter_copied() {
+            for (pred, span) in tcx.explicit_item_bounds(item).instantiate_identity_iter_copied() {
                 collector.visit_spanned(span, pred);
             }
         }
diff --git a/compiler/rustc_ty_utils/src/representability.rs b/compiler/rustc_ty_utils/src/representability.rs
index 0b5e27c2c74..f34e0df2c75 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).subst_identity()),
+        DefKind::Field => representability_ty(tcx, tcx.type_of(def_id).instantiate_identity()),
         def_kind => bug!("unexpected {def_kind:?}"),
     }
 }
@@ -68,14 +68,14 @@ representability_adt_ty(Bar<..>) is in the cycle and representability(Bar) is
 *not* in the cycle.
 */
 fn representability_adt_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Representability {
-    let ty::Adt(adt, substs) = ty.kind() else { bug!("expected adt") };
+    let ty::Adt(adt, args) = ty.kind() else { bug!("expected adt") };
     if let Some(def_id) = adt.did().as_local() {
         rtry!(tcx.representability(def_id));
     }
     // At this point, we know that the item of the ADT type is representable;
     // but the type parameters may cause a cycle with an upstream type
     let params_in_repr = tcx.params_in_repr(adt.did());
-    for (i, subst) in substs.iter().enumerate() {
+    for (i, subst) in args.iter().enumerate() {
         if let ty::GenericArgKind::Type(ty) = subst.unpack() {
             if params_in_repr.contains(i as u32) {
                 rtry!(representability_ty(tcx, ty));
@@ -91,7 +91,11 @@ fn params_in_repr(tcx: TyCtxt<'_>, def_id: LocalDefId) -> 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).subst_identity(), &mut params_in_repr);
+            params_in_repr_ty(
+                tcx,
+                tcx.type_of(field.did).instantiate_identity(),
+                &mut params_in_repr,
+            );
         }
     }
     params_in_repr
@@ -99,9 +103,9 @@ fn params_in_repr(tcx: TyCtxt<'_>, def_id: LocalDefId) -> BitSet<u32> {
 
 fn params_in_repr_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, params_in_repr: &mut BitSet<u32>) {
     match *ty.kind() {
-        ty::Adt(adt, substs) => {
+        ty::Adt(adt, args) => {
             let inner_params_in_repr = tcx.params_in_repr(adt.did());
-            for (i, subst) in substs.iter().enumerate() {
+            for (i, subst) in args.iter().enumerate() {
                 if let ty::GenericArgKind::Type(ty) = subst.unpack() {
                     if inner_params_in_repr.contains(i as u32) {
                         params_in_repr_ty(tcx, ty, params_in_repr);
diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs
index 43e3c99fb57..c228938126e 100644
--- a/compiler/rustc_ty_utils/src/ty.rs
+++ b/compiler/rustc_ty_utils/src/ty.rs
@@ -37,12 +37,12 @@ fn sized_constraint_for_ty<'tcx>(
             Some(&ty) => sized_constraint_for_ty(tcx, adtdef, ty),
         },
 
-        Adt(adt, substs) => {
+        Adt(adt, args) => {
             // recursive case
             let adt_tys = adt.sized_constraint(tcx);
             debug!("sized_constraint_for_ty({:?}) intermediate = {:?}", ty, adt_tys);
             adt_tys
-                .subst_iter_copied(tcx, substs)
+                .arg_iter_copied(tcx, args)
                 .flat_map(|ty| sized_constraint_for_ty(tcx, adtdef, ty))
                 .collect()
         }
@@ -100,12 +100,10 @@ fn adt_sized_constraint(tcx: TyCtxt<'_>, def_id: DefId) -> &[Ty<'_>] {
     }
     let def = tcx.adt_def(def_id);
 
-    let result = tcx.mk_type_list_from_iter(
-        def.variants()
-            .iter()
-            .filter_map(|v| v.tail_opt())
-            .flat_map(|f| sized_constraint_for_ty(tcx, def, tcx.type_of(f.did).subst_identity())),
-    );
+    let result =
+        tcx.mk_type_list_from_iter(def.variants().iter().filter_map(|v| v.tail_opt()).flat_map(
+            |f| sized_constraint_for_ty(tcx, def, tcx.type_of(f.did).instantiate_identity()),
+        ));
 
     debug!("adt_sized_constraint: {:?} => {:?}", def, result);
 
@@ -133,7 +131,7 @@ fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> {
     if tcx.def_kind(def_id) == DefKind::AssocFn
         && tcx.associated_item(def_id).container == ty::AssocItemContainer::TraitContainer
     {
-        let sig = tcx.fn_sig(def_id).subst_identity();
+        let sig = tcx.fn_sig(def_id).instantiate_identity();
         // We accounted for the binder of the fn sig, so skip the binder.
         sig.skip_binder().visit_with(&mut ImplTraitInTraitFinder {
             tcx,
@@ -282,7 +280,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ImplTraitInTraitFinder<'_, 'tcx> {
             // If we're lowering to associated item, install the opaque type which is just
             // the `type_of` of the trait's associated item. If we're using the old lowering
             // strategy, then just reinterpret the associated type like an opaque :^)
-            let default_ty = self.tcx.type_of(shifted_alias_ty.def_id).subst(self.tcx, shifted_alias_ty.substs);
+            let default_ty = self.tcx.type_of(shifted_alias_ty.def_id).instantiate(self.tcx, shifted_alias_ty.args);
 
             self.predicates.push(
                 ty::Binder::bind_with_vars(
@@ -299,7 +297,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ImplTraitInTraitFinder<'_, 'tcx> {
             for bound in self
                 .tcx
                 .item_bounds(unshifted_alias_ty.def_id)
-                .subst_iter(self.tcx, unshifted_alias_ty.substs)
+                .arg_iter(self.tcx, unshifted_alias_ty.args)
             {
                 bound.visit_with(self);
             }
@@ -352,8 +350,8 @@ fn issue33140_self_ty(tcx: TyCtxt<'_>, def_id: DefId) -> Option<EarlyBinder<Ty<'
     }
 
     // impl must be `impl Trait for dyn Marker1 + Marker2 + ...`
-    if trait_ref.substs.len() != 1 {
-        debug!("issue33140_self_ty - impl has substs!");
+    if trait_ref.args.len() != 1 {
+        debug!("issue33140_self_ty - impl has args!");
         return None;
     }
 
@@ -409,7 +407,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.type_of(tail_field.did).subst_identity().walk() {
+    for arg in tcx.type_of(tail_field.did).instantiate_identity().walk() {
         if let Some(i) = maybe_unsizing_param_idx(arg) {
             unsizing_params.insert(i);
         }
@@ -418,7 +416,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.type_of(field.did).subst_identity().walk() {
+        for arg in tcx.type_of(field.did).instantiate_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 9ca26d18ae1..a7cd7aa2c4f 100644
--- a/compiler/rustc_type_ir/src/lib.rs
+++ b/compiler/rustc_type_ir/src/lib.rs
@@ -40,7 +40,7 @@ pub trait HashStableContext {}
 
 pub trait Interner: Sized {
     type AdtDef: Clone + Debug + Hash + Ord;
-    type SubstsRef: Clone + DebugWithInfcx<Self> + Hash + Ord;
+    type GenericArgsRef: Clone + DebugWithInfcx<Self> + Hash + Ord;
     type DefId: Clone + Debug + Hash + Ord;
     type Binder<T>;
     type Ty: Clone + DebugWithInfcx<Self> + Hash + Ord;
diff --git a/compiler/rustc_type_ir/src/sty.rs b/compiler/rustc_type_ir/src/sty.rs
index 416e8a3d2d2..b134845dab0 100644
--- a/compiler/rustc_type_ir/src/sty.rs
+++ b/compiler/rustc_type_ir/src/sty.rs
@@ -74,11 +74,11 @@ pub enum TyKind<I: Interner> {
     /// Algebraic data types (ADT). For example: structures, enumerations and unions.
     ///
     /// For example, the type `List<i32>` would be represented using the `AdtDef`
-    /// for `struct List<T>` and the substs `[i32]`.
+    /// for `struct List<T>` and the args `[i32]`.
     ///
     /// Note that generic parameters in fields only get lazily substituted
-    /// by using something like `adt_def.all_fields().map(|field| field.ty(tcx, substs))`.
-    Adt(I::AdtDef, I::SubstsRef),
+    /// by using something like `adt_def.all_fields().map(|field| field.ty(tcx, args))`.
+    Adt(I::AdtDef, I::GenericArgsRef),
 
     /// An unsized FFI type that is opaque to Rust. Written as `extern type T`.
     Foreign(I::DefId),
@@ -110,7 +110,7 @@ pub enum TyKind<I: Interner> {
     /// fn foo() -> i32 { 1 }
     /// let bar = foo; // bar: fn() -> i32 {foo}
     /// ```
-    FnDef(I::DefId, I::SubstsRef),
+    FnDef(I::DefId, I::GenericArgsRef),
 
     /// A pointer to a function. Written as `fn() -> i32`.
     ///
@@ -130,20 +130,20 @@ pub enum TyKind<I: Interner> {
 
     /// The anonymous type of a closure. Used to represent the type of `|a| a`.
     ///
-    /// Closure substs contain both the - potentially substituted - generic parameters
+    /// Closure args contain both the - potentially substituted - generic parameters
     /// of its parent and some synthetic parameters. See the documentation for
-    /// `ClosureSubsts` for more details.
-    Closure(I::DefId, I::SubstsRef),
+    /// `ClosureArgs` for more details.
+    Closure(I::DefId, I::GenericArgsRef),
 
     /// The anonymous type of a generator. Used to represent the type of
     /// `|a| yield a`.
     ///
-    /// For more info about generator substs, visit the documentation for
-    /// `GeneratorSubsts`.
-    Generator(I::DefId, I::SubstsRef, I::Movability),
+    /// For more info about generator args, visit the documentation for
+    /// `GeneratorArgs`.
+    Generator(I::DefId, I::GenericArgsRef, I::Movability),
 
     /// A type representing the types stored inside a generator.
-    /// This should only appear as part of the `GeneratorSubsts`.
+    /// This should only appear as part of the `GeneratorArgs`.
     ///
     /// Note that the captured variables for generators are stored separately
     /// using a tuple in the same way as for closures.
@@ -168,7 +168,7 @@ pub enum TyKind<I: Interner> {
     GeneratorWitness(I::BinderListTy),
 
     /// A type representing the types stored inside a generator.
-    /// This should only appear as part of the `GeneratorSubsts`.
+    /// This should only appear as part of the `GeneratorArgs`.
     ///
     /// Unlike upvars, the witness can reference lifetimes from
     /// inside of the generator itself. To deal with them in
@@ -176,7 +176,7 @@ pub enum TyKind<I: Interner> {
     /// lifetimes bound by the witness itself.
     ///
     /// This variant is only using when `drop_tracking_mir` is set.
-    /// This contains the `DefId` and the `SubstsRef` of the generator.
+    /// This contains the `DefId` and the `GenericArgsRef` of the generator.
     /// The actual witness types are computed on MIR by the `mir_generator_witnesses` query.
     ///
     /// Looking at the following example, the witness for this generator
@@ -191,7 +191,7 @@ pub enum TyKind<I: Interner> {
     /// }
     /// # ;
     /// ```
-    GeneratorWitnessMIR(I::DefId, I::SubstsRef),
+    GeneratorWitnessMIR(I::DefId, I::GenericArgsRef),
 
     /// The never type `!`.
     Never,
@@ -587,7 +587,7 @@ impl<I: Interner, E: TyEncoder> Encodable<E> for TyKind<I>
 where
     I::ErrorGuaranteed: Encodable<E>,
     I::AdtDef: Encodable<E>,
-    I::SubstsRef: Encodable<E>,
+    I::GenericArgsRef: Encodable<E>,
     I::DefId: Encodable<E>,
     I::Ty: Encodable<E>,
     I::Const: Encodable<E>,
@@ -621,9 +621,9 @@ where
             Float(f) => e.emit_enum_variant(disc, |e| {
                 f.encode(e);
             }),
-            Adt(adt, substs) => e.emit_enum_variant(disc, |e| {
+            Adt(adt, args) => e.emit_enum_variant(disc, |e| {
                 adt.encode(e);
-                substs.encode(e);
+                args.encode(e);
             }),
             Foreign(def_id) => e.emit_enum_variant(disc, |e| {
                 def_id.encode(e);
@@ -644,9 +644,9 @@ where
                 t.encode(e);
                 m.encode(e);
             }),
-            FnDef(def_id, substs) => e.emit_enum_variant(disc, |e| {
+            FnDef(def_id, args) => e.emit_enum_variant(disc, |e| {
                 def_id.encode(e);
-                substs.encode(e);
+                args.encode(e);
             }),
             FnPtr(polyfnsig) => e.emit_enum_variant(disc, |e| {
                 polyfnsig.encode(e);
@@ -656,25 +656,25 @@ where
                 r.encode(e);
                 repr.encode(e);
             }),
-            Closure(def_id, substs) => e.emit_enum_variant(disc, |e| {
+            Closure(def_id, args) => e.emit_enum_variant(disc, |e| {
                 def_id.encode(e);
-                substs.encode(e);
+                args.encode(e);
             }),
-            Generator(def_id, substs, m) => e.emit_enum_variant(disc, |e| {
+            Generator(def_id, args, m) => e.emit_enum_variant(disc, |e| {
                 def_id.encode(e);
-                substs.encode(e);
+                args.encode(e);
                 m.encode(e);
             }),
             GeneratorWitness(b) => e.emit_enum_variant(disc, |e| {
                 b.encode(e);
             }),
-            GeneratorWitnessMIR(def_id, substs) => e.emit_enum_variant(disc, |e| {
+            GeneratorWitnessMIR(def_id, args) => e.emit_enum_variant(disc, |e| {
                 def_id.encode(e);
-                substs.encode(e);
+                args.encode(e);
             }),
             Never => e.emit_enum_variant(disc, |_| {}),
-            Tuple(substs) => e.emit_enum_variant(disc, |e| {
-                substs.encode(e);
+            Tuple(args) => e.emit_enum_variant(disc, |e| {
+                args.encode(e);
             }),
             Alias(k, p) => e.emit_enum_variant(disc, |e| {
                 k.encode(e);
@@ -705,7 +705,7 @@ impl<I: Interner, D: TyDecoder<I = I>> Decodable<D> for TyKind<I>
 where
     I::ErrorGuaranteed: Decodable<D>,
     I::AdtDef: Decodable<D>,
-    I::SubstsRef: Decodable<D>,
+    I::GenericArgsRef: Decodable<D>,
     I::DefId: Decodable<D>,
     I::Ty: Decodable<D>,
     I::Const: Decodable<D>,
@@ -772,7 +772,7 @@ impl<CTX: HashStableContext, I: Interner> HashStable<CTX> for TyKind<I>
 where
     I::AdtDef: HashStable<CTX>,
     I::DefId: HashStable<CTX>,
-    I::SubstsRef: HashStable<CTX>,
+    I::GenericArgsRef: HashStable<CTX>,
     I::Ty: HashStable<CTX>,
     I::Const: HashStable<CTX>,
     I::TypeAndMut: HashStable<CTX>,
@@ -809,9 +809,9 @@ where
             Float(f) => {
                 f.hash_stable(__hcx, __hasher);
             }
-            Adt(adt, substs) => {
+            Adt(adt, args) => {
                 adt.hash_stable(__hcx, __hasher);
-                substs.hash_stable(__hcx, __hasher);
+                args.hash_stable(__hcx, __hasher);
             }
             Foreign(def_id) => {
                 def_id.hash_stable(__hcx, __hasher);
@@ -832,9 +832,9 @@ where
                 t.hash_stable(__hcx, __hasher);
                 m.hash_stable(__hcx, __hasher);
             }
-            FnDef(def_id, substs) => {
+            FnDef(def_id, args) => {
                 def_id.hash_stable(__hcx, __hasher);
-                substs.hash_stable(__hcx, __hasher);
+                args.hash_stable(__hcx, __hasher);
             }
             FnPtr(polyfnsig) => {
                 polyfnsig.hash_stable(__hcx, __hasher);
@@ -844,25 +844,25 @@ where
                 r.hash_stable(__hcx, __hasher);
                 repr.hash_stable(__hcx, __hasher);
             }
-            Closure(def_id, substs) => {
+            Closure(def_id, args) => {
                 def_id.hash_stable(__hcx, __hasher);
-                substs.hash_stable(__hcx, __hasher);
+                args.hash_stable(__hcx, __hasher);
             }
-            Generator(def_id, substs, m) => {
+            Generator(def_id, args, m) => {
                 def_id.hash_stable(__hcx, __hasher);
-                substs.hash_stable(__hcx, __hasher);
+                args.hash_stable(__hcx, __hasher);
                 m.hash_stable(__hcx, __hasher);
             }
             GeneratorWitness(b) => {
                 b.hash_stable(__hcx, __hasher);
             }
-            GeneratorWitnessMIR(def_id, substs) => {
+            GeneratorWitnessMIR(def_id, args) => {
                 def_id.hash_stable(__hcx, __hasher);
-                substs.hash_stable(__hcx, __hasher);
+                args.hash_stable(__hcx, __hasher);
             }
             Never => {}
-            Tuple(substs) => {
-                substs.hash_stable(__hcx, __hasher);
+            Tuple(args) => {
+                args.hash_stable(__hcx, __hasher);
             }
             Alias(k, p) => {
                 k.hash_stable(__hcx, __hasher);
@@ -1167,7 +1167,7 @@ impl<I: Interner> Clone for ConstKind<I> {
 /// These are regions that are stored behind a binder and must be substituted
 /// with some concrete region before being used. There are two kind of
 /// bound regions: early-bound, which are bound in an item's `Generics`,
-/// and are substituted by an `InternalSubsts`, and late-bound, which are part of
+/// and are substituted by an `GenericArgs`, and late-bound, which are part of
 /// higher-ranked types (e.g., `for<'a> fn(&'a ())`), and are substituted by
 /// the likes of `liberate_late_bound_regions`. The distinction exists
 /// because higher-ranked lifetimes aren't supported in all places. See [1][2].