about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock6
-rw-r--r--compiler/rustc_ast/src/ast.rs20
-rw-r--r--compiler/rustc_ast/src/attr/mod.rs6
-rw-r--r--compiler/rustc_ast/src/mut_visit.rs23
-rw-r--r--compiler/rustc_ast/src/token.rs22
-rw-r--r--compiler/rustc_ast/src/visit.rs24
-rw-r--r--compiler/rustc_ast_lowering/messages.ftl2
-rw-r--r--compiler/rustc_ast_lowering/src/errors.rs7
-rw-r--r--compiler/rustc_ast_lowering/src/expr.rs11
-rw-r--r--compiler/rustc_ast_lowering/src/index.rs17
-rw-r--r--compiler/rustc_ast_lowering/src/lib.rs173
-rw-r--r--compiler/rustc_ast_lowering/src/lifetime_collector.rs15
-rw-r--r--compiler/rustc_ast_passes/src/ast_validation.rs2
-rw-r--r--compiler/rustc_ast_passes/src/feature_gate.rs1
-rw-r--r--compiler/rustc_ast_pretty/src/pprust/state.rs13
-rw-r--r--compiler/rustc_ast_pretty/src/pprust/tests.rs10
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs33
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/region_errors.rs147
-rw-r--r--compiler/rustc_borrowck/src/region_infer/graphviz.rs40
-rw-r--r--compiler/rustc_borrowck/src/region_infer/mod.rs2
-rw-r--r--compiler/rustc_borrowck/src/region_infer/opaque_types.rs2
-rw-r--r--compiler/rustc_borrowck/src/type_check/input_output.rs7
-rw-r--r--compiler/rustc_borrowck/src/type_check/mod.rs4
-rw-r--r--compiler/rustc_borrowck/src/type_check/relate_tys.rs9
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/generic/ty.rs3
-rw-r--r--compiler/rustc_codegen_ssa/Cargo.toml2
-rw-r--r--compiler/rustc_codegen_ssa/src/back/archive.rs9
-rw-r--r--compiler/rustc_codegen_ssa/src/back/link.rs9
-rw-r--r--compiler/rustc_codegen_ssa/src/back/write.rs13
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/block.rs8
-rw-r--r--compiler/rustc_const_eval/src/interpret/machine.rs3
-rw-r--r--compiler/rustc_const_eval/src/interpret/memory.rs2
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/check.rs7
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/ops.rs11
-rw-r--r--compiler/rustc_driver_impl/src/pretty.rs19
-rw-r--r--compiler/rustc_expand/src/proc_macro_server.rs2
-rw-r--r--compiler/rustc_feature/src/unstable.rs6
-rw-r--r--compiler/rustc_hir/src/def.rs4
-rw-r--r--compiler/rustc_hir/src/hir.rs23
-rw-r--r--compiler/rustc_hir/src/intravisit.rs20
-rw-r--r--compiler/rustc_hir/src/tests.rs2
-rw-r--r--compiler/rustc_hir_analysis/messages.ftl19
-rw-r--r--compiler/rustc_hir_analysis/src/check/check.rs134
-rw-r--r--compiler/rustc_hir_analysis/src/check/compare_impl_item.rs10
-rw-r--r--compiler/rustc_hir_analysis/src/check/errs.rs8
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/builtin.rs35
-rw-r--r--compiler/rustc_hir_analysis/src/collect/predicates_of.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs64
-rw-r--r--compiler/rustc_hir_analysis/src/errors.rs3
-rw-r--r--compiler/rustc_hir_analysis/src/errors/precise_captures.rs63
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs37
-rw-r--r--compiler/rustc_hir_pretty/src/lib.rs34
-rw-r--r--compiler/rustc_hir_typeck/messages.ftl4
-rw-r--r--compiler/rustc_hir_typeck/src/_match.rs15
-rw-r--r--compiler/rustc_hir_typeck/src/callee.rs25
-rw-r--r--compiler/rustc_hir_typeck/src/check.rs5
-rw-r--r--compiler/rustc_hir_typeck/src/closure.rs72
-rw-r--r--compiler/rustc_hir_typeck/src/coercion.rs23
-rw-r--r--compiler/rustc_hir_typeck/src/demand.rs11
-rw-r--r--compiler/rustc_hir_typeck/src/errors.rs8
-rw-r--r--compiler/rustc_hir_typeck/src/expectation.rs7
-rw-r--r--compiler/rustc_hir_typeck/src/expr.rs37
-rw-r--r--compiler/rustc_hir_typeck/src/expr_use_visitor.rs22
-rw-r--r--compiler/rustc_hir_typeck/src/fallback.rs9
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs38
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs4
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs23
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs14
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs8
-rw-r--r--compiler/rustc_hir_typeck/src/gather_locals.rs19
-rw-r--r--compiler/rustc_hir_typeck/src/lib.rs50
-rw-r--r--compiler/rustc_hir_typeck/src/mem_categorization.rs30
-rw-r--r--compiler/rustc_hir_typeck/src/method/confirm.rs4
-rw-r--r--compiler/rustc_hir_typeck/src/method/prelude2021.rs16
-rw-r--r--compiler/rustc_hir_typeck/src/method/probe.rs17
-rw-r--r--compiler/rustc_hir_typeck/src/method/suggest.rs33
-rw-r--r--compiler/rustc_hir_typeck/src/op.rs14
-rw-r--r--compiler/rustc_hir_typeck/src/pat.rs252
-rw-r--r--compiler/rustc_hir_typeck/src/place_op.rs8
-rw-r--r--compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs6
-rw-r--r--compiler/rustc_hir_typeck/src/upvar.rs29
-rw-r--r--compiler/rustc_hir_typeck/src/writeback.rs25
-rw-r--r--compiler/rustc_infer/src/infer/at.rs2
-rw-r--r--compiler/rustc_infer/src/infer/canonical/canonicalizer.rs2
-rw-r--r--compiler/rustc_infer/src/infer/canonical/mod.rs8
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs71
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs1
-rw-r--r--compiler/rustc_infer/src/infer/mod.rs213
-rw-r--r--compiler/rustc_infer/src/infer/opaque_types/mod.rs10
-rw-r--r--compiler/rustc_infer/src/infer/projection.rs4
-rw-r--r--compiler/rustc_infer/src/infer/relate/combine.rs4
-rw-r--r--compiler/rustc_infer/src/infer/relate/generalize.rs9
-rw-r--r--compiler/rustc_infer/src/infer/relate/lattice.rs14
-rw-r--r--compiler/rustc_infer/src/infer/resolve.rs14
-rw-r--r--compiler/rustc_infer/src/infer/snapshot/fudge.rs9
-rw-r--r--compiler/rustc_infer/src/infer/type_variable.rs28
-rw-r--r--compiler/rustc_interface/src/interface.rs109
-rw-r--r--compiler/rustc_interface/src/tests.rs100
-rw-r--r--compiler/rustc_interface/src/util.rs16
-rw-r--r--compiler/rustc_lint/src/context/diagnostics/check_cfg.rs4
-rw-r--r--compiler/rustc_lint/src/late.rs9
-rw-r--r--compiler/rustc_lint/src/non_local_def.rs12
-rw-r--r--compiler/rustc_lint/src/unused.rs2
-rw-r--r--compiler/rustc_lint_defs/src/builtin.rs37
-rw-r--r--compiler/rustc_log/src/lib.rs2
-rw-r--r--compiler/rustc_middle/Cargo.toml1
-rw-r--r--compiler/rustc_middle/src/hir/map/mod.rs9
-rw-r--r--compiler/rustc_middle/src/hooks/mod.rs21
-rw-r--r--compiler/rustc_middle/src/infer/unify_key.rs14
-rw-r--r--compiler/rustc_middle/src/middle/region.rs14
-rw-r--r--compiler/rustc_middle/src/mir/mod.rs4
-rw-r--r--compiler/rustc_middle/src/mir/syntax.rs1
-rw-r--r--compiler/rustc_middle/src/query/mod.rs17
-rw-r--r--compiler/rustc_middle/src/query/plumbing.rs36
-rw-r--r--compiler/rustc_middle/src/thir.rs14
-rw-r--r--compiler/rustc_middle/src/traits/mod.rs31
-rw-r--r--compiler/rustc_middle/src/ty/closure.rs13
-rw-r--r--compiler/rustc_middle/src/ty/typeck_results.rs47
-rw-r--r--compiler/rustc_middle/src/ty/util.rs11
-rw-r--r--compiler/rustc_mir_build/src/build/matches/util.rs9
-rw-r--r--compiler/rustc_mir_build/src/build/mod.rs10
-rw-r--r--compiler/rustc_mir_build/src/check_unsafety.rs24
-rw-r--r--compiler/rustc_mir_build/src/lib.rs4
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/mod.rs2
-rw-r--r--compiler/rustc_mir_build/src/thir/print.rs11
-rw-r--r--compiler/rustc_mir_transform/src/gvn.rs4
-rw-r--r--compiler/rustc_parse/src/parser/diagnostics.rs12
-rw-r--r--compiler/rustc_parse/src/parser/generics.rs2
-rw-r--r--compiler/rustc_parse/src/parser/item.rs21
-rw-r--r--compiler/rustc_parse/src/parser/mod.rs4
-rw-r--r--compiler/rustc_parse/src/parser/nonterminal.rs4
-rw-r--r--compiler/rustc_parse/src/parser/pat.rs2
-rw-r--r--compiler/rustc_parse/src/parser/path.rs18
-rw-r--r--compiler/rustc_parse/src/parser/ty.rs57
-rw-r--r--compiler/rustc_passes/src/hir_stats.rs4
-rw-r--r--compiler/rustc_passes/src/liveness.rs2
-rw-r--r--compiler/rustc_passes/src/naked_functions.rs6
-rw-r--r--compiler/rustc_passes/src/upvars.rs2
-rw-r--r--compiler/rustc_resolve/src/late.rs31
-rw-r--r--compiler/rustc_resolve/src/late/diagnostics.rs2
-rw-r--r--compiler/rustc_session/src/config.rs14
-rw-r--r--compiler/rustc_session/src/config/cfg.rs2
-rw-r--r--compiler/rustc_session/src/options.rs4
-rw-r--r--compiler/rustc_session/src/session.rs36
-rw-r--r--compiler/rustc_span/src/lib.rs53
-rw-r--r--compiler/rustc_span/src/source_map.rs26
-rw-r--r--compiler/rustc_span/src/symbol.rs3
-rw-r--r--compiler/rustc_target/src/spec/base/apple/mod.rs1
-rw-r--r--compiler/rustc_target/src/spec/base/wasm.rs3
-rw-r--r--compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs14
-rw-r--r--compiler/rustc_trait_selection/src/solve/normalize.rs17
-rw-r--r--compiler/rustc_trait_selection/src/traits/coherence.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/const_evaluatable.rs9
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/infer_ctxt_ext.rs8
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs34
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs15
-rw-r--r--compiler/rustc_trait_selection/src/traits/mod.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/project.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs14
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/confirmation.rs9
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/mod.rs8
-rw-r--r--compiler/rustc_trait_selection/src/traits/structural_normalize.rs9
-rw-r--r--compiler/rustc_trait_selection/src/traits/util.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/wf.rs2
-rw-r--r--compiler/rustc_ty_utils/src/ty.rs4
-rw-r--r--compiler/rustc_type_ir/src/lib.rs5
-rw-r--r--library/alloc/src/boxed.rs8
-rw-r--r--library/core/src/iter/range.rs16
-rw-r--r--library/proc_macro/src/lib.rs2
-rw-r--r--library/std/src/fs.rs27
-rw-r--r--library/std/src/sys/pal/sgx/libunwind_integration.rs46
-rw-r--r--library/std/src/sys/pal/sgx/mod.rs1
-rw-r--r--library/std/src/sys/pal/sgx/waitqueue/mod.rs28
-rw-r--r--library/std/src/sys/pal/unix/process/process_unix.rs13
-rw-r--r--library/std/src/sys/sync/rwlock/mod.rs16
-rw-r--r--library/std/src/sys/sync/rwlock/sgx.rs219
-rw-r--r--library/std/src/sys/sync/rwlock/sgx/tests.rs21
-rw-r--r--library/std/src/sys/sync/rwlock/windows7.rs40
-rw-r--r--library/std/src/sys/sync/rwlock/xous.rs74
-rw-r--r--src/bootstrap/src/bin/main.rs4
-rw-r--r--src/bootstrap/src/core/build_steps/check.rs113
-rw-r--r--src/bootstrap/src/core/build_steps/clippy.rs330
-rw-r--r--src/bootstrap/src/core/build_steps/llvm.rs7
-rw-r--r--src/bootstrap/src/core/build_steps/mod.rs1
-rw-r--r--src/bootstrap/src/core/build_steps/tool.rs7
-rw-r--r--src/bootstrap/src/core/builder.rs33
-rw-r--r--src/bootstrap/src/core/config/config.rs16
-rw-r--r--src/bootstrap/src/core/config/tests.rs2
-rw-r--r--src/bootstrap/src/lib.rs22
-rw-r--r--src/bootstrap/src/utils/change_tracker.rs5
-rw-r--r--src/bootstrap/src/utils/tarball.rs7
-rw-r--r--src/ci/docker/host-x86_64/mingw-check/Dockerfile2
-rw-r--r--src/doc/rustc/src/SUMMARY.md1
-rw-r--r--src/doc/rustc/src/check-cfg.md (renamed from src/doc/unstable-book/src/compiler-flags/check-cfg.md)8
-rw-r--r--src/doc/rustc/src/codegen-options/index.md20
-rw-r--r--src/doc/rustc/src/command-line-arguments.md10
-rw-r--r--src/doc/rustdoc/src/command-line-arguments.md14
-rw-r--r--src/doc/rustdoc/src/unstable-features.md16
-rw-r--r--src/librustdoc/clean/mod.rs24
-rw-r--r--src/librustdoc/clean/types.rs2
-rw-r--r--src/librustdoc/doctest.rs7
-rw-r--r--src/librustdoc/html/render/mod.rs6
-rw-r--r--src/librustdoc/html/render/type_layout.rs5
-rw-r--r--src/librustdoc/html/static/js/main.js3
-rw-r--r--src/librustdoc/html/templates/page.html2
-rw-r--r--src/librustdoc/lib.rs2
m---------src/tools/cargo0
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/ptr_as_ptr.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/crate_in_macro_def.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/derivable_impls.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/doc/needless_doctest_main.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/from_raw_with_void_ptr.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/functions/result.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/implicit_saturating_add.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/index_refutable_slice.rs13
-rw-r--r--src/tools/clippy/clippy_lints/src/large_enum_variant.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/match_wild_err_arm.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/unnecessary_join.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/mut_key.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/mut_reference.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/non_copy_const.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/assign_op_pattern.rs33
-rw-r--r--src/tools/clippy/clippy_lints/src/ptr.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/significant_drop_tightening.rs18
-rw-r--r--src/tools/clippy/clippy_lints/src/zero_sized_map_values.rs4
-rw-r--r--src/tools/clippy/clippy_utils/src/ast_utils.rs11
-rw-r--r--src/tools/clippy/clippy_utils/src/ty.rs4
-rw-r--r--src/tools/compiletest/src/header.rs6
-rw-r--r--src/tools/compiletest/src/runtest.rs4
-rw-r--r--src/tools/lint-docs/src/lib.rs1
-rw-r--r--src/tools/miri/cargo-miri/src/phases.rs13
-rw-r--r--src/tools/miri/src/borrow_tracker/mod.rs2
-rw-r--r--src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs2
-rw-r--r--src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs2
-rw-r--r--src/tools/miri/src/concurrency/data_race.rs2
-rw-r--r--src/tools/miri/src/diagnostics.rs4
-rw-r--r--src/tools/miri/src/lib.rs2
-rw-r--r--src/tools/miri/src/machine.rs15
-rw-r--r--src/tools/miri/src/shims/os_str.rs8
-rw-r--r--src/tools/miri/tests/fail/both_borrows/newtype_pair_retagging.stack.stderr2
-rw-r--r--src/tools/miri/tests/fail/both_borrows/newtype_retagging.stack.stderr2
-rw-r--r--src/tools/miri/tests/pass/issues/issue-miri-3473.rs28
-rw-r--r--src/tools/miri/tests/pass/stacked-borrows/stacked-borrows.rs12
-rw-r--r--src/tools/run-make-support/Cargo.toml1
-rw-r--r--src/tools/run-make-support/src/lib.rs1
-rw-r--r--src/tools/run-make-support/src/rustc.rs9
-rw-r--r--src/tools/rustfmt/src/macros.rs2
-rw-r--r--src/tools/rustfmt/src/types.rs9
-rw-r--r--src/tools/tidy/src/allowed_run_make_makefiles.txt2
-rw-r--r--tests/crashes/123153.rs17
-rw-r--r--tests/crashes/123154.rs12
-rw-r--r--tests/crashes/README.md7
-rw-r--r--tests/debuginfo/include_string.rs2
-rw-r--r--tests/debuginfo/vec-slices.rs2
-rw-r--r--tests/run-make/artifact-incr-cache-no-obj/lib.rs6
-rw-r--r--tests/run-make/artifact-incr-cache-no-obj/rmake.rs23
-rw-r--r--tests/run-make/relro-levels/Makefile8
-rw-r--r--tests/run-make/rust-lld-custom-target/Makefile7
-rw-r--r--tests/run-make/rust-lld-custom-target/rmake.rs51
-rw-r--r--tests/run-make/rust-lld/Makefile12
-rw-r--r--tests/run-make/rust-lld/rmake.rs64
-rw-r--r--tests/rustdoc-ui/auxiliary/issue-73061.rs (renamed from tests/rustdoc/auxiliary/issue-73061.rs)0
-rw-r--r--tests/rustdoc-ui/check-cfg.rs (renamed from tests/rustdoc-ui/check-cfg/check-cfg.rs)2
-rw-r--r--tests/rustdoc-ui/check-cfg.stderr (renamed from tests/rustdoc-ui/check-cfg/check-cfg.stderr)2
-rw-r--r--tests/rustdoc-ui/check-cfg/check-cfg-test.stderr11
-rw-r--r--tests/rustdoc-ui/check-cfg/check-cfg-unstable.rs2
-rw-r--r--tests/rustdoc-ui/check-cfg/check-cfg-unstable.stderr2
-rw-r--r--tests/rustdoc-ui/doctest/check-cfg-test.stderr2
-rw-r--r--tests/rustdoc-ui/ice-blanket-impl-56701.rs (renamed from tests/rustdoc/issue-56701.rs)2
-rw-r--r--tests/rustdoc-ui/ice-cross-crate-opaque-assoc-type-73061.rs (renamed from tests/rustdoc/issue-73061-cross-crate-opaque-assoc-type.rs)3
-rw-r--r--tests/rustdoc/blanket-impl-78673.rs (renamed from tests/rustdoc/issue-78673.rs)1
-rw-r--r--tests/rustdoc/const-fn-76501.rs (renamed from tests/rustdoc/issue-76501.rs)7
-rw-r--r--tests/rustdoc/doc-cfg-inherit-from-module-79201.rs (renamed from tests/rustdoc/issue-79201.rs)5
-rw-r--r--tests/rustdoc/doc-hidden-private-67851-both.rs (renamed from tests/rustdoc/issue-67851-both.rs)6
-rw-r--r--tests/rustdoc/doc-hidden-private-67851-hidden.rs10
-rw-r--r--tests/rustdoc/doc-hidden-private-67851-neither.rs9
-rw-r--r--tests/rustdoc/doc-hidden-private-67851-private.rs10
-rw-r--r--tests/rustdoc/duplicated-glob-reexport-60522.rs (renamed from tests/rustdoc/issue-60522-duplicated-glob-reexport.rs)0
-rw-r--r--tests/rustdoc/hide-mut-methods-if-no-derefmut-impl-74083.rs (renamed from tests/rustdoc/issue-74083.rs)5
-rw-r--r--tests/rustdoc/implementors-unstable-75588.rs (renamed from tests/rustdoc/issue-75588.rs)1
-rw-r--r--tests/rustdoc/inline_cross/auxiliary/issue-57180.rs (renamed from tests/rustdoc/auxiliary/issue-57180.rs)0
-rw-r--r--tests/rustdoc/inline_cross/ice-import-crate-57180.rs (renamed from tests/rustdoc/issue-57180.rs)1
-rw-r--r--tests/rustdoc/intra-doc-link-method-trait-impl-72340.rs (renamed from tests/rustdoc/issue-72340.rs)2
-rw-r--r--tests/rustdoc/issue-67851-hidden.rs8
-rw-r--r--tests/rustdoc/issue-67851-neither.rs6
-rw-r--r--tests/rustdoc/issue-67851-private.rs8
-rw-r--r--tests/rustdoc/markdown-60482.rs (renamed from tests/rustdoc/issue-60482.rs)1
-rw-r--r--tests/rustdoc/sidebar-trait-impl-disambiguate-78701.rs (renamed from tests/rustdoc/issue-78701.rs)1
-rw-r--r--tests/rustdoc/synthetic_auto/auto-trait-lifetimes-56822.rs (renamed from tests/rustdoc/issue-56822.rs)5
-rw-r--r--tests/rustdoc/synthetic_auto/send-impl-conditional-60726.rs (renamed from tests/rustdoc/issue-60726.rs)5
-rw-r--r--tests/rustdoc/underscore-import-61592.rs (renamed from tests/rustdoc/issue-61592.rs)6
-rw-r--r--tests/ui/borrowck/borrowck-init-in-fru.stderr4
-rw-r--r--tests/ui/borrowck/borrowck-uninit-ref-chain.stderr4
-rw-r--r--tests/ui/borrowck/issue-103250.stderr4
-rw-r--r--tests/ui/borrowck/suggest-assign-rvalue.stderr4
-rw-r--r--tests/ui/check-cfg/allow-at-crate-level.rs2
-rw-r--r--tests/ui/check-cfg/allow-macro-cfg.rs2
-rw-r--r--tests/ui/check-cfg/allow-same-level.rs2
-rw-r--r--tests/ui/check-cfg/allow-same-level.stderr2
-rw-r--r--tests/ui/check-cfg/allow-top-level.rs2
-rw-r--r--tests/ui/check-cfg/allow-upper-level.rs2
-rw-r--r--tests/ui/check-cfg/cargo-feature.none.stderr8
-rw-r--r--tests/ui/check-cfg/cargo-feature.rs1
-rw-r--r--tests/ui/check-cfg/cargo-feature.some.stderr8
-rw-r--r--tests/ui/check-cfg/cfg-value-for-cfg-name-duplicate.rs1
-rw-r--r--tests/ui/check-cfg/cfg-value-for-cfg-name-duplicate.stderr4
-rw-r--r--tests/ui/check-cfg/cfg-value-for-cfg-name-multiple.rs1
-rw-r--r--tests/ui/check-cfg/cfg-value-for-cfg-name-multiple.stderr4
-rw-r--r--tests/ui/check-cfg/cfg-value-for-cfg-name.rs1
-rw-r--r--tests/ui/check-cfg/cfg-value-for-cfg-name.stderr8
-rw-r--r--tests/ui/check-cfg/compact-names.rs2
-rw-r--r--tests/ui/check-cfg/compact-names.stderr2
-rw-r--r--tests/ui/check-cfg/compact-values.rs2
-rw-r--r--tests/ui/check-cfg/compact-values.stderr2
-rw-r--r--tests/ui/check-cfg/concat-values.rs1
-rw-r--r--tests/ui/check-cfg/concat-values.stderr8
-rw-r--r--tests/ui/check-cfg/diagnotics.rs2
-rw-r--r--tests/ui/check-cfg/diagnotics.rustc.stderr12
-rw-r--r--tests/ui/check-cfg/empty-values.rs2
-rw-r--r--tests/ui/check-cfg/empty-values.stderr4
-rw-r--r--tests/ui/check-cfg/exhaustive-names-values.empty_cfg.stderr16
-rw-r--r--tests/ui/check-cfg/exhaustive-names-values.feature.stderr12
-rw-r--r--tests/ui/check-cfg/exhaustive-names-values.full.stderr12
-rw-r--r--tests/ui/check-cfg/exhaustive-names-values.rs1
-rw-r--r--tests/ui/check-cfg/exhaustive-names.rs2
-rw-r--r--tests/ui/check-cfg/exhaustive-names.stderr2
-rw-r--r--tests/ui/check-cfg/exhaustive-values.empty_cfg.stderr2
-rw-r--r--tests/ui/check-cfg/exhaustive-values.rs4
-rw-r--r--tests/ui/check-cfg/exhaustive-values.without_names.stderr2
-rw-r--r--tests/ui/check-cfg/invalid-arguments.rs1
-rw-r--r--tests/ui/check-cfg/mix.rs2
-rw-r--r--tests/ui/check-cfg/mix.stderr54
-rw-r--r--tests/ui/check-cfg/no-expected-values.empty.stderr8
-rw-r--r--tests/ui/check-cfg/no-expected-values.mixed.stderr8
-rw-r--r--tests/ui/check-cfg/no-expected-values.rs1
-rw-r--r--tests/ui/check-cfg/no-expected-values.simple.stderr8
-rw-r--r--tests/ui/check-cfg/order-independant.rs2
-rw-r--r--tests/ui/check-cfg/order-independant.values_after.stderr4
-rw-r--r--tests/ui/check-cfg/order-independant.values_before.stderr4
-rw-r--r--tests/ui/check-cfg/stmt-no-ice.rs2
-rw-r--r--tests/ui/check-cfg/stmt-no-ice.stderr2
-rw-r--r--tests/ui/check-cfg/unexpected-cfg-name.rs2
-rw-r--r--tests/ui/check-cfg/unexpected-cfg-name.stderr2
-rw-r--r--tests/ui/check-cfg/unexpected-cfg-value.rs2
-rw-r--r--tests/ui/check-cfg/unexpected-cfg-value.stderr4
-rw-r--r--tests/ui/check-cfg/unknown-values.rs1
-rw-r--r--tests/ui/check-cfg/values-none.explicit.stderr8
-rw-r--r--tests/ui/check-cfg/values-none.implicit.stderr8
-rw-r--r--tests/ui/check-cfg/values-none.rs1
-rw-r--r--tests/ui/check-cfg/values-target-json.rs2
-rw-r--r--tests/ui/check-cfg/well-known-names.rs2
-rw-r--r--tests/ui/check-cfg/well-known-names.stderr8
-rw-r--r--tests/ui/check-cfg/well-known-values.rs2
-rw-r--r--tests/ui/check-cfg/well-known-values.stderr56
-rw-r--r--tests/ui/closures/issue-78720.rs1
-rw-r--r--tests/ui/closures/issue-78720.stderr16
-rw-r--r--tests/ui/const-generics/kind_mismatch.rs24
-rw-r--r--tests/ui/const-generics/kind_mismatch.stderr39
-rw-r--r--tests/ui/const_prop/ice-type-mismatch-when-copying-112824.rs1
-rw-r--r--tests/ui/const_prop/ice-type-mismatch-when-copying-112824.stderr8
-rw-r--r--tests/ui/consts/const-eval/ice-unsized-struct-const-eval-123154.rs15
-rw-r--r--tests/ui/consts/const-eval/ice-unsized-struct-const-eval-123154.stderr24
-rw-r--r--tests/ui/consts/value-suggestion-ice-123906.stderr6
-rw-r--r--tests/ui/enum/error-variant-with-turbofishes.rs8
-rw-r--r--tests/ui/enum/error-variant-with-turbofishes.stderr9
-rw-r--r--tests/ui/feature-gates/feature-gate-abi.rs2
-rw-r--r--tests/ui/feature-gates/feature-gate-abi.stderr71
-rw-r--r--tests/ui/feature-gates/feature-gate-check-cfg.rs3
-rw-r--r--tests/ui/feature-gates/feature-gate-check-cfg.stderr2
-rw-r--r--tests/ui/feature-gates/feature-gate-intrinsics.rs1
-rw-r--r--tests/ui/feature-gates/feature-gate-intrinsics.stderr10
-rw-r--r--tests/ui/feature-gates/feature-gate-precise-capturing.rs4
-rw-r--r--tests/ui/feature-gates/feature-gate-precise-capturing.stderr13
-rw-r--r--tests/ui/impl-trait/precise-capturing/apit.rs7
-rw-r--r--tests/ui/impl-trait/precise-capturing/apit.stderr17
-rw-r--r--tests/ui/impl-trait/precise-capturing/bad-lifetimes.rs14
-rw-r--r--tests/ui/impl-trait/precise-capturing/bad-lifetimes.stderr45
-rw-r--r--tests/ui/impl-trait/precise-capturing/bad-params.rs19
-rw-r--r--tests/ui/impl-trait/precise-capturing/bad-params.stderr46
-rw-r--r--tests/ui/impl-trait/precise-capturing/elided.rs8
-rw-r--r--tests/ui/impl-trait/precise-capturing/elided.stderr11
-rw-r--r--tests/ui/impl-trait/precise-capturing/forgot-to-capture-const.rs7
-rw-r--r--tests/ui/impl-trait/precise-capturing/forgot-to-capture-const.stderr19
-rw-r--r--tests/ui/impl-trait/precise-capturing/forgot-to-capture-lifetime.rs10
-rw-r--r--tests/ui/impl-trait/precise-capturing/forgot-to-capture-lifetime.stderr35
-rw-r--r--tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.rs12
-rw-r--r--tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.stderr30
-rw-r--r--tests/ui/impl-trait/precise-capturing/higher-ranked.rs18
-rw-r--r--tests/ui/impl-trait/precise-capturing/higher-ranked.stderr11
-rw-r--r--tests/ui/impl-trait/precise-capturing/ordering.rs16
-rw-r--r--tests/ui/impl-trait/precise-capturing/ordering.stderr37
-rw-r--r--tests/ui/impl-trait/precise-capturing/outlives.rs16
-rw-r--r--tests/ui/impl-trait/precise-capturing/outlives.stderr11
-rw-r--r--tests/ui/impl-trait/precise-capturing/self-capture.rs10
-rw-r--r--tests/ui/impl-trait/precise-capturing/self-capture.stderr11
-rw-r--r--tests/ui/intrinsics/incorrect-read_via_copy-defn.rs7
-rw-r--r--tests/ui/intrinsics/incorrect-read_via_copy-defn.stderr18
-rw-r--r--tests/ui/intrinsics/incorrect-transmute.rs3
-rw-r--r--tests/ui/intrinsics/incorrect-transmute.stderr11
-rw-r--r--tests/ui/loops/loop-break-value.stderr20
-rw-r--r--tests/ui/match/ref_pat_eat_one_layer_2024/feature-gate-ref_pat_eat_one_layer_2024.rs37
-rw-r--r--tests/ui/match/ref_pat_eat_one_layer_2024/feature-gate-ref_pat_eat_one_layer_2024.stderr128
-rw-r--r--tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2021.rs37
-rw-r--r--tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2021.stderr128
-rw-r--r--tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024.rs65
-rw-r--r--tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.rs33
-rw-r--r--tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.stderr91
-rw-r--r--tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail2.rs11
-rw-r--r--tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail2.stderr17
-rw-r--r--tests/ui/moves/issue-72649-uninit-in-loop.stderr8
-rw-r--r--tests/ui/moves/move-into-dead-array-1.stderr4
-rw-r--r--tests/ui/moves/move-of-addr-of-mut.stderr4
-rw-r--r--tests/ui/nll/match-on-borrowed.stderr4
-rw-r--r--tests/ui/pattern/feature-gate-mut_preserve_binding_mode_2024.rs14
-rw-r--r--tests/ui/pattern/feature-gate-mut_preserve_binding_mode_2024.stderr31
-rw-r--r--tests/ui/pattern/mut_preserve_binding_mode_2021.rs16
-rw-r--r--tests/ui/pattern/mut_preserve_binding_mode_2021.stderr31
-rw-r--r--tests/ui/pattern/mut_preserve_binding_mode_2024.rs15
-rw-r--r--tests/ui/pattern/mut_preserve_binding_mode_2024_lint.rs16
-rw-r--r--tests/ui/pattern/mut_preserve_binding_mode_2024_lint.stderr31
-rw-r--r--tests/ui/sized/ensure-overriding-bindings-in-pattern-with-ty-err-doesnt-ice.rs2
-rw-r--r--tests/ui/sized/ensure-overriding-bindings-in-pattern-with-ty-err-doesnt-ice.stderr4
-rw-r--r--tests/ui/specialization/issue-68830-spurious-diagnostics.rs1
-rw-r--r--tests/ui/specialization/issue-68830-spurious-diagnostics.stderr14
-rw-r--r--tests/ui/statics/unsized_type2.rs21
-rw-r--r--tests/ui/statics/unsized_type2.stderr37
-rw-r--r--triagebot.toml10
428 files changed, 4473 insertions, 2618 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 71967b03b09..cf5425a5a89 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -210,9 +210,9 @@ dependencies = [
 
 [[package]]
 name = "ar_archive_writer"
-version = "0.1.5"
+version = "0.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9792d37ca5173d7e7f4fe453739a0671d0557915a030a383d6b866476bbc3e71"
+checksum = "f0c269894b6fe5e9d7ada0cf69b5bf847ff35bc25fc271f08e1d080fce80339a"
 dependencies = [
  "object 0.32.2",
 ]
@@ -3342,6 +3342,7 @@ name = "run_make_support"
 version = "0.0.0"
 dependencies = [
  "object 0.34.0",
+ "regex",
  "wasmparser",
 ]
 
@@ -4278,6 +4279,7 @@ dependencies = [
  "rustc_fluent_macro",
  "rustc_graphviz",
  "rustc_hir",
+ "rustc_hir_pretty",
  "rustc_index",
  "rustc_macros",
  "rustc_query_system",
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs
index 5b708cf4e1a..519eeeded9a 100644
--- a/compiler/rustc_ast/src/ast.rs
+++ b/compiler/rustc_ast/src/ast.rs
@@ -36,6 +36,7 @@ use rustc_macros::HashStable_Generic;
 use rustc_span::source_map::{respan, Spanned};
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::{ErrorGuaranteed, Span, DUMMY_SP};
+use std::cmp;
 use std::fmt;
 use std::mem;
 use thin_vec::{thin_vec, ThinVec};
@@ -63,7 +64,7 @@ impl fmt::Debug for Label {
 
 /// A "Lifetime" is an annotation of the scope in which variable
 /// can be used, e.g. `'a` in `&'a i32`.
-#[derive(Clone, Encodable, Decodable, Copy, PartialEq, Eq)]
+#[derive(Clone, Encodable, Decodable, Copy, PartialEq, Eq, Hash)]
 pub struct Lifetime {
     pub id: NodeId,
     pub ident: Ident,
@@ -731,6 +732,13 @@ impl BindingAnnotation {
             Self::MUT_REF_MUT => "mut ref mut ",
         }
     }
+
+    pub fn cap_ref_mutability(mut self, mutbl: Mutability) -> Self {
+        if let ByRef::Yes(old_mutbl) = &mut self.0 {
+            *old_mutbl = cmp::min(*old_mutbl, mutbl);
+        }
+        self
+    }
 }
 
 #[derive(Clone, Encodable, Decodable, Debug)]
@@ -2132,7 +2140,7 @@ pub enum TyKind {
     /// The `NodeId` exists to prevent lowering from having to
     /// generate `NodeId`s on the fly, which would complicate
     /// the generation of opaque `type Foo = impl Trait` items significantly.
-    ImplTrait(NodeId, GenericBounds),
+    ImplTrait(NodeId, GenericBounds, Option<P<(ThinVec<PreciseCapturingArg>, Span)>>),
     /// No-op; kept solely so that we can pretty-print faithfully.
     Paren(P<Ty>),
     /// Unused for now.
@@ -2188,6 +2196,14 @@ pub enum TraitObjectSyntax {
     None,
 }
 
+#[derive(Clone, Encodable, Decodable, Debug)]
+pub enum PreciseCapturingArg {
+    /// Lifetime parameter
+    Lifetime(Lifetime),
+    /// Type or const parameter
+    Arg(Path, NodeId),
+}
+
 /// Inline assembly operand explicit register or register class.
 ///
 /// E.g., `"eax"` as in `asm!("mov eax, 2", out("eax") result)`.
diff --git a/compiler/rustc_ast/src/attr/mod.rs b/compiler/rustc_ast/src/attr/mod.rs
index 98138cedb24..5e3fc7e3357 100644
--- a/compiler/rustc_ast/src/attr/mod.rs
+++ b/compiler/rustc_ast/src/attr/mod.rs
@@ -308,11 +308,11 @@ impl MetaItem {
         // FIXME: Share code with `parse_path`.
         let path = match tokens.next().map(|tt| TokenTree::uninterpolate(tt)).as_deref() {
             Some(&TokenTree::Token(
-                Token { kind: ref kind @ (token::Ident(..) | token::ModSep), span },
+                Token { kind: ref kind @ (token::Ident(..) | token::PathSep), span },
                 _,
             )) => 'arm: {
                 let mut segments = if let &token::Ident(name, _) = kind {
-                    if let Some(TokenTree::Token(Token { kind: token::ModSep, .. }, _)) =
+                    if let Some(TokenTree::Token(Token { kind: token::PathSep, .. }, _)) =
                         tokens.peek()
                     {
                         tokens.next();
@@ -331,7 +331,7 @@ impl MetaItem {
                     } else {
                         return None;
                     }
-                    if let Some(TokenTree::Token(Token { kind: token::ModSep, .. }, _)) =
+                    if let Some(TokenTree::Token(Token { kind: token::PathSep, .. }, _)) =
                         tokens.peek()
                     {
                         tokens.next();
diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs
index da57def263d..c4e49d7dbea 100644
--- a/compiler/rustc_ast/src/mut_visit.rs
+++ b/compiler/rustc_ast/src/mut_visit.rs
@@ -259,6 +259,10 @@ pub trait MutVisitor: Sized {
         noop_visit_param_bound(tpb, self);
     }
 
+    fn visit_precise_capturing_arg(&mut self, arg: &mut PreciseCapturingArg) {
+        noop_visit_precise_capturing_arg(arg, self);
+    }
+
     fn visit_mt(&mut self, mt: &mut MutTy) {
         noop_visit_mt(mt, self);
     }
@@ -518,9 +522,14 @@ pub fn noop_visit_ty<T: MutVisitor>(ty: &mut P<Ty>, vis: &mut T) {
         TyKind::TraitObject(bounds, _syntax) => {
             visit_vec(bounds, |bound| vis.visit_param_bound(bound))
         }
-        TyKind::ImplTrait(id, bounds) => {
+        TyKind::ImplTrait(id, bounds, precise_capturing) => {
             vis.visit_id(id);
             visit_vec(bounds, |bound| vis.visit_param_bound(bound));
+            if let Some((precise_capturing, _span)) = precise_capturing.as_deref_mut() {
+                for arg in precise_capturing {
+                    vis.visit_precise_capturing_arg(arg);
+                }
+            }
         }
         TyKind::MacCall(mac) => vis.visit_mac_call(mac),
         TyKind::AnonStruct(id, fields) | TyKind::AnonUnion(id, fields) => {
@@ -914,6 +923,18 @@ pub fn noop_visit_param_bound<T: MutVisitor>(pb: &mut GenericBound, vis: &mut T)
     }
 }
 
+pub fn noop_visit_precise_capturing_arg<T: MutVisitor>(arg: &mut PreciseCapturingArg, vis: &mut T) {
+    match arg {
+        PreciseCapturingArg::Lifetime(lt) => {
+            vis.visit_lifetime(lt);
+        }
+        PreciseCapturingArg::Arg(path, id) => {
+            vis.visit_path(path);
+            vis.visit_id(id);
+        }
+    }
+}
+
 pub fn noop_flat_map_generic_param<T: MutVisitor>(
     mut param: GenericParam,
     vis: &mut T,
diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs
index 5060bbec421..5b41ac8a69e 100644
--- a/compiler/rustc_ast/src/token.rs
+++ b/compiler/rustc_ast/src/token.rs
@@ -51,7 +51,7 @@ pub enum Delimiter {
     Brace,
     /// `[ ... ]`
     Bracket,
-    /// `Ø ... Ø`
+    /// `∅ ... ∅`
     /// An invisible delimiter, that may, for example, appear around tokens coming from a
     /// "macro variable" `$var`. It is important to preserve operator priorities in cases like
     /// `$var * 3` where `$var` is `1 + 2`.
@@ -290,7 +290,7 @@ pub enum TokenKind {
     /// `:`
     Colon,
     /// `::`
-    ModSep,
+    PathSep,
     /// `->`
     RArrow,
     /// `<-`
@@ -393,7 +393,7 @@ impl TokenKind {
             BinOpEq(Shr) => (Gt, Ge),
             DotDot => (Dot, Dot),
             DotDotDot => (Dot, DotDot),
-            ModSep => (Colon, Colon),
+            PathSep => (Colon, Colon),
             RArrow => (BinOp(Minus), Gt),
             LArrow => (Lt, BinOp(Minus)),
             FatArrow => (Eq, Gt),
@@ -454,7 +454,9 @@ impl Token {
         match self.kind {
             Eq | Lt | Le | EqEq | Ne | Ge | Gt | AndAnd | OrOr | Not | Tilde | BinOp(_)
             | BinOpEq(_) | At | Dot | DotDot | DotDotDot | DotDotEq | Comma | Semi | Colon
-            | ModSep | RArrow | LArrow | FatArrow | Pound | Dollar | Question | SingleQuote => true,
+            | PathSep | RArrow | LArrow | FatArrow | Pound | Dollar | Question | SingleQuote => {
+                true
+            }
 
             OpenDelim(..) | CloseDelim(..) | Literal(..) | DocComment(..) | Ident(..)
             | Lifetime(..) | Interpolated(..) | Eof => false,
@@ -481,7 +483,7 @@ impl Token {
             // DotDotDot is no longer supported, but we need some way to display the error
             DotDot | DotDotDot | DotDotEq     | // range notation
             Lt | BinOp(Shl)                   | // associated path
-            ModSep                            | // global path
+            PathSep                            | // global path
             Lifetime(..)                      | // labeled loop
             Pound                             => true, // expression attributes
             Interpolated(ref nt) => matches!(&nt.0, NtLiteral(..) |
@@ -507,7 +509,7 @@ impl Token {
             // DotDotDot is no longer supported
             | DotDot | DotDotDot | DotDotEq      // ranges
             | Lt | BinOp(Shl)                    // associated path
-            | ModSep                    => true, // global path
+            | PathSep                    => true, // global path
             Interpolated(ref nt) => matches!(&nt.0, NtLiteral(..) |
                 NtPat(..)     |
                 NtBlock(..)   |
@@ -530,7 +532,7 @@ impl Token {
             Question                    | // maybe bound in trait object
             Lifetime(..)                | // lifetime bound in trait object
             Lt | BinOp(Shl)             | // associated path
-            ModSep                      => true, // global path
+            PathSep                      => true, // global path
             Interpolated(ref nt) => matches!(&nt.0, NtTy(..) | NtPath(..)),
             // For anonymous structs or unions, which only appear in specific positions
             // (type of struct fields or union fields), we don't consider them as regular types
@@ -708,7 +710,7 @@ impl Token {
     }
 
     pub fn is_path_start(&self) -> bool {
-        self == &ModSep
+        self == &PathSep
             || self.is_qpath_start()
             || self.is_whole_path()
             || self.is_path_segment_keyword()
@@ -821,7 +823,7 @@ impl Token {
                 _ => return None,
             },
             Colon => match joint.kind {
-                Colon => ModSep,
+                Colon => PathSep,
                 _ => return None,
             },
             SingleQuote => match joint.kind {
@@ -830,7 +832,7 @@ impl Token {
             },
 
             Le | EqEq | Ne | Ge | AndAnd | OrOr | Tilde | BinOpEq(..) | At | DotDotDot
-            | DotDotEq | Comma | Semi | ModSep | RArrow | LArrow | FatArrow | Pound | Dollar
+            | DotDotEq | Comma | Semi | PathSep | RArrow | LArrow | FatArrow | Pound | Dollar
             | Question | OpenDelim(..) | CloseDelim(..) | Literal(..) | Ident(..)
             | Lifetime(..) | Interpolated(..) | DocComment(..) | Eof => return None,
         };
diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs
index 9e9ae52962d..968d10ad487 100644
--- a/compiler/rustc_ast/src/visit.rs
+++ b/compiler/rustc_ast/src/visit.rs
@@ -184,6 +184,9 @@ pub trait Visitor<'ast>: Sized {
     fn visit_param_bound(&mut self, bounds: &'ast GenericBound, _ctxt: BoundKind) -> Self::Result {
         walk_param_bound(self, bounds)
     }
+    fn visit_precise_capturing_arg(&mut self, arg: &'ast PreciseCapturingArg) {
+        walk_precise_capturing_arg(self, arg);
+    }
     fn visit_poly_trait_ref(&mut self, t: &'ast PolyTraitRef) -> Self::Result {
         walk_poly_trait_ref(self, t)
     }
@@ -457,8 +460,13 @@ pub fn walk_ty<'a, V: Visitor<'a>>(visitor: &mut V, typ: &'a Ty) -> V::Result {
         TyKind::TraitObject(bounds, ..) => {
             walk_list!(visitor, visit_param_bound, bounds, BoundKind::TraitObject);
         }
-        TyKind::ImplTrait(_, bounds) => {
+        TyKind::ImplTrait(_, bounds, precise_capturing) => {
             walk_list!(visitor, visit_param_bound, bounds, BoundKind::Impl);
+            if let Some((precise_capturing, _span)) = precise_capturing.as_deref() {
+                for arg in precise_capturing {
+                    try_visit!(visitor.visit_precise_capturing_arg(arg));
+                }
+            }
         }
         TyKind::Typeof(expression) => try_visit!(visitor.visit_anon_const(expression)),
         TyKind::Infer | TyKind::ImplicitSelf | TyKind::Dummy | TyKind::Err(_) => {}
@@ -637,6 +645,20 @@ pub fn walk_param_bound<'a, V: Visitor<'a>>(visitor: &mut V, bound: &'a GenericB
     }
 }
 
+pub fn walk_precise_capturing_arg<'a, V: Visitor<'a>>(
+    visitor: &mut V,
+    arg: &'a PreciseCapturingArg,
+) {
+    match arg {
+        PreciseCapturingArg::Lifetime(lt) => {
+            visitor.visit_lifetime(lt, LifetimeCtxt::GenericArg);
+        }
+        PreciseCapturingArg::Arg(path, id) => {
+            visitor.visit_path(path, *id);
+        }
+    }
+}
+
 pub fn walk_generic_param<'a, V: Visitor<'a>>(
     visitor: &mut V,
     param: &'a GenericParam,
diff --git a/compiler/rustc_ast_lowering/messages.ftl b/compiler/rustc_ast_lowering/messages.ftl
index d91d65497e1..a23e714ef01 100644
--- a/compiler/rustc_ast_lowering/messages.ftl
+++ b/compiler/rustc_ast_lowering/messages.ftl
@@ -127,6 +127,8 @@ ast_lowering_never_pattern_with_guard =
     a guard on a never pattern will never be run
     .suggestion = remove this guard
 
+ast_lowering_no_precise_captures_on_apit = `use<...>` precise capturing syntax not allowed on argument-position `impl Trait`
+
 ast_lowering_previously_used_here = previously used here
 
 ast_lowering_register1 = register `{$reg1_name}`
diff --git a/compiler/rustc_ast_lowering/src/errors.rs b/compiler/rustc_ast_lowering/src/errors.rs
index 6fd980ed3ca..ca0821e2c9e 100644
--- a/compiler/rustc_ast_lowering/src/errors.rs
+++ b/compiler/rustc_ast_lowering/src/errors.rs
@@ -414,3 +414,10 @@ pub(crate) struct AsyncBoundOnlyForFnTraits {
     #[primary_span]
     pub span: Span,
 }
+
+#[derive(Diagnostic)]
+#[diag(ast_lowering_no_precise_captures_on_apit)]
+pub(crate) struct NoPreciseCapturesOnApit {
+    #[primary_span]
+    pub span: Span,
+}
diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs
index 389cf4e3132..66841c094ce 100644
--- a/compiler/rustc_ast_lowering/src/expr.rs
+++ b/compiler/rustc_ast_lowering/src/expr.rs
@@ -14,6 +14,7 @@ use rustc_ast::*;
 use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
+use rustc_hir::HirId;
 use rustc_middle::span_bug;
 use rustc_session::errors::report_lit_error;
 use rustc_span::source_map::{respan, Spanned};
@@ -701,8 +702,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
     pub(super) fn maybe_forward_track_caller(
         &mut self,
         span: Span,
-        outer_hir_id: hir::HirId,
-        inner_hir_id: hir::HirId,
+        outer_hir_id: HirId,
+        inner_hir_id: HirId,
     ) {
         if self.tcx.features().async_fn_track_caller
             && let Some(attrs) = self.attrs.get(&outer_hir_id.local_id)
@@ -1048,7 +1049,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
         binder: &ClosureBinder,
         capture_clause: CaptureBy,
         closure_id: NodeId,
-        closure_hir_id: hir::HirId,
+        closure_hir_id: HirId,
         coroutine_kind: CoroutineKind,
         decl: &FnDecl,
         body: &Expr,
@@ -2036,7 +2037,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
         &mut self,
         sp: Span,
         ident: Ident,
-        binding: hir::HirId,
+        binding: HirId,
     ) -> &'hir hir::Expr<'hir> {
         self.arena.alloc(self.expr_ident_mut(sp, ident, binding))
     }
@@ -2045,7 +2046,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
         &mut self,
         span: Span,
         ident: Ident,
-        binding: hir::HirId,
+        binding: HirId,
     ) -> hir::Expr<'hir> {
         let hir_id = self.next_id();
         let res = Res::Local(binding);
diff --git a/compiler/rustc_ast_lowering/src/index.rs b/compiler/rustc_ast_lowering/src/index.rs
index 4c552289a81..93be9b9b8cf 100644
--- a/compiler/rustc_ast_lowering/src/index.rs
+++ b/compiler/rustc_ast_lowering/src/index.rs
@@ -385,4 +385,21 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
     fn visit_pattern_type_pattern(&mut self, p: &'hir hir::Pat<'hir>) {
         self.visit_pat(p)
     }
+
+    fn visit_precise_capturing_arg(
+        &mut self,
+        arg: &'hir PreciseCapturingArg<'hir>,
+    ) -> Self::Result {
+        match arg {
+            PreciseCapturingArg::Lifetime(_) => {
+                // This is represented as a `Node::Lifetime`, intravisit will get to it below.
+            }
+            PreciseCapturingArg::Param(param) => self.insert(
+                param.ident.span,
+                param.hir_id,
+                Node::PreciseCapturingNonLifetimeArg(param),
+            ),
+        }
+        intravisit::walk_precise_capturing_arg(self, arg);
+    }
 }
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index 5005c22d4cc..d6e62462b98 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -48,6 +48,7 @@ use rustc_ast::{self as ast, *};
 use rustc_ast_pretty::pprust;
 use rustc_data_structures::captures::Captures;
 use rustc_data_structures::fingerprint::Fingerprint;
+use rustc_data_structures::fx::FxIndexSet;
 use rustc_data_structures::sorted_map::SortedMap;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_data_structures::sync::Lrc;
@@ -56,7 +57,7 @@ use rustc_hir as hir;
 use rustc_hir::def::{DefKind, LifetimeRes, Namespace, PartialRes, PerNS, Res};
 use rustc_hir::def_id::{LocalDefId, LocalDefIdMap, CRATE_DEF_ID, LOCAL_CRATE};
 use rustc_hir::{
-    ConstArg, GenericArg, ItemLocalMap, MissingLifetimeKind, ParamName, TraitCandidate,
+    ConstArg, GenericArg, HirId, ItemLocalMap, MissingLifetimeKind, ParamName, TraitCandidate,
 };
 use rustc_index::{Idx, IndexSlice, IndexVec};
 use rustc_macros::extension;
@@ -107,7 +108,7 @@ struct LoweringContext<'a, 'hir> {
 
     /// When inside an `async` context, this is the `HirId` of the
     /// `task_context` local bound to the resume argument of the coroutine.
-    task_context: Option<hir::HirId>,
+    task_context: Option<HirId>,
 
     /// Used to get the current `fn`'s def span to point to when using `await`
     /// outside of an `async fn`.
@@ -661,18 +662,16 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
     /// `HirIdValidator` later on, which makes sure that all `NodeId`s got mapped
     /// properly. Calling the method twice with the same `NodeId` is fine though.
     #[instrument(level = "debug", skip(self), ret)]
-    fn lower_node_id(&mut self, ast_node_id: NodeId) -> hir::HirId {
+    fn lower_node_id(&mut self, ast_node_id: NodeId) -> HirId {
         assert_ne!(ast_node_id, DUMMY_NODE_ID);
 
         match self.node_id_to_local_id.entry(ast_node_id) {
-            Entry::Occupied(o) => {
-                hir::HirId { owner: self.current_hir_id_owner, local_id: *o.get() }
-            }
+            Entry::Occupied(o) => HirId { owner: self.current_hir_id_owner, local_id: *o.get() },
             Entry::Vacant(v) => {
                 // Generate a new `HirId`.
                 let owner = self.current_hir_id_owner;
                 let local_id = self.item_local_id_counter;
-                let hir_id = hir::HirId { owner, local_id };
+                let hir_id = HirId { owner, local_id };
 
                 v.insert(local_id);
                 self.item_local_id_counter.increment_by(1);
@@ -693,12 +692,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
 
     /// Generate a new `HirId` without a backing `NodeId`.
     #[instrument(level = "debug", skip(self), ret)]
-    fn next_id(&mut self) -> hir::HirId {
+    fn next_id(&mut self) -> HirId {
         let owner = self.current_hir_id_owner;
         let local_id = self.item_local_id_counter;
         assert_ne!(local_id, hir::ItemLocalId::ZERO);
         self.item_local_id_counter.increment_by(1);
-        hir::HirId { owner, local_id }
+        HirId { owner, local_id }
     }
 
     #[instrument(level = "trace", skip(self))]
@@ -706,7 +705,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         let res: Result<Res, ()> = res.apply_id(|id| {
             let owner = self.current_hir_id_owner;
             let local_id = self.node_id_to_local_id.get(&id).copied().ok_or(())?;
-            Ok(hir::HirId { owner, local_id })
+            Ok(HirId { owner, local_id })
         });
         trace!(?res);
 
@@ -889,7 +888,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         ret
     }
 
-    fn lower_attrs(&mut self, id: hir::HirId, attrs: &[Attribute]) -> Option<&'hir [Attribute]> {
+    fn lower_attrs(&mut self, id: HirId, attrs: &[Attribute]) -> Option<&'hir [Attribute]> {
         if attrs.is_empty() {
             None
         } else {
@@ -921,7 +920,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         Attribute { kind, id: attr.id, style: attr.style, span: self.lower_span(attr.span) }
     }
 
-    fn alias_attrs(&mut self, id: hir::HirId, target_id: hir::HirId) {
+    fn alias_attrs(&mut self, id: HirId, target_id: HirId) {
         debug_assert_eq!(id.owner, self.current_hir_id_owner);
         debug_assert_eq!(target_id.owner, self.current_hir_id_owner);
         if let Some(&a) = self.attrs.get(&target_id.local_id) {
@@ -1398,7 +1397,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                 });
                 hir::TyKind::TraitObject(bounds, lifetime_bound, *kind)
             }
-            TyKind::ImplTrait(def_node_id, bounds) => {
+            TyKind::ImplTrait(def_node_id, bounds, precise_capturing) => {
                 let span = t.span;
                 match itctx {
                     ImplTraitContext::OpaqueTy { origin, fn_kind } => self.lower_opaque_impl_trait(
@@ -1408,8 +1407,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                         bounds,
                         fn_kind,
                         itctx,
+                        precise_capturing.as_deref().map(|(args, _)| args.as_slice()),
                     ),
                     ImplTraitContext::Universal => {
+                        if let Some(&(_, span)) = precise_capturing.as_deref() {
+                            self.tcx.dcx().emit_err(errors::NoPreciseCapturesOnApit { span });
+                        };
                         let span = t.span;
 
                         // HACK: pprust breaks strings with newlines when the type
@@ -1520,6 +1523,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         bounds: &GenericBounds,
         fn_kind: Option<FnDeclKind>,
         itctx: ImplTraitContext,
+        precise_capturing_args: Option<&[PreciseCapturingArg]>,
     ) -> hir::TyKind<'hir> {
         // Make sure we know that some funky desugaring has been going on here.
         // This is a first: there is code in other places like for loop
@@ -1528,42 +1532,59 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         // frequently opened issues show.
         let opaque_ty_span = self.mark_span_with_reason(DesugaringKind::OpaqueTy, span, None);
 
-        let captured_lifetimes_to_duplicate = match origin {
-            hir::OpaqueTyOrigin::TyAlias { .. } => {
-                // type alias impl trait and associated type position impl trait were
-                // decided to capture all in-scope lifetimes, which we collect for
-                // all opaques during resolution.
-                self.resolver
-                    .take_extra_lifetime_params(opaque_ty_node_id)
-                    .into_iter()
-                    .map(|(ident, id, _)| Lifetime { id, ident })
+        let captured_lifetimes_to_duplicate =
+            if let Some(precise_capturing) = precise_capturing_args {
+                // We'll actually validate these later on; all we need is the list of
+                // lifetimes to duplicate during this portion of lowering.
+                precise_capturing
+                    .iter()
+                    .filter_map(|arg| match arg {
+                        PreciseCapturingArg::Lifetime(lt) => Some(*lt),
+                        PreciseCapturingArg::Arg(..) => None,
+                    })
+                    // Add in all the lifetimes mentioned in the bounds. We will error
+                    // them out later, but capturing them here is important to make sure
+                    // they actually get resolved in resolve_bound_vars.
+                    .chain(lifetime_collector::lifetimes_in_bounds(self.resolver, bounds))
                     .collect()
-            }
-            hir::OpaqueTyOrigin::FnReturn(..) => {
-                if matches!(
-                    fn_kind.expect("expected RPITs to be lowered with a FnKind"),
-                    FnDeclKind::Impl | FnDeclKind::Trait
-                ) || self.tcx.features().lifetime_capture_rules_2024
-                    || span.at_least_rust_2024()
-                {
-                    // return-position impl trait in trait was decided to capture all
-                    // in-scope lifetimes, which we collect for all opaques during resolution.
-                    self.resolver
-                        .take_extra_lifetime_params(opaque_ty_node_id)
-                        .into_iter()
-                        .map(|(ident, id, _)| Lifetime { id, ident })
-                        .collect()
-                } else {
-                    // in fn return position, like the `fn test<'a>() -> impl Debug + 'a`
-                    // example, we only need to duplicate lifetimes that appear in the
-                    // bounds, since those are the only ones that are captured by the opaque.
-                    lifetime_collector::lifetimes_in_bounds(self.resolver, bounds)
+            } else {
+                match origin {
+                    hir::OpaqueTyOrigin::TyAlias { .. } => {
+                        // type alias impl trait and associated type position impl trait were
+                        // decided to capture all in-scope lifetimes, which we collect for
+                        // all opaques during resolution.
+                        self.resolver
+                            .take_extra_lifetime_params(opaque_ty_node_id)
+                            .into_iter()
+                            .map(|(ident, id, _)| Lifetime { id, ident })
+                            .collect()
+                    }
+                    hir::OpaqueTyOrigin::FnReturn(..) => {
+                        if matches!(
+                            fn_kind.expect("expected RPITs to be lowered with a FnKind"),
+                            FnDeclKind::Impl | FnDeclKind::Trait
+                        ) || self.tcx.features().lifetime_capture_rules_2024
+                            || span.at_least_rust_2024()
+                        {
+                            // return-position impl trait in trait was decided to capture all
+                            // in-scope lifetimes, which we collect for all opaques during resolution.
+                            self.resolver
+                                .take_extra_lifetime_params(opaque_ty_node_id)
+                                .into_iter()
+                                .map(|(ident, id, _)| Lifetime { id, ident })
+                                .collect()
+                        } else {
+                            // in fn return position, like the `fn test<'a>() -> impl Debug + 'a`
+                            // example, we only need to duplicate lifetimes that appear in the
+                            // bounds, since those are the only ones that are captured by the opaque.
+                            lifetime_collector::lifetimes_in_bounds(self.resolver, bounds)
+                        }
+                    }
+                    hir::OpaqueTyOrigin::AsyncFn(..) => {
+                        unreachable!("should be using `lower_async_fn_ret_ty`")
+                    }
                 }
-            }
-            hir::OpaqueTyOrigin::AsyncFn(..) => {
-                unreachable!("should be using `lower_async_fn_ret_ty`")
-            }
-        };
+            };
         debug!(?captured_lifetimes_to_duplicate);
 
         self.lower_opaque_inner(
@@ -1573,6 +1594,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             captured_lifetimes_to_duplicate,
             span,
             opaque_ty_span,
+            precise_capturing_args,
             |this| this.lower_param_bounds(bounds, itctx),
         )
     }
@@ -1582,9 +1604,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         opaque_ty_node_id: NodeId,
         origin: hir::OpaqueTyOrigin,
         in_trait: bool,
-        captured_lifetimes_to_duplicate: Vec<Lifetime>,
+        captured_lifetimes_to_duplicate: FxIndexSet<Lifetime>,
         span: Span,
         opaque_ty_span: Span,
+        precise_capturing_args: Option<&[PreciseCapturingArg]>,
         lower_item_bounds: impl FnOnce(&mut Self) -> &'hir [hir::GenericBound<'hir>],
     ) -> hir::TyKind<'hir> {
         let opaque_ty_def_id = self.create_def(
@@ -1671,8 +1694,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             // Install the remapping from old to new (if any). This makes sure that
             // any lifetimes that would have resolved to the def-id of captured
             // lifetimes are remapped to the new *synthetic* lifetimes of the opaque.
-            let bounds = this
-                .with_remapping(captured_to_synthesized_mapping, |this| lower_item_bounds(this));
+            let (bounds, precise_capturing_args) =
+                this.with_remapping(captured_to_synthesized_mapping, |this| {
+                    (
+                        lower_item_bounds(this),
+                        precise_capturing_args.map(|precise_capturing| {
+                            this.lower_precise_capturing_args(precise_capturing)
+                        }),
+                    )
+                });
 
             let generic_params =
                 this.arena.alloc_from_iter(synthesized_lifetime_definitions.iter().map(
@@ -1717,6 +1747,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                 origin,
                 lifetime_mapping,
                 in_trait,
+                precise_capturing_args,
             };
 
             // Generate an `type Foo = impl Trait;` declaration.
@@ -1749,6 +1780,30 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         )
     }
 
+    fn lower_precise_capturing_args(
+        &mut self,
+        precise_capturing_args: &[PreciseCapturingArg],
+    ) -> &'hir [hir::PreciseCapturingArg<'hir>] {
+        self.arena.alloc_from_iter(precise_capturing_args.iter().map(|arg| match arg {
+            PreciseCapturingArg::Lifetime(lt) => {
+                hir::PreciseCapturingArg::Lifetime(self.lower_lifetime(lt))
+            }
+            PreciseCapturingArg::Arg(path, id) => {
+                let [segment] = path.segments.as_slice() else {
+                    panic!();
+                };
+                let res = self.resolver.get_partial_res(*id).map_or(Res::Err, |partial_res| {
+                    partial_res.full_res().expect("no partial res expected for precise capture arg")
+                });
+                hir::PreciseCapturingArg::Param(hir::PreciseCapturingNonLifetimeArg {
+                    hir_id: self.lower_node_id(*id),
+                    ident: self.lower_ident(segment.ident),
+                    res: self.lower_res(res),
+                })
+            }
+        }))
+    }
+
     fn lower_fn_params_to_names(&mut self, decl: &FnDecl) -> &'hir [Ident] {
         self.arena.alloc_from_iter(decl.inputs.iter().map(|param| match param.pat.kind {
             PatKind::Ident(_, ident, _) => self.lower_ident(ident),
@@ -1889,7 +1944,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         let opaque_ty_span =
             self.mark_span_with_reason(DesugaringKind::Async, span, allowed_features);
 
-        let captured_lifetimes: Vec<_> = self
+        let captured_lifetimes = self
             .resolver
             .take_extra_lifetime_params(opaque_ty_node_id)
             .into_iter()
@@ -1903,6 +1958,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             captured_lifetimes,
             span,
             opaque_ty_span,
+            None,
             |this| {
                 let bound = this.lower_coroutine_fn_output_type_to_bound(
                     output,
@@ -2421,11 +2477,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         self.pat(span, hir::PatKind::Struct(qpath, fields, false))
     }
 
-    fn pat_ident(&mut self, span: Span, ident: Ident) -> (&'hir hir::Pat<'hir>, hir::HirId) {
+    fn pat_ident(&mut self, span: Span, ident: Ident) -> (&'hir hir::Pat<'hir>, HirId) {
         self.pat_ident_binding_mode(span, ident, hir::BindingAnnotation::NONE)
     }
 
-    fn pat_ident_mut(&mut self, span: Span, ident: Ident) -> (hir::Pat<'hir>, hir::HirId) {
+    fn pat_ident_mut(&mut self, span: Span, ident: Ident) -> (hir::Pat<'hir>, HirId) {
         self.pat_ident_binding_mode_mut(span, ident, hir::BindingAnnotation::NONE)
     }
 
@@ -2434,7 +2490,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         span: Span,
         ident: Ident,
         bm: hir::BindingAnnotation,
-    ) -> (&'hir hir::Pat<'hir>, hir::HirId) {
+    ) -> (&'hir hir::Pat<'hir>, HirId) {
         let (pat, hir_id) = self.pat_ident_binding_mode_mut(span, ident, bm);
         (self.arena.alloc(pat), hir_id)
     }
@@ -2444,7 +2500,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         span: Span,
         ident: Ident,
         bm: hir::BindingAnnotation,
-    ) -> (hir::Pat<'hir>, hir::HirId) {
+    ) -> (hir::Pat<'hir>, HirId) {
         let hir_id = self.next_id();
 
         (
@@ -2476,12 +2532,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         }
     }
 
-    fn ty_path(
-        &mut self,
-        mut hir_id: hir::HirId,
-        span: Span,
-        qpath: hir::QPath<'hir>,
-    ) -> hir::Ty<'hir> {
+    fn ty_path(&mut self, mut hir_id: HirId, span: Span, qpath: hir::QPath<'hir>) -> hir::Ty<'hir> {
         let kind = match qpath {
             hir::QPath::Resolved(None, path) => {
                 // Turn trait object paths into `TyKind::TraitObject` instead.
diff --git a/compiler/rustc_ast_lowering/src/lifetime_collector.rs b/compiler/rustc_ast_lowering/src/lifetime_collector.rs
index 4b1c057cdbf..5456abd489b 100644
--- a/compiler/rustc_ast_lowering/src/lifetime_collector.rs
+++ b/compiler/rustc_ast_lowering/src/lifetime_collector.rs
@@ -1,6 +1,7 @@
 use super::ResolverAstLoweringExt;
 use rustc_ast::visit::{self, BoundKind, LifetimeCtxt, Visitor};
 use rustc_ast::{GenericBounds, Lifetime, NodeId, PathSegment, PolyTraitRef, Ty, TyKind};
+use rustc_data_structures::fx::FxIndexSet;
 use rustc_hir::def::{DefKind, LifetimeRes, Res};
 use rustc_middle::span_bug;
 use rustc_middle::ty::ResolverAstLowering;
@@ -10,27 +11,23 @@ use rustc_span::Span;
 struct LifetimeCollectVisitor<'ast> {
     resolver: &'ast ResolverAstLowering,
     current_binders: Vec<NodeId>,
-    collected_lifetimes: Vec<Lifetime>,
+    collected_lifetimes: FxIndexSet<Lifetime>,
 }
 
 impl<'ast> LifetimeCollectVisitor<'ast> {
     fn new(resolver: &'ast ResolverAstLowering) -> Self {
-        Self { resolver, current_binders: Vec::new(), collected_lifetimes: Vec::new() }
+        Self { resolver, current_binders: Vec::new(), collected_lifetimes: FxIndexSet::default() }
     }
 
     fn record_lifetime_use(&mut self, lifetime: Lifetime) {
         match self.resolver.get_lifetime_res(lifetime.id).unwrap_or(LifetimeRes::Error) {
             LifetimeRes::Param { binder, .. } | LifetimeRes::Fresh { binder, .. } => {
                 if !self.current_binders.contains(&binder) {
-                    if !self.collected_lifetimes.contains(&lifetime) {
-                        self.collected_lifetimes.push(lifetime);
-                    }
+                    self.collected_lifetimes.insert(lifetime);
                 }
             }
             LifetimeRes::Static | LifetimeRes::Error => {
-                if !self.collected_lifetimes.contains(&lifetime) {
-                    self.collected_lifetimes.push(lifetime);
-                }
+                self.collected_lifetimes.insert(lifetime);
             }
             LifetimeRes::Infer => {}
             res => {
@@ -111,7 +108,7 @@ impl<'ast> Visitor<'ast> for LifetimeCollectVisitor<'ast> {
 pub(crate) fn lifetimes_in_bounds(
     resolver: &ResolverAstLowering,
     bounds: &GenericBounds,
-) -> Vec<Lifetime> {
+) -> FxIndexSet<Lifetime> {
     let mut visitor = LifetimeCollectVisitor::new(resolver);
     for bound in bounds {
         visitor.visit_param_bound(bound, BoundKind::Bound);
diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs
index cb4dcf3ae75..495e90e967b 100644
--- a/compiler/rustc_ast_passes/src/ast_validation.rs
+++ b/compiler/rustc_ast_passes/src/ast_validation.rs
@@ -737,7 +737,7 @@ impl<'a> AstValidator<'a> {
                     }
                 }
             }
-            TyKind::ImplTrait(_, bounds) => {
+            TyKind::ImplTrait(_, bounds, _) => {
                 if self.is_impl_trait_banned {
                     self.dcx().emit_err(errors::ImplTraitPath { span: ty.span });
                 }
diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs
index d7cd3efe408..70a3ccb0f44 100644
--- a/compiler/rustc_ast_passes/src/feature_gate.rs
+++ b/compiler/rustc_ast_passes/src/feature_gate.rs
@@ -569,6 +569,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
     gate_all!(fn_delegation, "functions delegation is not yet fully implemented");
     gate_all!(postfix_match, "postfix match is experimental");
     gate_all!(mut_ref, "mutable by-reference bindings are experimental");
+    gate_all!(precise_capturing, "precise captures on `impl Trait` are experimental");
 
     if !visitor.features.never_patterns {
         if let Some(spans) = spans.get(&sym::never_patterns) {
diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs
index 51ccfe89fbd..242335f769c 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state.rs
@@ -893,7 +893,7 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
             token::Comma => ",".into(),
             token::Semi => ";".into(),
             token::Colon => ":".into(),
-            token::ModSep => "::".into(),
+            token::PathSep => "::".into(),
             token::RArrow => "->".into(),
             token::LArrow => "<-".into(),
             token::FatArrow => "=>".into(),
@@ -1150,8 +1150,17 @@ impl<'a> State<'a> {
                 }
                 self.print_type_bounds(bounds);
             }
-            ast::TyKind::ImplTrait(_, bounds) => {
+            ast::TyKind::ImplTrait(_, bounds, precise_capturing_args) => {
                 self.word_nbsp("impl");
+                if let Some((precise_capturing_args, ..)) = precise_capturing_args.as_deref() {
+                    self.word("use");
+                    self.word("<");
+                    self.commasep(Inconsistent, precise_capturing_args, |s, arg| match arg {
+                        ast::PreciseCapturingArg::Arg(p, _) => s.print_path(p, false, 0),
+                        ast::PreciseCapturingArg::Lifetime(lt) => s.print_lifetime(*lt),
+                    });
+                    self.word(">")
+                }
                 self.print_type_bounds(bounds);
             }
             ast::TyKind::Array(ty, length) => {
diff --git a/compiler/rustc_ast_pretty/src/pprust/tests.rs b/compiler/rustc_ast_pretty/src/pprust/tests.rs
index 3b2b60a86f0..5b5ffbc6f88 100644
--- a/compiler/rustc_ast_pretty/src/pprust/tests.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/tests.rs
@@ -3,6 +3,7 @@ use super::*;
 use rustc_ast as ast;
 use rustc_span::create_default_session_globals_then;
 use rustc_span::symbol::Ident;
+use rustc_span::DUMMY_SP;
 use thin_vec::ThinVec;
 
 fn fun_to_string(
@@ -28,10 +29,7 @@ fn test_fun_to_string() {
     create_default_session_globals_then(|| {
         let abba_ident = Ident::from_str("abba");
 
-        let decl = ast::FnDecl {
-            inputs: ThinVec::new(),
-            output: ast::FnRetTy::Default(rustc_span::DUMMY_SP),
-        };
+        let decl = ast::FnDecl { inputs: ThinVec::new(), output: ast::FnRetTy::Default(DUMMY_SP) };
         let generics = ast::Generics::default();
         assert_eq!(
             fun_to_string(&decl, ast::FnHeader::default(), abba_ident, &generics),
@@ -48,7 +46,7 @@ fn test_variant_to_string() {
         let var = ast::Variant {
             ident,
             vis: ast::Visibility {
-                span: rustc_span::DUMMY_SP,
+                span: DUMMY_SP,
                 kind: ast::VisibilityKind::Inherited,
                 tokens: None,
             },
@@ -56,7 +54,7 @@ fn test_variant_to_string() {
             id: ast::DUMMY_NODE_ID,
             data: ast::VariantData::Unit(ast::DUMMY_NODE_ID),
             disr_expr: None,
-            span: rustc_span::DUMMY_SP,
+            span: DUMMY_SP,
             is_placeholder: false,
         };
 
diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index 0a4f32c9585..8ccf88ec59c 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -1752,32 +1752,31 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         let tcx = self.infcx.tcx;
         let hir = tcx.hir();
         let Some(body_id) = tcx.hir_node(self.mir_hir_id()).body_id() else { return };
-        struct FindUselessClone<'hir> {
-            tcx: TyCtxt<'hir>,
-            def_id: DefId,
-            pub clones: Vec<&'hir hir::Expr<'hir>>,
+
+        struct FindUselessClone<'tcx> {
+            tcx: TyCtxt<'tcx>,
+            typeck_results: &'tcx ty::TypeckResults<'tcx>,
+            pub clones: Vec<&'tcx hir::Expr<'tcx>>,
         }
-        impl<'hir> FindUselessClone<'hir> {
-            pub fn new(tcx: TyCtxt<'hir>, def_id: DefId) -> Self {
-                Self { tcx, def_id, clones: vec![] }
+        impl<'tcx> FindUselessClone<'tcx> {
+            pub fn new(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Self {
+                Self { tcx, typeck_results: tcx.typeck(def_id), clones: vec![] }
             }
         }
-
-        impl<'v> Visitor<'v> for FindUselessClone<'v> {
-            fn visit_expr(&mut self, ex: &'v hir::Expr<'v>) {
-                if let hir::ExprKind::MethodCall(segment, _rcvr, args, _span) = ex.kind
-                    && segment.ident.name == sym::clone
-                    && args.len() == 0
-                    && let Some(def_id) = self.def_id.as_local()
-                    && let Some(method) = self.tcx.lookup_method_for_diagnostic((def_id, ex.hir_id))
-                    && Some(self.tcx.parent(method)) == self.tcx.lang_items().clone_trait()
+        impl<'tcx> Visitor<'tcx> for FindUselessClone<'tcx> {
+            fn visit_expr(&mut self, ex: &'tcx hir::Expr<'tcx>) {
+                if let hir::ExprKind::MethodCall(..) = ex.kind
+                    && let Some(method_def_id) =
+                        self.typeck_results.type_dependent_def_id(ex.hir_id)
+                    && self.tcx.lang_items().clone_trait() == Some(self.tcx.parent(method_def_id))
                 {
                     self.clones.push(ex);
                 }
                 hir::intravisit::walk_expr(self, ex);
             }
         }
-        let mut expr_finder = FindUselessClone::new(tcx, self.mir_def_id().into());
+
+        let mut expr_finder = FindUselessClone::new(tcx, self.mir_def_id());
 
         let body = hir.body(body_id).value;
         expr_finder.visit_expr(body);
diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
index 304d41d6941..2fe75fe2a2b 100644
--- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
@@ -26,7 +26,6 @@ use rustc_middle::ty::{self, RegionVid, Ty};
 use rustc_middle::ty::{Region, TyCtxt};
 use rustc_span::symbol::{kw, Ident};
 use rustc_span::Span;
-use rustc_trait_selection::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use rustc_trait_selection::infer::InferCtxtExt;
 use rustc_trait_selection::traits::{Obligation, ObligationCtxt};
 
@@ -813,7 +812,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
         self.add_static_impl_trait_suggestion(&mut diag, *fr, fr_name, *outlived_fr);
         self.suggest_adding_lifetime_params(&mut diag, *fr, *outlived_fr);
         self.suggest_move_on_borrowing_closure(&mut diag);
-        self.suggest_deref_closure_value(&mut diag);
+        self.suggest_deref_closure_return(&mut diag);
 
         diag
     }
@@ -1048,125 +1047,111 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
     /// When encountering a lifetime error caused by the return type of a closure, check the
     /// corresponding trait bound and see if dereferencing the closure return value would satisfy
     /// them. If so, we produce a structured suggestion.
-    fn suggest_deref_closure_value(&self, diag: &mut Diag<'_>) {
+    fn suggest_deref_closure_return(&self, diag: &mut Diag<'_>) {
         let tcx = self.infcx.tcx;
-        let map = tcx.hir();
 
         // Get the closure return value and type.
-        let body_id = map.body_owned_by(self.mir_def_id());
-        let body = &map.body(body_id);
-        let value = &body.value.peel_blocks();
-        let hir::Node::Expr(closure_expr) = tcx.hir_node_by_def_id(self.mir_def_id()) else {
+        let closure_def_id = self.mir_def_id();
+        let hir::Node::Expr(
+            closure_expr @ hir::Expr {
+                kind: hir::ExprKind::Closure(hir::Closure { body, .. }), ..
+            },
+        ) = tcx.hir_node_by_def_id(closure_def_id)
+        else {
+            return;
+        };
+        let ty::Closure(_, args) = *tcx.type_of(closure_def_id).instantiate_identity().kind()
+        else {
+            return;
+        };
+        let args = args.as_closure();
+
+        // Make sure that the parent expression is a method call.
+        let parent_expr_id = tcx.parent_hir_id(self.mir_hir_id());
+        let hir::Node::Expr(
+            parent_expr @ hir::Expr {
+                kind: hir::ExprKind::MethodCall(_, rcvr, call_args, _), ..
+            },
+        ) = tcx.hir_node(parent_expr_id)
+        else {
             return;
         };
-        let fn_call_id = tcx.parent_hir_id(self.mir_hir_id());
-        let hir::Node::Expr(expr) = tcx.hir_node(fn_call_id) else { return };
-        let def_id = map.enclosing_body_owner(fn_call_id);
-        let tables = tcx.typeck(def_id);
-        let Some(return_value_ty) = tables.node_type_opt(value.hir_id) else { return };
-        let return_value_ty = self.infcx.resolve_vars_if_possible(return_value_ty);
+        let typeck_results = tcx.typeck(self.mir_def_id());
 
         // We don't use `ty.peel_refs()` to get the number of `*`s needed to get the root type.
-        let mut ty = return_value_ty;
+        let liberated_sig = tcx.liberate_late_bound_regions(closure_def_id.to_def_id(), args.sig());
+        let mut peeled_ty = liberated_sig.output();
         let mut count = 0;
-        while let ty::Ref(_, t, _) = ty.kind() {
-            ty = *t;
+        while let ty::Ref(_, ref_ty, _) = *peeled_ty.kind() {
+            peeled_ty = ref_ty;
             count += 1;
         }
-        if !self.infcx.type_is_copy_modulo_regions(self.param_env, ty) {
+        if !self.infcx.type_is_copy_modulo_regions(self.param_env, peeled_ty) {
             return;
         }
 
         // Build a new closure where the return type is an owned value, instead of a ref.
-        let Some(ty::Closure(did, args)) =
-            tables.node_type_opt(closure_expr.hir_id).as_ref().map(|ty| ty.kind())
-        else {
-            return;
-        };
-        let sig = args.as_closure().sig();
         let closure_sig_as_fn_ptr_ty = Ty::new_fn_ptr(
             tcx,
-            sig.map_bound(|s| {
-                let unsafety = hir::Unsafety::Normal;
-                use rustc_target::spec::abi;
-                tcx.mk_fn_sig(
-                    [s.inputs()[0]],
-                    s.output().peel_refs(),
-                    s.c_variadic,
-                    unsafety,
-                    abi::Abi::Rust,
-                )
-            }),
+            ty::Binder::dummy(tcx.mk_fn_sig(
+                liberated_sig.inputs().iter().copied(),
+                peeled_ty,
+                liberated_sig.c_variadic,
+                hir::Unsafety::Normal,
+                rustc_target::spec::abi::Abi::Rust,
+            )),
         );
-        let parent_args = GenericArgs::identity_for_item(
+        let closure_ty = Ty::new_closure(
             tcx,
-            tcx.typeck_root_def_id(self.mir_def_id().to_def_id()),
-        );
-        let closure_kind = args.as_closure().kind();
-        let closure_kind_ty = Ty::from_closure_kind(tcx, closure_kind);
-        let tupled_upvars_ty = self.infcx.next_ty_var(TypeVariableOrigin {
-            kind: TypeVariableOriginKind::ClosureSynthetic,
-            span: closure_expr.span,
-        });
-        let closure_args = ty::ClosureArgs::new(
-            tcx,
-            ty::ClosureArgsParts {
-                parent_args,
-                closure_kind_ty,
-                closure_sig_as_fn_ptr_ty,
-                tupled_upvars_ty,
-            },
+            closure_def_id.to_def_id(),
+            ty::ClosureArgs::new(
+                tcx,
+                ty::ClosureArgsParts {
+                    parent_args: args.parent_args(),
+                    closure_kind_ty: args.kind_ty(),
+                    tupled_upvars_ty: args.tupled_upvars_ty(),
+                    closure_sig_as_fn_ptr_ty,
+                },
+            )
+            .args,
         );
-        let closure_ty = Ty::new_closure(tcx, *did, closure_args.args);
-        let closure_ty = tcx.erase_regions(closure_ty);
-
-        let hir::ExprKind::MethodCall(_, rcvr, args, _) = expr.kind else { return };
-        let Some(pos) = args
-            .iter()
-            .enumerate()
-            .find(|(_, arg)| arg.hir_id == closure_expr.hir_id)
-            .map(|(i, _)| i)
-        else {
-            return;
-        };
-        // The found `Self` type of the method call.
-        let Some(possible_rcvr_ty) = tables.node_type_opt(rcvr.hir_id) else { return };
 
-        // The `MethodCall` expression is `Res::Err`, so we search for the method on the `rcvr_ty`.
-        let Some(method) = tcx.lookup_method_for_diagnostic((self.mir_def_id(), expr.hir_id))
+        let Some((closure_arg_pos, _)) =
+            call_args.iter().enumerate().find(|(_, arg)| arg.hir_id == closure_expr.hir_id)
         else {
             return;
         };
-
         // Get the type for the parameter corresponding to the argument the closure with the
         // lifetime error we had.
-        let Some(input) = tcx
-            .fn_sig(method)
-            .instantiate_identity()
+        let Some(method_def_id) = typeck_results.type_dependent_def_id(parent_expr.hir_id) else {
+            return;
+        };
+        let Some(input_arg) = tcx
+            .fn_sig(method_def_id)
+            .skip_binder()
             .inputs()
             .skip_binder()
             // Methods have a `self` arg, so `pos` is actually `+ 1` to match the method call arg.
-            .get(pos + 1)
+            .get(closure_arg_pos + 1)
         else {
             return;
         };
-
-        trace!(?input);
-
-        let ty::Param(closure_param) = input.kind() else { return };
+        // If this isn't a param, then we can't substitute a new closure.
+        let ty::Param(closure_param) = input_arg.kind() else { return };
 
         // Get the arguments for the found method, only specifying that `Self` is the receiver type.
-        let args = GenericArgs::for_item(tcx, method, |param, _| {
+        let Some(possible_rcvr_ty) = typeck_results.node_type_opt(rcvr.hir_id) else { return };
+        let args = GenericArgs::for_item(tcx, method_def_id, |param, _| {
             if param.index == 0 {
                 possible_rcvr_ty.into()
             } else if param.index == closure_param.index {
                 closure_ty.into()
             } else {
-                self.infcx.var_for_def(expr.span, param)
+                self.infcx.var_for_def(parent_expr.span, param)
             }
         });
 
-        let preds = tcx.predicates_of(method).instantiate(tcx, args);
+        let preds = tcx.predicates_of(method_def_id).instantiate(tcx, args);
 
         let ocx = ObligationCtxt::new(&self.infcx);
         ocx.register_obligations(preds.iter().map(|(pred, span)| {
@@ -1176,7 +1161,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
 
         if ocx.select_all_or_error().is_empty() {
             diag.span_suggestion_verbose(
-                value.span.shrink_to_lo(),
+                tcx.hir().body(*body).value.peel_blocks().span.shrink_to_lo(),
                 "dereference the return value",
                 "*".repeat(count),
                 Applicability::MachineApplicable,
diff --git a/compiler/rustc_borrowck/src/region_infer/graphviz.rs b/compiler/rustc_borrowck/src/region_infer/graphviz.rs
index c103ba3c407..f145d30fe38 100644
--- a/compiler/rustc_borrowck/src/region_infer/graphviz.rs
+++ b/compiler/rustc_borrowck/src/region_infer/graphviz.rs
@@ -6,7 +6,38 @@ use std::borrow::Cow;
 use std::io::{self, Write};
 
 use super::*;
+use itertools::Itertools;
 use rustc_graphviz as dot;
+use rustc_middle::ty::UniverseIndex;
+
+fn render_outlives_constraint(constraint: &OutlivesConstraint<'_>) -> String {
+    match constraint.locations {
+        Locations::All(_) => "All(...)".to_string(),
+        Locations::Single(loc) => format!("{loc:?}"),
+    }
+}
+
+fn render_universe(u: UniverseIndex) -> String {
+    if u.is_root() {
+        return "".to_string();
+    }
+
+    format!("/{:?}", u)
+}
+
+fn render_region_vid(rvid: RegionVid, regioncx: &RegionInferenceContext<'_>) -> String {
+    let universe_str = render_universe(regioncx.region_definition(rvid).universe);
+
+    let external_name_str = if let Some(external_name) =
+        regioncx.region_definition(rvid).external_name.and_then(|e| e.get_name())
+    {
+        format!(" ({external_name})")
+    } else {
+        "".to_string()
+    };
+
+    format!("{:?}{universe_str}{external_name_str}", rvid)
+}
 
 impl<'tcx> RegionInferenceContext<'tcx> {
     /// Write out the region constraint graph.
@@ -46,10 +77,10 @@ impl<'a, 'this, 'tcx> dot::Labeller<'this> for RawConstraints<'a, 'tcx> {
         Some(dot::LabelText::LabelStr(Cow::Borrowed("box")))
     }
     fn node_label(&'this self, n: &RegionVid) -> dot::LabelText<'this> {
-        dot::LabelText::LabelStr(format!("{n:?}").into())
+        dot::LabelText::LabelStr(render_region_vid(*n, self.regioncx).into())
     }
     fn edge_label(&'this self, e: &OutlivesConstraint<'tcx>) -> dot::LabelText<'this> {
-        dot::LabelText::LabelStr(format!("{:?}", e.locations).into())
+        dot::LabelText::LabelStr(render_outlives_constraint(e).into())
     }
 }
 
@@ -96,8 +127,9 @@ impl<'a, 'this, 'tcx> dot::Labeller<'this> for SccConstraints<'a, 'tcx> {
         Some(dot::LabelText::LabelStr(Cow::Borrowed("box")))
     }
     fn node_label(&'this self, n: &ConstraintSccIndex) -> dot::LabelText<'this> {
-        let nodes = &self.nodes_per_scc[*n];
-        dot::LabelText::LabelStr(format!("{n:?} = {nodes:?}").into())
+        let nodes_str =
+            self.nodes_per_scc[*n].iter().map(|n| render_region_vid(*n, self.regioncx)).join(", ");
+        dot::LabelText::LabelStr(format!("SCC({n}) = {{{nodes_str}}}", n = n.as_usize()).into())
     }
 }
 
diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs
index 599f7dd18c3..dd75548a15d 100644
--- a/compiler/rustc_borrowck/src/region_infer/mod.rs
+++ b/compiler/rustc_borrowck/src/region_infer/mod.rs
@@ -1562,7 +1562,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
 
         // Because this free region must be in the ROOT universe, we
         // know it cannot contain any bound universes.
-        assert!(self.scc_universes[longer_fr_scc] == ty::UniverseIndex::ROOT);
+        assert!(self.scc_universes[longer_fr_scc].is_root());
         debug_assert!(self.scc_values.placeholders_contained_in(longer_fr_scc).next().is_none());
 
         // Only check all of the relations for the main representative of each
diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
index 9f0e54febe4..73ba5bee13b 100644
--- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
+++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
@@ -213,7 +213,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
                 let scc = self.constraint_sccs.scc(vid);
 
                 // Special handling of higher-ranked regions.
-                if self.scc_universes[scc] != ty::UniverseIndex::ROOT {
+                if !self.scc_universes[scc].is_root() {
                     match self.scc_values.placeholders_contained_in(scc).enumerate().last() {
                         // If the region contains a single placeholder then they're equal.
                         Some((0, placeholder)) => {
diff --git a/compiler/rustc_borrowck/src/type_check/input_output.rs b/compiler/rustc_borrowck/src/type_check/input_output.rs
index a4c1066ee8e..2511a1535af 100644
--- a/compiler/rustc_borrowck/src/type_check/input_output.rs
+++ b/compiler/rustc_borrowck/src/type_check/input_output.rs
@@ -11,7 +11,7 @@ use std::assert_matches::assert_matches;
 
 use itertools::Itertools;
 use rustc_hir as hir;
-use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
+use rustc_infer::infer::type_variable::TypeVariableOrigin;
 use rustc_infer::infer::{BoundRegionConversionTime, RegionVariableOrigin};
 use rustc_middle::mir::*;
 use rustc_middle::ty::{self, Ty};
@@ -75,10 +75,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
             );
 
             let next_ty_var = || {
-                self.infcx.next_ty_var(TypeVariableOrigin {
-                    span: body.span,
-                    kind: TypeVariableOriginKind::MiscVariable,
-                })
+                self.infcx.next_ty_var(TypeVariableOrigin { span: body.span, param_def_id: None })
             };
             let output_ty = Ty::new_coroutine(
                 self.tcx(),
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index 71b54a761a2..0600a105459 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -16,7 +16,7 @@ use rustc_index::{IndexSlice, IndexVec};
 use rustc_infer::infer::canonical::QueryRegionConstraints;
 use rustc_infer::infer::outlives::env::RegionBoundPairs;
 use rustc_infer::infer::region_constraints::RegionConstraintData;
-use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
+use rustc_infer::infer::type_variable::TypeVariableOrigin;
 use rustc_infer::infer::{
     BoundRegion, BoundRegionConversionTime, InferCtxt, NllRegionVariableOrigin,
 };
@@ -2425,7 +2425,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                     ty::RawPtr(_, _) | ty::FnPtr(_) => {
                         let ty_right = right.ty(body, tcx);
                         let common_ty = self.infcx.next_ty_var(TypeVariableOrigin {
-                            kind: TypeVariableOriginKind::MiscVariable,
+                            param_def_id: None,
                             span: body.source_info(location).span,
                         });
                         self.sub_types(
diff --git a/compiler/rustc_borrowck/src/type_check/relate_tys.rs b/compiler/rustc_borrowck/src/type_check/relate_tys.rs
index 78609a482ed..d67ede57e78 100644
--- a/compiler/rustc_borrowck/src/type_check/relate_tys.rs
+++ b/compiler/rustc_borrowck/src/type_check/relate_tys.rs
@@ -1,6 +1,6 @@
 use rustc_data_structures::fx::FxHashMap;
 use rustc_errors::ErrorGuaranteed;
-use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
+use rustc_infer::infer::type_variable::TypeVariableOrigin;
 use rustc_infer::infer::NllRegionVariableOrigin;
 use rustc_infer::infer::{ObligationEmittingRelation, StructurallyRelateAliases};
 use rustc_infer::traits::{Obligation, PredicateObligations};
@@ -129,10 +129,7 @@ impl<'me, 'bccx, 'tcx> NllTypeRelating<'me, 'bccx, 'tcx> {
         // the opaque.
         let mut enable_subtyping = |ty, opaque_is_expected| {
             let ty_vid = infcx.next_ty_var_id_in_universe(
-                TypeVariableOrigin {
-                    kind: TypeVariableOriginKind::MiscVariable,
-                    span: self.span(),
-                },
+                TypeVariableOrigin { param_def_id: None, span: self.span() },
                 ty::UniverseIndex::ROOT,
             );
 
@@ -437,7 +434,7 @@ impl<'bccx, 'tcx> TypeRelation<'tcx> for NllTypeRelating<'_, 'bccx, 'tcx> {
         a: ty::Const<'tcx>,
         b: ty::Const<'tcx>,
     ) -> RelateResult<'tcx, ty::Const<'tcx>> {
-        let a = self.type_checker.infcx.shallow_resolve(a);
+        let a = self.type_checker.infcx.shallow_resolve_const(a);
         assert!(!a.has_non_region_infer(), "unexpected inference var {:?}", a);
         assert!(!b.has_non_region_infer(), "unexpected inference var {:?}", b);
 
diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs b/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs
index 603cefdd386..18883324683 100644
--- a/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs
@@ -8,8 +8,7 @@ use rustc_ast::{self as ast, Expr, GenericArg, GenericParamKind, Generics, SelfK
 use rustc_expand::base::ExtCtxt;
 use rustc_span::source_map::respan;
 use rustc_span::symbol::{kw, Ident, Symbol};
-use rustc_span::Span;
-use rustc_span::DUMMY_SP;
+use rustc_span::{Span, DUMMY_SP};
 use thin_vec::ThinVec;
 
 /// A path, e.g., `::std::option::Option::<i32>` (global). Has support
diff --git a/compiler/rustc_codegen_ssa/Cargo.toml b/compiler/rustc_codegen_ssa/Cargo.toml
index baf10622a6d..f347a7fb0bb 100644
--- a/compiler/rustc_codegen_ssa/Cargo.toml
+++ b/compiler/rustc_codegen_ssa/Cargo.toml
@@ -5,7 +5,7 @@ edition = "2021"
 
 [dependencies]
 # tidy-alphabetical-start
-ar_archive_writer = "0.1.5"
+ar_archive_writer = "0.2.0"
 bitflags = "2.4.1"
 cc = "1.0.90"
 itertools = "0.12"
diff --git a/compiler/rustc_codegen_ssa/src/back/archive.rs b/compiler/rustc_codegen_ssa/src/back/archive.rs
index ef55682d541..d336973d2b9 100644
--- a/compiler/rustc_codegen_ssa/src/back/archive.rs
+++ b/compiler/rustc_codegen_ssa/src/back/archive.rs
@@ -285,14 +285,7 @@ impl<'a> ArArchiveBuilder<'a> {
             .tempfile_in(output.parent().unwrap_or_else(|| Path::new("")))
             .map_err(|err| io_error_context("couldn't create a temp file", err))?;
 
-        write_archive_to_stream(
-            archive_tmpfile.as_file_mut(),
-            &entries,
-            true,
-            archive_kind,
-            true,
-            false,
-        )?;
+        write_archive_to_stream(archive_tmpfile.as_file_mut(), &entries, archive_kind, false)?;
 
         let any_entries = !entries.is_empty();
         drop(entries);
diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs
index e7d6a671e12..b458f325b73 100644
--- a/compiler/rustc_codegen_ssa/src/back/link.rs
+++ b/compiler/rustc_codegen_ssa/src/back/link.rs
@@ -2059,7 +2059,7 @@ fn add_library_search_dirs(cmd: &mut dyn Linker, sess: &Session, self_contained:
 /// Add options making relocation sections in the produced ELF files read-only
 /// and suppressing lazy binding.
 fn add_relro_args(cmd: &mut dyn Linker, sess: &Session) {
-    match sess.opts.unstable_opts.relro_level.unwrap_or(sess.target.relro_level) {
+    match sess.opts.cg.relro_level.unwrap_or(sess.target.relro_level) {
         RelroLevel::Full => cmd.full_relro(),
         RelroLevel::Partial => cmd.partial_relro(),
         RelroLevel::Off => cmd.no_relro(),
@@ -3038,9 +3038,10 @@ fn get_apple_sdk_root(sdk_name: &str) -> Result<String, errors::AppleSdkRootErro
                     || sdkroot.contains("MacOSX.platform") => {}
             "watchsimulator"
                 if sdkroot.contains("WatchOS.platform") || sdkroot.contains("MacOSX.platform") => {}
-            "visionos"
-                if sdkroot.contains("XROS.platform") || sdkroot.contains("MacOSX.platform") => {}
-            "visionossimulator"
+            "xros"
+                if sdkroot.contains("XRSimulator.platform")
+                    || sdkroot.contains("MacOSX.platform") => {}
+            "xrsimulator"
                 if sdkroot.contains("XROS.platform") || sdkroot.contains("MacOSX.platform") => {}
             // Ignore `SDKROOT` if it's not a valid path.
             _ if !p.is_absolute() || p == Path::new("/") || !p.exists() => {}
diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs
index e7f692144ff..c4f062405bb 100644
--- a/compiler/rustc_codegen_ssa/src/back/write.rs
+++ b/compiler/rustc_codegen_ssa/src/back/write.rs
@@ -907,8 +907,6 @@ fn execute_copy_from_cache_work_item<B: ExtraBackendMethods>(
     module: CachedModuleCodegen,
     module_config: &ModuleConfig,
 ) -> WorkItemResult<B> {
-    assert!(module_config.emit_obj != EmitObj::None);
-
     let incr_comp_session_dir = cgcx.incr_comp_session_dir.as_ref().unwrap();
 
     let load_from_incr_comp_dir = |output_path: PathBuf, saved_path: &str| {
@@ -928,12 +926,6 @@ fn execute_copy_from_cache_work_item<B: ExtraBackendMethods>(
         }
     };
 
-    let object = load_from_incr_comp_dir(
-        cgcx.output_filenames.temp_path(OutputType::Object, Some(&module.name)),
-        module.source.saved_files.get("o").unwrap_or_else(|| {
-            cgcx.create_dcx().emit_fatal(errors::NoSavedObjectFile { cgu_name: &module.name })
-        }),
-    );
     let dwarf_object =
         module.source.saved_files.get("dwo").as_ref().and_then(|saved_dwarf_object_file| {
             let dwarf_obj_out = cgcx
@@ -955,9 +947,14 @@ fn execute_copy_from_cache_work_item<B: ExtraBackendMethods>(
         }
     };
 
+    let should_emit_obj = module_config.emit_obj != EmitObj::None;
     let assembly = load_from_incr_cache(module_config.emit_asm, OutputType::Assembly);
     let llvm_ir = load_from_incr_cache(module_config.emit_ir, OutputType::LlvmAssembly);
     let bytecode = load_from_incr_cache(module_config.emit_bc, OutputType::Bitcode);
+    let object = load_from_incr_cache(should_emit_obj, OutputType::Object);
+    if should_emit_obj && object.is_none() {
+        cgcx.create_dcx().emit_fatal(errors::NoSavedObjectFile { cgu_name: &module.name })
+    }
 
     WorkItemResult::Finished(CompiledModule {
         name: module.name,
diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs
index 24f2c50e882..452398e6d82 100644
--- a/compiler/rustc_codegen_ssa/src/mir/block.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/block.rs
@@ -1861,12 +1861,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
 }
 
 enum ReturnDest<'tcx, V> {
-    // Do nothing; the return value is indirect or ignored.
+    /// Do nothing; the return value is indirect or ignored.
     Nothing,
-    // Store the return value to the pointer.
+    /// Store the return value to the pointer.
     Store(PlaceRef<'tcx, V>),
-    // Store an indirect return value to an operand local place.
+    /// Store an indirect return value to an operand local place.
     IndirectOperand(PlaceRef<'tcx, V>, mir::Local),
-    // Store a direct return value to an operand local place.
+    /// Store a direct return value to an operand local place.
     DirectOperand(mir::Local),
 }
diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs
index 827d8fd9417..3aeae5ebf6d 100644
--- a/compiler/rustc_const_eval/src/interpret/machine.rs
+++ b/compiler/rustc_const_eval/src/interpret/machine.rs
@@ -347,8 +347,6 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized {
     /// allocation (because a copy had to be done to adjust things), machine memory will
     /// cache the result. (This relies on `AllocMap::get_or` being able to add the
     /// owned allocation to the map even when the map is shared.)
-    ///
-    /// This must only fail if `alloc` contains provenance.
     fn adjust_allocation<'b>(
         ecx: &InterpCx<'mir, 'tcx, Self>,
         id: AllocId,
@@ -427,6 +425,7 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized {
         _prov: (AllocId, Self::ProvenanceExtra),
         _size: Size,
         _align: Align,
+        _kind: MemoryKind<Self::MemoryKind>,
     ) -> InterpResult<'tcx> {
         Ok(())
     }
diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs
index 9b1d9cf932b..fbb0907f7d0 100644
--- a/compiler/rustc_const_eval/src/interpret/memory.rs
+++ b/compiler/rustc_const_eval/src/interpret/memory.rs
@@ -227,7 +227,6 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         self.allocate_raw_ptr(alloc, kind)
     }
 
-    /// This can fail only if `alloc` contains provenance.
     pub fn allocate_raw_ptr(
         &mut self,
         alloc: Allocation,
@@ -355,6 +354,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             (alloc_id, prov),
             size,
             alloc.align,
+            kind,
         )?;
 
         // Don't forget to remember size and align of this now-dead allocation
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 543996c86ba..a506d10c1d0 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs
@@ -168,7 +168,7 @@ impl<'ck, 'mir, 'tcx> TypeVisitor<TyCtxt<'tcx>> for LocalReturnTyVisitor<'ck, 'm
         match t.kind() {
             ty::FnPtr(_) => {}
             ty::Ref(_, _, hir::Mutability::Mut) => {
-                self.checker.check_op(ops::ty::MutRef(self.kind));
+                self.checker.check_op(ops::mut_ref::MutRef(self.kind));
                 t.super_visit_with(self)
             }
             _ => t.super_visit_with(self),
@@ -331,6 +331,11 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> {
         if self.tcx.is_thread_local_static(def_id) {
             self.tcx.dcx().span_bug(span, "tls access is checked in `Rvalue::ThreadLocalRef`");
         }
+        if let Some(def_id) = def_id.as_local()
+            && let Err(guar) = self.tcx.at(span).check_well_formed(hir::OwnerId { def_id })
+        {
+            self.error_emitted = Some(guar);
+        }
         self.check_op_spanned(ops::StaticAccess, span)
     }
 
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 e87e60f62dc..dda8f3ed87d 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,10 @@ 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::TraitRef;
-use rustc_middle::ty::{suggest_constraining_type_param, Adt, Closure, FnDef, FnPtr, Param, Ty};
-use rustc_middle::ty::{GenericArgKind, GenericArgsRef};
+use rustc_middle::ty::{
+    self, suggest_constraining_type_param, Closure, FnDef, FnPtr, GenericArgKind, GenericArgsRef,
+    Param, TraitRef, Ty,
+};
 use rustc_middle::util::{call_kind, CallDesugaringKind, CallKind};
 use rustc_session::parse::feature_err;
 use rustc_span::symbol::sym;
@@ -123,7 +124,7 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> {
                         );
                     }
                 }
-                Adt(..) => {
+                ty::Adt(..) => {
                     let obligation =
                         Obligation::new(tcx, ObligationCause::dummy(), param_env, trait_ref);
 
@@ -620,7 +621,7 @@ impl<'tcx> NonConstOp<'tcx> for ThreadLocalAccess {
 }
 
 /// Types that cannot appear in the signature or locals of a `const fn`.
-pub mod ty {
+pub mod mut_ref {
     use super::*;
 
     #[derive(Debug)]
diff --git a/compiler/rustc_driver_impl/src/pretty.rs b/compiler/rustc_driver_impl/src/pretty.rs
index c0c6201f73d..40f6f764993 100644
--- a/compiler/rustc_driver_impl/src/pretty.rs
+++ b/compiler/rustc_driver_impl/src/pretty.rs
@@ -24,20 +24,6 @@ struct AstNoAnn;
 
 impl pprust_ast::PpAnn for AstNoAnn {}
 
-struct HirNoAnn<'tcx> {
-    tcx: TyCtxt<'tcx>,
-}
-
-impl<'tcx> pprust_hir::PpAnn for HirNoAnn<'tcx> {
-    fn nested(&self, state: &mut pprust_hir::State<'_>, nested: pprust_hir::Nested) {
-        pprust_hir::PpAnn::nested(
-            &(&self.tcx.hir() as &dyn hir::intravisit::Map<'_>),
-            state,
-            nested,
-        )
-    }
-}
-
 struct AstIdentifiedAnn;
 
 impl pprust_ast::PpAnn for AstIdentifiedAnn {
@@ -300,10 +286,7 @@ pub fn print<'tcx>(sess: &Session, ppm: PpMode, ex: PrintExtra<'tcx>) {
                 )
             };
             match s {
-                PpHirMode::Normal => {
-                    let annotation = HirNoAnn { tcx };
-                    f(&annotation)
-                }
+                PpHirMode::Normal => f(&tcx),
                 PpHirMode::Identified => {
                     let annotation = HirIdentifiedAnn { tcx };
                     f(&annotation)
diff --git a/compiler/rustc_expand/src/proc_macro_server.rs b/compiler/rustc_expand/src/proc_macro_server.rs
index ddc685c9d07..5a66b0fbdef 100644
--- a/compiler/rustc_expand/src/proc_macro_server.rs
+++ b/compiler/rustc_expand/src/proc_macro_server.rs
@@ -208,7 +208,7 @@ impl FromInternal<(TokenStream, &mut Rustc<'_, '_>)> for Vec<TokenTree<TokenStre
                 Comma => op(","),
                 Semi => op(";"),
                 Colon => op(":"),
-                ModSep => op("::"),
+                PathSep => op("::"),
                 RArrow => op("->"),
                 LArrow => op("<-"),
                 FatArrow => op("=>"),
diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs
index e6b19817de3..9641d336c3f 100644
--- a/compiler/rustc_feature/src/unstable.rs
+++ b/compiler/rustc_feature/src/unstable.rs
@@ -533,6 +533,8 @@ declare_features! (
     (unstable, more_qualified_paths, "1.54.0", Some(86935)),
     /// Allows the `#[must_not_suspend]` attribute.
     (unstable, must_not_suspend, "1.57.0", Some(83310)),
+    /// Make `mut` not reset the binding mode on edition >= 2024.
+    (incomplete, mut_preserve_binding_mode_2024, "CURRENT_RUSTC_VERSION", Some(123076)),
     /// Allows `mut ref` and `mut ref mut` identifier patterns.
     (incomplete, mut_ref, "CURRENT_RUSTC_VERSION", Some(123076)),
     /// Allows using `#[naked]` on functions.
@@ -567,10 +569,14 @@ declare_features! (
     (unstable, optimize_attribute, "1.34.0", Some(54882)),
     /// Allows postfix match `expr.match { ... }`
     (unstable, postfix_match, "CURRENT_RUSTC_VERSION", Some(121618)),
+    /// Allows `use<'a, 'b, A, B>` in `impl use<...> Trait` for precise capture of generic args.
+    (incomplete, precise_capturing, "CURRENT_RUSTC_VERSION", Some(123432)),
     /// Allows macro attributes on expressions, statements and non-inline modules.
     (unstable, proc_macro_hygiene, "1.30.0", Some(54727)),
     /// Allows `&raw const $place_expr` and `&raw mut $place_expr` expressions.
     (unstable, raw_ref_op, "1.41.0", Some(64490)),
+    /// Makes `&` and `&mut` patterns eat only one layer of references in Rust 2024.
+    (incomplete, ref_pat_eat_one_layer_2024, "CURRENT_RUSTC_VERSION", Some(123076)),
     /// Allows `&` and `&mut` patterns to consume match-ergonomics-inserted references.
     (incomplete, ref_pat_everywhere, "CURRENT_RUSTC_VERSION", Some(123076)),
     /// Allows using the `#[register_tool]` attribute.
diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs
index 2662f5661ba..37d9b2ffd6a 100644
--- a/compiler/rustc_hir/src/def.rs
+++ b/compiler/rustc_hir/src/def.rs
@@ -207,7 +207,6 @@ impl DefKind {
             | DefKind::Enum
             | DefKind::Variant
             | DefKind::Trait
-            | DefKind::OpaqueTy
             | DefKind::TyAlias
             | DefKind::ForeignTy
             | DefKind::TraitAlias
@@ -234,7 +233,8 @@ impl DefKind {
             | DefKind::Use
             | DefKind::ForeignMod
             | DefKind::GlobalAsm
-            | DefKind::Impl { .. } => None,
+            | DefKind::Impl { .. }
+            | DefKind::OpaqueTy => None,
         }
     }
 
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index c6e3ad31f01..b39056d8690 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -2557,6 +2557,27 @@ pub struct OpaqueTy<'hir> {
     /// originating from a trait method. This makes it so that the opaque is
     /// lowered as an associated type.
     pub in_trait: bool,
+    /// List of arguments captured via `impl use<'a, P, ...> Trait` syntax.
+    pub precise_capturing_args: Option<&'hir [PreciseCapturingArg<'hir>]>,
+}
+
+#[derive(Debug, Clone, Copy, HashStable_Generic)]
+pub enum PreciseCapturingArg<'hir> {
+    Lifetime(&'hir Lifetime),
+    /// Non-lifetime argument (type or const)
+    Param(PreciseCapturingNonLifetimeArg),
+}
+
+/// We need to have a [`Node`] for the [`HirId`] that we attach the type/const param
+/// resolution to. Lifetimes don't have this problem, and for them, it's actually
+/// kind of detrimental to use a custom node type versus just using [`Lifetime`],
+/// since resolve_bound_vars operates on `Lifetime`s.
+// FIXME(precise_capturing): Investigate storing this as a path instead?
+#[derive(Debug, Clone, Copy, HashStable_Generic)]
+pub struct PreciseCapturingNonLifetimeArg {
+    pub hir_id: HirId,
+    pub ident: Ident,
+    pub res: Res,
 }
 
 /// From whence the opaque type came.
@@ -3535,6 +3556,7 @@ pub enum Node<'hir> {
     WhereBoundPredicate(&'hir WhereBoundPredicate<'hir>),
     // FIXME: Merge into `Node::Infer`.
     ArrayLenInfer(&'hir InferArg),
+    PreciseCapturingNonLifetimeArg(&'hir PreciseCapturingNonLifetimeArg),
     // Created by query feeding
     Synthetic,
     // Span by reference to minimize `Node`'s size
@@ -3571,6 +3593,7 @@ impl<'hir> Node<'hir> {
             Node::TypeBinding(b) => Some(b.ident),
             Node::PatField(f) => Some(f.ident),
             Node::ExprField(f) => Some(f.ident),
+            Node::PreciseCapturingNonLifetimeArg(a) => Some(a.ident),
             Node::Param(..)
             | Node::AnonConst(..)
             | Node::ConstBlock(..)
diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs
index 5da9d4444da..cd9f9ff9109 100644
--- a/compiler/rustc_hir/src/intravisit.rs
+++ b/compiler/rustc_hir/src/intravisit.rs
@@ -413,6 +413,9 @@ pub trait Visitor<'v>: Sized {
     fn visit_param_bound(&mut self, bounds: &'v GenericBound<'v>) -> Self::Result {
         walk_param_bound(self, bounds)
     }
+    fn visit_precise_capturing_arg(&mut self, arg: &'v PreciseCapturingArg<'v>) -> Self::Result {
+        walk_precise_capturing_arg(self, arg)
+    }
     fn visit_poly_trait_ref(&mut self, t: &'v PolyTraitRef<'v>) -> Self::Result {
         walk_poly_trait_ref(self, t)
     }
@@ -526,10 +529,15 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) -> V::
             try_visit!(visitor.visit_ty(ty));
             try_visit!(visitor.visit_generics(generics));
         }
-        ItemKind::OpaqueTy(&OpaqueTy { generics, bounds, .. }) => {
+        ItemKind::OpaqueTy(&OpaqueTy { generics, bounds, precise_capturing_args, .. }) => {
             try_visit!(visitor.visit_id(item.hir_id()));
             try_visit!(walk_generics(visitor, generics));
             walk_list!(visitor, visit_param_bound, bounds);
+            if let Some(precise_capturing_args) = precise_capturing_args {
+                for arg in precise_capturing_args {
+                    try_visit!(visitor.visit_precise_capturing_arg(arg));
+                }
+            }
         }
         ItemKind::Enum(ref enum_definition, ref generics) => {
             try_visit!(visitor.visit_generics(generics));
@@ -1137,6 +1145,16 @@ pub fn walk_param_bound<'v, V: Visitor<'v>>(
     }
 }
 
+pub fn walk_precise_capturing_arg<'v, V: Visitor<'v>>(
+    visitor: &mut V,
+    arg: &'v PreciseCapturingArg<'v>,
+) -> V::Result {
+    match *arg {
+        PreciseCapturingArg::Lifetime(lt) => visitor.visit_lifetime(lt),
+        PreciseCapturingArg::Param(param) => visitor.visit_id(param.hir_id),
+    }
+}
+
 pub fn walk_poly_trait_ref<'v, V: Visitor<'v>>(
     visitor: &mut V,
     trait_ref: &'v PolyTraitRef<'v>,
diff --git a/compiler/rustc_hir/src/tests.rs b/compiler/rustc_hir/src/tests.rs
index 74b8e88a977..571923b5462 100644
--- a/compiler/rustc_hir/src/tests.rs
+++ b/compiler/rustc_hir/src/tests.rs
@@ -14,7 +14,7 @@ fn def_path_hash_depends_on_crate_id() {
     // the crate by changing the crate disambiguator (e.g. via bumping the
     // crate's version number).
 
-    create_session_globals_then(Edition::Edition2024, || {
+    create_session_globals_then(Edition::Edition2024, None, || {
         let id0 = StableCrateId::new(Symbol::intern("foo"), false, vec!["1".to_string()], "");
         let id1 = StableCrateId::new(Symbol::intern("foo"), false, vec!["2".to_string()], "");
 
diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl
index 86b8b6d6b2b..0ff78ebff99 100644
--- a/compiler/rustc_hir_analysis/messages.ftl
+++ b/compiler/rustc_hir_analysis/messages.ftl
@@ -37,6 +37,8 @@ hir_analysis_auto_deref_reached_recursion_limit = reached the recursion limit wh
     .label = deref recursion limit reached
     .help = consider increasing the recursion limit by adding a `#![recursion_limit = "{$suggested_limit}"]` attribute to your crate (`{$crate_name}`)
 
+hir_analysis_bad_precise_capture = expected {$kind} parameter in `use<...>` precise captures list, found {$found}
+
 hir_analysis_cannot_capture_late_bound_const =
     cannot capture late-bound const parameter in {$what}
     .label = parameter defined here
@@ -111,6 +113,9 @@ hir_analysis_drop_impl_on_wrong_item =
 
 hir_analysis_drop_impl_reservation = reservation `Drop` impls are not supported
 
+hir_analysis_duplicate_precise_capture = cannot capture parameter `{$name}` twice
+    .label = parameter captured again here
+
 hir_analysis_empty_specialization = specialization impl does not specialize any associated items
     .note = impl is a specialization of this impl
 
@@ -214,6 +219,13 @@ hir_analysis_late_bound_lifetime_in_apit = `impl Trait` can only mention lifetim
 hir_analysis_late_bound_type_in_apit = `impl Trait` can only mention type parameters from an fn or impl
     .label = type parameter declared here
 
+hir_analysis_lifetime_must_be_first = lifetime parameter `{$name}` must be listed before non-lifetime parameters
+    .label = move the lifetime before this parameter
+
+hir_analysis_lifetime_not_captured = `impl Trait` captures lifetime parameter, but it is not mentioned in `use<...>` precise captures list
+    .label = lifetime captured due to being mentioned in the bounds of the `impl Trait`
+    .param_label = this lifetime parameter is captured
+
 hir_analysis_lifetimes_or_bounds_mismatch_on_trait =
     lifetime parameters or bounds on {$item_kind} `{$ident}` do not match the trait declaration
     .label = lifetimes do not match {$item_kind} in trait
@@ -339,6 +351,10 @@ hir_analysis_param_in_ty_of_assoc_const_binding =
         *[normal] the {$param_def_kind} `{$param_name}` is defined here
     }
 
+hir_analysis_param_not_captured = `impl Trait` must mention all {$kind} parameters in scope
+    .label = {$kind} parameter is implicitly captured by this `impl Trait`
+    .note = currently, all {$kind} parameters are required to be mentioned in the precise captures list
+
 hir_analysis_paren_sugar_attribute = the `#[rustc_paren_sugar]` attribute is a temporary means of controlling which traits can use parenthetical notation
     .help = add `#![feature(unboxed_closures)]` to the crate attributes to use it
 
@@ -355,6 +371,9 @@ hir_analysis_pattern_type_wild_pat = "wildcard patterns are not permitted for pa
 hir_analysis_placeholder_not_allowed_item_signatures = the placeholder `_` is not allowed within types on item signatures for {$kind}
     .label = not allowed in type signatures
 
+hir_analysis_precise_capture_self_alias = `Self` can't be captured in `use<...>` precise captures list, since it is an alias
+    .label = `Self` is not a generic argument, but an alias to the type of the {$what}
+
 hir_analysis_redundant_lifetime_args = unnecessary lifetime parameter `{$victim}`
     .note = you can use the `{$candidate}` lifetime directly, in place of `{$victim}`
 
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index 216b89fd4f1..8c85d13650b 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -1,10 +1,10 @@
 use crate::check::intrinsicck::InlineAsmCtxt;
-use crate::errors::LinkageType;
 
 use super::compare_impl_item::check_type_bounds;
 use super::compare_impl_item::{compare_impl_method, compare_impl_ty};
 use super::*;
 use rustc_attr as attr;
+use rustc_data_structures::unord::{UnordMap, UnordSet};
 use rustc_errors::{codes::*, MultiSpan};
 use rustc_hir as hir;
 use rustc_hir::def::{CtorKind, DefKind};
@@ -12,6 +12,7 @@ use rustc_hir::Node;
 use rustc_infer::infer::{RegionVariableOrigin, TyCtxtInferExt};
 use rustc_infer::traits::{Obligation, TraitEngineExt as _};
 use rustc_lint_defs::builtin::REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS;
+use rustc_middle::middle::resolve_bound_vars::ResolvedArg;
 use rustc_middle::middle::stability::EvalResult;
 use rustc_middle::traits::ObligationCauseCode;
 use rustc_middle::ty::fold::BottomUpFolder;
@@ -474,6 +475,133 @@ fn sanity_check_found_hidden_type<'tcx>(
     }
 }
 
+/// Check that the opaque's precise captures list is valid (if present).
+/// We check this for regular `impl Trait`s and also RPITITs, even though the latter
+/// are technically GATs.
+///
+/// This function is responsible for:
+/// 1. Checking that all type/const params are mention in the captures list.
+/// 2. Checking that all lifetimes that are implicitly captured are mentioned.
+/// 3. Asserting that all parameters mentioned in the captures list are invariant.
+fn check_opaque_precise_captures<'tcx>(tcx: TyCtxt<'tcx>, opaque_def_id: LocalDefId) {
+    let hir::OpaqueTy { precise_capturing_args, .. } =
+        *tcx.hir_node_by_def_id(opaque_def_id).expect_item().expect_opaque_ty();
+    let Some(precise_capturing_args) = precise_capturing_args else {
+        // No precise capturing args; nothing to validate
+        return;
+    };
+
+    let mut expected_captures = UnordSet::default();
+    let mut seen_params = UnordMap::default();
+    let mut prev_non_lifetime_param = None;
+    for arg in precise_capturing_args {
+        let (hir_id, ident) = match *arg {
+            hir::PreciseCapturingArg::Param(hir::PreciseCapturingNonLifetimeArg {
+                hir_id,
+                ident,
+                ..
+            }) => {
+                if prev_non_lifetime_param.is_none() {
+                    prev_non_lifetime_param = Some(ident);
+                }
+                (hir_id, ident)
+            }
+            hir::PreciseCapturingArg::Lifetime(&hir::Lifetime { hir_id, ident, .. }) => {
+                if let Some(prev_non_lifetime_param) = prev_non_lifetime_param {
+                    tcx.dcx().emit_err(errors::LifetimesMustBeFirst {
+                        lifetime_span: ident.span,
+                        name: ident.name,
+                        other_span: prev_non_lifetime_param.span,
+                    });
+                }
+                (hir_id, ident)
+            }
+        };
+
+        let ident = ident.normalize_to_macros_2_0();
+        if let Some(span) = seen_params.insert(ident, ident.span) {
+            tcx.dcx().emit_err(errors::DuplicatePreciseCapture {
+                name: ident.name,
+                first_span: span,
+                second_span: ident.span,
+            });
+        }
+
+        match tcx.named_bound_var(hir_id) {
+            Some(ResolvedArg::EarlyBound(def_id)) => {
+                expected_captures.insert(def_id);
+            }
+            _ => {
+                tcx.dcx().span_delayed_bug(
+                    tcx.hir().span(hir_id),
+                    "parameter should have been resolved",
+                );
+            }
+        }
+    }
+
+    let variances = tcx.variances_of(opaque_def_id);
+    let mut def_id = Some(opaque_def_id.to_def_id());
+    while let Some(generics) = def_id {
+        let generics = tcx.generics_of(generics);
+        def_id = generics.parent;
+
+        for param in &generics.params {
+            if expected_captures.contains(&param.def_id) {
+                assert_eq!(
+                    variances[param.index as usize],
+                    ty::Invariant,
+                    "precise captured param should be invariant"
+                );
+                continue;
+            }
+
+            match param.kind {
+                ty::GenericParamDefKind::Lifetime => {
+                    // Check if the lifetime param was captured but isn't named in the precise captures list.
+                    if variances[param.index as usize] == ty::Invariant {
+                        let param_span =
+                            if let ty::ReEarlyParam(ty::EarlyParamRegion { def_id, .. })
+                            | ty::ReLateParam(ty::LateParamRegion {
+                                bound_region: ty::BoundRegionKind::BrNamed(def_id, _),
+                                ..
+                            }) = *tcx
+                                .map_opaque_lifetime_to_parent_lifetime(param.def_id.expect_local())
+                            {
+                                Some(tcx.def_span(def_id))
+                            } else {
+                                None
+                            };
+                        // FIXME(precise_capturing): Structured suggestion for this would be useful
+                        tcx.dcx().emit_err(errors::LifetimeNotCaptured {
+                            use_span: tcx.def_span(param.def_id),
+                            param_span,
+                            opaque_span: tcx.def_span(opaque_def_id),
+                        });
+                        continue;
+                    }
+                }
+                ty::GenericParamDefKind::Type { .. } => {
+                    // FIXME(precise_capturing): Structured suggestion for this would be useful
+                    tcx.dcx().emit_err(errors::ParamNotCaptured {
+                        param_span: tcx.def_span(param.def_id),
+                        opaque_span: tcx.def_span(opaque_def_id),
+                        kind: "type",
+                    });
+                }
+                ty::GenericParamDefKind::Const { .. } => {
+                    // FIXME(precise_capturing): Structured suggestion for this would be useful
+                    tcx.dcx().emit_err(errors::ParamNotCaptured {
+                        param_span: tcx.def_span(param.def_id),
+                        opaque_span: tcx.def_span(opaque_def_id),
+                        kind: "const",
+                    });
+                }
+            }
+        }
+    }
+}
+
 fn is_enum_of_nonnullable_ptr<'tcx>(
     tcx: TyCtxt<'tcx>,
     adt_def: AdtDef<'tcx>,
@@ -499,7 +627,7 @@ fn check_static_linkage(tcx: TyCtxt<'_>, def_id: LocalDefId) {
             ty::Adt(adt_def, args) => !is_enum_of_nonnullable_ptr(tcx, *adt_def, *args),
             _ => true,
         } {
-            tcx.dcx().emit_err(LinkageType { span: tcx.def_span(def_id) });
+            tcx.dcx().emit_err(errors::LinkageType { span: tcx.def_span(def_id) });
         }
     }
 }
@@ -566,6 +694,8 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) {
             check_union(tcx, def_id);
         }
         DefKind::OpaqueTy => {
+            check_opaque_precise_captures(tcx, def_id);
+
             let origin = tcx.opaque_type_origin(def_id);
             if let hir::OpaqueTyOrigin::FnReturn(fn_def_id)
             | hir::OpaqueTyOrigin::AsyncFn(fn_def_id) = origin
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 a668a104575..d2759087cb4 100644
--- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
@@ -9,7 +9,7 @@ use rustc_hir::def::{DefKind, Res};
 use rustc_hir::intravisit;
 use rustc_hir::{GenericParamKind, ImplItemKind};
 use rustc_infer::infer::outlives::env::OutlivesEnvironment;
-use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
+use rustc_infer::infer::type_variable::TypeVariableOrigin;
 use rustc_infer::infer::{self, InferCtxt, TyCtxtInferExt};
 use rustc_infer::traits::{util, FulfillmentError};
 use rustc_middle::ty::error::{ExpectedFound, TypeError};
@@ -800,10 +800,10 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ImplTraitInTraitCollector<'_, 'tcx> {
                 bug!("FIXME(RPITIT): error here");
             }
             // Replace with infer var
-            let infer_ty = self.ocx.infcx.next_ty_var(TypeVariableOrigin {
-                span: self.span,
-                kind: TypeVariableOriginKind::MiscVariable,
-            });
+            let infer_ty = self
+                .ocx
+                .infcx
+                .next_ty_var(TypeVariableOrigin { span: self.span, param_def_id: None });
             self.types.insert(proj.def_id, (infer_ty, proj.args));
             // Recurse into bounds
             for (pred, pred_span) in self
diff --git a/compiler/rustc_hir_analysis/src/check/errs.rs b/compiler/rustc_hir_analysis/src/check/errs.rs
index 548f9b0810f..a49626eed35 100644
--- a/compiler/rustc_hir_analysis/src/check/errs.rs
+++ b/compiler/rustc_hir_analysis/src/check/errs.rs
@@ -12,7 +12,7 @@ pub fn maybe_expr_static_mut(tcx: TyCtxt<'_>, expr: hir::Expr<'_>) {
     let hir_id = expr.hir_id;
     if let hir::ExprKind::AddrOf(borrow_kind, m, expr) = expr.kind
         && matches!(borrow_kind, hir::BorrowKind::Ref)
-        && let Some(var) = is_path_static_mut(*expr)
+        && let Some(var) = path_if_static_mut(tcx, expr)
     {
         handle_static_mut_ref(tcx, span, var, span.edition().at_least_rust_2024(), m, hir_id);
     }
@@ -24,7 +24,7 @@ pub fn maybe_stmt_static_mut(tcx: TyCtxt<'_>, stmt: hir::Stmt<'_>) {
         && let hir::PatKind::Binding(ba, _, _, _) = loc.pat.kind
         && let hir::ByRef::Yes(rmutbl) = ba.0
         && let Some(init) = loc.init
-        && let Some(var) = is_path_static_mut(*init)
+        && let Some(var) = path_if_static_mut(tcx, init)
     {
         handle_static_mut_ref(
             tcx,
@@ -37,13 +37,13 @@ pub fn maybe_stmt_static_mut(tcx: TyCtxt<'_>, stmt: hir::Stmt<'_>) {
     }
 }
 
-fn is_path_static_mut(expr: hir::Expr<'_>) -> Option<String> {
+fn path_if_static_mut(tcx: TyCtxt<'_>, expr: &hir::Expr<'_>) -> Option<String> {
     if let hir::ExprKind::Path(qpath) = expr.kind
         && let hir::QPath::Resolved(_, path) = qpath
         && let hir::def::Res::Def(def_kind, _) = path.res
         && let hir::def::DefKind::Static { mutability: Mutability::Mut, nested: false } = def_kind
     {
-        return Some(qpath_to_string(&qpath));
+        return Some(qpath_to_string(&tcx, &qpath));
     }
     None
 }
diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs
index 5e404847656..0b6c60e4ba2 100644
--- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs
@@ -10,8 +10,8 @@ use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::lang_items::LangItem;
 use rustc_hir::ItemKind;
 use rustc_infer::infer::outlives::env::OutlivesEnvironment;
+use rustc_infer::infer::TyCtxtInferExt;
 use rustc_infer::infer::{self, RegionResolutionError};
-use rustc_infer::infer::{DefineOpaqueTypes, TyCtxtInferExt};
 use rustc_infer::traits::Obligation;
 use rustc_middle::ty::adjustment::CoerceUnsizedInfo;
 use rustc_middle::ty::{self, suggest_constraining_type_params, Ty, TyCtxt, TypeVisitableExt};
@@ -189,10 +189,7 @@ fn visit_implementation_of_dispatch_from_dyn(checker: &Checker<'_>) -> Result<()
     // even if they do not carry that attribute.
     use rustc_type_ir::TyKind::*;
     match (source.kind(), target.kind()) {
-        (&Ref(r_a, _, mutbl_a), Ref(r_b, _, mutbl_b))
-            if infcx.at(&cause, param_env).eq(DefineOpaqueTypes::No, r_a, *r_b).is_ok()
-                && mutbl_a == *mutbl_b =>
-        {
+        (&Ref(r_a, _, mutbl_a), Ref(r_b, _, mutbl_b)) if r_a == *r_b && mutbl_a == *mutbl_b => {
             Ok(())
         }
         (&RawPtr(_, a_mutbl), &RawPtr(_, b_mutbl)) if a_mutbl == b_mutbl => Ok(()),
@@ -230,18 +227,14 @@ fn visit_implementation_of_dispatch_from_dyn(checker: &Checker<'_>) -> Result<()
                         }
                     }
 
-                    if let Ok(ok) =
-                        infcx.at(&cause, param_env).eq(DefineOpaqueTypes::No, ty_a, ty_b)
-                    {
-                        if ok.obligations.is_empty() {
-                            res = Err(tcx.dcx().emit_err(errors::DispatchFromDynZST {
-                                span,
-                                name: field.name,
-                                ty: ty_a,
-                            }));
+                    if ty_a == ty_b {
+                        res = Err(tcx.dcx().emit_err(errors::DispatchFromDynZST {
+                            span,
+                            name: field.name,
+                            ty: ty_a,
+                        }));
 
-                            return false;
-                        }
+                        return false;
                     }
 
                     return true;
@@ -433,14 +426,12 @@ pub fn coerce_unsized_info<'tcx>(
                     // something more accepting, but we use
                     // equality because we want to be able to
                     // perform this check without computing
-                    // variance where possible. (This is because
-                    // we may have to evaluate constraint
+                    // variance or constraining opaque types' hidden types.
+                    // (This is because we may have to evaluate constraint
                     // expressions in the course of execution.)
                     // See e.g., #41936.
-                    if let Ok(ok) = infcx.at(&cause, param_env).eq(DefineOpaqueTypes::No, a, b) {
-                        if ok.obligations.is_empty() {
-                            return None;
-                        }
+                    if a == b {
+                        return None;
                     }
 
                     // Collect up all fields that were significantly changed
diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
index efd3ceebe6c..472657290ed 100644
--- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
@@ -37,7 +37,7 @@ pub(super) fn predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredic
         // from the trait itself that *shouldn't* be shown as the source of
         // an obligation and instead be skipped. Otherwise we'd use
         // `tcx.def_span(def_id);`
-        let span = rustc_span::DUMMY_SP;
+        let span = DUMMY_SP;
 
         result.predicates =
             tcx.arena.alloc_from_iter(result.predicates.iter().copied().chain(std::iter::once((
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 3d16f1420d9..a5f038d383d 100644
--- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
+++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
@@ -13,7 +13,7 @@ use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::LocalDefId;
 use rustc_hir::intravisit::{self, Visitor};
-use rustc_hir::{GenericArg, GenericParam, GenericParamKind, HirIdMap, LifetimeName, Node};
+use rustc_hir::{GenericArg, GenericParam, GenericParamKind, HirId, HirIdMap, LifetimeName, Node};
 use rustc_macros::extension;
 use rustc_middle::bug;
 use rustc_middle::hir::nested_filter;
@@ -107,7 +107,7 @@ enum Scope<'a> {
         /// queried later. However, if we enter an elision scope, we have to
         /// later append the elided bound vars to the list and need to know what
         /// to append to.
-        hir_id: hir::HirId,
+        hir_id: HirId,
 
         s: ScopeRef<'a>,
 
@@ -557,6 +557,50 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
         }
     }
 
+    fn visit_precise_capturing_arg(
+        &mut self,
+        arg: &'tcx hir::PreciseCapturingArg<'tcx>,
+    ) -> Self::Result {
+        match *arg {
+            hir::PreciseCapturingArg::Lifetime(lt) => match lt.res {
+                LifetimeName::Param(def_id) => {
+                    self.resolve_lifetime_ref(def_id, lt);
+                }
+                LifetimeName::Error => {}
+                LifetimeName::ImplicitObjectLifetimeDefault
+                | LifetimeName::Infer
+                | LifetimeName::Static => {
+                    self.tcx.dcx().emit_err(errors::BadPreciseCapture {
+                        span: lt.ident.span,
+                        kind: "lifetime",
+                        found: format!("`{}`", lt.ident.name),
+                    });
+                }
+            },
+            hir::PreciseCapturingArg::Param(param) => match param.res {
+                Res::Def(DefKind::TyParam | DefKind::ConstParam, def_id)
+                | Res::SelfTyParam { trait_: def_id } => {
+                    self.resolve_type_ref(def_id.expect_local(), param.hir_id);
+                }
+                Res::Err => {}
+                Res::SelfTyAlias { alias_to, .. } => {
+                    self.tcx.dcx().emit_err(errors::PreciseCaptureSelfAlias {
+                        span: param.ident.span,
+                        self_span: self.tcx.def_span(alias_to),
+                        what: self.tcx.def_descr(alias_to),
+                    });
+                }
+                res => {
+                    self.tcx.dcx().emit_err(errors::BadPreciseCapture {
+                        span: param.ident.span,
+                        kind: "type or const",
+                        found: res.descr().to_string(),
+                    });
+                }
+            },
+        }
+    }
+
     fn visit_foreign_item(&mut self, item: &'tcx hir::ForeignItem<'tcx>) {
         match item.kind {
             hir::ForeignItemKind::Fn(_, _, generics) => {
@@ -781,7 +825,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
         }
     }
 
-    fn visit_path(&mut self, path: &hir::Path<'tcx>, hir_id: hir::HirId) {
+    fn visit_path(&mut self, path: &hir::Path<'tcx>, hir_id: HirId) {
         for (i, segment) in path.segments.iter().enumerate() {
             let depth = path.segments.len() - i - 1;
             if let Some(args) = segment.args {
@@ -983,7 +1027,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
         }
     }
 
-    fn record_late_bound_vars(&mut self, hir_id: hir::HirId, binder: Vec<ty::BoundVariableKind>) {
+    fn record_late_bound_vars(&mut self, hir_id: HirId, binder: Vec<ty::BoundVariableKind>) {
         if let Some(old) = self.map.late_bound_vars.insert(hir_id, binder) {
             bug!(
                 "overwrote bound vars for {hir_id:?}:\nold={old:?}\nnew={:?}",
@@ -1010,12 +1054,8 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
     /// already in scope (for a fn item, that will be 0, but for a method it might not be). Late
     /// bound lifetimes are resolved by name and associated with a binder ID (`binder_id`), so the
     /// ordering is not important there.
-    fn visit_early_late<F>(
-        &mut self,
-        hir_id: hir::HirId,
-        generics: &'tcx hir::Generics<'tcx>,
-        walk: F,
-    ) where
+    fn visit_early_late<F>(&mut self, hir_id: HirId, generics: &'tcx hir::Generics<'tcx>, walk: F)
+    where
         F: for<'b, 'c> FnOnce(&'b mut BoundVarContext<'c, 'tcx>),
     {
         let mut named_late_bound_vars = 0;
@@ -1062,7 +1102,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
         self.with(scope, walk);
     }
 
-    fn visit_early<F>(&mut self, hir_id: hir::HirId, generics: &'tcx hir::Generics<'tcx>, walk: F)
+    fn visit_early<F>(&mut self, hir_id: HirId, generics: &'tcx hir::Generics<'tcx>, walk: F)
     where
         F: for<'b, 'c> FnOnce(&'b mut BoundVarContext<'c, 'tcx>),
     {
@@ -1288,7 +1328,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
         );
     }
 
-    fn resolve_type_ref(&mut self, param_def_id: LocalDefId, hir_id: hir::HirId) {
+    fn resolve_type_ref(&mut self, param_def_id: LocalDefId, hir_id: HirId) {
         // Walk up the scope chain, tracking the number of fn scopes
         // that we pass through, until we find a lifetime with the
         // given name or we run out of scopes.
diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs
index d129614e0e1..867ee772a30 100644
--- a/compiler/rustc_hir_analysis/src/errors.rs
+++ b/compiler/rustc_hir_analysis/src/errors.rs
@@ -10,6 +10,9 @@ use rustc_span::{symbol::Ident, Span, Symbol};
 mod pattern_types;
 pub use pattern_types::*;
 
+mod precise_captures;
+pub(crate) use precise_captures::*;
+
 #[derive(Diagnostic)]
 #[diag(hir_analysis_ambiguous_assoc_item)]
 pub struct AmbiguousAssocItem<'a> {
diff --git a/compiler/rustc_hir_analysis/src/errors/precise_captures.rs b/compiler/rustc_hir_analysis/src/errors/precise_captures.rs
new file mode 100644
index 00000000000..520bf1d9f40
--- /dev/null
+++ b/compiler/rustc_hir_analysis/src/errors/precise_captures.rs
@@ -0,0 +1,63 @@
+use rustc_macros::Diagnostic;
+use rustc_span::{Span, Symbol};
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_param_not_captured)]
+#[note]
+pub struct ParamNotCaptured {
+    #[primary_span]
+    pub param_span: Span,
+    #[label]
+    pub opaque_span: Span,
+    pub kind: &'static str,
+}
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_lifetime_not_captured)]
+pub struct LifetimeNotCaptured {
+    #[primary_span]
+    pub use_span: Span,
+    #[label(hir_analysis_param_label)]
+    pub param_span: Option<Span>,
+    #[label]
+    pub opaque_span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_bad_precise_capture)]
+pub struct BadPreciseCapture {
+    #[primary_span]
+    pub span: Span,
+    pub kind: &'static str,
+    pub found: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_precise_capture_self_alias)]
+pub struct PreciseCaptureSelfAlias {
+    #[primary_span]
+    pub span: Span,
+    #[label]
+    pub self_span: Span,
+    pub what: &'static str,
+}
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_duplicate_precise_capture)]
+pub struct DuplicatePreciseCapture {
+    #[primary_span]
+    pub first_span: Span,
+    pub name: Symbol,
+    #[label]
+    pub second_span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_lifetime_must_be_first)]
+pub struct LifetimesMustBeFirst {
+    #[primary_span]
+    pub lifetime_span: Span,
+    pub name: Symbol,
+    #[label]
+    pub other_span: Span,
+}
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
index b15bf54234d..0d5a295ca96 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
@@ -35,7 +35,7 @@ use rustc_hir as hir;
 use rustc_hir::def::{CtorOf, DefKind, Namespace, Res};
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::intravisit::{walk_generics, Visitor as _};
-use rustc_hir::{GenericArg, GenericArgs};
+use rustc_hir::{GenericArg, GenericArgs, HirId};
 use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
 use rustc_infer::traits::ObligationCause;
 use rustc_middle::middle::stability::AllowUnstable;
@@ -158,7 +158,7 @@ pub trait HirTyLowerer<'tcx> {
     fn probe_adt(&self, span: Span, ty: Ty<'tcx>) -> Option<ty::AdtDef<'tcx>>;
 
     /// Record the lowered type of a HIR node in this context.
-    fn record_ty(&self, hir_id: hir::HirId, ty: Ty<'tcx>, span: Span);
+    fn record_ty(&self, hir_id: HirId, ty: Ty<'tcx>, span: Span);
 
     /// The inference context of the lowering context if applicable.
     fn infcx(&self) -> Option<&InferCtxt<'tcx>>;
@@ -999,7 +999,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
     #[instrument(level = "debug", skip_all, ret)]
     pub fn lower_assoc_path(
         &self,
-        hir_ref_id: hir::HirId,
+        hir_ref_id: HirId,
         span: Span,
         qself_ty: Ty<'tcx>,
         qself: &'tcx hir::Ty<'tcx>,
@@ -1200,7 +1200,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
         segment: &hir::PathSegment<'tcx>,
         adt_did: DefId,
         self_ty: Ty<'tcx>,
-        block: hir::HirId,
+        block: HirId,
         span: Span,
     ) -> Result<Option<(Ty<'tcx>, DefId)>, ErrorGuaranteed> {
         let tcx = self.tcx();
@@ -1349,13 +1349,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
         }
     }
 
-    fn probe_assoc_ty(
-        &self,
-        name: Ident,
-        block: hir::HirId,
-        span: Span,
-        scope: DefId,
-    ) -> Option<DefId> {
+    fn probe_assoc_ty(&self, name: Ident, block: HirId, span: Span, scope: DefId) -> Option<DefId> {
         let (item, def_scope) = self.probe_assoc_ty_unchecked(name, block, scope)?;
         self.check_assoc_ty(item, name, def_scope, block, span);
         Some(item)
@@ -1364,7 +1358,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
     fn probe_assoc_ty_unchecked(
         &self,
         name: Ident,
-        block: hir::HirId,
+        block: HirId,
         scope: DefId,
     ) -> Option<(DefId, DefId)> {
         let tcx = self.tcx();
@@ -1381,14 +1375,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
         Some((item.def_id, def_scope))
     }
 
-    fn check_assoc_ty(
-        &self,
-        item: DefId,
-        name: Ident,
-        def_scope: DefId,
-        block: hir::HirId,
-        span: Span,
-    ) {
+    fn check_assoc_ty(&self, item: DefId, name: Ident, def_scope: DefId, block: HirId, span: Span) {
         let tcx = self.tcx();
         let kind = DefKind::AssocTy;
 
@@ -1714,7 +1701,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
         &self,
         opt_self_ty: Option<Ty<'tcx>>,
         path: &hir::Path<'tcx>,
-        hir_id: hir::HirId,
+        hir_id: HirId,
         permit_variants: bool,
     ) -> Ty<'tcx> {
         debug!(?path.res, ?opt_self_ty, ?path.segments);
@@ -1898,7 +1885,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
     ///
     /// Early-bound type parameters get lowered to [`ty::Param`]
     /// and late-bound ones to [`ty::Bound`].
-    pub(crate) fn lower_ty_param(&self, hir_id: hir::HirId) -> Ty<'tcx> {
+    pub(crate) fn lower_ty_param(&self, hir_id: HirId) -> Ty<'tcx> {
         let tcx = self.tcx();
         match tcx.named_bound_var(hir_id) {
             Some(rbv::ResolvedArg::LateBound(debruijn, index, def_id)) => {
@@ -1925,7 +1912,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
     ///
     /// Early-bound const parameters get lowered to [`ty::ConstKind::Param`]
     /// and late-bound ones to [`ty::ConstKind::Bound`].
-    pub(crate) fn lower_const_param(&self, hir_id: hir::HirId, param_ty: Ty<'tcx>) -> Const<'tcx> {
+    pub(crate) fn lower_const_param(&self, hir_id: HirId, param_ty: Ty<'tcx>) -> Const<'tcx> {
         let tcx = self.tcx();
         match tcx.named_bound_var(hir_id) {
             Some(rbv::ResolvedArg::EarlyBound(def_id)) => {
@@ -2352,7 +2339,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
     #[instrument(level = "debug", skip(self, hir_id, unsafety, abi, decl, generics, hir_ty), ret)]
     pub fn lower_fn_ty(
         &self,
-        hir_id: hir::HirId,
+        hir_id: HirId,
         unsafety: hir::Unsafety,
         abi: abi::Abi,
         decl: &hir::FnDecl<'tcx>,
@@ -2480,7 +2467,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
     /// corresponds to the return type.
     fn suggest_trait_fn_ty_for_impl_fn_infer(
         &self,
-        fn_hir_id: hir::HirId,
+        fn_hir_id: HirId,
         arg_idx: Option<usize>,
     ) -> Option<Ty<'tcx>> {
         let tcx = self.tcx();
diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs
index 39312614c1b..0f4d8df7293 100644
--- a/compiler/rustc_hir_pretty/src/lib.rs
+++ b/compiler/rustc_hir_pretty/src/lib.rs
@@ -9,9 +9,10 @@ use rustc_ast_pretty::pp::Breaks::{Consistent, Inconsistent};
 use rustc_ast_pretty::pp::{self, Breaks};
 use rustc_ast_pretty::pprust::{Comments, PrintState};
 use rustc_hir as hir;
-use rustc_hir::LifetimeParamKind;
-use rustc_hir::{BindingAnnotation, ByRef, GenericArg, GenericParam, GenericParamKind, Node, Term};
-use rustc_hir::{GenericBound, PatKind, RangeEnd, TraitBoundModifier};
+use rustc_hir::{
+    BindingAnnotation, ByRef, GenericArg, GenericBound, GenericParam, GenericParamKind, HirId,
+    LifetimeParamKind, Node, PatKind, RangeEnd, Term, TraitBoundModifier,
+};
 use rustc_span::source_map::SourceMap;
 use rustc_span::symbol::{kw, Ident, Symbol};
 use rustc_span::FileName;
@@ -20,7 +21,7 @@ use rustc_target::spec::abi::Abi;
 use std::cell::Cell;
 use std::vec;
 
-pub fn id_to_string(map: &dyn rustc_hir::intravisit::Map<'_>, hir_id: hir::HirId) -> String {
+pub fn id_to_string(map: &dyn rustc_hir::intravisit::Map<'_>, hir_id: HirId) -> String {
     to_string(&map, |s| s.print_node(map.hir_node(hir_id)))
 }
 
@@ -28,7 +29,7 @@ pub enum AnnNode<'a> {
     Name(&'a Symbol),
     Block(&'a hir::Block<'a>),
     Item(&'a hir::Item<'a>),
-    SubItem(hir::HirId),
+    SubItem(HirId),
     Expr(&'a hir::Expr<'a>),
     Pat(&'a hir::Pat<'a>),
     Arm(&'a hir::Arm<'a>),
@@ -49,10 +50,6 @@ pub trait PpAnn {
     fn post(&self, _state: &mut State<'_>, _node: AnnNode<'_>) {}
 }
 
-pub struct NoAnn;
-
-impl PpAnn for NoAnn {}
-
 impl PpAnn for &dyn rustc_hir::intravisit::Map<'_> {
     fn nested(&self, state: &mut State<'_>, nested: Nested) {
         match nested {
@@ -69,12 +66,12 @@ impl PpAnn for &dyn rustc_hir::intravisit::Map<'_> {
 pub struct State<'a> {
     pub s: pp::Printer,
     comments: Option<Comments<'a>>,
-    attrs: &'a dyn Fn(hir::HirId) -> &'a [ast::Attribute],
+    attrs: &'a dyn Fn(HirId) -> &'a [ast::Attribute],
     ann: &'a (dyn PpAnn + 'a),
 }
 
 impl<'a> State<'a> {
-    fn attrs(&self, id: hir::HirId) -> &'a [ast::Attribute] {
+    fn attrs(&self, id: HirId) -> &'a [ast::Attribute] {
         (self.attrs)(id)
     }
 
@@ -99,6 +96,7 @@ impl<'a> State<'a> {
             Node::PatField(a) => self.print_patfield(a),
             Node::Arm(a) => self.print_arm(a),
             Node::Infer(_) => self.word("_"),
+            Node::PreciseCapturingNonLifetimeArg(param) => self.print_ident(param.ident),
             Node::Block(a) => {
                 // Containing cbox, will be closed by print-block at `}`.
                 self.cbox(INDENT_UNIT);
@@ -163,7 +161,7 @@ pub fn print_crate<'a>(
     krate: &hir::Mod<'_>,
     filename: FileName,
     input: String,
-    attrs: &'a dyn Fn(hir::HirId) -> &'a [ast::Attribute],
+    attrs: &'a dyn Fn(HirId) -> &'a [ast::Attribute],
     ann: &'a dyn PpAnn,
 ) -> String {
     let mut s = State {
@@ -190,16 +188,16 @@ where
     printer.s.eof()
 }
 
-pub fn ty_to_string(ty: &hir::Ty<'_>) -> String {
-    to_string(&NoAnn, |s| s.print_type(ty))
+pub fn ty_to_string(ann: &dyn PpAnn, ty: &hir::Ty<'_>) -> String {
+    to_string(ann, |s| s.print_type(ty))
 }
 
-pub fn qpath_to_string(segment: &hir::QPath<'_>) -> String {
-    to_string(&NoAnn, |s| s.print_qpath(segment, false))
+pub fn qpath_to_string(ann: &dyn PpAnn, segment: &hir::QPath<'_>) -> String {
+    to_string(ann, |s| s.print_qpath(segment, false))
 }
 
-pub fn pat_to_string(pat: &hir::Pat<'_>) -> String {
-    to_string(&NoAnn, |s| s.print_pat(pat))
+pub fn pat_to_string(ann: &dyn PpAnn, pat: &hir::Pat<'_>) -> String {
+    to_string(ann, |s| s.print_pat(pat))
 }
 
 impl<'a> State<'a> {
diff --git a/compiler/rustc_hir_typeck/messages.ftl b/compiler/rustc_hir_typeck/messages.ftl
index 18d9d739dd6..07b4948872d 100644
--- a/compiler/rustc_hir_typeck/messages.ftl
+++ b/compiler/rustc_hir_typeck/messages.ftl
@@ -46,6 +46,10 @@ hir_typeck_ctor_is_private = tuple struct constructor `{$def}` is private
 
 hir_typeck_deref_is_empty = this expression `Deref`s to `{$deref_ty}` which implements `is_empty`
 
+hir_typeck_dereferencing_mut_binding = dereferencing `mut` binding
+    .label = `mut` dereferences the type of this binding
+    .help = this will change in edition 2024
+
 hir_typeck_expected_default_return_type = expected `()` because of default return type
 
 hir_typeck_expected_return_type = expected `{$expected}` because of return type
diff --git a/compiler/rustc_hir_typeck/src/_match.rs b/compiler/rustc_hir_typeck/src/_match.rs
index 2a2fd0a41a6..334a424d2e2 100644
--- a/compiler/rustc_hir_typeck/src/_match.rs
+++ b/compiler/rustc_hir_typeck/src/_match.rs
@@ -5,7 +5,7 @@ use rustc_hir::def::{CtorOf, DefKind, Res};
 use rustc_hir::def_id::LocalDefId;
 use rustc_hir::{self as hir, ExprKind, PatKind};
 use rustc_hir_pretty::ty_to_string;
-use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
+use rustc_infer::infer::type_variable::TypeVariableOrigin;
 use rustc_middle::ty::{self, Ty};
 use rustc_span::Span;
 use rustc_trait_selection::traits::{
@@ -67,10 +67,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 // arm for inconsistent arms or to the whole match when a `()` type
                 // is required).
                 Expectation::ExpectHasType(ety) if ety != Ty::new_unit(self.tcx) => ety,
-                _ => self.next_ty_var(TypeVariableOrigin {
-                    kind: TypeVariableOriginKind::MiscVariable,
-                    span: expr.span,
-                }),
+                _ => self.next_ty_var(TypeVariableOrigin { param_def_id: None, span: expr.span }),
             };
             CoerceMany::with_coercion_sites(coerce_first, arms)
         };
@@ -395,7 +392,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     return self.get_fn_decl(hir_id).map(|(_, fn_decl, _)| {
                         let (ty, span) = match fn_decl.output {
                             hir::FnRetTy::DefaultReturn(span) => ("()".to_string(), span),
-                            hir::FnRetTy::Return(ty) => (ty_to_string(ty), ty.span),
+                            hir::FnRetTy::Return(ty) => (ty_to_string(&self.tcx, ty), ty.span),
                         };
                         (span, format!("expected `{ty}` because of this return type"))
                     });
@@ -578,10 +575,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             // ...but otherwise we want to use any supertype of the
             // scrutinee. This is sort of a workaround, see note (*) in
             // `check_pat` for some details.
-            let scrut_ty = self.next_ty_var(TypeVariableOrigin {
-                kind: TypeVariableOriginKind::TypeInference,
-                span: scrut.span,
-            });
+            let scrut_ty =
+                self.next_ty_var(TypeVariableOrigin { param_def_id: None, span: scrut.span });
             self.check_expr_has_type_or_error(scrut, scrut_ty, |_| {});
             scrut_ty
         }
diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs
index aa94632b2b0..a64d3b9633f 100644
--- a/compiler/rustc_hir_typeck/src/callee.rs
+++ b/compiler/rustc_hir_typeck/src/callee.rs
@@ -13,10 +13,7 @@ use rustc_infer::{
     infer,
     traits::{self, Obligation},
 };
-use rustc_infer::{
-    infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind},
-    traits::ObligationCause,
-};
+use rustc_infer::{infer::type_variable::TypeVariableOrigin, traits::ObligationCause};
 use rustc_middle::ty::adjustment::{
     Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability,
 };
@@ -180,18 +177,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     infer::FnCall,
                     closure_args.coroutine_closure_sig(),
                 );
-                let tupled_upvars_ty = self.next_ty_var(TypeVariableOrigin {
-                    kind: TypeVariableOriginKind::TypeInference,
-                    span: callee_expr.span,
-                });
+                let tupled_upvars_ty = self
+                    .next_ty_var(TypeVariableOrigin { param_def_id: None, span: callee_expr.span });
                 // We may actually receive a coroutine back whose kind is different
                 // from the closure that this dispatched from. This is because when
                 // we have no captures, we automatically implement `FnOnce`. This
                 // impl forces the closure kind to `FnOnce` i.e. `u8`.
-                let kind_ty = self.next_ty_var(TypeVariableOrigin {
-                    kind: TypeVariableOriginKind::TypeInference,
-                    span: callee_expr.span,
-                });
+                let kind_ty = self
+                    .next_ty_var(TypeVariableOrigin { param_def_id: None, span: callee_expr.span });
                 let call_sig = self.tcx.mk_fn_sig(
                     [coroutine_closure_sig.tupled_inputs_ty],
                     coroutine_closure_sig.to_coroutine(
@@ -305,10 +298,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 Ty::new_tup_from_iter(
                     self.tcx,
                     arg_exprs.iter().map(|e| {
-                        self.next_ty_var(TypeVariableOrigin {
-                            kind: TypeVariableOriginKind::TypeInference,
-                            span: e.span,
-                        })
+                        self.next_ty_var(TypeVariableOrigin { param_def_id: None, span: e.span })
                     }),
                 )
             });
@@ -724,7 +714,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 def::CtorOf::Variant => "enum variant",
             };
             let removal_span = callee_expr.span.shrink_to_hi().to(call_expr.span.shrink_to_hi());
-            unit_variant = Some((removal_span, descr, rustc_hir_pretty::qpath_to_string(qpath)));
+            unit_variant =
+                Some((removal_span, descr, rustc_hir_pretty::qpath_to_string(&self.tcx, qpath)));
         }
 
         let callee_ty = self.resolve_vars_if_possible(callee_ty);
diff --git a/compiler/rustc_hir_typeck/src/check.rs b/compiler/rustc_hir_typeck/src/check.rs
index 59a043d1d69..b0d1b6655db 100644
--- a/compiler/rustc_hir_typeck/src/check.rs
+++ b/compiler/rustc_hir_typeck/src/check.rs
@@ -8,7 +8,7 @@ use rustc_hir::def::DefKind;
 use rustc_hir::intravisit::Visitor;
 use rustc_hir::lang_items::LangItem;
 use rustc_hir_analysis::check::{check_function_signature, forbid_intrinsic_abi};
-use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
+use rustc_infer::infer::type_variable::TypeVariableOrigin;
 use rustc_infer::infer::RegionVariableOrigin;
 use rustc_middle::ty::{self, Binder, Ty, TyCtxt};
 use rustc_span::def_id::LocalDefId;
@@ -123,8 +123,7 @@ pub(super) fn check_fn<'a, 'tcx>(
         // We have special-cased the case where the function is declared
         // `-> dyn Foo` and we don't actually relate it to the
         // `fcx.ret_coercion`, so just instantiate a type variable.
-        actual_return_ty =
-            fcx.next_ty_var(TypeVariableOrigin { kind: TypeVariableOriginKind::DynReturnFn, span });
+        actual_return_ty = fcx.next_ty_var(TypeVariableOrigin { param_def_id: None, span });
         debug!("actual_return_ty replaced with {:?}", actual_return_ty);
     }
 
diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs
index dbae8bfb542..d6704d9e44f 100644
--- a/compiler/rustc_hir_typeck/src/closure.rs
+++ b/compiler/rustc_hir_typeck/src/closure.rs
@@ -6,7 +6,7 @@ use rustc_errors::ErrorGuaranteed;
 use rustc_hir as hir;
 use rustc_hir::lang_items::LangItem;
 use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer;
-use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
+use rustc_infer::infer::type_variable::TypeVariableOrigin;
 use rustc_infer::infer::{BoundRegionConversionTime, DefineOpaqueTypes};
 use rustc_infer::infer::{InferOk, InferResult};
 use rustc_macros::{TypeFoldable, TypeVisitable};
@@ -72,10 +72,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let parent_args =
             GenericArgs::identity_for_item(tcx, tcx.typeck_root_def_id(expr_def_id.to_def_id()));
 
-        let tupled_upvars_ty = self.next_ty_var(TypeVariableOrigin {
-            kind: TypeVariableOriginKind::ClosureSynthetic,
-            span: expr_span,
-        });
+        let tupled_upvars_ty =
+            self.next_ty_var(TypeVariableOrigin { param_def_id: None, span: expr_span });
 
         // FIXME: We could probably actually just unify this further --
         // instead of having a `FnSig` and a `Option<CoroutineTypes>`,
@@ -102,11 +100,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
                     // Create a type variable (for now) to represent the closure kind.
                     // It will be unified during the upvar inference phase (`upvar.rs`)
-                    None => self.next_ty_var(TypeVariableOrigin {
-                        // FIXME(eddyb) distinguish closure kind inference variables from the rest.
-                        kind: TypeVariableOriginKind::ClosureSynthetic,
-                        span: expr_span,
-                    }),
+                    None => {
+                        self.next_ty_var(TypeVariableOrigin { param_def_id: None, span: expr_span })
+                    }
                 };
 
                 let closure_args = ty::ClosureArgs::new(
@@ -126,7 +122,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Gen, _)
                     | hir::CoroutineKind::Coroutine(_) => {
                         let yield_ty = self.next_ty_var(TypeVariableOrigin {
-                            kind: TypeVariableOriginKind::ClosureSynthetic,
+                            param_def_id: None,
                             span: expr_span,
                         });
                         self.require_type_is_sized(yield_ty, expr_span, traits::SizedYieldType);
@@ -138,7 +134,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     // not a problem.
                     hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::AsyncGen, _) => {
                         let yield_ty = self.next_ty_var(TypeVariableOrigin {
-                            kind: TypeVariableOriginKind::ClosureSynthetic,
+                            param_def_id: None,
                             span: expr_span,
                         });
                         self.require_type_is_sized(yield_ty, expr_span, traits::SizedYieldType);
@@ -166,10 +162,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 // Resume type defaults to `()` if the coroutine has no argument.
                 let resume_ty = liberated_sig.inputs().get(0).copied().unwrap_or(tcx.types.unit);
 
-                let interior = self.next_ty_var(TypeVariableOrigin {
-                    kind: TypeVariableOriginKind::ClosureSynthetic,
-                    span: expr_span,
-                });
+                let interior =
+                    self.next_ty_var(TypeVariableOrigin { param_def_id: None, span: expr_span });
                 self.deferred_coroutine_interiors.borrow_mut().push((
                     expr_def_id,
                     body.id(),
@@ -181,11 +175,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 // later during upvar analysis. Regular coroutines always have the kind
                 // ty of `().`
                 let kind_ty = match kind {
-                    hir::CoroutineKind::Desugared(_, hir::CoroutineSource::Closure) => self
-                        .next_ty_var(TypeVariableOrigin {
-                            kind: TypeVariableOriginKind::ClosureSynthetic,
-                            span: expr_span,
-                        }),
+                    hir::CoroutineKind::Desugared(_, hir::CoroutineSource::Closure) => {
+                        self.next_ty_var(TypeVariableOrigin { param_def_id: None, span: expr_span })
+                    }
                     _ => tcx.types.unit,
                 };
 
@@ -219,30 +211,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     }
                 };
                 // Compute all of the variables that will be used to populate the coroutine.
-                let resume_ty = self.next_ty_var(TypeVariableOrigin {
-                    kind: TypeVariableOriginKind::ClosureSynthetic,
-                    span: expr_span,
-                });
-                let interior = self.next_ty_var(TypeVariableOrigin {
-                    kind: TypeVariableOriginKind::ClosureSynthetic,
-                    span: expr_span,
-                });
+                let resume_ty =
+                    self.next_ty_var(TypeVariableOrigin { param_def_id: None, span: expr_span });
+                let interior =
+                    self.next_ty_var(TypeVariableOrigin { param_def_id: None, span: expr_span });
 
                 let closure_kind_ty = match expected_kind {
                     Some(kind) => Ty::from_closure_kind(tcx, kind),
 
                     // Create a type variable (for now) to represent the closure kind.
                     // It will be unified during the upvar inference phase (`upvar.rs`)
-                    None => self.next_ty_var(TypeVariableOrigin {
-                        kind: TypeVariableOriginKind::ClosureSynthetic,
-                        span: expr_span,
-                    }),
+                    None => {
+                        self.next_ty_var(TypeVariableOrigin { param_def_id: None, span: expr_span })
+                    }
                 };
 
-                let coroutine_captures_by_ref_ty = self.next_ty_var(TypeVariableOrigin {
-                    kind: TypeVariableOriginKind::ClosureSynthetic,
-                    span: expr_span,
-                });
+                let coroutine_captures_by_ref_ty =
+                    self.next_ty_var(TypeVariableOrigin { param_def_id: None, span: expr_span });
                 let closure_args = ty::CoroutineClosureArgs::new(
                     tcx,
                     ty::CoroutineClosureArgsParts {
@@ -274,16 +259,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
                     // Create a type variable (for now) to represent the closure kind.
                     // It will be unified during the upvar inference phase (`upvar.rs`)
-                    None => self.next_ty_var(TypeVariableOrigin {
-                        kind: TypeVariableOriginKind::ClosureSynthetic,
-                        span: expr_span,
-                    }),
+                    None => {
+                        self.next_ty_var(TypeVariableOrigin { param_def_id: None, span: expr_span })
+                    }
                 };
 
-                let coroutine_upvars_ty = self.next_ty_var(TypeVariableOrigin {
-                    kind: TypeVariableOriginKind::ClosureSynthetic,
-                    span: expr_span,
-                });
+                let coroutine_upvars_ty =
+                    self.next_ty_var(TypeVariableOrigin { param_def_id: None, span: expr_span });
 
                 // We need to turn the liberated signature that we got from HIR, which
                 // looks something like `|Args...| -> T`, into a signature that is suitable
diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs
index 079cca82408..9ebb5f95f05 100644
--- a/compiler/rustc_hir_typeck/src/coercion.rs
+++ b/compiler/rustc_hir_typeck/src/coercion.rs
@@ -43,7 +43,7 @@ use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::intravisit::{self, Visitor};
 use rustc_hir::Expr;
 use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer;
-use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
+use rustc_infer::infer::type_variable::TypeVariableOrigin;
 use rustc_infer::infer::{Coercion, DefineOpaqueTypes, InferOk, InferResult};
 use rustc_infer::traits::TraitEngineExt as _;
 use rustc_infer::traits::{IfExpressionCause, MatchExpressionArmCause, TraitEngine};
@@ -59,8 +59,7 @@ use rustc_middle::ty::visit::TypeVisitableExt;
 use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt};
 use rustc_session::parse::feature_err;
 use rustc_span::symbol::sym;
-use rustc_span::DesugaringKind;
-use rustc_span::{BytePos, Span};
+use rustc_span::{BytePos, DesugaringKind, Span, DUMMY_SP};
 use rustc_target::spec::abi::Abi;
 use rustc_trait_selection::infer::InferCtxtExt as _;
 use rustc_trait_selection::traits::error_reporting::suggestions::TypeErrCtxtExt;
@@ -280,10 +279,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
         if b.is_ty_var() {
             // Two unresolved type variables: create a `Coerce` predicate.
             let target_ty = if self.use_lub {
-                self.next_ty_var(TypeVariableOrigin {
-                    kind: TypeVariableOriginKind::LatticeVariable,
-                    span: self.cause.span,
-                })
+                self.next_ty_var(TypeVariableOrigin { param_def_id: None, span: self.cause.span })
             } else {
                 b
             };
@@ -582,10 +578,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
         // the `CoerceUnsized` target type and the expected type.
         // We only have the latter, so we use an inference variable
         // for the former and let type inference do the rest.
-        let origin = TypeVariableOrigin {
-            kind: TypeVariableOriginKind::MiscVariable,
-            span: self.cause.span,
-        };
+        let origin = TypeVariableOrigin { param_def_id: None, span: self.cause.span };
         let coerce_target = self.next_ty_var(origin);
         let mut coercion = self.unify_and(coerce_target, target, |target| {
             let unsize = Adjustment { kind: Adjust::Pointer(PointerCoercion::Unsize), target };
@@ -1051,7 +1044,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let source = self.resolve_vars_with_obligations(expr_ty);
         debug!("coercion::can_with_predicates({:?} -> {:?})", source, target);
 
-        let cause = self.cause(rustc_span::DUMMY_SP, ObligationCauseCode::ExprAssignable);
+        let cause = self.cause(DUMMY_SP, ObligationCauseCode::ExprAssignable);
         // We don't ever need two-phase here since we throw out the result of the coercion
         let coerce = Coerce::new(self, cause, AllowTwoPhase::No);
         self.probe(|_| {
@@ -1068,11 +1061,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     /// how many dereference steps needed to achieve `expr_ty <: target`. If
     /// it's not possible, return `None`.
     pub fn deref_steps(&self, expr_ty: Ty<'tcx>, target: Ty<'tcx>) -> Option<usize> {
-        let cause = self.cause(rustc_span::DUMMY_SP, ObligationCauseCode::ExprAssignable);
+        let cause = self.cause(DUMMY_SP, ObligationCauseCode::ExprAssignable);
         // We don't ever need two-phase here since we throw out the result of the coercion
         let coerce = Coerce::new(self, cause, AllowTwoPhase::No);
         coerce
-            .autoderef(rustc_span::DUMMY_SP, expr_ty)
+            .autoderef(DUMMY_SP, expr_ty)
             .find_map(|(ty, steps)| self.probe(|_| coerce.unify(ty, target)).ok().map(|_| steps))
     }
 
@@ -1083,7 +1076,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     /// trait or region sub-obligations. (presumably we could, but it's not
     /// particularly important for diagnostics...)
     pub fn deref_once_mutably_for_diagnostic(&self, expr_ty: Ty<'tcx>) -> Option<Ty<'tcx>> {
-        self.autoderef(rustc_span::DUMMY_SP, expr_ty).nth(1).and_then(|(deref_ty, _)| {
+        self.autoderef(DUMMY_SP, expr_ty).nth(1).and_then(|(deref_ty, _)| {
             self.infcx
                 .type_implements_trait(
                     self.tcx.lang_items().deref_mut_trait()?,
diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs
index 75a68f16cf1..d6d22a43fe0 100644
--- a/compiler/rustc_hir_typeck/src/demand.rs
+++ b/compiler/rustc_hir_typeck/src/demand.rs
@@ -337,10 +337,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             ty_op: |ty| {
                 if let ty::Infer(infer) = ty.kind() {
                     match infer {
-                        ty::TyVar(_) => self.next_ty_var(TypeVariableOrigin {
-                            kind: TypeVariableOriginKind::MiscVariable,
-                            span: DUMMY_SP,
-                        }),
+                        ty::TyVar(_) => self
+                            .next_ty_var(TypeVariableOrigin { param_def_id: None, span: DUMMY_SP }),
                         ty::IntVar(_) => self.next_int_var(),
                         ty::FloatVar(_) => self.next_float_var(),
                         ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_) => {
@@ -356,10 +354,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 if let ty::ConstKind::Infer(_) = ct.kind() {
                     self.next_const_var(
                         ct.ty(),
-                        ConstVariableOrigin {
-                            kind: ConstVariableOriginKind::MiscVariable,
-                            span: DUMMY_SP,
-                        },
+                        ConstVariableOrigin { param_def_id: None, span: DUMMY_SP },
                     )
                 } else {
                     ct
diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs
index d399730bf3d..3dc9c7b86f7 100644
--- a/compiler/rustc_hir_typeck/src/errors.rs
+++ b/compiler/rustc_hir_typeck/src/errors.rs
@@ -632,3 +632,11 @@ pub enum SuggestBoxingForReturnImplTrait {
         ends: Vec<Span>,
     },
 }
+
+#[derive(LintDiagnostic)]
+#[diag(hir_typeck_dereferencing_mut_binding)]
+pub struct DereferencingMutBinding {
+    #[label]
+    #[help]
+    pub span: Span,
+}
diff --git a/compiler/rustc_hir_typeck/src/expectation.rs b/compiler/rustc_hir_typeck/src/expectation.rs
index ff84e753d70..5106d29091a 100644
--- a/compiler/rustc_hir_typeck/src/expectation.rs
+++ b/compiler/rustc_hir_typeck/src/expectation.rs
@@ -1,4 +1,4 @@
-use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
+use rustc_infer::infer::type_variable::TypeVariableOrigin;
 use rustc_middle::ty::{self, Ty};
 use rustc_span::Span;
 
@@ -110,8 +110,7 @@ impl<'a, 'tcx> Expectation<'tcx> {
     /// Like `only_has_type`, but instead of returning `None` if no
     /// hard constraint exists, creates a fresh type variable.
     pub(super) fn coercion_target_type(self, fcx: &FnCtxt<'a, 'tcx>, span: Span) -> Ty<'tcx> {
-        self.only_has_type(fcx).unwrap_or_else(|| {
-            fcx.next_ty_var(TypeVariableOrigin { kind: TypeVariableOriginKind::MiscVariable, span })
-        })
+        self.only_has_type(fcx)
+            .unwrap_or_else(|| fcx.next_ty_var(TypeVariableOrigin { param_def_id: None, span }))
     }
 }
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index 64590ca542d..8923137fdd8 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -37,7 +37,7 @@ use rustc_hir::lang_items::LangItem;
 use rustc_hir::{ExprKind, HirId, QPath};
 use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer as _;
 use rustc_infer::infer;
-use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
+use rustc_infer::infer::type_variable::TypeVariableOrigin;
 use rustc_infer::infer::DefineOpaqueTypes;
 use rustc_infer::infer::InferOk;
 use rustc_infer::traits::query::NoSolution;
@@ -54,7 +54,6 @@ use rustc_span::source_map::Spanned;
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::Span;
 use rustc_target::abi::{FieldIdx, FIRST_VARIANT};
-use rustc_target::spec::abi::Abi::RustIntrinsic;
 use rustc_trait_selection::infer::InferCtxtExt;
 use rustc_trait_selection::traits::error_reporting::suggestions::TypeErrCtxtExt as _;
 use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
@@ -81,10 +80,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 return Ty::new_error(self.tcx(), reported);
             }
 
-            let adj_ty = self.next_ty_var(TypeVariableOrigin {
-                kind: TypeVariableOriginKind::AdjustmentType,
-                span: expr.span,
-            });
+            let adj_ty =
+                self.next_ty_var(TypeVariableOrigin { param_def_id: None, span: expr.span });
             self.apply_adjustments(
                 expr,
                 vec![Adjustment { kind: Adjust::NeverToAny, target: adj_ty }],
@@ -541,16 +538,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         if let ty::FnDef(did, _) = *ty.kind() {
             let fn_sig = ty.fn_sig(tcx);
 
-            if tcx.fn_sig(did).skip_binder().abi() == RustIntrinsic
-                && tcx.item_name(did) == sym::transmute
-            {
+            if tcx.is_intrinsic(did, sym::transmute) {
                 let Some(from) = fn_sig.inputs().skip_binder().get(0) else {
-                    let e = self.dcx().span_delayed_bug(
+                    span_bug!(
                         tcx.def_span(did),
-                        "intrinsic fn `transmute` defined with no parameters",
+                        "intrinsic fn `transmute` defined with no parameters"
                     );
-                    self.set_tainted_by_errors(e);
-                    return Ty::new_error(tcx, e);
                 };
                 let to = fn_sig.output().skip_binder();
                 // We defer the transmute to the end of typeck, once all inference vars have
@@ -1420,10 +1413,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     _ => None,
                 })
                 .unwrap_or_else(|| {
-                    self.next_ty_var(TypeVariableOrigin {
-                        kind: TypeVariableOriginKind::TypeInference,
-                        span: expr.span,
-                    })
+                    self.next_ty_var(TypeVariableOrigin { param_def_id: None, span: expr.span })
                 });
             let mut coerce = CoerceMany::with_coercion_sites(coerce_to, args);
             assert_eq!(self.diverges.get(), Diverges::Maybe);
@@ -1434,10 +1424,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             }
             coerce.complete(self)
         } else {
-            self.next_ty_var(TypeVariableOrigin {
-                kind: TypeVariableOriginKind::TypeInference,
-                span: expr.span,
-            })
+            self.next_ty_var(TypeVariableOrigin { param_def_id: None, span: expr.span })
         };
         let array_len = args.len() as u64;
         self.suggest_array_len(expr, array_len);
@@ -1520,10 +1507,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 (uty, uty)
             }
             None => {
-                let ty = self.next_ty_var(TypeVariableOrigin {
-                    kind: TypeVariableOriginKind::MiscVariable,
-                    span: element.span,
-                });
+                let ty =
+                    self.next_ty_var(TypeVariableOrigin { param_def_id: None, span: element.span });
                 let element_ty = self.check_expr_has_type_or_error(element, ty, |_| {});
                 (element_ty, ty)
             }
@@ -2866,7 +2851,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         span: Span,
         base_ty: Ty<'tcx>,
         mod_id: DefId,
-        hir_id: hir::HirId,
+        hir_id: HirId,
     ) -> Vec<(Vec<&'tcx ty::FieldDef>, GenericArgsRef<'tcx>)> {
         debug!("get_field_candidates(span: {:?}, base_t: {:?}", span, base_ty);
 
diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
index 5986b959666..a0a5a75d382 100644
--- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
+++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
@@ -13,7 +13,7 @@ use rustc_data_structures::fx::FxIndexMap;
 use rustc_hir as hir;
 use rustc_hir::def::Res;
 use rustc_hir::def_id::LocalDefId;
-use rustc_hir::PatKind;
+use rustc_hir::{HirId, PatKind};
 use rustc_infer::infer::InferCtxt;
 use rustc_middle::hir::place::ProjectionKind;
 use rustc_middle::mir::FakeReadCause;
@@ -39,20 +39,20 @@ pub trait Delegate<'tcx> {
     /// diagnostics. Around pattern matching such as `let pat = expr`, the diagnostic
     /// id will be the id of the expression `expr` but the place itself will have
     /// the id of the binding in the pattern `pat`.
-    fn consume(&mut self, place_with_id: &PlaceWithHirId<'tcx>, diag_expr_id: hir::HirId);
+    fn consume(&mut self, place_with_id: &PlaceWithHirId<'tcx>, diag_expr_id: HirId);
 
     /// The value found at `place` is being borrowed with kind `bk`.
     /// `diag_expr_id` is the id used for diagnostics (see `consume` for more details).
     fn borrow(
         &mut self,
         place_with_id: &PlaceWithHirId<'tcx>,
-        diag_expr_id: hir::HirId,
+        diag_expr_id: HirId,
         bk: ty::BorrowKind,
     );
 
     /// The value found at `place` is being copied.
     /// `diag_expr_id` is the id used for diagnostics (see `consume` for more details).
-    fn copy(&mut self, place_with_id: &PlaceWithHirId<'tcx>, diag_expr_id: hir::HirId) {
+    fn copy(&mut self, place_with_id: &PlaceWithHirId<'tcx>, diag_expr_id: HirId) {
         // In most cases, copying data from `x` is equivalent to doing `*&x`, so by default
         // we treat a copy of `x` as a borrow of `x`.
         self.borrow(place_with_id, diag_expr_id, ty::BorrowKind::ImmBorrow)
@@ -60,12 +60,12 @@ pub trait Delegate<'tcx> {
 
     /// The path at `assignee_place` is being assigned to.
     /// `diag_expr_id` is the id used for diagnostics (see `consume` for more details).
-    fn mutate(&mut self, assignee_place: &PlaceWithHirId<'tcx>, diag_expr_id: hir::HirId);
+    fn mutate(&mut self, assignee_place: &PlaceWithHirId<'tcx>, diag_expr_id: HirId);
 
     /// The path at `binding_place` is a binding that is being initialized.
     ///
     /// This covers cases such as `let x = 42;`
-    fn bind(&mut self, binding_place: &PlaceWithHirId<'tcx>, diag_expr_id: hir::HirId) {
+    fn bind(&mut self, binding_place: &PlaceWithHirId<'tcx>, diag_expr_id: HirId) {
         // Bindings can normally be treated as a regular assignment, so by default we
         // forward this to the mutate callback.
         self.mutate(binding_place, diag_expr_id)
@@ -76,7 +76,7 @@ pub trait Delegate<'tcx> {
         &mut self,
         place_with_id: &PlaceWithHirId<'tcx>,
         cause: FakeReadCause,
-        diag_expr_id: hir::HirId,
+        diag_expr_id: HirId,
     );
 }
 
@@ -154,7 +154,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
         self.mc.tcx()
     }
 
-    fn delegate_consume(&mut self, place_with_id: &PlaceWithHirId<'tcx>, diag_expr_id: hir::HirId) {
+    fn delegate_consume(&mut self, place_with_id: &PlaceWithHirId<'tcx>, diag_expr_id: HirId) {
         delegate_consume(&self.mc, self.delegate, place_with_id, diag_expr_id)
     }
 
@@ -775,8 +775,8 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
     /// closure as the DefId.
     fn walk_captures(&mut self, closure_expr: &hir::Closure<'_>) {
         fn upvar_is_local_variable(
-            upvars: Option<&FxIndexMap<hir::HirId, hir::Upvar>>,
-            upvar_id: hir::HirId,
+            upvars: Option<&FxIndexMap<HirId, hir::Upvar>>,
+            upvar_id: HirId,
             body_owner_is_closure: bool,
         ) -> bool {
             upvars.map(|upvars| !upvars.contains_key(&upvar_id)).unwrap_or(body_owner_is_closure)
@@ -902,7 +902,7 @@ fn delegate_consume<'a, 'tcx>(
     mc: &mc::MemCategorizationContext<'a, 'tcx>,
     delegate: &mut (dyn Delegate<'tcx> + 'a),
     place_with_id: &PlaceWithHirId<'tcx>,
-    diag_expr_id: hir::HirId,
+    diag_expr_id: HirId,
 ) {
     debug!("delegate_consume(place_with_id={:?})", place_with_id);
 
diff --git a/compiler/rustc_hir_typeck/src/fallback.rs b/compiler/rustc_hir_typeck/src/fallback.rs
index 69399b50695..c0b3984e3e1 100644
--- a/compiler/rustc_hir_typeck/src/fallback.rs
+++ b/compiler/rustc_hir_typeck/src/fallback.rs
@@ -5,6 +5,7 @@ use rustc_data_structures::{
 };
 use rustc_infer::infer::{DefineOpaqueTypes, InferOk};
 use rustc_middle::ty::{self, Ty};
+use rustc_span::DUMMY_SP;
 
 #[derive(Copy, Clone)]
 pub enum DivergingFallbackBehavior {
@@ -102,7 +103,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
         // that field is only used for type fallback diagnostics.
         for effect in unsolved_effects {
             let expected = self.tcx.consts.true_;
-            let cause = self.misc(rustc_span::DUMMY_SP);
+            let cause = self.misc(DUMMY_SP);
             match self.at(&cause, self.param_env).eq(DefineOpaqueTypes::Yes, expected, effect) {
                 Ok(InferOk { obligations, value: () }) => {
                     self.register_predicates(obligations);
@@ -165,11 +166,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
         };
         debug!("fallback_if_possible(ty={:?}): defaulting to `{:?}`", ty, fallback);
 
-        let span = self
-            .infcx
-            .type_var_origin(ty)
-            .map(|origin| origin.span)
-            .unwrap_or(rustc_span::DUMMY_SP);
+        let span = self.infcx.type_var_origin(ty).map(|origin| origin.span).unwrap_or(DUMMY_SP);
         self.demand_eqtype(span, ty, fallback);
         self.fallback_has_occurred.set(true);
         true
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
index 2d5ba447e4e..786754ed12f 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
@@ -10,7 +10,7 @@ use rustc_hir as hir;
 use rustc_hir::def::{CtorOf, DefKind, Res};
 use rustc_hir::def_id::DefId;
 use rustc_hir::lang_items::LangItem;
-use rustc_hir::{ExprKind, GenericArg, Node, QPath};
+use rustc_hir::{ExprKind, GenericArg, HirId, Node, QPath};
 use rustc_hir_analysis::hir_ty_lowering::errors::GenericsArgsErrExtend;
 use rustc_hir_analysis::hir_ty_lowering::generics::{
     check_generic_arg_count_for_call, lower_generic_args,
@@ -47,7 +47,7 @@ use std::slice;
 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     /// Produces warning on the given node, if the current point in the
     /// function is unreachable, and there hasn't been another warning.
-    pub(in super::super) fn warn_if_unreachable(&self, id: hir::HirId, span: Span, kind: &str) {
+    pub(in super::super) fn warn_if_unreachable(&self, id: HirId, span: Span, kind: &str) {
         // FIXME: Combine these two 'if' expressions into one once
         // let chains are implemented
         if let Diverges::Always { span: orig_span, custom_note } = self.diverges.get() {
@@ -130,14 +130,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         format!("{self:p}")
     }
 
-    pub fn local_ty(&self, span: Span, nid: hir::HirId) -> Ty<'tcx> {
+    pub fn local_ty(&self, span: Span, nid: HirId) -> Ty<'tcx> {
         self.locals.borrow().get(&nid).cloned().unwrap_or_else(|| {
             span_bug!(span, "no type for local variable {}", self.tcx.hir().node_to_string(nid))
         })
     }
 
     #[inline]
-    pub fn write_ty(&self, id: hir::HirId, ty: Ty<'tcx>) {
+    pub fn write_ty(&self, id: HirId, ty: Ty<'tcx>) {
         debug!("write_ty({:?}, {:?}) in fcx {}", id, self.resolve_vars_if_possible(ty), self.tag());
         let mut typeck = self.typeck_results.borrow_mut();
         let mut node_ty = typeck.node_types_mut();
@@ -161,7 +161,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
     pub fn write_field_index(
         &self,
-        hir_id: hir::HirId,
+        hir_id: HirId,
         index: FieldIdx,
         nested_fields: Vec<(Ty<'tcx>, FieldIdx)>,
     ) {
@@ -174,7 +174,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     #[instrument(level = "debug", skip(self))]
     pub(in super::super) fn write_resolution(
         &self,
-        hir_id: hir::HirId,
+        hir_id: HirId,
         r: Result<(DefKind, DefId), ErrorGuaranteed>,
     ) {
         self.typeck_results.borrow_mut().type_dependent_defs_mut().insert(hir_id, r);
@@ -183,7 +183,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     #[instrument(level = "debug", skip(self))]
     pub fn write_method_call_and_enforce_effects(
         &self,
-        hir_id: hir::HirId,
+        hir_id: HirId,
         span: Span,
         method: MethodCallee<'tcx>,
     ) {
@@ -192,7 +192,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         self.write_args(hir_id, method.args);
     }
 
-    pub fn write_args(&self, node_id: hir::HirId, args: GenericArgsRef<'tcx>) {
+    pub fn write_args(&self, node_id: HirId, args: GenericArgsRef<'tcx>) {
         if !args.is_empty() {
             debug!("write_args({:?}, {:?}) in fcx {}", node_id, args, self.tag());
 
@@ -210,7 +210,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     #[instrument(skip(self), level = "debug")]
     pub fn write_user_type_annotation_from_args(
         &self,
-        hir_id: hir::HirId,
+        hir_id: HirId,
         def_id: DefId,
         args: GenericArgsRef<'tcx>,
         user_self_ty: Option<UserSelfTy<'tcx>>,
@@ -230,7 +230,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     #[instrument(skip(self), level = "debug")]
     pub fn write_user_type_annotation(
         &self,
-        hir_id: hir::HirId,
+        hir_id: HirId,
         canonical_user_type_annotation: CanonicalUserType<'tcx>,
     ) {
         debug!("fcx {}", self.tag());
@@ -464,7 +464,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         t.has_free_regions() || t.has_aliases() || t.has_infer_types()
     }
 
-    pub fn node_ty(&self, id: hir::HirId) -> Ty<'tcx> {
+    pub fn node_ty(&self, id: HirId) -> Ty<'tcx> {
         match self.typeck_results.borrow().node_types().get(id) {
             Some(&t) => t,
             None if let Some(e) = self.tainted_by_errors() => Ty::new_error(self.tcx, e),
@@ -478,7 +478,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         }
     }
 
-    pub fn node_ty_opt(&self, id: hir::HirId) -> Option<Ty<'tcx>> {
+    pub fn node_ty_opt(&self, id: HirId) -> Option<Ty<'tcx>> {
         match self.typeck_results.borrow().node_types().get(id) {
             Some(&t) => Some(t),
             None if let Some(e) = self.tainted_by_errors() => Some(Ty::new_error(self.tcx, e)),
@@ -742,7 +742,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         &self,
         lang_item: hir::LangItem,
         span: Span,
-        hir_id: hir::HirId,
+        hir_id: HirId,
     ) -> (Res, Ty<'tcx>) {
         let def_id = self.tcx.require_lang_item(lang_item, Some(span));
         let def_kind = self.tcx.def_kind(def_id);
@@ -790,7 +790,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     pub fn resolve_ty_and_res_fully_qualified_call(
         &self,
         qpath: &'tcx QPath<'tcx>,
-        hir_id: hir::HirId,
+        hir_id: HirId,
         span: Span,
         args: Option<&'tcx [hir::Expr<'tcx>]>,
     ) -> (Res, Option<LoweredTy<'tcx>>, &'tcx [hir::PathSegment<'tcx>]) {
@@ -984,7 +984,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     /// suggestion can be made, `None` otherwise.
     pub fn get_fn_decl(
         &self,
-        blk_id: hir::HirId,
+        blk_id: HirId,
     ) -> Option<(LocalDefId, &'tcx hir::FnDecl<'tcx>, bool)> {
         // Get enclosing Fn, if it is a function or a trait method, unless there's a `loop` or
         // `while` before reaching it, as block tail returns are not available in them.
@@ -1080,7 +1080,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         res: Res,
         span: Span,
         path_span: Span,
-        hir_id: hir::HirId,
+        hir_id: HirId,
     ) -> (Ty<'tcx>, Res) {
         let tcx = self.tcx;
 
@@ -1450,7 +1450,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         span: Span,
         def_id: DefId,
         args: GenericArgsRef<'tcx>,
-        hir_id: hir::HirId,
+        hir_id: HirId,
     ) {
         self.add_required_obligations_with_code(span, def_id, args, |idx, span| {
             if span.is_dummy() {
@@ -1541,7 +1541,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
     pub(in super::super) fn with_breakable_ctxt<F: FnOnce() -> R, R>(
         &self,
-        id: hir::HirId,
+        id: HirId,
         ctxt: BreakableCtxt<'tcx>,
         f: F,
     ) -> (BreakableCtxt<'tcx>, R) {
@@ -1580,7 +1580,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     }
 
     /// Returns `true` if an expression is contained inside the LHS of an assignment expression.
-    pub(in super::super) fn expr_in_place(&self, mut expr_id: hir::HirId) -> bool {
+    pub(in super::super) fn expr_in_place(&self, mut expr_id: HirId) -> bool {
         let mut contained_in_place = false;
 
         while let hir::Node::Expr(parent_expr) = self.tcx.parent_hir_node(expr_id) {
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 789cc52169b..a718760f4d8 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
@@ -2,7 +2,7 @@ use crate::FnCtxt;
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::DefId;
-use rustc_infer::{infer::type_variable::TypeVariableOriginKind, traits::ObligationCauseCode};
+use rustc_infer::traits::ObligationCauseCode;
 use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor};
 use rustc_span::{symbol::kw, Span};
 use rustc_trait_selection::traits;
@@ -340,7 +340,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             type Result = ControlFlow<ty::GenericArg<'tcx>>;
             fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result {
                 if let Some(origin) = self.0.type_var_origin(ty)
-                    && let TypeVariableOriginKind::TypeParameterDefinition(_, def_id) = origin.kind
+                    && let Some(def_id) = origin.param_def_id
                     && 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(arg) =
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
index 13226d304c8..4a73ce2e640 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
@@ -24,14 +24,14 @@ use rustc_hir as hir;
 use rustc_hir::def::{CtorOf, DefKind, Res};
 use rustc_hir::def_id::DefId;
 use rustc_hir::intravisit::Visitor;
-use rustc_hir::{ExprKind, Node, QPath};
+use rustc_hir::{ExprKind, HirId, Node, QPath};
 use rustc_hir_analysis::check::intrinsicck::InlineAsmCtxt;
 use rustc_hir_analysis::check::potentially_plural_count;
 use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer;
 use rustc_hir_analysis::structured_errors::StructuredDiag;
 use rustc_index::IndexVec;
 use rustc_infer::infer::error_reporting::{FailureCode, ObligationCauseExt};
-use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
+use rustc_infer::infer::type_variable::TypeVariableOrigin;
 use rustc_infer::infer::TypeTrace;
 use rustc_infer::infer::{DefineOpaqueTypes, InferOk};
 use rustc_middle::traits::ObligationCauseCode::ExprBindingObligation;
@@ -1489,7 +1489,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     pub fn check_struct_path(
         &self,
         qpath: &QPath<'tcx>,
-        hir_id: hir::HirId,
+        hir_id: HirId,
     ) -> Result<(&'tcx ty::VariantDef, Ty<'tcx>), ErrorGuaranteed> {
         let path_span = qpath.span();
         let (def, ty) = self.finish_resolving_struct_path(qpath, path_span, hir_id);
@@ -1554,7 +1554,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
     pub fn check_decl_initializer(
         &self,
-        hir_id: hir::HirId,
+        hir_id: HirId,
         pat: &'tcx hir::Pat<'tcx>,
         init: &'tcx hir::Expr<'tcx>,
     ) -> Ty<'tcx> {
@@ -1879,7 +1879,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         ty
     }
 
-    fn parent_item_span(&self, id: hir::HirId) -> Option<Span> {
+    fn parent_item_span(&self, id: HirId) -> Option<Span> {
         let node = self.tcx.hir_node_by_def_id(self.tcx.hir().get_parent_item(id).def_id);
         match node {
             Node::Item(&hir::Item { kind: hir::ItemKind::Fn(_, _, body_id), .. })
@@ -1897,7 +1897,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     /// Given a function block's `HirId`, returns its `FnDecl` if it exists, or `None` otherwise.
     pub(crate) fn get_parent_fn_decl(
         &self,
-        blk_id: hir::HirId,
+        blk_id: HirId,
     ) -> Option<(&'tcx hir::FnDecl<'tcx>, Ident)> {
         let parent = self.tcx.hir_node_by_def_id(self.tcx.hir().get_parent_item(blk_id).def_id);
         self.get_node_fn_decl(parent).map(|(_, fn_decl, ident, _)| (fn_decl, ident))
@@ -1939,12 +1939,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         expr.span
     }
 
-    fn overwrite_local_ty_if_err(
-        &self,
-        hir_id: hir::HirId,
-        pat: &'tcx hir::Pat<'tcx>,
-        ty: Ty<'tcx>,
-    ) {
+    fn overwrite_local_ty_if_err(&self, hir_id: HirId, pat: &'tcx hir::Pat<'tcx>, ty: Ty<'tcx>) {
         if let Err(guar) = ty.error_reported() {
             struct OverwritePatternsWithError {
                 pat_hir_ids: Vec<hir::HirId>,
@@ -1977,7 +1972,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         &self,
         qpath: &QPath<'tcx>,
         path_span: Span,
-        hir_id: hir::HirId,
+        hir_id: HirId,
     ) -> (Res, LoweredTy<'tcx>) {
         match *qpath {
             QPath::Resolved(ref maybe_qself, path) => {
@@ -2184,7 +2179,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             [
                                 callee_ty,
                                 self.next_ty_var(TypeVariableOrigin {
-                                    kind: TypeVariableOriginKind::MiscVariable,
+                                    param_def_id: None,
                                     span: rustc_span::DUMMY_SP,
                                 }),
                             ],
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
index 0b69c7a2431..080571e1a70 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
@@ -16,8 +16,8 @@ use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer;
 use rustc_infer::infer;
 use rustc_infer::infer::error_reporting::sub_relations::SubRelations;
 use rustc_infer::infer::error_reporting::TypeErrCtxt;
-use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
-use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
+use rustc_infer::infer::type_variable::TypeVariableOrigin;
+use rustc_middle::infer::unify_key::ConstVariableOrigin;
 use rustc_middle::ty::{self, Const, Ty, TyCtxt, TypeVisitableExt};
 use rustc_session::Session;
 use rustc_span::symbol::Ident;
@@ -236,10 +236,7 @@ impl<'a, 'tcx> HirTyLowerer<'tcx> for FnCtxt<'a, 'tcx> {
     fn ty_infer(&self, param: Option<&ty::GenericParamDef>, span: Span) -> Ty<'tcx> {
         match param {
             Some(param) => self.var_for_def(span, param).as_type().unwrap(),
-            None => self.next_ty_var(TypeVariableOrigin {
-                kind: TypeVariableOriginKind::TypeInference,
-                span,
-            }),
+            None => self.next_ty_var(TypeVariableOrigin { param_def_id: None, span }),
         }
     }
 
@@ -258,10 +255,7 @@ impl<'a, 'tcx> HirTyLowerer<'tcx> for FnCtxt<'a, 'tcx> {
                 },
             ) => self.var_for_effect(param).as_const().unwrap(),
             Some(param) => self.var_for_def(span, param).as_const().unwrap(),
-            None => self.next_const_var(
-                ty,
-                ConstVariableOrigin { kind: ConstVariableOriginKind::ConstInference, span },
-            ),
+            None => self.next_const_var(ty, ConstVariableOrigin { span, param_def_id: None }),
         }
     }
 
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
index ce203eae95f..43e5ab0ed53 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
@@ -71,7 +71,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         expr: &'tcx hir::Expr<'tcx>,
         expected: Ty<'tcx>,
         found: Ty<'tcx>,
-        blk_id: hir::HirId,
+        blk_id: HirId,
     ) -> bool {
         let expr = expr.peel_drop_temps();
         let mut pointing_at_return_type = false;
@@ -1031,7 +1031,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         fn_decl: &hir::FnDecl<'tcx>,
         expected: Ty<'tcx>,
         found: Ty<'tcx>,
-        id: hir::HirId,
+        id: HirId,
         fn_id: LocalDefId,
     ) {
         if !expected.is_unit() {
@@ -1600,12 +1600,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         }
     }
 
-    fn is_loop(&self, id: hir::HirId) -> bool {
+    fn is_loop(&self, id: HirId) -> bool {
         let node = self.tcx.hir_node(id);
         matches!(node, Node::Expr(Expr { kind: ExprKind::Loop(..), .. }))
     }
 
-    fn is_local_statement(&self, id: hir::HirId) -> bool {
+    fn is_local_statement(&self, id: HirId) -> bool {
         let node = self.tcx.hir_node(id);
         matches!(node, Node::Stmt(Stmt { kind: StmtKind::Let(..), .. }))
     }
diff --git a/compiler/rustc_hir_typeck/src/gather_locals.rs b/compiler/rustc_hir_typeck/src/gather_locals.rs
index be5cd6e9d48..fe0a46924de 100644
--- a/compiler/rustc_hir_typeck/src/gather_locals.rs
+++ b/compiler/rustc_hir_typeck/src/gather_locals.rs
@@ -1,8 +1,8 @@
 use crate::FnCtxt;
 use rustc_hir as hir;
 use rustc_hir::intravisit::{self, Visitor};
-use rustc_hir::PatKind;
-use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
+use rustc_hir::{HirId, PatKind};
+use rustc_infer::infer::type_variable::TypeVariableOrigin;
 use rustc_middle::ty::Ty;
 use rustc_middle::ty::UserType;
 use rustc_span::def_id::LocalDefId;
@@ -33,7 +33,7 @@ impl<'a> DeclOrigin<'a> {
 ///
 /// It must have a hir_id, as this is how we connect gather_locals to the check functions.
 pub(super) struct Declaration<'a> {
-    pub hir_id: hir::HirId,
+    pub hir_id: HirId,
     pub pat: &'a hir::Pat<'a>,
     pub ty: Option<&'a hir::Ty<'a>>,
     pub span: Span,
@@ -48,8 +48,8 @@ impl<'a> From<&'a hir::LetStmt<'a>> for Declaration<'a> {
     }
 }
 
-impl<'a> From<(&'a hir::LetExpr<'a>, hir::HirId)> for Declaration<'a> {
-    fn from((let_expr, hir_id): (&'a hir::LetExpr<'a>, hir::HirId)) -> Self {
+impl<'a> From<(&'a hir::LetExpr<'a>, HirId)> for Declaration<'a> {
+    fn from((let_expr, hir_id): (&'a hir::LetExpr<'a>, HirId)) -> Self {
         let hir::LetExpr { pat, ty, span, init, is_recovered: _ } = *let_expr;
         Declaration { hir_id, pat, ty, span, init: Some(init), origin: DeclOrigin::LetExpr }
     }
@@ -60,7 +60,7 @@ pub(super) struct GatherLocalsVisitor<'a, 'tcx> {
     // parameters are special cases of patterns, but we want to handle them as
     // *distinct* cases. so track when we are hitting a pattern *within* an fn
     // parameter.
-    outermost_fn_param_pat: Option<(Span, hir::HirId)>,
+    outermost_fn_param_pat: Option<(Span, HirId)>,
 }
 
 impl<'a, 'tcx> GatherLocalsVisitor<'a, 'tcx> {
@@ -68,14 +68,11 @@ impl<'a, 'tcx> GatherLocalsVisitor<'a, 'tcx> {
         Self { fcx, outermost_fn_param_pat: None }
     }
 
-    fn assign(&mut self, span: Span, nid: hir::HirId, ty_opt: Option<Ty<'tcx>>) -> Ty<'tcx> {
+    fn assign(&mut self, span: Span, nid: HirId, ty_opt: Option<Ty<'tcx>>) -> Ty<'tcx> {
         match ty_opt {
             None => {
                 // Infer the variable's type.
-                let var_ty = self.fcx.next_ty_var(TypeVariableOrigin {
-                    kind: TypeVariableOriginKind::TypeInference,
-                    span,
-                });
+                let var_ty = self.fcx.next_ty_var(TypeVariableOrigin { param_def_id: None, span });
                 self.fcx.locals.borrow_mut().insert(nid, var_ty);
                 var_ty
             }
diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs
index 476df9ae793..121815ecc0b 100644
--- a/compiler/rustc_hir_typeck/src/lib.rs
+++ b/compiler/rustc_hir_typeck/src/lib.rs
@@ -56,11 +56,11 @@ use rustc_data_structures::unord::UnordSet;
 use rustc_errors::{codes::*, struct_span_code_err, ErrorGuaranteed};
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
-use rustc_hir::intravisit::{Map, Visitor};
-use rustc_hir::{HirIdMap, Node};
+use rustc_hir::intravisit::Visitor;
+use rustc_hir::{HirId, HirIdMap, Node};
 use rustc_hir_analysis::check::check_abi;
 use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer;
-use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
+use rustc_infer::infer::type_variable::TypeVariableOrigin;
 use rustc_infer::traits::{ObligationCauseCode, ObligationInspector, WellFormedLoc};
 use rustc_middle::query::Providers;
 use rustc_middle::traits;
@@ -261,10 +261,7 @@ fn infer_type_if_missing<'tcx>(fcx: &FnCtxt<'_, 'tcx>, node: Node<'tcx>) -> Opti
                 tcx.impl_trait_ref(item.container_id(tcx)).unwrap().instantiate_identity().args;
             Some(tcx.type_of(trait_item).instantiate(tcx, args))
         } else {
-            Some(fcx.next_ty_var(TypeVariableOrigin {
-                kind: TypeVariableOriginKind::TypeInference,
-                span,
-            }))
+            Some(fcx.next_ty_var(TypeVariableOrigin { span, param_def_id: None }))
         }
     } else if let Node::AnonConst(_) = node {
         let id = tcx.local_def_id_to_hir_id(def_id);
@@ -272,10 +269,7 @@ fn infer_type_if_missing<'tcx>(fcx: &FnCtxt<'_, 'tcx>, node: Node<'tcx>) -> Opti
             Node::Ty(&hir::Ty { kind: hir::TyKind::Typeof(ref anon_const), span, .. })
                 if anon_const.hir_id == id =>
             {
-                Some(fcx.next_ty_var(TypeVariableOrigin {
-                    kind: TypeVariableOriginKind::TypeInference,
-                    span,
-                }))
+                Some(fcx.next_ty_var(TypeVariableOrigin { span, param_def_id: None }))
             }
             Node::Expr(&hir::Expr { kind: hir::ExprKind::InlineAsm(asm), span, .. })
             | Node::Item(&hir::Item { kind: hir::ItemKind::GlobalAsm(asm), span, .. }) => {
@@ -285,10 +279,7 @@ fn infer_type_if_missing<'tcx>(fcx: &FnCtxt<'_, 'tcx>, node: Node<'tcx>) -> Opti
                         Some(fcx.next_int_var())
                     }
                     hir::InlineAsmOperand::SymFn { anon_const } if anon_const.hir_id == id => {
-                        Some(fcx.next_ty_var(TypeVariableOrigin {
-                            kind: TypeVariableOriginKind::MiscVariable,
-                            span,
-                        }))
+                        Some(fcx.next_ty_var(TypeVariableOrigin { span, param_def_id: None }))
                     }
                     _ => None,
                 })
@@ -348,13 +339,13 @@ pub struct EnclosingBreakables<'tcx> {
 }
 
 impl<'tcx> EnclosingBreakables<'tcx> {
-    fn find_breakable(&mut self, target_id: hir::HirId) -> &mut BreakableCtxt<'tcx> {
+    fn find_breakable(&mut self, target_id: HirId) -> &mut BreakableCtxt<'tcx> {
         self.opt_find_breakable(target_id).unwrap_or_else(|| {
             bug!("could not find enclosing breakable with id {}", target_id);
         })
     }
 
-    fn opt_find_breakable(&mut self, target_id: hir::HirId) -> Option<&mut BreakableCtxt<'tcx>> {
+    fn opt_find_breakable(&mut self, target_id: HirId) -> Option<&mut BreakableCtxt<'tcx>> {
         match self.by_id.get(&target_id) {
             Some(ix) => Some(&mut self.stack[*ix]),
             None => None,
@@ -374,7 +365,7 @@ fn report_unexpected_variant_res(
         Res::Def(DefKind::Variant, _) => "struct variant",
         _ => res.descr(),
     };
-    let path_str = rustc_hir_pretty::qpath_to_string(qpath);
+    let path_str = rustc_hir_pretty::qpath_to_string(&tcx, qpath);
     let err = tcx
         .dcx()
         .struct_span_err(span, format!("expected {expected}, found {res_descr} `{path_str}`"))
@@ -436,28 +427,6 @@ fn fatally_break_rust(tcx: TyCtxt<'_>, span: Span) -> ! {
     diag.emit()
 }
 
-pub fn lookup_method_for_diagnostic<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    (def_id, hir_id): (LocalDefId, hir::HirId),
-) -> Option<DefId> {
-    let root_ctxt = TypeckRootCtxt::new(tcx, def_id);
-    let param_env = tcx.param_env(def_id);
-    let fn_ctxt = FnCtxt::new(&root_ctxt, param_env, def_id);
-    let hir::Node::Expr(expr) = tcx.hir().hir_node(hir_id) else {
-        return None;
-    };
-    let hir::ExprKind::MethodCall(segment, rcvr, _, _) = expr.kind else {
-        return None;
-    };
-    let tables = tcx.typeck(def_id);
-    // The found `Self` type of the method call.
-    let possible_rcvr_ty = tables.node_type_opt(rcvr.hir_id)?;
-    fn_ctxt
-        .lookup_method_for_diagnostic(possible_rcvr_ty, segment, expr.span, expr, rcvr)
-        .ok()
-        .map(|method| method.def_id)
-}
-
 pub fn provide(providers: &mut Providers) {
     method::provide(providers);
     *providers = Providers {
@@ -465,7 +434,6 @@ pub fn provide(providers: &mut Providers) {
         diagnostic_only_typeck,
         has_typeck_results,
         used_trait_imports,
-        lookup_method_for_diagnostic: lookup_method_for_diagnostic,
         ..*providers
     };
 }
diff --git a/compiler/rustc_hir_typeck/src/mem_categorization.rs b/compiler/rustc_hir_typeck/src/mem_categorization.rs
index f2425d03449..859877962fe 100644
--- a/compiler/rustc_hir_typeck/src/mem_categorization.rs
+++ b/compiler/rustc_hir_typeck/src/mem_categorization.rs
@@ -58,24 +58,24 @@ use rustc_hir as hir;
 use rustc_hir::def::{CtorOf, DefKind, Res};
 use rustc_hir::def_id::LocalDefId;
 use rustc_hir::pat_util::EnumerateAndAdjustIterator;
-use rustc_hir::PatKind;
+use rustc_hir::{HirId, PatKind};
 use rustc_infer::infer::InferCtxt;
 use rustc_span::Span;
 use rustc_target::abi::{FieldIdx, VariantIdx, FIRST_VARIANT};
 use rustc_trait_selection::infer::InferCtxtExt;
 
 pub(crate) trait HirNode {
-    fn hir_id(&self) -> hir::HirId;
+    fn hir_id(&self) -> HirId;
 }
 
 impl HirNode for hir::Expr<'_> {
-    fn hir_id(&self) -> hir::HirId {
+    fn hir_id(&self) -> HirId {
         self.hir_id
     }
 }
 
 impl HirNode for hir::Pat<'_> {
-    fn hir_id(&self) -> hir::HirId {
+    fn hir_id(&self) -> HirId {
         self.hir_id
     }
 }
@@ -86,7 +86,7 @@ pub(crate) struct MemCategorizationContext<'a, 'tcx> {
     infcx: &'a InferCtxt<'tcx>,
     param_env: ty::ParamEnv<'tcx>,
     body_owner: LocalDefId,
-    upvars: Option<&'tcx FxIndexMap<hir::HirId, hir::Upvar>>,
+    upvars: Option<&'tcx FxIndexMap<HirId, hir::Upvar>>,
 }
 
 pub(crate) type McResult<T> = Result<T, ()>;
@@ -127,11 +127,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
         self.infcx.tainted_by_errors().is_some()
     }
 
-    fn resolve_type_vars_or_error(
-        &self,
-        id: hir::HirId,
-        ty: Option<Ty<'tcx>>,
-    ) -> McResult<Ty<'tcx>> {
+    fn resolve_type_vars_or_error(&self, id: HirId, ty: Option<Ty<'tcx>>) -> McResult<Ty<'tcx>> {
         match ty {
             Some(ty) => {
                 let ty = self.resolve_vars_if_possible(ty);
@@ -153,7 +149,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
         }
     }
 
-    pub(crate) fn node_ty(&self, hir_id: hir::HirId) -> McResult<Ty<'tcx>> {
+    pub(crate) fn node_ty(&self, hir_id: HirId) -> McResult<Ty<'tcx>> {
         self.resolve_type_vars_or_error(hir_id, self.typeck_results.node_type_opt(hir_id))
     }
 
@@ -377,7 +373,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
     #[instrument(level = "debug", skip(self, span), ret)]
     pub(crate) fn cat_res(
         &self,
-        hir_id: hir::HirId,
+        hir_id: HirId,
         span: Span,
         expr_ty: Ty<'tcx>,
         res: Res,
@@ -416,7 +412,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
     /// environment and upvar reference as appropriate. Only regionck cares
     /// about these dereferences, so we let it compute them as needed.
     #[instrument(level = "debug", skip(self), ret)]
-    fn cat_upvar(&self, hir_id: hir::HirId, var_id: hir::HirId) -> McResult<PlaceWithHirId<'tcx>> {
+    fn cat_upvar(&self, hir_id: HirId, var_id: HirId) -> McResult<PlaceWithHirId<'tcx>> {
         let closure_expr_def_id = self.body_owner;
 
         let upvar_id = ty::UpvarId {
@@ -429,7 +425,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
     }
 
     #[instrument(level = "debug", skip(self), ret)]
-    pub(crate) fn cat_rvalue(&self, hir_id: hir::HirId, expr_ty: Ty<'tcx>) -> PlaceWithHirId<'tcx> {
+    pub(crate) fn cat_rvalue(&self, hir_id: HirId, expr_ty: Ty<'tcx>) -> PlaceWithHirId<'tcx> {
         PlaceWithHirId::new(hir_id, expr_ty, PlaceBase::Rvalue, Vec::new())
     }
 
@@ -523,7 +519,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
     fn variant_index_for_adt(
         &self,
         qpath: &hir::QPath<'_>,
-        pat_hir_id: hir::HirId,
+        pat_hir_id: HirId,
         span: Span,
     ) -> McResult<VariantIdx> {
         let res = self.typeck_results.qpath_res(qpath, pat_hir_id);
@@ -556,7 +552,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
     /// Here `pat_hir_id` is the HirId of the pattern itself.
     fn total_fields_in_adt_variant(
         &self,
-        pat_hir_id: hir::HirId,
+        pat_hir_id: HirId,
         variant_index: VariantIdx,
         span: Span,
     ) -> McResult<usize> {
@@ -573,7 +569,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
 
     /// Returns the total number of fields in a tuple used within a Tuple pattern.
     /// Here `pat_hir_id` is the HirId of the pattern itself.
-    fn total_fields_in_tuple(&self, pat_hir_id: hir::HirId, span: Span) -> McResult<usize> {
+    fn total_fields_in_tuple(&self, pat_hir_id: HirId, span: Span) -> McResult<usize> {
         let ty = self.typeck_results.node_type(pat_hir_id);
         match ty.kind() {
             ty::Tuple(args) => Ok(args.len()),
diff --git a/compiler/rustc_hir_typeck/src/method/confirm.rs b/compiler/rustc_hir_typeck/src/method/confirm.rs
index 36860e446fc..02759064abd 100644
--- a/compiler/rustc_hir_typeck/src/method/confirm.rs
+++ b/compiler/rustc_hir_typeck/src/method/confirm.rs
@@ -173,7 +173,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
         let Some((ty, n)) = autoderef.nth(pick.autoderefs) else {
             return Ty::new_error_with_message(
                 self.tcx,
-                rustc_span::DUMMY_SP,
+                DUMMY_SP,
                 format!("failed autoderef {}", pick.autoderefs),
             );
         };
@@ -608,7 +608,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
                     let span = predicates
                         .iter()
                         .find_map(|(p, span)| if p == pred { Some(span) } else { None })
-                        .unwrap_or(rustc_span::DUMMY_SP);
+                        .unwrap_or(DUMMY_SP);
                     Some((trait_pred, span))
                 }
                 _ => None,
diff --git a/compiler/rustc_hir_typeck/src/method/prelude2021.rs b/compiler/rustc_hir_typeck/src/method/prelude2021.rs
index 0e43cb40485..22eef8e53da 100644
--- a/compiler/rustc_hir_typeck/src/method/prelude2021.rs
+++ b/compiler/rustc_hir_typeck/src/method/prelude2021.rs
@@ -7,8 +7,8 @@ use hir::HirId;
 use hir::ItemKind;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
-use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
-use rustc_middle::ty::{Adt, Array, Ref, Ty};
+use rustc_infer::infer::type_variable::TypeVariableOrigin;
+use rustc_middle::ty::{self, Ty};
 use rustc_session::lint::builtin::RUST_2021_PRELUDE_COLLISIONS;
 use rustc_span::symbol::kw::{Empty, Underscore};
 use rustc_span::symbol::{sym, Ident};
@@ -44,7 +44,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             // but `[T; N].into_iter()` doesn't resolve to IntoIterator::into_iter
             // before Rust 2021, which results in the same problem.
             // It is only a problem for arrays.
-            sym::into_iter if let Array(..) = self_ty.kind() => {
+            sym::into_iter if let ty::Array(..) = self_ty.kind() => {
                 // In this case, it wasn't really a prelude addition that was the problem.
                 // Instead, the problem is that the array-into_iter hack will no longer apply in Rust 2021.
                 rustc_lint::ARRAY_INTO_ITER
@@ -64,7 +64,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     pick.autoref_or_ptr_adjustment,
                     Some(probe::AutorefOrPtrAdjustment::Autoref { .. })
                 )
-                && matches!(self_ty.kind(), Ref(..))
+                && matches!(self_ty.kind(), ty::Ref(..))
             {
                 return;
             }
@@ -218,10 +218,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         // If we know it does not, we don't need to warn.
         if method_name.name == sym::from_iter {
             if let Some(trait_def_id) = self.tcx.get_diagnostic_item(sym::FromIterator) {
-                let any_type = self.infcx.next_ty_var(TypeVariableOrigin {
-                    kind: TypeVariableOriginKind::MiscVariable,
-                    span,
-                });
+                let any_type =
+                    self.infcx.next_ty_var(TypeVariableOrigin { param_def_id: None, span });
                 if !self
                     .infcx
                     .type_implements_trait(trait_def_id, [self_ty, any_type], self.param_env)
@@ -280,7 +278,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 // the user has written the self type with generics already which we (naively) do by looking
                 // for a "<" in `self_ty_name`.
                 if !self_ty_name.contains('<') {
-                    if let Adt(def, _) = self_ty.kind() {
+                    if let ty::Adt(def, _) = self_ty.kind() {
                         let generics = self.tcx.generics_of(def.did());
                         if !generics.params.is_empty() {
                             let counts = generics.own_counts();
diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs
index 28e17e1de36..2876e0b49db 100644
--- a/compiler/rustc_hir_typeck/src/method/probe.rs
+++ b/compiler/rustc_hir_typeck/src/method/probe.rs
@@ -8,6 +8,7 @@ use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_hir::def::DefKind;
+use rustc_hir::HirId;
 use rustc_hir_analysis::autoderef::{self, Autoderef};
 use rustc_infer::infer::canonical::OriginalQueryValues;
 use rustc_infer::infer::canonical::{Canonical, QueryResponse};
@@ -86,7 +87,7 @@ pub(crate) struct ProbeContext<'a, 'tcx> {
         Vec<(ty::Predicate<'tcx>, Option<ty::Predicate<'tcx>>, Option<ObligationCause<'tcx>>)>,
     >,
 
-    scope_expr_id: hir::HirId,
+    scope_expr_id: HirId,
 }
 
 impl<'a, 'tcx> Deref for ProbeContext<'a, 'tcx> {
@@ -263,7 +264,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         mode: Mode,
         return_type: Ty<'tcx>,
         self_ty: Ty<'tcx>,
-        scope_expr_id: hir::HirId,
+        scope_expr_id: HirId,
         candidate_filter: impl Fn(&ty::AssocItem) -> bool,
     ) -> Vec<ty::AssocItem> {
         let method_names = self
@@ -307,7 +308,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         return_type: Option<Ty<'tcx>>,
         is_suggestion: IsSuggestion,
         self_ty: Ty<'tcx>,
-        scope_expr_id: hir::HirId,
+        scope_expr_id: HirId,
         scope: ProbeScope,
     ) -> PickResult<'tcx> {
         self.probe_op(
@@ -331,7 +332,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         return_type: Option<Ty<'tcx>>,
         is_suggestion: IsSuggestion,
         self_ty: Ty<'tcx>,
-        scope_expr_id: hir::HirId,
+        scope_expr_id: HirId,
         scope: ProbeScope,
     ) -> Vec<Candidate<'tcx>> {
         self.probe_op(
@@ -362,7 +363,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         return_type: Option<Ty<'tcx>>,
         is_suggestion: IsSuggestion,
         self_ty: Ty<'tcx>,
-        scope_expr_id: hir::HirId,
+        scope_expr_id: HirId,
         scope: ProbeScope,
         op: OP,
     ) -> Result<R, MethodError<'tcx>>
@@ -589,7 +590,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
         return_type: Option<Ty<'tcx>>,
         orig_steps_var_values: &'a OriginalQueryValues<'tcx>,
         steps: &'tcx [CandidateStep<'tcx>],
-        scope_expr_id: hir::HirId,
+        scope_expr_id: HirId,
     ) -> ProbeContext<'a, 'tcx> {
         ProbeContext {
             fcx,
@@ -1381,7 +1382,7 @@ impl<'tcx> Pick<'tcx> {
         &self,
         tcx: TyCtxt<'tcx>,
         span: Span,
-        scope_expr_id: hir::HirId,
+        scope_expr_id: HirId,
     ) {
         if self.unstable_candidates.is_empty() {
             return;
@@ -1696,7 +1697,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
                 if let ProbeResult::Match = result
                     && self
                         .at(&ObligationCause::dummy(), self.param_env)
-                        .sup(DefineOpaqueTypes::No, return_ty, xform_ret_ty)
+                        .sup(DefineOpaqueTypes::Yes, return_ty, xform_ret_ty)
                         .is_err()
                 {
                     result = ProbeResult::BadReturnType;
diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs
index 754866c85c4..46227e406a3 100644
--- a/compiler/rustc_hir_typeck/src/method/suggest.rs
+++ b/compiler/rustc_hir_typeck/src/method/suggest.rs
@@ -22,12 +22,8 @@ use rustc_hir::lang_items::LangItem;
 use rustc_hir::PatKind::Binding;
 use rustc_hir::PathSegment;
 use rustc_hir::{ExprKind, Node, QPath};
-use rustc_infer::infer::{
-    self,
-    type_variable::{TypeVariableOrigin, TypeVariableOriginKind},
-    RegionVariableOrigin,
-};
-use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
+use rustc_infer::infer::{self, type_variable::TypeVariableOrigin, RegionVariableOrigin};
+use rustc_middle::infer::unify_key::ConstVariableOrigin;
 use rustc_middle::ty::fast_reject::DeepRejectCtxt;
 use rustc_middle::ty::fast_reject::{simplify_type, TreatParams};
 use rustc_middle::ty::print::{with_crate_prefix, with_forced_trimmed_paths};
@@ -82,13 +78,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         let trait_ref = ty::TraitRef::new(
                             tcx,
                             fn_once,
-                            [
-                                ty,
-                                self.next_ty_var(TypeVariableOrigin {
-                                    kind: TypeVariableOriginKind::MiscVariable,
-                                    span,
-                                }),
-                            ],
+                            [ty, self.next_ty_var(TypeVariableOrigin { param_def_id: None, span })],
                         );
                         let poly_trait_ref = ty::Binder::dummy(trait_ref);
                         let obligation = Obligation::misc(
@@ -1271,7 +1261,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     .map(|expr| {
                         self.node_ty_opt(expr.hir_id).unwrap_or_else(|| {
                             self.next_ty_var(TypeVariableOrigin {
-                                kind: TypeVariableOriginKind::MiscVariable,
+                                param_def_id: None,
                                 span: expr.span,
                             })
                         })
@@ -1854,23 +1844,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         has_unsuggestable_args = true;
                         match arg.unpack() {
                             GenericArgKind::Lifetime(_) => self
-                                .next_region_var(RegionVariableOrigin::MiscVariable(
-                                    rustc_span::DUMMY_SP,
-                                ))
+                                .next_region_var(RegionVariableOrigin::MiscVariable(DUMMY_SP))
                                 .into(),
                             GenericArgKind::Type(_) => self
                                 .next_ty_var(TypeVariableOrigin {
-                                    span: rustc_span::DUMMY_SP,
-                                    kind: TypeVariableOriginKind::MiscVariable,
+                                    span: DUMMY_SP,
+                                    param_def_id: None,
                                 })
                                 .into(),
                             GenericArgKind::Const(arg) => self
                                 .next_const_var(
                                     arg.ty(),
-                                    ConstVariableOrigin {
-                                        span: rustc_span::DUMMY_SP,
-                                        kind: ConstVariableOriginKind::MiscVariable,
-                                    },
+                                    ConstVariableOrigin { span: DUMMY_SP, param_def_id: None },
                                 )
                                 .into(),
                         }
@@ -2768,7 +2753,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let SelfSource::QPath(ty) = self_source else {
             return;
         };
-        for (deref_ty, _) in self.autoderef(rustc_span::DUMMY_SP, rcvr_ty).skip(1) {
+        for (deref_ty, _) in self.autoderef(DUMMY_SP, rcvr_ty).skip(1) {
             if let Ok(pick) = self.probe_for_name(
                 Mode::Path,
                 item_name,
diff --git a/compiler/rustc_hir_typeck/src/op.rs b/compiler/rustc_hir_typeck/src/op.rs
index 94b723f694e..49d0c8bfcd1 100644
--- a/compiler/rustc_hir_typeck/src/op.rs
+++ b/compiler/rustc_hir_typeck/src/op.rs
@@ -7,7 +7,7 @@ use rustc_ast as ast;
 use rustc_data_structures::packed::Pu128;
 use rustc_errors::{codes::*, struct_span_code_err, Applicability, Diag};
 use rustc_hir as hir;
-use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
+use rustc_infer::infer::type_variable::TypeVariableOrigin;
 use rustc_infer::traits::ObligationCauseCode;
 use rustc_middle::ty::adjustment::{
     Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability,
@@ -219,10 +219,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 // e.g., adding `&'a T` and `&'b T`, given `&'x T: Add<&'x T>`, will result
                 // in `&'a T <: &'x T` and `&'b T <: &'x T`, instead of `'a = 'b = 'x`.
                 let lhs_ty = self.check_expr(lhs_expr);
-                let fresh_var = self.next_ty_var(TypeVariableOrigin {
-                    kind: TypeVariableOriginKind::MiscVariable,
-                    span: lhs_expr.span,
-                });
+                let fresh_var = self
+                    .next_ty_var(TypeVariableOrigin { param_def_id: None, span: lhs_expr.span });
                 self.demand_coerce(lhs_expr, lhs_ty, fresh_var, Some(rhs_expr), AllowTwoPhase::No)
             }
             IsAssign::Yes => {
@@ -241,10 +239,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         // using this variable as the expected type, which sometimes lets
         // us do better coercions than we would be able to do otherwise,
         // particularly for things like `String + &String`.
-        let rhs_ty_var = self.next_ty_var(TypeVariableOrigin {
-            kind: TypeVariableOriginKind::MiscVariable,
-            span: rhs_expr.span,
-        });
+        let rhs_ty_var =
+            self.next_ty_var(TypeVariableOrigin { param_def_id: None, span: rhs_expr.span });
 
         let result = self.lookup_op_method(
             (lhs_expr, lhs_ty),
diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs
index bb47f8dfba4..3c1e01cfb53 100644
--- a/compiler/rustc_hir_typeck/src/pat.rs
+++ b/compiler/rustc_hir_typeck/src/pat.rs
@@ -9,9 +9,10 @@ use rustc_hir::def::{CtorKind, DefKind, Res};
 use rustc_hir::pat_util::EnumerateAndAdjustIterator;
 use rustc_hir::{self as hir, BindingAnnotation, ByRef, HirId, Mutability, Pat, PatKind};
 use rustc_infer::infer;
-use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
+use rustc_infer::infer::type_variable::TypeVariableOrigin;
+use rustc_lint as lint;
 use rustc_middle::mir::interpret::ErrorHandled;
-use rustc_middle::ty::{self, Adt, Ty, TypeVisitableExt};
+use rustc_middle::ty::{self, Ty, TypeVisitableExt};
 use rustc_session::lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS;
 use rustc_span::edit_distance::find_best_match_for_name;
 use rustc_span::hygiene::DesugaringKind;
@@ -79,6 +80,7 @@ struct TopInfo<'tcx> {
 #[derive(Copy, Clone)]
 struct PatInfo<'tcx, 'a> {
     binding_mode: BindingAnnotation,
+    max_ref_mutbl: Mutability,
     top_info: TopInfo<'tcx>,
     decl_origin: Option<DeclOrigin<'a>>,
 
@@ -160,8 +162,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         decl_origin: Option<DeclOrigin<'tcx>>,
     ) {
         let info = TopInfo { expected, origin_expr, span };
-        let pat_info =
-            PatInfo { binding_mode: INITIAL_BM, top_info: info, decl_origin, current_depth: 0 };
+        let pat_info = PatInfo {
+            binding_mode: INITIAL_BM,
+            max_ref_mutbl: Mutability::Mut,
+            top_info: info,
+            decl_origin,
+            current_depth: 0,
+        };
         self.check_pat(pat, expected, pat_info);
     }
 
@@ -172,7 +179,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     /// Conversely, inside this module, `check_pat_top` should never be used.
     #[instrument(level = "debug", skip(self, pat_info))]
     fn check_pat(&self, pat: &'tcx Pat<'tcx>, expected: Ty<'tcx>, pat_info: PatInfo<'tcx, '_>) {
-        let PatInfo { binding_mode: def_bm, top_info: ti, current_depth, .. } = pat_info;
+        let PatInfo { binding_mode: def_bm, max_ref_mutbl, top_info: ti, current_depth, .. } =
+            pat_info;
 
         let path_res = match &pat.kind {
             PatKind::Path(qpath) => Some(
@@ -181,10 +189,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             _ => None,
         };
         let adjust_mode = self.calc_adjust_mode(pat, path_res.map(|(res, ..)| res));
-        let (expected, def_bm, ref_pattern_already_consumed) =
-            self.calc_default_binding_mode(pat, expected, def_bm, adjust_mode);
+        let (expected, def_bm, max_ref_mutbl, ref_pattern_already_consumed) =
+            self.calc_default_binding_mode(pat, expected, def_bm, adjust_mode, max_ref_mutbl);
         let pat_info = PatInfo {
             binding_mode: def_bm,
+            max_ref_mutbl,
             top_info: ti,
             decl_origin: pat_info.decl_origin,
             current_depth: current_depth + 1,
@@ -289,16 +298,42 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         expected: Ty<'tcx>,
         def_bm: BindingAnnotation,
         adjust_mode: AdjustMode,
-    ) -> (Ty<'tcx>, BindingAnnotation, bool) {
+        max_ref_mutbl: Mutability,
+    ) -> (Ty<'tcx>, BindingAnnotation, Mutability, bool) {
+        if let ByRef::Yes(mutbl) = def_bm.0 {
+            debug_assert!(mutbl <= max_ref_mutbl);
+        }
         match adjust_mode {
-            AdjustMode::Pass => (expected, def_bm, false),
-            AdjustMode::Reset => (expected, INITIAL_BM, false),
-            AdjustMode::ResetAndConsumeRef(mutbl) => {
-                (expected, INITIAL_BM, def_bm.0 == ByRef::Yes(mutbl))
+            AdjustMode::Pass => (expected, def_bm, max_ref_mutbl, false),
+            AdjustMode::Reset => (expected, INITIAL_BM, Mutability::Mut, false),
+            AdjustMode::ResetAndConsumeRef(ref_pat_mutbl) => {
+                let mutbls_match = def_bm.0 == ByRef::Yes(ref_pat_mutbl);
+                if pat.span.at_least_rust_2024() && self.tcx.features().ref_pat_eat_one_layer_2024 {
+                    if mutbls_match {
+                        debug!("consuming inherited reference");
+                        (expected, INITIAL_BM, cmp::min(max_ref_mutbl, ref_pat_mutbl), true)
+                    } else {
+                        let (new_ty, new_bm, max_ref_mutbl) = if ref_pat_mutbl == Mutability::Mut {
+                            self.peel_off_references(
+                                pat,
+                                expected,
+                                def_bm,
+                                Mutability::Not,
+                                max_ref_mutbl,
+                            )
+                        } else {
+                            (expected, def_bm.cap_ref_mutability(Mutability::Not), Mutability::Not)
+                        };
+                        (new_ty, new_bm, max_ref_mutbl, false)
+                    }
+                } else {
+                    (expected, INITIAL_BM, max_ref_mutbl, mutbls_match)
+                }
             }
             AdjustMode::Peel => {
-                let peeled = self.peel_off_references(pat, expected, def_bm);
-                (peeled.0, peeled.1, false)
+                let peeled =
+                    self.peel_off_references(pat, expected, def_bm, Mutability::Mut, max_ref_mutbl);
+                (peeled.0, peeled.1, peeled.2, false)
             }
         }
     }
@@ -379,7 +414,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         pat: &'tcx Pat<'tcx>,
         expected: Ty<'tcx>,
         mut def_bm: BindingAnnotation,
-    ) -> (Ty<'tcx>, BindingAnnotation) {
+        max_peelable_mutability: Mutability,
+        mut max_ref_mutability: Mutability,
+    ) -> (Ty<'tcx>, BindingAnnotation, Mutability) {
         let mut expected = self.try_structurally_resolve_type(pat.span, expected);
         // Peel off as many `&` or `&mut` from the scrutinee type as possible. For example,
         // for `match &&&mut Some(5)` the loop runs three times, aborting when it reaches
@@ -390,7 +427,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         //
         // See the examples in `ui/match-defbm*.rs`.
         let mut pat_adjustments = vec![];
-        while let ty::Ref(_, inner_ty, inner_mutability) = *expected.kind() {
+        while let ty::Ref(_, inner_ty, inner_mutability) = *expected.kind()
+            && inner_mutability <= max_peelable_mutability
+        {
             debug!("inspecting {:?}", expected);
 
             debug!("current discriminant is Ref, inserting implicit deref");
@@ -410,6 +449,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             });
         }
 
+        if pat.span.at_least_rust_2024() && self.tcx.features().ref_pat_eat_one_layer_2024 {
+            def_bm = def_bm.cap_ref_mutability(max_ref_mutability);
+            if def_bm.0 == ByRef::Yes(Mutability::Not) {
+                max_ref_mutability = Mutability::Not;
+            }
+        }
+
         if !pat_adjustments.is_empty() {
             debug!("default binding mode is now {:?}", def_bm);
             self.typeck_results
@@ -418,7 +464,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 .insert(pat.hir_id, pat_adjustments);
         }
 
-        (expected, def_bm)
+        (expected, def_bm, max_ref_mutability)
     }
 
     fn check_pat_lit(
@@ -629,12 +675,26 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         expected: Ty<'tcx>,
         pat_info: PatInfo<'tcx, '_>,
     ) -> Ty<'tcx> {
-        let PatInfo { binding_mode: def_bm, top_info: ti, .. } = pat_info;
+        let PatInfo { binding_mode: BindingAnnotation(def_br, _), top_info: ti, .. } = pat_info;
 
         // Determine the binding mode...
         let bm = match ba {
-            BindingAnnotation(ByRef::No, Mutability::Not) => def_bm,
-            _ => ba,
+            BindingAnnotation(ByRef::No, Mutability::Mut)
+                if !(pat.span.at_least_rust_2024()
+                    && self.tcx.features().mut_preserve_binding_mode_2024)
+                    && matches!(def_br, ByRef::Yes(_)) =>
+            {
+                // `mut x` resets the binding mode in edition <= 2021.
+                self.tcx.emit_node_span_lint(
+                    lint::builtin::DEREFERENCING_MUT_BINDING,
+                    pat.hir_id,
+                    pat.span,
+                    errors::DereferencingMutBinding { span: pat.span },
+                );
+                BindingAnnotation(ByRef::No, Mutability::Mut)
+            }
+            BindingAnnotation(ByRef::No, mutbl) => BindingAnnotation(def_br, mutbl),
+            BindingAnnotation(ByRef::Yes(_), _) => ba,
         };
         // ...and store it in a side table:
         self.typeck_results.borrow_mut().pat_binding_modes_mut().insert(pat.hir_id, bm);
@@ -743,7 +803,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         }
     }
 
-    // Precondition: pat is a Ref(_) pattern
+    /// Precondition: pat is a `Ref(_)` pattern
     fn borrow_pat_suggestion(&self, err: &mut Diag<'_>, pat: &Pat<'_>) {
         let tcx = self.tcx;
         if let PatKind::Ref(inner, mutbl) = pat.kind
@@ -1046,7 +1106,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     }
                     _ => {
                         let (type_def_id, item_def_id) = match pat_ty.kind() {
-                            Adt(def, _) => match res {
+                            ty::Adt(def, _) => match res {
                                 Res::Def(DefKind::Const, def_id) => (Some(def.did()), Some(def_id)),
                                 _ => (None, None),
                             },
@@ -1094,15 +1154,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         expected: Ty<'tcx>,
         pat_info: PatInfo<'tcx, '_>,
     ) -> Ty<'tcx> {
-        let PatInfo { binding_mode: def_bm, top_info: ti, decl_origin, current_depth } = pat_info;
         let tcx = self.tcx;
         let on_error = |e| {
             for pat in subpats {
-                self.check_pat(
-                    pat,
-                    Ty::new_error(tcx, e),
-                    PatInfo { binding_mode: def_bm, top_info: ti, decl_origin, current_depth },
-                );
+                self.check_pat(pat, Ty::new_error(tcx, e), pat_info);
             }
         };
         let report_unexpected_res = |res: Res| {
@@ -1147,7 +1202,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let pat_ty = pat_ty.no_bound_vars().expect("expected fn type");
 
         // Type-check the tuple struct pattern against the expected type.
-        let diag = self.demand_eqtype_pat_diag(pat.span, expected, pat_ty, ti);
+        let diag = self.demand_eqtype_pat_diag(pat.span, expected, pat_ty, pat_info.top_info);
         let had_err = if let Some(err) = diag {
             err.emit();
             true
@@ -1165,11 +1220,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             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, args);
-                self.check_pat(
-                    subpat,
-                    field_ty,
-                    PatInfo { binding_mode: def_bm, top_info: ti, decl_origin, current_depth },
-                );
+                self.check_pat(subpat, field_ty, pat_info);
 
                 self.tcx.check_stability(
                     variant.fields[FieldIdx::from_usize(i)].did,
@@ -1365,13 +1416,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         }
         let max_len = cmp::max(expected_len, elements.len());
 
-        let element_tys_iter = (0..max_len).map(|_| {
-            self.next_ty_var(
-                // FIXME: `MiscVariable` for now -- obtaining the span and name information
-                // from all tuple elements isn't trivial.
-                TypeVariableOrigin { kind: TypeVariableOriginKind::TypeInference, span },
-            )
-        });
+        let element_tys_iter =
+            (0..max_len).map(|_| self.next_ty_var(TypeVariableOrigin { param_def_id: None, span }));
         let element_tys = tcx.mk_type_list_from_iter(element_tys_iter);
         let pat_ty = Ty::new_tup(tcx, element_tys);
         if let Some(err) = self.demand_eqtype_pat_diag(span, expected, pat_ty, pat_info.top_info) {
@@ -1561,7 +1607,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         {
             let has_shorthand_field_name = field_patterns.iter().any(|field| field.is_shorthand);
             if has_shorthand_field_name {
-                let path = rustc_hir_pretty::qpath_to_string(qpath);
+                let path = rustc_hir_pretty::qpath_to_string(&self.tcx, qpath);
                 let mut err = struct_span_code_err!(
                     self.dcx(),
                     pat.span,
@@ -1743,7 +1789,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 return None;
             }
 
-            let path = rustc_hir_pretty::qpath_to_string(qpath);
+            let path = rustc_hir_pretty::qpath_to_string(&self.tcx, qpath);
             let mut err = struct_span_code_err!(
                 self.dcx(),
                 pat.span,
@@ -1793,7 +1839,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             f
                         }
                     }
-                    Err(_) => rustc_hir_pretty::pat_to_string(field.pat),
+                    Err(_) => rustc_hir_pretty::pat_to_string(&self.tcx, field.pat),
                 }
             })
             .collect::<Vec<String>>()
@@ -1997,10 +2043,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             Ok(()) => {
                 // Here, `demand::subtype` is good enough, but I don't
                 // think any errors can be introduced by using `demand::eqtype`.
-                let inner_ty = self.next_ty_var(TypeVariableOrigin {
-                    kind: TypeVariableOriginKind::TypeInference,
-                    span: inner.span,
-                });
+                let inner_ty =
+                    self.next_ty_var(TypeVariableOrigin { param_def_id: None, span: inner.span });
                 let box_ty = Ty::new_box(tcx, inner_ty);
                 self.demand_eqtype_pat(span, expected, box_ty, pat_info.top_info);
                 (box_ty, inner_ty)
@@ -2063,61 +2107,70 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         pat_info: PatInfo<'tcx, '_>,
         consumed_inherited_ref: bool,
     ) -> Ty<'tcx> {
-        let tcx = self.tcx;
-        let expected = self.shallow_resolve(expected);
-        let (ref_ty, inner_ty) = match self.check_dereferenceable(pat.span, expected, inner) {
-            Ok(()) => {
-                // `demand::subtype` would be good enough, but using `eqtype` turns
-                // out to be equally general. See (note_1) for details.
-
-                // Take region, inner-type from expected type if we can,
-                // to avoid creating needless variables. This also helps with
-                // the bad interactions of the given hack detailed in (note_1).
-                debug!("check_pat_ref: expected={:?}", expected);
-                match *expected.kind() {
-                    ty::Ref(_, r_ty, r_mutbl) if r_mutbl == mutbl => (expected, r_ty),
-                    _ => {
-                        if consumed_inherited_ref && self.tcx.features().ref_pat_everywhere {
-                            // We already matched against a match-ergonmics inserted reference,
-                            // so we don't need to match against a reference from the original type.
-                            // Save this infor for use in lowering later
-                            self.typeck_results
-                                .borrow_mut()
-                                .skipped_ref_pats_mut()
-                                .insert(pat.hir_id);
-                            (expected, expected)
-                        } else {
-                            let inner_ty = self.next_ty_var(TypeVariableOrigin {
-                                kind: TypeVariableOriginKind::TypeInference,
-                                span: inner.span,
-                            });
-                            let ref_ty = self.new_ref_ty(pat.span, mutbl, inner_ty);
-                            debug!("check_pat_ref: demanding {:?} = {:?}", expected, ref_ty);
-                            let err = self.demand_eqtype_pat_diag(
-                                pat.span,
-                                expected,
-                                ref_ty,
-                                pat_info.top_info,
-                            );
+        if consumed_inherited_ref
+            && pat.span.at_least_rust_2024()
+            && self.tcx.features().ref_pat_eat_one_layer_2024
+        {
+            self.typeck_results.borrow_mut().skipped_ref_pats_mut().insert(pat.hir_id);
+            self.check_pat(inner, expected, pat_info);
+            expected
+        } else {
+            let tcx = self.tcx;
+            let expected = self.shallow_resolve(expected);
+            let (ref_ty, inner_ty) = match self.check_dereferenceable(pat.span, expected, inner) {
+                Ok(()) => {
+                    // `demand::subtype` would be good enough, but using `eqtype` turns
+                    // out to be equally general. See (note_1) for details.
+
+                    // Take region, inner-type from expected type if we can,
+                    // to avoid creating needless variables. This also helps with
+                    // the bad interactions of the given hack detailed in (note_1).
+                    debug!("check_pat_ref: expected={:?}", expected);
+                    match *expected.kind() {
+                        ty::Ref(_, r_ty, r_mutbl) if r_mutbl == mutbl => (expected, r_ty),
+                        _ => {
+                            if consumed_inherited_ref && self.tcx.features().ref_pat_everywhere {
+                                // We already matched against a match-ergonmics inserted reference,
+                                // so we don't need to match against a reference from the original type.
+                                // Save this infor for use in lowering later
+                                self.typeck_results
+                                    .borrow_mut()
+                                    .skipped_ref_pats_mut()
+                                    .insert(pat.hir_id);
+                                (expected, expected)
+                            } else {
+                                let inner_ty = self.next_ty_var(TypeVariableOrigin {
+                                    param_def_id: None,
+                                    span: inner.span,
+                                });
+                                let ref_ty = self.new_ref_ty(pat.span, mutbl, inner_ty);
+                                debug!("check_pat_ref: demanding {:?} = {:?}", expected, ref_ty);
+                                let err = self.demand_eqtype_pat_diag(
+                                    pat.span,
+                                    expected,
+                                    ref_ty,
+                                    pat_info.top_info,
+                                );
 
-                            // Look for a case like `fn foo(&foo: u32)` and suggest
-                            // `fn foo(foo: &u32)`
-                            if let Some(mut err) = err {
-                                self.borrow_pat_suggestion(&mut err, pat);
-                                err.emit();
+                                // Look for a case like `fn foo(&foo: u32)` and suggest
+                                // `fn foo(foo: &u32)`
+                                if let Some(mut err) = err {
+                                    self.borrow_pat_suggestion(&mut err, pat);
+                                    err.emit();
+                                }
+                                (ref_ty, inner_ty)
                             }
-                            (ref_ty, inner_ty)
                         }
                     }
                 }
-            }
-            Err(guar) => {
-                let err = Ty::new_error(tcx, guar);
-                (err, err)
-            }
-        };
-        self.check_pat(inner, inner_ty, pat_info);
-        ref_ty
+                Err(guar) => {
+                    let err = Ty::new_error(tcx, guar);
+                    (err, err)
+                }
+            };
+            self.check_pat(inner, inner_ty, pat_info);
+            ref_ty
+        }
     }
 
     /// Create a reference type with a fresh region variable.
@@ -2138,8 +2191,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         let tcx = self.tcx;
         let len = before.len();
-        let ty_var_origin =
-            TypeVariableOrigin { kind: TypeVariableOriginKind::TypeInference, span };
+        let ty_var_origin = TypeVariableOrigin { param_def_id: None, span };
         let inner_ty = self.next_ty_var(ty_var_origin);
 
         Some(Ty::new_array(tcx, inner_ty, len.try_into().unwrap()))
diff --git a/compiler/rustc_hir_typeck/src/place_op.rs b/compiler/rustc_hir_typeck/src/place_op.rs
index f29dc39b7be..bce43b3be34 100644
--- a/compiler/rustc_hir_typeck/src/place_op.rs
+++ b/compiler/rustc_hir_typeck/src/place_op.rs
@@ -4,7 +4,7 @@ use rustc_ast as ast;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_hir_analysis::autoderef::Autoderef;
-use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
+use rustc_infer::infer::type_variable::TypeVariableOrigin;
 use rustc_infer::infer::InferOk;
 use rustc_middle::ty::adjustment::{Adjust, Adjustment, OverloadedDeref, PointerCoercion};
 use rustc_middle::ty::adjustment::{AllowTwoPhase, AutoBorrow, AutoBorrowMutability};
@@ -147,10 +147,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             // If some lookup succeeds, write callee into table and extract index/element
             // type from the method signature.
             // If some lookup succeeded, install method in table
-            let input_ty = self.next_ty_var(TypeVariableOrigin {
-                kind: TypeVariableOriginKind::AutoDeref,
-                span: base_expr.span,
-            });
+            let input_ty =
+                self.next_ty_var(TypeVariableOrigin { param_def_id: None, span: base_expr.span });
             let method =
                 self.try_overloaded_place_op(expr.span, self_ty, &[input_ty], PlaceOp::Index);
 
diff --git a/compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs b/compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs
index 694ddd0e3e8..31ce271a5fc 100644
--- a/compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs
+++ b/compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs
@@ -3,7 +3,7 @@ use super::callee::DeferredCallResolution;
 use rustc_data_structures::unord::{UnordMap, UnordSet};
 use rustc_hir as hir;
 use rustc_hir::def_id::LocalDefId;
-use rustc_hir::HirIdMap;
+use rustc_hir::{HirId, HirIdMap};
 use rustc_infer::infer::{InferCtxt, InferOk, TyCtxtInferExt};
 use rustc_middle::ty::visit::TypeVisitableExt;
 use rustc_middle::ty::{self, Ty, TyCtxt};
@@ -52,9 +52,9 @@ pub(crate) struct TypeckRootCtxt<'tcx> {
 
     pub(super) deferred_cast_checks: RefCell<Vec<super::cast::CastCheck<'tcx>>>,
 
-    pub(super) deferred_transmute_checks: RefCell<Vec<(Ty<'tcx>, Ty<'tcx>, hir::HirId)>>,
+    pub(super) deferred_transmute_checks: RefCell<Vec<(Ty<'tcx>, Ty<'tcx>, HirId)>>,
 
-    pub(super) deferred_asm_checks: RefCell<Vec<(&'tcx hir::InlineAsm<'tcx>, hir::HirId)>>,
+    pub(super) deferred_asm_checks: RefCell<Vec<(&'tcx hir::InlineAsm<'tcx>, HirId)>>,
 
     pub(super) deferred_coroutine_interiors: RefCell<Vec<(LocalDefId, hir::BodyId, Ty<'tcx>)>>,
 
diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs
index 86f36eedd90..60a5838cafc 100644
--- a/compiler/rustc_hir_typeck/src/upvar.rs
+++ b/compiler/rustc_hir_typeck/src/upvar.rs
@@ -38,6 +38,7 @@ use rustc_errors::{Applicability, MultiSpan};
 use rustc_hir as hir;
 use rustc_hir::def_id::LocalDefId;
 use rustc_hir::intravisit::{self, Visitor};
+use rustc_hir::HirId;
 use rustc_infer::infer::UpvarRegion;
 use rustc_middle::hir::place::{Place, PlaceBase, PlaceWithHirId, Projection, ProjectionKind};
 use rustc_middle::mir::FakeReadCause;
@@ -88,7 +89,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
 enum UpvarMigrationInfo {
     /// We previously captured all of `x`, but now we capture some sub-path.
-    CapturingPrecise { source_expr: Option<hir::HirId>, var_name: String },
+    CapturingPrecise { source_expr: Option<HirId>, var_name: String },
     CapturingNothing {
         // where the variable appears in the closure (but is not captured)
         use_span: Span,
@@ -131,7 +132,7 @@ struct MigrationLintNote {
 /// Intermediate format to store the hir id of the root variable and a HashSet containing
 /// information on why the root variable should be fully captured
 struct NeededMigration {
-    var_hir_id: hir::HirId,
+    var_hir_id: HirId,
     diagnostics_info: Vec<MigrationLintNote>,
 }
 
@@ -163,7 +164,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     #[instrument(skip(self, body), level = "debug")]
     fn analyze_closure(
         &self,
-        closure_hir_id: hir::HirId,
+        closure_hir_id: HirId,
         span: Span,
         body_id: hir::BodyId,
         body: &'tcx hir::Body<'tcx>,
@@ -1098,7 +1099,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     fn compute_2229_migrations_for_trait(
         &self,
         min_captures: Option<&ty::RootVariableMinCaptureList<'tcx>>,
-        var_hir_id: hir::HirId,
+        var_hir_id: HirId,
         closure_clause: hir::CaptureBy,
     ) -> Option<FxIndexMap<UpvarMigrationInfo, UnordSet<&'static str>>> {
         let auto_traits_def_id = [
@@ -1210,7 +1211,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         closure_span: Span,
         min_captures: Option<&ty::RootVariableMinCaptureList<'tcx>>,
         closure_clause: hir::CaptureBy,
-        var_hir_id: hir::HirId,
+        var_hir_id: HirId,
     ) -> Option<FxIndexSet<UpvarMigrationInfo>> {
         let ty = self.resolve_vars_if_possible(self.node_ty(var_hir_id));
 
@@ -1650,7 +1651,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     fn place_for_root_variable(
         &self,
         closure_def_id: LocalDefId,
-        var_hir_id: hir::HirId,
+        var_hir_id: HirId,
     ) -> Place<'tcx> {
         let upvar_id = ty::UpvarId::new(var_hir_id, closure_def_id);
 
@@ -1881,7 +1882,7 @@ fn apply_capture_kind_on_capture_ty<'tcx>(
 }
 
 /// Returns the Span of where the value with the provided HirId would be dropped
-fn drop_location_span(tcx: TyCtxt<'_>, hir_id: hir::HirId) -> Span {
+fn drop_location_span(tcx: TyCtxt<'_>, hir_id: HirId) -> Span {
     let owner_id = tcx.hir().get_enclosing_scope(hir_id).unwrap();
 
     let owner_node = tcx.hir_node(owner_id);
@@ -1933,7 +1934,7 @@ struct InferBorrowKind<'tcx> {
     /// Place { V1, [ProjectionKind::Field(Index=1, Variant=0)] } : CaptureKind { E2, MutableBorrow }
     /// ```
     capture_information: InferredCaptureInformation<'tcx>,
-    fake_reads: Vec<(Place<'tcx>, FakeReadCause, hir::HirId)>,
+    fake_reads: Vec<(Place<'tcx>, FakeReadCause, HirId)>,
 }
 
 impl<'tcx> euv::Delegate<'tcx> for InferBorrowKind<'tcx> {
@@ -1941,7 +1942,7 @@ impl<'tcx> euv::Delegate<'tcx> for InferBorrowKind<'tcx> {
         &mut self,
         place: &PlaceWithHirId<'tcx>,
         cause: FakeReadCause,
-        diag_expr_id: hir::HirId,
+        diag_expr_id: HirId,
     ) {
         let PlaceBase::Upvar(_) = place.place.base else { return };
 
@@ -1956,7 +1957,7 @@ impl<'tcx> euv::Delegate<'tcx> for InferBorrowKind<'tcx> {
     }
 
     #[instrument(skip(self), level = "debug")]
-    fn consume(&mut self, place_with_id: &PlaceWithHirId<'tcx>, diag_expr_id: hir::HirId) {
+    fn consume(&mut self, place_with_id: &PlaceWithHirId<'tcx>, diag_expr_id: HirId) {
         let PlaceBase::Upvar(upvar_id) = place_with_id.place.base else { return };
         assert_eq!(self.closure_def_id, upvar_id.closure_expr_id);
 
@@ -1974,7 +1975,7 @@ impl<'tcx> euv::Delegate<'tcx> for InferBorrowKind<'tcx> {
     fn borrow(
         &mut self,
         place_with_id: &PlaceWithHirId<'tcx>,
-        diag_expr_id: hir::HirId,
+        diag_expr_id: HirId,
         bk: ty::BorrowKind,
     ) {
         let PlaceBase::Upvar(upvar_id) = place_with_id.place.base else { return };
@@ -2005,7 +2006,7 @@ impl<'tcx> euv::Delegate<'tcx> for InferBorrowKind<'tcx> {
     }
 
     #[instrument(skip(self), level = "debug")]
-    fn mutate(&mut self, assignee_place: &PlaceWithHirId<'tcx>, diag_expr_id: hir::HirId) {
+    fn mutate(&mut self, assignee_place: &PlaceWithHirId<'tcx>, diag_expr_id: HirId) {
         self.borrow(assignee_place, diag_expr_id, ty::BorrowKind::MutBorrow);
     }
 }
@@ -2192,14 +2193,14 @@ fn construct_capture_info_string<'tcx>(
     format!("{place_str} -> {capture_kind_str}")
 }
 
-fn var_name(tcx: TyCtxt<'_>, var_hir_id: hir::HirId) -> Symbol {
+fn var_name(tcx: TyCtxt<'_>, var_hir_id: HirId) -> Symbol {
     tcx.hir().name(var_hir_id)
 }
 
 #[instrument(level = "debug", skip(tcx))]
 fn should_do_rust_2021_incompatible_closure_captures_analysis(
     tcx: TyCtxt<'_>,
-    closure_id: hir::HirId,
+    closure_id: HirId,
 ) -> bool {
     if tcx.sess.at_least_rust_2021() {
         return false;
diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs
index 6604bf094c1..875f8b23a84 100644
--- a/compiler/rustc_hir_typeck/src/writeback.rs
+++ b/compiler/rustc_hir_typeck/src/writeback.rs
@@ -7,6 +7,7 @@ use rustc_data_structures::unord::ExtendUnord;
 use rustc_errors::{ErrorGuaranteed, StashKey};
 use rustc_hir as hir;
 use rustc_hir::intravisit::{self, Visitor};
+use rustc_hir::HirId;
 use rustc_infer::infer::error_reporting::TypeAnnotationNeeded::E0282;
 use rustc_middle::traits::ObligationCause;
 use rustc_middle::ty::adjustment::{Adjust, Adjustment, PointerCoercion};
@@ -134,7 +135,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
         self.fcx.tcx
     }
 
-    fn write_ty_to_typeck_results(&mut self, hir_id: hir::HirId, ty: Ty<'tcx>) {
+    fn write_ty_to_typeck_results(&mut self, hir_id: HirId, ty: Ty<'tcx>) {
         debug!("write_ty_to_typeck_results({:?}, {:?})", hir_id, ty);
         assert!(
             !ty.has_infer() && !ty.has_placeholders() && !ty.has_free_regions(),
@@ -461,7 +462,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
             fcx_typeck_results.closure_kind_origins().items_in_stable_order();
 
         for (local_id, origin) in fcx_closure_kind_origins {
-            let hir_id = hir::HirId { owner: common_hir_owner, local_id };
+            let hir_id = HirId { owner: common_hir_owner, local_id };
             let place_span = origin.0;
             let place = self.resolve(origin.1.clone(), &place_span);
             self.typeck_results.closure_kind_origins_mut().insert(hir_id, (place_span, place));
@@ -490,7 +491,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
 
             let mut errors_buffer = Vec::new();
             for (local_id, c_ty) in sorted_user_provided_types {
-                let hir_id = hir::HirId { owner: common_hir_owner, local_id };
+                let hir_id = HirId { owner: common_hir_owner, local_id };
 
                 if let ty::UserType::TypeOf(_, user_args) = c_ty.value {
                     // This is a unit-testing mechanism.
@@ -513,7 +514,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
 
         self.typeck_results.user_provided_types_mut().extend(
             fcx_typeck_results.user_provided_types().items().map(|(local_id, c_ty)| {
-                let hir_id = hir::HirId { owner: common_hir_owner, local_id };
+                let hir_id = HirId { owner: common_hir_owner, local_id };
 
                 if cfg!(debug_assertions) && c_ty.has_infer() {
                     span_bug!(
@@ -604,7 +605,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
         }
     }
 
-    fn visit_field_id(&mut self, hir_id: hir::HirId) {
+    fn visit_field_id(&mut self, hir_id: HirId) {
         if let Some(index) = self.fcx.typeck_results.borrow_mut().field_indices_mut().remove(hir_id)
         {
             self.typeck_results.field_indices_mut().insert(hir_id, index);
@@ -617,7 +618,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
     }
 
     #[instrument(skip(self, span), level = "debug")]
-    fn visit_node_id(&mut self, span: Span, hir_id: hir::HirId) {
+    fn visit_node_id(&mut self, span: Span, hir_id: HirId) {
         // Export associated path extensions and method resolutions.
         if let Some(def) =
             self.fcx.typeck_results.borrow_mut().type_dependent_defs_mut().remove(hir_id)
@@ -644,7 +645,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
     }
 
     #[instrument(skip(self, span), level = "debug")]
-    fn visit_adjustments(&mut self, span: Span, hir_id: hir::HirId) {
+    fn visit_adjustments(&mut self, span: Span, hir_id: HirId) {
         let adjustment = self.fcx.typeck_results.borrow_mut().adjustments_mut().remove(hir_id);
         match adjustment {
             None => {
@@ -660,7 +661,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
     }
 
     #[instrument(skip(self, span), level = "debug")]
-    fn visit_pat_adjustments(&mut self, span: Span, hir_id: hir::HirId) {
+    fn visit_pat_adjustments(&mut self, span: Span, hir_id: HirId) {
         let adjustment = self.fcx.typeck_results.borrow_mut().pat_adjustments_mut().remove(hir_id);
         match adjustment {
             None => {
@@ -691,7 +692,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
         let fcx_liberated_fn_sigs = fcx_typeck_results.liberated_fn_sigs().items_in_stable_order();
 
         for (local_id, &fn_sig) in fcx_liberated_fn_sigs {
-            let hir_id = hir::HirId { owner: common_hir_owner, local_id };
+            let hir_id = HirId { owner: common_hir_owner, local_id };
             let fn_sig = self.resolve(fn_sig, &hir_id);
             self.typeck_results.liberated_fn_sigs_mut().insert(hir_id, fn_sig);
         }
@@ -705,7 +706,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
         let fcx_fru_field_types = fcx_typeck_results.fru_field_types().items_in_stable_order();
 
         for (local_id, ftys) in fcx_fru_field_types {
-            let hir_id = hir::HirId { owner: common_hir_owner, local_id };
+            let hir_id = HirId { owner: common_hir_owner, local_id };
             let ftys = self.resolve(ftys.clone(), &hir_id);
             self.typeck_results.fru_field_types_mut().insert(hir_id, ftys);
         }
@@ -719,7 +720,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
         for (local_id, &(container, ref indices)) in
             fcx_typeck_results.offset_of_data().items_in_stable_order()
         {
-            let hir_id = hir::HirId { owner: common_hir_owner, local_id };
+            let hir_id = HirId { owner: common_hir_owner, local_id };
             let container = self.resolve(container, &hir_id);
             self.typeck_results.offset_of_data_mut().insert(hir_id, (container, indices.clone()));
         }
@@ -754,7 +755,7 @@ impl Locatable for Span {
     }
 }
 
-impl Locatable for hir::HirId {
+impl Locatable for HirId {
     fn to_span(&self, tcx: TyCtxt<'_>) -> Span {
         tcx.hir().span(*self)
     }
diff --git a/compiler/rustc_infer/src/infer/at.rs b/compiler/rustc_infer/src/infer/at.rs
index f14bbe74890..0f21d3966c4 100644
--- a/compiler/rustc_infer/src/infer/at.rs
+++ b/compiler/rustc_infer/src/infer/at.rs
@@ -282,7 +282,7 @@ impl<'a, 'tcx> Trace<'a, 'tcx> {
     {
         let Trace { at, trace } = self;
         debug_assert!(at.infcx.next_trait_solver());
-        let mut fields = at.infcx.combine_fields(trace, at.param_env, DefineOpaqueTypes::No);
+        let mut fields = at.infcx.combine_fields(trace, at.param_env, DefineOpaqueTypes::Yes);
         fields
             .equate(StructurallyRelateAliases::Yes)
             .relate(a, b)
diff --git a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
index 825c3bf82fc..4d712e9ffd3 100644
--- a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
+++ b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
@@ -802,7 +802,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
         const_var: ty::Const<'tcx>,
     ) -> ty::Const<'tcx> {
         debug_assert!(
-            !self.infcx.is_some_and(|infcx| const_var != infcx.shallow_resolve(const_var))
+            !self.infcx.is_some_and(|infcx| const_var != infcx.shallow_resolve_const(const_var))
         );
         let var = self.canonical_var(info, const_var.into());
         ty::Const::new_bound(self.tcx, self.binder_index, var, self.fold_ty(const_var.ty()))
diff --git a/compiler/rustc_infer/src/infer/canonical/mod.rs b/compiler/rustc_infer/src/infer/canonical/mod.rs
index bcc476393ea..734fa919eb5 100644
--- a/compiler/rustc_infer/src/infer/canonical/mod.rs
+++ b/compiler/rustc_infer/src/infer/canonical/mod.rs
@@ -21,8 +21,8 @@
 //!
 //! [c]: https://rust-lang.github.io/chalk/book/canonical_queries/canonicalization.html
 
-use crate::infer::{ConstVariableOrigin, ConstVariableOriginKind};
-use crate::infer::{InferCtxt, RegionVariableOrigin, TypeVariableOrigin, TypeVariableOriginKind};
+use crate::infer::ConstVariableOrigin;
+use crate::infer::{InferCtxt, RegionVariableOrigin, TypeVariableOrigin};
 use rustc_index::IndexVec;
 use rustc_middle::infer::unify_key::EffectVarValue;
 use rustc_middle::ty::fold::TypeFoldable;
@@ -115,7 +115,7 @@ impl<'tcx> InferCtxt<'tcx> {
             CanonicalVarKind::Ty(ty_kind) => {
                 let ty = match ty_kind {
                     CanonicalTyVarKind::General(ui) => self.next_ty_var_in_universe(
-                        TypeVariableOrigin { kind: TypeVariableOriginKind::MiscVariable, span },
+                        TypeVariableOrigin { param_def_id: None, span },
                         universe_map(ui),
                     ),
 
@@ -148,7 +148,7 @@ impl<'tcx> InferCtxt<'tcx> {
             CanonicalVarKind::Const(ui, ty) => self
                 .next_const_var_in_universe(
                     ty,
-                    ConstVariableOrigin { kind: ConstVariableOriginKind::MiscVariable, span },
+                    ConstVariableOrigin { param_def_id: None, span },
                     universe_map(ui),
                 )
                 .into(),
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 3b5658ed0ee..a2a38d1c507 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
@@ -3,7 +3,7 @@ use crate::errors::{
     SourceKindMultiSuggestion, SourceKindSubdiag,
 };
 use crate::infer::error_reporting::TypeErrCtxt;
-use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
+use crate::infer::type_variable::TypeVariableOrigin;
 use crate::infer::InferCtxt;
 use rustc_errors::{codes::*, Diag, IntoDiagArg};
 use rustc_hir as hir;
@@ -13,16 +13,14 @@ use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::intravisit::{self, Visitor};
 use rustc_hir::{Body, Closure, Expr, ExprKind, FnRetTy, HirId, LetStmt, LocalSource};
 use rustc_middle::hir::nested_filter;
-use rustc_middle::infer::unify_key::{
-    ConstVariableOrigin, ConstVariableOriginKind, ConstVariableValue,
-};
+use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableValue};
 use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow};
 use rustc_middle::ty::print::{FmtPrinter, PrettyPrinter, Print, Printer};
 use rustc_middle::ty::{
     self, GenericArg, GenericArgKind, GenericArgsRef, InferConst, IsSuggestable, Ty, TyCtxt,
     TypeFoldable, TypeFolder, TypeSuperFoldable, TypeckResults,
 };
-use rustc_span::symbol::{kw, sym, Ident};
+use rustc_span::symbol::{sym, Ident};
 use rustc_span::{BytePos, Span, DUMMY_SP};
 use std::borrow::Cow;
 use std::iter;
@@ -188,8 +186,11 @@ fn fmt_printer<'a, 'tcx>(infcx: &'a InferCtxt<'tcx>, ns: Namespace) -> FmtPrinte
         let mut infcx_inner = infcx.inner.borrow_mut();
         let ty_vars = infcx_inner.type_variables();
         let var_origin = ty_vars.var_origin(ty_vid);
-        if let TypeVariableOriginKind::TypeParameterDefinition(name, def_id) = var_origin.kind
-            && name != kw::SelfUpper
+        if let Some(def_id) = var_origin.param_def_id
+            // The `Self` param of a trait has the def-id of the trait,
+            // since it's a synthetic parameter.
+            && infcx.tcx.def_kind(def_id) == DefKind::TyParam
+            && let name = infcx.tcx.item_name(def_id)
             && !var_origin.span.from_expansion()
         {
             let generics = infcx.tcx.generics_of(infcx.tcx.parent(def_id));
@@ -216,8 +217,8 @@ fn fmt_printer<'a, 'tcx>(infcx: &'a InferCtxt<'tcx>, ns: Namespace) -> FmtPrinte
             None
         }
         ConstVariableValue::Unknown { origin, universe: _ } => {
-            if let ConstVariableOriginKind::ConstParameterDefinition(name, _) = origin.kind {
-                return Some(name);
+            if let Some(def_id) = origin.param_def_id {
+                Some(infcx.tcx.item_name(def_id))
             } else {
                 None
             }
@@ -302,21 +303,18 @@ impl<'tcx> InferCtxt<'tcx> {
                     let mut inner = self.inner.borrow_mut();
                     let ty_vars = &inner.type_variables();
                     let var_origin = ty_vars.var_origin(ty_vid);
-                    if let TypeVariableOriginKind::TypeParameterDefinition(name, def_id) =
-                        var_origin.kind
+                    if let Some(def_id) = var_origin.param_def_id
+                        // The `Self` param of a trait has the def-id of the trait,
+                        // since it's a synthetic parameter.
+                        && self.tcx.def_kind(def_id) == DefKind::TyParam
+                        && !var_origin.span.from_expansion()
                     {
-                        if name != kw::SelfUpper && !var_origin.span.from_expansion() {
-                            return InferenceDiagnosticsData {
-                                name: name.to_string(),
-                                span: Some(var_origin.span),
-                                kind: UnderspecifiedArgKind::Type {
-                                    prefix: "type parameter".into(),
-                                },
-                                parent: InferenceDiagnosticsParentData::for_def_id(
-                                    self.tcx, def_id,
-                                ),
-                            };
-                        }
+                        return InferenceDiagnosticsData {
+                            name: self.tcx.item_name(def_id).to_string(),
+                            span: Some(var_origin.span),
+                            kind: UnderspecifiedArgKind::Type { prefix: "type parameter".into() },
+                            parent: InferenceDiagnosticsParentData::for_def_id(self.tcx, def_id),
+                        };
                     }
                 }
 
@@ -341,11 +339,9 @@ impl<'tcx> InferCtxt<'tcx> {
                             }
                             ConstVariableValue::Unknown { origin, universe: _ } => origin,
                         };
-                    if let ConstVariableOriginKind::ConstParameterDefinition(name, def_id) =
-                        origin.kind
-                    {
+                    if let Some(def_id) = origin.param_def_id {
                         return InferenceDiagnosticsData {
-                            name: name.to_string(),
+                            name: self.tcx.item_name(def_id).to_string(),
                             span: Some(origin.span),
                             kind: UnderspecifiedArgKind::Const { is_parameter: true },
                             parent: InferenceDiagnosticsParentData::for_def_id(self.tcx, def_id),
@@ -549,16 +545,13 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                                 GenericArgKind::Type(_) => self
                                     .next_ty_var(TypeVariableOrigin {
                                         span: DUMMY_SP,
-                                        kind: TypeVariableOriginKind::MiscVariable,
+                                        param_def_id: None,
                                     })
                                     .into(),
                                 GenericArgKind::Const(arg) => self
                                     .next_const_var(
                                         arg.ty(),
-                                        ConstVariableOrigin {
-                                            span: DUMMY_SP,
-                                            kind: ConstVariableOriginKind::MiscVariable,
-                                        },
+                                        ConstVariableOrigin { span: DUMMY_SP, param_def_id: None },
                                     )
                                     .into(),
                             }
@@ -576,10 +569,9 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                 }
             }
             InferSourceKind::FullyQualifiedMethodCall { receiver, successor, args, def_id } => {
-                let placeholder = Some(self.next_ty_var(TypeVariableOrigin {
-                    span: DUMMY_SP,
-                    kind: TypeVariableOriginKind::MiscVariable,
-                }));
+                let placeholder = Some(
+                    self.next_ty_var(TypeVariableOrigin { span: DUMMY_SP, param_def_id: None }),
+                );
                 if let Some(args) = args.make_suggestable(self.infcx.tcx, true, placeholder) {
                     let mut printer = fmt_printer(self, Namespace::ValueNS);
                     printer.print_def_path(def_id, args).unwrap();
@@ -613,10 +605,9 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                 }
             }
             InferSourceKind::ClosureReturn { ty, data, should_wrap_expr } => {
-                let placeholder = Some(self.next_ty_var(TypeVariableOrigin {
-                    span: DUMMY_SP,
-                    kind: TypeVariableOriginKind::MiscVariable,
-                }));
+                let placeholder = Some(
+                    self.next_ty_var(TypeVariableOrigin { span: DUMMY_SP, param_def_id: None }),
+                );
                 if let Some(ty) = ty.make_suggestable(self.infcx.tcx, true, placeholder) {
                     let ty_info = ty_to_string(self, ty, None);
                     multi_suggestions.push(SourceKindMultiSuggestion::new_closure_return(
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 fe70b631cdb..0bbabefaf95 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
@@ -283,6 +283,7 @@ pub fn suggest_new_region_bound(
             continue;
         }
         match fn_return.kind {
+            // FIXME(precise_captures): Suggest adding to `use<...>` list instead.
             TyKind::OpaqueDef(item_id, _, _) => {
                 let item = tcx.hir().item(item_id);
                 let ItemKind::OpaqueTy(opaque) = &item.kind else {
diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs
index f2fd50a47d5..1dbf435e8c7 100644
--- a/compiler/rustc_infer/src/infer/mod.rs
+++ b/compiler/rustc_infer/src/infer/mod.rs
@@ -30,7 +30,7 @@ use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_middle::infer::canonical::{Canonical, CanonicalVarValues};
 use rustc_middle::infer::unify_key::ConstVariableValue;
 use rustc_middle::infer::unify_key::EffectVarValue;
-use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind, ToType};
+use rustc_middle::infer::unify_key::{ConstVariableOrigin, ToType};
 use rustc_middle::infer::unify_key::{ConstVidKey, EffectVidKey};
 use rustc_middle::mir::interpret::{ErrorHandled, EvalToValTreeResult};
 use rustc_middle::mir::ConstraintCategory;
@@ -48,7 +48,7 @@ use rustc_span::Span;
 use snapshot::undo_log::InferCtxtUndoLogs;
 use std::cell::{Cell, RefCell};
 use std::fmt;
-use type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
+use type_variable::TypeVariableOrigin;
 
 pub mod at;
 pub mod canonical;
@@ -945,14 +945,27 @@ impl<'tcx> InferCtxt<'tcx> {
             (&ty::Infer(ty::TyVar(a_vid)), &ty::Infer(ty::TyVar(b_vid))) => {
                 return Err((a_vid, b_vid));
             }
+            // We don't silently want to constrain hidden types here, so we assert that either one side is
+            // an infer var, so it'll get constrained to whatever the other side is, or there are no opaque
+            // types involved.
+            // We don't expect this to actually get hit, but if it does, we now at least know how to write
+            // a test for it.
+            (_, ty::Infer(ty::TyVar(_))) => {}
+            (ty::Infer(ty::TyVar(_)), _) => {}
+            _ if (r_a, r_b).has_opaque_types() => {
+                span_bug!(
+                    cause.span(),
+                    "opaque types got hidden types registered from within subtype predicate: {r_a:?} vs {r_b:?}"
+                )
+            }
             _ => {}
         }
 
         self.enter_forall(predicate, |ty::SubtypePredicate { a_is_expected, a, b }| {
             if a_is_expected {
-                Ok(self.at(cause, param_env).sub(DefineOpaqueTypes::No, a, b))
+                Ok(self.at(cause, param_env).sub(DefineOpaqueTypes::Yes, a, b))
             } else {
-                Ok(self.at(cause, param_env).sup(DefineOpaqueTypes::No, b, a))
+                Ok(self.at(cause, param_env).sup(DefineOpaqueTypes::Yes, b, a))
             }
         })
     }
@@ -1111,13 +1124,7 @@ impl<'tcx> InferCtxt<'tcx> {
                 // as the generic parameters for the default, `(T, U)`.
                 let ty_var_id = self.inner.borrow_mut().type_variables().new_var(
                     self.universe(),
-                    TypeVariableOrigin {
-                        kind: TypeVariableOriginKind::TypeParameterDefinition(
-                            param.name,
-                            param.def_id,
-                        ),
-                        span,
-                    },
+                    TypeVariableOrigin { param_def_id: Some(param.def_id), span },
                 );
 
                 Ty::new_var(self.tcx, ty_var_id).into()
@@ -1126,13 +1133,7 @@ impl<'tcx> InferCtxt<'tcx> {
                 if is_host_effect {
                     return self.var_for_effect(param);
                 }
-                let origin = ConstVariableOrigin {
-                    kind: ConstVariableOriginKind::ConstParameterDefinition(
-                        param.name,
-                        param.def_id,
-                    ),
-                    span,
-                };
+                let origin = ConstVariableOrigin { param_def_id: Some(param.def_id), span };
                 let const_var_id = self
                     .inner
                     .borrow_mut()
@@ -1253,19 +1254,76 @@ impl<'tcx> InferCtxt<'tcx> {
         }
     }
 
-    /// Resolve any type variables found in `value` -- but only one
-    /// level. So, if the variable `?X` is bound to some type
-    /// `Foo<?Y>`, then this would return `Foo<?Y>` (but `?Y` may
-    /// itself be bound to a type).
-    ///
-    /// Useful when you only need to inspect the outermost level of
-    /// the type and don't care about nested types (or perhaps you
-    /// will be resolving them as well, e.g. in a loop).
-    pub fn shallow_resolve<T>(&self, value: T) -> T
-    where
-        T: TypeFoldable<TyCtxt<'tcx>>,
-    {
-        value.fold_with(&mut ShallowResolver { infcx: self })
+    pub fn shallow_resolve(&self, ty: Ty<'tcx>) -> Ty<'tcx> {
+        if let ty::Infer(v) = ty.kind() { self.fold_infer_ty(*v).unwrap_or(ty) } else { ty }
+    }
+
+    // This is separate from `shallow_resolve` to keep that method small and inlinable.
+    #[inline(never)]
+    fn fold_infer_ty(&self, v: InferTy) -> Option<Ty<'tcx>> {
+        match v {
+            ty::TyVar(v) => {
+                // Not entirely obvious: if `typ` is a type variable,
+                // it can be resolved to an int/float variable, which
+                // can then be recursively resolved, hence the
+                // recursion. Note though that we prevent type
+                // variables from unifying to other type variables
+                // directly (though they may be embedded
+                // structurally), and we prevent cycles in any case,
+                // so this recursion should always be of very limited
+                // depth.
+                //
+                // Note: if these two lines are combined into one we get
+                // dynamic borrow errors on `self.inner`.
+                let known = self.inner.borrow_mut().type_variables().probe(v).known();
+                known.map(|t| self.shallow_resolve(t))
+            }
+
+            ty::IntVar(v) => self
+                .inner
+                .borrow_mut()
+                .int_unification_table()
+                .probe_value(v)
+                .map(|v| v.to_type(self.tcx)),
+
+            ty::FloatVar(v) => self
+                .inner
+                .borrow_mut()
+                .float_unification_table()
+                .probe_value(v)
+                .map(|v| v.to_type(self.tcx)),
+
+            ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_) => None,
+        }
+    }
+
+    pub fn shallow_resolve_const(&self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
+        match ct.kind() {
+            ty::ConstKind::Infer(infer_ct) => match infer_ct {
+                InferConst::Var(vid) => self
+                    .inner
+                    .borrow_mut()
+                    .const_unification_table()
+                    .probe_value(vid)
+                    .known()
+                    .unwrap_or(ct),
+                InferConst::EffectVar(vid) => self
+                    .inner
+                    .borrow_mut()
+                    .effect_unification_table()
+                    .probe_value(vid)
+                    .known()
+                    .unwrap_or(ct),
+                InferConst::Fresh(_) => ct,
+            },
+            ty::ConstKind::Param(_)
+            | ty::ConstKind::Bound(_, _)
+            | ty::ConstKind::Placeholder(_)
+            | ty::ConstKind::Unevaluated(_)
+            | ty::ConstKind::Value(_)
+            | ty::ConstKind::Error(_)
+            | ty::ConstKind::Expr(_) => ct,
+        }
     }
 
     pub fn root_var(&self, var: ty::TyVid) -> ty::TyVid {
@@ -1411,10 +1469,7 @@ impl<'tcx> InferCtxt<'tcx> {
                     .entry(bt.var)
                     .or_insert_with(|| {
                         self.infcx
-                            .next_ty_var(TypeVariableOrigin {
-                                kind: TypeVariableOriginKind::MiscVariable,
-                                span: self.span,
-                            })
+                            .next_ty_var(TypeVariableOrigin { param_def_id: None, span: self.span })
                             .into()
                     })
                     .expect_ty()
@@ -1426,10 +1481,7 @@ impl<'tcx> InferCtxt<'tcx> {
                         self.infcx
                             .next_const_var(
                                 ty,
-                                ConstVariableOrigin {
-                                    kind: ConstVariableOriginKind::MiscVariable,
-                                    span: self.span,
-                                },
+                                ConstVariableOrigin { param_def_id: None, span: self.span },
                             )
                             .into()
                     })
@@ -1782,89 +1834,6 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for InferenceLiteralEraser<'tcx> {
     }
 }
 
-struct ShallowResolver<'a, 'tcx> {
-    infcx: &'a InferCtxt<'tcx>,
-}
-
-impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for ShallowResolver<'a, 'tcx> {
-    fn interner(&self) -> TyCtxt<'tcx> {
-        self.infcx.tcx
-    }
-
-    /// If `ty` is a type variable of some kind, resolve it one level
-    /// (but do not resolve types found in the result). If `typ` is
-    /// not a type variable, just return it unmodified.
-    #[inline]
-    fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
-        if let ty::Infer(v) = ty.kind() { self.fold_infer_ty(*v).unwrap_or(ty) } else { ty }
-    }
-
-    fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
-        match ct.kind() {
-            ty::ConstKind::Infer(InferConst::Var(vid)) => self
-                .infcx
-                .inner
-                .borrow_mut()
-                .const_unification_table()
-                .probe_value(vid)
-                .known()
-                .unwrap_or(ct),
-            ty::ConstKind::Infer(InferConst::EffectVar(vid)) => self
-                .infcx
-                .inner
-                .borrow_mut()
-                .effect_unification_table()
-                .probe_value(vid)
-                .known()
-                .unwrap_or(ct),
-            _ => ct,
-        }
-    }
-}
-
-impl<'a, 'tcx> ShallowResolver<'a, 'tcx> {
-    // This is separate from `fold_ty` to keep that method small and inlinable.
-    #[inline(never)]
-    fn fold_infer_ty(&mut self, v: InferTy) -> Option<Ty<'tcx>> {
-        match v {
-            ty::TyVar(v) => {
-                // Not entirely obvious: if `typ` is a type variable,
-                // it can be resolved to an int/float variable, which
-                // can then be recursively resolved, hence the
-                // recursion. Note though that we prevent type
-                // variables from unifying to other type variables
-                // directly (though they may be embedded
-                // structurally), and we prevent cycles in any case,
-                // so this recursion should always be of very limited
-                // depth.
-                //
-                // Note: if these two lines are combined into one we get
-                // dynamic borrow errors on `self.inner`.
-                let known = self.infcx.inner.borrow_mut().type_variables().probe(v).known();
-                known.map(|t| self.fold_ty(t))
-            }
-
-            ty::IntVar(v) => self
-                .infcx
-                .inner
-                .borrow_mut()
-                .int_unification_table()
-                .probe_value(v)
-                .map(|v| v.to_type(self.infcx.tcx)),
-
-            ty::FloatVar(v) => self
-                .infcx
-                .inner
-                .borrow_mut()
-                .float_unification_table()
-                .probe_value(v)
-                .map(|v| v.to_type(self.infcx.tcx)),
-
-            ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_) => None,
-        }
-    }
-}
-
 impl<'tcx> TypeTrace<'tcx> {
     pub fn span(&self) -> Span {
         self.cause.span
diff --git a/compiler/rustc_infer/src/infer/opaque_types/mod.rs b/compiler/rustc_infer/src/infer/opaque_types/mod.rs
index d32515425c4..94a546f87ee 100644
--- a/compiler/rustc_infer/src/infer/opaque_types/mod.rs
+++ b/compiler/rustc_infer/src/infer/opaque_types/mod.rs
@@ -1,4 +1,4 @@
-use super::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
+use super::type_variable::TypeVariableOrigin;
 use super::{DefineOpaqueTypes, InferResult};
 use crate::errors::OpaqueHiddenTypeDiag;
 use crate::infer::{InferCtxt, InferOk};
@@ -65,13 +65,7 @@ impl<'tcx> InferCtxt<'tcx> {
                     let span = if span.contains(def_span) { def_span } else { span };
                     let code = traits::ObligationCauseCode::OpaqueReturnType(None);
                     let cause = ObligationCause::new(span, body_id, code);
-                    // FIXME(compiler-errors): We probably should add a new TypeVariableOriginKind
-                    // for opaque types, and then use that kind to fix the spans for type errors
-                    // that we see later on.
-                    let ty_var = self.next_ty_var(TypeVariableOrigin {
-                        kind: TypeVariableOriginKind::MiscVariable,
-                        span,
-                    });
+                    let ty_var = self.next_ty_var(TypeVariableOrigin { param_def_id: None, span });
                     obligations.extend(
                         self.handle_opaque_type(ty, ty_var, &cause, param_env).unwrap().obligations,
                     );
diff --git a/compiler/rustc_infer/src/infer/projection.rs b/compiler/rustc_infer/src/infer/projection.rs
index 38e74e53868..e60efe37fd9 100644
--- a/compiler/rustc_infer/src/infer/projection.rs
+++ b/compiler/rustc_infer/src/infer/projection.rs
@@ -3,7 +3,7 @@ use rustc_middle::ty::{self, Ty};
 
 use crate::traits::{Obligation, PredicateObligation};
 
-use super::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
+use super::type_variable::TypeVariableOrigin;
 use super::InferCtxt;
 
 impl<'tcx> InferCtxt<'tcx> {
@@ -24,7 +24,7 @@ impl<'tcx> InferCtxt<'tcx> {
         debug_assert!(!self.next_trait_solver());
         let def_id = projection_ty.def_id;
         let ty_var = self.next_ty_var(TypeVariableOrigin {
-            kind: TypeVariableOriginKind::NormalizeProjectionType,
+            param_def_id: None,
             span: self.tcx.def_span(def_id),
         });
         let projection = ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::Projection(
diff --git a/compiler/rustc_infer/src/infer/relate/combine.rs b/compiler/rustc_infer/src/infer/relate/combine.rs
index 28b7db275a3..8a3125f9ded 100644
--- a/compiler/rustc_infer/src/infer/relate/combine.rs
+++ b/compiler/rustc_infer/src/infer/relate/combine.rs
@@ -155,8 +155,8 @@ impl<'tcx> InferCtxt<'tcx> {
             return Ok(a);
         }
 
-        let a = self.shallow_resolve(a);
-        let b = self.shallow_resolve(b);
+        let a = self.shallow_resolve_const(a);
+        let b = self.shallow_resolve_const(b);
 
         // We should never have to relate the `ty` field on `Const` as it is checked elsewhere that consts have the
         // correct type for the generic param they are an argument for. However there have been a number of cases
diff --git a/compiler/rustc_infer/src/infer/relate/generalize.rs b/compiler/rustc_infer/src/infer/relate/generalize.rs
index 5fb9d9341e0..74929daffe2 100644
--- a/compiler/rustc_infer/src/infer/relate/generalize.rs
+++ b/compiler/rustc_infer/src/infer/relate/generalize.rs
@@ -1,7 +1,7 @@
 use std::mem;
 
 use super::StructurallyRelateAliases;
-use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind, TypeVariableValue};
+use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableValue};
 use crate::infer::{InferCtxt, ObligationEmittingRelation, RegionVariableOrigin};
 use rustc_data_structures::sso::SsoHashMap;
 use rustc_data_structures::stack::ensure_sufficient_stack;
@@ -352,7 +352,7 @@ impl<'tcx> Generalizer<'_, 'tcx> {
     ) -> Result<Ty<'tcx>, TypeError<'tcx>> {
         if self.infcx.next_trait_solver() && !alias.has_escaping_bound_vars() {
             return Ok(self.infcx.next_ty_var_in_universe(
-                TypeVariableOrigin { kind: TypeVariableOriginKind::MiscVariable, span: self.span },
+                TypeVariableOrigin { param_def_id: None, span: self.span },
                 self.for_universe,
             ));
         }
@@ -375,10 +375,7 @@ impl<'tcx> Generalizer<'_, 'tcx> {
 
                     debug!("generalization failure in alias");
                     Ok(self.infcx.next_ty_var_in_universe(
-                        TypeVariableOrigin {
-                            kind: TypeVariableOriginKind::MiscVariable,
-                            span: self.span,
-                        },
+                        TypeVariableOrigin { param_def_id: None, span: self.span },
                         self.for_universe,
                     ))
                 }
diff --git a/compiler/rustc_infer/src/infer/relate/lattice.rs b/compiler/rustc_infer/src/infer/relate/lattice.rs
index 747158585db..f9470c9b8f6 100644
--- a/compiler/rustc_infer/src/infer/relate/lattice.rs
+++ b/compiler/rustc_infer/src/infer/relate/lattice.rs
@@ -18,7 +18,7 @@
 //! [lattices]: https://en.wikipedia.org/wiki/Lattice_(order)
 
 use super::combine::ObligationEmittingRelation;
-use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
+use crate::infer::type_variable::TypeVariableOrigin;
 use crate::infer::{DefineOpaqueTypes, InferCtxt};
 use crate::traits::ObligationCause;
 
@@ -88,18 +88,14 @@ where
         // iterate on the subtype obligations that are returned, but I
         // think this suffices. -nmatsakis
         (&ty::Infer(TyVar(..)), _) => {
-            let v = infcx.next_ty_var(TypeVariableOrigin {
-                kind: TypeVariableOriginKind::LatticeVariable,
-                span: this.cause().span,
-            });
+            let v = infcx
+                .next_ty_var(TypeVariableOrigin { param_def_id: None, span: this.cause().span });
             this.relate_bound(v, b, a)?;
             Ok(v)
         }
         (_, &ty::Infer(TyVar(..))) => {
-            let v = infcx.next_ty_var(TypeVariableOrigin {
-                kind: TypeVariableOriginKind::LatticeVariable,
-                span: this.cause().span,
-            });
+            let v = infcx
+                .next_ty_var(TypeVariableOrigin { param_def_id: None, span: this.cause().span });
             this.relate_bound(v, a, b)?;
             Ok(v)
         }
diff --git a/compiler/rustc_infer/src/infer/resolve.rs b/compiler/rustc_infer/src/infer/resolve.rs
index d5999331dfa..758aac004dc 100644
--- a/compiler/rustc_infer/src/infer/resolve.rs
+++ b/compiler/rustc_infer/src/infer/resolve.rs
@@ -12,21 +12,19 @@ use rustc_middle::ty::{self, Const, InferConst, Ty, TyCtxt, TypeFoldable};
 /// useful for printing messages etc but also required at various
 /// points for correctness.
 pub struct OpportunisticVarResolver<'a, 'tcx> {
-    // The shallow resolver is used to resolve inference variables at every
-    // level of the type.
-    shallow_resolver: crate::infer::ShallowResolver<'a, 'tcx>,
+    infcx: &'a InferCtxt<'tcx>,
 }
 
 impl<'a, 'tcx> OpportunisticVarResolver<'a, 'tcx> {
     #[inline]
     pub fn new(infcx: &'a InferCtxt<'tcx>) -> Self {
-        OpportunisticVarResolver { shallow_resolver: crate::infer::ShallowResolver { infcx } }
+        OpportunisticVarResolver { infcx }
     }
 }
 
 impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for OpportunisticVarResolver<'a, 'tcx> {
     fn interner(&self) -> TyCtxt<'tcx> {
-        TypeFolder::interner(&self.shallow_resolver)
+        self.infcx.tcx
     }
 
     #[inline]
@@ -34,7 +32,7 @@ impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for OpportunisticVarResolver<'a, 'tcx> {
         if !t.has_non_region_infer() {
             t // micro-optimize -- if there is nothing in this type that this fold affects...
         } else {
-            let t = self.shallow_resolver.fold_ty(t);
+            let t = self.infcx.shallow_resolve(t);
             t.super_fold_with(self)
         }
     }
@@ -43,7 +41,7 @@ impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for OpportunisticVarResolver<'a, 'tcx> {
         if !ct.has_non_region_infer() {
             ct // micro-optimize -- if there is nothing in this const that this fold affects...
         } else {
-            let ct = self.shallow_resolver.fold_const(ct);
+            let ct = self.infcx.shallow_resolve_const(ct);
             ct.super_fold_with(self)
         }
     }
@@ -160,7 +158,7 @@ impl<'a, 'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for FullTypeResolver<'a, 'tcx> {
         if !c.has_infer() {
             Ok(c) // micro-optimize -- if there is nothing in this const that this fold affects...
         } else {
-            let c = self.infcx.shallow_resolve(c);
+            let c = self.infcx.shallow_resolve_const(c);
             match c.kind() {
                 ty::ConstKind::Infer(InferConst::Var(vid)) => {
                     return Err(FixupError::UnresolvedConst(vid));
diff --git a/compiler/rustc_infer/src/infer/snapshot/fudge.rs b/compiler/rustc_infer/src/infer/snapshot/fudge.rs
index f8f1c1b4c45..83667f7276d 100644
--- a/compiler/rustc_infer/src/infer/snapshot/fudge.rs
+++ b/compiler/rustc_infer/src/infer/snapshot/fudge.rs
@@ -1,4 +1,4 @@
-use rustc_middle::infer::unify_key::{ConstVariableOriginKind, ConstVariableValue, ConstVidKey};
+use rustc_middle::infer::unify_key::{ConstVariableValue, ConstVidKey};
 use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
 use rustc_middle::ty::{self, ConstVid, FloatVid, IntVid, RegionVid, Ty, TyCtxt, TyVid};
 
@@ -33,10 +33,9 @@ fn const_vars_since_snapshot<'tcx>(
         range.start.vid..range.end.vid,
         (range.start.index()..range.end.index())
             .map(|index| match table.probe_value(ConstVid::from_u32(index)) {
-                ConstVariableValue::Known { value: _ } => ConstVariableOrigin {
-                    kind: ConstVariableOriginKind::MiscVariable,
-                    span: rustc_span::DUMMY_SP,
-                },
+                ConstVariableValue::Known { value: _ } => {
+                    ConstVariableOrigin { param_def_id: None, span: rustc_span::DUMMY_SP }
+                }
                 ConstVariableValue::Unknown { origin, universe: _ } => origin,
             })
             .collect(),
diff --git a/compiler/rustc_infer/src/infer/type_variable.rs b/compiler/rustc_infer/src/infer/type_variable.rs
index 55c6c92a584..96afa257ebb 100644
--- a/compiler/rustc_infer/src/infer/type_variable.rs
+++ b/compiler/rustc_infer/src/infer/type_variable.rs
@@ -2,7 +2,6 @@ use rustc_data_structures::undo_log::Rollback;
 use rustc_hir::def_id::DefId;
 use rustc_index::IndexVec;
 use rustc_middle::ty::{self, Ty, TyVid};
-use rustc_span::symbol::Symbol;
 use rustc_span::Span;
 
 use crate::infer::InferCtxtUndoLogs;
@@ -37,30 +36,11 @@ pub struct TypeVariableTable<'a, 'tcx> {
 
 #[derive(Copy, Clone, Debug)]
 pub struct TypeVariableOrigin {
-    pub kind: TypeVariableOriginKind,
     pub span: Span,
-}
-
-/// Reasons to create a type inference variable
-#[derive(Copy, Clone, Debug)]
-pub enum TypeVariableOriginKind {
-    MiscVariable,
-    NormalizeProjectionType,
-    TypeInference,
-    TypeParameterDefinition(Symbol, DefId),
-
-    /// 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,
-    AutoDeref,
-    AdjustmentType,
-
-    /// In type check, when we are type checking a function that
-    /// returns `-> dyn Foo`, we instantiate a type variable with the
-    /// return type for diagnostic purposes.
-    DynReturnFn,
-    LatticeVariable,
+    /// `DefId` of the type parameter this was instantiated for, if any.
+    ///
+    /// This should only be used for diagnostics.
+    pub param_def_id: Option<DefId>,
 }
 
 #[derive(Clone)]
diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs
index da2fb490a36..c5b81dbd679 100644
--- a/compiler/rustc_interface/src/interface.rs
+++ b/compiler/rustc_interface/src/interface.rs
@@ -5,6 +5,7 @@ use rustc_ast::{LitKind, MetaItemKind};
 use rustc_codegen_ssa::traits::CodegenBackend;
 use rustc_data_structures::defer;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_data_structures::jobserver;
 use rustc_data_structures::stable_hasher::StableHasher;
 use rustc_data_structures::sync::Lrc;
 use rustc_errors::registry::Registry;
@@ -21,7 +22,7 @@ use rustc_session::config::{self, Cfg, CheckCfg, ExpectedValues, Input, OutFileN
 use rustc_session::filesearch::{self, sysroot_candidates};
 use rustc_session::parse::ParseSess;
 use rustc_session::{lint, CompilerIO, EarlyDiagCtxt, Session};
-use rustc_span::source_map::FileLoader;
+use rustc_span::source_map::{FileLoader, RealFileLoader, SourceMapInputs};
 use rustc_span::symbol::sym;
 use rustc_span::FileName;
 use std::path::PathBuf;
@@ -323,6 +324,18 @@ pub struct Config {
     pub expanded_args: Vec<String>,
 }
 
+/// Initialize jobserver before getting `jobserver::client` and `build_session`.
+pub(crate) fn initialize_checked_jobserver(early_dcx: &EarlyDiagCtxt) {
+    jobserver::initialize_checked(|err| {
+        #[allow(rustc::untranslatable_diagnostic)]
+        #[allow(rustc::diagnostic_outside_of_impl)]
+        early_dcx
+            .early_struct_warn(err)
+            .with_note("the build environment is likely misconfigured")
+            .emit()
+    });
+}
+
 // JUSTIFICATION: before session exists, only config
 #[allow(rustc::bad_opt_access)]
 #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
@@ -334,20 +347,25 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se
 
     // Check jobserver before run_in_thread_pool_with_globals, which call jobserver::acquire_thread
     let early_dcx = EarlyDiagCtxt::new(config.opts.error_format);
-    early_dcx.initialize_checked_jobserver();
+    initialize_checked_jobserver(&early_dcx);
+
+    crate::callbacks::setup_callbacks();
+
+    let sysroot = filesearch::materialize_sysroot(config.opts.maybe_sysroot.clone());
+    let target = config::build_target_config(&early_dcx, &config.opts, &sysroot);
+    let file_loader = config.file_loader.unwrap_or_else(|| Box::new(RealFileLoader));
+    let path_mapping = config.opts.file_path_mapping();
+    let hash_kind = config.opts.unstable_opts.src_hash_algorithm(&target);
 
     util::run_in_thread_pool_with_globals(
         config.opts.edition,
         config.opts.unstable_opts.threads,
+        SourceMapInputs { file_loader, path_mapping, hash_kind },
         |current_gcx| {
-            crate::callbacks::setup_callbacks();
-
+            // The previous `early_dcx` can't be reused here because it doesn't
+            // impl `Send`. Creating a new one is fine.
             let early_dcx = EarlyDiagCtxt::new(config.opts.error_format);
 
-            let sysroot = filesearch::materialize_sysroot(config.opts.maybe_sysroot.clone());
-
-            let target = config::build_target_config(&early_dcx, &config.opts, &sysroot);
-
             let codegen_backend = match config.make_codegen_backend {
                 None => util::get_codegen_backend(
                     &early_dcx,
@@ -372,9 +390,7 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se
                 config.opts.unstable_opts.translate_directionality_markers,
             ) {
                 Ok(bundle) => bundle,
-                Err(e) => {
-                    early_dcx.early_fatal(format!("failed to load fluent bundle: {e}"));
-                }
+                Err(e) => early_dcx.early_fatal(format!("failed to load fluent bundle: {e}")),
             };
 
             let mut locale_resources = Vec::from(config.locale_resources);
@@ -393,7 +409,6 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se
                 config.registry.clone(),
                 locale_resources,
                 config.lint_caps,
-                config.file_loader,
                 target,
                 sysroot,
                 util::rustc_version_str().unwrap_or("unknown"),
@@ -440,45 +455,43 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se
                 current_gcx,
             };
 
-            rustc_span::set_source_map(compiler.sess.psess.clone_source_map(), move || {
-                // There are two paths out of `f`.
-                // - Normal exit.
-                // - Panic, e.g. triggered by `abort_if_errors`.
-                //
-                // We must run `finish_diagnostics` in both cases.
-                let res = {
-                    // If `f` panics, `finish_diagnostics` will run during
-                    // unwinding because of the `defer`.
-                    let mut guar = None;
-                    let sess_abort_guard = defer(|| {
-                        guar = compiler.sess.finish_diagnostics(&config.registry);
-                    });
-
-                    let res = f(&compiler);
-
-                    // If `f` doesn't panic, `finish_diagnostics` will run
-                    // normally when `sess_abort_guard` is dropped.
-                    drop(sess_abort_guard);
-
-                    // If `finish_diagnostics` emits errors (e.g. stashed
-                    // errors) we can't return an error directly, because the
-                    // return type of this function is `R`, not `Result<R, E>`.
-                    // But we need to communicate the errors' existence to the
-                    // caller, otherwise the caller might mistakenly think that
-                    // no errors occurred and return a zero exit code. So we
-                    // abort (panic) instead, similar to if `f` had panicked.
-                    if guar.is_some() {
-                        compiler.sess.dcx().abort_if_errors();
-                    }
+            // There are two paths out of `f`.
+            // - Normal exit.
+            // - Panic, e.g. triggered by `abort_if_errors`.
+            //
+            // We must run `finish_diagnostics` in both cases.
+            let res = {
+                // If `f` panics, `finish_diagnostics` will run during
+                // unwinding because of the `defer`.
+                let mut guar = None;
+                let sess_abort_guard = defer(|| {
+                    guar = compiler.sess.finish_diagnostics(&config.registry);
+                });
+
+                let res = f(&compiler);
+
+                // If `f` doesn't panic, `finish_diagnostics` will run
+                // normally when `sess_abort_guard` is dropped.
+                drop(sess_abort_guard);
+
+                // If `finish_diagnostics` emits errors (e.g. stashed
+                // errors) we can't return an error directly, because the
+                // return type of this function is `R`, not `Result<R, E>`.
+                // But we need to communicate the errors' existence to the
+                // caller, otherwise the caller might mistakenly think that
+                // no errors occurred and return a zero exit code. So we
+                // abort (panic) instead, similar to if `f` had panicked.
+                if guar.is_some() {
+                    compiler.sess.dcx().abort_if_errors();
+                }
 
-                    res
-                };
+                res
+            };
 
-                let prof = compiler.sess.prof.clone();
-                prof.generic_activity("drop_compiler").run(move || drop(compiler));
+            let prof = compiler.sess.prof.clone();
+            prof.generic_activity("drop_compiler").run(move || drop(compiler));
 
-                res
-            })
+            res
         },
     )
 }
diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs
index d2fb65b5d4f..e563728c893 100644
--- a/compiler/rustc_interface/src/tests.rs
+++ b/compiler/rustc_interface/src/tests.rs
@@ -1,5 +1,5 @@
 #![allow(rustc::bad_opt_access)]
-use crate::interface::parse_cfg;
+use crate::interface::{initialize_checked_jobserver, parse_cfg};
 use rustc_data_structures::profiling::TimePassesFormat;
 use rustc_errors::{emitter::HumanReadableErrorType, registry, ColorConfig};
 use rustc_session::config::{
@@ -16,6 +16,7 @@ use rustc_session::search_paths::SearchPath;
 use rustc_session::utils::{CanonicalizedPath, NativeLib, NativeLibKind};
 use rustc_session::{build_session, filesearch, getopts, CompilerIO, EarlyDiagCtxt, Session};
 use rustc_span::edition::{Edition, DEFAULT_EDITION};
+use rustc_span::source_map::{RealFileLoader, SourceMapInputs};
 use rustc_span::symbol::sym;
 use rustc_span::{FileName, SourceFileHashAlgorithm};
 use rustc_target::spec::{CodeModel, LinkerFlavorCli, MergeFunctions, PanicStrategy, RelocModel};
@@ -25,42 +26,52 @@ use std::num::NonZero;
 use std::path::{Path, PathBuf};
 use std::sync::Arc;
 
-fn mk_session(matches: getopts::Matches) -> (Session, Cfg) {
+fn sess_and_cfg<F>(args: &[&'static str], f: F)
+where
+    F: FnOnce(Session, Cfg),
+{
     let mut early_dcx = EarlyDiagCtxt::new(ErrorOutputType::default());
-    early_dcx.initialize_checked_jobserver();
+    initialize_checked_jobserver(&early_dcx);
 
-    let registry = registry::Registry::new(&[]);
+    let matches = optgroups().parse(args).unwrap();
     let sessopts = build_session_options(&mut early_dcx, &matches);
-    let temps_dir = sessopts.unstable_opts.temps_dir.as_deref().map(PathBuf::from);
-    let io = CompilerIO {
-        input: Input::Str { name: FileName::Custom(String::new()), input: String::new() },
-        output_dir: None,
-        output_file: None,
-        temps_dir,
-    };
-
     let sysroot = filesearch::materialize_sysroot(sessopts.maybe_sysroot.clone());
-
     let target = rustc_session::config::build_target_config(&early_dcx, &sessopts, &sysroot);
+    let hash_kind = sessopts.unstable_opts.src_hash_algorithm(&target);
+    let sm_inputs = Some(SourceMapInputs {
+        file_loader: Box::new(RealFileLoader) as _,
+        path_mapping: sessopts.file_path_mapping(),
+        hash_kind,
+    });
 
-    let sess = build_session(
-        early_dcx,
-        sessopts,
-        io,
-        None,
-        registry,
-        vec![],
-        Default::default(),
-        None,
-        target,
-        sysroot,
-        "",
-        None,
-        Arc::default(),
-        Default::default(),
-    );
-    let cfg = parse_cfg(&sess.dcx(), matches.opt_strs("cfg"));
-    (sess, cfg)
+    rustc_span::create_session_globals_then(DEFAULT_EDITION, sm_inputs, || {
+        let temps_dir = sessopts.unstable_opts.temps_dir.as_deref().map(PathBuf::from);
+        let io = CompilerIO {
+            input: Input::Str { name: FileName::Custom(String::new()), input: String::new() },
+            output_dir: None,
+            output_file: None,
+            temps_dir,
+        };
+
+        let sess = build_session(
+            early_dcx,
+            sessopts,
+            io,
+            None,
+            registry::Registry::new(&[]),
+            vec![],
+            Default::default(),
+            target,
+            sysroot,
+            "",
+            None,
+            Arc::default(),
+            Default::default(),
+        );
+        let cfg = parse_cfg(&sess.dcx(), matches.opt_strs("cfg"));
+        let cfg = build_configuration(&sess, cfg);
+        f(sess, cfg)
+    });
 }
 
 fn new_public_extern_entry<S, I>(locations: I) -> ExternEntry
@@ -125,21 +136,15 @@ fn assert_non_crate_hash_different(x: &Options, y: &Options) {
 // When the user supplies --test we should implicitly supply --cfg test
 #[test]
 fn test_switch_implies_cfg_test() {
-    rustc_span::create_default_session_globals_then(|| {
-        let matches = optgroups().parse(&["--test".to_string()]).unwrap();
-        let (sess, cfg) = mk_session(matches);
-        let cfg = build_configuration(&sess, cfg);
+    sess_and_cfg(&["--test"], |_sess, cfg| {
         assert!(cfg.contains(&(sym::test, None)));
-    });
+    })
 }
 
 // When the user supplies --test and --cfg test, don't implicitly add another --cfg test
 #[test]
 fn test_switch_implies_cfg_test_unless_cfg_test() {
-    rustc_span::create_default_session_globals_then(|| {
-        let matches = optgroups().parse(&["--test".to_string(), "--cfg=test".to_string()]).unwrap();
-        let (sess, cfg) = mk_session(matches);
-        let cfg = build_configuration(&sess, cfg);
+    sess_and_cfg(&["--test", "--cfg=test"], |_sess, cfg| {
         let mut test_items = cfg.iter().filter(|&&(name, _)| name == sym::test);
         assert!(test_items.next().is_some());
         assert!(test_items.next().is_none());
@@ -148,22 +153,15 @@ fn test_switch_implies_cfg_test_unless_cfg_test() {
 
 #[test]
 fn test_can_print_warnings() {
-    rustc_span::create_default_session_globals_then(|| {
-        let matches = optgroups().parse(&["-Awarnings".to_string()]).unwrap();
-        let (sess, _) = mk_session(matches);
+    sess_and_cfg(&["-Awarnings"], |sess, _cfg| {
         assert!(!sess.dcx().can_emit_warnings());
     });
 
-    rustc_span::create_default_session_globals_then(|| {
-        let matches =
-            optgroups().parse(&["-Awarnings".to_string(), "-Dwarnings".to_string()]).unwrap();
-        let (sess, _) = mk_session(matches);
+    sess_and_cfg(&["-Awarnings", "-Dwarnings"], |sess, _cfg| {
         assert!(sess.dcx().can_emit_warnings());
     });
 
-    rustc_span::create_default_session_globals_then(|| {
-        let matches = optgroups().parse(&["-Adead_code".to_string()]).unwrap();
-        let (sess, _) = mk_session(matches);
+    sess_and_cfg(&["-Adead_code"], |sess, _cfg| {
         assert!(sess.dcx().can_emit_warnings());
     });
 }
@@ -624,6 +622,7 @@ fn test_codegen_options_tracking_hash() {
     tracked!(profile_generate, SwitchWithOptPath::Enabled(None));
     tracked!(profile_use, Some(PathBuf::from("abc")));
     tracked!(relocation_model, Some(RelocModel::Pic));
+    tracked!(relro_level, Some(RelroLevel::Full));
     tracked!(soft_float, true);
     tracked!(split_debuginfo, Some(SplitDebuginfo::Packed));
     tracked!(symbol_mangling_version, Some(SymbolManglingVersion::V0));
@@ -822,7 +821,6 @@ fn test_unstable_options_tracking_hash() {
     tracked!(profile_sample_use, Some(PathBuf::from("abc")));
     tracked!(profiler_runtime, "abc".to_string());
     tracked!(relax_elf_relocations, Some(true));
-    tracked!(relro_level, Some(RelroLevel::Full));
     tracked!(remap_cwd_prefix, Some(PathBuf::from("abc")));
     tracked!(sanitizer, SanitizerSet::ADDRESS);
     tracked!(sanitizer_cfi_canonical_jump_tables, None);
diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs
index d0f04fccc48..02dcfe9c8df 100644
--- a/compiler/rustc_interface/src/util.rs
+++ b/compiler/rustc_interface/src/util.rs
@@ -14,6 +14,7 @@ use rustc_session::lint::{self, BuiltinLintDiag, LintBuffer};
 use rustc_session::{filesearch, Session};
 use rustc_span::edit_distance::find_best_match_for_name;
 use rustc_span::edition::Edition;
+use rustc_span::source_map::SourceMapInputs;
 use rustc_span::symbol::sym;
 use rustc_target::spec::Target;
 use session::output::{categorize_crate_type, CRATE_TYPES};
@@ -65,8 +66,9 @@ fn init_stack_size() -> usize {
     })
 }
 
-pub(crate) fn run_in_thread_with_globals<F: FnOnce(CurrentGcx) -> R + Send, R: Send>(
+fn run_in_thread_with_globals<F: FnOnce(CurrentGcx) -> R + Send, R: Send>(
     edition: Edition,
+    sm_inputs: SourceMapInputs,
     f: F,
 ) -> R {
     // The "thread pool" is a single spawned thread in the non-parallel
@@ -84,7 +86,9 @@ pub(crate) fn run_in_thread_with_globals<F: FnOnce(CurrentGcx) -> R + Send, R: S
         // name contains null bytes.
         let r = builder
             .spawn_scoped(s, move || {
-                rustc_span::create_session_globals_then(edition, || f(CurrentGcx::new()))
+                rustc_span::create_session_globals_then(edition, Some(sm_inputs), || {
+                    f(CurrentGcx::new())
+                })
             })
             .unwrap()
             .join();
@@ -100,15 +104,17 @@ pub(crate) fn run_in_thread_with_globals<F: FnOnce(CurrentGcx) -> R + Send, R: S
 pub(crate) fn run_in_thread_pool_with_globals<F: FnOnce(CurrentGcx) -> R + Send, R: Send>(
     edition: Edition,
     _threads: usize,
+    sm_inputs: SourceMapInputs,
     f: F,
 ) -> R {
-    run_in_thread_with_globals(edition, f)
+    run_in_thread_with_globals(edition, sm_inputs, f)
 }
 
 #[cfg(parallel_compiler)]
 pub(crate) fn run_in_thread_pool_with_globals<F: FnOnce(CurrentGcx) -> R + Send, R: Send>(
     edition: Edition,
     threads: usize,
+    sm_inputs: SourceMapInputs,
     f: F,
 ) -> R {
     use rustc_data_structures::{defer, jobserver, sync::FromDyn};
@@ -120,7 +126,7 @@ pub(crate) fn run_in_thread_pool_with_globals<F: FnOnce(CurrentGcx) -> R + Send,
     let registry = sync::Registry::new(std::num::NonZero::new(threads).unwrap());
 
     if !sync::is_dyn_thread_safe() {
-        return run_in_thread_with_globals(edition, |current_gcx| {
+        return run_in_thread_with_globals(edition, sm_inputs, |current_gcx| {
             // Register the thread for use with the `WorkerLocal` type.
             registry.register();
 
@@ -169,7 +175,7 @@ pub(crate) fn run_in_thread_pool_with_globals<F: FnOnce(CurrentGcx) -> R + Send,
     // pool. Upon creation, each worker thread created gets a copy of the
     // session globals in TLS. This is possible because `SessionGlobals` impls
     // `Send` in the parallel compiler.
-    rustc_span::create_session_globals_then(edition, || {
+    rustc_span::create_session_globals_then(edition, Some(sm_inputs), || {
         rustc_span::with_session_globals(|session_globals| {
             let session_globals = FromDyn::from(session_globals);
             builder
diff --git a/compiler/rustc_lint/src/context/diagnostics/check_cfg.rs b/compiler/rustc_lint/src/context/diagnostics/check_cfg.rs
index 2c9a3a6d1b2..0472525d49a 100644
--- a/compiler/rustc_lint/src/context/diagnostics/check_cfg.rs
+++ b/compiler/rustc_lint/src/context/diagnostics/check_cfg.rs
@@ -168,7 +168,7 @@ pub(super) fn unexpected_cfg_name(
         diag.note("see <https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#check-cfg> for more information about checking conditional configuration");
     } else {
         diag.help(format!("to expect this configuration use `--check-cfg={inst}`"));
-        diag.note("see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration");
+        diag.note("see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration");
     }
 }
 
@@ -272,6 +272,6 @@ pub(super) fn unexpected_cfg_value(
         if !is_cfg_a_well_know_name {
             diag.help(format!("to expect this configuration use `--check-cfg={inst}`"));
         }
-        diag.note("see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration");
+        diag.note("see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration");
     }
 }
diff --git a/compiler/rustc_lint/src/late.rs b/compiler/rustc_lint/src/late.rs
index 99207e3f315..ca188277b9d 100644
--- a/compiler/rustc_lint/src/late.rs
+++ b/compiler/rustc_lint/src/late.rs
@@ -20,6 +20,7 @@ use rustc_data_structures::sync::{join, Lrc};
 use rustc_hir as hir;
 use rustc_hir::def_id::{LocalDefId, LocalModDefId};
 use rustc_hir::intravisit as hir_visit;
+use rustc_hir::HirId;
 use rustc_middle::hir::nested_filter;
 use rustc_middle::ty::{self, TyCtxt};
 use rustc_session::lint::LintPass;
@@ -53,7 +54,7 @@ impl<'tcx, T: LateLintPass<'tcx>> LateContextAndPass<'tcx, T> {
     /// Merge the lints specified by any lint attributes into the
     /// current lint context, call the provided function, then reset the
     /// lints in effect to their previous state.
-    fn with_lint_attrs<F>(&mut self, id: hir::HirId, f: F)
+    fn with_lint_attrs<F>(&mut self, id: HirId, f: F)
     where
         F: FnOnce(&mut Self),
     {
@@ -81,7 +82,7 @@ impl<'tcx, T: LateLintPass<'tcx>> LateContextAndPass<'tcx, T> {
         self.context.param_env = old_param_env;
     }
 
-    fn process_mod(&mut self, m: &'tcx hir::Mod<'tcx>, n: hir::HirId) {
+    fn process_mod(&mut self, m: &'tcx hir::Mod<'tcx>, n: HirId) {
         lint_callback!(self, check_mod, m, n);
         hir_visit::walk_mod(self, m, n);
     }
@@ -231,7 +232,7 @@ impl<'tcx, T: LateLintPass<'tcx>> hir_visit::Visitor<'tcx> for LateContextAndPas
         hir_visit::walk_inf(self, inf);
     }
 
-    fn visit_mod(&mut self, m: &'tcx hir::Mod<'tcx>, _: Span, n: hir::HirId) {
+    fn visit_mod(&mut self, m: &'tcx hir::Mod<'tcx>, _: Span, n: HirId) {
         if !self.context.only_module {
             self.process_mod(m, n);
         }
@@ -305,7 +306,7 @@ impl<'tcx, T: LateLintPass<'tcx>> hir_visit::Visitor<'tcx> for LateContextAndPas
         hir_visit::walk_lifetime(self, lt);
     }
 
-    fn visit_path(&mut self, p: &hir::Path<'tcx>, id: hir::HirId) {
+    fn visit_path(&mut self, p: &hir::Path<'tcx>, id: HirId) {
         lint_callback!(self, check_path, p, id);
         hir_visit::walk_path(self, p);
     }
diff --git a/compiler/rustc_lint/src/non_local_def.rs b/compiler/rustc_lint/src/non_local_def.rs
index 870e198d70a..4b06278330f 100644
--- a/compiler/rustc_lint/src/non_local_def.rs
+++ b/compiler/rustc_lint/src/non_local_def.rs
@@ -1,9 +1,8 @@
 use rustc_hir::{def::DefKind, Body, Item, ItemKind, Node, TyKind};
 use rustc_hir::{Path, QPath};
-use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
+use rustc_infer::infer::type_variable::TypeVariableOrigin;
 use rustc_infer::infer::InferCtxt;
 use rustc_infer::traits::{Obligation, ObligationCause};
-use rustc_middle::query::Key;
 use rustc_middle::ty::{self, Binder, Ty, TyCtxt, TypeFoldable, TypeFolder};
 use rustc_middle::ty::{EarlyBinder, TraitRef, TypeSuperFoldable};
 use rustc_span::def_id::{DefId, LOCAL_CRATE};
@@ -313,13 +312,10 @@ impl<'a, 'tcx, F: FnMut(DefId) -> bool> TypeFolder<TyCtxt<'tcx>>
     }
 
     fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
-        if let Some(ty_did) = t.ty_def_id()
-            && (self.did_has_local_parent)(ty_did)
+        if let Some(def) = t.ty_adt_def()
+            && (self.did_has_local_parent)(def.did())
         {
-            self.infcx.next_ty_var(TypeVariableOrigin {
-                kind: TypeVariableOriginKind::TypeInference,
-                span: self.infer_span,
-            })
+            self.infcx.next_ty_var(TypeVariableOrigin { param_def_id: None, span: self.infer_span })
         } else {
             t.super_fold_with(self)
         }
diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs
index 503caa35358..3fe1f21d56a 100644
--- a/compiler/rustc_lint/src/unused.rs
+++ b/compiler/rustc_lint/src/unused.rs
@@ -1235,7 +1235,7 @@ impl EarlyLintPass for UnusedParens {
                     ast::TyKind::TraitObject(..) => {}
                     ast::TyKind::BareFn(b)
                         if self.with_self_ty_parens && b.generic_params.len() > 0 => {}
-                    ast::TyKind::ImplTrait(_, bounds) if bounds.len() > 1 => {}
+                    ast::TyKind::ImplTrait(_, bounds, _) if bounds.len() > 1 => {}
                     _ => {
                         let spans = if !ty.span.from_expansion() {
                             r.span
diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs
index 2713690f812..e74cc388cab 100644
--- a/compiler/rustc_lint_defs/src/builtin.rs
+++ b/compiler/rustc_lint_defs/src/builtin.rs
@@ -38,6 +38,7 @@ declare_lint_pass! {
         DEPRECATED_CFG_ATTR_CRATE_TYPE_NAME,
         DEPRECATED_IN_FUTURE,
         DEPRECATED_WHERE_CLAUSE_LOCATION,
+        DEREFERENCING_MUT_BINDING,
         DUPLICATE_MACRO_ATTRIBUTES,
         ELIDED_LIFETIMES_IN_ASSOCIATED_CONSTANT,
         ELIDED_LIFETIMES_IN_PATHS,
@@ -1628,6 +1629,42 @@ declare_lint! {
 }
 
 declare_lint! {
+    /// The `dereferencing_mut_binding` lint detects a `mut x` pattern that resets the binding mode,
+    /// as this behavior will change in rust 2024.
+    ///
+    /// ### Example
+    ///
+    /// ```rust
+    /// # #![warn(dereferencing_mut_binding)]
+    /// let x = Some(123u32);
+    /// let _y = match &x {
+    ///     Some(mut x) => {
+    ///         x += 1;
+    ///         x
+    ///     }
+    ///     None => 0,
+    /// };
+    /// ```
+    ///
+    /// {{produces}}
+    ///
+    /// ### Explanation
+    ///
+    /// Without the `mut`, `x` would have type `&u32`. Pre-2024, adding `mut` makes `x` have type
+    /// `u32`, which was deemed surprising. After edition 2024, adding `mut` will not change the
+    /// type of `x`. This lint warns users of editions before 2024 to update their code.
+    pub DEREFERENCING_MUT_BINDING,
+    Allow,
+    "detects `mut x` bindings that change the type of `x`",
+    @feature_gate = sym::mut_preserve_binding_mode_2024;
+    // FIXME uncomment below upon stabilization
+    /*@future_incompatible = FutureIncompatibleInfo {
+        reason: FutureIncompatibilityReason::EditionSemanticsChange(Edition::Edition2024),
+        reference: "123076",
+    };*/
+}
+
+declare_lint! {
     /// The `unconditional_recursion` lint detects functions that cannot
     /// return without calling themselves.
     ///
diff --git a/compiler/rustc_log/src/lib.rs b/compiler/rustc_log/src/lib.rs
index e4b67cde244..81257f9be88 100644
--- a/compiler/rustc_log/src/lib.rs
+++ b/compiler/rustc_log/src/lib.rs
@@ -17,7 +17,7 @@
 //!     rustc_log::init_logger(rustc_log::LoggerConfig::from_env("LOG")).unwrap();
 //!
 //!     let edition = rustc_span::edition::Edition::Edition2021;
-//!     rustc_span::create_session_globals_then(edition, || {
+//!     rustc_span::create_session_globals_then(edition, None, || {
 //!         /* ... */
 //!     });
 //! }
diff --git a/compiler/rustc_middle/Cargo.toml b/compiler/rustc_middle/Cargo.toml
index 6c3ff237d59..d1cdabc293d 100644
--- a/compiler/rustc_middle/Cargo.toml
+++ b/compiler/rustc_middle/Cargo.toml
@@ -25,6 +25,7 @@ rustc_feature = { path = "../rustc_feature" }
 rustc_fluent_macro = { path = "../rustc_fluent_macro" }
 rustc_graphviz = { path = "../rustc_graphviz" }
 rustc_hir = { path = "../rustc_hir" }
+rustc_hir_pretty = { path = "../rustc_hir_pretty" }
 rustc_index = { path = "../rustc_index" }
 rustc_macros = { path = "../rustc_macros" }
 rustc_query_system = { path = "../rustc_query_system" }
diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs
index 72f849b534a..c0c773c6285 100644
--- a/compiler/rustc_middle/src/hir/map/mod.rs
+++ b/compiler/rustc_middle/src/hir/map/mod.rs
@@ -13,6 +13,7 @@ use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId, LOCAL_CRATE};
 use rustc_hir::definitions::{DefKey, DefPath, DefPathHash};
 use rustc_hir::intravisit::Visitor;
 use rustc_hir::*;
+use rustc_hir_pretty as pprust_hir;
 use rustc_middle::hir::nested_filter;
 use rustc_span::def_id::StableCrateId;
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
@@ -909,6 +910,7 @@ impl<'hir> Map<'hir> {
             Node::Crate(item) => item.spans.inner_span,
             Node::WhereBoundPredicate(pred) => pred.span,
             Node::ArrayLenInfer(inf) => inf.span,
+            Node::PreciseCapturingNonLifetimeArg(param) => param.ident.span,
             Node::Synthetic => unreachable!(),
             Node::Err(span) => *span,
         }
@@ -999,6 +1001,12 @@ impl<'hir> intravisit::Map<'hir> for Map<'hir> {
     }
 }
 
+impl<'tcx> pprust_hir::PpAnn for TyCtxt<'tcx> {
+    fn nested(&self, state: &mut pprust_hir::State<'_>, nested: pprust_hir::Nested) {
+        pprust_hir::PpAnn::nested(&(&self.hir() as &dyn intravisit::Map<'_>), state, nested)
+    }
+}
+
 pub(super) fn crate_hash(tcx: TyCtxt<'_>, _: LocalCrate) -> Svh {
     let krate = tcx.hir_crate(());
     let hir_body_hash = krate.opt_hir_hash.expect("HIR hash missing while computing crate hash");
@@ -1176,6 +1184,7 @@ fn hir_id_to_string(map: Map<'_>, id: HirId) -> String {
         Node::ArrayLenInfer(_) => node_str("array len infer"),
         Node::Synthetic => unreachable!(),
         Node::Err(_) => node_str("error"),
+        Node::PreciseCapturingNonLifetimeArg(_param) => node_str("parameter"),
     }
 }
 
diff --git a/compiler/rustc_middle/src/hooks/mod.rs b/compiler/rustc_middle/src/hooks/mod.rs
index f7ce15d0a8d..d35b9fc46e4 100644
--- a/compiler/rustc_middle/src/hooks/mod.rs
+++ b/compiler/rustc_middle/src/hooks/mod.rs
@@ -47,12 +47,7 @@ macro_rules! declare_hooks {
         impl Default for Providers {
             fn default() -> Self {
                 Providers {
-                    $($name: |_, $($arg,)*| bug!(
-                        "`tcx.{}{:?}` cannot be called as `{}` was never assigned to a provider function.\n",
-                        stringify!($name),
-                        ($($arg,)*),
-                        stringify!($name),
-                    ),)*
+                    $($name: |_, $($arg,)*| default_hook(stringify!($name), &($($arg,)*))),*
                 }
             }
         }
@@ -84,7 +79,6 @@ declare_hooks! {
     /// via `mir_built`
     hook build_mir(key: LocalDefId) -> mir::Body<'tcx>;
 
-
     /// Imports all `SourceFile`s from the given crate into the current session.
     /// This normally happens automatically when we decode a `Span` from
     /// that crate's metadata - however, the incr comp cache needs
@@ -102,4 +96,17 @@ declare_hooks! {
     /// turn a deserialized `DefPathHash` into its current `DefId`.
     /// Will fetch a DefId from a DefPathHash for a foreign crate.
     hook def_path_hash_to_def_id_extern(hash: DefPathHash, stable_crate_id: StableCrateId) -> DefId;
+
+    /// Create a THIR tree for debugging.
+    hook thir_tree(key: LocalDefId) -> String;
+
+    /// Create a list-like THIR representation for debugging.
+    hook thir_flat(key: LocalDefId) -> String;
+}
+
+#[cold]
+fn default_hook(name: &str, args: &dyn std::fmt::Debug) -> ! {
+    bug!(
+        "`tcx.{name}{args:?}` cannot be called as `{name}` was never assigned to a provider function"
+    )
 }
diff --git a/compiler/rustc_middle/src/infer/unify_key.rs b/compiler/rustc_middle/src/infer/unify_key.rs
index 84b428297db..105be21f272 100644
--- a/compiler/rustc_middle/src/infer/unify_key.rs
+++ b/compiler/rustc_middle/src/infer/unify_key.rs
@@ -1,7 +1,6 @@
 use crate::ty::{self, Ty, TyCtxt};
 use rustc_data_structures::unify::{NoError, UnifyKey, UnifyValue};
 use rustc_span::def_id::DefId;
-use rustc_span::symbol::Symbol;
 use rustc_span::Span;
 use std::cmp;
 use std::marker::PhantomData;
@@ -106,16 +105,11 @@ impl ToType for ty::FloatVarValue {
 
 #[derive(Copy, Clone, Debug)]
 pub struct ConstVariableOrigin {
-    pub kind: ConstVariableOriginKind,
     pub span: Span,
-}
-
-/// Reasons to create a const inference variable
-#[derive(Copy, Clone, Debug)]
-pub enum ConstVariableOriginKind {
-    MiscVariable,
-    ConstInference,
-    ConstParameterDefinition(Symbol, DefId),
+    /// `DefId` of the const parameter this was instantiated for, if any.
+    ///
+    /// This should only be used for diagnostics.
+    pub param_def_id: Option<DefId>,
 }
 
 #[derive(Copy, Clone, Debug)]
diff --git a/compiler/rustc_middle/src/middle/region.rs b/compiler/rustc_middle/src/middle/region.rs
index b9914f6cb7a..5ae60e04277 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::FxIndexMap;
 use rustc_data_structures::unord::UnordMap;
 use rustc_hir as hir;
-use rustc_hir::{HirIdMap, Node};
+use rustc_hir::{HirId, HirIdMap, Node};
 use rustc_macros::HashStable;
 use rustc_span::{Span, DUMMY_SP};
 
@@ -164,10 +164,10 @@ impl Scope {
         self.id
     }
 
-    pub fn hir_id(&self, scope_tree: &ScopeTree) -> Option<hir::HirId> {
+    pub fn hir_id(&self, scope_tree: &ScopeTree) -> Option<HirId> {
         scope_tree
             .root_body
-            .map(|hir_id| hir::HirId { owner: hir_id.owner, local_id: self.item_local_id() })
+            .map(|hir_id| HirId { owner: hir_id.owner, local_id: self.item_local_id() })
     }
 
     /// Returns the span of this `Scope`. Note that in general the
@@ -207,7 +207,7 @@ pub type ScopeDepth = u32;
 #[derive(Default, Debug, HashStable)]
 pub struct ScopeTree {
     /// If not empty, this body is the root of this region hierarchy.
-    pub root_body: Option<hir::HirId>,
+    pub root_body: Option<HirId>,
 
     /// Maps from a scope ID to the enclosing scope id;
     /// this is usually corresponding to the lexical nesting, though
@@ -341,11 +341,7 @@ impl ScopeTree {
         self.var_map.insert(var, lifetime);
     }
 
-    pub fn record_rvalue_candidate(
-        &mut self,
-        var: hir::HirId,
-        candidate_type: RvalueCandidateType,
-    ) {
+    pub fn record_rvalue_candidate(&mut self, var: HirId, candidate_type: RvalueCandidateType) {
         debug!("record_rvalue_candidate(var={var:?}, type={candidate_type:?})");
         match &candidate_type {
             RvalueCandidateType::Borrow { lifetime: Some(lifetime), .. }
diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs
index 601bfc770f4..df013effcb0 100644
--- a/compiler/rustc_middle/src/mir/mod.rs
+++ b/compiler/rustc_middle/src/mir/mod.rs
@@ -1545,7 +1545,7 @@ pub struct SourceScopeData<'tcx> {
 #[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)]
 pub struct SourceScopeLocalData {
     /// An `HirId` with lint levels equivalent to this scope's lint levels.
-    pub lint_root: hir::HirId,
+    pub lint_root: HirId,
 }
 
 /// A collection of projections into user types.
@@ -1823,9 +1823,7 @@ mod size_asserts {
     static_assert_size!(LocalDecl<'_>, 40);
     static_assert_size!(SourceScopeData<'_>, 64);
     static_assert_size!(Statement<'_>, 32);
-    static_assert_size!(StatementKind<'_>, 16);
     static_assert_size!(Terminator<'_>, 112);
-    static_assert_size!(TerminatorKind<'_>, 96);
     static_assert_size!(VarDebugInfo<'_>, 88);
     // tidy-alphabetical-end
 }
diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs
index c78c225b0cd..9b409574026 100644
--- a/compiler/rustc_middle/src/mir/syntax.rs
+++ b/compiler/rustc_middle/src/mir/syntax.rs
@@ -1463,5 +1463,6 @@ mod size_asserts {
     static_assert_size!(PlaceElem<'_>, 24);
     static_assert_size!(Rvalue<'_>, 40);
     static_assert_size!(StatementKind<'_>, 16);
+    static_assert_size!(TerminatorKind<'_>, 96);
     // tidy-alphabetical-end
 }
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index 394515f091f..0d625ff0fae 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -474,20 +474,6 @@ rustc_queries! {
         desc { |tcx| "building THIR for `{}`", tcx.def_path_str(key) }
     }
 
-    /// Create a THIR tree for debugging.
-    query thir_tree(key: LocalDefId) -> &'tcx String {
-        no_hash
-        arena_cache
-        desc { |tcx| "constructing THIR tree for `{}`", tcx.def_path_str(key) }
-    }
-
-    /// Create a list-like THIR representation for debugging.
-    query thir_flat(key: LocalDefId) -> &'tcx String {
-        no_hash
-        arena_cache
-        desc { |tcx| "constructing flat THIR representation for `{}`", tcx.def_path_str(key) }
-    }
-
     /// Set of all the `DefId`s in this crate that have MIR associated with
     /// them. This includes all the body owners, but also things like struct
     /// constructors.
@@ -983,9 +969,6 @@ rustc_queries! {
     query diagnostic_only_typeck(key: LocalDefId) -> &'tcx ty::TypeckResults<'tcx> {
         desc { |tcx| "type-checking `{}`", tcx.def_path_str(key) }
     }
-    query lookup_method_for_diagnostic((def_id, hir_id): (LocalDefId, hir::HirId)) -> Option<DefId> {
-        desc { |tcx| "lookup_method_for_diagnostics `{}`", tcx.def_path_str(def_id) }
-    }
 
     query used_trait_imports(key: LocalDefId) -> &'tcx UnordSet<LocalDefId> {
         desc { |tcx| "finding used_trait_imports `{}`", tcx.def_path_str(key) }
diff --git a/compiler/rustc_middle/src/query/plumbing.rs b/compiler/rustc_middle/src/query/plumbing.rs
index 4ce6f7747a5..643861972c4 100644
--- a/compiler/rustc_middle/src/query/plumbing.rs
+++ b/compiler/rustc_middle/src/query/plumbing.rs
@@ -266,13 +266,7 @@ macro_rules! separate_provide_extern_default {
         ()
     };
     ([(separate_provide_extern) $($rest:tt)*][$name:ident]) => {
-        |_, key| bug!(
-            "`tcx.{}({:?})` unsupported by its crate; \
-             perhaps the `{}` query was never assigned a provider function",
-            stringify!($name),
-            key,
-            stringify!($name),
-        )
+        |_, key| $crate::query::plumbing::default_extern_query(stringify!($name), &key)
     };
     ([$other:tt $($modifiers:tt)*][$($args:tt)*]) => {
         separate_provide_extern_default!([$($modifiers)*][$($args)*])
@@ -462,15 +456,7 @@ macro_rules! define_callbacks {
         impl Default for Providers {
             fn default() -> Self {
                 Providers {
-                    $($name: |_, key| bug!(
-                        "`tcx.{}({:?})` is not supported for this key;\n\
-                        hint: Queries can be either made to the local crate, or the external crate. \
-                        This error means you tried to use it for one that's not supported.\n\
-                        If that's not the case, {} was likely never assigned to a provider function.\n",
-                        stringify!($name),
-                        key,
-                        stringify!($name),
-                    ),)*
+                    $($name: |_, key| $crate::query::plumbing::default_query(stringify!($name), &key)),*
                 }
             }
         }
@@ -661,3 +647,21 @@ use super::erase::EraseType;
 
 #[derive(Copy, Clone, Debug, HashStable)]
 pub struct CyclePlaceholder(pub ErrorGuaranteed);
+
+#[cold]
+pub(crate) fn default_query(name: &str, key: &dyn std::fmt::Debug) -> ! {
+    bug!(
+        "`tcx.{name}({key:?})` is not supported for this key;\n\
+        hint: Queries can be either made to the local crate, or the external crate. \
+        This error means you tried to use it for one that's not supported.\n\
+        If that's not the case, {name} was likely never assigned to a provider function.\n",
+    )
+}
+
+#[cold]
+pub(crate) fn default_extern_query(name: &str, key: &dyn std::fmt::Debug) -> ! {
+    bug!(
+        "`tcx.{name}({key:?})` unsupported by its crate; \
+         perhaps the `{name}` query was never assigned a provider function",
+    )
+}
diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs
index f10b204cd47..8763e94c8b0 100644
--- a/compiler/rustc_middle/src/thir.rs
+++ b/compiler/rustc_middle/src/thir.rs
@@ -12,7 +12,7 @@ use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
 use rustc_errors::{DiagArgValue, IntoDiagArg};
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
-use rustc_hir::{BindingAnnotation, ByRef, MatchSource, RangeEnd};
+use rustc_hir::{BindingAnnotation, ByRef, HirId, MatchSource, RangeEnd};
 use rustc_index::newtype_index;
 use rustc_index::IndexVec;
 use rustc_middle::middle::region;
@@ -115,13 +115,13 @@ pub struct Param<'tcx> {
     /// Whether this param is `self`, and how it is bound.
     pub self_kind: Option<hir::ImplicitSelfKind>,
     /// HirId for lints.
-    pub hir_id: Option<hir::HirId>,
+    pub hir_id: Option<HirId>,
 }
 
 #[derive(Copy, Clone, Debug, HashStable)]
 pub enum LintLevel {
     Inherited,
-    Explicit(hir::HirId),
+    Explicit(HirId),
 }
 
 #[derive(Clone, Debug, HashStable)]
@@ -167,7 +167,7 @@ pub struct ClosureExpr<'tcx> {
     pub args: UpvarArgs<'tcx>,
     pub upvars: Box<[ExprId]>,
     pub movability: Option<hir::Movability>,
-    pub fake_reads: Vec<(ExprId, FakeReadCause, hir::HirId)>,
+    pub fake_reads: Vec<(ExprId, FakeReadCause, HirId)>,
 }
 
 #[derive(Clone, Debug, HashStable)]
@@ -184,7 +184,7 @@ pub enum BlockSafety {
     /// A compiler-generated unsafe block
     BuiltinUnsafe,
     /// An `unsafe` block. The `HirId` is the ID of the block.
-    ExplicitUnsafe(hir::HirId),
+    ExplicitUnsafe(HirId),
 }
 
 #[derive(Clone, Debug, HashStable)]
@@ -233,7 +233,7 @@ pub enum StmtKind<'tcx> {
 }
 
 #[derive(Clone, Debug, Copy, PartialEq, Eq, Hash, HashStable, TyEncodable, TyDecodable)]
-pub struct LocalVarId(pub hir::HirId);
+pub struct LocalVarId(pub HirId);
 
 /// A THIR expression.
 #[derive(Clone, Debug, HashStable)]
@@ -356,7 +356,7 @@ pub enum ExprKind<'tcx> {
     /// A `match` expression.
     Match {
         scrutinee: ExprId,
-        scrutinee_hir_id: hir::HirId,
+        scrutinee_hir_id: HirId,
         arms: Box<[ArmId]>,
         match_source: MatchSource,
     },
diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs
index 790e11b8e4b..28f6184a34e 100644
--- a/compiler/rustc_middle/src/traits/mod.rs
+++ b/compiler/rustc_middle/src/traits/mod.rs
@@ -19,6 +19,7 @@ use rustc_data_structures::sync::Lrc;
 use rustc_errors::{Applicability, Diag, EmissionGuarantee};
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
+use rustc_hir::HirId;
 use rustc_span::def_id::{LocalDefId, CRATE_DEF_ID};
 use rustc_span::symbol::Symbol;
 use rustc_span::{Span, DUMMY_SP};
@@ -262,10 +263,10 @@ pub enum ObligationCauseCode<'tcx> {
     /// expression that caused the obligation, and the `usize`
     /// indicates exactly which predicate it is in the list of
     /// instantiated predicates.
-    ExprItemObligation(DefId, rustc_hir::HirId, usize),
+    ExprItemObligation(DefId, HirId, usize),
 
     /// Combines `ExprItemObligation` and `BindingObligation`.
-    ExprBindingObligation(DefId, Span, rustc_hir::HirId, usize),
+    ExprBindingObligation(DefId, Span, HirId, usize),
 
     /// A type like `&'a T` is WF only if `T: 'a`.
     ReferenceOutlivesReferent(Ty<'tcx>),
@@ -287,9 +288,9 @@ pub enum ObligationCauseCode<'tcx> {
     /// `S { ... }` must be `Sized`.
     StructInitializerSized,
     /// Type of each variable must be `Sized`.
-    VariableType(hir::HirId),
+    VariableType(HirId),
     /// Argument type must be `Sized`.
-    SizedArgumentType(Option<hir::HirId>),
+    SizedArgumentType(Option<HirId>),
     /// Return type must be `Sized`.
     SizedReturnType,
     /// Return type of a call expression must be `Sized`.
@@ -335,9 +336,9 @@ pub enum ObligationCauseCode<'tcx> {
 
     FunctionArgumentObligation {
         /// The node of the relevant argument in the function call.
-        arg_hir_id: hir::HirId,
+        arg_hir_id: HirId,
         /// The node of the function call.
-        call_hir_id: hir::HirId,
+        call_hir_id: HirId,
         /// The obligation introduced by this argument.
         parent_code: InternedObligationCauseCode<'tcx>,
     },
@@ -402,18 +403,18 @@ pub enum ObligationCauseCode<'tcx> {
     ReturnNoExpression,
 
     /// `return` with an expression
-    ReturnValue(hir::HirId),
+    ReturnValue(HirId),
 
     /// Opaque return type of this function
     OpaqueReturnType(Option<(Ty<'tcx>, Span)>),
 
     /// Block implicit return
-    BlockTailExpression(hir::HirId, hir::MatchSource),
+    BlockTailExpression(HirId, hir::MatchSource),
 
     /// #[feature(trivial_bounds)] is not enabled
     TrivialBound,
 
-    AwaitableExpr(hir::HirId),
+    AwaitableExpr(HirId),
 
     ForLoopIterator,
 
@@ -431,8 +432,8 @@ pub enum ObligationCauseCode<'tcx> {
     MatchImpl(ObligationCause<'tcx>, DefId),
 
     BinOp {
-        lhs_hir_id: hir::HirId,
-        rhs_hir_id: Option<hir::HirId>,
+        lhs_hir_id: HirId,
+        rhs_hir_id: Option<HirId>,
         rhs_span: Option<Span>,
         rhs_is_lit: bool,
         output_ty: Option<Ty<'tcx>>,
@@ -562,10 +563,10 @@ pub enum StatementAsExpression {
 #[derive(Clone, Debug, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)]
 #[derive(TypeVisitable, TypeFoldable)]
 pub struct MatchExpressionArmCause<'tcx> {
-    pub arm_block_id: Option<hir::HirId>,
+    pub arm_block_id: Option<HirId>,
     pub arm_ty: Ty<'tcx>,
     pub arm_span: Span,
-    pub prior_arm_block_id: Option<hir::HirId>,
+    pub prior_arm_block_id: Option<HirId>,
     pub prior_arm_ty: Ty<'tcx>,
     pub prior_arm_span: Span,
     pub scrut_span: Span,
@@ -578,8 +579,8 @@ pub struct MatchExpressionArmCause<'tcx> {
 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
 #[derive(TypeFoldable, TypeVisitable, HashStable, TyEncodable, TyDecodable)]
 pub struct IfExpressionCause<'tcx> {
-    pub then_id: hir::HirId,
-    pub else_id: hir::HirId,
+    pub then_id: HirId,
+    pub else_id: HirId,
     pub then_ty: Ty<'tcx>,
     pub else_ty: Ty<'tcx>,
     pub outer_span: Option<Span>,
diff --git a/compiler/rustc_middle/src/ty/closure.rs b/compiler/rustc_middle/src/ty/closure.rs
index 211d403998f..11167515b7c 100644
--- a/compiler/rustc_middle/src/ty/closure.rs
+++ b/compiler/rustc_middle/src/ty/closure.rs
@@ -10,6 +10,7 @@ use rustc_data_structures::captures::Captures;
 use rustc_data_structures::fx::FxIndexMap;
 use rustc_hir as hir;
 use rustc_hir::def_id::LocalDefId;
+use rustc_hir::HirId;
 use rustc_span::def_id::LocalDefIdMap;
 use rustc_span::symbol::Ident;
 use rustc_span::{Span, Symbol};
@@ -25,7 +26,7 @@ pub const CAPTURE_STRUCT_LOCAL: mir::Local = mir::Local::from_u32(1);
 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)]
 #[derive(TypeFoldable, TypeVisitable)]
 pub struct UpvarPath {
-    pub hir_id: hir::HirId,
+    pub hir_id: HirId,
 }
 
 /// Upvars do not get their own `NodeId`. Instead, we use the pair of
@@ -39,7 +40,7 @@ pub struct UpvarId {
 }
 
 impl UpvarId {
-    pub fn new(var_hir_id: hir::HirId, closure_def_id: LocalDefId) -> UpvarId {
+    pub fn new(var_hir_id: HirId, closure_def_id: LocalDefId) -> UpvarId {
         UpvarId { var_path: UpvarPath { hir_id: var_hir_id }, closure_expr_id: closure_def_id }
     }
 }
@@ -68,7 +69,7 @@ pub type MinCaptureInformationMap<'tcx> = LocalDefIdMap<RootVariableMinCaptureLi
 ///
 /// This provides a convenient and quick way of checking if a variable being used within
 /// a closure is a capture of a local variable.
-pub type RootVariableMinCaptureList<'tcx> = FxIndexMap<hir::HirId, MinCaptureList<'tcx>>;
+pub type RootVariableMinCaptureList<'tcx> = FxIndexMap<HirId, MinCaptureList<'tcx>>;
 
 /// Part of `MinCaptureInformationMap`; List of `CapturePlace`s.
 pub type MinCaptureList<'tcx> = Vec<CapturedPlace<'tcx>>;
@@ -135,7 +136,7 @@ impl<'tcx> CapturedPlace<'tcx> {
 
     /// Returns the hir-id of the root variable for the captured place.
     /// e.g., if `a.b.c` was captured, would return the hir-id for `a`.
-    pub fn get_root_variable(&self) -> hir::HirId {
+    pub fn get_root_variable(&self) -> HirId {
         match self.place.base {
             HirPlaceBase::Upvar(upvar_id) => upvar_id.var_path.hir_id,
             base => bug!("Expected upvar, found={:?}", base),
@@ -286,12 +287,12 @@ pub struct CaptureInfo {
     ///
     /// In this example, if `capture_disjoint_fields` is **not** set, then x will be captured,
     /// but we won't see it being used during capture analysis, since it's essentially a discard.
-    pub capture_kind_expr_id: Option<hir::HirId>,
+    pub capture_kind_expr_id: Option<HirId>,
     /// Expr Id pointing to use that resulted the corresponding place being captured
     ///
     /// See `capture_kind_expr_id` for example.
     ///
-    pub path_expr_id: Option<hir::HirId>,
+    pub path_expr_id: Option<HirId>,
 
     /// Capture mode that was selected
     pub capture_kind: UpvarCapture,
diff --git a/compiler/rustc_middle/src/ty/typeck_results.rs b/compiler/rustc_middle/src/ty/typeck_results.rs
index 995feeaa148..818fb78793e 100644
--- a/compiler/rustc_middle/src/ty/typeck_results.rs
+++ b/compiler/rustc_middle/src/ty/typeck_results.rs
@@ -192,7 +192,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: LocalDefIdMap<Vec<(HirPlace<'tcx>, FakeReadCause, hir::HirId)>>,
+    pub closure_fake_reads: LocalDefIdMap<Vec<(HirPlace<'tcx>, FakeReadCause, HirId)>>,
 
     /// Tracks the rvalue scoping rules which defines finer scoping for rvalue expressions
     /// by applying extended parameter rules.
@@ -251,7 +251,7 @@ impl<'tcx> TypeckResults<'tcx> {
     }
 
     /// Returns the final resolution of a `QPath` in an `Expr` or `Pat` node.
-    pub fn qpath_res(&self, qpath: &hir::QPath<'_>, id: hir::HirId) -> Res {
+    pub fn qpath_res(&self, qpath: &hir::QPath<'_>, id: HirId) -> Res {
         match *qpath {
             hir::QPath::Resolved(_, path) => path.res,
             hir::QPath::TypeRelative(..) | hir::QPath::LangItem(..) => self
@@ -289,11 +289,11 @@ impl<'tcx> TypeckResults<'tcx> {
         LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.field_indices }
     }
 
-    pub fn field_index(&self, id: hir::HirId) -> FieldIdx {
+    pub fn field_index(&self, id: HirId) -> FieldIdx {
         self.field_indices().get(id).cloned().expect("no index for a field")
     }
 
-    pub fn opt_field_index(&self, id: hir::HirId) -> Option<FieldIdx> {
+    pub fn opt_field_index(&self, id: HirId) -> Option<FieldIdx> {
         self.field_indices().get(id).cloned()
     }
 
@@ -305,7 +305,7 @@ impl<'tcx> TypeckResults<'tcx> {
         LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.nested_fields }
     }
 
-    pub fn nested_field_tys_and_indices(&self, id: hir::HirId) -> &[(Ty<'tcx>, FieldIdx)] {
+    pub fn nested_field_tys_and_indices(&self, id: HirId) -> &[(Ty<'tcx>, FieldIdx)] {
         self.nested_fields().get(id).map_or(&[], Vec::as_slice)
     }
 
@@ -327,13 +327,13 @@ impl<'tcx> TypeckResults<'tcx> {
         LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.node_types }
     }
 
-    pub fn node_type(&self, id: hir::HirId) -> Ty<'tcx> {
+    pub fn node_type(&self, id: HirId) -> Ty<'tcx> {
         self.node_type_opt(id).unwrap_or_else(|| {
             bug!("node_type: no type for node {}", tls::with(|tcx| tcx.hir().node_to_string(id)))
         })
     }
 
-    pub fn node_type_opt(&self, id: hir::HirId) -> Option<Ty<'tcx>> {
+    pub fn node_type_opt(&self, id: HirId) -> Option<Ty<'tcx>> {
         validate_hir_id_for_typeck_results(self.hir_owner, id);
         self.node_types.get(&id.local_id).cloned()
     }
@@ -342,12 +342,12 @@ impl<'tcx> TypeckResults<'tcx> {
         LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.node_args }
     }
 
-    pub fn node_args(&self, id: hir::HirId) -> GenericArgsRef<'tcx> {
+    pub fn node_args(&self, id: HirId) -> GenericArgsRef<'tcx> {
         validate_hir_id_for_typeck_results(self.hir_owner, id);
         self.node_args.get(&id.local_id).cloned().unwrap_or_else(|| GenericArgs::empty())
     }
 
-    pub fn node_args_opt(&self, id: hir::HirId) -> Option<GenericArgsRef<'tcx>> {
+    pub fn node_args_opt(&self, id: HirId) -> Option<GenericArgsRef<'tcx>> {
         validate_hir_id_for_typeck_results(self.hir_owner, id);
         self.node_args.get(&id.local_id).cloned()
     }
@@ -512,7 +512,7 @@ impl<'tcx> TypeckResults<'tcx> {
         LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.fru_field_types }
     }
 
-    pub fn is_coercion_cast(&self, hir_id: hir::HirId) -> bool {
+    pub fn is_coercion_cast(&self, hir_id: HirId) -> bool {
         validate_hir_id_for_typeck_results(self.hir_owner, hir_id);
         self.coercion_casts.contains(&hir_id.local_id)
     }
@@ -546,7 +546,7 @@ impl<'tcx> TypeckResults<'tcx> {
 /// would result in lookup errors, or worse, in silently wrong data being
 /// stored/returned.
 #[inline]
-fn validate_hir_id_for_typeck_results(hir_owner: OwnerId, hir_id: hir::HirId) {
+fn validate_hir_id_for_typeck_results(hir_owner: OwnerId, hir_id: HirId) {
     if hir_id.owner != hir_owner {
         invalid_hir_id_for_typeck_results(hir_owner, hir_id);
     }
@@ -554,7 +554,7 @@ fn validate_hir_id_for_typeck_results(hir_owner: OwnerId, hir_id: hir::HirId) {
 
 #[cold]
 #[inline(never)]
-fn invalid_hir_id_for_typeck_results(hir_owner: OwnerId, hir_id: hir::HirId) {
+fn invalid_hir_id_for_typeck_results(hir_owner: OwnerId, hir_id: HirId) {
     ty::tls::with(|tcx| {
         bug!(
             "node {} cannot be placed in TypeckResults with hir_owner {:?}",
@@ -570,12 +570,12 @@ pub struct LocalTableInContext<'a, V> {
 }
 
 impl<'a, V> LocalTableInContext<'a, V> {
-    pub fn contains_key(&self, id: hir::HirId) -> bool {
+    pub fn contains_key(&self, id: HirId) -> bool {
         validate_hir_id_for_typeck_results(self.hir_owner, id);
         self.data.contains_key(&id.local_id)
     }
 
-    pub fn get(&self, id: hir::HirId) -> Option<&'a V> {
+    pub fn get(&self, id: HirId) -> Option<&'a V> {
         validate_hir_id_for_typeck_results(self.hir_owner, id);
         self.data.get(&id.local_id)
     }
@@ -592,10 +592,10 @@ impl<'a, V> LocalTableInContext<'a, V> {
     }
 }
 
-impl<'a, V> ::std::ops::Index<hir::HirId> for LocalTableInContext<'a, V> {
+impl<'a, V> ::std::ops::Index<HirId> for LocalTableInContext<'a, V> {
     type Output = V;
 
-    fn index(&self, key: hir::HirId) -> &V {
+    fn index(&self, key: HirId) -> &V {
         self.get(key).expect("LocalTableInContext: key not found")
     }
 }
@@ -606,35 +606,32 @@ pub struct LocalTableInContextMut<'a, V> {
 }
 
 impl<'a, V> LocalTableInContextMut<'a, V> {
-    pub fn get_mut(&mut self, id: hir::HirId) -> Option<&mut V> {
+    pub fn get_mut(&mut self, id: HirId) -> Option<&mut V> {
         validate_hir_id_for_typeck_results(self.hir_owner, id);
         self.data.get_mut(&id.local_id)
     }
 
-    pub fn get(&mut self, id: hir::HirId) -> Option<&V> {
+    pub fn get(&mut self, id: HirId) -> Option<&V> {
         validate_hir_id_for_typeck_results(self.hir_owner, id);
         self.data.get(&id.local_id)
     }
 
-    pub fn entry(&mut self, id: hir::HirId) -> Entry<'_, hir::ItemLocalId, V> {
+    pub fn entry(&mut self, id: HirId) -> Entry<'_, hir::ItemLocalId, V> {
         validate_hir_id_for_typeck_results(self.hir_owner, id);
         self.data.entry(id.local_id)
     }
 
-    pub fn insert(&mut self, id: hir::HirId, val: V) -> Option<V> {
+    pub fn insert(&mut self, id: HirId, val: V) -> Option<V> {
         validate_hir_id_for_typeck_results(self.hir_owner, id);
         self.data.insert(id.local_id, val)
     }
 
-    pub fn remove(&mut self, id: hir::HirId) -> Option<V> {
+    pub fn remove(&mut self, id: HirId) -> Option<V> {
         validate_hir_id_for_typeck_results(self.hir_owner, id);
         self.data.remove(&id.local_id)
     }
 
-    pub fn extend(
-        &mut self,
-        items: UnordItems<(hir::HirId, V), impl Iterator<Item = (hir::HirId, V)>>,
-    ) {
+    pub fn extend(&mut self, items: UnordItems<(HirId, V), impl Iterator<Item = (HirId, V)>>) {
         self.data.extend_unord(items.map(|(id, value)| {
             validate_hir_id_for_typeck_results(self.hir_owner, id);
             (id.local_id, value)
diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs
index e422fb0d020..9af665cfb6f 100644
--- a/compiler/rustc_middle/src/ty/util.rs
+++ b/compiler/rustc_middle/src/ty/util.rs
@@ -1684,10 +1684,15 @@ pub fn is_doc_notable_trait(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
         .any(|items| items.iter().any(|item| item.has_name(sym::notable_trait)))
 }
 
-/// Determines whether an item is an intrinsic (which may be via Abi or via the `rustc_intrinsic` attribute)
+/// Determines whether an item is an intrinsic (which may be via Abi or via the `rustc_intrinsic` attribute).
+///
+/// We double check the feature gate here because whether a function may be defined as an intrinsic causes
+/// the compiler to make some assumptions about its shape; if the user doesn't use a feature gate, they may
+/// cause an ICE that we otherwise may want to prevent.
 pub fn intrinsic_raw(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<ty::IntrinsicDef> {
-    if matches!(tcx.fn_sig(def_id).skip_binder().abi(), Abi::RustIntrinsic)
-        || tcx.has_attr(def_id, sym::rustc_intrinsic)
+    if (matches!(tcx.fn_sig(def_id).skip_binder().abi(), Abi::RustIntrinsic)
+        && tcx.features().intrinsics)
+        || (tcx.has_attr(def_id, sym::rustc_intrinsic) && tcx.features().rustc_attrs)
     {
         Some(ty::IntrinsicDef {
             name: tcx.item_name(def_id.into()),
diff --git a/compiler/rustc_mir_build/src/build/matches/util.rs b/compiler/rustc_mir_build/src/build/matches/util.rs
index 440be873d4e..d6376b7b0dc 100644
--- a/compiler/rustc_mir_build/src/build/matches/util.rs
+++ b/compiler/rustc_mir_build/src/build/matches/util.rs
@@ -2,7 +2,7 @@ use crate::build::expr::as_place::{PlaceBase, PlaceBuilder};
 use crate::build::matches::{Binding, Candidate, FlatPat, MatchPair, TestCase};
 use crate::build::Builder;
 use rustc_data_structures::fx::FxIndexSet;
-use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
+use rustc_infer::infer::type_variable::TypeVariableOrigin;
 use rustc_middle::mir::*;
 use rustc_middle::thir::{self, *};
 use rustc_middle::ty;
@@ -178,10 +178,9 @@ impl<'pat, 'tcx> MatchPair<'pat, 'tcx> {
                         cx.tcx,
                         ty::InlineConstArgsParts {
                             parent_args: ty::GenericArgs::identity_for_item(cx.tcx, parent_id),
-                            ty: cx.infcx.next_ty_var(TypeVariableOrigin {
-                                kind: TypeVariableOriginKind::MiscVariable,
-                                span,
-                            }),
+                            ty: cx
+                                .infcx
+                                .next_ty_var(TypeVariableOrigin { param_def_id: None, span }),
                         },
                     )
                     .args;
diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs
index 6972bc00e0b..b5d72619a38 100644
--- a/compiler/rustc_mir_build/src/build/mod.rs
+++ b/compiler/rustc_mir_build/src/build/mod.rs
@@ -9,7 +9,7 @@ use rustc_data_structures::sorted_map::SortedIndexMultiMap;
 use rustc_errors::ErrorGuaranteed;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{DefId, LocalDefId};
-use rustc_hir::{self as hir, BindingAnnotation, ByRef, Node};
+use rustc_hir::{self as hir, BindingAnnotation, ByRef, HirId, Node};
 use rustc_index::bit_set::GrowableBitSet;
 use rustc_index::{Idx, IndexSlice, IndexVec};
 use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
@@ -158,7 +158,7 @@ struct Builder<'a, 'tcx> {
     cfg: CFG<'tcx>,
 
     def_id: LocalDefId,
-    hir_id: hir::HirId,
+    hir_id: HirId,
     parent_module: DefId,
     check_overflow: bool,
     fn_span: Span,
@@ -222,7 +222,7 @@ struct Builder<'a, 'tcx> {
     coverage_branch_info: Option<coverageinfo::BranchInfoBuilder>,
 }
 
-type CaptureMap<'tcx> = SortedIndexMultiMap<usize, hir::HirId, Capture<'tcx>>;
+type CaptureMap<'tcx> = SortedIndexMultiMap<usize, HirId, Capture<'tcx>>;
 
 #[derive(Debug)]
 struct Capture<'tcx> {
@@ -721,7 +721,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         thir: &'a Thir<'tcx>,
         infcx: InferCtxt<'tcx>,
         def: LocalDefId,
-        hir_id: hir::HirId,
+        hir_id: HirId,
         span: Span,
         arg_count: usize,
         return_ty: Ty<'tcx>,
@@ -981,7 +981,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
 
     fn set_correct_source_scope_for_arg(
         &mut self,
-        arg_hir_id: hir::HirId,
+        arg_hir_id: HirId,
         original_source_scope: SourceScope,
         pattern_span: Span,
     ) {
diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs
index 8aa9a75d96a..9ee0fb79bf4 100644
--- a/compiler/rustc_mir_build/src/check_unsafety.rs
+++ b/compiler/rustc_mir_build/src/check_unsafety.rs
@@ -1,10 +1,8 @@
-use std::borrow::Cow;
-
 use crate::build::ExprCategory;
 use crate::errors::*;
 
 use rustc_errors::DiagArgValue;
-use rustc_hir::{self as hir, BindingAnnotation, ByRef, Mutability};
+use rustc_hir::{self as hir, BindingAnnotation, ByRef, HirId, Mutability};
 use rustc_middle::mir::BorrowKind;
 use rustc_middle::thir::visit::Visitor;
 use rustc_middle::thir::*;
@@ -16,6 +14,7 @@ use rustc_span::def_id::{DefId, LocalDefId};
 use rustc_span::symbol::Symbol;
 use rustc_span::{sym, Span};
 
+use std::borrow::Cow;
 use std::mem;
 use std::ops::Bound;
 
@@ -24,7 +23,7 @@ struct UnsafetyVisitor<'a, 'tcx> {
     thir: &'a Thir<'tcx>,
     /// The `HirId` of the current scope, which would be the `HirId`
     /// of the current HIR node, modulo adjustments. Used for lint levels.
-    hir_context: hir::HirId,
+    hir_context: HirId,
     /// The current "safety context". This notably tracks whether we are in an
     /// `unsafe` block, and whether it has been used.
     safety_context: SafetyContext,
@@ -123,7 +122,7 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> {
 
     fn warn_unused_unsafe(
         &mut self,
-        hir_id: hir::HirId,
+        hir_id: HirId,
         block_span: Span,
         enclosing_unsafe: Option<UnusedUnsafeEnclosing>,
     ) {
@@ -537,22 +536,17 @@ enum SafetyContext {
     Safe,
     BuiltinUnsafeBlock,
     UnsafeFn,
-    UnsafeBlock {
-        span: Span,
-        hir_id: hir::HirId,
-        used: bool,
-        nested_used_blocks: Vec<NestedUsedBlock>,
-    },
+    UnsafeBlock { span: Span, hir_id: HirId, used: bool, nested_used_blocks: Vec<NestedUsedBlock> },
 }
 
 #[derive(Clone, Copy)]
 struct NestedUsedBlock {
-    hir_id: hir::HirId,
+    hir_id: HirId,
     span: Span,
 }
 
 struct UnusedUnsafeWarning {
-    hir_id: hir::HirId,
+    hir_id: HirId,
     block_span: Span,
     enclosing_unsafe: Option<UnusedUnsafeEnclosing>,
 }
@@ -585,7 +579,7 @@ impl UnsafeOpKind {
     pub fn emit_unsafe_op_in_unsafe_fn_lint(
         &self,
         tcx: TyCtxt<'_>,
-        hir_id: hir::HirId,
+        hir_id: HirId,
         span: Span,
         suggest_unsafe_block: bool,
     ) {
@@ -726,7 +720,7 @@ impl UnsafeOpKind {
         &self,
         tcx: TyCtxt<'_>,
         span: Span,
-        hir_context: hir::HirId,
+        hir_context: HirId,
         unsafe_op_in_unsafe_fn_allowed: bool,
     ) {
         let note_non_inherited = tcx.hir().parent_iter(hir_context).find(|(id, node)| {
diff --git a/compiler/rustc_mir_build/src/lib.rs b/compiler/rustc_mir_build/src/lib.rs
index 82fb7d1ae4a..442f5fa7d17 100644
--- a/compiler/rustc_mir_build/src/lib.rs
+++ b/compiler/rustc_mir_build/src/lib.rs
@@ -34,6 +34,6 @@ pub fn provide(providers: &mut Providers) {
         build::closure_saved_names_of_captured_variables;
     providers.check_unsafety = check_unsafety::check_unsafety;
     providers.thir_body = thir::cx::thir_body;
-    providers.thir_tree = thir::print::thir_tree;
-    providers.thir_flat = thir::print::thir_flat;
+    providers.hooks.thir_tree = thir::print::thir_tree;
+    providers.hooks.thir_flat = thir::print::thir_flat;
 }
diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
index 133cf8e3349..bcb43a00547 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
@@ -69,7 +69,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
             hir::PatKind::Ref(inner, _)
                 if self.typeck_results.skipped_ref_pats().contains(pat.hir_id) =>
             {
-                self.lower_pattern_unadjusted(inner)
+                self.lower_pattern(inner)
             }
             _ => self.lower_pattern_unadjusted(pat),
         };
diff --git a/compiler/rustc_mir_build/src/thir/print.rs b/compiler/rustc_mir_build/src/thir/print.rs
index ef15082a481..49e48427b65 100644
--- a/compiler/rustc_mir_build/src/thir/print.rs
+++ b/compiler/rustc_mir_build/src/thir/print.rs
@@ -1,10 +1,11 @@
+use rustc_middle::query::TyCtxtAt;
 use rustc_middle::thir::*;
-use rustc_middle::ty::{self, TyCtxt};
+use rustc_middle::ty;
 use rustc_span::def_id::LocalDefId;
 use std::fmt::{self, Write};
 
-pub(crate) fn thir_tree(tcx: TyCtxt<'_>, owner_def: LocalDefId) -> String {
-    match super::cx::thir_body(tcx, owner_def) {
+pub(crate) fn thir_tree(tcx: TyCtxtAt<'_>, owner_def: LocalDefId) -> String {
+    match super::cx::thir_body(*tcx, owner_def) {
         Ok((thir, _)) => {
             let thir = thir.steal();
             let mut printer = ThirPrinter::new(&thir);
@@ -15,8 +16,8 @@ pub(crate) fn thir_tree(tcx: TyCtxt<'_>, owner_def: LocalDefId) -> String {
     }
 }
 
-pub(crate) fn thir_flat(tcx: TyCtxt<'_>, owner_def: LocalDefId) -> String {
-    match super::cx::thir_body(tcx, owner_def) {
+pub(crate) fn thir_flat(tcx: TyCtxtAt<'_>, owner_def: LocalDefId) -> String {
+    match super::cx::thir_body(*tcx, owner_def) {
         Ok((thir, _)) => format!("{:#?}", thir.steal()),
         Err(_) => "error".into(),
     }
diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs
index d4f736d2a50..8e8d78226c3 100644
--- a/compiler/rustc_mir_transform/src/gvn.rs
+++ b/compiler/rustc_mir_transform/src/gvn.rs
@@ -1202,7 +1202,7 @@ impl<'tcx> VnState<'_, 'tcx> {
             // not give the same value as the former mention.
             && value.is_deterministic()
         {
-            return Some(ConstOperand { span: rustc_span::DUMMY_SP, user_ty: None, const_: value });
+            return Some(ConstOperand { span: DUMMY_SP, user_ty: None, const_: value });
         }
 
         let op = self.evaluated[index].as_ref()?;
@@ -1219,7 +1219,7 @@ impl<'tcx> VnState<'_, 'tcx> {
         assert!(!value.may_have_provenance(self.tcx, op.layout.size));
 
         let const_ = Const::Val(value, op.layout.ty);
-        Some(ConstOperand { span: rustc_span::DUMMY_SP, user_ty: None, const_ })
+        Some(ConstOperand { span: DUMMY_SP, user_ty: None, const_ })
     }
 
     /// If there is a local which is assigned `index`, and its assignment strictly dominates `loc`,
diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs
index 7038b8bbe47..64f766543a7 100644
--- a/compiler/rustc_parse/src/parser/diagnostics.rs
+++ b/compiler/rustc_parse/src/parser/diagnostics.rs
@@ -279,7 +279,7 @@ impl<'a> Parser<'a> {
             TokenKind::Colon,
             TokenKind::Comma,
             TokenKind::Semi,
-            TokenKind::ModSep,
+            TokenKind::PathSep,
             TokenKind::OpenDelim(Delimiter::Brace),
             TokenKind::OpenDelim(Delimiter::Parenthesis),
             TokenKind::CloseDelim(Delimiter::Brace),
@@ -1169,7 +1169,7 @@ impl<'a> Parser<'a> {
             return;
         }
 
-        if token::ModSep == self.token.kind && segment.args.is_none() {
+        if token::PathSep == self.token.kind && segment.args.is_none() {
             let snapshot = self.create_snapshot_for_diagnostic();
             self.bump();
             let lo = self.token.span;
@@ -1420,7 +1420,7 @@ impl<'a> Parser<'a> {
                             [(token::Lt, 1), (token::Gt, -1), (token::BinOp(token::Shr), -2)];
                         self.consume_tts(1, &modifiers);
 
-                        if !&[token::OpenDelim(Delimiter::Parenthesis), token::ModSep]
+                        if !&[token::OpenDelim(Delimiter::Parenthesis), token::PathSep]
                             .contains(&self.token.kind)
                         {
                             // We don't have `foo< bar >(` or `foo< bar >::`, so we rewind the
@@ -1428,7 +1428,7 @@ impl<'a> Parser<'a> {
                             self.restore_snapshot(snapshot);
                         }
                     }
-                    return if token::ModSep == self.token.kind {
+                    return if token::PathSep == self.token.kind {
                         // We have some certainty that this was a bad turbofish at this point.
                         // `foo< bar >::`
                         if let ExprKind::Binary(o, ..) = inner_op.kind
@@ -1784,7 +1784,7 @@ impl<'a> Parser<'a> {
         }
 
         // Do not add `::` to expected tokens.
-        if self.token == token::ModSep {
+        if self.token == token::PathSep {
             if let Some(ty) = base.to_ty() {
                 return self.maybe_recover_from_bad_qpath_stage_2(ty.span, ty);
             }
@@ -1799,7 +1799,7 @@ impl<'a> Parser<'a> {
         ty_span: Span,
         ty: P<Ty>,
     ) -> PResult<'a, P<T>> {
-        self.expect(&token::ModSep)?;
+        self.expect(&token::PathSep)?;
 
         let mut path = ast::Path { segments: ThinVec::new(), span: DUMMY_SP, tokens: None };
         self.parse_path_segments(&mut path.segments, T::PATH_STYLE, None)?;
diff --git a/compiler/rustc_parse/src/parser/generics.rs b/compiler/rustc_parse/src/parser/generics.rs
index fde16ac957d..93a15c938ec 100644
--- a/compiler/rustc_parse/src/parser/generics.rs
+++ b/compiler/rustc_parse/src/parser/generics.rs
@@ -62,7 +62,7 @@ impl<'a> Parser<'a> {
                 let snapshot = self.create_snapshot_for_diagnostic();
                 match self.parse_ty() {
                     Ok(p) => {
-                        if let TyKind::ImplTrait(_, bounds) = &p.kind {
+                        if let TyKind::ImplTrait(_, bounds, None) = &p.kind {
                             let span = impl_span.to(self.token.span.shrink_to_lo());
                             let mut err = self.dcx().struct_span_err(
                                 span,
diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs
index d54eb8dc4c9..8ae809f566b 100644
--- a/compiler/rustc_parse/src/parser/item.rs
+++ b/compiler/rustc_parse/src/parser/item.rs
@@ -358,12 +358,12 @@ impl<'a> Parser<'a> {
     fn is_reuse_path_item(&mut self) -> bool {
         // no: `reuse ::path` for compatibility reasons with macro invocations
         self.token.is_keyword(kw::Reuse)
-            && self.look_ahead(1, |t| t.is_path_start() && t.kind != token::ModSep)
+            && self.look_ahead(1, |t| t.is_path_start() && t.kind != token::PathSep)
     }
 
     /// Are we sure this could not possibly be a macro invocation?
     fn isnt_macro_invocation(&mut self) -> bool {
-        self.check_ident() && self.look_ahead(1, |t| *t != token::Not && *t != token::ModSep)
+        self.check_ident() && self.look_ahead(1, |t| *t != token::Not && *t != token::PathSep)
     }
 
     /// Recover on encountering a struct or method definition where the user
@@ -625,7 +625,7 @@ impl<'a> Parser<'a> {
                     // This notably includes paths passed through `ty` macro fragments (#46438).
                     TyKind::Path(None, path) => path,
                     other => {
-                        if let TyKind::ImplTrait(_, bounds) = other
+                        if let TyKind::ImplTrait(_, bounds, None) = other
                             && let [bound] = bounds.as_slice()
                         {
                             // Suggest removing extra `impl` keyword:
@@ -1020,7 +1020,7 @@ impl<'a> Parser<'a> {
         {
             // `use *;` or `use ::*;` or `use {...};` or `use ::{...};`
             let mod_sep_ctxt = self.token.span.ctxt();
-            if self.eat(&token::ModSep) {
+            if self.eat(&token::PathSep) {
                 prefix
                     .segments
                     .push(PathSegment::path_root(lo.shrink_to_lo().with_ctxt(mod_sep_ctxt)));
@@ -1031,7 +1031,7 @@ impl<'a> Parser<'a> {
             // `use path::*;` or `use path::{...};` or `use path;` or `use path as bar;`
             prefix = self.parse_path(PathStyle::Mod)?;
 
-            if self.eat(&token::ModSep) {
+            if self.eat(&token::PathSep) {
                 self.parse_use_tree_glob_or_nested()?
             } else {
                 // Recover from using a colon as path separator.
@@ -1063,7 +1063,7 @@ impl<'a> Parser<'a> {
     /// Parses a `UseTreeKind::Nested(list)`.
     ///
     /// ```text
-    /// USE_TREE_LIST = Ø | (USE_TREE `,`)* USE_TREE [`,`]
+    /// USE_TREE_LIST = ∅ | (USE_TREE `,`)* USE_TREE [`,`]
     /// ```
     fn parse_use_tree_list(&mut self) -> PResult<'a, ThinVec<(UseTree, ast::NodeId)>> {
         self.parse_delim_comma_seq(Delimiter::Brace, |p| {
@@ -1968,11 +1968,8 @@ impl<'a> Parser<'a> {
         } else if matches!(is_raw, IdentIsRaw::No) && ident.is_reserved() {
             let snapshot = self.create_snapshot_for_diagnostic();
             let err = if self.check_fn_front_matter(false, Case::Sensitive) {
-                let inherited_vis = Visibility {
-                    span: rustc_span::DUMMY_SP,
-                    kind: VisibilityKind::Inherited,
-                    tokens: None,
-                };
+                let inherited_vis =
+                    Visibility { span: DUMMY_SP, kind: VisibilityKind::Inherited, tokens: None };
                 // We use `parse_fn` to get a span for the function
                 let fn_parse_mode = FnParseMode { req_name: |_| true, req_body: true };
                 match self.parse_fn(
@@ -2752,7 +2749,7 @@ impl<'a> Parser<'a> {
         // Is `self` `n` tokens ahead?
         let is_isolated_self = |this: &Self, n| {
             this.is_keyword_ahead(n, &[kw::SelfLower])
-                && this.look_ahead(n + 1, |t| t != &token::ModSep)
+                && this.look_ahead(n + 1, |t| t != &token::PathSep)
         };
         // Is `mut self` `n` tokens ahead?
         let is_isolated_mut_self =
diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs
index 09bc00403f3..a4a9ba9d229 100644
--- a/compiler/rustc_parse/src/parser/mod.rs
+++ b/compiler/rustc_parse/src/parser/mod.rs
@@ -109,7 +109,7 @@ macro_rules! maybe_recover_from_interpolated_ty_qpath {
     ($self: expr, $allow_qpath_recovery: expr) => {
         if $allow_qpath_recovery
             && $self.may_recover()
-            && $self.look_ahead(1, |t| t == &token::ModSep)
+            && $self.look_ahead(1, |t| t == &token::PathSep)
             && let token::Interpolated(nt) = &$self.token.kind
             && let token::NtTy(ty) = &nt.0
         {
@@ -1532,7 +1532,7 @@ impl<'a> Parser<'a> {
 
     /// `::{` or `::*`
     fn is_import_coupler(&mut self) -> bool {
-        self.check(&token::ModSep)
+        self.check(&token::PathSep)
             && self.look_ahead(1, |t| {
                 *t == token::OpenDelim(Delimiter::Brace) || *t == token::BinOp(token::Star)
             })
diff --git a/compiler/rustc_parse/src/parser/nonterminal.rs b/compiler/rustc_parse/src/parser/nonterminal.rs
index 36a00df7b44..73b17353ac9 100644
--- a/compiler/rustc_parse/src/parser/nonterminal.rs
+++ b/compiler/rustc_parse/src/parser/nonterminal.rs
@@ -62,7 +62,7 @@ impl<'a> Parser<'a> {
                 _ => false,
             },
             NonterminalKind::Path | NonterminalKind::Meta => match &token.kind {
-                token::ModSep | token::Ident(..) => true,
+                token::PathSep | token::Ident(..) => true,
                 token::Interpolated(nt) => may_be_ident(&nt.0),
                 _ => false,
             },
@@ -76,7 +76,7 @@ impl<'a> Parser<'a> {
                 token::Literal(_) |                         // literal
                 token::DotDot |                             // range pattern (future compat)
                 token::DotDotDot |                          // range pattern (future compat)
-                token::ModSep |                             // path
+                token::PathSep |                             // path
                 token::Lt |                                 // path (UFCS constant)
                 token::BinOp(token::Shl) => true,           // path (double UFCS)
                 // leading vert `|` or-pattern
diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs
index 59e0cd92c4c..dd1ecf9b7c1 100644
--- a/compiler/rustc_parse/src/parser/pat.rs
+++ b/compiler/rustc_parse/src/parser/pat.rs
@@ -1016,7 +1016,7 @@ impl<'a> Parser<'a> {
         && self.look_ahead(1, |t| !matches!(t.kind, token::OpenDelim(Delimiter::Parenthesis) // A tuple struct pattern.
             | token::OpenDelim(Delimiter::Brace) // A struct pattern.
             | token::DotDotDot | token::DotDotEq | token::DotDot // A range pattern.
-            | token::ModSep // A tuple / struct variant pattern.
+            | token::PathSep // A tuple / struct variant pattern.
             | token::Not)) // A macro expanding to a pattern.
     }
 
diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs
index 608cdd945ff..0f410772dd9 100644
--- a/compiler/rustc_parse/src/parser/path.rs
+++ b/compiler/rustc_parse/src/parser/path.rs
@@ -96,7 +96,7 @@ impl<'a> Parser<'a> {
         }
 
         if !self.recover_colon_before_qpath_proj() {
-            self.expect(&token::ModSep)?;
+            self.expect(&token::PathSep)?;
         }
 
         let qself = P(QSelf { ty, path_span, position: path.segments.len() });
@@ -200,7 +200,7 @@ impl<'a> Parser<'a> {
         let lo = self.token.span;
         let mut segments = ThinVec::new();
         let mod_sep_ctxt = self.token.span.ctxt();
-        if self.eat(&token::ModSep) {
+        if self.eat(&token::PathSep) {
             segments.push(PathSegment::path_root(lo.shrink_to_lo().with_ctxt(mod_sep_ctxt)));
         }
         self.parse_path_segments(&mut segments, style, ty_generics)?;
@@ -232,11 +232,11 @@ impl<'a> Parser<'a> {
                 // `PathStyle::Expr` is only provided at the root invocation and never in
                 // `parse_path_segment` to recurse and therefore can be checked to maintain
                 // this invariant.
-                self.check_trailing_angle_brackets(&segment, &[&token::ModSep]);
+                self.check_trailing_angle_brackets(&segment, &[&token::PathSep]);
             }
             segments.push(segment);
 
-            if self.is_import_coupler() || !self.eat(&token::ModSep) {
+            if self.is_import_coupler() || !self.eat(&token::PathSep) {
                 if style == PathStyle::Expr
                     && self.may_recover()
                     && self.token == token::Colon
@@ -291,7 +291,7 @@ impl<'a> Parser<'a> {
         Ok(
             if style == PathStyle::Type && check_args_start(self)
                 || style != PathStyle::Mod
-                    && self.check(&token::ModSep)
+                    && self.check(&token::PathSep)
                     && self.look_ahead(1, |t| is_args_start(t))
             {
                 // We use `style == PathStyle::Expr` to check if this is in a recursion or not. If
@@ -303,7 +303,7 @@ impl<'a> Parser<'a> {
                 }
 
                 // Generic arguments are found - `<`, `(`, `::<` or `::(`.
-                self.eat(&token::ModSep);
+                self.eat(&token::PathSep);
                 let lo = self.token.span;
                 let args = if self.eat_lt() {
                     // `<'a, T, A = U>`
@@ -379,7 +379,7 @@ impl<'a> Parser<'a> {
                     let token_before_parsing = self.token.clone();
                     let mut snapshot = None;
                     if self.may_recover()
-                        && prev_token_before_parsing.kind == token::ModSep
+                        && prev_token_before_parsing.kind == token::PathSep
                         && (style == PathStyle::Expr && self.token.can_begin_expr()
                             || style == PathStyle::Pat && self.token.can_begin_pattern())
                     {
@@ -388,7 +388,7 @@ impl<'a> Parser<'a> {
 
                     let (inputs, _) = match self.parse_paren_comma_seq(|p| p.parse_ty()) {
                         Ok(output) => output,
-                        Err(mut error) if prev_token_before_parsing.kind == token::ModSep => {
+                        Err(mut error) if prev_token_before_parsing.kind == token::PathSep => {
                             error.span_label(
                                 prev_token_before_parsing.span.to(token_before_parsing.span),
                                 "while parsing this parenthesized list of type arguments starting here",
@@ -470,7 +470,7 @@ impl<'a> Parser<'a> {
             }
         }
 
-        if let token::ModSep | token::RArrow = self.token.kind {
+        if let token::PathSep | token::RArrow = self.token.kind {
             return;
         }
 
diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs
index 1cea32cb90f..7096b201f84 100644
--- a/compiler/rustc_parse/src/parser/ty.rs
+++ b/compiler/rustc_parse/src/parser/ty.rs
@@ -1,4 +1,4 @@
-use super::{Parser, PathStyle, TokenType, Trailing};
+use super::{Parser, PathStyle, SeqSep, TokenType, Trailing};
 
 use crate::errors::{
     self, DynAfterMut, ExpectedFnPathFoundFnKeyword, ExpectedMutOrConstInRawPointerType,
@@ -14,7 +14,7 @@ use rustc_ast::util::case::Case;
 use rustc_ast::{
     self as ast, BareFnTy, BoundAsyncness, BoundConstness, BoundPolarity, FnRetTy, GenericBound,
     GenericBounds, GenericParam, Generics, Lifetime, MacCall, MutTy, Mutability, PolyTraitRef,
-    TraitBoundModifiers, TraitObjectSyntax, Ty, TyKind, DUMMY_NODE_ID,
+    PreciseCapturingArg, TraitBoundModifiers, TraitObjectSyntax, Ty, TyKind, DUMMY_NODE_ID,
 };
 use rustc_errors::{Applicability, PResult};
 use rustc_span::symbol::{kw, sym, Ident};
@@ -82,7 +82,7 @@ enum AllowCVariadic {
 /// Types can also be of the form `IDENT(u8, u8) -> u8`, however this assumes
 /// that `IDENT` is not the ident of a fn trait.
 fn can_continue_type_after_non_fn_ident(t: &Token) -> bool {
-    t == &token::ModSep || t == &token::Lt || t == &token::BinOp(token::Shl)
+    t == &token::PathSep || t == &token::Lt || t == &token::BinOp(token::Shl)
 }
 
 fn can_begin_dyn_bound_in_edition_2015(t: &Token) -> bool {
@@ -316,7 +316,7 @@ impl<'a> Parser<'a> {
                             TyKind::TraitObject(bounds, TraitObjectSyntax::Dyn)
                         }
                         (TyKind::TraitObject(bounds, _), kw::Impl) => {
-                            TyKind::ImplTrait(ast::DUMMY_NODE_ID, bounds)
+                            TyKind::ImplTrait(ast::DUMMY_NODE_ID, bounds, None)
                         }
                         _ => return Err(err),
                     };
@@ -655,7 +655,6 @@ impl<'a> Parser<'a> {
 
     /// Parses an `impl B0 + ... + Bn` type.
     fn parse_impl_ty(&mut self, impl_dyn_multi: &mut bool) -> PResult<'a, TyKind> {
-        // Always parse bounds greedily for better error recovery.
         if self.token.is_lifetime() {
             self.look_ahead(1, |t| {
                 if let token::Ident(sym, _) = t.kind {
@@ -669,9 +668,53 @@ impl<'a> Parser<'a> {
                 }
             })
         }
+
+        // parse precise captures, if any. This is `use<'lt, 'lt, P, P>`; a list of
+        // lifetimes and ident params (including SelfUpper). These are validated later
+        // for order, duplication, and whether they actually reference params.
+        let precise_capturing = if self.eat_keyword(kw::Use) {
+            let use_span = self.prev_token.span;
+            self.psess.gated_spans.gate(sym::precise_capturing, use_span);
+            let args = self.parse_precise_capturing_args()?;
+            Some(P((args, use_span)))
+        } else {
+            None
+        };
+
+        // Always parse bounds greedily for better error recovery.
         let bounds = self.parse_generic_bounds()?;
+
         *impl_dyn_multi = bounds.len() > 1 || self.prev_token.kind == TokenKind::BinOp(token::Plus);
-        Ok(TyKind::ImplTrait(ast::DUMMY_NODE_ID, bounds))
+
+        Ok(TyKind::ImplTrait(ast::DUMMY_NODE_ID, bounds, precise_capturing))
+    }
+
+    fn parse_precise_capturing_args(&mut self) -> PResult<'a, ThinVec<PreciseCapturingArg>> {
+        Ok(self
+            .parse_unspanned_seq(
+                &TokenKind::Lt,
+                &TokenKind::Gt,
+                SeqSep::trailing_allowed(token::Comma),
+                |self_| {
+                    if self_.check_keyword(kw::SelfUpper) {
+                        self_.bump();
+                        Ok(PreciseCapturingArg::Arg(
+                            ast::Path::from_ident(self_.prev_token.ident().unwrap().0),
+                            DUMMY_NODE_ID,
+                        ))
+                    } else if self_.check_ident() {
+                        Ok(PreciseCapturingArg::Arg(
+                            ast::Path::from_ident(self_.parse_ident()?),
+                            DUMMY_NODE_ID,
+                        ))
+                    } else if self_.check_lifetime() {
+                        Ok(PreciseCapturingArg::Lifetime(self_.expect_lifetime()))
+                    } else {
+                        self_.unexpected_any()
+                    }
+                },
+            )?
+            .0)
     }
 
     /// Is a `dyn B0 + ... + Bn` type allowed here?
@@ -957,7 +1000,7 @@ impl<'a> Parser<'a> {
                             Applicability::MaybeIncorrect,
                         )
                     }
-                    TyKind::ImplTrait(_, bounds)
+                    TyKind::ImplTrait(_, bounds, None)
                         if let [GenericBound::Trait(tr, ..), ..] = bounds.as_slice() =>
                     {
                         (
diff --git a/compiler/rustc_passes/src/hir_stats.rs b/compiler/rustc_passes/src/hir_stats.rs
index 72c6a714e4d..49408c5618b 100644
--- a/compiler/rustc_passes/src/hir_stats.rs
+++ b/compiler/rustc_passes/src/hir_stats.rs
@@ -389,7 +389,7 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> {
         hir_visit::walk_fn(self, fk, fd, b, id)
     }
 
-    fn visit_use(&mut self, p: &'v hir::UsePath<'v>, hir_id: hir::HirId) {
+    fn visit_use(&mut self, p: &'v hir::UsePath<'v>, hir_id: HirId) {
         // This is `visit_use`, but the type is `Path` so record it that way.
         self.record("Path", Id::None, p);
         hir_visit::walk_use(self, p, hir_id)
@@ -462,7 +462,7 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> {
         hir_visit::walk_lifetime(self, lifetime)
     }
 
-    fn visit_path(&mut self, path: &hir::Path<'v>, _id: hir::HirId) {
+    fn visit_path(&mut self, path: &hir::Path<'v>, _id: HirId) {
         self.record("Path", Id::None, path);
         hir_visit::walk_path(self, path)
     }
diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs
index 125084f4750..c7729302783 100644
--- a/compiler/rustc_passes/src/liveness.rs
+++ b/compiler/rustc_passes/src/liveness.rs
@@ -602,7 +602,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
         String::from_utf8(wr).unwrap()
     }
 
-    fn log_liveness(&self, entry_ln: LiveNode, hir_id: hir::HirId) {
+    fn log_liveness(&self, entry_ln: LiveNode, hir_id: HirId) {
         // hack to skip the loop unless debug! is enabled:
         debug!(
             "^^ liveness computation results for body {} (entry={:?})",
diff --git a/compiler/rustc_passes/src/naked_functions.rs b/compiler/rustc_passes/src/naked_functions.rs
index bd34b0597e2..a1f37ee3b83 100644
--- a/compiler/rustc_passes/src/naked_functions.rs
+++ b/compiler/rustc_passes/src/naked_functions.rs
@@ -5,7 +5,7 @@ use rustc_hir as hir;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{LocalDefId, LocalModDefId};
 use rustc_hir::intravisit::Visitor;
-use rustc_hir::{ExprKind, InlineAsmOperand, StmtKind};
+use rustc_hir::{ExprKind, HirIdSet, InlineAsmOperand, StmtKind};
 use rustc_middle::query::Providers;
 use rustc_middle::ty::TyCtxt;
 use rustc_session::lint::builtin::UNDEFINED_NAKED_FUNCTION_ABI;
@@ -94,7 +94,7 @@ fn check_no_patterns(tcx: TyCtxt<'_>, params: &[hir::Param<'_>]) {
 
 /// Checks that function parameters aren't used in the function body.
 fn check_no_parameters_use<'tcx>(tcx: TyCtxt<'tcx>, body: &'tcx hir::Body<'tcx>) {
-    let mut params = hir::HirIdSet::default();
+    let mut params = HirIdSet::default();
     for param in body.params {
         param.pat.each_binding(|_binding_mode, hir_id, _span, _ident| {
             params.insert(hir_id);
@@ -105,7 +105,7 @@ fn check_no_parameters_use<'tcx>(tcx: TyCtxt<'tcx>, body: &'tcx hir::Body<'tcx>)
 
 struct CheckParameters<'tcx> {
     tcx: TyCtxt<'tcx>,
-    params: hir::HirIdSet,
+    params: HirIdSet,
 }
 
 impl<'tcx> Visitor<'tcx> for CheckParameters<'tcx> {
diff --git a/compiler/rustc_passes/src/upvars.rs b/compiler/rustc_passes/src/upvars.rs
index 4d44e8762b0..2eed58d10bb 100644
--- a/compiler/rustc_passes/src/upvars.rs
+++ b/compiler/rustc_passes/src/upvars.rs
@@ -66,7 +66,7 @@ impl CaptureCollector<'_, '_> {
 }
 
 impl<'tcx> Visitor<'tcx> for CaptureCollector<'_, 'tcx> {
-    fn visit_path(&mut self, path: &hir::Path<'tcx>, _: hir::HirId) {
+    fn visit_path(&mut self, path: &hir::Path<'tcx>, _: HirId) {
         if let Res::Local(var_id) = path.res {
             self.visit_local_use(var_id, path.span);
         }
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index 33c9c7fcc62..ba1391bc378 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -793,7 +793,7 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast,
                 self.r.record_partial_res(ty.id, PartialRes::new(res));
                 visit::walk_ty(self, ty)
             }
-            TyKind::ImplTrait(node_id, _) => {
+            TyKind::ImplTrait(node_id, _, _) => {
                 let candidates = self.lifetime_elision_candidates.take();
                 visit::walk_ty(self, ty);
                 self.record_lifetime_params_for_impl_trait(*node_id);
@@ -1047,10 +1047,39 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast,
         });
         self.diag_metadata.current_function = previous_value;
     }
+
     fn visit_lifetime(&mut self, lifetime: &'ast Lifetime, use_ctxt: visit::LifetimeCtxt) {
         self.resolve_lifetime(lifetime, use_ctxt)
     }
 
+    fn visit_precise_capturing_arg(&mut self, arg: &'ast PreciseCapturingArg) {
+        match arg {
+            // Lower the lifetime regularly; we'll resolve the lifetime and check
+            // it's a parameter later on in HIR lowering.
+            PreciseCapturingArg::Lifetime(_) => {}
+
+            PreciseCapturingArg::Arg(path, id) => {
+                // we want `impl use<C>` to try to resolve `C` as both a type parameter or
+                // a const parameter. Since the resolver specifically doesn't allow having
+                // two generic params with the same name, even if they're a different namespace,
+                // it doesn't really matter which we try resolving first, but just like
+                // `Ty::Param` we just fall back to the value namespace only if it's missing
+                // from the type namespace.
+                let mut check_ns = |ns| {
+                    self.maybe_resolve_ident_in_lexical_scope(path.segments[0].ident, ns).is_some()
+                };
+                // Like `Ty::Param`, we try resolving this as both a const and a type.
+                if !check_ns(TypeNS) && check_ns(ValueNS) {
+                    self.smart_resolve_path(*id, &None, path, PathSource::Expr(None));
+                } else {
+                    self.smart_resolve_path(*id, &None, path, PathSource::Type);
+                }
+            }
+        }
+
+        visit::walk_precise_capturing_arg(self, arg)
+    }
+
     fn visit_generics(&mut self, generics: &'ast Generics) {
         self.visit_generic_params(&generics.params, self.diag_metadata.current_self_item.is_some());
         for p in &generics.where_clause.predicates {
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index bb4294fbcfb..d79c638fa07 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -3121,7 +3121,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
                                 .inputs
                                 .iter()
                                 .filter_map(|param| match &param.ty.kind {
-                                    TyKind::ImplTrait(_, bounds) => Some(bounds),
+                                    TyKind::ImplTrait(_, bounds, _) => Some(bounds),
                                     _ => None,
                                 })
                                 .flat_map(|bounds| bounds.into_iter())
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index 7aca86f7169..2a7b5650fc2 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -1125,7 +1125,7 @@ impl Options {
             || self.unstable_opts.query_dep_graph
     }
 
-    pub(crate) fn file_path_mapping(&self) -> FilePathMapping {
+    pub fn file_path_mapping(&self) -> FilePathMapping {
         file_path_mapping(self.remap_path_prefix.clone(), &self.unstable_opts)
     }
 
@@ -1162,6 +1162,16 @@ impl UnstableOptions {
             track_diagnostics: self.track_diagnostics,
         }
     }
+
+    pub fn src_hash_algorithm(&self, target: &Target) -> SourceFileHashAlgorithm {
+        self.src_hash_algorithm.unwrap_or_else(|| {
+            if target.is_like_msvc {
+                SourceFileHashAlgorithm::Sha256
+            } else {
+                SourceFileHashAlgorithm::Md5
+            }
+        })
+    }
 }
 
 // The type of entry function, so users can have their own entry functions
@@ -1373,7 +1383,7 @@ pub fn rustc_short_optgroups() -> Vec<RustcOptGroup> {
         opt::flag_s("h", "help", "Display this message"),
         opt::multi_s("", "cfg", "Configure the compilation environment.
                              SPEC supports the syntax `NAME[=\"VALUE\"]`.", "SPEC"),
-        opt::multi("", "check-cfg", "Provide list of valid cfg options for checking", "SPEC"),
+        opt::multi_s("", "check-cfg", "Provide list of expected cfgs for checking", "SPEC"),
         opt::multi_s(
             "L",
             "",
diff --git a/compiler/rustc_session/src/config/cfg.rs b/compiler/rustc_session/src/config/cfg.rs
index 34dcd0cf598..31badbd8692 100644
--- a/compiler/rustc_session/src/config/cfg.rs
+++ b/compiler/rustc_session/src/config/cfg.rs
@@ -257,7 +257,7 @@ impl CheckCfg {
         // `tests/ui/check-cfg/well-known-values.rs` (in order to test the
         // expected values of the new config) and bless the all directory.
         //
-        // Don't forget to update `src/doc/unstable-book/src/compiler-flags/check-cfg.md`
+        // Don't forget to update `src/doc/rustc/src/check-cfg.md`
         // in the unstable book as well!
 
         ins!(sym::debug_assertions, no_values);
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index 963c9558c17..c4d802a222b 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -1534,6 +1534,8 @@ options! {
     relocation_model: Option<RelocModel> = (None, parse_relocation_model, [TRACKED],
         "control generation of position-independent code (PIC) \
         (`rustc --print relocation-models` for details)"),
+    relro_level: Option<RelroLevel> = (None, parse_relro_level, [TRACKED],
+        "choose which RELRO level to use"),
     remark: Passes = (Passes::Some(Vec::new()), parse_passes, [UNTRACKED],
         "output remarks for these optimization passes (space separated, or \"all\")"),
     rpath: bool = (false, parse_bool, [UNTRACKED],
@@ -1881,8 +1883,6 @@ options! {
         "randomize the layout of types (default: no)"),
     relax_elf_relocations: Option<bool> = (None, parse_opt_bool, [TRACKED],
         "whether ELF relocations can be relaxed"),
-    relro_level: Option<RelroLevel> = (None, parse_relro_level, [TRACKED],
-        "choose which RELRO level to use"),
     remap_cwd_prefix: Option<PathBuf> = (None, parse_opt_pathbuf, [TRACKED],
         "remap paths under the current working directory to this path prefix"),
     remap_path_scope: RemapPathScopeComponents = (RemapPathScopeComponents::all(), parse_remap_path_scope, [TRACKED],
diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs
index 22ca8a3cf3e..b63c119eee0 100644
--- a/compiler/rustc_session/src/session.rs
+++ b/compiler/rustc_session/src/session.rs
@@ -28,9 +28,9 @@ use rustc_errors::{
 use rustc_macros::HashStable_Generic;
 pub use rustc_span::def_id::StableCrateId;
 use rustc_span::edition::Edition;
-use rustc_span::source_map::{FileLoader, FilePathMapping, RealFileLoader, SourceMap};
+use rustc_span::source_map::{FilePathMapping, SourceMap};
 use rustc_span::{FileNameDisplayPreference, RealFileName};
-use rustc_span::{SourceFileHashAlgorithm, Span, Symbol};
+use rustc_span::{Span, Symbol};
 use rustc_target::asm::InlineAsmArch;
 use rustc_target::spec::{CodeModel, PanicStrategy, RelocModel, RelroLevel};
 use rustc_target::spec::{
@@ -573,7 +573,7 @@ impl Session {
 
         let dbg_opts = &self.opts.unstable_opts;
 
-        let relro_level = dbg_opts.relro_level.unwrap_or(self.target.relro_level);
+        let relro_level = self.opts.cg.relro_level.unwrap_or(self.target.relro_level);
 
         // Only enable this optimization by default if full relro is also enabled.
         // In this case, lazy binding was already unavailable, so nothing is lost.
@@ -988,7 +988,6 @@ pub fn build_session(
     registry: rustc_errors::registry::Registry,
     fluent_resources: Vec<&'static str>,
     driver_lint_caps: FxHashMap<lint::LintId, lint::Level>,
-    file_loader: Option<Box<dyn FileLoader + Send + Sync + 'static>>,
     target: Target,
     sysroot: PathBuf,
     cfg_version: &'static str,
@@ -1015,24 +1014,11 @@ pub fn build_session(
         early_dcx.early_warn(warning)
     }
 
-    let loader = file_loader.unwrap_or_else(|| Box::new(RealFileLoader));
-    let hash_kind = sopts.unstable_opts.src_hash_algorithm.unwrap_or_else(|| {
-        if target.is_like_msvc {
-            SourceFileHashAlgorithm::Sha256
-        } else {
-            SourceFileHashAlgorithm::Md5
-        }
-    });
-    let source_map = Lrc::new(SourceMap::with_file_loader_and_hash_kind(
-        loader,
-        sopts.file_path_mapping(),
-        hash_kind,
-    ));
-
     let fallback_bundle = fallback_fluent_bundle(
         fluent_resources,
         sopts.unstable_opts.translate_directionality_markers,
     );
+    let source_map = rustc_span::source_map::get_source_map().unwrap();
     let emitter = default_emitter(&sopts, registry, source_map.clone(), bundle, fallback_bundle);
 
     let mut dcx =
@@ -1411,16 +1397,10 @@ impl EarlyDiagCtxt {
         self.dcx.warn(msg)
     }
 
-    pub fn initialize_checked_jobserver(&self) {
-        // initialize jobserver before getting `jobserver::client` and `build_session`.
-        jobserver::initialize_checked(|err| {
-            #[allow(rustc::untranslatable_diagnostic)]
-            #[allow(rustc::diagnostic_outside_of_impl)]
-            self.dcx
-                .struct_warn(err)
-                .with_note("the build environment is likely misconfigured")
-                .emit()
-        });
+    #[allow(rustc::untranslatable_diagnostic)]
+    #[allow(rustc::diagnostic_outside_of_impl)]
+    pub fn early_struct_warn(&self, msg: impl Into<DiagMessage>) -> Diag<'_, ()> {
+        self.dcx.struct_warn(msg)
     }
 }
 
diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs
index c1e1175b4bd..f749d4eb833 100644
--- a/compiler/rustc_span/src/lib.rs
+++ b/compiler/rustc_span/src/lib.rs
@@ -49,7 +49,7 @@ use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
 mod caching_source_map_view;
 pub mod source_map;
 pub use self::caching_source_map_view::CachingSourceMapView;
-use source_map::SourceMap;
+use source_map::{SourceMap, SourceMapInputs};
 
 pub mod edition;
 use edition::Edition;
@@ -104,35 +104,35 @@ pub struct SessionGlobals {
     metavar_spans: Lock<FxHashMap<Span, Span>>,
     hygiene_data: Lock<hygiene::HygieneData>,
 
-    /// A reference to the source map in the `Session`. It's an `Option`
-    /// because it can't be initialized until `Session` is created, which
-    /// happens after `SessionGlobals`. `set_source_map` does the
-    /// initialization.
-    ///
-    /// This field should only be used in places where the `Session` is truly
-    /// not available, such as `<Span as Debug>::fmt`.
-    source_map: Lock<Option<Lrc<SourceMap>>>,
+    /// The session's source map, if there is one. This field should only be
+    /// used in places where the `Session` is truly not available, such as
+    /// `<Span as Debug>::fmt`.
+    source_map: Option<Lrc<SourceMap>>,
 }
 
 impl SessionGlobals {
-    pub fn new(edition: Edition) -> SessionGlobals {
+    pub fn new(edition: Edition, sm_inputs: Option<SourceMapInputs>) -> SessionGlobals {
         SessionGlobals {
             symbol_interner: symbol::Interner::fresh(),
             span_interner: Lock::new(span_encoding::SpanInterner::default()),
             metavar_spans: Default::default(),
             hygiene_data: Lock::new(hygiene::HygieneData::new(edition)),
-            source_map: Lock::new(None),
+            source_map: sm_inputs.map(|inputs| Lrc::new(SourceMap::with_inputs(inputs))),
         }
     }
 }
 
-pub fn create_session_globals_then<R>(edition: Edition, f: impl FnOnce() -> R) -> R {
+pub fn create_session_globals_then<R>(
+    edition: Edition,
+    sm_inputs: Option<SourceMapInputs>,
+    f: impl FnOnce() -> R,
+) -> R {
     assert!(
         !SESSION_GLOBALS.is_set(),
         "SESSION_GLOBALS should never be overwritten! \
          Use another thread if you need another SessionGlobals"
     );
-    let session_globals = SessionGlobals::new(edition);
+    let session_globals = SessionGlobals::new(edition, sm_inputs);
     SESSION_GLOBALS.set(&session_globals, f)
 }
 
@@ -145,12 +145,13 @@ pub fn set_session_globals_then<R>(session_globals: &SessionGlobals, f: impl FnO
     SESSION_GLOBALS.set(session_globals, f)
 }
 
+/// No source map.
 pub fn create_session_if_not_set_then<R, F>(edition: Edition, f: F) -> R
 where
     F: FnOnce(&SessionGlobals) -> R,
 {
     if !SESSION_GLOBALS.is_set() {
-        let session_globals = SessionGlobals::new(edition);
+        let session_globals = SessionGlobals::new(edition, None);
         SESSION_GLOBALS.set(&session_globals, || SESSION_GLOBALS.with(f))
     } else {
         SESSION_GLOBALS.with(f)
@@ -164,8 +165,9 @@ where
     SESSION_GLOBALS.with(f)
 }
 
+/// Default edition, no source map.
 pub fn create_default_session_globals_then<R>(f: impl FnOnce() -> R) -> R {
-    create_session_globals_then(edition::DEFAULT_EDITION, f)
+    create_session_globals_then(edition::DEFAULT_EDITION, None, f)
 }
 
 // If this ever becomes non thread-local, `decode_syntax_context`
@@ -1318,25 +1320,6 @@ impl<D: SpanDecoder> Decodable<D> for AttrId {
     }
 }
 
-/// Insert `source_map` into the session globals for the duration of the
-/// closure's execution.
-pub fn set_source_map<T, F: FnOnce() -> T>(source_map: Lrc<SourceMap>, f: F) -> T {
-    with_session_globals(|session_globals| {
-        *session_globals.source_map.borrow_mut() = Some(source_map);
-    });
-    struct ClearSourceMap;
-    impl Drop for ClearSourceMap {
-        fn drop(&mut self) {
-            with_session_globals(|session_globals| {
-                session_globals.source_map.borrow_mut().take();
-            });
-        }
-    }
-
-    let _guard = ClearSourceMap;
-    f()
-}
-
 impl fmt::Debug for Span {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         // Use the global `SourceMap` to print the span. If that's not
@@ -1352,7 +1335,7 @@ impl fmt::Debug for Span {
 
         if SESSION_GLOBALS.is_set() {
             with_session_globals(|session_globals| {
-                if let Some(source_map) = &*session_globals.source_map.borrow() {
+                if let Some(source_map) = &session_globals.source_map {
                     write!(f, "{} ({:?})", source_map.span_to_diagnostic_string(*self), self.ctxt())
                 } else {
                     fallback(*self, f)
diff --git a/compiler/rustc_span/src/source_map.rs b/compiler/rustc_span/src/source_map.rs
index 93d5f06a167..e3e76caebaf 100644
--- a/compiler/rustc_span/src/source_map.rs
+++ b/compiler/rustc_span/src/source_map.rs
@@ -167,9 +167,17 @@ struct SourceMapFiles {
     stable_id_to_source_file: UnhashMap<StableSourceFileId, Lrc<SourceFile>>,
 }
 
+/// Used to construct a `SourceMap` with `SourceMap::with_inputs`.
+pub struct SourceMapInputs {
+    pub file_loader: Box<dyn FileLoader + Send + Sync>,
+    pub path_mapping: FilePathMapping,
+    pub hash_kind: SourceFileHashAlgorithm,
+}
+
 pub struct SourceMap {
     files: RwLock<SourceMapFiles>,
     file_loader: IntoDynSyncSend<Box<dyn FileLoader + Sync + Send>>,
+
     // This is used to apply the file path remapping as specified via
     // `--remap-path-prefix` to all `SourceFile`s allocated within this `SourceMap`.
     path_mapping: FilePathMapping,
@@ -180,17 +188,15 @@ pub struct SourceMap {
 
 impl SourceMap {
     pub fn new(path_mapping: FilePathMapping) -> SourceMap {
-        Self::with_file_loader_and_hash_kind(
-            Box::new(RealFileLoader),
+        Self::with_inputs(SourceMapInputs {
+            file_loader: Box::new(RealFileLoader),
             path_mapping,
-            SourceFileHashAlgorithm::Md5,
-        )
+            hash_kind: SourceFileHashAlgorithm::Md5,
+        })
     }
 
-    pub fn with_file_loader_and_hash_kind(
-        file_loader: Box<dyn FileLoader + Sync + Send>,
-        path_mapping: FilePathMapping,
-        hash_kind: SourceFileHashAlgorithm,
+    pub fn with_inputs(
+        SourceMapInputs { file_loader, path_mapping, hash_kind }: SourceMapInputs,
     ) -> SourceMap {
         SourceMap {
             files: Default::default(),
@@ -1054,6 +1060,10 @@ impl SourceMap {
     }
 }
 
+pub fn get_source_map() -> Option<Lrc<SourceMap>> {
+    with_session_globals(|session_globals| session_globals.source_map.clone())
+}
+
 #[derive(Clone)]
 pub struct FilePathMapping {
     mapping: Vec<(PathBuf, PathBuf)>,
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index bfd0f77c237..46bae1c1e98 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -1194,6 +1194,7 @@ symbols! {
         multiple_supertrait_upcastable,
         must_not_suspend,
         must_use,
+        mut_preserve_binding_mode_2024,
         mut_ref,
         naked,
         naked_functions,
@@ -1375,6 +1376,7 @@ symbols! {
         powif32,
         powif64,
         pre_dash_lto: "pre-lto",
+        precise_capturing,
         precise_pointer_size_matching,
         pref_align_of,
         prefetch_read_data,
@@ -1460,6 +1462,7 @@ symbols! {
         receiver,
         recursion_limit,
         reexport_test_harness_main,
+        ref_pat_eat_one_layer_2024,
         ref_pat_everywhere,
         ref_unwind_safe_trait,
         reference,
diff --git a/compiler/rustc_target/src/spec/base/apple/mod.rs b/compiler/rustc_target/src/spec/base/apple/mod.rs
index 021457b145f..d667bad44e3 100644
--- a/compiler/rustc_target/src/spec/base/apple/mod.rs
+++ b/compiler/rustc_target/src/spec/base/apple/mod.rs
@@ -298,6 +298,7 @@ fn link_env_remove(os: &'static str) -> StaticCow<[StaticCow<str>]> {
                 || sdkroot.contains("WatchOS.platform")
                 || sdkroot.contains("WatchSimulator.platform")
                 || sdkroot.contains("XROS.platform")
+                || sdkroot.contains("XRSimulator.platform")
             {
                 env_remove.push("SDKROOT".into())
             }
diff --git a/compiler/rustc_target/src/spec/base/wasm.rs b/compiler/rustc_target/src/spec/base/wasm.rs
index 4b4d2aca26e..f237391016e 100644
--- a/compiler/rustc_target/src/spec/base/wasm.rs
+++ b/compiler/rustc_target/src/spec/base/wasm.rs
@@ -80,9 +80,6 @@ pub fn options() -> TargetOptions {
         // threaded model which will legalize atomics to normal operations.
         singlethread: true,
 
-        // no dynamic linking, no need for default visibility!
-        default_hidden_visibility: true,
-
         // Symbol visibility takes care of this for the WebAssembly.
         // Additionally the only known linker, LLD, doesn't support the script
         // arguments just yet
diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs
index 0154aff12b6..f914e6b3f2e 100644
--- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs
+++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs
@@ -2,7 +2,7 @@ use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_hir::def_id::DefId;
 use rustc_infer::infer::at::ToTrace;
 use rustc_infer::infer::canonical::CanonicalVarValues;
-use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
+use rustc_infer::infer::type_variable::TypeVariableOrigin;
 use rustc_infer::infer::{
     BoundRegionConversionTime, DefineOpaqueTypes, InferCtxt, InferOk, TyCtxtInferExt,
 };
@@ -10,7 +10,7 @@ use rustc_infer::traits::query::NoSolution;
 use rustc_infer::traits::solve::{MaybeCause, NestedNormalizationGoals};
 use rustc_infer::traits::ObligationCause;
 use rustc_middle::infer::canonical::CanonicalVarInfos;
-use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
+use rustc_middle::infer::unify_key::ConstVariableOrigin;
 use rustc_middle::traits::solve::inspect;
 use rustc_middle::traits::solve::{
     CanonicalInput, CanonicalResponse, Certainty, PredefinedOpaques, PredefinedOpaquesData,
@@ -587,17 +587,11 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
     }
 
     pub(super) fn next_ty_infer(&self) -> Ty<'tcx> {
-        self.infcx.next_ty_var(TypeVariableOrigin {
-            kind: TypeVariableOriginKind::MiscVariable,
-            span: DUMMY_SP,
-        })
+        self.infcx.next_ty_var(TypeVariableOrigin { param_def_id: None, span: DUMMY_SP })
     }
 
     pub(super) fn next_const_infer(&self, ty: Ty<'tcx>) -> ty::Const<'tcx> {
-        self.infcx.next_const_var(
-            ty,
-            ConstVariableOrigin { kind: ConstVariableOriginKind::MiscVariable, span: DUMMY_SP },
-        )
+        self.infcx.next_const_var(ty, ConstVariableOrigin { param_def_id: None, span: DUMMY_SP })
     }
 
     /// Returns a ty infer or a const infer depending on whether `kind` is a `Ty` or `Const`.
diff --git a/compiler/rustc_trait_selection/src/solve/normalize.rs b/compiler/rustc_trait_selection/src/solve/normalize.rs
index 5b45e1a34e4..65ef4659907 100644
--- a/compiler/rustc_trait_selection/src/solve/normalize.rs
+++ b/compiler/rustc_trait_selection/src/solve/normalize.rs
@@ -3,11 +3,11 @@ use crate::traits::query::evaluate_obligation::InferCtxtExt;
 use crate::traits::{BoundVarReplacer, PlaceholderReplacer};
 use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_infer::infer::at::At;
-use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
+use rustc_infer::infer::type_variable::TypeVariableOrigin;
 use rustc_infer::infer::InferCtxt;
 use rustc_infer::traits::TraitEngineExt;
 use rustc_infer::traits::{FulfillmentError, Obligation, TraitEngine};
-use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
+use rustc_middle::infer::unify_key::ConstVariableOrigin;
 use rustc_middle::traits::ObligationCause;
 use rustc_middle::ty::{self, AliasTy, Ty, TyCtxt, UniverseIndex};
 use rustc_middle::ty::{FallibleTypeFolder, TypeFolder, TypeSuperFoldable};
@@ -74,10 +74,8 @@ impl<'tcx> NormalizationFolder<'_, 'tcx> {
 
         self.depth += 1;
 
-        let new_infer_ty = infcx.next_ty_var(TypeVariableOrigin {
-            kind: TypeVariableOriginKind::NormalizeProjectionType,
-            span: self.at.cause.span,
-        });
+        let new_infer_ty =
+            infcx.next_ty_var(TypeVariableOrigin { param_def_id: None, span: self.at.cause.span });
         let obligation = Obligation::new(
             tcx,
             self.at.cause.clone(),
@@ -124,10 +122,7 @@ impl<'tcx> NormalizationFolder<'_, 'tcx> {
 
         let new_infer_ct = infcx.next_const_var(
             ty,
-            ConstVariableOrigin {
-                kind: ConstVariableOriginKind::MiscVariable,
-                span: self.at.cause.span,
-            },
+            ConstVariableOrigin { param_def_id: None, span: self.at.cause.span },
         );
         let obligation = Obligation::new(
             tcx,
@@ -203,7 +198,7 @@ impl<'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for NormalizationFolder<'_, 'tcx> {
     #[instrument(level = "debug", skip(self), ret)]
     fn try_fold_const(&mut self, ct: ty::Const<'tcx>) -> Result<ty::Const<'tcx>, Self::Error> {
         let infcx = self.at.infcx;
-        debug_assert_eq!(ct, infcx.shallow_resolve(ct));
+        debug_assert_eq!(ct, infcx.shallow_resolve_const(ct));
         if !ct.has_aliases() {
             return Ok(ct);
         }
diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs
index 77eaa4fd03e..36028b51659 100644
--- a/compiler/rustc_trait_selection/src/traits/coherence.rs
+++ b/compiler/rustc_trait_selection/src/traits/coherence.rs
@@ -501,7 +501,7 @@ fn plug_infer_with_placeholders<'tcx>(
         }
 
         fn visit_const(&mut self, ct: ty::Const<'tcx>) {
-            let ct = self.infcx.shallow_resolve(ct);
+            let ct = self.infcx.shallow_resolve_const(ct);
             if ct.is_ct_infer() {
                 let Ok(InferOk { value: (), obligations }) =
                     self.infcx.at(&ObligationCause::dummy(), ty::ParamEnv::empty()).eq(
diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
index 9ca1dd4557d..a8be5627fed 100644
--- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
+++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
@@ -8,15 +8,14 @@
 //! In this case we try to build an abstract representation of this constant using
 //! `thir_abstract_const` which can then be checked for structural equality with other
 //! generic constants mentioned in the `caller_bounds` of the current environment.
+
 use rustc_hir::def::DefKind;
 use rustc_infer::infer::InferCtxt;
 use rustc_middle::mir::interpret::ErrorHandled;
-
 use rustc_middle::traits::ObligationCause;
 use rustc_middle::ty::abstract_const::NotConstEvaluatable;
 use rustc_middle::ty::{self, TyCtxt, TypeVisitable, TypeVisitableExt, TypeVisitor};
-
-use rustc_span::Span;
+use rustc_span::{Span, DUMMY_SP};
 
 use crate::traits::ObligationCtxt;
 
@@ -116,12 +115,12 @@ pub fn is_const_evaluatable<'tcx>(
                 tcx.dcx()
                     .struct_span_fatal(
                         // Slightly better span than just using `span` alone
-                        if span == rustc_span::DUMMY_SP { tcx.def_span(uv.def) } else { span },
+                        if span == DUMMY_SP { tcx.def_span(uv.def) } else { span },
                         "failed to evaluate generic const expression",
                     )
                     .with_note("the crate this constant originates from uses `#![feature(generic_const_exprs)]`")
                     .with_span_suggestion_verbose(
-                        rustc_span::DUMMY_SP,
+                        DUMMY_SP,
                         "consider enabling this feature",
                         "#![feature(generic_const_exprs)]\n",
                         rustc_errors::Applicability::MaybeIncorrect,
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/infer_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/infer_ctxt_ext.rs
index 6c6c8ca1d9f..d41d43bad71 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/infer_ctxt_ext.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/infer_ctxt_ext.rs
@@ -1,4 +1,4 @@
-use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
+use crate::infer::type_variable::TypeVariableOrigin;
 use crate::infer::InferCtxt;
 use crate::traits::{Obligation, ObligationCause, ObligationCtxt};
 use rustc_errors::{codes::*, pluralize, struct_span_code_err, Applicability, Diag};
@@ -217,10 +217,8 @@ impl<'tcx> InferCtxt<'tcx> {
                 let Some(trait_def_id) = trait_def_id else { continue };
                 // Make a fresh inference variable so we can determine what the generic parameters
                 // of the trait are.
-                let var = self.next_ty_var(TypeVariableOrigin {
-                    span: DUMMY_SP,
-                    kind: TypeVariableOriginKind::MiscVariable,
-                });
+                let var =
+                    self.next_ty_var(TypeVariableOrigin { span: DUMMY_SP, param_def_id: None });
                 // FIXME(effects)
                 let trait_ref = ty::TraitRef::new(self.tcx, trait_def_id, [ty.skip_binder(), var]);
                 let obligation = Obligation::new(
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 af8713ba3ff..4c1784a18e5 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -24,7 +24,7 @@ use rustc_hir::is_range_literal;
 use rustc_hir::lang_items::LangItem;
 use rustc_hir::{CoroutineDesugaring, CoroutineKind, CoroutineSource, Expr, HirId, Node};
 use rustc_infer::infer::error_reporting::TypeErrCtxt;
-use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
+use rustc_infer::infer::type_variable::TypeVariableOrigin;
 use rustc_infer::infer::{BoundRegionConversionTime, DefineOpaqueTypes, InferOk};
 use rustc_middle::hir::map;
 use rustc_middle::traits::IsConstable;
@@ -1894,10 +1894,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                 ty::Tuple(inputs) if infcx.tcx.is_fn_trait(trait_ref.def_id) => {
                     infcx.tcx.mk_fn_sig(
                         *inputs,
-                        infcx.next_ty_var(TypeVariableOrigin {
-                            span: DUMMY_SP,
-                            kind: TypeVariableOriginKind::MiscVariable,
-                        }),
+                        infcx
+                            .next_ty_var(TypeVariableOrigin { span: DUMMY_SP, param_def_id: None }),
                         false,
                         hir::Unsafety::Normal,
                         abi::Abi::Rust,
@@ -1905,10 +1903,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                 }
                 _ => infcx.tcx.mk_fn_sig(
                     [inputs],
-                    infcx.next_ty_var(TypeVariableOrigin {
-                        span: DUMMY_SP,
-                        kind: TypeVariableOriginKind::MiscVariable,
-                    }),
+                    infcx.next_ty_var(TypeVariableOrigin { span: DUMMY_SP, param_def_id: None }),
                     false,
                     hir::Unsafety::Normal,
                     abi::Abi::Rust,
@@ -4256,7 +4251,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
         type_diffs: &[TypeError<'tcx>],
         span: Span,
         prev_ty: Ty<'tcx>,
-        body_id: hir::HirId,
+        body_id: HirId,
         param_env: ty::ParamEnv<'tcx>,
     ) -> Vec<Option<(Span, (DefId, Ty<'tcx>))>> {
         let ocx = ObligationCtxt::new(self.infcx);
@@ -4269,7 +4264,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                 continue;
             };
 
-            let origin = TypeVariableOrigin { kind: TypeVariableOriginKind::TypeInference, span };
+            let origin = TypeVariableOrigin { param_def_id: None, span };
             // 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.
@@ -4550,7 +4545,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
             self.type_implements_trait(default_trait, [ty], param_env).must_apply_modulo_regions()
         };
 
-        Some(match ty.kind() {
+        Some(match *ty.kind() {
             ty::Never | ty::Error(_) => return None,
             ty::Bool => "false".to_string(),
             ty::Char => "\'x\'".to_string(),
@@ -4577,12 +4572,19 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                 if let (ty::Str, hir::Mutability::Not) = (ty.kind(), mutability) {
                     "\"\"".to_string()
                 } else {
-                    let ty = self.ty_kind_suggestion(param_env, *ty)?;
+                    let ty = self.ty_kind_suggestion(param_env, ty)?;
                     format!("&{}{ty}", mutability.prefix_str())
                 }
             }
             ty::Array(ty, len) if let Some(len) = len.try_eval_target_usize(tcx, param_env) => {
-                format!("[{}; {}]", self.ty_kind_suggestion(param_env, *ty)?, len)
+                if len == 0 {
+                    "[]".to_string()
+                } else if self.type_is_copy_modulo_regions(param_env, ty) || len == 1 {
+                    // Can only suggest `[ty; 0]` if sz == 1 or copy
+                    format!("[{}; {}]", self.ty_kind_suggestion(param_env, ty)?, len)
+                } else {
+                    "/* value */".to_string()
+                }
             }
             ty::Tuple(tys) => format!(
                 "({}{})",
@@ -4592,7 +4594,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                     .join(", "),
                 if tys.len() == 1 { "," } else { "" }
             ),
-            _ => "value".to_string(),
+            _ => "/* value */".to_string(),
         })
     }
 }
@@ -4762,7 +4764,7 @@ impl<'v> Visitor<'v> for ReturnsVisitor<'v> {
 /// Collect all the awaited expressions within the input expression.
 #[derive(Default)]
 struct AwaitsVisitor {
-    awaits: Vec<hir::HirId>,
+    awaits: Vec<HirId>,
 }
 
 impl<'v> Visitor<'v> for AwaitsVisitor {
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs
index 6be4589d380..96596de32aa 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs
@@ -6,7 +6,7 @@ use crate::errors::{
     AsyncClosureNotFn, ClosureFnMutLabel, ClosureFnOnceLabel, ClosureKindMismatch,
 };
 use crate::infer::error_reporting::{TyCategory, TypeAnnotationNeeded as ErrorCode};
-use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
+use crate::infer::type_variable::TypeVariableOrigin;
 use crate::infer::InferCtxtExt as _;
 use crate::infer::{self, InferCtxt};
 use crate::traits::error_reporting::infer_ctxt_ext::InferCtxtExt;
@@ -984,7 +984,10 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
             // Already reported in the query.
             SelectionError::NotConstEvaluatable(NotConstEvaluatable::Error(guar)) |
             // Already reported.
-            Overflow(OverflowError::Error(guar)) => return guar,
+            Overflow(OverflowError::Error(guar)) => {
+                self.set_tainted_by_errors(guar);
+                return guar
+            },
 
             Overflow(_) => {
                 bug!("overflow should be handled before the `report_selection_error` path");
@@ -1974,6 +1977,9 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                     for (obligation_arg, impl_arg) in
                         std::iter::zip(obligation_trait_ref.args, impl_trait_ref.args)
                     {
+                        if (obligation_arg, impl_arg).references_error() {
+                            return false;
+                        }
                         if let Err(terr) =
                             ocx.eq(&ObligationCause::dummy(), param_env, impl_arg, obligation_arg)
                         {
@@ -2820,10 +2826,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                 if let ty::Param(_) = *ty.kind() {
                     let infcx = self.infcx;
                     *self.var_map.entry(ty).or_insert_with(|| {
-                        infcx.next_ty_var(TypeVariableOrigin {
-                            kind: TypeVariableOriginKind::MiscVariable,
-                            span: DUMMY_SP,
-                        })
+                        infcx.next_ty_var(TypeVariableOrigin { param_def_id: None, span: DUMMY_SP })
                     })
                 } else {
                     ty.super_fold_with(self)
diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs
index 98d5b466cd0..8f5a30c436d 100644
--- a/compiler/rustc_trait_selection/src/traits/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/mod.rs
@@ -162,7 +162,7 @@ fn pred_known_to_hold_modulo_regions<'tcx>(
             let errors = ocx.select_all_or_error();
             match errors.as_slice() {
                 // Only known to hold if we did no inference.
-                [] => infcx.shallow_resolve(goal) == goal,
+                [] => infcx.resolve_vars_if_possible(goal) == goal,
 
                 errors => {
                     debug!(?errors);
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index a5483c5bbc0..4a8df6c6a5b 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -18,7 +18,7 @@ use rustc_middle::traits::ImplSource;
 use rustc_middle::traits::ImplSourceUserDefinedData;
 
 use crate::errors::InherentProjectionNormalizationOverflow;
-use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
+use crate::infer::type_variable::TypeVariableOrigin;
 use crate::infer::{BoundRegionConversionTime, InferOk};
 use crate::traits::normalize::normalize_with_depth;
 use crate::traits::normalize::normalize_with_depth_to;
@@ -522,7 +522,7 @@ fn normalize_to_error<'a, 'tcx>(
     };
     let tcx = selcx.infcx.tcx;
     let new_value = selcx.infcx.next_ty_var(TypeVariableOrigin {
-        kind: TypeVariableOriginKind::NormalizeProjectionType,
+        param_def_id: None,
         span: tcx.def_span(projection_ty.def_id),
     });
     Normalized { value: new_value, obligations: vec![trait_obligation] }
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 974e5ef0e16..c415d288b8f 100644
--- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
@@ -87,6 +87,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             } else if lang_items.sized_trait() == Some(def_id) {
                 // Sized is never implementable by end-users, it is
                 // always automatically computed.
+
+                // FIXME: Consider moving this check to the top level as it
+                // may also be useful for predicates other than `Sized`
+                // Error type cannot possibly implement `Sized` (fixes #123154)
+                if let Err(e) = obligation.predicate.skip_binder().self_ty().error_reported() {
+                    return Err(SelectionError::Overflow(e.into()));
+                }
+
                 let sized_conditions = self.sized_conditions(obligation);
                 self.assemble_builtin_bound_candidates(sized_conditions, &mut candidates);
             } else if lang_items.unsize_trait() == Some(def_id) {
@@ -1165,8 +1173,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             return;
         }
 
-        let self_ty = self.infcx.shallow_resolve(obligation.self_ty());
-        match self_ty.skip_binder().kind() {
+        let self_ty = self.infcx.shallow_resolve(obligation.self_ty().skip_binder());
+        match self_ty.kind() {
             ty::Alias(..)
             | ty::Dynamic(..)
             | ty::Error(_)
@@ -1317,7 +1325,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         obligation: &PolyTraitObligation<'tcx>,
         candidates: &mut SelectionCandidateSet<'tcx>,
     ) {
-        let self_ty = self.infcx.shallow_resolve(obligation.self_ty());
+        let self_ty = self.infcx.resolve_vars_if_possible(obligation.self_ty());
 
         match self_ty.skip_binder().kind() {
             ty::FnPtr(_) => candidates.vec.push(BuiltinCandidate { has_nested: false }),
diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
index 716b9a49ab5..4fa2455c42d 100644
--- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
@@ -157,10 +157,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
     ) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
         let tcx = self.tcx();
 
-        let trait_predicate = self.infcx.shallow_resolve(obligation.predicate);
         let placeholder_trait_predicate =
-            self.infcx.enter_forall_and_leak_universe(trait_predicate).trait_ref;
-        let placeholder_self_ty = placeholder_trait_predicate.self_ty();
+            self.infcx.enter_forall_and_leak_universe(obligation.predicate).trait_ref;
+        let placeholder_self_ty = self.infcx.shallow_resolve(placeholder_trait_predicate.self_ty());
         let candidate_predicate = self
             .for_each_item_bound(
                 placeholder_self_ty,
@@ -422,7 +421,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
     ) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
         debug!(?obligation, "confirm_auto_impl_candidate");
 
-        let self_ty = self.infcx.shallow_resolve(obligation.predicate.self_ty());
+        let self_ty = obligation.predicate.self_ty().map_bound(|ty| self.infcx.shallow_resolve(ty));
         let types = self.constituent_types_for_ty(self_ty)?;
         Ok(self.vtable_auto_impl(obligation, obligation.predicate.def_id(), types))
     }
@@ -1378,7 +1377,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         let drop_trait = self.tcx().require_lang_item(LangItem::Drop, None);
 
         let tcx = self.tcx();
-        let self_ty = self.infcx.shallow_resolve(obligation.self_ty());
+        let self_ty = obligation.self_ty().map_bound(|ty| self.infcx.shallow_resolve(ty));
 
         let mut nested = vec![];
         let cause = obligation.derived_cause(BuiltinDerivedObligation);
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index e363119393a..10370c7898b 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -571,7 +571,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             )?;
             // If the predicate has done any inference, then downgrade the
             // result to ambiguous.
-            if this.infcx.shallow_resolve(goal) != goal {
+            if this.infcx.resolve_vars_if_possible(goal) != goal {
                 result = result.max(EvaluatedToAmbig);
             }
             Ok(result)
@@ -1774,9 +1774,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             // 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.args[generics.parent_count..]
-                    .iter()
-                    .any(|&p| p.has_non_region_infer() && self.infcx.shallow_resolve(p) != p)
+                && obligation.predicate.args[generics.parent_count..].iter().any(|&p| {
+                    p.has_non_region_infer() && self.infcx.resolve_vars_if_possible(p) != p
+                })
             {
                 ProjectionMatchesProjection::Ambiguous
             } else {
diff --git a/compiler/rustc_trait_selection/src/traits/structural_normalize.rs b/compiler/rustc_trait_selection/src/traits/structural_normalize.rs
index 2f428564ae7..5746e20490d 100644
--- a/compiler/rustc_trait_selection/src/traits/structural_normalize.rs
+++ b/compiler/rustc_trait_selection/src/traits/structural_normalize.rs
@@ -1,5 +1,5 @@
 use rustc_infer::infer::at::At;
-use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
+use rustc_infer::infer::type_variable::TypeVariableOrigin;
 use rustc_infer::traits::{FulfillmentError, TraitEngine};
 use rustc_middle::ty::{self, Ty};
 
@@ -19,10 +19,9 @@ impl<'tcx> At<'_, 'tcx> {
                 return Ok(ty);
             };
 
-            let new_infer_ty = self.infcx.next_ty_var(TypeVariableOrigin {
-                kind: TypeVariableOriginKind::NormalizeProjectionType,
-                span: self.cause.span,
-            });
+            let new_infer_ty = self
+                .infcx
+                .next_ty_var(TypeVariableOrigin { param_def_id: None, span: self.cause.span });
 
             // We simply emit an `alias-eq` goal here, since that will take care of
             // normalizing the LHS of the projection until it is a rigid projection
diff --git a/compiler/rustc_trait_selection/src/traits/util.rs b/compiler/rustc_trait_selection/src/traits/util.rs
index d29fc7921bc..a8ca7d164a0 100644
--- a/compiler/rustc_trait_selection/src/traits/util.rs
+++ b/compiler/rustc_trait_selection/src/traits/util.rs
@@ -649,7 +649,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for PlaceholderReplacer<'_, 'tcx> {
     }
 
     fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
-        let ct = self.infcx.shallow_resolve(ct);
+        let ct = self.infcx.shallow_resolve_const(ct);
         if let ty::ConstKind::Placeholder(p) = ct.kind() {
             let replace_var = self.mapped_consts.get(&p);
             match replace_var {
diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs
index 5553490542b..f1c24b6adc1 100644
--- a/compiler/rustc_trait_selection/src/traits/wf.rs
+++ b/compiler/rustc_trait_selection/src/traits/wf.rs
@@ -44,7 +44,7 @@ pub fn obligations<'tcx>(
         GenericArgKind::Const(ct) => {
             match ct.kind() {
                 ty::ConstKind::Infer(_) => {
-                    let resolved = infcx.shallow_resolve(ct);
+                    let resolved = infcx.shallow_resolve_const(ct);
                     if resolved == ct {
                         // No progress.
                         return None;
diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs
index f33234122c9..2139b8c665b 100644
--- a/compiler/rustc_ty_utils/src/ty.rs
+++ b/compiler/rustc_ty_utils/src/ty.rs
@@ -91,8 +91,8 @@ fn adt_sized_constraint<'tcx>(
     let tail_ty = tcx.type_of(tail_def.did).instantiate_identity();
 
     let constraint_ty = sized_constraint_for_ty(tcx, tail_ty)?;
-    if constraint_ty.references_error() {
-        return None;
+    if let Err(guar) = constraint_ty.error_reported() {
+        return Some(ty::EarlyBinder::bind(Ty::new_error(tcx, guar)));
     }
 
     // perf hack: if there is a `constraint_ty: Sized` bound, then we know
diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs
index 45e22b12a8b..a5b33a8125d 100644
--- a/compiler/rustc_type_ir/src/lib.rs
+++ b/compiler/rustc_type_ir/src/lib.rs
@@ -346,6 +346,11 @@ impl UniverseIndex {
     pub fn cannot_name(self, other: UniverseIndex) -> bool {
         self < other
     }
+
+    /// Returns `true` if `self` is the root universe, otherwise false.
+    pub fn is_root(self) -> bool {
+        self == Self::ROOT
+    }
 }
 
 impl Default for UniverseIndex {
diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs
index 7c3fa2312e5..ed3ad8b39a5 100644
--- a/library/alloc/src/boxed.rs
+++ b/library/alloc/src/boxed.rs
@@ -1058,7 +1058,8 @@ impl<T: ?Sized, A: Allocator> Box<T, A> {
     #[stable(feature = "box_raw", since = "1.4.0")]
     #[inline]
     pub fn into_raw(b: Self) -> *mut T {
-        Self::into_raw_with_allocator(b).0
+        // Make sure Miri realizes that we transition from a noalias pointer to a raw pointer here.
+        unsafe { addr_of_mut!(*&mut *Self::into_raw_with_allocator(b).0) }
     }
 
     /// Consumes the `Box`, returning a wrapped raw pointer and the allocator.
@@ -1112,7 +1113,10 @@ impl<T: ?Sized, A: Allocator> Box<T, A> {
     pub fn into_raw_with_allocator(b: Self) -> (*mut T, A) {
         let mut b = mem::ManuallyDrop::new(b);
         // We carefully get the raw pointer out in a way that Miri's aliasing model understands what
-        // is happening: using the primitive "deref" of `Box`.
+        // is happening: using the primitive "deref" of `Box`. In case `A` is *not* `Global`, we
+        // want *no* aliasing requirements here!
+        // In case `A` *is* `Global`, this does not quite have the right behavior; `into_raw`
+        // works around that.
         let ptr = addr_of_mut!(**b);
         let alloc = unsafe { ptr::read(&b.1) };
         (ptr, alloc)
diff --git a/library/core/src/iter/range.rs b/library/core/src/iter/range.rs
index 5eea764b28a..644a1692943 100644
--- a/library/core/src/iter/range.rs
+++ b/library/core/src/iter/range.rs
@@ -1156,11 +1156,11 @@ impl<T: TrustedStep> RangeInclusiveIteratorImpl for ops::RangeInclusive<T> {
         let is_iterating = self.start < self.end;
         Some(if is_iterating {
             // SAFETY: just checked precondition
-            let n = unsafe { Step::forward_unchecked(self.start.clone(), 1) };
+            let n = unsafe { Step::forward_unchecked(self.start, 1) };
             mem::replace(&mut self.start, n)
         } else {
             self.exhausted = true;
-            self.start.clone()
+            self.start
         })
     }
 
@@ -1179,7 +1179,7 @@ impl<T: TrustedStep> RangeInclusiveIteratorImpl for ops::RangeInclusive<T> {
 
         while self.start < self.end {
             // SAFETY: just checked precondition
-            let n = unsafe { Step::forward_unchecked(self.start.clone(), 1) };
+            let n = unsafe { Step::forward_unchecked(self.start, 1) };
             let n = mem::replace(&mut self.start, n);
             accum = f(accum, n)?;
         }
@@ -1187,7 +1187,7 @@ impl<T: TrustedStep> RangeInclusiveIteratorImpl for ops::RangeInclusive<T> {
         self.exhausted = true;
 
         if self.start == self.end {
-            accum = f(accum, self.start.clone())?;
+            accum = f(accum, self.start)?;
         }
 
         try { accum }
@@ -1201,11 +1201,11 @@ impl<T: TrustedStep> RangeInclusiveIteratorImpl for ops::RangeInclusive<T> {
         let is_iterating = self.start < self.end;
         Some(if is_iterating {
             // SAFETY: just checked precondition
-            let n = unsafe { Step::backward_unchecked(self.end.clone(), 1) };
+            let n = unsafe { Step::backward_unchecked(self.end, 1) };
             mem::replace(&mut self.end, n)
         } else {
             self.exhausted = true;
-            self.end.clone()
+            self.end
         })
     }
 
@@ -1224,7 +1224,7 @@ impl<T: TrustedStep> RangeInclusiveIteratorImpl for ops::RangeInclusive<T> {
 
         while self.start < self.end {
             // SAFETY: just checked precondition
-            let n = unsafe { Step::backward_unchecked(self.end.clone(), 1) };
+            let n = unsafe { Step::backward_unchecked(self.end, 1) };
             let n = mem::replace(&mut self.end, n);
             accum = f(accum, n)?;
         }
@@ -1232,7 +1232,7 @@ impl<T: TrustedStep> RangeInclusiveIteratorImpl for ops::RangeInclusive<T> {
         self.exhausted = true;
 
         if self.start == self.end {
-            accum = f(accum, self.start.clone())?;
+            accum = f(accum, self.start)?;
         }
 
         try { accum }
diff --git a/library/proc_macro/src/lib.rs b/library/proc_macro/src/lib.rs
index a3ebef45c88..c8db028b651 100644
--- a/library/proc_macro/src/lib.rs
+++ b/library/proc_macro/src/lib.rs
@@ -811,7 +811,7 @@ pub enum Delimiter {
     /// `[ ... ]`
     #[stable(feature = "proc_macro_lib2", since = "1.29.0")]
     Bracket,
-    /// `Ø ... Ø`
+    /// `∅ ... ∅`
     /// An invisible delimiter, that may, for example, appear around tokens coming from a
     /// "macro variable" `$var`. It is important to preserve operator priorities in cases like
     /// `$var * 3` where `$var` is `1 + 2`.
diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs
index 8a24949631c..1293abddaf3 100644
--- a/library/std/src/fs.rs
+++ b/library/std/src/fs.rs
@@ -980,15 +980,21 @@ impl OpenOptions {
     /// Note that setting `.write(true).append(true)` has the same effect as
     /// setting only `.append(true)`.
     ///
-    /// For most filesystems, the operating system guarantees that all writes are
-    /// atomic: no writes get mangled because another process writes at the same
-    /// time.
-    ///
-    /// One maybe obvious note when using append-mode: make sure that all data
-    /// that belongs together is written to the file in one operation. This
-    /// can be done by concatenating strings before passing them to [`write()`],
-    /// or using a buffered writer (with a buffer of adequate size),
-    /// and calling [`flush()`] when the message is complete.
+    /// Append mode guarantees that writes will be positioned at the current end of file,
+    /// even when there are other processes or threads appending to the same file. This is
+    /// unlike <code>[seek]\([SeekFrom]::[End]\(0))</code> followed by `write()`, which
+    /// has a race between seeking and writing during which another writer can write, with
+    /// our `write()` overwriting their data.
+    ///
+    /// Keep in mind that this does not necessarily guarantee that data appended by
+    /// different processes or threads does not interleave. The amount of data accepted a
+    /// single `write()` call depends on the operating system and file system. A
+    /// successful `write()` is allowed to write only part of the given data, so even if
+    /// you're careful to provide the whole message in a single call to `write()`, there
+    /// is no guarantee that it will be written out in full. If you rely on the filesystem
+    /// accepting the message in a single write, make sure that all data that belongs
+    /// together is written in one operation. This can be done by concatenating strings
+    /// before passing them to [`write()`].
     ///
     /// If a file is opened with both read and append access, beware that after
     /// opening, and after every write, the position for reading may be set at the
@@ -1003,6 +1009,9 @@ impl OpenOptions {
     /// [`write()`]: Write::write "io::Write::write"
     /// [`flush()`]: Write::flush "io::Write::flush"
     /// [stream_position]: Seek::stream_position "io::Seek::stream_position"
+    /// [seek]: Seek::seek "io::Seek::seek"
+    /// [Current]: SeekFrom::Current "io::SeekFrom::Current"
+    /// [End]: SeekFrom::End "io::SeekFrom::End"
     ///
     /// # Examples
     ///
diff --git a/library/std/src/sys/pal/sgx/libunwind_integration.rs b/library/std/src/sys/pal/sgx/libunwind_integration.rs
new file mode 100644
index 00000000000..debfd324c86
--- /dev/null
+++ b/library/std/src/sys/pal/sgx/libunwind_integration.rs
@@ -0,0 +1,46 @@
+//! The functions in this module are needed by libunwind. These symbols are named
+//! in pre-link args for the target specification, so keep that in sync.
+
+#![cfg(not(test))]
+
+use crate::sys::sync::RwLock;
+
+// Verify that the byte pattern libunwind uses to initialize an RwLock is
+// equivalent to the value of RwLock::new(). If the value changes,
+// `src/UnwindRustSgx.h` in libunwind needs to be changed too.
+const _: () = unsafe {
+    let bits_rust: usize = crate::mem::transmute(RwLock::new());
+    assert!(bits_rust == 0);
+};
+
+const EINVAL: i32 = 22;
+
+#[no_mangle]
+pub unsafe extern "C" fn __rust_rwlock_rdlock(p: *mut RwLock) -> i32 {
+    if p.is_null() {
+        return EINVAL;
+    }
+
+    // We cannot differentiate between reads an writes in unlock and therefore
+    // always use a write-lock. Unwinding isn't really in the hot path anyway.
+    unsafe { (*p).write() };
+    return 0;
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn __rust_rwlock_wrlock(p: *mut RwLock) -> i32 {
+    if p.is_null() {
+        return EINVAL;
+    }
+    unsafe { (*p).write() };
+    return 0;
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn __rust_rwlock_unlock(p: *mut RwLock) -> i32 {
+    if p.is_null() {
+        return EINVAL;
+    }
+    unsafe { (*p).write_unlock() };
+    return 0;
+}
diff --git a/library/std/src/sys/pal/sgx/mod.rs b/library/std/src/sys/pal/sgx/mod.rs
index 76f930b86f2..d30976ec151 100644
--- a/library/std/src/sys/pal/sgx/mod.rs
+++ b/library/std/src/sys/pal/sgx/mod.rs
@@ -17,6 +17,7 @@ pub mod fd;
 pub mod fs;
 #[path = "../unsupported/io.rs"]
 pub mod io;
+mod libunwind_integration;
 pub mod net;
 pub mod os;
 #[path = "../unsupported/pipe.rs"]
diff --git a/library/std/src/sys/pal/sgx/waitqueue/mod.rs b/library/std/src/sys/pal/sgx/waitqueue/mod.rs
index 2d952b7ebbc..f5668a9493f 100644
--- a/library/std/src/sys/pal/sgx/waitqueue/mod.rs
+++ b/library/std/src/sys/pal/sgx/waitqueue/mod.rs
@@ -52,10 +52,6 @@ impl<T> WaitVariable<T> {
         WaitVariable { queue: WaitQueue::new(), lock: var }
     }
 
-    pub fn queue_empty(&self) -> bool {
-        self.queue.is_empty()
-    }
-
     pub fn lock_var(&self) -> &T {
         &self.lock
     }
@@ -68,7 +64,7 @@ impl<T> WaitVariable<T> {
 #[derive(Copy, Clone)]
 pub enum NotifiedTcs {
     Single(Tcs),
-    All { count: NonZero<usize> },
+    All { _count: NonZero<usize> },
 }
 
 /// An RAII guard that will notify a set of target threads as well as unlock
@@ -98,19 +94,6 @@ impl Default for WaitQueue {
     }
 }
 
-impl<'a, T> WaitGuard<'a, T> {
-    /// Returns which TCSes will be notified when this guard drops.
-    pub fn notified_tcs(&self) -> NotifiedTcs {
-        self.notified_tcs
-    }
-
-    /// Drop this `WaitGuard`, after dropping another `guard`.
-    pub fn drop_after<U>(self, guard: U) {
-        drop(guard);
-        drop(self);
-    }
-}
-
 impl<'a, T> Deref for WaitGuard<'a, T> {
     type Target = SpinMutexGuard<'a, WaitVariable<T>>;
 
@@ -141,10 +124,6 @@ impl WaitQueue {
         WaitQueue { inner: UnsafeList::new() }
     }
 
-    pub fn is_empty(&self) -> bool {
-        self.inner.is_empty()
-    }
-
     /// Adds the calling thread to the `WaitVariable`'s wait queue, then wait
     /// until a wakeup event.
     ///
@@ -253,7 +232,10 @@ impl WaitQueue {
             }
 
             if let Some(count) = NonZero::new(count) {
-                Ok(WaitGuard { mutex_guard: Some(guard), notified_tcs: NotifiedTcs::All { count } })
+                Ok(WaitGuard {
+                    mutex_guard: Some(guard),
+                    notified_tcs: NotifiedTcs::All { _count: count },
+                })
             } else {
                 Err(guard)
             }
diff --git a/library/std/src/sys/pal/unix/process/process_unix.rs b/library/std/src/sys/pal/unix/process/process_unix.rs
index e798510f9e6..d65657790c4 100644
--- a/library/std/src/sys/pal/unix/process/process_unix.rs
+++ b/library/std/src/sys/pal/unix/process/process_unix.rs
@@ -11,18 +11,6 @@ use crate::os::linux::process::PidFd;
 #[cfg(target_os = "linux")]
 use crate::os::unix::io::AsRawFd;
 
-#[cfg(any(
-    target_os = "macos",
-    target_os = "watchos",
-    target_os = "visionos",
-    target_os = "tvos",
-    target_os = "freebsd",
-    all(target_os = "linux", target_env = "gnu"),
-    all(target_os = "linux", target_env = "musl"),
-    target_os = "nto",
-))]
-use crate::sys::weak::weak;
-
 #[cfg(target_os = "vxworks")]
 use libc::RTP_ID as pid_t;
 
@@ -466,6 +454,7 @@ impl Command {
         envp: Option<&CStringArray>,
     ) -> io::Result<Option<Process>> {
         use crate::mem::MaybeUninit;
+        use crate::sys::weak::weak;
         use crate::sys::{self, cvt_nz, unix_sigpipe_attr_specified};
 
         if self.get_gid().is_some()
diff --git a/library/std/src/sys/sync/rwlock/mod.rs b/library/std/src/sys/sync/rwlock/mod.rs
index 675931c64bd..70ba6bf38ef 100644
--- a/library/std/src/sys/sync/rwlock/mod.rs
+++ b/library/std/src/sys/sync/rwlock/mod.rs
@@ -12,24 +12,20 @@ cfg_if::cfg_if! {
     ))] {
         mod futex;
         pub use futex::RwLock;
-    } else if #[cfg(target_family = "unix")] {
+    } else if #[cfg(any(
+        target_family = "unix",
+        all(target_os = "windows", target_vendor = "win7"),
+        all(target_vendor = "fortanix", target_env = "sgx"),
+        target_os = "xous",
+    ))] {
         mod queue;
         pub use queue::RwLock;
-    } else if #[cfg(all(target_os = "windows", target_vendor = "win7"))] {
-        mod windows7;
-        pub use windows7::RwLock;
-    } else if #[cfg(all(target_vendor = "fortanix", target_env = "sgx"))] {
-        mod sgx;
-        pub use sgx::RwLock;
     } else if #[cfg(target_os = "solid_asp3")] {
         mod solid;
         pub use solid::RwLock;
     } else if #[cfg(target_os = "teeos")] {
         mod teeos;
         pub use teeos::RwLock;
-    } else if #[cfg(target_os = "xous")] {
-        mod xous;
-        pub use xous::RwLock;
     } else {
         mod no_threads;
         pub use no_threads::RwLock;
diff --git a/library/std/src/sys/sync/rwlock/sgx.rs b/library/std/src/sys/sync/rwlock/sgx.rs
deleted file mode 100644
index 136dea597bb..00000000000
--- a/library/std/src/sys/sync/rwlock/sgx.rs
+++ /dev/null
@@ -1,219 +0,0 @@
-#[cfg(test)]
-mod tests;
-
-use crate::alloc::Layout;
-use crate::num::NonZero;
-use crate::sys::pal::waitqueue::{
-    try_lock_or_false, NotifiedTcs, SpinMutex, SpinMutexGuard, WaitQueue, WaitVariable,
-};
-use crate::sys_common::lazy_box::{LazyBox, LazyInit};
-
-struct AllocatedRwLock {
-    readers: SpinMutex<WaitVariable<Option<NonZero<usize>>>>,
-    writer: SpinMutex<WaitVariable<bool>>,
-}
-
-pub struct RwLock {
-    inner: LazyBox<AllocatedRwLock>,
-}
-
-impl LazyInit for AllocatedRwLock {
-    fn init() -> Box<Self> {
-        Box::new(AllocatedRwLock {
-            readers: SpinMutex::new(WaitVariable::new(None)),
-            writer: SpinMutex::new(WaitVariable::new(false)),
-        })
-    }
-}
-
-// Check at compile time that RwLock's size and alignment matches the C definition
-// in libunwind (see also `test_c_rwlock_initializer` in `tests`).
-const _: () = {
-    let rust = Layout::new::<RwLock>();
-    let c = Layout::new::<*mut ()>();
-    assert!(rust.size() == c.size());
-    assert!(rust.align() == c.align());
-};
-
-impl RwLock {
-    pub const fn new() -> RwLock {
-        RwLock { inner: LazyBox::new() }
-    }
-
-    #[inline]
-    pub fn read(&self) {
-        let lock = &*self.inner;
-        let mut rguard = lock.readers.lock();
-        let wguard = lock.writer.lock();
-        if *wguard.lock_var() || !wguard.queue_empty() {
-            // Another thread has or is waiting for the write lock, wait
-            drop(wguard);
-            WaitQueue::wait(rguard, || {});
-        // Another thread has passed the lock to us
-        } else {
-            // No waiting writers, acquire the read lock
-            *rguard.lock_var_mut() = NonZero::new(rguard.lock_var().map_or(0, |n| n.get()) + 1);
-        }
-    }
-
-    #[inline]
-    pub unsafe fn try_read(&self) -> bool {
-        let lock = &*self.inner;
-        let mut rguard = try_lock_or_false!(lock.readers);
-        let wguard = try_lock_or_false!(lock.writer);
-        if *wguard.lock_var() || !wguard.queue_empty() {
-            // Another thread has or is waiting for the write lock
-            false
-        } else {
-            // No waiting writers, acquire the read lock
-            *rguard.lock_var_mut() = NonZero::new(rguard.lock_var().map_or(0, |n| n.get()) + 1);
-            true
-        }
-    }
-
-    #[inline]
-    pub fn write(&self) {
-        let lock = &*self.inner;
-        let rguard = lock.readers.lock();
-        let mut wguard = lock.writer.lock();
-        if *wguard.lock_var() || rguard.lock_var().is_some() {
-            // Another thread has the lock, wait
-            drop(rguard);
-            WaitQueue::wait(wguard, || {});
-        // Another thread has passed the lock to us
-        } else {
-            // We are just now obtaining the lock
-            *wguard.lock_var_mut() = true;
-        }
-    }
-
-    #[inline]
-    pub fn try_write(&self) -> bool {
-        let lock = &*self.inner;
-        let rguard = try_lock_or_false!(lock.readers);
-        let mut wguard = try_lock_or_false!(lock.writer);
-        if *wguard.lock_var() || rguard.lock_var().is_some() {
-            // Another thread has the lock
-            false
-        } else {
-            // We are just now obtaining the lock
-            *wguard.lock_var_mut() = true;
-            true
-        }
-    }
-
-    #[inline]
-    unsafe fn __read_unlock(
-        &self,
-        mut rguard: SpinMutexGuard<'_, WaitVariable<Option<NonZero<usize>>>>,
-        wguard: SpinMutexGuard<'_, WaitVariable<bool>>,
-    ) {
-        *rguard.lock_var_mut() = NonZero::new(rguard.lock_var().unwrap().get() - 1);
-        if rguard.lock_var().is_some() {
-            // There are other active readers
-        } else {
-            if let Ok(mut wguard) = WaitQueue::notify_one(wguard) {
-                // A writer was waiting, pass the lock
-                *wguard.lock_var_mut() = true;
-                wguard.drop_after(rguard);
-            } else {
-                // No writers were waiting, the lock is released
-                rtassert!(rguard.queue_empty());
-            }
-        }
-    }
-
-    #[inline]
-    pub unsafe fn read_unlock(&self) {
-        let lock = &*self.inner;
-        let rguard = lock.readers.lock();
-        let wguard = lock.writer.lock();
-        unsafe { self.__read_unlock(rguard, wguard) };
-    }
-
-    #[inline]
-    unsafe fn __write_unlock(
-        &self,
-        rguard: SpinMutexGuard<'_, WaitVariable<Option<NonZero<usize>>>>,
-        wguard: SpinMutexGuard<'_, WaitVariable<bool>>,
-    ) {
-        match WaitQueue::notify_one(wguard) {
-            Err(mut wguard) => {
-                // No writers waiting, release the write lock
-                *wguard.lock_var_mut() = false;
-                if let Ok(mut rguard) = WaitQueue::notify_all(rguard) {
-                    // One or more readers were waiting, pass the lock to them
-                    if let NotifiedTcs::All { count } = rguard.notified_tcs() {
-                        *rguard.lock_var_mut() = Some(count)
-                    } else {
-                        unreachable!() // called notify_all
-                    }
-                    rguard.drop_after(wguard);
-                } else {
-                    // No readers waiting, the lock is released
-                }
-            }
-            Ok(wguard) => {
-                // There was a thread waiting for write, just pass the lock
-                wguard.drop_after(rguard);
-            }
-        }
-    }
-
-    #[inline]
-    pub unsafe fn write_unlock(&self) {
-        let lock = &*self.inner;
-        let rguard = lock.readers.lock();
-        let wguard = lock.writer.lock();
-        unsafe { self.__write_unlock(rguard, wguard) };
-    }
-
-    // only used by __rust_rwlock_unlock below
-    #[inline]
-    #[cfg_attr(test, allow(dead_code))]
-    unsafe fn unlock(&self) {
-        let lock = &*self.inner;
-        let rguard = lock.readers.lock();
-        let wguard = lock.writer.lock();
-        if *wguard.lock_var() == true {
-            unsafe { self.__write_unlock(rguard, wguard) };
-        } else {
-            unsafe { self.__read_unlock(rguard, wguard) };
-        }
-    }
-}
-
-// The following functions are needed by libunwind. These symbols are named
-// in pre-link args for the target specification, so keep that in sync.
-#[cfg(not(test))]
-const EINVAL: i32 = 22;
-
-#[cfg(not(test))]
-#[no_mangle]
-pub unsafe extern "C" fn __rust_rwlock_rdlock(p: *mut RwLock) -> i32 {
-    if p.is_null() {
-        return EINVAL;
-    }
-    unsafe { (*p).read() };
-    return 0;
-}
-
-#[cfg(not(test))]
-#[no_mangle]
-pub unsafe extern "C" fn __rust_rwlock_wrlock(p: *mut RwLock) -> i32 {
-    if p.is_null() {
-        return EINVAL;
-    }
-    unsafe { (*p).write() };
-    return 0;
-}
-
-#[cfg(not(test))]
-#[no_mangle]
-pub unsafe extern "C" fn __rust_rwlock_unlock(p: *mut RwLock) -> i32 {
-    if p.is_null() {
-        return EINVAL;
-    }
-    unsafe { (*p).unlock() };
-    return 0;
-}
diff --git a/library/std/src/sys/sync/rwlock/sgx/tests.rs b/library/std/src/sys/sync/rwlock/sgx/tests.rs
deleted file mode 100644
index 5fd6670afd4..00000000000
--- a/library/std/src/sys/sync/rwlock/sgx/tests.rs
+++ /dev/null
@@ -1,21 +0,0 @@
-use super::*;
-use crate::ptr;
-
-// Verify that the byte pattern libunwind uses to initialize an RwLock is
-// equivalent to the value of RwLock::new(). If the value changes,
-// `src/UnwindRustSgx.h` in libunwind needs to be changed too.
-#[test]
-fn test_c_rwlock_initializer() {
-    const C_RWLOCK_INIT: *mut () = ptr::null_mut();
-
-    // For the test to work, we need the padding/unused bytes in RwLock to be
-    // initialized as 0. In practice, this is the case with statics.
-    static RUST_RWLOCK_INIT: RwLock = RwLock::new();
-
-    unsafe {
-        // If the assertion fails, that not necessarily an issue with the value
-        // of C_RWLOCK_INIT. It might just be an issue with the way padding
-        // bytes are initialized in the test code.
-        assert_eq!(crate::mem::transmute_copy::<_, *mut ()>(&RUST_RWLOCK_INIT), C_RWLOCK_INIT);
-    };
-}
diff --git a/library/std/src/sys/sync/rwlock/windows7.rs b/library/std/src/sys/sync/rwlock/windows7.rs
deleted file mode 100644
index e69415baac4..00000000000
--- a/library/std/src/sys/sync/rwlock/windows7.rs
+++ /dev/null
@@ -1,40 +0,0 @@
-use crate::cell::UnsafeCell;
-use crate::sys::c;
-
-pub struct RwLock {
-    inner: UnsafeCell<c::SRWLOCK>,
-}
-
-unsafe impl Send for RwLock {}
-unsafe impl Sync for RwLock {}
-
-impl RwLock {
-    #[inline]
-    pub const fn new() -> RwLock {
-        RwLock { inner: UnsafeCell::new(c::SRWLOCK_INIT) }
-    }
-    #[inline]
-    pub fn read(&self) {
-        unsafe { c::AcquireSRWLockShared(self.inner.get()) }
-    }
-    #[inline]
-    pub fn try_read(&self) -> bool {
-        unsafe { c::TryAcquireSRWLockShared(self.inner.get()) != 0 }
-    }
-    #[inline]
-    pub fn write(&self) {
-        unsafe { c::AcquireSRWLockExclusive(self.inner.get()) }
-    }
-    #[inline]
-    pub fn try_write(&self) -> bool {
-        unsafe { c::TryAcquireSRWLockExclusive(self.inner.get()) != 0 }
-    }
-    #[inline]
-    pub unsafe fn read_unlock(&self) {
-        c::ReleaseSRWLockShared(self.inner.get())
-    }
-    #[inline]
-    pub unsafe fn write_unlock(&self) {
-        c::ReleaseSRWLockExclusive(self.inner.get())
-    }
-}
diff --git a/library/std/src/sys/sync/rwlock/xous.rs b/library/std/src/sys/sync/rwlock/xous.rs
deleted file mode 100644
index ab45b33e1f6..00000000000
--- a/library/std/src/sys/sync/rwlock/xous.rs
+++ /dev/null
@@ -1,74 +0,0 @@
-use crate::sync::atomic::{AtomicIsize, Ordering::Acquire};
-use crate::thread::yield_now;
-
-pub struct RwLock {
-    /// The "mode" value indicates how many threads are waiting on this
-    /// Mutex. Possible values are:
-    ///    -1: The lock is locked for writing
-    ///     0: The lock is unlocked
-    ///   >=1: The lock is locked for reading
-    ///
-    /// This currently spins waiting for the lock to be freed. An
-    /// optimization would be to involve the ticktimer server to
-    /// coordinate unlocks.
-    mode: AtomicIsize,
-}
-
-const RWLOCK_WRITING: isize = -1;
-const RWLOCK_FREE: isize = 0;
-
-unsafe impl Send for RwLock {}
-unsafe impl Sync for RwLock {}
-
-impl RwLock {
-    #[inline]
-    #[rustc_const_stable(feature = "const_locks", since = "1.63.0")]
-    pub const fn new() -> RwLock {
-        RwLock { mode: AtomicIsize::new(RWLOCK_FREE) }
-    }
-
-    #[inline]
-    pub unsafe fn read(&self) {
-        while !unsafe { self.try_read() } {
-            yield_now();
-        }
-    }
-
-    #[inline]
-    pub unsafe fn try_read(&self) -> bool {
-        self.mode
-            .fetch_update(
-                Acquire,
-                Acquire,
-                |v| if v == RWLOCK_WRITING { None } else { Some(v + 1) },
-            )
-            .is_ok()
-    }
-
-    #[inline]
-    pub unsafe fn write(&self) {
-        while !unsafe { self.try_write() } {
-            yield_now();
-        }
-    }
-
-    #[inline]
-    pub unsafe fn try_write(&self) -> bool {
-        self.mode.compare_exchange(RWLOCK_FREE, RWLOCK_WRITING, Acquire, Acquire).is_ok()
-    }
-
-    #[inline]
-    pub unsafe fn read_unlock(&self) {
-        let previous = self.mode.fetch_sub(1, Acquire);
-        assert!(previous != RWLOCK_FREE);
-        assert!(previous != RWLOCK_WRITING);
-    }
-
-    #[inline]
-    pub unsafe fn write_unlock(&self) {
-        assert_eq!(
-            self.mode.compare_exchange(RWLOCK_WRITING, RWLOCK_FREE, Acquire, Acquire),
-            Ok(RWLOCK_WRITING)
-        );
-    }
-}
diff --git a/src/bootstrap/src/bin/main.rs b/src/bootstrap/src/bin/main.rs
index 340a5c87f0b..4cb67b7aa62 100644
--- a/src/bootstrap/src/bin/main.rs
+++ b/src/bootstrap/src/bin/main.rs
@@ -131,10 +131,6 @@ fn main() {
 fn check_version(config: &Config) -> Option<String> {
     let mut msg = String::new();
 
-    if config.changelog_seen.is_some() {
-        msg.push_str("WARNING: The use of `changelog-seen` is deprecated. Please refer to `change-id` option in `config.example.toml` instead.\n");
-    }
-
     let latest_change_id = CONFIG_CHANGE_HISTORY.last().unwrap().change_id;
     let warned_id_path = config.out.join("bootstrap").join(".last-warned-change-id");
 
diff --git a/src/bootstrap/src/core/build_steps/check.rs b/src/bootstrap/src/core/build_steps/check.rs
index 37d91b14ca1..927d72e8ccb 100644
--- a/src/bootstrap/src/core/build_steps/check.rs
+++ b/src/bootstrap/src/core/build_steps/check.rs
@@ -11,6 +11,16 @@ use crate::core::config::TargetSelection;
 use crate::{Compiler, Mode, Subcommand};
 use std::path::{Path, PathBuf};
 
+pub fn cargo_subcommand(kind: Kind) -> &'static str {
+    match kind {
+        Kind::Check
+        // We ensure check steps for both std and rustc from build_steps/clippy, so handle `Kind::Clippy` as well.
+        | Kind::Clippy => "check",
+        Kind::Fix => "fix",
+        _ => unreachable!(),
+    }
+}
+
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
 pub struct Std {
     pub target: TargetSelection,
@@ -22,97 +32,6 @@ pub struct Std {
     crates: Vec<String>,
 }
 
-/// Returns args for the subcommand itself (not for cargo)
-fn args(builder: &Builder<'_>) -> Vec<String> {
-    fn strings<'a>(arr: &'a [&str]) -> impl Iterator<Item = String> + 'a {
-        arr.iter().copied().map(String::from)
-    }
-
-    if let Subcommand::Clippy { fix, allow_dirty, allow_staged, allow, deny, warn, forbid } =
-        &builder.config.cmd
-    {
-        // disable the most spammy clippy lints
-        let ignored_lints = [
-            "many_single_char_names", // there are a lot in stdarch
-            "collapsible_if",
-            "type_complexity",
-            "missing_safety_doc", // almost 3K warnings
-            "too_many_arguments",
-            "needless_lifetimes", // people want to keep the lifetimes
-            "wrong_self_convention",
-        ];
-        let mut args = vec![];
-        if *fix {
-            #[rustfmt::skip]
-            args.extend(strings(&[
-                "--fix", "-Zunstable-options",
-                // FIXME: currently, `--fix` gives an error while checking tests for libtest,
-                // possibly because libtest is not yet built in the sysroot.
-                // As a workaround, avoid checking tests and benches when passed --fix.
-                "--lib", "--bins", "--examples",
-            ]));
-
-            if *allow_dirty {
-                args.push("--allow-dirty".to_owned());
-            }
-
-            if *allow_staged {
-                args.push("--allow-staged".to_owned());
-            }
-        }
-
-        args.extend(strings(&["--"]));
-
-        if deny.is_empty() && forbid.is_empty() {
-            args.extend(strings(&["--cap-lints", "warn"]));
-        }
-
-        let all_args = std::env::args().collect::<Vec<_>>();
-        args.extend(get_clippy_rules_in_order(&all_args, allow, deny, warn, forbid));
-
-        args.extend(ignored_lints.iter().map(|lint| format!("-Aclippy::{}", lint)));
-        args.extend(builder.config.free_args.clone());
-        args
-    } else {
-        builder.config.free_args.clone()
-    }
-}
-
-/// We need to keep the order of the given clippy lint rules before passing them.
-/// Since clap doesn't offer any useful interface for this purpose out of the box,
-/// we have to handle it manually.
-pub(crate) fn get_clippy_rules_in_order(
-    all_args: &[String],
-    allow_rules: &[String],
-    deny_rules: &[String],
-    warn_rules: &[String],
-    forbid_rules: &[String],
-) -> Vec<String> {
-    let mut result = vec![];
-
-    for (prefix, item) in
-        [("-A", allow_rules), ("-D", deny_rules), ("-W", warn_rules), ("-F", forbid_rules)]
-    {
-        item.iter().for_each(|v| {
-            let rule = format!("{prefix}{v}");
-            let position = all_args.iter().position(|t| t == &rule).unwrap();
-            result.push((position, rule));
-        });
-    }
-
-    result.sort_by_key(|&(position, _)| position);
-    result.into_iter().map(|v| v.1).collect()
-}
-
-fn cargo_subcommand(kind: Kind) -> &'static str {
-    match kind {
-        Kind::Check => "check",
-        Kind::Clippy => "clippy",
-        Kind::Fix => "fix",
-        _ => unreachable!(),
-    }
-}
-
 impl Std {
     pub fn new(target: TargetSelection) -> Self {
         Self { target, crates: vec![] }
@@ -164,7 +83,7 @@ impl Step for Std {
         run_cargo(
             builder,
             cargo,
-            args(builder),
+            builder.config.free_args.clone(),
             &libstd_stamp(builder, compiler, target),
             vec![],
             true,
@@ -221,7 +140,7 @@ impl Step for Std {
         run_cargo(
             builder,
             cargo,
-            args(builder),
+            builder.config.free_args.clone(),
             &libstd_test_stamp(builder, compiler, target),
             vec![],
             true,
@@ -318,7 +237,7 @@ impl Step for Rustc {
         run_cargo(
             builder,
             cargo,
-            args(builder),
+            builder.config.free_args.clone(),
             &librustc_stamp(builder, compiler, target),
             vec![],
             true,
@@ -384,7 +303,7 @@ impl Step for CodegenBackend {
         run_cargo(
             builder,
             cargo,
-            args(builder),
+            builder.config.free_args.clone(),
             &codegen_backend_stamp(builder, compiler, target, backend),
             vec![],
             true,
@@ -450,7 +369,7 @@ impl Step for RustAnalyzer {
         run_cargo(
             builder,
             cargo,
-            args(builder),
+            builder.config.free_args.clone(),
             &stamp(builder, compiler, target),
             vec![],
             true,
@@ -513,7 +432,7 @@ macro_rules! tool_check_step {
                 run_cargo(
                     builder,
                     cargo,
-                    args(builder),
+                    builder.config.free_args.clone(),
                     &stamp(builder, compiler, target),
                     vec![],
                     true,
diff --git a/src/bootstrap/src/core/build_steps/clippy.rs b/src/bootstrap/src/core/build_steps/clippy.rs
new file mode 100644
index 00000000000..33323ec1e5d
--- /dev/null
+++ b/src/bootstrap/src/core/build_steps/clippy.rs
@@ -0,0 +1,330 @@
+//! Implementation of running clippy on the compiler, standard library and various tools.
+
+use std::path::Path;
+
+use crate::builder::Builder;
+use crate::builder::ShouldRun;
+use crate::core::builder;
+use crate::core::builder::crate_description;
+use crate::core::builder::Alias;
+use crate::core::builder::Kind;
+use crate::core::builder::RunConfig;
+use crate::core::builder::Step;
+use crate::Mode;
+use crate::Subcommand;
+use crate::TargetSelection;
+
+use super::check;
+use super::compile;
+use super::compile::librustc_stamp;
+use super::compile::libstd_stamp;
+use super::compile::run_cargo;
+use super::compile::rustc_cargo;
+use super::compile::std_cargo;
+use super::tool::prepare_tool_cargo;
+use super::tool::SourceType;
+
+// Disable the most spammy clippy lints
+const IGNORED_RULES_FOR_STD_AND_RUSTC: &[&str] = &[
+    "many_single_char_names", // there are a lot in stdarch
+    "collapsible_if",
+    "type_complexity",
+    "missing_safety_doc", // almost 3K warnings
+    "too_many_arguments",
+    "needless_lifetimes", // people want to keep the lifetimes
+    "wrong_self_convention",
+];
+
+fn lint_args(builder: &Builder<'_>, ignored_rules: &[&str]) -> Vec<String> {
+    fn strings<'a>(arr: &'a [&str]) -> impl Iterator<Item = String> + 'a {
+        arr.iter().copied().map(String::from)
+    }
+
+    let Subcommand::Clippy { fix, allow_dirty, allow_staged, allow, deny, warn, forbid } =
+        &builder.config.cmd
+    else {
+        unreachable!("clippy::lint_args can only be called from `clippy` subcommands.");
+    };
+
+    let mut args = vec![];
+    if *fix {
+        #[rustfmt::skip]
+            args.extend(strings(&[
+                "--fix", "-Zunstable-options",
+                // FIXME: currently, `--fix` gives an error while checking tests for libtest,
+                // possibly because libtest is not yet built in the sysroot.
+                // As a workaround, avoid checking tests and benches when passed --fix.
+                "--lib", "--bins", "--examples",
+            ]));
+
+        if *allow_dirty {
+            args.push("--allow-dirty".to_owned());
+        }
+
+        if *allow_staged {
+            args.push("--allow-staged".to_owned());
+        }
+    }
+
+    args.extend(strings(&["--"]));
+
+    if deny.is_empty() && forbid.is_empty() {
+        args.extend(strings(&["--cap-lints", "warn"]));
+    }
+
+    let all_args = std::env::args().collect::<Vec<_>>();
+    args.extend(get_clippy_rules_in_order(&all_args, allow, deny, warn, forbid));
+
+    args.extend(ignored_rules.iter().map(|lint| format!("-Aclippy::{}", lint)));
+    args.extend(builder.config.free_args.clone());
+    args
+}
+
+/// We need to keep the order of the given clippy lint rules before passing them.
+/// Since clap doesn't offer any useful interface for this purpose out of the box,
+/// we have to handle it manually.
+pub(crate) fn get_clippy_rules_in_order(
+    all_args: &[String],
+    allow_rules: &[String],
+    deny_rules: &[String],
+    warn_rules: &[String],
+    forbid_rules: &[String],
+) -> Vec<String> {
+    let mut result = vec![];
+
+    for (prefix, item) in
+        [("-A", allow_rules), ("-D", deny_rules), ("-W", warn_rules), ("-F", forbid_rules)]
+    {
+        item.iter().for_each(|v| {
+            let rule = format!("{prefix}{v}");
+            let position = all_args.iter().position(|t| t == &rule).unwrap();
+            result.push((position, rule));
+        });
+    }
+
+    result.sort_by_key(|&(position, _)| position);
+    result.into_iter().map(|v| v.1).collect()
+}
+
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct Std {
+    pub target: TargetSelection,
+    /// Whether to lint only a subset of crates.
+    crates: Vec<String>,
+}
+
+impl Step for Std {
+    type Output = ();
+    const DEFAULT: bool = true;
+
+    fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
+        run.crate_or_deps("sysroot").path("library")
+    }
+
+    fn make_run(run: RunConfig<'_>) {
+        let crates = run.make_run_crates(Alias::Library);
+        run.builder.ensure(Std { target: run.target, crates });
+    }
+
+    fn run(self, builder: &Builder<'_>) {
+        builder.update_submodule(&Path::new("library").join("stdarch"));
+
+        let target = self.target;
+        let compiler = builder.compiler(builder.top_stage, builder.config.build);
+
+        let mut cargo =
+            builder::Cargo::new(builder, compiler, Mode::Std, SourceType::InTree, target, "clippy");
+
+        std_cargo(builder, target, compiler.stage, &mut cargo);
+
+        for krate in &*self.crates {
+            cargo.arg("-p").arg(krate);
+        }
+
+        let _guard =
+            builder.msg_clippy(format_args!("library{}", crate_description(&self.crates)), target);
+
+        run_cargo(
+            builder,
+            cargo,
+            lint_args(builder, IGNORED_RULES_FOR_STD_AND_RUSTC),
+            &libstd_stamp(builder, compiler, target),
+            vec![],
+            true,
+            false,
+        );
+    }
+}
+
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct Rustc {
+    pub target: TargetSelection,
+    /// Whether to lint only a subset of crates.
+    crates: Vec<String>,
+}
+
+impl Step for Rustc {
+    type Output = ();
+    const ONLY_HOSTS: bool = true;
+    const DEFAULT: bool = true;
+
+    fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
+        run.crate_or_deps("rustc-main").path("compiler")
+    }
+
+    fn make_run(run: RunConfig<'_>) {
+        let crates = run.make_run_crates(Alias::Compiler);
+        run.builder.ensure(Rustc { target: run.target, crates });
+    }
+
+    /// Lints the compiler.
+    ///
+    /// This will lint the compiler for a particular stage of the build using
+    /// the `compiler` targeting the `target` architecture.
+    fn run(self, builder: &Builder<'_>) {
+        let compiler = builder.compiler(builder.top_stage, builder.config.build);
+        let target = self.target;
+
+        if compiler.stage != 0 {
+            // If we're not in stage 0, then we won't have a std from the beta
+            // compiler around. That means we need to make sure there's one in
+            // the sysroot for the compiler to find. Otherwise, we're going to
+            // fail when building crates that need to generate code (e.g., build
+            // scripts and their dependencies).
+            builder.ensure(compile::Std::new(compiler, compiler.host));
+            builder.ensure(compile::Std::new(compiler, target));
+        } else {
+            builder.ensure(check::Std::new(target));
+        }
+
+        let mut cargo = builder::Cargo::new(
+            builder,
+            compiler,
+            Mode::Rustc,
+            SourceType::InTree,
+            target,
+            "clippy",
+        );
+
+        rustc_cargo(builder, &mut cargo, target, &compiler);
+
+        // Explicitly pass -p for all compiler crates -- this will force cargo
+        // to also lint the tests/benches/examples for these crates, rather
+        // than just the leaf crate.
+        for krate in &*self.crates {
+            cargo.arg("-p").arg(krate);
+        }
+
+        let _guard =
+            builder.msg_clippy(format_args!("compiler{}", crate_description(&self.crates)), target);
+
+        run_cargo(
+            builder,
+            cargo,
+            lint_args(builder, IGNORED_RULES_FOR_STD_AND_RUSTC),
+            &librustc_stamp(builder, compiler, target),
+            vec![],
+            true,
+            false,
+        );
+    }
+}
+
+macro_rules! lint_any {
+    ($(
+        $name:ident, $path:expr, $readable_name:expr
+        $(,lint_by_default = $lint_by_default:expr)*
+        ;
+    )+) => {
+        $(
+
+        #[derive(Debug, Clone, Hash, PartialEq, Eq)]
+        pub struct $name {
+            pub target: TargetSelection,
+        }
+
+        impl Step for $name {
+            type Output = ();
+            const DEFAULT: bool = if false $(|| $lint_by_default)* { true } else { false };
+
+            fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
+                run.path($path)
+            }
+
+            fn make_run(run: RunConfig<'_>) {
+                run.builder.ensure($name {
+                    target: run.target,
+                });
+            }
+
+            fn run(self, builder: &Builder<'_>) -> Self::Output {
+                let compiler = builder.compiler(builder.top_stage, builder.config.build);
+                let target = self.target;
+
+                builder.ensure(check::Rustc::new(target, builder));
+
+                let cargo = prepare_tool_cargo(
+                    builder,
+                    compiler,
+                    Mode::ToolRustc,
+                    target,
+                    "clippy",
+                    $path,
+                    SourceType::InTree,
+                    &[],
+                );
+
+                let _guard = builder.msg_tool(
+                    Kind::Clippy,
+                    Mode::ToolRustc,
+                    $readable_name,
+                    compiler.stage,
+                    &compiler.host,
+                    &target,
+                );
+
+                let stamp = builder
+                    .cargo_out(compiler, Mode::ToolRustc, target)
+                    .join(format!(".{}-check.stamp", stringify!($name).to_lowercase()));
+
+                run_cargo(
+                    builder,
+                    cargo,
+                    lint_args(builder, &[]),
+                    &stamp,
+                    vec![],
+                    true,
+                    false,
+                );
+            }
+        }
+        )+
+    }
+}
+
+lint_any!(
+    Bootstrap, "src/bootstrap", "bootstrap";
+    BuildHelper, "src/tools/build_helper", "build_helper";
+    BuildManifest, "src/tools/build-manifest", "build-manifest";
+    CargoMiri, "src/tools/miri/cargo-miri", "cargo-miri";
+    Clippy, "src/tools/clippy", "clippy";
+    CollectLicenseMetadata, "src/tools/collect-license-metadata", "collect-license-metadata";
+    Compiletest, "src/tools/compiletest", "compiletest";
+    CoverageDump, "src/tools/coverage-dump", "coverage-dump";
+    Jsondocck, "src/tools/jsondocck", "jsondocck";
+    Jsondoclint, "src/tools/jsondoclint", "jsondoclint";
+    LintDocs, "src/tools/lint-docs", "lint-docs";
+    LlvmBitcodeLinker, "src/tools/llvm-bitcode-linker", "llvm-bitcode-linker";
+    Miri, "src/tools/miri", "miri";
+    MiroptTestTools, "src/tools/miropt-test-tools", "miropt-test-tools";
+    OptDist, "src/tools/opt-dist", "opt-dist";
+    RemoteTestClient, "src/tools/remote-test-client", "remote-test-client";
+    RemoteTestServer, "src/tools/remote-test-server", "remote-test-server";
+    Rls, "src/tools/rls", "rls";
+    RustAnalyzer, "src/tools/rust-analyzer", "rust-analyzer";
+    RustDemangler, "src/tools/rust-demangler", "rust-demangler";
+    Rustdoc, "src/tools/rustdoc", "clippy";
+    Rustfmt, "src/tools/rustfmt", "rustfmt";
+    RustInstaller, "src/tools/rust-installer", "rust-installer";
+    Tidy, "src/tools/tidy", "tidy";
+);
diff --git a/src/bootstrap/src/core/build_steps/llvm.rs b/src/bootstrap/src/core/build_steps/llvm.rs
index 420336fee14..7cb15fe5590 100644
--- a/src/bootstrap/src/core/build_steps/llvm.rs
+++ b/src/bootstrap/src/core/build_steps/llvm.rs
@@ -76,6 +76,9 @@ pub fn prebuilt_llvm_config(
     builder: &Builder<'_>,
     target: TargetSelection,
 ) -> Result<LlvmResult, Meta> {
+    // If we have llvm submodule initialized already, sync it.
+    builder.update_existing_submodule(&Path::new("src").join("llvm-project"));
+
     builder.config.maybe_download_ci_llvm();
 
     // If we're using a custom LLVM bail out here, but we can only use a
@@ -94,6 +97,9 @@ pub fn prebuilt_llvm_config(
         }
     }
 
+    // Initialize the llvm submodule if not initialized already.
+    builder.update_submodule(&Path::new("src").join("llvm-project"));
+
     let root = "src/llvm-project/llvm";
     let out_dir = builder.llvm_out(target);
 
@@ -280,7 +286,6 @@ impl Step for Llvm {
             Err(m) => m,
         };
 
-        builder.update_submodule(&Path::new("src").join("llvm-project"));
         if builder.llvm_link_shared() && target.is_windows() {
             panic!("shared linking to LLVM is not currently supported on {}", target.triple);
         }
diff --git a/src/bootstrap/src/core/build_steps/mod.rs b/src/bootstrap/src/core/build_steps/mod.rs
index 50d83789be8..9b7378165de 100644
--- a/src/bootstrap/src/core/build_steps/mod.rs
+++ b/src/bootstrap/src/core/build_steps/mod.rs
@@ -1,5 +1,6 @@
 pub(crate) mod check;
 pub(crate) mod clean;
+pub(crate) mod clippy;
 pub(crate) mod compile;
 pub(crate) mod dist;
 pub(crate) mod doc;
diff --git a/src/bootstrap/src/core/build_steps/tool.rs b/src/bootstrap/src/core/build_steps/tool.rs
index 8d1ff2fcb24..45b1d5a05f3 100644
--- a/src/bootstrap/src/core/build_steps/tool.rs
+++ b/src/bootstrap/src/core/build_steps/tool.rs
@@ -36,8 +36,9 @@ struct ToolBuild {
 
 impl Builder<'_> {
     #[track_caller]
-    fn msg_tool(
+    pub(crate) fn msg_tool(
         &self,
+        kind: Kind,
         mode: Mode,
         tool: &str,
         build_stage: u32,
@@ -47,7 +48,7 @@ impl Builder<'_> {
         match mode {
             // depends on compiler stage, different to host compiler
             Mode::ToolRustc => self.msg_sysroot_tool(
-                Kind::Build,
+                kind,
                 build_stage,
                 format_args!("tool {tool}"),
                 *host,
@@ -100,6 +101,7 @@ impl Step for ToolBuild {
             cargo.allow_features(self.allow_features);
         }
         let _guard = builder.msg_tool(
+            Kind::Build,
             self.mode,
             self.tool,
             self.compiler.stage,
@@ -481,6 +483,7 @@ impl Step for Rustdoc {
         );
 
         let _guard = builder.msg_tool(
+            Kind::Build,
             Mode::ToolRustc,
             "rustdoc",
             build_compiler.stage,
diff --git a/src/bootstrap/src/core/builder.rs b/src/bootstrap/src/core/builder.rs
index f31bc46d25f..499a74be6b1 100644
--- a/src/bootstrap/src/core/builder.rs
+++ b/src/bootstrap/src/core/builder.rs
@@ -13,9 +13,9 @@ use std::process::Command;
 use std::sync::OnceLock;
 use std::time::{Duration, Instant};
 
-use crate::core::build_steps::llvm;
 use crate::core::build_steps::tool::{self, SourceType};
 use crate::core::build_steps::{check, clean, compile, dist, doc, install, run, setup, test};
+use crate::core::build_steps::{clippy, llvm};
 use crate::core::config::flags::{Color, Subcommand};
 use crate::core::config::{DryRun, SplitDebuginfo, TargetSelection};
 use crate::prepare_behaviour_dump_dir;
@@ -672,6 +672,7 @@ impl Kind {
             Kind::Doc => "Documenting",
             Kind::Run => "Running",
             Kind::Suggest => "Suggesting",
+            Kind::Clippy => "Linting",
             _ => {
                 let title_letter = self.as_str()[0..1].to_ascii_uppercase();
                 return format!("{title_letter}{}ing", &self.as_str()[1..]);
@@ -726,7 +727,35 @@ impl<'a> Builder<'a> {
                 tool::CoverageDump,
                 tool::LlvmBitcodeLinker
             ),
-            Kind::Check | Kind::Clippy | Kind::Fix => describe!(
+            Kind::Clippy => describe!(
+                clippy::Std,
+                clippy::Rustc,
+                clippy::Bootstrap,
+                clippy::BuildHelper,
+                clippy::BuildManifest,
+                clippy::CargoMiri,
+                clippy::Clippy,
+                clippy::CollectLicenseMetadata,
+                clippy::Compiletest,
+                clippy::CoverageDump,
+                clippy::Jsondocck,
+                clippy::Jsondoclint,
+                clippy::LintDocs,
+                clippy::LlvmBitcodeLinker,
+                clippy::Miri,
+                clippy::MiroptTestTools,
+                clippy::OptDist,
+                clippy::RemoteTestClient,
+                clippy::RemoteTestServer,
+                clippy::Rls,
+                clippy::RustAnalyzer,
+                clippy::RustDemangler,
+                clippy::Rustdoc,
+                clippy::Rustfmt,
+                clippy::RustInstaller,
+                clippy::Tidy,
+            ),
+            Kind::Check | Kind::Fix => describe!(
                 check::Std,
                 check::Rustc,
                 check::Rustdoc,
diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs
index c84eb8a684f..a272d8bff00 100644
--- a/src/bootstrap/src/core/config/config.rs
+++ b/src/bootstrap/src/core/config/config.rs
@@ -145,7 +145,6 @@ impl LldMode {
 /// `config.example.toml`.
 #[derive(Default, Clone)]
 pub struct Config {
-    pub changelog_seen: Option<usize>, // FIXME: Deprecated field. Remove it at 2024.
     pub change_id: Option<usize>,
     pub bypass_bootstrap_lock: bool,
     pub ccache: Option<String>,
@@ -605,7 +604,6 @@ impl Target {
 #[derive(Deserialize, Default)]
 #[serde(deny_unknown_fields, rename_all = "kebab-case")]
 pub(crate) struct TomlConfig {
-    changelog_seen: Option<usize>, // FIXME: Deprecated field. Remove it at 2024.
     #[serde(flatten)]
     change_id: ChangeIdWrapper,
     build: Option<Build>,
@@ -645,17 +643,7 @@ trait Merge {
 impl Merge for TomlConfig {
     fn merge(
         &mut self,
-        TomlConfig {
-            build,
-            install,
-            llvm,
-            rust,
-            dist,
-            target,
-            profile: _,
-            changelog_seen,
-            change_id,
-        }: Self,
+        TomlConfig { build, install, llvm, rust, dist, target, profile: _, change_id }: Self,
         replace: ReplaceOpt,
     ) {
         fn do_merge<T: Merge>(x: &mut Option<T>, y: Option<T>, replace: ReplaceOpt) {
@@ -667,7 +655,6 @@ impl Merge for TomlConfig {
                 }
             }
         }
-        self.changelog_seen.merge(changelog_seen, replace);
         self.change_id.inner.merge(change_id.inner, replace);
         do_merge(&mut self.build, build, replace);
         do_merge(&mut self.install, install, replace);
@@ -1400,7 +1387,6 @@ impl Config {
         }
         toml.merge(override_toml, ReplaceOpt::Override);
 
-        config.changelog_seen = toml.changelog_seen;
         config.change_id = toml.change_id.inner;
 
         let Build {
diff --git a/src/bootstrap/src/core/config/tests.rs b/src/bootstrap/src/core/config/tests.rs
index 8cd538953c5..59e16b65427 100644
--- a/src/bootstrap/src/core/config/tests.rs
+++ b/src/bootstrap/src/core/config/tests.rs
@@ -1,5 +1,5 @@
 use super::{flags::Flags, ChangeIdWrapper, Config};
-use crate::core::build_steps::check::get_clippy_rules_in_order;
+use crate::core::build_steps::clippy::get_clippy_rules_in_order;
 use crate::core::config::{LldMode, TomlConfig};
 
 use clap::CommandFactory;
diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs
index 1a8322c0dfd..f37b0f10437 100644
--- a/src/bootstrap/src/lib.rs
+++ b/src/bootstrap/src/lib.rs
@@ -630,6 +630,18 @@ impl Build {
         }
     }
 
+    /// Updates the given submodule only if it's initialized already; nothing happens otherwise.
+    pub fn update_existing_submodule(&self, submodule: &Path) {
+        // Avoid running git when there isn't a git checkout.
+        if !self.config.submodules(self.rust_info()) {
+            return;
+        }
+
+        if GitInfo::new(false, submodule).is_managed_git_subrepository() {
+            self.update_submodule(submodule);
+        }
+    }
+
     /// Executes the entire build, as configured by the flags and configuration.
     pub fn build(&mut self) {
         unsafe {
@@ -1080,6 +1092,16 @@ impl Build {
 
     #[must_use = "Groups should not be dropped until the Step finishes running"]
     #[track_caller]
+    fn msg_clippy(
+        &self,
+        what: impl Display,
+        target: impl Into<Option<TargetSelection>>,
+    ) -> Option<gha::Group> {
+        self.msg(Kind::Clippy, self.config.stage, what, self.config.build, target)
+    }
+
+    #[must_use = "Groups should not be dropped until the Step finishes running"]
+    #[track_caller]
     fn msg_check(
         &self,
         what: impl Display,
diff --git a/src/bootstrap/src/utils/change_tracker.rs b/src/bootstrap/src/utils/change_tracker.rs
index 277ec00fa62..db3df598a0c 100644
--- a/src/bootstrap/src/utils/change_tracker.rs
+++ b/src/bootstrap/src/utils/change_tracker.rs
@@ -170,4 +170,9 @@ pub const CONFIG_CHANGE_HISTORY: &[ChangeInfo] = &[
         severity: ChangeSeverity::Warning,
         summary: "`rust.split-debuginfo` has been moved to `target.<triple>.split-debuginfo` and its default value is determined for each target individually.",
     },
+    ChangeInfo {
+        change_id: 123711,
+        severity: ChangeSeverity::Warning,
+        summary: "The deprecated field `changelog-seen` has been removed. Using that field in `config.toml` from now on will result in breakage.",
+    },
 ];
diff --git a/src/bootstrap/src/utils/tarball.rs b/src/bootstrap/src/utils/tarball.rs
index 89fcac2a84b..cc86e3bab0c 100644
--- a/src/bootstrap/src/utils/tarball.rs
+++ b/src/bootstrap/src/utils/tarball.rs
@@ -1,3 +1,10 @@
+//! Facilitates the management and generation of tarballs.
+//!
+//! Tarballs efficiently hold Rust compiler build artifacts and
+//! capture a snapshot of each boostrap stage.
+//! In uplifting, a tarball from Stage N captures essential components
+//! to assemble Stage N + 1 compiler.
+
 use std::{
     path::{Path, PathBuf},
     process::Command,
diff --git a/src/ci/docker/host-x86_64/mingw-check/Dockerfile b/src/ci/docker/host-x86_64/mingw-check/Dockerfile
index 6918574814f..ae8dfadec73 100644
--- a/src/ci/docker/host-x86_64/mingw-check/Dockerfile
+++ b/src/ci/docker/host-x86_64/mingw-check/Dockerfile
@@ -46,7 +46,7 @@ ENV SCRIPT python3 ../x.py --stage 2 test src/tools/expand-yaml-anchors && \
            # We also skip the x86_64-unknown-linux-gnu target as it is well-tested by other jobs.
            python3 ../x.py check --stage 0 --set build.optimized-compiler-builtins=false core alloc std --target=aarch64-unknown-linux-gnu,i686-pc-windows-msvc,i686-unknown-linux-gnu,x86_64-apple-darwin,x86_64-pc-windows-gnu,x86_64-pc-windows-msvc && \
            python3 ../x.py check --target=i686-pc-windows-gnu --host=i686-pc-windows-gnu && \
-           python3 ../x.py clippy compiler -Aclippy::all -Dclippy::correctness && \
+           python3 ../x.py clippy compiler library -Aclippy::all -Dclippy::correctness && \
            python3 ../x.py build --stage 0 src/tools/build-manifest && \
            python3 ../x.py test --stage 0 src/tools/compiletest && \
            python3 ../x.py test --stage 0 core alloc std test proc_macro && \
diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md
index db85753145d..31096b6df92 100644
--- a/src/doc/rustc/src/SUMMARY.md
+++ b/src/doc/rustc/src/SUMMARY.md
@@ -77,6 +77,7 @@
 - [Profile-guided Optimization](profile-guided-optimization.md)
 - [Instrumentation-based Code Coverage](instrument-coverage.md)
 - [Linker-plugin-based LTO](linker-plugin-lto.md)
+- [Checking conditional configurations](check-cfg.md)
 - [Exploit Mitigations](exploit-mitigations.md)
 - [Symbol Mangling](symbol-mangling/index.md)
     - [v0 Symbol Format](symbol-mangling/v0.md)
diff --git a/src/doc/unstable-book/src/compiler-flags/check-cfg.md b/src/doc/rustc/src/check-cfg.md
index 836929aba0b..37708bda1f3 100644
--- a/src/doc/unstable-book/src/compiler-flags/check-cfg.md
+++ b/src/doc/rustc/src/check-cfg.md
@@ -1,10 +1,4 @@
-# `check-cfg`
-
-The tracking issue for this feature is: [#82450](https://github.com/rust-lang/rust/issues/82450).
-
-------------------------
-
-This feature enables checking of conditional configuration.
+# Checking conditional configurations
 
 `rustc` accepts the `--check-cfg` option, which specifies whether to check conditions and how to
 check them. The `--check-cfg` option takes a value, called the _check cfg specification_.
diff --git a/src/doc/rustc/src/codegen-options/index.md b/src/doc/rustc/src/codegen-options/index.md
index c8f5d649570..35bf2c27ff1 100644
--- a/src/doc/rustc/src/codegen-options/index.md
+++ b/src/doc/rustc/src/codegen-options/index.md
@@ -479,6 +479,26 @@ then `-C target-feature=+crt-static` "wins" over `-C relocation-model=pic`,
 and the linker is instructed (`-static`) to produce a statically linked
 but not position-independent executable.
 
+## relro-level
+
+This flag controls what level of RELRO (Relocation Read-Only) is enabled. RELRO is an exploit
+mitigation which makes the Global Offset Table (GOT) read-only.
+
+Supported values for this option are:
+
+- `off`: Dynamically linked functions are resolved lazily and the GOT is writable.
+- `partial`: Dynamically linked functions are resolved lazily and written into the Procedure
+  Linking Table (PLT) part of the GOT (`.got.plt`). The non-PLT part of the GOT (`.got`) is made
+  read-only and both are moved to prevent writing from buffer overflows.
+- `full`: Dynamically linked functions are resolved at the start of program execution and the
+  Global Offset Table (`.got`/`.got.plt`) is populated eagerly and then made read-only. The GOT is
+  also moved to prevent writing from buffer overflows. Full RELRO uses more memory and increases
+  process startup time.
+
+This flag is ignored on platforms where RELRO is not supported (targets which do not use the ELF
+binary format), such as Windows or macOS. Each rustc target has its own default for RELRO. rustc
+enables Full RELRO by default on platforms where it is supported.
+
 ## remark
 
 This flag lets you print remarks for optimization passes.
diff --git a/src/doc/rustc/src/command-line-arguments.md b/src/doc/rustc/src/command-line-arguments.md
index 5e02453e236..7c605333c25 100644
--- a/src/doc/rustc/src/command-line-arguments.md
+++ b/src/doc/rustc/src/command-line-arguments.md
@@ -18,6 +18,16 @@ The value can either be a single identifier or two identifiers separated by `=`.
 For examples, `--cfg 'verbose'` or `--cfg 'feature="serde"'`. These correspond
 to `#[cfg(verbose)]` and `#[cfg(feature = "serde")]` respectively.
 
+<a id="option-check-cfg"></a>
+## `--check-cfg`: enables checking conditional configurations
+
+This flag will enable checking conditional configurations.
+Refer to the [Checking conditional configurations](check-cfg.md) of this book
+for further details and explanation.
+
+For examples, `--check-cfg 'cfg(verbose)'` or `--check-cfg 'cfg(feature, values("serde"))'`.
+These correspond to `#[cfg(verbose)]` and `#[cfg(feature = "serde")]` respectively.
+
 <a id="option-l-search-path"></a>
 ## `-L`: add a directory to the library search path
 
diff --git a/src/doc/rustdoc/src/command-line-arguments.md b/src/doc/rustdoc/src/command-line-arguments.md
index fe5cb529c26..822f341b370 100644
--- a/src/doc/rustdoc/src/command-line-arguments.md
+++ b/src/doc/rustdoc/src/command-line-arguments.md
@@ -131,6 +131,20 @@ This flag accepts the same values as `rustc --cfg`, and uses it to configure
 compilation. The example above uses `feature`, but any of the `cfg` values
 are acceptable.
 
+## `--check-cfg`: check configuration flags
+
+This flag accepts the same values as `rustc --check-cfg`, and uses it to
+check configuration flags.
+
+Using this flag looks like this:
+
+```bash
+$ rustdoc src/lib.rs --check-cfg='cfg(my_cfg, values("foo", "bar"))'
+```
+
+The example above check every well known names and values (`target_os`, `doc`, `test`, ...)
+and check the values of `my_cfg`: `foo` and `bar`.
+
 ## `--extern`: specify a dependency's location
 
 Using this flag looks like this:
diff --git a/src/doc/rustdoc/src/unstable-features.md b/src/doc/rustdoc/src/unstable-features.md
index 41602dec44c..bdb55de8d63 100644
--- a/src/doc/rustdoc/src/unstable-features.md
+++ b/src/doc/rustdoc/src/unstable-features.md
@@ -618,22 +618,6 @@ crate being documented (`foobar`) and a path to output the calls
 To scrape examples from test code, e.g. functions marked `#[test]`, then
 add the `--scrape-tests` flag.
 
-### `--check-cfg`: check configuration flags
-
- * Tracking issue: [#82450](https://github.com/rust-lang/rust/issues/82450)
-
-This flag accepts the same values as `rustc --check-cfg`, and uses it to check configuration flags.
-
-Using this flag looks like this:
-
-```bash
-$ rustdoc src/lib.rs -Z unstable-options \
-    --check-cfg='cfg(feature, values("foo", "bar"))'
-```
-
-The example above check every well known names and values (`target_os`, `doc`, `test`, ...)
-and check the values of `feature`: `foo` and `bar`.
-
 ### `--generate-link-to-definition`: Generate links on types in source code
 
  * Tracking issue: [#89095](https://github.com/rust-lang/rust/issues/89095)
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 925d41e67f8..fc4f48262e5 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -1,5 +1,25 @@
-//! This module contains the "cleaned" pieces of the AST, and the functions
-//! that clean them.
+//! This module defines the primary IR[^1] used in rustdoc together with the procedures that
+//! transform rustc data types into it.
+//!
+//! This IR — commonly referred to as the *cleaned AST* — is modeled after the [AST][ast].
+//!
+//! There are two kinds of transformation — *cleaning* — procedures:
+//!
+//! 1. Cleans [HIR][hir] types. Used for user-written code and inlined local re-exports
+//!    both found in the local crate.
+//! 2. Cleans [`rustc_middle::ty`] types. Used for inlined cross-crate re-exports and anything
+//!    output by the trait solver (e.g., when synthesizing blanket and auto-trait impls).
+//!    They usually have `ty` or `middle` in their name.
+//!
+//! Their name is prefixed by `clean_`.
+//!
+//! Both the HIR and the `rustc_middle::ty` IR are quite removed from the source code.
+//! The cleaned AST on the other hand is closer to it which simplifies the rendering process.
+//! Furthermore, operating on a single IR instead of two avoids duplicating efforts down the line.
+//!
+//! This IR is consumed by both the HTML and the JSON backend.
+//!
+//! [^1]: Intermediate representation.
 
 mod auto_trait;
 mod blanket_impl;
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index b592bd76e4c..aeb7137b722 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -408,7 +408,7 @@ impl Item {
 
     pub(crate) fn attr_span(&self, tcx: TyCtxt<'_>) -> rustc_span::Span {
         span_of_fragments(&self.attrs.doc_strings)
-            .unwrap_or_else(|| self.span(tcx).map_or(rustc_span::DUMMY_SP, |span| span.inner()))
+            .unwrap_or_else(|| self.span(tcx).map_or(DUMMY_SP, |span| span.inner()))
     }
 
     /// Combine all doc strings into a single value handling indentation and newlines as needed.
diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs
index 22a3cf4d44d..0ad4c9c2346 100644
--- a/src/librustdoc/doctest.rs
+++ b/src/librustdoc/doctest.rs
@@ -60,11 +60,8 @@ pub(crate) fn generate_args_file(file_path: &Path, options: &RustdocOptions) ->
     for cfg in &options.cfgs {
         content.push(format!("--cfg={cfg}"));
     }
-    if !options.check_cfgs.is_empty() {
-        content.push("-Zunstable-options".to_string());
-        for check_cfg in &options.check_cfgs {
-            content.push(format!("--check-cfg={check_cfg}"));
-        }
+    for check_cfg in &options.check_cfgs {
+        content.push(format!("--check-cfg={check_cfg}"));
     }
 
     for lib_str in &options.lib_strs {
diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs
index 4e46f847fd7..a949f795753 100644
--- a/src/librustdoc/html/render/mod.rs
+++ b/src/librustdoc/html/render/mod.rs
@@ -56,7 +56,7 @@ use rustc_middle::ty::{self, TyCtxt};
 use rustc_session::RustcVersion;
 use rustc_span::{
     symbol::{sym, Symbol},
-    BytePos, FileName, RealFileName,
+    BytePos, FileName, RealFileName, DUMMY_SP,
 };
 use serde::ser::SerializeMap;
 use serde::{Serialize, Serializer};
@@ -2414,7 +2414,7 @@ fn render_call_locations<W: fmt::Write>(mut w: W, cx: &mut Context<'_>, item: &c
         let contents = match fs::read_to_string(&path) {
             Ok(contents) => contents,
             Err(err) => {
-                let span = item.span(tcx).map_or(rustc_span::DUMMY_SP, |span| span.inner());
+                let span = item.span(tcx).map_or(DUMMY_SP, |span| span.inner());
                 tcx.dcx().span_err(span, format!("failed to read file {}: {err}", path.display()));
                 return false;
             }
@@ -2495,7 +2495,7 @@ fn render_call_locations<W: fmt::Write>(mut w: W, cx: &mut Context<'_>, item: &c
                 file.start_pos + BytePos(byte_max),
             ))
         })()
-        .unwrap_or(rustc_span::DUMMY_SP);
+        .unwrap_or(DUMMY_SP);
 
         let mut decoration_info = FxHashMap::default();
         decoration_info.insert("highlight focus", vec![byte_ranges.remove(0)]);
diff --git a/src/librustdoc/html/render/type_layout.rs b/src/librustdoc/html/render/type_layout.rs
index 738ea0aee7e..a27e327f235 100644
--- a/src/librustdoc/html/render/type_layout.rs
+++ b/src/librustdoc/html/render/type_layout.rs
@@ -3,8 +3,7 @@ use askama::Template;
 use rustc_data_structures::captures::Captures;
 use rustc_hir::def_id::DefId;
 use rustc_middle::span_bug;
-use rustc_middle::ty::layout::LayoutError;
-use rustc_middle::ty::Adt;
+use rustc_middle::ty::{self, layout::LayoutError};
 use rustc_span::symbol::Symbol;
 use rustc_target::abi::{Primitive, TagEncoding, Variants};
 
@@ -57,7 +56,7 @@ pub(crate) fn document_type_layout<'a, 'cx: 'a>(
             variants
                 .iter_enumerated()
                 .map(|(variant_idx, variant_layout)| {
-                    let Adt(adt, _) = type_layout.ty.kind() else {
+                    let ty::Adt(adt, _) = type_layout.ty.kind() else {
                         span_bug!(tcx.def_span(ty_def_id), "not an adt")
                     };
                     let name = adt.variant(variant_idx).name;
diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js
index 940b62be0c9..ee7d19634b4 100644
--- a/src/librustdoc/html/static/js/main.js
+++ b/src/librustdoc/html/static/js/main.js
@@ -462,6 +462,7 @@ function preLoadCss(cssUrl) {
 
             case "s":
             case "S":
+            case "/":
                 ev.preventDefault();
                 searchState.focus();
                 break;
@@ -1334,7 +1335,7 @@ function preLoadCss(cssUrl) {
 
         const shortcuts = [
             ["?", "Show this help dialog"],
-            ["S", "Focus the search field"],
+            ["S / /", "Focus the search field"],
             ["↑", "Move up in search results"],
             ["↓", "Move down in search results"],
             ["← / →", "Switch result tab (when results focused)"],
diff --git a/src/librustdoc/html/templates/page.html b/src/librustdoc/html/templates/page.html
index 1dc9041658e..1e01cd70b96 100644
--- a/src/librustdoc/html/templates/page.html
+++ b/src/librustdoc/html/templates/page.html
@@ -129,7 +129,7 @@
                         aria-label="Run search in the documentation" {#+ #}
                         autocomplete="off" {#+ #}
                         spellcheck="false" {#+ #}
-                        placeholder="Click or press ‘S’ to search, ‘?’ for more options…" {#+ #}
+                        placeholder="Type ‘S’ or ‘/’ to search, ‘?’ for more options…" {#+ #}
                         type="search"> {# #}
                     <div id="help-button" tabindex="-1"> {# #}
                         <a href="{{page.root_path|safe}}help.html" title="help">?</a> {# #}
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index b78fb4c4eee..f2a7518b4ce 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -242,7 +242,7 @@ fn opts() -> Vec<RustcOptGroup> {
             o.optmulti("L", "library-path", "directory to add to crate search path", "DIR")
         }),
         stable("cfg", |o| o.optmulti("", "cfg", "pass a --cfg to rustc", "")),
-        unstable("check-cfg", |o| o.optmulti("", "check-cfg", "pass a --check-cfg to rustc", "")),
+        stable("check-cfg", |o| o.optmulti("", "check-cfg", "pass a --check-cfg to rustc", "")),
         stable("extern", |o| o.optmulti("", "extern", "pass an --extern to rustc", "NAME[=PATH]")),
         unstable("extern-html-root-url", |o| {
             o.optmulti(
diff --git a/src/tools/cargo b/src/tools/cargo
-Subproject 48eca1b164695022295ce466b64b44e4e0228b0
+Subproject 6f06fe908a5ee0f415c187f868ea627e82efe07
diff --git a/src/tools/clippy/clippy_lints/src/casts/ptr_as_ptr.rs b/src/tools/clippy/clippy_lints/src/casts/ptr_as_ptr.rs
index 68841076f77..2c168405ee2 100644
--- a/src/tools/clippy/clippy_lints/src/casts/ptr_as_ptr.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/ptr_as_ptr.rs
@@ -77,7 +77,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, msrv: &Msrv) {
 
         let (help, final_suggestion) = if let Some(method) = omit_cast.corresponding_item() {
             // don't force absolute path
-            let method = qpath_to_string(method);
+            let method = qpath_to_string(&cx.tcx, method);
             ("try call directly", format!("{method}{turbofish}()"))
         } else {
             let cast_expr_sugg = Sugg::hir_with_applicability(cx, cast_expr, "_", &mut app);
diff --git a/src/tools/clippy/clippy_lints/src/crate_in_macro_def.rs b/src/tools/clippy/clippy_lints/src/crate_in_macro_def.rs
index b1aa472aa03..adf6f7c4737 100644
--- a/src/tools/clippy/clippy_lints/src/crate_in_macro_def.rs
+++ b/src/tools/clippy/clippy_lints/src/crate_in_macro_def.rs
@@ -88,7 +88,7 @@ fn contains_unhygienic_crate_reference(tts: &TokenStream) -> Option<Span> {
         if !prev_is_dollar
             && let Some(span) = is_crate_keyword(curr)
             && let Some(next) = cursor.look_ahead(0)
-            && is_token(next, &TokenKind::ModSep)
+            && is_token(next, &TokenKind::PathSep)
         {
             return Some(span);
         }
diff --git a/src/tools/clippy/clippy_lints/src/derivable_impls.rs b/src/tools/clippy/clippy_lints/src/derivable_impls.rs
index 80327586fed..0c9ad5e8d00 100644
--- a/src/tools/clippy/clippy_lints/src/derivable_impls.rs
+++ b/src/tools/clippy/clippy_lints/src/derivable_impls.rs
@@ -9,7 +9,7 @@ use rustc_hir::{
 };
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty::adjustment::{Adjust, PointerCoercion};
-use rustc_middle::ty::{self, Adt, AdtDef, GenericArgsRef, Ty, TypeckResults};
+use rustc_middle::ty::{self, AdtDef, GenericArgsRef, Ty, TypeckResults};
 use rustc_session::impl_lint_pass;
 use rustc_span::sym;
 
@@ -79,7 +79,7 @@ fn is_path_self(e: &Expr<'_>) -> bool {
 fn contains_trait_object(ty: Ty<'_>) -> bool {
     match ty.kind() {
         ty::Ref(_, ty, _) => contains_trait_object(*ty),
-        Adt(def, args) => def.is_box() && args[0].as_type().map_or(false, contains_trait_object),
+        ty::Adt(def, args) => def.is_box() && args[0].as_type().map_or(false, contains_trait_object),
         ty::Dynamic(..) => true,
         _ => false,
     }
@@ -198,7 +198,7 @@ impl<'tcx> LateLintPass<'tcx> for DerivableImpls {
             && let Node::ImplItem(impl_item) = cx.tcx.hir_node(impl_item_hir)
             && let ImplItemKind::Fn(_, b) = &impl_item.kind
             && let Body { value: func_expr, .. } = cx.tcx.hir().body(*b)
-            && let &Adt(adt_def, args) = cx.tcx.type_of(item.owner_id).instantiate_identity().kind()
+            && let &ty::Adt(adt_def, args) = cx.tcx.type_of(item.owner_id).instantiate_identity().kind()
             && let attrs = cx.tcx.hir().attrs(item.hir_id())
             && !attrs.iter().any(|attr| attr.doc_str().is_some())
             && cx.tcx.hir().attrs(impl_item_hir).is_empty()
diff --git a/src/tools/clippy/clippy_lints/src/doc/needless_doctest_main.rs b/src/tools/clippy/clippy_lints/src/doc/needless_doctest_main.rs
index e55a988321b..651f2ebaee6 100644
--- a/src/tools/clippy/clippy_lints/src/doc/needless_doctest_main.rs
+++ b/src/tools/clippy/clippy_lints/src/doc/needless_doctest_main.rs
@@ -38,7 +38,7 @@ pub fn check(
     // of all `#[test]` attributes in not ignored code examples
     fn check_code_sample(code: String, edition: Edition, ignore: bool) -> (bool, Vec<Range<usize>>) {
         rustc_driver::catch_fatal_errors(|| {
-            rustc_span::create_session_globals_then(edition, || {
+            rustc_span::create_session_globals_then(edition, None, || {
                 let mut test_attr_spans = vec![];
                 let filename = FileName::anon_source_code(&code);
 
diff --git a/src/tools/clippy/clippy_lints/src/from_raw_with_void_ptr.rs b/src/tools/clippy/clippy_lints/src/from_raw_with_void_ptr.rs
index ba2495c17a2..d62d008d480 100644
--- a/src/tools/clippy/clippy_lints/src/from_raw_with_void_ptr.rs
+++ b/src/tools/clippy/clippy_lints/src/from_raw_with_void_ptr.rs
@@ -4,7 +4,7 @@ use clippy_utils::ty::is_c_void;
 use rustc_hir::def_id::DefId;
 use rustc_hir::{Expr, ExprKind, QPath};
 use rustc_lint::{LateContext, LateLintPass};
-use rustc_middle::ty::RawPtr;
+use rustc_middle::ty;
 use rustc_session::declare_lint_pass;
 use rustc_span::sym;
 
@@ -44,7 +44,7 @@ impl LateLintPass<'_> for FromRawWithVoidPtr {
             && seg.ident.name == sym!(from_raw)
             && let Some(type_str) = path_def_id(cx, ty).and_then(|id| def_id_matches_type(cx, id))
             && let arg_kind = cx.typeck_results().expr_ty(arg).kind()
-            && let RawPtr(ty, _) = arg_kind
+            && let ty::RawPtr(ty, _) = arg_kind
             && is_c_void(cx, *ty)
         {
             let msg = format!("creating a `{type_str}` from a void raw pointer");
diff --git a/src/tools/clippy/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs b/src/tools/clippy/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs
index 2d757883f26..995dd782cbb 100644
--- a/src/tools/clippy/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs
+++ b/src/tools/clippy/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs
@@ -1,4 +1,4 @@
-use rustc_hir::{self as hir, intravisit, HirIdSet};
+use rustc_hir::{self as hir, intravisit, HirId, HirIdSet};
 use rustc_lint::LateContext;
 use rustc_middle::ty;
 use rustc_span::def_id::LocalDefId;
@@ -74,7 +74,7 @@ fn check_raw_ptr<'tcx>(
     }
 }
 
-fn raw_ptr_arg(cx: &LateContext<'_>, arg: &hir::Param<'_>) -> Option<hir::HirId> {
+fn raw_ptr_arg(cx: &LateContext<'_>, arg: &hir::Param<'_>) -> Option<HirId> {
     if let (&hir::PatKind::Binding(_, id, _, _), Some(&ty::RawPtr(_, _))) = (
         &arg.pat.kind,
         cx.maybe_typeck_results()
diff --git a/src/tools/clippy/clippy_lints/src/functions/result.rs b/src/tools/clippy/clippy_lints/src/functions/result.rs
index 93f088d3e33..c3a0b40a677 100644
--- a/src/tools/clippy/clippy_lints/src/functions/result.rs
+++ b/src/tools/clippy/clippy_lints/src/functions/result.rs
@@ -2,7 +2,7 @@ use rustc_errors::Diag;
 use rustc_hir as hir;
 use rustc_lint::{LateContext, LintContext};
 use rustc_middle::lint::in_external_macro;
-use rustc_middle::ty::{Adt, Ty};
+use rustc_middle::ty::{self, Ty};
 use rustc_span::{sym, Span};
 
 use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_then};
@@ -25,7 +25,7 @@ fn result_err_ty<'tcx>(
             .tcx
             .instantiate_bound_regions_with_erased(cx.tcx.fn_sig(id).instantiate_identity().output())
         && is_type_diagnostic_item(cx, ty, sym::Result)
-        && let Adt(_, args) = ty.kind()
+        && let ty::Adt(_, args) = ty.kind()
     {
         let err_ty = args.type_at(1);
         Some((hir_ty, err_ty))
@@ -86,7 +86,7 @@ fn check_result_unit_err(cx: &LateContext<'_>, err_ty: Ty<'_>, fn_header_span: S
 }
 
 fn check_result_large_err<'tcx>(cx: &LateContext<'tcx>, err_ty: Ty<'tcx>, hir_ty_span: Span, large_err_threshold: u64) {
-    if let Adt(adt, subst) = err_ty.kind()
+    if let ty::Adt(adt, subst) = err_ty.kind()
         && let Some(local_def_id) = err_ty
             .ty_adt_def()
             .expect("already checked this is adt")
diff --git a/src/tools/clippy/clippy_lints/src/implicit_saturating_add.rs b/src/tools/clippy/clippy_lints/src/implicit_saturating_add.rs
index b8d7e8f3b07..f225c6e7f04 100644
--- a/src/tools/clippy/clippy_lints/src/implicit_saturating_add.rs
+++ b/src/tools/clippy/clippy_lints/src/implicit_saturating_add.rs
@@ -7,7 +7,7 @@ use rustc_data_structures::packed::Pu128;
 use rustc_errors::Applicability;
 use rustc_hir::{BinOpKind, Block, Expr, ExprKind, Stmt, StmtKind};
 use rustc_lint::{LateContext, LateLintPass};
-use rustc_middle::ty::{Int, IntTy, Ty, Uint, UintTy};
+use rustc_middle::ty::{IntTy, Ty, UintTy};
 use rustc_session::declare_lint_pass;
 
 declare_clippy_lint! {
@@ -97,6 +97,7 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitSaturatingAdd {
 }
 
 fn get_int_max(ty: Ty<'_>) -> Option<u128> {
+    use rustc_middle::ty::{Int, Uint};
     match ty.peel_refs().kind() {
         Int(IntTy::I8) => i8::MAX.try_into().ok(),
         Int(IntTy::I16) => i16::MAX.try_into().ok(),
diff --git a/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs b/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs
index 4d1f89b1d9d..6ddc8346511 100644
--- a/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs
+++ b/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs
@@ -7,6 +7,7 @@ use clippy_utils::{is_expn_of, is_lint_allowed, path_to_local};
 use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
 use rustc_errors::Applicability;
 use rustc_hir as hir;
+use rustc_hir::HirId;
 use rustc_hir::intravisit::{self, Visitor};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::hir::nested_filter;
@@ -87,9 +88,9 @@ impl<'tcx> LateLintPass<'tcx> for IndexRefutableSlice {
     extract_msrv_attr!(LateContext);
 }
 
-fn find_slice_values(cx: &LateContext<'_>, pat: &hir::Pat<'_>) -> FxIndexMap<hir::HirId, SliceLintInformation> {
-    let mut removed_pat: FxHashSet<hir::HirId> = FxHashSet::default();
-    let mut slices: FxIndexMap<hir::HirId, SliceLintInformation> = FxIndexMap::default();
+fn find_slice_values(cx: &LateContext<'_>, pat: &hir::Pat<'_>) -> FxIndexMap<HirId, SliceLintInformation> {
+    let mut removed_pat: FxHashSet<HirId> = FxHashSet::default();
+    let mut slices: FxIndexMap<HirId, SliceLintInformation> = FxIndexMap::default();
     pat.walk_always(|pat| {
         // We'll just ignore mut and ref mut for simplicity sake right now
         if let hir::PatKind::Binding(
@@ -206,10 +207,10 @@ impl SliceLintInformation {
 
 fn filter_lintable_slices<'tcx>(
     cx: &LateContext<'tcx>,
-    slice_lint_info: FxIndexMap<hir::HirId, SliceLintInformation>,
+    slice_lint_info: FxIndexMap<HirId, SliceLintInformation>,
     max_suggested_slice: u64,
     scope: &'tcx hir::Expr<'tcx>,
-) -> FxIndexMap<hir::HirId, SliceLintInformation> {
+) -> FxIndexMap<HirId, SliceLintInformation> {
     let mut visitor = SliceIndexLintingVisitor {
         cx,
         slice_lint_info,
@@ -223,7 +224,7 @@ fn filter_lintable_slices<'tcx>(
 
 struct SliceIndexLintingVisitor<'a, 'tcx> {
     cx: &'a LateContext<'tcx>,
-    slice_lint_info: FxIndexMap<hir::HirId, SliceLintInformation>,
+    slice_lint_info: FxIndexMap<HirId, SliceLintInformation>,
     max_suggested_slice: u64,
 }
 
diff --git a/src/tools/clippy/clippy_lints/src/large_enum_variant.rs b/src/tools/clippy/clippy_lints/src/large_enum_variant.rs
index 6feb1885576..0bf7389ef9c 100644
--- a/src/tools/clippy/clippy_lints/src/large_enum_variant.rs
+++ b/src/tools/clippy/clippy_lints/src/large_enum_variant.rs
@@ -7,7 +7,7 @@ use rustc_errors::Applicability;
 use rustc_hir::{Item, ItemKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::lint::in_external_macro;
-use rustc_middle::ty::{Adt, Ty};
+use rustc_middle::ty::{self, Ty};
 use rustc_session::impl_lint_pass;
 use rustc_span::Span;
 
@@ -82,7 +82,7 @@ impl<'tcx> LateLintPass<'tcx> for LargeEnumVariant {
         }
         if let ItemKind::Enum(ref def, _) = item.kind {
             let ty = cx.tcx.type_of(item.owner_id).instantiate_identity();
-            let Adt(adt, subst) = ty.kind() else {
+            let ty::Adt(adt, subst) = ty.kind() else {
                 panic!("already checked whether this is an enum")
             };
             if adt.variants().len() <= 1 {
@@ -167,7 +167,7 @@ impl<'tcx> LateLintPass<'tcx> for LargeEnumVariant {
 }
 
 fn maybe_copy<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
-    if let Adt(_def, args) = ty.kind()
+    if let ty::Adt(_def, args) = ty.kind()
         && args.types().next().is_some()
         && let Some(copy_trait) = cx.tcx.lang_items().copy_trait()
     {
diff --git a/src/tools/clippy/clippy_lints/src/matches/match_wild_err_arm.rs b/src/tools/clippy/clippy_lints/src/matches/match_wild_err_arm.rs
index d1f637ec78c..310675d01a2 100644
--- a/src/tools/clippy/clippy_lints/src/matches/match_wild_err_arm.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/match_wild_err_arm.rs
@@ -19,7 +19,7 @@ pub(crate) fn check<'tcx>(cx: &LateContext<'tcx>, ex: &Expr<'tcx>, arms: &[Arm<'
     if is_type_diagnostic_item(cx, ex_ty, sym::Result) {
         for arm in arms {
             if let PatKind::TupleStruct(ref path, inner, _) = arm.pat.kind {
-                let path_str = rustc_hir_pretty::qpath_to_string(path);
+                let path_str = rustc_hir_pretty::qpath_to_string(&cx.tcx, path);
                 if path_str == "Err" {
                     let mut matching_wild = inner.iter().any(is_wild);
                     let mut ident_bind_name = kw::Underscore;
diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_join.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_join.rs
index c3ad4db3875..efd1a718504 100644
--- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_join.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_join.rs
@@ -4,7 +4,7 @@ use rustc_ast::ast::LitKind;
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind, LangItem};
 use rustc_lint::LateContext;
-use rustc_middle::ty::{Ref, Slice};
+use rustc_middle::ty;
 use rustc_span::Span;
 
 use super::UNNECESSARY_JOIN;
@@ -18,9 +18,9 @@ pub(super) fn check<'tcx>(
 ) {
     let applicability = Applicability::MachineApplicable;
     let collect_output_adjusted_type = cx.typeck_results().expr_ty_adjusted(join_self_arg);
-    if let Ref(_, ref_type, _) = collect_output_adjusted_type.kind()
+    if let ty::Ref(_, ref_type, _) = collect_output_adjusted_type.kind()
         // the turbofish for collect is ::<Vec<String>>
-        && let Slice(slice) = ref_type.kind()
+        && let ty::Slice(slice) = ref_type.kind()
         && is_type_lang_item(cx, *slice, LangItem::String)
         // the argument for join is ""
         && let ExprKind::Lit(spanned) = &join_arg.kind
diff --git a/src/tools/clippy/clippy_lints/src/mut_key.rs b/src/tools/clippy/clippy_lints/src/mut_key.rs
index 79f0a398d55..8c2f43c97f4 100644
--- a/src/tools/clippy/clippy_lints/src/mut_key.rs
+++ b/src/tools/clippy/clippy_lints/src/mut_key.rs
@@ -4,7 +4,7 @@ use clippy_utils::{def_path_def_ids, trait_ref_of_method};
 use rustc_data_structures::fx::FxHashSet;
 use rustc_hir as hir;
 use rustc_lint::{LateContext, LateLintPass};
-use rustc_middle::ty::{Adt, Ty};
+use rustc_middle::ty::{self, Ty};
 use rustc_session::impl_lint_pass;
 use rustc_span::def_id::LocalDefId;
 use rustc_span::symbol::sym;
@@ -153,7 +153,7 @@ impl MutableKeyType {
     // generics (because the compiler cannot ensure immutability for unknown types).
     fn check_ty_<'tcx>(&self, cx: &LateContext<'tcx>, span: Span, ty: Ty<'tcx>) {
         let ty = ty.peel_refs();
-        if let Adt(def, args) = ty.kind() {
+        if let ty::Adt(def, args) = ty.kind() {
             let is_keyed_type = [sym::HashMap, sym::BTreeMap, sym::HashSet, sym::BTreeSet]
                 .iter()
                 .any(|diag_item| cx.tcx.is_diagnostic_item(*diag_item, def.did()));
diff --git a/src/tools/clippy/clippy_lints/src/mut_reference.rs b/src/tools/clippy/clippy_lints/src/mut_reference.rs
index 6867f76a723..0a3b769c3e6 100644
--- a/src/tools/clippy/clippy_lints/src/mut_reference.rs
+++ b/src/tools/clippy/clippy_lints/src/mut_reference.rs
@@ -49,7 +49,7 @@ impl<'tcx> LateLintPass<'tcx> for UnnecessaryMutPassed {
                         cx,
                         arguments.iter().collect(),
                         cx.typeck_results().expr_ty(fn_expr),
-                        &rustc_hir_pretty::qpath_to_string(path),
+                        &rustc_hir_pretty::qpath_to_string(&cx.tcx, path),
                         "function",
                     );
                 }
diff --git a/src/tools/clippy/clippy_lints/src/non_copy_const.rs b/src/tools/clippy/clippy_lints/src/non_copy_const.rs
index 73fc34c2450..5ca388d67a1 100644
--- a/src/tools/clippy/clippy_lints/src/non_copy_const.rs
+++ b/src/tools/clippy/clippy_lints/src/non_copy_const.rs
@@ -18,7 +18,7 @@ use rustc_middle::mir::interpret::{ErrorHandled, EvalToValTreeResult, GlobalId};
 use rustc_middle::ty::adjustment::Adjust;
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_session::impl_lint_pass;
-use rustc_span::{sym, InnerSpan, Span};
+use rustc_span::{sym, DUMMY_SP, InnerSpan, Span};
 use rustc_target::abi::VariantIdx;
 
 // FIXME: this is a correctness problem but there's no suitable
@@ -290,9 +290,7 @@ impl NonCopyConst {
             promoted: None,
         };
         let param_env = cx.tcx.param_env(def_id).with_reveal_all_normalized(cx.tcx);
-        let result = cx
-            .tcx
-            .const_eval_global_id_for_typeck(param_env, cid, rustc_span::DUMMY_SP);
+        let result = cx.tcx.const_eval_global_id_for_typeck(param_env, cid, DUMMY_SP);
         self.is_value_unfrozen_raw(cx, result, ty)
     }
 
@@ -303,7 +301,7 @@ impl NonCopyConst {
             cx.tcx,
             cx.param_env,
             ty::UnevaluatedConst::new(def_id, args),
-            rustc_span::DUMMY_SP,
+            DUMMY_SP,
         );
         self.is_value_unfrozen_raw(cx, result, ty)
     }
diff --git a/src/tools/clippy/clippy_lints/src/operators/assign_op_pattern.rs b/src/tools/clippy/clippy_lints/src/operators/assign_op_pattern.rs
index 2f85130fba1..435eb9048f5 100644
--- a/src/tools/clippy/clippy_lints/src/operators/assign_op_pattern.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/assign_op_pattern.rs
@@ -6,6 +6,7 @@ use clippy_utils::{binop_traits, eq_expr_value, trait_ref_of_method};
 use core::ops::ControlFlow;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
+use rustc_hir::{HirId, HirIdSet};
 use rustc_hir_typeck::expr_use_visitor::{Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId};
 use rustc_lint::LateContext;
 use rustc_middle::mir::FakeReadCause;
@@ -98,10 +99,10 @@ pub(super) fn check<'tcx>(
     }
 }
 
-fn imm_borrows_in_expr(cx: &LateContext<'_>, e: &hir::Expr<'_>) -> hir::HirIdSet {
-    struct S(hir::HirIdSet);
+fn imm_borrows_in_expr(cx: &LateContext<'_>, e: &hir::Expr<'_>) -> HirIdSet {
+    struct S(HirIdSet);
     impl Delegate<'_> for S {
-        fn borrow(&mut self, place: &PlaceWithHirId<'_>, _: hir::HirId, kind: BorrowKind) {
+        fn borrow(&mut self, place: &PlaceWithHirId<'_>, _: HirId, kind: BorrowKind) {
             if matches!(kind, BorrowKind::ImmBorrow | BorrowKind::UniqueImmBorrow) {
                 self.0.insert(match place.place.base {
                     PlaceBase::Local(id) => id,
@@ -111,13 +112,13 @@ fn imm_borrows_in_expr(cx: &LateContext<'_>, e: &hir::Expr<'_>) -> hir::HirIdSet
             }
         }
 
-        fn consume(&mut self, _: &PlaceWithHirId<'_>, _: hir::HirId) {}
-        fn mutate(&mut self, _: &PlaceWithHirId<'_>, _: hir::HirId) {}
-        fn fake_read(&mut self, _: &PlaceWithHirId<'_>, _: FakeReadCause, _: hir::HirId) {}
-        fn copy(&mut self, _: &PlaceWithHirId<'_>, _: hir::HirId) {}
+        fn consume(&mut self, _: &PlaceWithHirId<'_>, _: HirId) {}
+        fn mutate(&mut self, _: &PlaceWithHirId<'_>, _: HirId) {}
+        fn fake_read(&mut self, _: &PlaceWithHirId<'_>, _: FakeReadCause, _: HirId) {}
+        fn copy(&mut self, _: &PlaceWithHirId<'_>, _: HirId) {}
     }
 
-    let mut s = S(hir::HirIdSet::default());
+    let mut s = S(HirIdSet::default());
     let infcx = cx.tcx.infer_ctxt().build();
     let mut v = ExprUseVisitor::new(
         &mut s,
@@ -130,10 +131,10 @@ fn imm_borrows_in_expr(cx: &LateContext<'_>, e: &hir::Expr<'_>) -> hir::HirIdSet
     s.0
 }
 
-fn mut_borrows_in_expr(cx: &LateContext<'_>, e: &hir::Expr<'_>) -> hir::HirIdSet {
-    struct S(hir::HirIdSet);
+fn mut_borrows_in_expr(cx: &LateContext<'_>, e: &hir::Expr<'_>) -> HirIdSet {
+    struct S(HirIdSet);
     impl Delegate<'_> for S {
-        fn borrow(&mut self, place: &PlaceWithHirId<'_>, _: hir::HirId, kind: BorrowKind) {
+        fn borrow(&mut self, place: &PlaceWithHirId<'_>, _: HirId, kind: BorrowKind) {
             if matches!(kind, BorrowKind::MutBorrow) {
                 self.0.insert(match place.place.base {
                     PlaceBase::Local(id) => id,
@@ -143,13 +144,13 @@ fn mut_borrows_in_expr(cx: &LateContext<'_>, e: &hir::Expr<'_>) -> hir::HirIdSet
             }
         }
 
-        fn consume(&mut self, _: &PlaceWithHirId<'_>, _: hir::HirId) {}
-        fn mutate(&mut self, _: &PlaceWithHirId<'_>, _: hir::HirId) {}
-        fn fake_read(&mut self, _: &PlaceWithHirId<'_>, _: FakeReadCause, _: hir::HirId) {}
-        fn copy(&mut self, _: &PlaceWithHirId<'_>, _: hir::HirId) {}
+        fn consume(&mut self, _: &PlaceWithHirId<'_>, _: HirId) {}
+        fn mutate(&mut self, _: &PlaceWithHirId<'_>, _: HirId) {}
+        fn fake_read(&mut self, _: &PlaceWithHirId<'_>, _: FakeReadCause, _: HirId) {}
+        fn copy(&mut self, _: &PlaceWithHirId<'_>, _: HirId) {}
     }
 
-    let mut s = S(hir::HirIdSet::default());
+    let mut s = S(HirIdSet::default());
     let infcx = cx.tcx.infer_ctxt().build();
     let mut v = ExprUseVisitor::new(
         &mut s,
diff --git a/src/tools/clippy/clippy_lints/src/ptr.rs b/src/tools/clippy/clippy_lints/src/ptr.rs
index 83b32000a9f..d6592622f0b 100644
--- a/src/tools/clippy/clippy_lints/src/ptr.rs
+++ b/src/tools/clippy/clippy_lints/src/ptr.rs
@@ -8,7 +8,7 @@ use clippy_utils::{get_expr_use_or_unification_node, is_lint_allowed, path_def_i
 use hir::LifetimeName;
 use rustc_errors::{Applicability, MultiSpan};
 use rustc_hir::def_id::DefId;
-use rustc_hir::hir_id::HirIdMap;
+use rustc_hir::hir_id::{HirId, HirIdMap};
 use rustc_hir::intravisit::{walk_expr, Visitor};
 use rustc_hir::{
     self as hir, AnonConst, BinOpKind, BindingAnnotation, Body, Expr, ExprKind, FnRetTy, FnSig, GenericArg,
@@ -324,7 +324,7 @@ struct PtrArgReplacement {
 
 struct PtrArg<'tcx> {
     idx: usize,
-    emission_id: hir::HirId,
+    emission_id: HirId,
     span: Span,
     ty_did: DefId,
     ty_name: Symbol,
diff --git a/src/tools/clippy/clippy_lints/src/significant_drop_tightening.rs b/src/tools/clippy/clippy_lints/src/significant_drop_tightening.rs
index d3540bc8e1c..038eb92d652 100644
--- a/src/tools/clippy/clippy_lints/src/significant_drop_tightening.rs
+++ b/src/tools/clippy/clippy_lints/src/significant_drop_tightening.rs
@@ -5,7 +5,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
 use rustc_errors::Applicability;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::intravisit::{walk_expr, Visitor};
-use rustc_hir::{self as hir};
+use rustc_hir::{self as hir, HirId};
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::ty::{GenericArgKind, Ty};
 use rustc_session::impl_lint_pass;
@@ -55,7 +55,7 @@ impl_lint_pass!(SignificantDropTightening<'_> => [SIGNIFICANT_DROP_TIGHTENING]);
 
 #[derive(Default)]
 pub struct SignificantDropTightening<'tcx> {
-    apas: FxIndexMap<hir::HirId, AuxParamsAttr>,
+    apas: FxIndexMap<HirId, AuxParamsAttr>,
     /// Auxiliary structure used to avoid having to verify the same type multiple times.
     seen_types: FxHashSet<Ty<'tcx>>,
     type_cache: FxHashMap<Ty<'tcx>, bool>,
@@ -359,9 +359,9 @@ impl<'ap, 'lc, 'others, 'stmt, 'tcx> Visitor<'tcx> for StmtsChecker<'ap, 'lc, 'o
 /// Auxiliary parameters used on each block check of an item
 struct AuxParams<'others, 'stmt, 'tcx> {
     //// See [AuxParamsAttr].
-    apas: &'others mut FxIndexMap<hir::HirId, AuxParamsAttr>,
+    apas: &'others mut FxIndexMap<HirId, AuxParamsAttr>,
     /// The current block identifier that is being visited.
-    curr_block_hir_id: hir::HirId,
+    curr_block_hir_id: HirId,
     /// The current block span that is being visited.
     curr_block_span: Span,
     /// The current statement that is being visited.
@@ -369,10 +369,10 @@ struct AuxParams<'others, 'stmt, 'tcx> {
 }
 
 impl<'others, 'stmt, 'tcx> AuxParams<'others, 'stmt, 'tcx> {
-    fn new(apas: &'others mut FxIndexMap<hir::HirId, AuxParamsAttr>, curr_stmt: &'stmt hir::Stmt<'tcx>) -> Self {
+    fn new(apas: &'others mut FxIndexMap<HirId, AuxParamsAttr>, curr_stmt: &'stmt hir::Stmt<'tcx>) -> Self {
         Self {
             apas,
-            curr_block_hir_id: hir::HirId::INVALID,
+            curr_block_hir_id: HirId::INVALID,
             curr_block_span: DUMMY_SP,
             curr_stmt: Cow::Borrowed(curr_stmt),
         }
@@ -389,7 +389,7 @@ struct AuxParamsAttr {
     has_expensive_expr_after_last_attr: bool,
 
     /// The identifier of the block that involves the first `#[has_significant_drop]`.
-    first_block_hir_id: hir::HirId,
+    first_block_hir_id: HirId,
     /// The span of the block that involves the first `#[has_significant_drop]`.
     first_block_span: Span,
     /// The binding or variable that references the initial construction of the type marked with
@@ -414,7 +414,7 @@ impl Default for AuxParamsAttr {
         Self {
             counter: 0,
             has_expensive_expr_after_last_attr: false,
-            first_block_hir_id: hir::HirId::INVALID,
+            first_block_hir_id: HirId::INVALID,
             first_bind_ident: Ident::empty(),
             first_block_span: DUMMY_SP,
             first_method_span: DUMMY_SP,
@@ -428,7 +428,7 @@ impl Default for AuxParamsAttr {
 
 fn dummy_stmt_expr<'any>(expr: &'any hir::Expr<'any>) -> hir::Stmt<'any> {
     hir::Stmt {
-        hir_id: hir::HirId::INVALID,
+        hir_id: HirId::INVALID,
         kind: hir::StmtKind::Expr(expr),
         span: DUMMY_SP,
     }
diff --git a/src/tools/clippy/clippy_lints/src/zero_sized_map_values.rs b/src/tools/clippy/clippy_lints/src/zero_sized_map_values.rs
index d1f7c6417c7..e14480b8655 100644
--- a/src/tools/clippy/clippy_lints/src/zero_sized_map_values.rs
+++ b/src/tools/clippy/clippy_lints/src/zero_sized_map_values.rs
@@ -4,7 +4,7 @@ use rustc_hir::{self as hir, HirId, ItemKind, Node};
 use rustc_hir_analysis::lower_ty;
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty::layout::LayoutOf as _;
-use rustc_middle::ty::{Adt, Ty, TypeVisitableExt};
+use rustc_middle::ty::{self, Ty, TypeVisitableExt};
 use rustc_session::declare_lint_pass;
 use rustc_span::sym;
 
@@ -49,7 +49,7 @@ impl LateLintPass<'_> for ZeroSizedMapValues {
             && !in_trait_impl(cx, hir_ty.hir_id)
             && let ty = ty_from_hir_ty(cx, hir_ty)
             && (is_type_diagnostic_item(cx, ty, sym::HashMap) || is_type_diagnostic_item(cx, ty, sym::BTreeMap))
-            && let Adt(_, args) = ty.kind()
+            && let ty::Adt(_, args) = ty.kind()
             && let ty = args.type_at(1)
             // Fixes https://github.com/rust-lang/rust-clippy/issues/7447 because of
             // https://github.com/rust-lang/rust/blob/master/compiler/rustc_middle/src/ty/sty.rs#L968
diff --git a/src/tools/clippy/clippy_utils/src/ast_utils.rs b/src/tools/clippy/clippy_utils/src/ast_utils.rs
index f594a40ff59..9f0bd4ea7e2 100644
--- a/src/tools/clippy/clippy_utils/src/ast_utils.rs
+++ b/src/tools/clippy/clippy_utils/src/ast_utils.rs
@@ -709,7 +709,8 @@ pub fn eq_ty(l: &Ty, r: &Ty) -> bool {
         (Tup(l), Tup(r)) => over(l, r, |l, r| eq_ty(l, r)),
         (Path(lq, lp), Path(rq, rp)) => both(lq, rq, eq_qself) && eq_path(lp, rp),
         (TraitObject(lg, ls), TraitObject(rg, rs)) => ls == rs && over(lg, rg, eq_generic_bound),
-        (ImplTrait(_, lg), ImplTrait(_, rg)) => over(lg, rg, eq_generic_bound),
+        (ImplTrait(_, lg, lc), ImplTrait(_, rg, rc)) =>
+            over(lg, rg, eq_generic_bound) && both(lc, rc, |lc, rc| over(lc.0.as_slice(), rc.0.as_slice(), eq_precise_capture)),
         (Typeof(l), Typeof(r)) => eq_expr(&l.value, &r.value),
         (MacCall(l), MacCall(r)) => eq_mac_call(l, r),
         _ => false,
@@ -770,6 +771,14 @@ pub fn eq_generic_bound(l: &GenericBound, r: &GenericBound) -> bool {
     }
 }
 
+pub fn eq_precise_capture(l: &PreciseCapturingArg, r: &PreciseCapturingArg) -> bool {
+    match (l, r) {
+        (PreciseCapturingArg::Lifetime(l), PreciseCapturingArg::Lifetime(r)) => l.ident == r.ident,
+        (PreciseCapturingArg::Arg(l, _), PreciseCapturingArg::Arg(r, _)) => l.segments[0].ident == r.segments[0].ident,
+        _ => false,
+    }
+}
+
 fn eq_term(l: &Term, r: &Term) -> bool {
     match (l, r) {
         (Term::Ty(l), Term::Ty(r)) => eq_ty(l, r),
diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs
index ab1be66dc78..1afc5ed0157 100644
--- a/src/tools/clippy/clippy_utils/src/ty.rs
+++ b/src/tools/clippy/clippy_utils/src/ty.rs
@@ -10,7 +10,7 @@ use rustc_hir as hir;
 use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
 use rustc_hir::def_id::DefId;
 use rustc_hir::{Expr, FnDecl, LangItem, TyKind, Unsafety};
-use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
+use rustc_infer::infer::type_variable::{TypeVariableOrigin};
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_lint::LateContext;
 use rustc_middle::mir::interpret::Scalar;
@@ -276,8 +276,8 @@ pub fn implements_trait_with_env_from_iter<'tcx>(
         .map(|arg| {
             arg.into().unwrap_or_else(|| {
                 let orig = TypeVariableOrigin {
-                    kind: TypeVariableOriginKind::MiscVariable,
                     span: DUMMY_SP,
+                    param_def_id: None,
                 };
                 infcx.next_ty_var(orig).into()
             })
diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs
index f78e0363f55..f5d7ce1c5f9 100644
--- a/src/tools/compiletest/src/header.rs
+++ b/src/tools/compiletest/src/header.rs
@@ -265,7 +265,10 @@ impl TestProps {
             aux_bins: vec![],
             aux_crates: vec![],
             revisions: vec![],
-            rustc_env: vec![("RUSTC_ICE".to_string(), "0".to_string())],
+            rustc_env: vec![
+                ("RUSTC_ICE".to_string(), "0".to_string()),
+                ("RUST_BACKTRACE".to_string(), "short".to_string()),
+            ],
             unset_rustc_env: vec![("RUSTC_LOG_COLOR".to_string())],
             exec_env: vec![],
             unset_exec_env: vec![],
@@ -839,6 +842,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[
     "needs-profiler-support",
     "needs-relocation-model-pic",
     "needs-run-enabled",
+    "needs-rust-lld",
     "needs-rust-lldb",
     "needs-sanitizer-address",
     "needs-sanitizer-cfi",
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index 38d22fef113..1dd639a8918 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -2173,8 +2173,8 @@ impl<'test> TestCx<'test> {
         let aux_dir = self.aux_output_dir();
         self.build_all_auxiliary(&self.testpaths, &aux_dir, &mut rustc);
 
-        self.props.unset_rustc_env.iter().fold(&mut rustc, Command::env_remove);
         rustc.envs(self.props.rustc_env.clone());
+        self.props.unset_rustc_env.iter().fold(&mut rustc, Command::env_remove);
         self.compose_and_run(
             rustc,
             self.config.compile_lib_path.to_str().unwrap(),
@@ -2220,10 +2220,10 @@ impl<'test> TestCx<'test> {
         );
         aux_cx.build_all_auxiliary(of, &aux_dir, &mut aux_rustc);
 
+        aux_rustc.envs(aux_props.rustc_env.clone());
         for key in &aux_props.unset_rustc_env {
             aux_rustc.env_remove(key);
         }
-        aux_rustc.envs(aux_props.rustc_env.clone());
 
         let (aux_type, crate_type) = if is_bin {
             (AuxType::Bin, Some("bin"))
diff --git a/src/tools/lint-docs/src/lib.rs b/src/tools/lint-docs/src/lib.rs
index b7c8b9ed2e3..2566124a037 100644
--- a/src/tools/lint-docs/src/lib.rs
+++ b/src/tools/lint-docs/src/lib.rs
@@ -270,7 +270,6 @@ impl<'a> LintExtractor<'a> {
         if matches!(
             lint.name.as_str(),
             "unused_features" // broken lint
-            | "unstable_features" // deprecated
         ) {
             return Ok(());
         }
diff --git a/src/tools/miri/cargo-miri/src/phases.rs b/src/tools/miri/cargo-miri/src/phases.rs
index ca8b35a17be..b774ca8fa72 100644
--- a/src/tools/miri/cargo-miri/src/phases.rs
+++ b/src/tools/miri/cargo-miri/src/phases.rs
@@ -412,8 +412,11 @@ pub fn phase_rustc(mut args: impl Iterator<Item = String>, phase: RustcPhase) {
     // Arguments are treated very differently depending on whether this crate is
     // for interpretation by Miri, or for use by a build script / proc macro.
     if target_crate {
-        // Set the sysroot.
-        cmd.arg("--sysroot").arg(env::var_os("MIRI_SYSROOT").unwrap());
+        if phase != RustcPhase::Setup {
+            // Set the sysroot -- except during setup, where we don't have an existing sysroot yet
+            // and where the bootstrap wrapper adds its own `--sysroot` flag so we can't set ours.
+            cmd.arg("--sysroot").arg(env::var_os("MIRI_SYSROOT").unwrap());
+        }
 
         // Forward arguments, but patched.
         let emit_flag = "--emit";
@@ -578,9 +581,9 @@ pub fn phase_runner(mut binary_args: impl Iterator<Item = String>, phase: Runner
     }
 
     if phase != RunnerPhase::Rustdoc {
-        // Set the sysroot. Not necessary in rustdoc, where we already set the sysroot when invoking
-        // rustdoc itself, which will forward that flag when invoking rustc (i.e., us), so the flag
-        // is present in `info.args`.
+        // Set the sysroot. Not necessary in rustdoc, where we already set the sysroot in
+        // `phase_rustdoc`. rustdoc will forward that flag when invoking rustc (i.e., us), so the
+        // flag is present in `info.args`.
         cmd.arg("--sysroot").arg(env::var_os("MIRI_SYSROOT").unwrap());
     }
     // Forward rustc arguments.
diff --git a/src/tools/miri/src/borrow_tracker/mod.rs b/src/tools/miri/src/borrow_tracker/mod.rs
index 8d76a488269..f21315790a5 100644
--- a/src/tools/miri/src/borrow_tracker/mod.rs
+++ b/src/tools/miri/src/borrow_tracker/mod.rs
@@ -260,7 +260,7 @@ impl GlobalStateInner {
         &mut self,
         id: AllocId,
         alloc_size: Size,
-        kind: MemoryKind<machine::MiriMemoryKind>,
+        kind: MemoryKind,
         machine: &MiriMachine<'_, '_>,
     ) -> AllocState {
         match self.borrow_tracker_method {
diff --git a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs
index 96ff298402d..b4005515d9d 100644
--- a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs
+++ b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs
@@ -509,7 +509,7 @@ impl Stacks {
         id: AllocId,
         size: Size,
         state: &mut GlobalStateInner,
-        kind: MemoryKind<MiriMemoryKind>,
+        kind: MemoryKind,
         machine: &MiriMachine<'_, '_>,
     ) -> Self {
         let (base_tag, perm) = match kind {
diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs
index a3d49756e4c..492e324de45 100644
--- a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs
+++ b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs
@@ -34,7 +34,7 @@ impl<'tcx> Tree {
         id: AllocId,
         size: Size,
         state: &mut GlobalStateInner,
-        _kind: MemoryKind<machine::MiriMemoryKind>,
+        _kind: MemoryKind,
         machine: &MiriMachine<'_, 'tcx>,
     ) -> Self {
         let tag = state.base_ptr_tag(id, machine); // Fresh tag for the root
diff --git a/src/tools/miri/src/concurrency/data_race.rs b/src/tools/miri/src/concurrency/data_race.rs
index d51160b2831..95049b91cba 100644
--- a/src/tools/miri/src/concurrency/data_race.rs
+++ b/src/tools/miri/src/concurrency/data_race.rs
@@ -844,7 +844,7 @@ impl VClockAlloc {
         global: &GlobalState,
         thread_mgr: &ThreadManager<'_, '_>,
         len: Size,
-        kind: MemoryKind<MiriMemoryKind>,
+        kind: MemoryKind,
         current_span: Span,
     ) -> VClockAlloc {
         let (alloc_timestamp, alloc_index) = match kind {
diff --git a/src/tools/miri/src/diagnostics.rs b/src/tools/miri/src/diagnostics.rs
index dfbcaaac5c6..d44d04e9bf8 100644
--- a/src/tools/miri/src/diagnostics.rs
+++ b/src/tools/miri/src/diagnostics.rs
@@ -115,7 +115,7 @@ pub enum NonHaltingDiagnostic {
     /// This `Item` was popped from the borrow stack. The string explains the reason.
     PoppedPointerTag(Item, String),
     CreatedCallId(CallId),
-    CreatedAlloc(AllocId, Size, Align, MemoryKind<MiriMemoryKind>),
+    CreatedAlloc(AllocId, Size, Align, MemoryKind),
     FreedAlloc(AllocId),
     AccessedAlloc(AllocId, AccessKind),
     RejectedIsolatedOp(String),
@@ -447,7 +447,7 @@ pub fn report_error<'tcx, 'mir>(
 
 pub fn report_leaks<'mir, 'tcx>(
     ecx: &InterpCx<'mir, 'tcx, MiriMachine<'mir, 'tcx>>,
-    leaks: Vec<(AllocId, MemoryKind<MiriMemoryKind>, Allocation<Provenance, AllocExtra<'tcx>>)>,
+    leaks: Vec<(AllocId, MemoryKind, Allocation<Provenance, AllocExtra<'tcx>>)>,
 ) {
     let mut any_pruned = false;
     for (id, kind, mut alloc) in leaks {
diff --git a/src/tools/miri/src/lib.rs b/src/tools/miri/src/lib.rs
index fbe4c9c6760..2e19c9ff713 100644
--- a/src/tools/miri/src/lib.rs
+++ b/src/tools/miri/src/lib.rs
@@ -128,7 +128,7 @@ pub use crate::eval::{
 };
 pub use crate::helpers::{AccessKind, EvalContextExt as _};
 pub use crate::machine::{
-    AllocExtra, FrameExtra, MiriInterpCx, MiriInterpCxExt, MiriMachine, MiriMemoryKind,
+    AllocExtra, FrameExtra, MemoryKind, MiriInterpCx, MiriInterpCxExt, MiriMachine, MiriMemoryKind,
     PrimitiveLayouts, Provenance, ProvenanceExtra,
 };
 pub use crate::mono_hash_map::MonoHashMap;
diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs
index ff081328a72..1d06d5c69d3 100644
--- a/src/tools/miri/src/machine.rs
+++ b/src/tools/miri/src/machine.rs
@@ -135,9 +135,9 @@ pub enum MiriMemoryKind {
     Mmap,
 }
 
-impl From<MiriMemoryKind> for MemoryKind<MiriMemoryKind> {
+impl From<MiriMemoryKind> for MemoryKind {
     #[inline(always)]
-    fn from(kind: MiriMemoryKind) -> MemoryKind<MiriMemoryKind> {
+    fn from(kind: MiriMemoryKind) -> MemoryKind {
         MemoryKind::Machine(kind)
     }
 }
@@ -185,6 +185,8 @@ impl fmt::Display for MiriMemoryKind {
     }
 }
 
+pub type MemoryKind = interpret::MemoryKind<MiriMemoryKind>;
+
 /// Pointer provenance.
 #[derive(Clone, Copy)]
 pub enum Provenance {
@@ -863,10 +865,8 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
     type ProvenanceExtra = ProvenanceExtra;
     type Bytes = Box<[u8]>;
 
-    type MemoryMap = MonoHashMap<
-        AllocId,
-        (MemoryKind<MiriMemoryKind>, Allocation<Provenance, Self::AllocExtra, Self::Bytes>),
-    >;
+    type MemoryMap =
+        MonoHashMap<AllocId, (MemoryKind, Allocation<Provenance, Self::AllocExtra, Self::Bytes>)>;
 
     const GLOBAL_KIND: Option<MiriMemoryKind> = Some(MiriMemoryKind::Global);
 
@@ -1088,7 +1088,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
         ecx: &MiriInterpCx<'mir, 'tcx>,
         id: AllocId,
         alloc: Cow<'b, Allocation>,
-        kind: Option<MemoryKind<Self::MemoryKind>>,
+        kind: Option<MemoryKind>,
     ) -> InterpResult<'tcx, Cow<'b, Allocation<Self::Provenance, Self::AllocExtra>>> {
         let kind = kind.expect("we set our STATIC_KIND so this cannot be None");
         if ecx.machine.tracked_alloc_ids.contains(&id) {
@@ -1280,6 +1280,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
         (alloc_id, prove_extra): (AllocId, Self::ProvenanceExtra),
         size: Size,
         align: Align,
+        _kind: MemoryKind,
     ) -> InterpResult<'tcx> {
         if machine.tracked_alloc_ids.contains(&alloc_id) {
             machine.emit_diagnostic(NonHaltingDiagnostic::FreedAlloc(alloc_id));
diff --git a/src/tools/miri/src/shims/os_str.rs b/src/tools/miri/src/shims/os_str.rs
index 0157c4845c5..0409e31d65a 100644
--- a/src/tools/miri/src/shims/os_str.rs
+++ b/src/tools/miri/src/shims/os_str.rs
@@ -137,7 +137,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
     fn alloc_os_str_as_c_str(
         &mut self,
         os_str: &OsStr,
-        memkind: MemoryKind<MiriMemoryKind>,
+        memkind: MemoryKind,
     ) -> InterpResult<'tcx, Pointer<Option<Provenance>>> {
         let size = u64::try_from(os_str.len()).unwrap().checked_add(1).unwrap(); // Make space for `0` terminator.
         let this = self.eval_context_mut();
@@ -153,7 +153,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
     fn alloc_os_str_as_wide_str(
         &mut self,
         os_str: &OsStr,
-        memkind: MemoryKind<MiriMemoryKind>,
+        memkind: MemoryKind,
     ) -> InterpResult<'tcx, Pointer<Option<Provenance>>> {
         let size = u64::try_from(os_str.len()).unwrap().checked_add(1).unwrap(); // Make space for `0x0000` terminator.
         let this = self.eval_context_mut();
@@ -230,7 +230,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
     fn alloc_path_as_c_str(
         &mut self,
         path: &Path,
-        memkind: MemoryKind<MiriMemoryKind>,
+        memkind: MemoryKind,
     ) -> InterpResult<'tcx, Pointer<Option<Provenance>>> {
         let this = self.eval_context_mut();
         let os_str =
@@ -243,7 +243,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
     fn alloc_path_as_wide_str(
         &mut self,
         path: &Path,
-        memkind: MemoryKind<MiriMemoryKind>,
+        memkind: MemoryKind,
     ) -> InterpResult<'tcx, Pointer<Option<Provenance>>> {
         let this = self.eval_context_mut();
         let os_str =
diff --git a/src/tools/miri/tests/fail/both_borrows/newtype_pair_retagging.stack.stderr b/src/tools/miri/tests/fail/both_borrows/newtype_pair_retagging.stack.stderr
index 867907e98e6..c26c7f397b0 100644
--- a/src/tools/miri/tests/fail/both_borrows/newtype_pair_retagging.stack.stderr
+++ b/src/tools/miri/tests/fail/both_borrows/newtype_pair_retagging.stack.stderr
@@ -6,7 +6,7 @@ LL |         Box(unsafe { Unique::new_unchecked(raw) }, alloc)
    |
    = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental
    = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information
-help: <TAG> was created by a Unique retag at offsets [0x0..0x4]
+help: <TAG> was created by a SharedReadWrite retag at offsets [0x0..0x4]
   --> $DIR/newtype_pair_retagging.rs:LL:CC
    |
 LL |     let ptr = Box::into_raw(Box::new(0i32));
diff --git a/src/tools/miri/tests/fail/both_borrows/newtype_retagging.stack.stderr b/src/tools/miri/tests/fail/both_borrows/newtype_retagging.stack.stderr
index 56715938e97..ae54da70fe2 100644
--- a/src/tools/miri/tests/fail/both_borrows/newtype_retagging.stack.stderr
+++ b/src/tools/miri/tests/fail/both_borrows/newtype_retagging.stack.stderr
@@ -6,7 +6,7 @@ LL |         Box(unsafe { Unique::new_unchecked(raw) }, alloc)
    |
    = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental
    = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information
-help: <TAG> was created by a Unique retag at offsets [0x0..0x4]
+help: <TAG> was created by a SharedReadWrite retag at offsets [0x0..0x4]
   --> $DIR/newtype_retagging.rs:LL:CC
    |
 LL |     let ptr = Box::into_raw(Box::new(0i32));
diff --git a/src/tools/miri/tests/pass/issues/issue-miri-3473.rs b/src/tools/miri/tests/pass/issues/issue-miri-3473.rs
new file mode 100644
index 00000000000..77b960c1cdc
--- /dev/null
+++ b/src/tools/miri/tests/pass/issues/issue-miri-3473.rs
@@ -0,0 +1,28 @@
+//@revisions: stack tree
+//@[tree]compile-flags: -Zmiri-tree-borrows
+use std::cell::UnsafeCell;
+
+#[repr(C)]
+#[derive(Default)]
+struct Node {
+    _meta: UnsafeCell<usize>,
+    value: usize,
+}
+
+impl Node {
+    fn value(&self) -> &usize {
+        &self.value
+    }
+}
+
+/// This used to cause Stacked Borrows errors because of trouble around conversion
+/// from Box to raw pointer.
+fn main() {
+    unsafe {
+        let a = Box::into_raw(Box::new(Node::default()));
+        let ptr = &*a;
+        *UnsafeCell::raw_get(a.cast::<UnsafeCell<usize>>()) = 2;
+        assert_eq!(*ptr.value(), 0);
+        drop(Box::from_raw(a));
+    }
+}
diff --git a/src/tools/miri/tests/pass/stacked-borrows/stacked-borrows.rs b/src/tools/miri/tests/pass/stacked-borrows/stacked-borrows.rs
index 734411ccc72..43ba490d5bb 100644
--- a/src/tools/miri/tests/pass/stacked-borrows/stacked-borrows.rs
+++ b/src/tools/miri/tests/pass/stacked-borrows/stacked-borrows.rs
@@ -20,6 +20,7 @@ fn main() {
     wide_raw_ptr_in_tuple();
     not_unpin_not_protected();
     write_does_not_invalidate_all_aliases();
+    box_into_raw_allows_interior_mutable_alias();
 }
 
 // Make sure that reading from an `&mut` does, like reborrowing to `&`,
@@ -263,3 +264,14 @@ fn write_does_not_invalidate_all_aliases() {
     other::lib2();
     assert_eq!(*x, 1337); // oops, the value changed! I guess not all pointers were invalidated
 }
+
+fn box_into_raw_allows_interior_mutable_alias() { unsafe {
+    let b = Box::new(std::cell::Cell::new(42));
+    let raw = Box::into_raw(b);
+    let c = &*raw;
+    let d = raw.cast::<i32>(); // bypassing `Cell` -- only okay in Miri tests
+    // `c` and `d` should permit arbitrary aliasing with each other now.
+    *d = 1;
+    c.set(2);
+    drop(Box::from_raw(raw));
+} }
diff --git a/src/tools/run-make-support/Cargo.toml b/src/tools/run-make-support/Cargo.toml
index d8bb8c643d1..3ea35c7940c 100644
--- a/src/tools/run-make-support/Cargo.toml
+++ b/src/tools/run-make-support/Cargo.toml
@@ -6,3 +6,4 @@ edition = "2021"
 [dependencies]
 object = "0.34.0"
 wasmparser = "0.118.2"
+regex = "1.8" # 1.8 to avoid memchr 2.6.0, as 2.5.0 is pinned in the workspace
diff --git a/src/tools/run-make-support/src/lib.rs b/src/tools/run-make-support/src/lib.rs
index 47b46a0a699..9a4fdff5d15 100644
--- a/src/tools/run-make-support/src/lib.rs
+++ b/src/tools/run-make-support/src/lib.rs
@@ -13,6 +13,7 @@ use std::path::{Path, PathBuf};
 use std::process::{Command, Output};
 
 pub use object;
+pub use regex;
 pub use wasmparser;
 
 pub use cc::{cc, extra_c_flags, extra_cxx_flags, Cc};
diff --git a/src/tools/run-make-support/src/rustc.rs b/src/tools/run-make-support/src/rustc.rs
index ebda151b908..9bf41c6e2e9 100644
--- a/src/tools/run-make-support/src/rustc.rs
+++ b/src/tools/run-make-support/src/rustc.rs
@@ -128,9 +128,8 @@ impl Rustc {
         self
     }
 
-    /// Specify target triple.
+    /// Specify the target triple, or a path to a custom target json spec file.
     pub fn target(&mut self, target: &str) -> &mut Self {
-        assert!(!target.contains(char::is_whitespace), "target triple cannot contain spaces");
         self.cmd.arg(format!("--target={target}"));
         self
     }
@@ -149,6 +148,12 @@ impl Rustc {
         self
     }
 
+    /// Add an extra argument to the linker invocation, via `-Clink-arg`.
+    pub fn link_arg(&mut self, link_arg: &str) -> &mut Self {
+        self.cmd.arg(format!("-Clink-arg={link_arg}"));
+        self
+    }
+
     #[track_caller]
     pub fn run_fail_assert_exit_code(&mut self, code: i32) -> Output {
         let caller_location = std::panic::Location::caller();
diff --git a/src/tools/rustfmt/src/macros.rs b/src/tools/rustfmt/src/macros.rs
index 8d77d2b3254..6b24b1aec5d 100644
--- a/src/tools/rustfmt/src/macros.rs
+++ b/src/tools/rustfmt/src/macros.rs
@@ -1091,7 +1091,7 @@ fn next_space(tok: &TokenKind) -> SpaceState {
         | TokenKind::DotDotEq
         | TokenKind::Question => SpaceState::Punctuation,
 
-        TokenKind::ModSep
+        TokenKind::PathSep
         | TokenKind::Pound
         | TokenKind::Dollar
         | TokenKind::OpenDelim(_)
diff --git a/src/tools/rustfmt/src/types.rs b/src/tools/rustfmt/src/types.rs
index 10a87f6e698..fe2d28ae1b9 100644
--- a/src/tools/rustfmt/src/types.rs
+++ b/src/tools/rustfmt/src/types.rs
@@ -843,7 +843,11 @@ impl Rewrite for ast::Ty {
                 rewrite_macro(mac, None, context, shape, MacroPosition::Expression)
             }
             ast::TyKind::ImplicitSelf => Some(String::from("")),
-            ast::TyKind::ImplTrait(_, ref it) => {
+            ast::TyKind::ImplTrait(_, ref it, ref captures) => {
+                // FIXME(precise_capturing): Implement formatting.
+                if captures.is_some() {
+                    return None;
+                }
                 // Empty trait is not a parser error.
                 if it.is_empty() {
                     return Some("impl".to_owned());
@@ -1106,7 +1110,8 @@ fn join_bounds_inner(
 
 pub(crate) fn opaque_ty(ty: &Option<ptr::P<ast::Ty>>) -> Option<&ast::GenericBounds> {
     ty.as_ref().and_then(|t| match &t.kind {
-        ast::TyKind::ImplTrait(_, bounds) => Some(bounds),
+        // FIXME(precise_capturing): Implement support here
+        ast::TyKind::ImplTrait(_, bounds, _) => Some(bounds),
         _ => None,
     })
 }
diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt
index 3914feb3499..f0ed0ae806f 100644
--- a/src/tools/tidy/src/allowed_run_make_makefiles.txt
+++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt
@@ -249,8 +249,6 @@ run-make/rlib-format-packed-bundled-libs-2/Makefile
 run-make/rlib-format-packed-bundled-libs-3/Makefile
 run-make/rlib-format-packed-bundled-libs/Makefile
 run-make/rmeta-preferred/Makefile
-run-make/rust-lld-custom-target/Makefile
-run-make/rust-lld/Makefile
 run-make/rustc-macro-dep-files/Makefile
 run-make/rustdoc-determinism/Makefile
 run-make/rustdoc-error-lines/Makefile
diff --git a/tests/crashes/123153.rs b/tests/crashes/123153.rs
deleted file mode 100644
index d2c32ecd73e..00000000000
--- a/tests/crashes/123153.rs
+++ /dev/null
@@ -1,17 +0,0 @@
-//@ known-bug: #123153
-pub struct wl_interface {
-    pub version: str,
-}
-
-pub struct Interface {
-    pub other_interfaces: &'static [&'static Interface],
-    pub c_ptr: Option<&'static wl_interface>,
-}
-
-pub static mut wl_callback_interface: wl_interface = wl_interface { version: 0 };
-
-pub static WL_CALLBACK_INTERFACE: Interface =
-    Interface { other_interfaces: &[], c_ptr: Some(unsafe { &wl_callback_interface }) };
-
-
-fn main() {}
diff --git a/tests/crashes/123154.rs b/tests/crashes/123154.rs
deleted file mode 100644
index 510ae8adf35..00000000000
--- a/tests/crashes/123154.rs
+++ /dev/null
@@ -1,12 +0,0 @@
-//@ known-bug: #123154
-struct AA {
-    pub data: [&usize]
-}
-
-impl AA {
-    const fn new() -> Self { }
-}
-
-static AA = AA::new();
-
-fn main() { }
diff --git a/tests/crashes/README.md b/tests/crashes/README.md
index dee11e2a3dd..71ce9b2eca6 100644
--- a/tests/crashes/README.md
+++ b/tests/crashes/README.md
@@ -14,3 +14,10 @@ If you happen to fix one of the crashes, please move it to a fitting
 subdirectory in `tests/ui` and give it a meaningful name.
 Also please add a doc comment at the top of the file explaining why
 this test exists. :)
+Adding
+Fixes #NNNNN
+Fixes #MMMMM
+to the description of your pull request will ensure the
+corresponding tickets will be closed automatically upon merge.
+The ticket ids can be found in the file name or the `known-bug` annotation
+inside the testfile.
diff --git a/tests/debuginfo/include_string.rs b/tests/debuginfo/include_string.rs
index 75013ab5274..628ac92fe34 100644
--- a/tests/debuginfo/include_string.rs
+++ b/tests/debuginfo/include_string.rs
@@ -1,4 +1,6 @@
 //@ min-lldb-version: 310
+//@ ignore-gdb-version: 15.0 - 99.0
+// ^ test temporarily disabled as it fails under gdb 15
 
 //@ compile-flags:-g
 // gdb-command:run
diff --git a/tests/debuginfo/vec-slices.rs b/tests/debuginfo/vec-slices.rs
index 5a8481699b2..a8235dba40c 100644
--- a/tests/debuginfo/vec-slices.rs
+++ b/tests/debuginfo/vec-slices.rs
@@ -1,4 +1,6 @@
 //@ min-lldb-version: 310
+//@ ignore-gdb-version: 15.0 - 99.0
+// ^ test temporarily disabled as it fails under gdb 15
 
 //@ compile-flags:-g
 
diff --git a/tests/run-make/artifact-incr-cache-no-obj/lib.rs b/tests/run-make/artifact-incr-cache-no-obj/lib.rs
new file mode 100644
index 00000000000..fa4048594e3
--- /dev/null
+++ b/tests/run-make/artifact-incr-cache-no-obj/lib.rs
@@ -0,0 +1,6 @@
+#![crate_name = "foo"]
+
+#[inline(never)]
+pub fn add(a: u32, b: u32) -> u32 {
+    a + b
+}
diff --git a/tests/run-make/artifact-incr-cache-no-obj/rmake.rs b/tests/run-make/artifact-incr-cache-no-obj/rmake.rs
new file mode 100644
index 00000000000..de55de2a1ee
--- /dev/null
+++ b/tests/run-make/artifact-incr-cache-no-obj/rmake.rs
@@ -0,0 +1,23 @@
+// emitting an object file is not necessary if user didn't ask for one
+//
+// This test is similar to run-make/artifact-incr-cache but it doesn't
+// require to emit an object file
+//
+// Fixes: rust-lang/rust#123234
+
+extern crate run_make_support;
+
+use run_make_support::{rustc, tmp_dir};
+
+fn main() {
+    let inc_dir = tmp_dir();
+
+    for _ in 0..=1 {
+        rustc()
+            .input("lib.rs")
+            .crate_type("lib")
+            .emit("asm,dep-info,link,mir,llvm-ir,llvm-bc")
+            .incremental(&inc_dir)
+            .run();
+    }
+}
diff --git a/tests/run-make/relro-levels/Makefile b/tests/run-make/relro-levels/Makefile
index e0402f59f12..94f08bcb494 100644
--- a/tests/run-make/relro-levels/Makefile
+++ b/tests/run-make/relro-levels/Makefile
@@ -3,20 +3,20 @@ include ../tools.mk
 
 # only-linux
 #
-# This tests the different -Zrelro-level values, and makes sure that they work properly.
+# This tests the different -Crelro-level values, and makes sure that they work properly.
 
 all:
 	# Ensure that binaries built with the full relro level links them with both
 	# RELRO and BIND_NOW for doing eager symbol resolving.
-	$(RUSTC) -Zrelro-level=full hello.rs
+	$(RUSTC) -Crelro-level=full hello.rs
 	readelf -l $(TMPDIR)/hello | grep -q GNU_RELRO
 	readelf -d $(TMPDIR)/hello | grep -q BIND_NOW
 
-	$(RUSTC) -Zrelro-level=partial hello.rs
+	$(RUSTC) -Crelro-level=partial hello.rs
 	readelf -l $(TMPDIR)/hello | grep -q GNU_RELRO
 
 	# Ensure that we're *not* built with RELRO when setting it to off.  We do
 	# not want to check for BIND_NOW however, as the linker might have that
 	# enabled by default.
-	$(RUSTC) -Zrelro-level=off hello.rs
+	$(RUSTC) -Crelro-level=off hello.rs
 	! readelf -l $(TMPDIR)/hello | grep -q GNU_RELRO
diff --git a/tests/run-make/rust-lld-custom-target/Makefile b/tests/run-make/rust-lld-custom-target/Makefile
deleted file mode 100644
index 007493ab0b9..00000000000
--- a/tests/run-make/rust-lld-custom-target/Makefile
+++ /dev/null
@@ -1,7 +0,0 @@
-include ../tools.mk
-
-# needs-rust-lld
-# only-x86_64-unknown-linux-gnu
-all:
-	RUSTC_LOG=rustc_codegen_ssa::back::link=info $(RUSTC) --crate-type cdylib --target custom-target.json -Clink-args=-Wl,-v lib.rs 2> $(TMPDIR)/output.txt
-	$(CGREP) -e "^LLD [0-9]+\.[0-9]+\.[0-9]+" < $(TMPDIR)/output.txt
diff --git a/tests/run-make/rust-lld-custom-target/rmake.rs b/tests/run-make/rust-lld-custom-target/rmake.rs
new file mode 100644
index 00000000000..b5341725e36
--- /dev/null
+++ b/tests/run-make/rust-lld-custom-target/rmake.rs
@@ -0,0 +1,51 @@
+// Test linking using `cc` with `rust-lld`, using a custom target with features described in MCP 510
+// see https://github.com/rust-lang/compiler-team/issues/510 for more info:
+//
+// Starting from the `x86_64-unknown-linux-gnu` target spec, we add the following options:
+// - a linker-flavor using lld via a C compiler
+// - the self-contained linker component is enabled
+
+//@ needs-rust-lld
+//@ only-x86_64-unknown-linux-gnu
+
+extern crate run_make_support;
+
+use run_make_support::regex::Regex;
+use run_make_support::rustc;
+use std::process::Output;
+
+fn main() {
+    // Compile to a custom target spec with rust-lld enabled by default. We'll check that by asking
+    // the linker to display its version number with a link-arg.
+    let output = rustc()
+        .env("RUSTC_LOG", "rustc_codegen_ssa::back::link=info")
+        .crate_type("cdylib")
+        .target("custom-target.json")
+        .link_arg("-Wl,-v")
+        .input("lib.rs")
+        .run();
+    assert!(
+        find_lld_version_in_logs(output),
+        "the LLD version string should be present in the output logs"
+    );
+
+    // But it can also be disabled via linker features.
+    let output = rustc()
+        .env("RUSTC_LOG", "rustc_codegen_ssa::back::link=info")
+        .crate_type("cdylib")
+        .target("custom-target.json")
+        .arg("-Zlinker-features=-lld")
+        .link_arg("-Wl,-v")
+        .input("lib.rs")
+        .run();
+    assert!(
+        !find_lld_version_in_logs(output),
+        "the LLD version string should not be present in the output logs"
+    );
+}
+
+fn find_lld_version_in_logs(output: Output) -> bool {
+    let lld_version_re = Regex::new(r"^LLD [0-9]+\.[0-9]+\.[0-9]+").unwrap();
+    let stderr = std::str::from_utf8(&output.stderr).unwrap();
+    stderr.lines().any(|line| lld_version_re.is_match(line))
+}
diff --git a/tests/run-make/rust-lld/Makefile b/tests/run-make/rust-lld/Makefile
deleted file mode 100644
index 1ecac479f41..00000000000
--- a/tests/run-make/rust-lld/Makefile
+++ /dev/null
@@ -1,12 +0,0 @@
-include ../tools.mk
-
-# ignore-msvc
-# needs-rust-lld
-# ignore-s390x lld does not yet support s390x as target
-all:
-	RUSTC_LOG=rustc_codegen_ssa::back::link=info $(RUSTC) -Clink-self-contained=+linker -Zlinker-features=+lld -Zunstable-options -Clink-args=-Wl,-v main.rs 2> $(TMPDIR)/output.txt
-	$(CGREP) -e "^LLD [0-9]+\.[0-9]+\.[0-9]+" < $(TMPDIR)/output.txt
-
-	# while we're here, also check that the last linker feature flag "wins"
-	RUSTC_LOG=rustc_codegen_ssa::back::link=info $(RUSTC) -Clink-self-contained=+linker -Zlinker-features=-lld -Zlinker-features=+lld -Zunstable-options -Clink-args=-Wl,-v main.rs 2> $(TMPDIR)/output.txt
-	$(CGREP) -e "^LLD [0-9]+\.[0-9]+\.[0-9]+" < $(TMPDIR)/output.txt
diff --git a/tests/run-make/rust-lld/rmake.rs b/tests/run-make/rust-lld/rmake.rs
new file mode 100644
index 00000000000..acb6d74aaa8
--- /dev/null
+++ b/tests/run-make/rust-lld/rmake.rs
@@ -0,0 +1,64 @@
+// Test linking using `cc` with `rust-lld`, using the unstable CLI described in MCP 510
+// see https://github.com/rust-lang/compiler-team/issues/510 for more info
+
+//@ needs-rust-lld
+//@ ignore-msvc
+//@ ignore-s390x lld does not yet support s390x as target
+
+extern crate run_make_support;
+
+use run_make_support::regex::Regex;
+use run_make_support::rustc;
+use std::process::Output;
+
+fn main() {
+    // Opt-in to lld and the self-contained linker, to link with rust-lld. We'll check that by
+    // asking the linker to display its version number with a link-arg.
+    let output = rustc()
+        .env("RUSTC_LOG", "rustc_codegen_ssa::back::link=info")
+        .arg("-Zlinker-features=+lld")
+        .arg("-Clink-self-contained=+linker")
+        .arg("-Zunstable-options")
+        .link_arg("-Wl,-v")
+        .input("main.rs")
+        .run();
+    assert!(
+        find_lld_version_in_logs(output),
+        "the LLD version string should be present in the output logs"
+    );
+
+    // It should not be used when we explictly opt-out of lld.
+    let output = rustc()
+        .env("RUSTC_LOG", "rustc_codegen_ssa::back::link=info")
+        .link_arg("-Wl,-v")
+        .arg("-Zlinker-features=-lld")
+        .input("main.rs")
+        .run();
+    assert!(
+        !find_lld_version_in_logs(output),
+        "the LLD version string should not be present in the output logs"
+    );
+
+    // While we're here, also check that the last linker feature flag "wins" when passed multiple
+    // times to rustc.
+    let output = rustc()
+        .env("RUSTC_LOG", "rustc_codegen_ssa::back::link=info")
+        .link_arg("-Wl,-v")
+        .arg("-Clink-self-contained=+linker")
+        .arg("-Zunstable-options")
+        .arg("-Zlinker-features=-lld")
+        .arg("-Zlinker-features=+lld")
+        .arg("-Zlinker-features=-lld,+lld")
+        .input("main.rs")
+        .run();
+    assert!(
+        find_lld_version_in_logs(output),
+        "the LLD version string should be present in the output logs"
+    );
+}
+
+fn find_lld_version_in_logs(output: Output) -> bool {
+    let lld_version_re = Regex::new(r"^LLD [0-9]+\.[0-9]+\.[0-9]+").unwrap();
+    let stderr = std::str::from_utf8(&output.stderr).unwrap();
+    stderr.lines().any(|line| lld_version_re.is_match(line))
+}
diff --git a/tests/rustdoc/auxiliary/issue-73061.rs b/tests/rustdoc-ui/auxiliary/issue-73061.rs
index 9a2e4aaf75e..9a2e4aaf75e 100644
--- a/tests/rustdoc/auxiliary/issue-73061.rs
+++ b/tests/rustdoc-ui/auxiliary/issue-73061.rs
diff --git a/tests/rustdoc-ui/check-cfg/check-cfg.rs b/tests/rustdoc-ui/check-cfg.rs
index 27b09985728..6ca37db75af 100644
--- a/tests/rustdoc-ui/check-cfg/check-cfg.rs
+++ b/tests/rustdoc-ui/check-cfg.rs
@@ -1,5 +1,5 @@
 //@ check-pass
-//@ compile-flags: --check-cfg=cfg() -Z unstable-options
+//@ compile-flags: --check-cfg=cfg()
 
 /// uniz is nor a builtin nor pass as arguments so is unexpected
 #[cfg(uniz)]
diff --git a/tests/rustdoc-ui/check-cfg/check-cfg.stderr b/tests/rustdoc-ui/check-cfg.stderr
index 3bca5dd0834..6f026cee41e 100644
--- a/tests/rustdoc-ui/check-cfg/check-cfg.stderr
+++ b/tests/rustdoc-ui/check-cfg.stderr
@@ -5,7 +5,7 @@ LL | #[cfg(uniz)]
    |       ^^^^ help: there is a config with a similar name: `unix`
    |
    = help: to expect this configuration use `--check-cfg=cfg(uniz)`
-   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
    = note: `#[warn(unexpected_cfgs)]` on by default
 
 warning: 1 warning emitted
diff --git a/tests/rustdoc-ui/check-cfg/check-cfg-test.stderr b/tests/rustdoc-ui/check-cfg/check-cfg-test.stderr
deleted file mode 100644
index 9770be2f191..00000000000
--- a/tests/rustdoc-ui/check-cfg/check-cfg-test.stderr
+++ /dev/null
@@ -1,11 +0,0 @@
-warning: unexpected `cfg` condition value
-  --> $DIR/check-cfg-test.rs:9:7
-   |
-LL | #[cfg(feature = "invalid")]
-   |       ^^^^^^^^^^^^^^^^^^^
-   |
-   = note: expected values for `feature` are: test
-   = note: `#[warn(unexpected_cfgs)]` on by default
-
-warning: 1 warning emitted
-
diff --git a/tests/rustdoc-ui/check-cfg/check-cfg-unstable.rs b/tests/rustdoc-ui/check-cfg/check-cfg-unstable.rs
deleted file mode 100644
index b24b198e807..00000000000
--- a/tests/rustdoc-ui/check-cfg/check-cfg-unstable.rs
+++ /dev/null
@@ -1,2 +0,0 @@
-//@ check-fail
-//@ compile-flags: --check-cfg=cfg()
diff --git a/tests/rustdoc-ui/check-cfg/check-cfg-unstable.stderr b/tests/rustdoc-ui/check-cfg/check-cfg-unstable.stderr
deleted file mode 100644
index 9b27c2bc058..00000000000
--- a/tests/rustdoc-ui/check-cfg/check-cfg-unstable.stderr
+++ /dev/null
@@ -1,2 +0,0 @@
-error: the `-Z unstable-options` flag must also be passed to enable the flag `check-cfg`
-
diff --git a/tests/rustdoc-ui/doctest/check-cfg-test.stderr b/tests/rustdoc-ui/doctest/check-cfg-test.stderr
index 5524f582d56..a2f173a2cb9 100644
--- a/tests/rustdoc-ui/doctest/check-cfg-test.stderr
+++ b/tests/rustdoc-ui/doctest/check-cfg-test.stderr
@@ -6,7 +6,7 @@ LL | #[cfg(feature = "invalid")]
    |
    = note: expected values for `feature` are: `test`
    = help: to expect this configuration use `--check-cfg=cfg(feature, values("invalid"))`
-   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
    = note: `#[warn(unexpected_cfgs)]` on by default
 
 warning: 1 warning emitted
diff --git a/tests/rustdoc/issue-56701.rs b/tests/rustdoc-ui/ice-blanket-impl-56701.rs
index ba00743fcd1..13b0fc9032a 100644
--- a/tests/rustdoc/issue-56701.rs
+++ b/tests/rustdoc-ui/ice-blanket-impl-56701.rs
@@ -1,4 +1,6 @@
+//@ check-pass
 // This shouldn't cause a stack overflow when rustdoc is run
+// https://github.com/rust-lang/rust/issues/56701
 
 use std::ops::Deref;
 use std::ops::DerefMut;
diff --git a/tests/rustdoc/issue-73061-cross-crate-opaque-assoc-type.rs b/tests/rustdoc-ui/ice-cross-crate-opaque-assoc-type-73061.rs
index e16aeac65cc..1434bef49e0 100644
--- a/tests/rustdoc/issue-73061-cross-crate-opaque-assoc-type.rs
+++ b/tests/rustdoc-ui/ice-cross-crate-opaque-assoc-type-73061.rs
@@ -1,5 +1,6 @@
-// Regression test for ICE #73061
+// Regression test for ICE https://github.com/rust-lang/rust/issues/73061
 
+//@ check-pass
 //@ aux-build:issue-73061.rs
 
 extern crate issue_73061;
diff --git a/tests/rustdoc/issue-78673.rs b/tests/rustdoc/blanket-impl-78673.rs
index d09141c3204..d7ceef2c057 100644
--- a/tests/rustdoc/issue-78673.rs
+++ b/tests/rustdoc/blanket-impl-78673.rs
@@ -1,3 +1,4 @@
+// https://github.com/rust-lang/rust/issues/78673
 #![crate_name = "issue_78673"]
 
 pub trait Something {}
diff --git a/tests/rustdoc/issue-76501.rs b/tests/rustdoc/const-fn-76501.rs
index 5caea0ec992..4a7284f9851 100644
--- a/tests/rustdoc/issue-76501.rs
+++ b/tests/rustdoc/const-fn-76501.rs
@@ -1,4 +1,7 @@
-// @has 'issue_76501/fn.bloop.html' '//pre' 'pub const fn bloop() -> i32'
+// https://github.com/rust-lang/rust/issues/76501
+#![crate_name="foo"]
+
+// @has 'foo/fn.bloop.html' '//pre' 'pub const fn bloop() -> i32'
 /// A useless function that always returns 1.
 pub const fn bloop() -> i32 {
     1
@@ -8,7 +11,7 @@ pub const fn bloop() -> i32 {
 pub struct Struct {}
 
 impl Struct {
-    // @has 'issue_76501/struct.Struct.html' '//*[@class="method"]' \
+    // @has 'foo/struct.Struct.html' '//*[@class="method"]' \
     // 'pub const fn blurp() -> i32'
     /// A useless function that always returns 1.
     pub const fn blurp() -> i32 {
diff --git a/tests/rustdoc/issue-79201.rs b/tests/rustdoc/doc-cfg-inherit-from-module-79201.rs
index f95d79cd493..76260c4a502 100644
--- a/tests/rustdoc/issue-79201.rs
+++ b/tests/rustdoc/doc-cfg-inherit-from-module-79201.rs
@@ -1,6 +1,9 @@
+// https://github.com/rust-lang/rust/issues/79201
+#![crate_name="foo"]
+
 #![feature(doc_cfg)]
 
-// @has 'issue_79201/trait.Foo.html'
+// @has 'foo/trait.Foo.html'
 // @count   - '//*[@class="stab portability"]' 6
 // @matches - '//*[@class="stab portability"]' 'crate feature foo-root'
 // @matches - '//*[@class="stab portability"]' 'crate feature foo-public-mod'
diff --git a/tests/rustdoc/issue-67851-both.rs b/tests/rustdoc/doc-hidden-private-67851-both.rs
index ed59652838e..e6eb6a68ffd 100644
--- a/tests/rustdoc/issue-67851-both.rs
+++ b/tests/rustdoc/doc-hidden-private-67851-both.rs
@@ -1,8 +1,10 @@
 //@ compile-flags: -Zunstable-options --document-private-items --document-hidden-items
+// https://github.com/rust-lang/rust/issues/67851
+#![crate_name="foo"]
 
-// @has issue_67851_both/struct.Hidden.html
+// @has foo/struct.Hidden.html
 #[doc(hidden)]
 pub struct Hidden;
 
-// @has issue_67851_both/struct.Private.html
+// @has foo/struct.Private.html
 struct Private;
diff --git a/tests/rustdoc/doc-hidden-private-67851-hidden.rs b/tests/rustdoc/doc-hidden-private-67851-hidden.rs
new file mode 100644
index 00000000000..9767f9c84f9
--- /dev/null
+++ b/tests/rustdoc/doc-hidden-private-67851-hidden.rs
@@ -0,0 +1,10 @@
+//@ compile-flags: -Zunstable-options --document-hidden-items
+// https://github.com/rust-lang/rust/issues/67851
+#![crate_name="foo"]
+
+// @has foo/struct.Hidden.html
+#[doc(hidden)]
+pub struct Hidden;
+
+// @!has foo/struct.Private.html
+struct Private;
diff --git a/tests/rustdoc/doc-hidden-private-67851-neither.rs b/tests/rustdoc/doc-hidden-private-67851-neither.rs
new file mode 100644
index 00000000000..6c6e84da43d
--- /dev/null
+++ b/tests/rustdoc/doc-hidden-private-67851-neither.rs
@@ -0,0 +1,9 @@
+// https://github.com/rust-lang/rust/issues/67851
+#![crate_name="foo"]
+
+// @!has foo/struct.Hidden.html
+#[doc(hidden)]
+pub struct Hidden;
+
+// @!has foo/struct.Private.html
+struct Private;
diff --git a/tests/rustdoc/doc-hidden-private-67851-private.rs b/tests/rustdoc/doc-hidden-private-67851-private.rs
new file mode 100644
index 00000000000..4aa39f5b789
--- /dev/null
+++ b/tests/rustdoc/doc-hidden-private-67851-private.rs
@@ -0,0 +1,10 @@
+//@ compile-flags: --document-private-items
+// https://github.com/rust-lang/rust/issues/67851
+#![crate_name="foo"]
+
+// @!has foo/struct.Hidden.html
+#[doc(hidden)]
+pub struct Hidden;
+
+// @has foo/struct.Private.html
+struct Private;
diff --git a/tests/rustdoc/issue-60522-duplicated-glob-reexport.rs b/tests/rustdoc/duplicated-glob-reexport-60522.rs
index 50def2c3cd9..50def2c3cd9 100644
--- a/tests/rustdoc/issue-60522-duplicated-glob-reexport.rs
+++ b/tests/rustdoc/duplicated-glob-reexport-60522.rs
diff --git a/tests/rustdoc/issue-74083.rs b/tests/rustdoc/hide-mut-methods-if-no-derefmut-impl-74083.rs
index c7f5d7eaa58..0bed7e2fb62 100644
--- a/tests/rustdoc/issue-74083.rs
+++ b/tests/rustdoc/hide-mut-methods-if-no-derefmut-impl-74083.rs
@@ -1,3 +1,6 @@
+// https://github.com/rust-lang/rust/issues/74083
+#![crate_name="foo"]
+
 use std::ops::Deref;
 
 pub struct Foo;
@@ -6,7 +9,7 @@ impl Foo {
     pub fn foo(&mut self) {}
 }
 
-// @has issue_74083/struct.Bar.html
+// @has foo/struct.Bar.html
 // @!has - '//div[@class="sidebar-links"]/a[@href="#method.foo"]' 'foo'
 pub struct Bar {
     foo: Foo,
diff --git a/tests/rustdoc/issue-75588.rs b/tests/rustdoc/implementors-unstable-75588.rs
index 4f790994b41..befddf6b788 100644
--- a/tests/rustdoc/issue-75588.rs
+++ b/tests/rustdoc/implementors-unstable-75588.rs
@@ -2,6 +2,7 @@
 //@ aux-build:real_gimli.rs
 
 // Ensure unstably exported traits have their Implementors sections.
+// https://github.com/rust-lang/rust/issues/75588
 
 #![crate_name = "foo"]
 #![feature(extremely_unstable_foo)]
diff --git a/tests/rustdoc/auxiliary/issue-57180.rs b/tests/rustdoc/inline_cross/auxiliary/issue-57180.rs
index cd905b7a598..cd905b7a598 100644
--- a/tests/rustdoc/auxiliary/issue-57180.rs
+++ b/tests/rustdoc/inline_cross/auxiliary/issue-57180.rs
diff --git a/tests/rustdoc/issue-57180.rs b/tests/rustdoc/inline_cross/ice-import-crate-57180.rs
index aa6b7758399..264b53cbd9a 100644
--- a/tests/rustdoc/issue-57180.rs
+++ b/tests/rustdoc/inline_cross/ice-import-crate-57180.rs
@@ -1,4 +1,5 @@
 //@ aux-build:issue-57180.rs
+// https://github.com/rust-lang/rust/issues/57180
 
 extern crate issue_57180;
 use issue_57180::Trait;
diff --git a/tests/rustdoc/issue-72340.rs b/tests/rustdoc/intra-doc-link-method-trait-impl-72340.rs
index 64044cfe947..880a308f9ab 100644
--- a/tests/rustdoc/issue-72340.rs
+++ b/tests/rustdoc/intra-doc-link-method-trait-impl-72340.rs
@@ -1,3 +1,5 @@
+// https://github.com/rust-lang/rust/issues/72340
+
 #![crate_name = "foo"]
 
 pub struct Body;
diff --git a/tests/rustdoc/issue-67851-hidden.rs b/tests/rustdoc/issue-67851-hidden.rs
deleted file mode 100644
index 6d532adc06f..00000000000
--- a/tests/rustdoc/issue-67851-hidden.rs
+++ /dev/null
@@ -1,8 +0,0 @@
-//@ compile-flags: -Zunstable-options --document-hidden-items
-
-// @has issue_67851_hidden/struct.Hidden.html
-#[doc(hidden)]
-pub struct Hidden;
-
-// @!has issue_67851_hidden/struct.Private.html
-struct Private;
diff --git a/tests/rustdoc/issue-67851-neither.rs b/tests/rustdoc/issue-67851-neither.rs
deleted file mode 100644
index 4e3cd832853..00000000000
--- a/tests/rustdoc/issue-67851-neither.rs
+++ /dev/null
@@ -1,6 +0,0 @@
-// @!has issue_67851_neither/struct.Hidden.html
-#[doc(hidden)]
-pub struct Hidden;
-
-// @!has issue_67851_neither/struct.Private.html
-struct Private;
diff --git a/tests/rustdoc/issue-67851-private.rs b/tests/rustdoc/issue-67851-private.rs
deleted file mode 100644
index ead7ddf397f..00000000000
--- a/tests/rustdoc/issue-67851-private.rs
+++ /dev/null
@@ -1,8 +0,0 @@
-//@ compile-flags: --document-private-items
-
-// @!has issue_67851_private/struct.Hidden.html
-#[doc(hidden)]
-pub struct Hidden;
-
-// @has issue_67851_private/struct.Private.html
-struct Private;
diff --git a/tests/rustdoc/issue-60482.rs b/tests/rustdoc/markdown-60482.rs
index 0fd1daa746d..e40af12e022 100644
--- a/tests/rustdoc/issue-60482.rs
+++ b/tests/rustdoc/markdown-60482.rs
@@ -1,4 +1,5 @@
 // This code caused a panic in `pulldown-cmark` 0.4.1.
+// https://github.com/rust-lang/rust/issues/60482
 
 pub const BASIC_UNICODE: bool = true;
 
diff --git a/tests/rustdoc/issue-78701.rs b/tests/rustdoc/sidebar-trait-impl-disambiguate-78701.rs
index 3f1638d5ffc..89b7ccb5222 100644
--- a/tests/rustdoc/issue-78701.rs
+++ b/tests/rustdoc/sidebar-trait-impl-disambiguate-78701.rs
@@ -1,3 +1,4 @@
+// https://github.com/rust-lang/rust/issues/78701
 #![crate_name = "foo"]
 
 // This test ensures that if a blanket impl has the same ID as another impl, it'll
diff --git a/tests/rustdoc/issue-56822.rs b/tests/rustdoc/synthetic_auto/auto-trait-lifetimes-56822.rs
index c9a74335702..315b20ddd70 100644
--- a/tests/rustdoc/issue-56822.rs
+++ b/tests/rustdoc/synthetic_auto/auto-trait-lifetimes-56822.rs
@@ -1,3 +1,6 @@
+// https://github.com/rust-lang/rust/issues/56822
+#![crate_name="foo"]
+
 struct Wrapper<T>(T);
 
 trait MyTrait {
@@ -16,7 +19,7 @@ impl<'a, T> MyTrait for Inner<'a, T> {
     type Output = &'a T;
 }
 
-// @has issue_56822/struct.Parser.html
+// @has foo/struct.Parser.html
 // @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//h3[@class="code-header"]' \
 // "impl<'a> Send for Parser<'a>"
 pub struct Parser<'a> {
diff --git a/tests/rustdoc/issue-60726.rs b/tests/rustdoc/synthetic_auto/send-impl-conditional-60726.rs
index e337e4a4f7a..ea10aee58e4 100644
--- a/tests/rustdoc/issue-60726.rs
+++ b/tests/rustdoc/synthetic_auto/send-impl-conditional-60726.rs
@@ -1,3 +1,6 @@
+// https://github.com/rust-lang/rust/issues/60726
+#![crate_name="foo"]
+
 use std::marker::PhantomData;
 
 pub struct True;
@@ -25,7 +28,7 @@ where
     I:InterfaceType<Send=True>
 {}
 
-// @has issue_60726/struct.IntoIter.html
+// @has foo/struct.IntoIter.html
 // @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//h3[@class="code-header"]' \
 // "impl<T> !Send for IntoIter<T>"
 // @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//h3[@class="code-header"]' \
diff --git a/tests/rustdoc/issue-61592.rs b/tests/rustdoc/underscore-import-61592.rs
index 068310fa6a3..d403f2cc7ab 100644
--- a/tests/rustdoc/issue-61592.rs
+++ b/tests/rustdoc/underscore-import-61592.rs
@@ -1,14 +1,16 @@
 //@ aux-build:issue-61592.rs
+// https://github.com/rust-lang/rust/issues/61592
+#![crate_name="bar"]
 
 extern crate foo;
 
-// @has issue_61592/index.html
+// @has bar/index.html
 // @has - '//a[@href="#reexports"]' 'Re-exports'
 // @has - '//code' 'pub use foo::FooTrait as _;'
 // @!has - '//a[@href="trait._.html"]' ''
 pub use foo::FooTrait as _;
 
-// @has issue_61592/index.html
+// @has bar/index.html
 // @has - '//a[@href="#reexports"]' 'Re-exports'
 // @has - '//code' 'pub use foo::FooStruct as _;'
 // @!has - '//a[@href="struct._.html"]' ''
diff --git a/tests/ui/borrowck/borrowck-init-in-fru.stderr b/tests/ui/borrowck/borrowck-init-in-fru.stderr
index b5c332a90bc..bfa86b44fe9 100644
--- a/tests/ui/borrowck/borrowck-init-in-fru.stderr
+++ b/tests/ui/borrowck/borrowck-init-in-fru.stderr
@@ -8,8 +8,8 @@ LL |     origin = Point { x: 10, ..origin };
    |
 help: consider assigning a value
    |
-LL |     let mut origin: Point = value;
-   |                           +++++++
+LL |     let mut origin: Point = /* value */;
+   |                           +++++++++++++
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/borrowck/borrowck-uninit-ref-chain.stderr b/tests/ui/borrowck/borrowck-uninit-ref-chain.stderr
index d6759b8e1cf..b1d508e2ac3 100644
--- a/tests/ui/borrowck/borrowck-uninit-ref-chain.stderr
+++ b/tests/ui/borrowck/borrowck-uninit-ref-chain.stderr
@@ -21,8 +21,8 @@ LL |     let _y = &**x;
    |
 help: consider assigning a value
    |
-LL |     let x: &&S<i32, i32> = &&value;
-   |                          +++++++++
+LL |     let x: &&S<i32, i32> = &&/* value */;
+   |                          +++++++++++++++
 
 error[E0381]: used binding `x` isn't initialized
   --> $DIR/borrowck-uninit-ref-chain.rs:14:14
diff --git a/tests/ui/borrowck/issue-103250.stderr b/tests/ui/borrowck/issue-103250.stderr
index 104bded5b0b..cd048e03a67 100644
--- a/tests/ui/borrowck/issue-103250.stderr
+++ b/tests/ui/borrowck/issue-103250.stderr
@@ -9,8 +9,8 @@ LL |         Err(last_error)
    |
 help: consider assigning a value
    |
-LL |         let mut last_error: Box<dyn std::error::Error> = Box::new(value);
-   |                                                        +++++++++++++++++
+LL |         let mut last_error: Box<dyn std::error::Error> = Box::new(/* value */);
+   |                                                        +++++++++++++++++++++++
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/borrowck/suggest-assign-rvalue.stderr b/tests/ui/borrowck/suggest-assign-rvalue.stderr
index 4305539f1b6..daaef6e3892 100644
--- a/tests/ui/borrowck/suggest-assign-rvalue.stderr
+++ b/tests/ui/borrowck/suggest-assign-rvalue.stderr
@@ -50,8 +50,8 @@ LL |     println!("demo_no: {:?}", demo_no);
    = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
 help: consider assigning a value
    |
-LL |     let demo_no: DemoNoDef = value;
-   |                            +++++++
+LL |     let demo_no: DemoNoDef = /* value */;
+   |                            +++++++++++++
 
 error[E0381]: used binding `arr` isn't initialized
   --> $DIR/suggest-assign-rvalue.rs:34:27
diff --git a/tests/ui/check-cfg/allow-at-crate-level.rs b/tests/ui/check-cfg/allow-at-crate-level.rs
index 48258b97ccc..03b4676ad5f 100644
--- a/tests/ui/check-cfg/allow-at-crate-level.rs
+++ b/tests/ui/check-cfg/allow-at-crate-level.rs
@@ -1,7 +1,7 @@
 // This test check that #![allow(unexpected_cfgs)] works with --cfg
 //
 //@ check-pass
-//@ compile-flags: --cfg=unexpected --check-cfg=cfg() -Z unstable-options
+//@ compile-flags: --cfg=unexpected --check-cfg=cfg()
 
 #![allow(unexpected_cfgs)]
 
diff --git a/tests/ui/check-cfg/allow-macro-cfg.rs b/tests/ui/check-cfg/allow-macro-cfg.rs
index d3999af7766..3db6e18d77a 100644
--- a/tests/ui/check-cfg/allow-macro-cfg.rs
+++ b/tests/ui/check-cfg/allow-macro-cfg.rs
@@ -1,7 +1,7 @@
 // This test check that local #[allow(unexpected_cfgs)] works
 //
 //@ check-pass
-//@ compile-flags: --check-cfg=cfg() -Z unstable-options
+//@ compile-flags: --check-cfg=cfg()
 
 #[allow(unexpected_cfgs)]
 fn foo() {
diff --git a/tests/ui/check-cfg/allow-same-level.rs b/tests/ui/check-cfg/allow-same-level.rs
index 231ad522c8d..e932ece6ee7 100644
--- a/tests/ui/check-cfg/allow-same-level.rs
+++ b/tests/ui/check-cfg/allow-same-level.rs
@@ -1,7 +1,7 @@
 // This test check that #[allow(unexpected_cfgs)] doesn't work if put on the same level
 //
 //@ check-pass
-//@ compile-flags: --check-cfg=cfg() -Z unstable-options
+//@ compile-flags: --check-cfg=cfg()
 
 #[allow(unexpected_cfgs)]
 #[cfg(FALSE)]
diff --git a/tests/ui/check-cfg/allow-same-level.stderr b/tests/ui/check-cfg/allow-same-level.stderr
index 493132d462a..349f41cb142 100644
--- a/tests/ui/check-cfg/allow-same-level.stderr
+++ b/tests/ui/check-cfg/allow-same-level.stderr
@@ -6,7 +6,7 @@ LL | #[cfg(FALSE)]
    |
    = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, `windows`
    = help: to expect this configuration use `--check-cfg=cfg(FALSE)`
-   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
    = note: `#[warn(unexpected_cfgs)]` on by default
 
 warning: 1 warning emitted
diff --git a/tests/ui/check-cfg/allow-top-level.rs b/tests/ui/check-cfg/allow-top-level.rs
index c77a0c7c97b..0f88543d847 100644
--- a/tests/ui/check-cfg/allow-top-level.rs
+++ b/tests/ui/check-cfg/allow-top-level.rs
@@ -1,7 +1,7 @@
 // This test check that a top-level #![allow(unexpected_cfgs)] works
 //
 //@ check-pass
-//@ compile-flags: --check-cfg=cfg() -Z unstable-options
+//@ compile-flags: --check-cfg=cfg()
 
 #![allow(unexpected_cfgs)]
 
diff --git a/tests/ui/check-cfg/allow-upper-level.rs b/tests/ui/check-cfg/allow-upper-level.rs
index 97339a887bf..d03d0cab37b 100644
--- a/tests/ui/check-cfg/allow-upper-level.rs
+++ b/tests/ui/check-cfg/allow-upper-level.rs
@@ -1,7 +1,7 @@
 // This test check that #[allow(unexpected_cfgs)] work if put on an upper level
 //
 //@ check-pass
-//@ compile-flags: --check-cfg=cfg() -Z unstable-options
+//@ compile-flags: --check-cfg=cfg()
 
 #[allow(unexpected_cfgs)]
 mod aa {
diff --git a/tests/ui/check-cfg/cargo-feature.none.stderr b/tests/ui/check-cfg/cargo-feature.none.stderr
index 09a1c950267..0b914c2bc35 100644
--- a/tests/ui/check-cfg/cargo-feature.none.stderr
+++ b/tests/ui/check-cfg/cargo-feature.none.stderr
@@ -1,5 +1,5 @@
 warning: unexpected `cfg` condition value: `serde`
-  --> $DIR/cargo-feature.rs:14:7
+  --> $DIR/cargo-feature.rs:13:7
    |
 LL | #[cfg(feature = "serde")]
    |       ^^^^^^^^^^^^^^^^^ help: remove the condition
@@ -10,7 +10,7 @@ LL | #[cfg(feature = "serde")]
    = note: `#[warn(unexpected_cfgs)]` on by default
 
 warning: unexpected `cfg` condition value: (none)
-  --> $DIR/cargo-feature.rs:18:7
+  --> $DIR/cargo-feature.rs:17:7
    |
 LL | #[cfg(feature)]
    |       ^^^^^^^ help: remove the condition
@@ -20,7 +20,7 @@ LL | #[cfg(feature)]
    = note: see <https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#check-cfg> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition name: `tokio_unstable`
-  --> $DIR/cargo-feature.rs:22:7
+  --> $DIR/cargo-feature.rs:21:7
    |
 LL | #[cfg(tokio_unstable)]
    |       ^^^^^^^^^^^^^^
@@ -30,7 +30,7 @@ LL | #[cfg(tokio_unstable)]
    = note: see <https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#check-cfg> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition name: `CONFIG_NVME`
-  --> $DIR/cargo-feature.rs:26:7
+  --> $DIR/cargo-feature.rs:25:7
    |
 LL | #[cfg(CONFIG_NVME = "m")]
    |       ^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/check-cfg/cargo-feature.rs b/tests/ui/check-cfg/cargo-feature.rs
index ba451921d79..ced0d381d2d 100644
--- a/tests/ui/check-cfg/cargo-feature.rs
+++ b/tests/ui/check-cfg/cargo-feature.rs
@@ -5,7 +5,6 @@
 //@ check-pass
 //@ revisions: some none
 //@ rustc-env:CARGO_CRATE_NAME=foo
-//@ compile-flags: -Z unstable-options
 //@ [none]compile-flags: --check-cfg=cfg(feature,values())
 //@ [some]compile-flags: --check-cfg=cfg(feature,values("bitcode"))
 //@ [some]compile-flags: --check-cfg=cfg(CONFIG_NVME,values("y"))
diff --git a/tests/ui/check-cfg/cargo-feature.some.stderr b/tests/ui/check-cfg/cargo-feature.some.stderr
index 4db9c66fc86..1a4ef89efc1 100644
--- a/tests/ui/check-cfg/cargo-feature.some.stderr
+++ b/tests/ui/check-cfg/cargo-feature.some.stderr
@@ -1,5 +1,5 @@
 warning: unexpected `cfg` condition value: `serde`
-  --> $DIR/cargo-feature.rs:14:7
+  --> $DIR/cargo-feature.rs:13:7
    |
 LL | #[cfg(feature = "serde")]
    |       ^^^^^^^^^^^^^^^^^
@@ -10,7 +10,7 @@ LL | #[cfg(feature = "serde")]
    = note: `#[warn(unexpected_cfgs)]` on by default
 
 warning: unexpected `cfg` condition value: (none)
-  --> $DIR/cargo-feature.rs:18:7
+  --> $DIR/cargo-feature.rs:17:7
    |
 LL | #[cfg(feature)]
    |       ^^^^^^^- help: specify a config value: `= "bitcode"`
@@ -20,7 +20,7 @@ LL | #[cfg(feature)]
    = note: see <https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#check-cfg> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition name: `tokio_unstable`
-  --> $DIR/cargo-feature.rs:22:7
+  --> $DIR/cargo-feature.rs:21:7
    |
 LL | #[cfg(tokio_unstable)]
    |       ^^^^^^^^^^^^^^
@@ -30,7 +30,7 @@ LL | #[cfg(tokio_unstable)]
    = note: see <https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#check-cfg> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `m`
-  --> $DIR/cargo-feature.rs:26:7
+  --> $DIR/cargo-feature.rs:25:7
    |
 LL | #[cfg(CONFIG_NVME = "m")]
    |       ^^^^^^^^^^^^^^---
diff --git a/tests/ui/check-cfg/cfg-value-for-cfg-name-duplicate.rs b/tests/ui/check-cfg/cfg-value-for-cfg-name-duplicate.rs
index 35c5f2ae31c..79d4e45c13b 100644
--- a/tests/ui/check-cfg/cfg-value-for-cfg-name-duplicate.rs
+++ b/tests/ui/check-cfg/cfg-value-for-cfg-name-duplicate.rs
@@ -2,7 +2,6 @@
 // This test checks we won't suggest more than 3 span suggestions for cfg names
 //
 //@ check-pass
-//@ compile-flags: -Z unstable-options
 //@ compile-flags: --check-cfg=cfg(foo,values("value")) --check-cfg=cfg(bar,values("value")) --check-cfg=cfg(bee,values("value")) --check-cfg=cfg(cow,values("value"))
 
 #[cfg(value)]
diff --git a/tests/ui/check-cfg/cfg-value-for-cfg-name-duplicate.stderr b/tests/ui/check-cfg/cfg-value-for-cfg-name-duplicate.stderr
index 9c190117e74..23ae4c55e42 100644
--- a/tests/ui/check-cfg/cfg-value-for-cfg-name-duplicate.stderr
+++ b/tests/ui/check-cfg/cfg-value-for-cfg-name-duplicate.stderr
@@ -1,12 +1,12 @@
 warning: unexpected `cfg` condition name: `value`
-  --> $DIR/cfg-value-for-cfg-name-duplicate.rs:8:7
+  --> $DIR/cfg-value-for-cfg-name-duplicate.rs:7:7
    |
 LL | #[cfg(value)]
    |       ^^^^^
    |
    = help: expected names are: `bar`, `bee`, `clippy`, `cow`, `debug_assertions`, `doc`, `doctest`, `foo`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, `windows`
    = help: to expect this configuration use `--check-cfg=cfg(value)`
-   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
    = note: `#[warn(unexpected_cfgs)]` on by default
 
 warning: 1 warning emitted
diff --git a/tests/ui/check-cfg/cfg-value-for-cfg-name-multiple.rs b/tests/ui/check-cfg/cfg-value-for-cfg-name-multiple.rs
index 6caedbe719e..f2fd050bb75 100644
--- a/tests/ui/check-cfg/cfg-value-for-cfg-name-multiple.rs
+++ b/tests/ui/check-cfg/cfg-value-for-cfg-name-multiple.rs
@@ -2,7 +2,6 @@
 // This test checks that when a single cfg has a value for user's specified name
 //
 //@ check-pass
-//@ compile-flags: -Z unstable-options
 //@ compile-flags: --check-cfg=cfg(foo,values("my_value")) --check-cfg=cfg(bar,values("my_value"))
 
 #[cfg(my_value)]
diff --git a/tests/ui/check-cfg/cfg-value-for-cfg-name-multiple.stderr b/tests/ui/check-cfg/cfg-value-for-cfg-name-multiple.stderr
index 7113790b83a..b5faaf6029c 100644
--- a/tests/ui/check-cfg/cfg-value-for-cfg-name-multiple.stderr
+++ b/tests/ui/check-cfg/cfg-value-for-cfg-name-multiple.stderr
@@ -1,12 +1,12 @@
 warning: unexpected `cfg` condition name: `my_value`
-  --> $DIR/cfg-value-for-cfg-name-multiple.rs:8:7
+  --> $DIR/cfg-value-for-cfg-name-multiple.rs:7:7
    |
 LL | #[cfg(my_value)]
    |       ^^^^^^^^
    |
    = help: expected names are: `bar`, `clippy`, `debug_assertions`, `doc`, `doctest`, `foo`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, `windows`
    = help: to expect this configuration use `--check-cfg=cfg(my_value)`
-   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
    = note: `#[warn(unexpected_cfgs)]` on by default
 help: found config with similar value
    |
diff --git a/tests/ui/check-cfg/cfg-value-for-cfg-name.rs b/tests/ui/check-cfg/cfg-value-for-cfg-name.rs
index eade190a75c..e8f9095655b 100644
--- a/tests/ui/check-cfg/cfg-value-for-cfg-name.rs
+++ b/tests/ui/check-cfg/cfg-value-for-cfg-name.rs
@@ -3,7 +3,6 @@
 // suggest to use `#[cfg(target_os = "linux")]` instead of `#[cfg(linux)]`
 //
 //@ check-pass
-//@ compile-flags: -Z unstable-options
 //@ compile-flags: --check-cfg=cfg()
 
 #[cfg(linux)]
diff --git a/tests/ui/check-cfg/cfg-value-for-cfg-name.stderr b/tests/ui/check-cfg/cfg-value-for-cfg-name.stderr
index ba9f5f4acbd..01586a6c71d 100644
--- a/tests/ui/check-cfg/cfg-value-for-cfg-name.stderr
+++ b/tests/ui/check-cfg/cfg-value-for-cfg-name.stderr
@@ -1,22 +1,22 @@
 warning: unexpected `cfg` condition name: `linux`
-  --> $DIR/cfg-value-for-cfg-name.rs:9:7
+  --> $DIR/cfg-value-for-cfg-name.rs:8:7
    |
 LL | #[cfg(linux)]
    |       ^^^^^ help: found config with similar value: `target_os = "linux"`
    |
    = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, `windows`
    = help: to expect this configuration use `--check-cfg=cfg(linux)`
-   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
    = note: `#[warn(unexpected_cfgs)]` on by default
 
 warning: unexpected `cfg` condition name: `linux`
-  --> $DIR/cfg-value-for-cfg-name.rs:14:7
+  --> $DIR/cfg-value-for-cfg-name.rs:13:7
    |
 LL | #[cfg(linux = "os-name")]
    |       ^^^^^^^^^^^^^^^^^
    |
    = help: to expect this configuration use `--check-cfg=cfg(linux, values("os-name"))`
-   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: 2 warnings emitted
 
diff --git a/tests/ui/check-cfg/compact-names.rs b/tests/ui/check-cfg/compact-names.rs
index 6592d2acb82..ddbd20b99b2 100644
--- a/tests/ui/check-cfg/compact-names.rs
+++ b/tests/ui/check-cfg/compact-names.rs
@@ -1,7 +1,7 @@
 // This test check that we correctly emit an warning for compact cfg
 //
 //@ check-pass
-//@ compile-flags: --check-cfg=cfg() -Z unstable-options
+//@ compile-flags: --check-cfg=cfg()
 
 #![feature(cfg_target_compact)]
 
diff --git a/tests/ui/check-cfg/compact-names.stderr b/tests/ui/check-cfg/compact-names.stderr
index 446b8f408e3..929501b420a 100644
--- a/tests/ui/check-cfg/compact-names.stderr
+++ b/tests/ui/check-cfg/compact-names.stderr
@@ -6,7 +6,7 @@ LL | #[cfg(target(os = "linux", architecture = "arm"))]
    |
    = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, `windows`
    = help: to expect this configuration use `--check-cfg=cfg(target_architecture, values("arm"))`
-   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
    = note: `#[warn(unexpected_cfgs)]` on by default
 
 warning: 1 warning emitted
diff --git a/tests/ui/check-cfg/compact-values.rs b/tests/ui/check-cfg/compact-values.rs
index 8df2bf55264..bda4686ebd7 100644
--- a/tests/ui/check-cfg/compact-values.rs
+++ b/tests/ui/check-cfg/compact-values.rs
@@ -1,7 +1,7 @@
 // This test check that we correctly emit an warning for compact cfg
 //
 //@ check-pass
-//@ compile-flags: --check-cfg=cfg() -Z unstable-options
+//@ compile-flags: --check-cfg=cfg()
 
 #![feature(cfg_target_compact)]
 
diff --git a/tests/ui/check-cfg/compact-values.stderr b/tests/ui/check-cfg/compact-values.stderr
index 661ee7bff52..45d084c46bf 100644
--- a/tests/ui/check-cfg/compact-values.stderr
+++ b/tests/ui/check-cfg/compact-values.stderr
@@ -5,7 +5,7 @@ LL | #[cfg(target(os = "linux", pointer_width = "X"))]
    |                            ^^^^^^^^^^^^^^^^^^^
    |
    = note: expected values for `target_pointer_width` are: `16`, `32`, `64`
-   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
    = note: `#[warn(unexpected_cfgs)]` on by default
 
 warning: 1 warning emitted
diff --git a/tests/ui/check-cfg/concat-values.rs b/tests/ui/check-cfg/concat-values.rs
index 0b2c1949ca3..c546590a2c1 100644
--- a/tests/ui/check-cfg/concat-values.rs
+++ b/tests/ui/check-cfg/concat-values.rs
@@ -1,5 +1,4 @@
 //@ check-pass
-//@ compile-flags: -Z unstable-options
 //@ compile-flags: --check-cfg=cfg(my_cfg,values("foo")) --check-cfg=cfg(my_cfg,values("bar"))
 //@ compile-flags: --check-cfg=cfg(my_cfg,values())
 
diff --git a/tests/ui/check-cfg/concat-values.stderr b/tests/ui/check-cfg/concat-values.stderr
index 6fe9f2baa09..ca8b58f73e5 100644
--- a/tests/ui/check-cfg/concat-values.stderr
+++ b/tests/ui/check-cfg/concat-values.stderr
@@ -1,23 +1,23 @@
 warning: unexpected `cfg` condition value: (none)
-  --> $DIR/concat-values.rs:6:7
+  --> $DIR/concat-values.rs:5:7
    |
 LL | #[cfg(my_cfg)]
    |       ^^^^^^
    |
    = note: expected values for `my_cfg` are: `bar`, `foo`
    = help: to expect this configuration use `--check-cfg=cfg(my_cfg)`
-   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
    = note: `#[warn(unexpected_cfgs)]` on by default
 
 warning: unexpected `cfg` condition value: `unk`
-  --> $DIR/concat-values.rs:10:7
+  --> $DIR/concat-values.rs:9:7
    |
 LL | #[cfg(my_cfg = "unk")]
    |       ^^^^^^^^^^^^^^
    |
    = note: expected values for `my_cfg` are: `bar`, `foo`
    = help: to expect this configuration use `--check-cfg=cfg(my_cfg, values("unk"))`
-   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: 2 warnings emitted
 
diff --git a/tests/ui/check-cfg/diagnotics.rs b/tests/ui/check-cfg/diagnotics.rs
index 134bfcf8ef4..cccd6f9bbc3 100644
--- a/tests/ui/check-cfg/diagnotics.rs
+++ b/tests/ui/check-cfg/diagnotics.rs
@@ -2,7 +2,7 @@
 //@ revisions: cargo rustc
 //@ [rustc]unset-rustc-env:CARGO_CRATE_NAME
 //@ [cargo]rustc-env:CARGO_CRATE_NAME=foo
-//@ compile-flags: --check-cfg=cfg(feature,values("foo")) --check-cfg=cfg(no_values) -Z unstable-options
+//@ compile-flags: --check-cfg=cfg(feature,values("foo")) --check-cfg=cfg(no_values)
 
 #[cfg(featur)]
 //~^ WARNING unexpected `cfg` condition name
diff --git a/tests/ui/check-cfg/diagnotics.rustc.stderr b/tests/ui/check-cfg/diagnotics.rustc.stderr
index 2b1129a3920..0a938d2143e 100644
--- a/tests/ui/check-cfg/diagnotics.rustc.stderr
+++ b/tests/ui/check-cfg/diagnotics.rustc.stderr
@@ -6,7 +6,7 @@ LL | #[cfg(featur)]
    |
    = help: expected values for `feature` are: `foo`
    = help: to expect this configuration use `--check-cfg=cfg(featur)`
-   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
    = note: `#[warn(unexpected_cfgs)]` on by default
 
 warning: unexpected `cfg` condition name: `featur`
@@ -16,7 +16,7 @@ LL | #[cfg(featur = "foo")]
    |       ^^^^^^^^^^^^^^
    |
    = help: to expect this configuration use `--check-cfg=cfg(featur, values("foo"))`
-   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 help: there is a config with a similar name and value
    |
 LL | #[cfg(feature = "foo")]
@@ -30,7 +30,7 @@ LL | #[cfg(featur = "fo")]
    |
    = help: expected values for `feature` are: `foo`
    = help: to expect this configuration use `--check-cfg=cfg(featur, values("fo"))`
-   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 help: there is a config with a similar name and different values
    |
 LL | #[cfg(feature = "foo")]
@@ -43,7 +43,7 @@ LL | #[cfg(no_value)]
    |       ^^^^^^^^ help: there is a config with a similar name: `no_values`
    |
    = help: to expect this configuration use `--check-cfg=cfg(no_value)`
-   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition name: `no_value`
   --> $DIR/diagnotics.rs:26:7
@@ -52,7 +52,7 @@ LL | #[cfg(no_value = "foo")]
    |       ^^^^^^^^^^^^^^^^
    |
    = help: to expect this configuration use `--check-cfg=cfg(no_value, values("foo"))`
-   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 help: there is a config with a similar name and no value
    |
 LL | #[cfg(no_values)]
@@ -68,7 +68,7 @@ LL | #[cfg(no_values = "bar")]
    |
    = note: no expected value for `no_values`
    = help: to expect this configuration use `--check-cfg=cfg(no_values, values("bar"))`
-   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: 6 warnings emitted
 
diff --git a/tests/ui/check-cfg/empty-values.rs b/tests/ui/check-cfg/empty-values.rs
index 07462951e1b..cad2d351b96 100644
--- a/tests/ui/check-cfg/empty-values.rs
+++ b/tests/ui/check-cfg/empty-values.rs
@@ -1,7 +1,7 @@
 // Check that we detect unexpected value when none are allowed
 //
 //@ check-pass
-//@ compile-flags: --check-cfg=cfg(foo,values()) -Zunstable-options
+//@ compile-flags: --check-cfg=cfg(foo,values())
 
 #[cfg(foo = "foo")]
 //~^ WARNING unexpected `cfg` condition value
diff --git a/tests/ui/check-cfg/empty-values.stderr b/tests/ui/check-cfg/empty-values.stderr
index e7b0b05d561..1f773b10316 100644
--- a/tests/ui/check-cfg/empty-values.stderr
+++ b/tests/ui/check-cfg/empty-values.stderr
@@ -6,7 +6,7 @@ LL | #[cfg(foo = "foo")]
    |
    = note: no expected values for `foo`
    = help: to expect this configuration use `--check-cfg=cfg(foo, values("foo"))`
-   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
    = note: `#[warn(unexpected_cfgs)]` on by default
 
 warning: unexpected `cfg` condition value: (none)
@@ -17,7 +17,7 @@ LL | #[cfg(foo)]
    |
    = note: no expected values for `foo`
    = help: to expect this configuration use `--check-cfg=cfg(foo)`
-   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: 2 warnings emitted
 
diff --git a/tests/ui/check-cfg/exhaustive-names-values.empty_cfg.stderr b/tests/ui/check-cfg/exhaustive-names-values.empty_cfg.stderr
index d2870263342..9537d4f5172 100644
--- a/tests/ui/check-cfg/exhaustive-names-values.empty_cfg.stderr
+++ b/tests/ui/check-cfg/exhaustive-names-values.empty_cfg.stderr
@@ -1,16 +1,16 @@
 warning: unexpected `cfg` condition name: `unknown_key`
-  --> $DIR/exhaustive-names-values.rs:10:7
+  --> $DIR/exhaustive-names-values.rs:9:7
    |
 LL | #[cfg(unknown_key = "value")]
    |       ^^^^^^^^^^^^^^^^^^^^^
    |
    = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, `windows`
    = help: to expect this configuration use `--check-cfg=cfg(unknown_key, values("value"))`
-   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
    = note: `#[warn(unexpected_cfgs)]` on by default
 
 warning: unexpected `cfg` condition value: `value`
-  --> $DIR/exhaustive-names-values.rs:14:7
+  --> $DIR/exhaustive-names-values.rs:13:7
    |
 LL | #[cfg(test = "value")]
    |       ^^^^----------
@@ -18,25 +18,25 @@ LL | #[cfg(test = "value")]
    |           help: remove the value
    |
    = note: no expected value for `test`
-   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition name: `feature`
-  --> $DIR/exhaustive-names-values.rs:18:7
+  --> $DIR/exhaustive-names-values.rs:17:7
    |
 LL | #[cfg(feature = "unk")]
    |       ^^^^^^^^^^^^^^^
    |
    = help: to expect this configuration use `--check-cfg=cfg(feature, values("unk"))`
-   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition name: `feature`
-  --> $DIR/exhaustive-names-values.rs:25:7
+  --> $DIR/exhaustive-names-values.rs:24:7
    |
 LL | #[cfg(feature = "std")]
    |       ^^^^^^^^^^^^^^^
    |
    = help: to expect this configuration use `--check-cfg=cfg(feature, values("std"))`
-   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: 4 warnings emitted
 
diff --git a/tests/ui/check-cfg/exhaustive-names-values.feature.stderr b/tests/ui/check-cfg/exhaustive-names-values.feature.stderr
index b24b10bb615..d63d8627953 100644
--- a/tests/ui/check-cfg/exhaustive-names-values.feature.stderr
+++ b/tests/ui/check-cfg/exhaustive-names-values.feature.stderr
@@ -1,16 +1,16 @@
 warning: unexpected `cfg` condition name: `unknown_key`
-  --> $DIR/exhaustive-names-values.rs:10:7
+  --> $DIR/exhaustive-names-values.rs:9:7
    |
 LL | #[cfg(unknown_key = "value")]
    |       ^^^^^^^^^^^^^^^^^^^^^
    |
    = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, `windows`
    = help: to expect this configuration use `--check-cfg=cfg(unknown_key, values("value"))`
-   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
    = note: `#[warn(unexpected_cfgs)]` on by default
 
 warning: unexpected `cfg` condition value: `value`
-  --> $DIR/exhaustive-names-values.rs:14:7
+  --> $DIR/exhaustive-names-values.rs:13:7
    |
 LL | #[cfg(test = "value")]
    |       ^^^^----------
@@ -18,17 +18,17 @@ LL | #[cfg(test = "value")]
    |           help: remove the value
    |
    = note: no expected value for `test`
-   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `unk`
-  --> $DIR/exhaustive-names-values.rs:18:7
+  --> $DIR/exhaustive-names-values.rs:17:7
    |
 LL | #[cfg(feature = "unk")]
    |       ^^^^^^^^^^^^^^^
    |
    = note: expected values for `feature` are: `std`
    = help: to expect this configuration use `--check-cfg=cfg(feature, values("unk"))`
-   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: 3 warnings emitted
 
diff --git a/tests/ui/check-cfg/exhaustive-names-values.full.stderr b/tests/ui/check-cfg/exhaustive-names-values.full.stderr
index b24b10bb615..d63d8627953 100644
--- a/tests/ui/check-cfg/exhaustive-names-values.full.stderr
+++ b/tests/ui/check-cfg/exhaustive-names-values.full.stderr
@@ -1,16 +1,16 @@
 warning: unexpected `cfg` condition name: `unknown_key`
-  --> $DIR/exhaustive-names-values.rs:10:7
+  --> $DIR/exhaustive-names-values.rs:9:7
    |
 LL | #[cfg(unknown_key = "value")]
    |       ^^^^^^^^^^^^^^^^^^^^^
    |
    = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, `windows`
    = help: to expect this configuration use `--check-cfg=cfg(unknown_key, values("value"))`
-   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
    = note: `#[warn(unexpected_cfgs)]` on by default
 
 warning: unexpected `cfg` condition value: `value`
-  --> $DIR/exhaustive-names-values.rs:14:7
+  --> $DIR/exhaustive-names-values.rs:13:7
    |
 LL | #[cfg(test = "value")]
    |       ^^^^----------
@@ -18,17 +18,17 @@ LL | #[cfg(test = "value")]
    |           help: remove the value
    |
    = note: no expected value for `test`
-   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `unk`
-  --> $DIR/exhaustive-names-values.rs:18:7
+  --> $DIR/exhaustive-names-values.rs:17:7
    |
 LL | #[cfg(feature = "unk")]
    |       ^^^^^^^^^^^^^^^
    |
    = note: expected values for `feature` are: `std`
    = help: to expect this configuration use `--check-cfg=cfg(feature, values("unk"))`
-   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: 3 warnings emitted
 
diff --git a/tests/ui/check-cfg/exhaustive-names-values.rs b/tests/ui/check-cfg/exhaustive-names-values.rs
index d554c19ef25..f6c3e1f575a 100644
--- a/tests/ui/check-cfg/exhaustive-names-values.rs
+++ b/tests/ui/check-cfg/exhaustive-names-values.rs
@@ -2,7 +2,6 @@
 //
 //@ check-pass
 //@ revisions: empty_cfg feature full
-//@ compile-flags: -Z unstable-options
 //@ [empty_cfg]compile-flags: --check-cfg=cfg()
 //@ [feature]compile-flags: --check-cfg=cfg(feature,values("std"))
 //@ [full]compile-flags: --check-cfg=cfg(feature,values("std")) --check-cfg=cfg()
diff --git a/tests/ui/check-cfg/exhaustive-names.rs b/tests/ui/check-cfg/exhaustive-names.rs
index edfb3705a7d..23bde4dff55 100644
--- a/tests/ui/check-cfg/exhaustive-names.rs
+++ b/tests/ui/check-cfg/exhaustive-names.rs
@@ -1,7 +1,7 @@
 // Check warning for unexpected cfg
 //
 //@ check-pass
-//@ compile-flags: --check-cfg=cfg() -Z unstable-options
+//@ compile-flags: --check-cfg=cfg()
 
 #[cfg(unknown_key = "value")]
 //~^ WARNING unexpected `cfg` condition name
diff --git a/tests/ui/check-cfg/exhaustive-names.stderr b/tests/ui/check-cfg/exhaustive-names.stderr
index 6ca7ed93625..c42adec94b2 100644
--- a/tests/ui/check-cfg/exhaustive-names.stderr
+++ b/tests/ui/check-cfg/exhaustive-names.stderr
@@ -6,7 +6,7 @@ LL | #[cfg(unknown_key = "value")]
    |
    = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, `windows`
    = help: to expect this configuration use `--check-cfg=cfg(unknown_key, values("value"))`
-   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
    = note: `#[warn(unexpected_cfgs)]` on by default
 
 warning: 1 warning emitted
diff --git a/tests/ui/check-cfg/exhaustive-values.empty_cfg.stderr b/tests/ui/check-cfg/exhaustive-values.empty_cfg.stderr
index e8cf29ae982..63ba2c68625 100644
--- a/tests/ui/check-cfg/exhaustive-values.empty_cfg.stderr
+++ b/tests/ui/check-cfg/exhaustive-values.empty_cfg.stderr
@@ -7,7 +7,7 @@ LL | #[cfg(test = "value")]
    |           help: remove the value
    |
    = note: no expected value for `test`
-   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
    = note: `#[warn(unexpected_cfgs)]` on by default
 
 warning: 1 warning emitted
diff --git a/tests/ui/check-cfg/exhaustive-values.rs b/tests/ui/check-cfg/exhaustive-values.rs
index 5e65caa6aea..029b2ff2c69 100644
--- a/tests/ui/check-cfg/exhaustive-values.rs
+++ b/tests/ui/check-cfg/exhaustive-values.rs
@@ -2,8 +2,8 @@
 //
 //@ check-pass
 //@ revisions: empty_cfg without_names
-//@ [empty_cfg]compile-flags: --check-cfg=cfg() -Z unstable-options
-//@ [without_names]compile-flags: --check-cfg=cfg(any()) -Z unstable-options
+//@ [empty_cfg]compile-flags: --check-cfg=cfg()
+//@ [without_names]compile-flags: --check-cfg=cfg(any())
 
 #[cfg(test = "value")]
 //~^ WARNING unexpected `cfg` condition value
diff --git a/tests/ui/check-cfg/exhaustive-values.without_names.stderr b/tests/ui/check-cfg/exhaustive-values.without_names.stderr
index e8cf29ae982..63ba2c68625 100644
--- a/tests/ui/check-cfg/exhaustive-values.without_names.stderr
+++ b/tests/ui/check-cfg/exhaustive-values.without_names.stderr
@@ -7,7 +7,7 @@ LL | #[cfg(test = "value")]
    |           help: remove the value
    |
    = note: no expected value for `test`
-   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
    = note: `#[warn(unexpected_cfgs)]` on by default
 
 warning: 1 warning emitted
diff --git a/tests/ui/check-cfg/invalid-arguments.rs b/tests/ui/check-cfg/invalid-arguments.rs
index bdcc202443b..84087a16e80 100644
--- a/tests/ui/check-cfg/invalid-arguments.rs
+++ b/tests/ui/check-cfg/invalid-arguments.rs
@@ -9,7 +9,6 @@
 //@ revisions: mixed_values_any mixed_any any_values giberich unterminated
 //@ revisions: none_not_empty cfg_none
 //
-//@ compile-flags: -Z unstable-options
 //@ [anything_else]compile-flags: --check-cfg=anything_else(...)
 //@ [string_for_name_1]compile-flags: --check-cfg=cfg("NOT_IDENT")
 //@ [string_for_name_2]compile-flags: --check-cfg=cfg(foo,"NOT_IDENT",bar)
diff --git a/tests/ui/check-cfg/mix.rs b/tests/ui/check-cfg/mix.rs
index 69156ab6763..ab8a180bc6f 100644
--- a/tests/ui/check-cfg/mix.rs
+++ b/tests/ui/check-cfg/mix.rs
@@ -3,7 +3,7 @@
 // we correctly lint on the `cfg!` macro and `cfg_attr` attribute.
 //
 //@ check-pass
-//@ compile-flags: --cfg feature="bar" --cfg unknown_name -Z unstable-options
+//@ compile-flags: --cfg feature="bar" --cfg unknown_name
 //@ compile-flags: --check-cfg=cfg(feature,values("foo"))
 
 #[cfg(windows)]
diff --git a/tests/ui/check-cfg/mix.stderr b/tests/ui/check-cfg/mix.stderr
index 87fabf8245f..feb4f21b0ca 100644
--- a/tests/ui/check-cfg/mix.stderr
+++ b/tests/ui/check-cfg/mix.stderr
@@ -5,7 +5,7 @@ LL | #[cfg(widnows)]
    |       ^^^^^^^ help: there is a config with a similar name: `windows`
    |
    = help: to expect this configuration use `--check-cfg=cfg(widnows)`
-   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
    = note: `#[warn(unexpected_cfgs)]` on by default
 
 warning: unexpected `cfg` condition value: (none)
@@ -16,7 +16,7 @@ LL | #[cfg(feature)]
    |
    = note: expected values for `feature` are: `foo`
    = help: to expect this configuration use `--check-cfg=cfg(feature)`
-   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `bar`
   --> $DIR/mix.rs:23:7
@@ -26,7 +26,7 @@ LL | #[cfg(feature = "bar")]
    |
    = note: expected values for `feature` are: `foo`
    = help: to expect this configuration use `--check-cfg=cfg(feature, values("bar"))`
-   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `zebra`
   --> $DIR/mix.rs:27:7
@@ -36,7 +36,7 @@ LL | #[cfg(feature = "zebra")]
    |
    = note: expected values for `feature` are: `foo`
    = help: to expect this configuration use `--check-cfg=cfg(feature, values("zebra"))`
-   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition name: `uu`
   --> $DIR/mix.rs:31:12
@@ -46,7 +46,7 @@ LL | #[cfg_attr(uu, test)]
    |
    = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, `windows`
    = help: to expect this configuration use `--check-cfg=cfg(uu)`
-   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition name: `widnows`
   --> $DIR/mix.rs:40:10
@@ -55,7 +55,7 @@ LL |     cfg!(widnows);
    |          ^^^^^^^ help: there is a config with a similar name: `windows`
    |
    = help: to expect this configuration use `--check-cfg=cfg(widnows)`
-   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `bar`
   --> $DIR/mix.rs:43:10
@@ -65,7 +65,7 @@ LL |     cfg!(feature = "bar");
    |
    = note: expected values for `feature` are: `foo`
    = help: to expect this configuration use `--check-cfg=cfg(feature, values("bar"))`
-   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `zebra`
   --> $DIR/mix.rs:45:10
@@ -75,7 +75,7 @@ LL |     cfg!(feature = "zebra");
    |
    = note: expected values for `feature` are: `foo`
    = help: to expect this configuration use `--check-cfg=cfg(feature, values("zebra"))`
-   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition name: `xxx`
   --> $DIR/mix.rs:47:10
@@ -84,7 +84,7 @@ LL |     cfg!(xxx = "foo");
    |          ^^^^^^^^^^^
    |
    = help: to expect this configuration use `--check-cfg=cfg(xxx, values("foo"))`
-   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition name: `xxx`
   --> $DIR/mix.rs:49:10
@@ -93,7 +93,7 @@ LL |     cfg!(xxx);
    |          ^^^
    |
    = help: to expect this configuration use `--check-cfg=cfg(xxx)`
-   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition name: `xxx`
   --> $DIR/mix.rs:51:14
@@ -102,7 +102,7 @@ LL |     cfg!(any(xxx, windows));
    |              ^^^
    |
    = help: to expect this configuration use `--check-cfg=cfg(xxx)`
-   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `bad`
   --> $DIR/mix.rs:53:14
@@ -112,7 +112,7 @@ LL |     cfg!(any(feature = "bad", windows));
    |
    = note: expected values for `feature` are: `foo`
    = help: to expect this configuration use `--check-cfg=cfg(feature, values("bad"))`
-   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition name: `xxx`
   --> $DIR/mix.rs:55:23
@@ -121,7 +121,7 @@ LL |     cfg!(any(windows, xxx));
    |                       ^^^
    |
    = help: to expect this configuration use `--check-cfg=cfg(xxx)`
-   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition name: `xxx`
   --> $DIR/mix.rs:57:20
@@ -130,7 +130,7 @@ LL |     cfg!(all(unix, xxx));
    |                    ^^^
    |
    = help: to expect this configuration use `--check-cfg=cfg(xxx)`
-   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition name: `aa`
   --> $DIR/mix.rs:59:14
@@ -139,7 +139,7 @@ LL |     cfg!(all(aa, bb));
    |              ^^
    |
    = help: to expect this configuration use `--check-cfg=cfg(aa)`
-   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition name: `bb`
   --> $DIR/mix.rs:59:18
@@ -148,7 +148,7 @@ LL |     cfg!(all(aa, bb));
    |                  ^^
    |
    = help: to expect this configuration use `--check-cfg=cfg(bb)`
-   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition name: `aa`
   --> $DIR/mix.rs:62:14
@@ -157,7 +157,7 @@ LL |     cfg!(any(aa, bb));
    |              ^^
    |
    = help: to expect this configuration use `--check-cfg=cfg(aa)`
-   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition name: `bb`
   --> $DIR/mix.rs:62:18
@@ -166,7 +166,7 @@ LL |     cfg!(any(aa, bb));
    |                  ^^
    |
    = help: to expect this configuration use `--check-cfg=cfg(bb)`
-   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `zebra`
   --> $DIR/mix.rs:65:20
@@ -176,7 +176,7 @@ LL |     cfg!(any(unix, feature = "zebra"));
    |
    = note: expected values for `feature` are: `foo`
    = help: to expect this configuration use `--check-cfg=cfg(feature, values("zebra"))`
-   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition name: `xxx`
   --> $DIR/mix.rs:67:14
@@ -185,7 +185,7 @@ LL |     cfg!(any(xxx, feature = "zebra"));
    |              ^^^
    |
    = help: to expect this configuration use `--check-cfg=cfg(xxx)`
-   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `zebra`
   --> $DIR/mix.rs:67:19
@@ -195,7 +195,7 @@ LL |     cfg!(any(xxx, feature = "zebra"));
    |
    = note: expected values for `feature` are: `foo`
    = help: to expect this configuration use `--check-cfg=cfg(feature, values("zebra"))`
-   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition name: `xxx`
   --> $DIR/mix.rs:70:14
@@ -204,7 +204,7 @@ LL |     cfg!(any(xxx, unix, xxx));
    |              ^^^
    |
    = help: to expect this configuration use `--check-cfg=cfg(xxx)`
-   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition name: `xxx`
   --> $DIR/mix.rs:70:25
@@ -213,7 +213,7 @@ LL |     cfg!(any(xxx, unix, xxx));
    |                         ^^^
    |
    = help: to expect this configuration use `--check-cfg=cfg(xxx)`
-   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `zebra`
   --> $DIR/mix.rs:73:14
@@ -223,7 +223,7 @@ LL |     cfg!(all(feature = "zebra", feature = "zebra", feature = "zebra"));
    |
    = note: expected values for `feature` are: `foo`
    = help: to expect this configuration use `--check-cfg=cfg(feature, values("zebra"))`
-   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `zebra`
   --> $DIR/mix.rs:73:33
@@ -233,7 +233,7 @@ LL |     cfg!(all(feature = "zebra", feature = "zebra", feature = "zebra"));
    |
    = note: expected values for `feature` are: `foo`
    = help: to expect this configuration use `--check-cfg=cfg(feature, values("zebra"))`
-   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `zebra`
   --> $DIR/mix.rs:73:52
@@ -243,7 +243,7 @@ LL |     cfg!(all(feature = "zebra", feature = "zebra", feature = "zebra"));
    |
    = note: expected values for `feature` are: `foo`
    = help: to expect this configuration use `--check-cfg=cfg(feature, values("zebra"))`
-   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `zebra`
   --> $DIR/mix.rs:77:10
@@ -252,7 +252,7 @@ LL |     cfg!(target_feature = "zebra");
    |          ^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: expected values for `target_feature` are: `10e60`, `2e3`, `3e3r1`, `3e3r2`, `3e3r3`, `3e7`, `7e10`, `a`, `aclass`, `adx`, `aes`, `altivec`, `alu32`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512er`, `avx512f`, `avx512fp16`, `avx512ifma`, `avx512pf`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, `avx512vpopcntdq`, `bf16`, `bmi1`, `bmi2` and 187 more
-   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: 27 warnings emitted
 
diff --git a/tests/ui/check-cfg/no-expected-values.empty.stderr b/tests/ui/check-cfg/no-expected-values.empty.stderr
index 0c0dbe9bac6..0f181cc2ab1 100644
--- a/tests/ui/check-cfg/no-expected-values.empty.stderr
+++ b/tests/ui/check-cfg/no-expected-values.empty.stderr
@@ -1,5 +1,5 @@
 warning: unexpected `cfg` condition value: `foo`
-  --> $DIR/no-expected-values.rs:11:7
+  --> $DIR/no-expected-values.rs:10:7
    |
 LL | #[cfg(feature = "foo")]
    |       ^^^^^^^--------
@@ -8,11 +8,11 @@ LL | #[cfg(feature = "foo")]
    |
    = note: no expected value for `feature`
    = help: to expect this configuration use `--check-cfg=cfg(feature, values("foo"))`
-   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
    = note: `#[warn(unexpected_cfgs)]` on by default
 
 warning: unexpected `cfg` condition value: `foo`
-  --> $DIR/no-expected-values.rs:15:7
+  --> $DIR/no-expected-values.rs:14:7
    |
 LL | #[cfg(test = "foo")]
    |       ^^^^--------
@@ -20,7 +20,7 @@ LL | #[cfg(test = "foo")]
    |           help: remove the value
    |
    = note: no expected value for `test`
-   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: 2 warnings emitted
 
diff --git a/tests/ui/check-cfg/no-expected-values.mixed.stderr b/tests/ui/check-cfg/no-expected-values.mixed.stderr
index 0c0dbe9bac6..0f181cc2ab1 100644
--- a/tests/ui/check-cfg/no-expected-values.mixed.stderr
+++ b/tests/ui/check-cfg/no-expected-values.mixed.stderr
@@ -1,5 +1,5 @@
 warning: unexpected `cfg` condition value: `foo`
-  --> $DIR/no-expected-values.rs:11:7
+  --> $DIR/no-expected-values.rs:10:7
    |
 LL | #[cfg(feature = "foo")]
    |       ^^^^^^^--------
@@ -8,11 +8,11 @@ LL | #[cfg(feature = "foo")]
    |
    = note: no expected value for `feature`
    = help: to expect this configuration use `--check-cfg=cfg(feature, values("foo"))`
-   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
    = note: `#[warn(unexpected_cfgs)]` on by default
 
 warning: unexpected `cfg` condition value: `foo`
-  --> $DIR/no-expected-values.rs:15:7
+  --> $DIR/no-expected-values.rs:14:7
    |
 LL | #[cfg(test = "foo")]
    |       ^^^^--------
@@ -20,7 +20,7 @@ LL | #[cfg(test = "foo")]
    |           help: remove the value
    |
    = note: no expected value for `test`
-   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: 2 warnings emitted
 
diff --git a/tests/ui/check-cfg/no-expected-values.rs b/tests/ui/check-cfg/no-expected-values.rs
index a80f9ec9776..42e7f45fa7a 100644
--- a/tests/ui/check-cfg/no-expected-values.rs
+++ b/tests/ui/check-cfg/no-expected-values.rs
@@ -2,7 +2,6 @@
 //
 //@ check-pass
 //@ revisions: simple mixed empty
-//@ compile-flags: -Z unstable-options
 //@ compile-flags: --check-cfg=cfg(values,simple,mixed,empty)
 //@ [simple]compile-flags: --check-cfg=cfg(test) --check-cfg=cfg(feature)
 //@ [mixed]compile-flags: --check-cfg=cfg(test,feature)
diff --git a/tests/ui/check-cfg/no-expected-values.simple.stderr b/tests/ui/check-cfg/no-expected-values.simple.stderr
index 0c0dbe9bac6..0f181cc2ab1 100644
--- a/tests/ui/check-cfg/no-expected-values.simple.stderr
+++ b/tests/ui/check-cfg/no-expected-values.simple.stderr
@@ -1,5 +1,5 @@
 warning: unexpected `cfg` condition value: `foo`
-  --> $DIR/no-expected-values.rs:11:7
+  --> $DIR/no-expected-values.rs:10:7
    |
 LL | #[cfg(feature = "foo")]
    |       ^^^^^^^--------
@@ -8,11 +8,11 @@ LL | #[cfg(feature = "foo")]
    |
    = note: no expected value for `feature`
    = help: to expect this configuration use `--check-cfg=cfg(feature, values("foo"))`
-   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
    = note: `#[warn(unexpected_cfgs)]` on by default
 
 warning: unexpected `cfg` condition value: `foo`
-  --> $DIR/no-expected-values.rs:15:7
+  --> $DIR/no-expected-values.rs:14:7
    |
 LL | #[cfg(test = "foo")]
    |       ^^^^--------
@@ -20,7 +20,7 @@ LL | #[cfg(test = "foo")]
    |           help: remove the value
    |
    = note: no expected value for `test`
-   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: 2 warnings emitted
 
diff --git a/tests/ui/check-cfg/order-independant.rs b/tests/ui/check-cfg/order-independant.rs
index 9ac96d0b15b..671d2e764d3 100644
--- a/tests/ui/check-cfg/order-independant.rs
+++ b/tests/ui/check-cfg/order-independant.rs
@@ -1,9 +1,7 @@
 //@ check-pass
 //
 //@ revisions: values_before values_after
-//@ compile-flags: -Z unstable-options
 //@ compile-flags: --check-cfg=cfg(values_before,values_after)
-//
 //@ [values_before]compile-flags: --check-cfg=cfg(a,values("b")) --check-cfg=cfg(a)
 //@ [values_after]compile-flags: --check-cfg=cfg(a) --check-cfg=cfg(a,values("b"))
 
diff --git a/tests/ui/check-cfg/order-independant.values_after.stderr b/tests/ui/check-cfg/order-independant.values_after.stderr
index d1de26ba303..7e18df8e1c2 100644
--- a/tests/ui/check-cfg/order-independant.values_after.stderr
+++ b/tests/ui/check-cfg/order-independant.values_after.stderr
@@ -1,12 +1,12 @@
 warning: unexpected `cfg` condition value: `unk`
-  --> $DIR/order-independant.rs:13:7
+  --> $DIR/order-independant.rs:11:7
    |
 LL | #[cfg(a = "unk")]
    |       ^^^^^^^^^
    |
    = note: expected values for `a` are: (none), `b`
    = help: to expect this configuration use `--check-cfg=cfg(a, values("unk"))`
-   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
    = note: `#[warn(unexpected_cfgs)]` on by default
 
 warning: 1 warning emitted
diff --git a/tests/ui/check-cfg/order-independant.values_before.stderr b/tests/ui/check-cfg/order-independant.values_before.stderr
index d1de26ba303..7e18df8e1c2 100644
--- a/tests/ui/check-cfg/order-independant.values_before.stderr
+++ b/tests/ui/check-cfg/order-independant.values_before.stderr
@@ -1,12 +1,12 @@
 warning: unexpected `cfg` condition value: `unk`
-  --> $DIR/order-independant.rs:13:7
+  --> $DIR/order-independant.rs:11:7
    |
 LL | #[cfg(a = "unk")]
    |       ^^^^^^^^^
    |
    = note: expected values for `a` are: (none), `b`
    = help: to expect this configuration use `--check-cfg=cfg(a, values("unk"))`
-   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
    = note: `#[warn(unexpected_cfgs)]` on by default
 
 warning: 1 warning emitted
diff --git a/tests/ui/check-cfg/stmt-no-ice.rs b/tests/ui/check-cfg/stmt-no-ice.rs
index 8a447ade068..866a5836db0 100644
--- a/tests/ui/check-cfg/stmt-no-ice.rs
+++ b/tests/ui/check-cfg/stmt-no-ice.rs
@@ -1,7 +1,7 @@
 // This test checks that there is no ICE with this code
 //
 //@ check-pass
-//@ compile-flags:--check-cfg=cfg() -Z unstable-options
+//@ compile-flags:--check-cfg=cfg()
 
 fn main() {
     #[cfg(crossbeam_loom)]
diff --git a/tests/ui/check-cfg/stmt-no-ice.stderr b/tests/ui/check-cfg/stmt-no-ice.stderr
index 1afdbe84d34..e686cdddc1c 100644
--- a/tests/ui/check-cfg/stmt-no-ice.stderr
+++ b/tests/ui/check-cfg/stmt-no-ice.stderr
@@ -6,7 +6,7 @@ LL |     #[cfg(crossbeam_loom)]
    |
    = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, `windows`
    = help: to expect this configuration use `--check-cfg=cfg(crossbeam_loom)`
-   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
    = note: `#[warn(unexpected_cfgs)]` on by default
 
 warning: 1 warning emitted
diff --git a/tests/ui/check-cfg/unexpected-cfg-name.rs b/tests/ui/check-cfg/unexpected-cfg-name.rs
index 5ea9f560ee4..365c29d10fb 100644
--- a/tests/ui/check-cfg/unexpected-cfg-name.rs
+++ b/tests/ui/check-cfg/unexpected-cfg-name.rs
@@ -1,7 +1,7 @@
 // Check warning for unexpected configuration name
 //
 //@ check-pass
-//@ compile-flags: --check-cfg=cfg() -Z unstable-options
+//@ compile-flags: --check-cfg=cfg()
 
 #[cfg(widnows)]
 //~^ WARNING unexpected `cfg` condition name
diff --git a/tests/ui/check-cfg/unexpected-cfg-name.stderr b/tests/ui/check-cfg/unexpected-cfg-name.stderr
index 8748b324fb6..0b265078aa5 100644
--- a/tests/ui/check-cfg/unexpected-cfg-name.stderr
+++ b/tests/ui/check-cfg/unexpected-cfg-name.stderr
@@ -5,7 +5,7 @@ LL | #[cfg(widnows)]
    |       ^^^^^^^ help: there is a config with a similar name: `windows`
    |
    = help: to expect this configuration use `--check-cfg=cfg(widnows)`
-   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
    = note: `#[warn(unexpected_cfgs)]` on by default
 
 warning: 1 warning emitted
diff --git a/tests/ui/check-cfg/unexpected-cfg-value.rs b/tests/ui/check-cfg/unexpected-cfg-value.rs
index a4a10e503be..583cf40c485 100644
--- a/tests/ui/check-cfg/unexpected-cfg-value.rs
+++ b/tests/ui/check-cfg/unexpected-cfg-value.rs
@@ -1,7 +1,7 @@
 // Check for unexpected configuration value in the code.
 //
 //@ check-pass
-//@ compile-flags: --cfg=feature="rand" -Z unstable-options
+//@ compile-flags: --cfg=feature="rand"
 //@ compile-flags: --check-cfg=cfg(feature,values("serde","full"))
 
 #[cfg(feature = "sedre")]
diff --git a/tests/ui/check-cfg/unexpected-cfg-value.stderr b/tests/ui/check-cfg/unexpected-cfg-value.stderr
index e5435d37670..c3001208492 100644
--- a/tests/ui/check-cfg/unexpected-cfg-value.stderr
+++ b/tests/ui/check-cfg/unexpected-cfg-value.stderr
@@ -8,7 +8,7 @@ LL | #[cfg(feature = "sedre")]
    |
    = note: expected values for `feature` are: `full`, `serde`
    = help: to expect this configuration use `--check-cfg=cfg(feature, values("sedre"))`
-   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
    = note: `#[warn(unexpected_cfgs)]` on by default
 
 warning: unexpected `cfg` condition value: `rand`
@@ -19,7 +19,7 @@ LL | #[cfg(feature = "rand")]
    |
    = note: expected values for `feature` are: `full`, `serde`
    = help: to expect this configuration use `--check-cfg=cfg(feature, values("rand"))`
-   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: 2 warnings emitted
 
diff --git a/tests/ui/check-cfg/unknown-values.rs b/tests/ui/check-cfg/unknown-values.rs
index 61ea82871b2..7b2b00fe9d4 100644
--- a/tests/ui/check-cfg/unknown-values.rs
+++ b/tests/ui/check-cfg/unknown-values.rs
@@ -2,7 +2,6 @@
 //
 //@ check-pass
 //@ revisions: simple mixed with_values
-//@ compile-flags: -Z unstable-options
 //@ compile-flags: --check-cfg=cfg(simple,mixed,with_values)
 //@ [simple]compile-flags: --check-cfg=cfg(foo,values(any()))
 //@ [mixed]compile-flags: --check-cfg=cfg(foo) --check-cfg=cfg(foo,values(any()))
diff --git a/tests/ui/check-cfg/values-none.explicit.stderr b/tests/ui/check-cfg/values-none.explicit.stderr
index a025ff441b7..f75cc08f551 100644
--- a/tests/ui/check-cfg/values-none.explicit.stderr
+++ b/tests/ui/check-cfg/values-none.explicit.stderr
@@ -1,5 +1,5 @@
 warning: unexpected `cfg` condition value: `too`
-  --> $DIR/values-none.rs:11:7
+  --> $DIR/values-none.rs:10:7
    |
 LL | #[cfg(foo = "too")]
    |       ^^^--------
@@ -8,11 +8,11 @@ LL | #[cfg(foo = "too")]
    |
    = note: no expected value for `foo`
    = help: to expect this configuration use `--check-cfg=cfg(foo, values("too"))`
-   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
    = note: `#[warn(unexpected_cfgs)]` on by default
 
 warning: unexpected `cfg` condition value: `bar`
-  --> $DIR/values-none.rs:16:7
+  --> $DIR/values-none.rs:15:7
    |
 LL | #[cfg(foo = "bar")]
    |       ^^^--------
@@ -21,7 +21,7 @@ LL | #[cfg(foo = "bar")]
    |
    = note: no expected value for `foo`
    = help: to expect this configuration use `--check-cfg=cfg(foo, values("bar"))`
-   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: 2 warnings emitted
 
diff --git a/tests/ui/check-cfg/values-none.implicit.stderr b/tests/ui/check-cfg/values-none.implicit.stderr
index a025ff441b7..f75cc08f551 100644
--- a/tests/ui/check-cfg/values-none.implicit.stderr
+++ b/tests/ui/check-cfg/values-none.implicit.stderr
@@ -1,5 +1,5 @@
 warning: unexpected `cfg` condition value: `too`
-  --> $DIR/values-none.rs:11:7
+  --> $DIR/values-none.rs:10:7
    |
 LL | #[cfg(foo = "too")]
    |       ^^^--------
@@ -8,11 +8,11 @@ LL | #[cfg(foo = "too")]
    |
    = note: no expected value for `foo`
    = help: to expect this configuration use `--check-cfg=cfg(foo, values("too"))`
-   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
    = note: `#[warn(unexpected_cfgs)]` on by default
 
 warning: unexpected `cfg` condition value: `bar`
-  --> $DIR/values-none.rs:16:7
+  --> $DIR/values-none.rs:15:7
    |
 LL | #[cfg(foo = "bar")]
    |       ^^^--------
@@ -21,7 +21,7 @@ LL | #[cfg(foo = "bar")]
    |
    = note: no expected value for `foo`
    = help: to expect this configuration use `--check-cfg=cfg(foo, values("bar"))`
-   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: 2 warnings emitted
 
diff --git a/tests/ui/check-cfg/values-none.rs b/tests/ui/check-cfg/values-none.rs
index 6a68020e418..bd9c0255b7d 100644
--- a/tests/ui/check-cfg/values-none.rs
+++ b/tests/ui/check-cfg/values-none.rs
@@ -1,7 +1,6 @@
 //@ check-pass
 //
 //@ revisions: explicit implicit
-//@ compile-flags: -Zunstable-options
 //@ [explicit]compile-flags: --check-cfg=cfg(foo,values(none()))
 //@ [implicit]compile-flags: --check-cfg=cfg(foo)
 //@ [simple]  compile-flags: --check-cfg=cfg(foo,values(none(),"too"))
diff --git a/tests/ui/check-cfg/values-target-json.rs b/tests/ui/check-cfg/values-target-json.rs
index afe6e0aaffd..f3a27043e67 100644
--- a/tests/ui/check-cfg/values-target-json.rs
+++ b/tests/ui/check-cfg/values-target-json.rs
@@ -2,7 +2,7 @@
 //
 //@ check-pass
 //@ needs-llvm-components: x86
-//@ compile-flags: --crate-type=lib --check-cfg=cfg() --target={{src-base}}/check-cfg/my-awesome-platform.json -Z unstable-options
+//@ compile-flags: --crate-type=lib --check-cfg=cfg() --target={{src-base}}/check-cfg/my-awesome-platform.json
 
 #![feature(lang_items, no_core, auto_traits)]
 #![no_core]
diff --git a/tests/ui/check-cfg/well-known-names.rs b/tests/ui/check-cfg/well-known-names.rs
index a0feee4225a..c277b84d9bd 100644
--- a/tests/ui/check-cfg/well-known-names.rs
+++ b/tests/ui/check-cfg/well-known-names.rs
@@ -1,7 +1,7 @@
 // This test checks that we lint on non well known names and that we don't lint on well known names
 //
 //@ check-pass
-//@ compile-flags: --check-cfg=cfg() -Z unstable-options
+//@ compile-flags: --check-cfg=cfg()
 
 #[cfg(target_oz = "linux")]
 //~^ WARNING unexpected `cfg` condition name
diff --git a/tests/ui/check-cfg/well-known-names.stderr b/tests/ui/check-cfg/well-known-names.stderr
index 467f9675f7f..b2db777e8a8 100644
--- a/tests/ui/check-cfg/well-known-names.stderr
+++ b/tests/ui/check-cfg/well-known-names.stderr
@@ -5,7 +5,7 @@ LL | #[cfg(target_oz = "linux")]
    |       ^^^^^^^^^^^^^^^^^^^
    |
    = help: to expect this configuration use `--check-cfg=cfg(target_oz, values("linux"))`
-   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
    = note: `#[warn(unexpected_cfgs)]` on by default
 help: there is a config with a similar name and value
    |
@@ -20,7 +20,7 @@ LL | #[cfg(features = "foo")]
    |
    = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, `windows`
    = help: to expect this configuration use `--check-cfg=cfg(features, values("foo"))`
-   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition name: `feature`
   --> $DIR/well-known-names.rs:17:7
@@ -29,7 +29,7 @@ LL | #[cfg(feature = "foo")]
    |       ^^^^^^^^^^^^^^^
    |
    = help: to expect this configuration use `--check-cfg=cfg(feature, values("foo"))`
-   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition name: `uniw`
   --> $DIR/well-known-names.rs:21:7
@@ -38,7 +38,7 @@ LL | #[cfg(uniw)]
    |       ^^^^ help: there is a config with a similar name: `unix`
    |
    = help: to expect this configuration use `--check-cfg=cfg(uniw)`
-   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: 4 warnings emitted
 
diff --git a/tests/ui/check-cfg/well-known-values.rs b/tests/ui/check-cfg/well-known-values.rs
index 2758a793538..4c010a62d21 100644
--- a/tests/ui/check-cfg/well-known-values.rs
+++ b/tests/ui/check-cfg/well-known-values.rs
@@ -5,7 +5,7 @@
 // values since the suggestion shows them.
 //
 //@ check-pass
-//@ compile-flags: --check-cfg=cfg() -Z unstable-options
+//@ compile-flags: --check-cfg=cfg()
 //@ compile-flags: -Zcheck-cfg-all-expected
 
 #![feature(cfg_overflow_checks)]
diff --git a/tests/ui/check-cfg/well-known-values.stderr b/tests/ui/check-cfg/well-known-values.stderr
index 729794150f6..af3ef92fdd5 100644
--- a/tests/ui/check-cfg/well-known-values.stderr
+++ b/tests/ui/check-cfg/well-known-values.stderr
@@ -7,7 +7,7 @@ LL |     clippy = "_UNEXPECTED_VALUE",
    |           help: remove the value
    |
    = note: no expected value for `clippy`
-   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
    = note: `#[warn(unexpected_cfgs)]` on by default
 
 warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
@@ -19,7 +19,7 @@ LL |     debug_assertions = "_UNEXPECTED_VALUE",
    |                     help: remove the value
    |
    = note: no expected value for `debug_assertions`
-   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
   --> $DIR/well-known-values.rs:31:5
@@ -30,7 +30,7 @@ LL |     doc = "_UNEXPECTED_VALUE",
    |        help: remove the value
    |
    = note: no expected value for `doc`
-   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
   --> $DIR/well-known-values.rs:33:5
@@ -41,7 +41,7 @@ LL |     doctest = "_UNEXPECTED_VALUE",
    |            help: remove the value
    |
    = note: no expected value for `doctest`
-   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
   --> $DIR/well-known-values.rs:35:5
@@ -52,7 +52,7 @@ LL |     miri = "_UNEXPECTED_VALUE",
    |         help: remove the value
    |
    = note: no expected value for `miri`
-   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
   --> $DIR/well-known-values.rs:37:5
@@ -63,7 +63,7 @@ LL |     overflow_checks = "_UNEXPECTED_VALUE",
    |                    help: remove the value
    |
    = note: no expected value for `overflow_checks`
-   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
   --> $DIR/well-known-values.rs:39:5
@@ -72,7 +72,7 @@ LL |     panic = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: expected values for `panic` are: `abort`, `unwind`
-   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
   --> $DIR/well-known-values.rs:41:5
@@ -83,7 +83,7 @@ LL |     proc_macro = "_UNEXPECTED_VALUE",
    |               help: remove the value
    |
    = note: no expected value for `proc_macro`
-   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
   --> $DIR/well-known-values.rs:43:5
@@ -92,7 +92,7 @@ LL |     relocation_model = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: expected values for `relocation_model` are: `dynamic-no-pic`, `pic`, `pie`, `ropi`, `ropi-rwpi`, `rwpi`, `static`
-   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
   --> $DIR/well-known-values.rs:45:5
@@ -101,7 +101,7 @@ LL |     sanitize = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: expected values for `sanitize` are: `address`, `cfi`, `dataflow`, `hwaddress`, `kcfi`, `kernel-address`, `leak`, `memory`, `memtag`, `safestack`, `shadow-call-stack`, `thread`
-   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
   --> $DIR/well-known-values.rs:47:5
@@ -110,7 +110,7 @@ LL |     target_abi = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: expected values for `target_abi` are: ``, `abi64`, `abiv2`, `abiv2hf`, `eabi`, `eabihf`, `elf`, `fortanix`, `ilp32`, `llvm`, `macabi`, `sim`, `softfloat`, `spe`, `uwp`, `vec-extabi`, `x32`
-   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
   --> $DIR/well-known-values.rs:49:5
@@ -119,7 +119,7 @@ LL |     target_arch = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: expected values for `target_arch` are: `aarch64`, `arm`, `arm64ec`, `avr`, `bpf`, `csky`, `hexagon`, `loongarch64`, `m68k`, `mips`, `mips32r6`, `mips64`, `mips64r6`, `msp430`, `nvptx64`, `powerpc`, `powerpc64`, `riscv32`, `riscv64`, `s390x`, `sparc`, `sparc64`, `wasm32`, `wasm64`, `x86`, `x86_64`
-   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
   --> $DIR/well-known-values.rs:51:5
@@ -128,7 +128,7 @@ LL |     target_endian = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: expected values for `target_endian` are: `big`, `little`
-   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
   --> $DIR/well-known-values.rs:53:5
@@ -137,7 +137,7 @@ LL |     target_env = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: expected values for `target_env` are: ``, `gnu`, `msvc`, `musl`, `newlib`, `nto70`, `nto71`, `ohos`, `p2`, `psx`, `relibc`, `sgx`, `uclibc`
-   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
   --> $DIR/well-known-values.rs:55:5
@@ -146,7 +146,7 @@ LL |     target_family = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: expected values for `target_family` are: `unix`, `wasm`, `windows`
-   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
   --> $DIR/well-known-values.rs:57:5
@@ -155,7 +155,7 @@ LL |     target_feature = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: expected values for `target_feature` are: `10e60`, `2e3`, `3e3r1`, `3e3r2`, `3e3r3`, `3e7`, `7e10`, `a`, `aclass`, `adx`, `aes`, `altivec`, `alu32`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512er`, `avx512f`, `avx512fp16`, `avx512ifma`, `avx512pf`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, `avx512vpopcntdq`, `bf16`, `bmi1`, `bmi2`, `bti`, `bulk-memory`, `c`, `cache`, `cmpxchg16b`, `crc`, `crt-static`, `d`, `d32`, `dit`, `doloop`, `dotprod`, `dpb`, `dpb2`, `dsp`, `dsp1e2`, `dspe60`, `e`, `e1`, `e2`, `edsp`, `elrw`, `ermsb`, `exception-handling`, `f`, `f16c`, `f32mm`, `f64mm`, `fast-unaligned-access`, `fcma`, `fdivdu`, `fhm`, `flagm`, `float1e2`, `float1e3`, `float3e4`, `float7e60`, `floate1`, `fma`, `fp-armv8`, `fp16`, `fp64`, `fpuv2_df`, `fpuv2_sf`, `fpuv3_df`, `fpuv3_hf`, `fpuv3_hi`, `fpuv3_sf`, `frecipe`, `frintts`, `fxsr`, `gfni`, `hard-float`, `hard-float-abi`, `hard-tp`, `high-registers`, `hvx`, `hvx-length128b`, `hwdiv`, `i8mm`, `jsconv`, `lahfsahf`, `lasx`, `lbt`, `lor`, `lse`, `lsx`, `lvz`, `lzcnt`, `m`, `mclass`, `movbe`, `mp`, `mp1e2`, `msa`, `mte`, `multivalue`, `mutable-globals`, `neon`, `nontrapping-fptoint`, `nvic`, `paca`, `pacg`, `pan`, `pclmulqdq`, `pmuv3`, `popcnt`, `power10-vector`, `power8-altivec`, `power8-vector`, `power9-altivec`, `power9-vector`, `prfchw`, `rand`, `ras`, `rclass`, `rcpc`, `rcpc2`, `rdm`, `rdrand`, `rdseed`, `reference-types`, `relax`, `relaxed-simd`, `rtm`, `sb`, `sha`, `sha2`, `sha3`, `sign-ext`, `simd128`, `sm4`, `spe`, `ssbs`, `sse`, `sse2`, `sse3`, `sse4.1`, `sse4.2`, `sse4a`, `ssse3`, `sve`, `sve2`, `sve2-aes`, `sve2-bitperm`, `sve2-sha3`, `sve2-sm4`, `tbm`, `thumb-mode`, `thumb2`, `tme`, `trust`, `trustzone`, `ual`, `v`, `v5te`, `v6`, `v6k`, `v6t2`, `v7`, `v8`, `v8.1a`, `v8.2a`, `v8.3a`, `v8.4a`, `v8.5a`, `v8.6a`, `v8.7a`, `vaes`, `vdsp2e60f`, `vdspv1`, `vdspv2`, `vfp2`, `vfp3`, `vfp4`, `vh`, `virt`, `virtualization`, `vpclmulqdq`, `vsx`, `xsave`, `xsavec`, `xsaveopt`, `xsaves`, `zba`, `zbb`, `zbc`, `zbkb`, `zbkc`, `zbkx`, `zbs`, `zdinx`, `zfh`, `zfhmin`, `zfinx`, `zhinx`, `zhinxmin`, `zk`, `zkn`, `zknd`, `zkne`, `zknh`, `zkr`, `zks`, `zksed`, `zksh`, `zkt`
-   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
   --> $DIR/well-known-values.rs:59:5
@@ -164,7 +164,7 @@ LL |     target_has_atomic = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: expected values for `target_has_atomic` are: (none), `128`, `16`, `32`, `64`, `8`, `ptr`
-   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
   --> $DIR/well-known-values.rs:61:5
@@ -173,7 +173,7 @@ LL |     target_has_atomic_equal_alignment = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: expected values for `target_has_atomic_equal_alignment` are: (none), `128`, `16`, `32`, `64`, `8`, `ptr`
-   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
   --> $DIR/well-known-values.rs:63:5
@@ -182,7 +182,7 @@ LL |     target_has_atomic_load_store = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: expected values for `target_has_atomic_load_store` are: (none), `128`, `16`, `32`, `64`, `8`, `ptr`
-   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
   --> $DIR/well-known-values.rs:65:5
@@ -191,7 +191,7 @@ LL |     target_os = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: expected values for `target_os` are: `aix`, `android`, `cuda`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `macos`, `netbsd`, `none`, `nto`, `openbsd`, `psp`, `redox`, `solaris`, `solid_asp3`, `teeos`, `tvos`, `uefi`, `unknown`, `visionos`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous`, `zkvm`
-   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
   --> $DIR/well-known-values.rs:67:5
@@ -200,7 +200,7 @@ LL |     target_pointer_width = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: expected values for `target_pointer_width` are: `16`, `32`, `64`
-   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
   --> $DIR/well-known-values.rs:69:5
@@ -211,7 +211,7 @@ LL |     target_thread_local = "_UNEXPECTED_VALUE",
    |                        help: remove the value
    |
    = note: no expected value for `target_thread_local`
-   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
   --> $DIR/well-known-values.rs:71:5
@@ -220,7 +220,7 @@ LL |     target_vendor = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: expected values for `target_vendor` are: `apple`, `espressif`, `fortanix`, `ibm`, `kmc`, `nintendo`, `nvidia`, `pc`, `risc0`, `sony`, `sun`, `unikraft`, `unknown`, `uwp`, `win7`, `wrs`
-   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
   --> $DIR/well-known-values.rs:73:5
@@ -231,7 +231,7 @@ LL |     test = "_UNEXPECTED_VALUE",
    |         help: remove the value
    |
    = note: no expected value for `test`
-   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
   --> $DIR/well-known-values.rs:75:5
@@ -242,7 +242,7 @@ LL |     ub_checks = "_UNEXPECTED_VALUE",
    |              help: remove the value
    |
    = note: no expected value for `ub_checks`
-   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
   --> $DIR/well-known-values.rs:77:5
@@ -253,7 +253,7 @@ LL |     unix = "_UNEXPECTED_VALUE",
    |         help: remove the value
    |
    = note: no expected value for `unix`
-   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
   --> $DIR/well-known-values.rs:79:5
@@ -264,7 +264,7 @@ LL |     windows = "_UNEXPECTED_VALUE",
    |            help: remove the value
    |
    = note: no expected value for `windows`
-   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `linuz`
   --> $DIR/well-known-values.rs:85:7
@@ -275,7 +275,7 @@ LL | #[cfg(target_os = "linuz")] // testing that we suggest `linux`
    |                   help: there is a expected value with a similar name: `"linux"`
    |
    = note: expected values for `target_os` are: `aix`, `android`, `cuda`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `macos`, `netbsd`, `none`, `nto`, `openbsd`, `psp`, `redox`, `solaris`, `solid_asp3`, `teeos`, `tvos`, `uefi`, `unknown`, `visionos`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous`, `zkvm`
-   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: 28 warnings emitted
 
diff --git a/tests/ui/closures/issue-78720.rs b/tests/ui/closures/issue-78720.rs
index 0c4f337ba57..81af030fe55 100644
--- a/tests/ui/closures/issue-78720.rs
+++ b/tests/ui/closures/issue-78720.rs
@@ -1,6 +1,5 @@
 fn server() -> impl {
     //~^ ERROR at least one trait must be specified
-    //~| ERROR type annotations needed
     ().map2(|| "")
 }
 
diff --git a/tests/ui/closures/issue-78720.stderr b/tests/ui/closures/issue-78720.stderr
index 2f57c7616f1..5d65c87b0fd 100644
--- a/tests/ui/closures/issue-78720.stderr
+++ b/tests/ui/closures/issue-78720.stderr
@@ -5,7 +5,7 @@ LL | fn server() -> impl {
    |                ^^^^
 
 error[E0412]: cannot find type `F` in this scope
-  --> $DIR/issue-78720.rs:14:12
+  --> $DIR/issue-78720.rs:13:12
    |
 LL |     _func: F,
    |            ^
@@ -22,14 +22,8 @@ help: you might be missing a type parameter
 LL | struct Map2<Segment2, F> {
    |                     +++
 
-error[E0282]: type annotations needed
-  --> $DIR/issue-78720.rs:1:16
-   |
-LL | fn server() -> impl {
-   |                ^^^^ cannot infer type
-
 error[E0308]: mismatched types
-  --> $DIR/issue-78720.rs:8:39
+  --> $DIR/issue-78720.rs:7:39
    |
 LL |     fn map2<F>(self, f: F) -> Map2<F> {}
    |                                       ^^ expected `Map2<F>`, found `()`
@@ -38,7 +32,7 @@ LL |     fn map2<F>(self, f: F) -> Map2<F> {}
            found unit type `()`
 
 error[E0277]: the size for values of type `Self` cannot be known at compilation time
-  --> $DIR/issue-78720.rs:8:16
+  --> $DIR/issue-78720.rs:7:16
    |
 LL |     fn map2<F>(self, f: F) -> Map2<F> {}
    |                ^^^^ doesn't have a size known at compile-time
@@ -53,7 +47,7 @@ help: function arguments must have a statically known size, borrowed types alway
 LL |     fn map2<F>(&self, f: F) -> Map2<F> {}
    |                +
 
-error: aborting due to 5 previous errors
+error: aborting due to 4 previous errors
 
-Some errors have detailed explanations: E0277, E0282, E0308, E0412.
+Some errors have detailed explanations: E0277, E0308, E0412.
 For more information about an error, try `rustc --explain E0277`.
diff --git a/tests/ui/const-generics/kind_mismatch.rs b/tests/ui/const-generics/kind_mismatch.rs
new file mode 100644
index 00000000000..bab58d5952a
--- /dev/null
+++ b/tests/ui/const-generics/kind_mismatch.rs
@@ -0,0 +1,24 @@
+//! This test used to ICE in typeck because of the type/const mismatch,
+//! even though wfcheck already errored.
+//! issue: rust-lang/rust#123457
+
+pub struct KeyHolder<const K: u8> {}
+
+pub trait ContainsKey<const K: u8> {}
+
+pub trait SubsetExcept<P> {}
+
+impl<K> ContainsKey<K> for KeyHolder<K> {}
+//~^ ERROR: type provided when a constant was expected
+//~| ERROR: type provided when a constant was expected
+
+impl<P, T: ContainsKey<0>> SubsetExcept<P> for T {}
+
+pub fn remove_key<K, S: SubsetExcept<K>>() -> S {
+    loop {}
+}
+
+fn main() {
+    let map: KeyHolder<0> = remove_key::<_, _>();
+    //~^ ERROR: the trait bound `KeyHolder<0>: SubsetExcept<_>` is not satisfied
+}
diff --git a/tests/ui/const-generics/kind_mismatch.stderr b/tests/ui/const-generics/kind_mismatch.stderr
new file mode 100644
index 00000000000..80968ebea68
--- /dev/null
+++ b/tests/ui/const-generics/kind_mismatch.stderr
@@ -0,0 +1,39 @@
+error[E0747]: type provided when a constant was expected
+  --> $DIR/kind_mismatch.rs:11:38
+   |
+LL | impl<K> ContainsKey<K> for KeyHolder<K> {}
+   |      -                               ^
+   |      |
+   |      help: consider changing this type parameter to a const parameter: `const K: u8`
+
+error[E0747]: type provided when a constant was expected
+  --> $DIR/kind_mismatch.rs:11:21
+   |
+LL | impl<K> ContainsKey<K> for KeyHolder<K> {}
+   |      -              ^
+   |      |
+   |      help: consider changing this type parameter to a const parameter: `const K: u8`
+
+error[E0277]: the trait bound `KeyHolder<0>: SubsetExcept<_>` is not satisfied
+  --> $DIR/kind_mismatch.rs:22:45
+   |
+LL |     let map: KeyHolder<0> = remove_key::<_, _>();
+   |                                             ^ the trait `ContainsKey<0>` is not implemented for `KeyHolder<0>`, which is required by `KeyHolder<0>: SubsetExcept<_>`
+   |
+note: required for `KeyHolder<0>` to implement `SubsetExcept<_>`
+  --> $DIR/kind_mismatch.rs:15:28
+   |
+LL | impl<P, T: ContainsKey<0>> SubsetExcept<P> for T {}
+   |            --------------  ^^^^^^^^^^^^^^^     ^
+   |            |
+   |            unsatisfied trait bound introduced here
+note: required by a bound in `remove_key`
+  --> $DIR/kind_mismatch.rs:17:25
+   |
+LL | pub fn remove_key<K, S: SubsetExcept<K>>() -> S {
+   |                         ^^^^^^^^^^^^^^^ required by this bound in `remove_key`
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0277, E0747.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/tests/ui/const_prop/ice-type-mismatch-when-copying-112824.rs b/tests/ui/const_prop/ice-type-mismatch-when-copying-112824.rs
index dc9782295c1..a41a159c1fd 100644
--- a/tests/ui/const_prop/ice-type-mismatch-when-copying-112824.rs
+++ b/tests/ui/const_prop/ice-type-mismatch-when-copying-112824.rs
@@ -13,7 +13,6 @@ impl Opcode2 {
 pub fn example2(msg_type: Opcode2) -> impl FnMut(&[u8]) {
     move |i| match msg_type {
         Opcode2::OP2 => unimplemented!(),
-        //~^ ERROR could not evaluate constant pattern
     }
 }
 
diff --git a/tests/ui/const_prop/ice-type-mismatch-when-copying-112824.stderr b/tests/ui/const_prop/ice-type-mismatch-when-copying-112824.stderr
index 9442eac0cf5..d95a8861230 100644
--- a/tests/ui/const_prop/ice-type-mismatch-when-copying-112824.stderr
+++ b/tests/ui/const_prop/ice-type-mismatch-when-copying-112824.stderr
@@ -17,13 +17,7 @@ help: you might be missing a type parameter
 LL | pub struct Opcode2<S>(&'a S);
    |                   +++
 
-error: could not evaluate constant pattern
-  --> $DIR/ice-type-mismatch-when-copying-112824.rs:15:9
-   |
-LL |         Opcode2::OP2 => unimplemented!(),
-   |         ^^^^^^^^^^^^
-
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
 Some errors have detailed explanations: E0261, E0412.
 For more information about an error, try `rustc --explain E0261`.
diff --git a/tests/ui/consts/const-eval/ice-unsized-struct-const-eval-123154.rs b/tests/ui/consts/const-eval/ice-unsized-struct-const-eval-123154.rs
new file mode 100644
index 00000000000..24a2cd19b18
--- /dev/null
+++ b/tests/ui/consts/const-eval/ice-unsized-struct-const-eval-123154.rs
@@ -0,0 +1,15 @@
+// Regression test for #123154
+
+struct AA {
+    pub data: [&usize]
+    //~^ ERROR missing lifetime specifier
+}
+
+impl AA {
+    const fn new() -> Self { }
+    //~^ ERROR mismatched types
+}
+
+static ST: AA = AA::new();
+
+fn main() {}
diff --git a/tests/ui/consts/const-eval/ice-unsized-struct-const-eval-123154.stderr b/tests/ui/consts/const-eval/ice-unsized-struct-const-eval-123154.stderr
new file mode 100644
index 00000000000..9657e5cdda1
--- /dev/null
+++ b/tests/ui/consts/const-eval/ice-unsized-struct-const-eval-123154.stderr
@@ -0,0 +1,24 @@
+error[E0106]: missing lifetime specifier
+  --> $DIR/ice-unsized-struct-const-eval-123154.rs:4:16
+   |
+LL |     pub data: [&usize]
+   |                ^ expected named lifetime parameter
+   |
+help: consider introducing a named lifetime parameter
+   |
+LL ~ struct AA<'a> {
+LL ~     pub data: [&'a usize]
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/ice-unsized-struct-const-eval-123154.rs:9:23
+   |
+LL |     const fn new() -> Self { }
+   |              ---      ^^^^ expected `AA`, found `()`
+   |              |
+   |              implicitly returns `()` as its body has no tail or `return` expression
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0106, E0308.
+For more information about an error, try `rustc --explain E0106`.
diff --git a/tests/ui/consts/value-suggestion-ice-123906.stderr b/tests/ui/consts/value-suggestion-ice-123906.stderr
index 8e2c316400d..9afd495268d 100644
--- a/tests/ui/consts/value-suggestion-ice-123906.stderr
+++ b/tests/ui/consts/value-suggestion-ice-123906.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
   --> $DIR/value-suggestion-ice-123906.rs:3:9
    |
 LL | fn as_chunks<const N: usize>() -> [u8; N] {
-   |                                   ------- expected `[u8; ]` because of this return type
+   |                                   ------- expected `[u8; N]` because of this return type
 LL |     loop {
    |     ---- this loop is expected to be of type `[u8; N]`
 LL |         break;
@@ -10,8 +10,8 @@ LL |         break;
    |
 help: give the `break` a value of the expected type
    |
-LL |         break value;
-   |               +++++
+LL |         break /* value */;
+   |               +++++++++++
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/enum/error-variant-with-turbofishes.rs b/tests/ui/enum/error-variant-with-turbofishes.rs
new file mode 100644
index 00000000000..a58d24ce20a
--- /dev/null
+++ b/tests/ui/enum/error-variant-with-turbofishes.rs
@@ -0,0 +1,8 @@
+enum Struct<const N: usize> { Variant { x: [(); N] } }
+
+fn test() {
+    let x = Struct::<0>::Variant;
+    //~^ ERROR expected value, found struct variant `Struct<0>::Variant`
+}
+
+fn main() {}
diff --git a/tests/ui/enum/error-variant-with-turbofishes.stderr b/tests/ui/enum/error-variant-with-turbofishes.stderr
new file mode 100644
index 00000000000..66bed1c0d85
--- /dev/null
+++ b/tests/ui/enum/error-variant-with-turbofishes.stderr
@@ -0,0 +1,9 @@
+error[E0533]: expected value, found struct variant `Struct<0>::Variant`
+  --> $DIR/error-variant-with-turbofishes.rs:4:13
+   |
+LL |     let x = Struct::<0>::Variant;
+   |             ^^^^^^^^^^^^^^^^^^^^ not a value
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0533`.
diff --git a/tests/ui/feature-gates/feature-gate-abi.rs b/tests/ui/feature-gates/feature-gate-abi.rs
index 1c3a732a497..3aa430e736f 100644
--- a/tests/ui/feature-gates/feature-gate-abi.rs
+++ b/tests/ui/feature-gates/feature-gate-abi.rs
@@ -13,10 +13,8 @@ trait Tuple { }
 // Functions
 extern "rust-intrinsic" fn f1() {} //~ ERROR intrinsics are subject to change
                                    //~^ ERROR intrinsic must be in
-                                   //~| ERROR unrecognized intrinsic function: `f1`
 extern "rust-intrinsic" fn f2() {} //~ ERROR intrinsics are subject to change
                                        //~^ ERROR intrinsic must be in
-                                       //~| ERROR unrecognized intrinsic function: `f2`
 extern "rust-call" fn f4(_: ()) {} //~ ERROR rust-call ABI is subject to change
 
 // Methods in trait definition
diff --git a/tests/ui/feature-gates/feature-gate-abi.stderr b/tests/ui/feature-gates/feature-gate-abi.stderr
index c28cd05a96a..dbdfa7b275d 100644
--- a/tests/ui/feature-gates/feature-gate-abi.stderr
+++ b/tests/ui/feature-gates/feature-gate-abi.stderr
@@ -8,7 +8,7 @@ LL | extern "rust-intrinsic" fn f1() {}
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0658]: intrinsics are subject to change
-  --> $DIR/feature-gate-abi.rs:17:8
+  --> $DIR/feature-gate-abi.rs:16:8
    |
 LL | extern "rust-intrinsic" fn f2() {}
    |        ^^^^^^^^^^^^^^^^
@@ -17,7 +17,7 @@ LL | extern "rust-intrinsic" fn f2() {}
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0658]: rust-call ABI is subject to change
-  --> $DIR/feature-gate-abi.rs:20:8
+  --> $DIR/feature-gate-abi.rs:18:8
    |
 LL | extern "rust-call" fn f4(_: ()) {}
    |        ^^^^^^^^^^^
@@ -27,7 +27,7 @@ LL | extern "rust-call" fn f4(_: ()) {}
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0658]: intrinsics are subject to change
-  --> $DIR/feature-gate-abi.rs:24:12
+  --> $DIR/feature-gate-abi.rs:22:12
    |
 LL |     extern "rust-intrinsic" fn m1();
    |            ^^^^^^^^^^^^^^^^
@@ -36,7 +36,7 @@ LL |     extern "rust-intrinsic" fn m1();
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0658]: intrinsics are subject to change
-  --> $DIR/feature-gate-abi.rs:26:12
+  --> $DIR/feature-gate-abi.rs:24:12
    |
 LL |     extern "rust-intrinsic" fn m2();
    |            ^^^^^^^^^^^^^^^^
@@ -45,7 +45,7 @@ LL |     extern "rust-intrinsic" fn m2();
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0658]: rust-call ABI is subject to change
-  --> $DIR/feature-gate-abi.rs:28:12
+  --> $DIR/feature-gate-abi.rs:26:12
    |
 LL |     extern "rust-call" fn m4(_: ());
    |            ^^^^^^^^^^^
@@ -55,7 +55,7 @@ LL |     extern "rust-call" fn m4(_: ());
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0658]: rust-call ABI is subject to change
-  --> $DIR/feature-gate-abi.rs:30:12
+  --> $DIR/feature-gate-abi.rs:28:12
    |
 LL |     extern "rust-call" fn dm4(_: ()) {}
    |            ^^^^^^^^^^^
@@ -65,7 +65,7 @@ LL |     extern "rust-call" fn dm4(_: ()) {}
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0658]: intrinsics are subject to change
-  --> $DIR/feature-gate-abi.rs:37:12
+  --> $DIR/feature-gate-abi.rs:35:12
    |
 LL |     extern "rust-intrinsic" fn m1() {}
    |            ^^^^^^^^^^^^^^^^
@@ -74,7 +74,7 @@ LL |     extern "rust-intrinsic" fn m1() {}
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0658]: intrinsics are subject to change
-  --> $DIR/feature-gate-abi.rs:39:12
+  --> $DIR/feature-gate-abi.rs:37:12
    |
 LL |     extern "rust-intrinsic" fn m2() {}
    |            ^^^^^^^^^^^^^^^^
@@ -83,7 +83,7 @@ LL |     extern "rust-intrinsic" fn m2() {}
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0658]: rust-call ABI is subject to change
-  --> $DIR/feature-gate-abi.rs:41:12
+  --> $DIR/feature-gate-abi.rs:39:12
    |
 LL |     extern "rust-call" fn m4(_: ()) {}
    |            ^^^^^^^^^^^
@@ -93,7 +93,7 @@ LL |     extern "rust-call" fn m4(_: ()) {}
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0658]: intrinsics are subject to change
-  --> $DIR/feature-gate-abi.rs:46:12
+  --> $DIR/feature-gate-abi.rs:44:12
    |
 LL |     extern "rust-intrinsic" fn im1() {}
    |            ^^^^^^^^^^^^^^^^
@@ -102,7 +102,7 @@ LL |     extern "rust-intrinsic" fn im1() {}
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0658]: intrinsics are subject to change
-  --> $DIR/feature-gate-abi.rs:48:12
+  --> $DIR/feature-gate-abi.rs:46:12
    |
 LL |     extern "rust-intrinsic" fn im2() {}
    |            ^^^^^^^^^^^^^^^^
@@ -111,7 +111,7 @@ LL |     extern "rust-intrinsic" fn im2() {}
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0658]: rust-call ABI is subject to change
-  --> $DIR/feature-gate-abi.rs:50:12
+  --> $DIR/feature-gate-abi.rs:48:12
    |
 LL |     extern "rust-call" fn im4(_: ()) {}
    |            ^^^^^^^^^^^
@@ -121,7 +121,7 @@ LL |     extern "rust-call" fn im4(_: ()) {}
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0658]: intrinsics are subject to change
-  --> $DIR/feature-gate-abi.rs:54:18
+  --> $DIR/feature-gate-abi.rs:52:18
    |
 LL | type A1 = extern "rust-intrinsic" fn();
    |                  ^^^^^^^^^^^^^^^^
@@ -130,7 +130,7 @@ LL | type A1 = extern "rust-intrinsic" fn();
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0658]: intrinsics are subject to change
-  --> $DIR/feature-gate-abi.rs:55:18
+  --> $DIR/feature-gate-abi.rs:53:18
    |
 LL | type A2 = extern "rust-intrinsic" fn();
    |                  ^^^^^^^^^^^^^^^^
@@ -139,7 +139,7 @@ LL | type A2 = extern "rust-intrinsic" fn();
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0658]: rust-call ABI is subject to change
-  --> $DIR/feature-gate-abi.rs:56:18
+  --> $DIR/feature-gate-abi.rs:54:18
    |
 LL | type A4 = extern "rust-call" fn(_: ());
    |                  ^^^^^^^^^^^
@@ -149,7 +149,7 @@ LL | type A4 = extern "rust-call" fn(_: ());
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0658]: intrinsics are subject to change
-  --> $DIR/feature-gate-abi.rs:59:8
+  --> $DIR/feature-gate-abi.rs:57:8
    |
 LL | extern "rust-intrinsic" {}
    |        ^^^^^^^^^^^^^^^^
@@ -158,7 +158,7 @@ LL | extern "rust-intrinsic" {}
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0658]: intrinsics are subject to change
-  --> $DIR/feature-gate-abi.rs:60:8
+  --> $DIR/feature-gate-abi.rs:58:8
    |
 LL | extern "rust-intrinsic" {}
    |        ^^^^^^^^^^^^^^^^
@@ -167,7 +167,7 @@ LL | extern "rust-intrinsic" {}
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0658]: rust-call ABI is subject to change
-  --> $DIR/feature-gate-abi.rs:61:8
+  --> $DIR/feature-gate-abi.rs:59:8
    |
 LL | extern "rust-call" {}
    |        ^^^^^^^^^^^
@@ -176,30 +176,14 @@ LL | extern "rust-call" {}
    = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0093]: unrecognized intrinsic function: `f1`
-  --> $DIR/feature-gate-abi.rs:14:28
-   |
-LL | extern "rust-intrinsic" fn f1() {}
-   |                            ^^ unrecognized intrinsic
-   |
-   = help: if you're adding an intrinsic, be sure to update `check_intrinsic_type`
-
-error[E0093]: unrecognized intrinsic function: `f2`
-  --> $DIR/feature-gate-abi.rs:17:28
-   |
-LL | extern "rust-intrinsic" fn f2() {}
-   |                            ^^ unrecognized intrinsic
-   |
-   = help: if you're adding an intrinsic, be sure to update `check_intrinsic_type`
-
 error: intrinsic must be in `extern "rust-intrinsic" { ... }` block
-  --> $DIR/feature-gate-abi.rs:24:32
+  --> $DIR/feature-gate-abi.rs:22:32
    |
 LL |     extern "rust-intrinsic" fn m1();
    |                                ^^
 
 error: intrinsic must be in `extern "rust-intrinsic" { ... }` block
-  --> $DIR/feature-gate-abi.rs:26:32
+  --> $DIR/feature-gate-abi.rs:24:32
    |
 LL |     extern "rust-intrinsic" fn m2();
    |                                ^^
@@ -211,36 +195,35 @@ LL | extern "rust-intrinsic" fn f1() {}
    |                                 ^^
 
 error: intrinsic must be in `extern "rust-intrinsic" { ... }` block
-  --> $DIR/feature-gate-abi.rs:17:33
+  --> $DIR/feature-gate-abi.rs:16:33
    |
 LL | extern "rust-intrinsic" fn f2() {}
    |                                 ^^
 
 error: intrinsic must be in `extern "rust-intrinsic" { ... }` block
-  --> $DIR/feature-gate-abi.rs:37:37
+  --> $DIR/feature-gate-abi.rs:35:37
    |
 LL |     extern "rust-intrinsic" fn m1() {}
    |                                     ^^
 
 error: intrinsic must be in `extern "rust-intrinsic" { ... }` block
-  --> $DIR/feature-gate-abi.rs:39:37
+  --> $DIR/feature-gate-abi.rs:37:37
    |
 LL |     extern "rust-intrinsic" fn m2() {}
    |                                     ^^
 
 error: intrinsic must be in `extern "rust-intrinsic" { ... }` block
-  --> $DIR/feature-gate-abi.rs:46:38
+  --> $DIR/feature-gate-abi.rs:44:38
    |
 LL |     extern "rust-intrinsic" fn im1() {}
    |                                      ^^
 
 error: intrinsic must be in `extern "rust-intrinsic" { ... }` block
-  --> $DIR/feature-gate-abi.rs:48:38
+  --> $DIR/feature-gate-abi.rs:46:38
    |
 LL |     extern "rust-intrinsic" fn im2() {}
    |                                      ^^
 
-error: aborting due to 29 previous errors
+error: aborting due to 27 previous errors
 
-Some errors have detailed explanations: E0093, E0658.
-For more information about an error, try `rustc --explain E0093`.
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/feature-gates/feature-gate-check-cfg.rs b/tests/ui/feature-gates/feature-gate-check-cfg.rs
deleted file mode 100644
index 1e0106aa748..00000000000
--- a/tests/ui/feature-gates/feature-gate-check-cfg.rs
+++ /dev/null
@@ -1,3 +0,0 @@
-//@ compile-flags: --check-cfg "cfg()"
-
-fn main() {}
diff --git a/tests/ui/feature-gates/feature-gate-check-cfg.stderr b/tests/ui/feature-gates/feature-gate-check-cfg.stderr
deleted file mode 100644
index 9b27c2bc058..00000000000
--- a/tests/ui/feature-gates/feature-gate-check-cfg.stderr
+++ /dev/null
@@ -1,2 +0,0 @@
-error: the `-Z unstable-options` flag must also be passed to enable the flag `check-cfg`
-
diff --git a/tests/ui/feature-gates/feature-gate-intrinsics.rs b/tests/ui/feature-gates/feature-gate-intrinsics.rs
index 725d968d24c..e0dc3cc579d 100644
--- a/tests/ui/feature-gates/feature-gate-intrinsics.rs
+++ b/tests/ui/feature-gates/feature-gate-intrinsics.rs
@@ -4,6 +4,5 @@ extern "rust-intrinsic" {   //~ ERROR intrinsics are subject to change
 
 extern "rust-intrinsic" fn baz() {} //~ ERROR intrinsics are subject to change
 //~^ ERROR intrinsic must be in
-//~| ERROR unrecognized intrinsic function: `baz`
 
 fn main() {}
diff --git a/tests/ui/feature-gates/feature-gate-intrinsics.stderr b/tests/ui/feature-gates/feature-gate-intrinsics.stderr
index 583a4a1a84e..577a620e2d2 100644
--- a/tests/ui/feature-gates/feature-gate-intrinsics.stderr
+++ b/tests/ui/feature-gates/feature-gate-intrinsics.stderr
@@ -24,21 +24,13 @@ LL |     fn bar();
    |
    = help: if you're adding an intrinsic, be sure to update `check_intrinsic_type`
 
-error[E0093]: unrecognized intrinsic function: `baz`
-  --> $DIR/feature-gate-intrinsics.rs:5:28
-   |
-LL | extern "rust-intrinsic" fn baz() {}
-   |                            ^^^ unrecognized intrinsic
-   |
-   = help: if you're adding an intrinsic, be sure to update `check_intrinsic_type`
-
 error: intrinsic must be in `extern "rust-intrinsic" { ... }` block
   --> $DIR/feature-gate-intrinsics.rs:5:34
    |
 LL | extern "rust-intrinsic" fn baz() {}
    |                                  ^^
 
-error: aborting due to 5 previous errors
+error: aborting due to 4 previous errors
 
 Some errors have detailed explanations: E0093, E0658.
 For more information about an error, try `rustc --explain E0093`.
diff --git a/tests/ui/feature-gates/feature-gate-precise-capturing.rs b/tests/ui/feature-gates/feature-gate-precise-capturing.rs
new file mode 100644
index 00000000000..0c3b4977623
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-precise-capturing.rs
@@ -0,0 +1,4 @@
+fn hello() -> impl use<> Sized {}
+//~^ ERROR precise captures on `impl Trait` are experimental
+
+fn main() {}
diff --git a/tests/ui/feature-gates/feature-gate-precise-capturing.stderr b/tests/ui/feature-gates/feature-gate-precise-capturing.stderr
new file mode 100644
index 00000000000..102b39148f9
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-precise-capturing.stderr
@@ -0,0 +1,13 @@
+error[E0658]: precise captures on `impl Trait` are experimental
+  --> $DIR/feature-gate-precise-capturing.rs:1:20
+   |
+LL | fn hello() -> impl use<> Sized {}
+   |                    ^^^
+   |
+   = note: see issue #123432 <https://github.com/rust-lang/rust/issues/123432> for more information
+   = help: add `#![feature(precise_capturing)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/impl-trait/precise-capturing/apit.rs b/tests/ui/impl-trait/precise-capturing/apit.rs
new file mode 100644
index 00000000000..efcac9ebb0b
--- /dev/null
+++ b/tests/ui/impl-trait/precise-capturing/apit.rs
@@ -0,0 +1,7 @@
+#![feature(precise_capturing)]
+//~^ WARN the feature `precise_capturing` is incomplete
+
+fn hello(_: impl use<> Sized) {}
+//~^ ERROR `use<...>` precise capturing syntax not allowed on argument-position `impl Trait`
+
+fn main() {}
diff --git a/tests/ui/impl-trait/precise-capturing/apit.stderr b/tests/ui/impl-trait/precise-capturing/apit.stderr
new file mode 100644
index 00000000000..36bf80d9e2f
--- /dev/null
+++ b/tests/ui/impl-trait/precise-capturing/apit.stderr
@@ -0,0 +1,17 @@
+warning: the feature `precise_capturing` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/apit.rs:1:12
+   |
+LL | #![feature(precise_capturing)]
+   |            ^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #123432 <https://github.com/rust-lang/rust/issues/123432> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+error: `use<...>` precise capturing syntax not allowed on argument-position `impl Trait`
+  --> $DIR/apit.rs:4:18
+   |
+LL | fn hello(_: impl use<> Sized) {}
+   |                  ^^^
+
+error: aborting due to 1 previous error; 1 warning emitted
+
diff --git a/tests/ui/impl-trait/precise-capturing/bad-lifetimes.rs b/tests/ui/impl-trait/precise-capturing/bad-lifetimes.rs
new file mode 100644
index 00000000000..623063a8f50
--- /dev/null
+++ b/tests/ui/impl-trait/precise-capturing/bad-lifetimes.rs
@@ -0,0 +1,14 @@
+#![feature(precise_capturing)]
+//~^ WARN the feature `precise_capturing` is incomplete
+
+fn no_elided_lt() -> impl use<'_> Sized {}
+//~^ ERROR missing lifetime specifier
+//~| ERROR expected lifetime parameter in `use<...>` precise captures list, found `'_`
+
+fn static_lt() -> impl use<'static> Sized {}
+//~^ ERROR expected lifetime parameter in `use<...>` precise captures list, found `'static`
+
+fn missing_lt() -> impl use<'missing> Sized {}
+//~^ ERROR use of undeclared lifetime name `'missing`
+
+fn main() {}
diff --git a/tests/ui/impl-trait/precise-capturing/bad-lifetimes.stderr b/tests/ui/impl-trait/precise-capturing/bad-lifetimes.stderr
new file mode 100644
index 00000000000..a926362c50c
--- /dev/null
+++ b/tests/ui/impl-trait/precise-capturing/bad-lifetimes.stderr
@@ -0,0 +1,45 @@
+error[E0106]: missing lifetime specifier
+  --> $DIR/bad-lifetimes.rs:4:31
+   |
+LL | fn no_elided_lt() -> impl use<'_> Sized {}
+   |                               ^^ expected named lifetime parameter
+   |
+   = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
+help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static`, or if you will only have owned values
+   |
+LL | fn no_elided_lt() -> impl use<'static> Sized {}
+   |                               ~~~~~~~
+
+error[E0261]: use of undeclared lifetime name `'missing`
+  --> $DIR/bad-lifetimes.rs:11:29
+   |
+LL | fn missing_lt() -> impl use<'missing> Sized {}
+   |              -              ^^^^^^^^ undeclared lifetime
+   |              |
+   |              help: consider introducing lifetime `'missing` here: `<'missing>`
+
+warning: the feature `precise_capturing` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/bad-lifetimes.rs:1:12
+   |
+LL | #![feature(precise_capturing)]
+   |            ^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #123432 <https://github.com/rust-lang/rust/issues/123432> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+error: expected lifetime parameter in `use<...>` precise captures list, found `'_`
+  --> $DIR/bad-lifetimes.rs:4:31
+   |
+LL | fn no_elided_lt() -> impl use<'_> Sized {}
+   |                               ^^
+
+error: expected lifetime parameter in `use<...>` precise captures list, found `'static`
+  --> $DIR/bad-lifetimes.rs:8:28
+   |
+LL | fn static_lt() -> impl use<'static> Sized {}
+   |                            ^^^^^^^
+
+error: aborting due to 4 previous errors; 1 warning emitted
+
+Some errors have detailed explanations: E0106, E0261.
+For more information about an error, try `rustc --explain E0106`.
diff --git a/tests/ui/impl-trait/precise-capturing/bad-params.rs b/tests/ui/impl-trait/precise-capturing/bad-params.rs
new file mode 100644
index 00000000000..7970d49bf7c
--- /dev/null
+++ b/tests/ui/impl-trait/precise-capturing/bad-params.rs
@@ -0,0 +1,19 @@
+#![feature(precise_capturing)]
+//~^ WARN the feature `precise_capturing` is incomplete
+
+fn missing() -> impl use<T> Sized {}
+//~^ ERROR cannot find type `T` in this scope
+
+fn missing_self() -> impl use<Self> Sized {}
+//~^ ERROR cannot find type `Self` in this scope
+
+struct MyType;
+impl MyType {
+    fn self_is_not_param() -> impl use<Self> Sized {}
+    //~^ ERROR `Self` can't be captured in `use<...>` precise captures list, since it is an alias
+}
+
+fn hello() -> impl use<hello> Sized {}
+//~^ ERROR expected type or const parameter in `use<...>` precise captures list, found function
+
+fn main() {}
diff --git a/tests/ui/impl-trait/precise-capturing/bad-params.stderr b/tests/ui/impl-trait/precise-capturing/bad-params.stderr
new file mode 100644
index 00000000000..27bf05302f9
--- /dev/null
+++ b/tests/ui/impl-trait/precise-capturing/bad-params.stderr
@@ -0,0 +1,46 @@
+error[E0412]: cannot find type `T` in this scope
+  --> $DIR/bad-params.rs:4:26
+   |
+LL | fn missing() -> impl use<T> Sized {}
+   |                          ^ not found in this scope
+   |
+help: you might be missing a type parameter
+   |
+LL | fn missing<T>() -> impl use<T> Sized {}
+   |           +++
+
+error[E0411]: cannot find type `Self` in this scope
+  --> $DIR/bad-params.rs:7:31
+   |
+LL | fn missing_self() -> impl use<Self> Sized {}
+   |    ------------               ^^^^ `Self` is only available in impls, traits, and type definitions
+   |    |
+   |    `Self` not allowed in a function
+
+warning: the feature `precise_capturing` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/bad-params.rs:1:12
+   |
+LL | #![feature(precise_capturing)]
+   |            ^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #123432 <https://github.com/rust-lang/rust/issues/123432> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+error: `Self` can't be captured in `use<...>` precise captures list, since it is an alias
+  --> $DIR/bad-params.rs:12:40
+   |
+LL | impl MyType {
+   | ----------- `Self` is not a generic argument, but an alias to the type of the implementation
+LL |     fn self_is_not_param() -> impl use<Self> Sized {}
+   |                                        ^^^^
+
+error: expected type or const parameter in `use<...>` precise captures list, found function
+  --> $DIR/bad-params.rs:16:24
+   |
+LL | fn hello() -> impl use<hello> Sized {}
+   |                        ^^^^^
+
+error: aborting due to 4 previous errors; 1 warning emitted
+
+Some errors have detailed explanations: E0411, E0412.
+For more information about an error, try `rustc --explain E0411`.
diff --git a/tests/ui/impl-trait/precise-capturing/elided.rs b/tests/ui/impl-trait/precise-capturing/elided.rs
new file mode 100644
index 00000000000..de80e8a5d58
--- /dev/null
+++ b/tests/ui/impl-trait/precise-capturing/elided.rs
@@ -0,0 +1,8 @@
+//@ check-pass
+
+#![feature(precise_capturing)]
+//~^ WARN the feature `precise_capturing` is incomplete
+
+fn elided(x: &()) -> impl use<'_> Sized { x }
+
+fn main() {}
diff --git a/tests/ui/impl-trait/precise-capturing/elided.stderr b/tests/ui/impl-trait/precise-capturing/elided.stderr
new file mode 100644
index 00000000000..38da0828de9
--- /dev/null
+++ b/tests/ui/impl-trait/precise-capturing/elided.stderr
@@ -0,0 +1,11 @@
+warning: the feature `precise_capturing` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/elided.rs:3:12
+   |
+LL | #![feature(precise_capturing)]
+   |            ^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #123432 <https://github.com/rust-lang/rust/issues/123432> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/impl-trait/precise-capturing/forgot-to-capture-const.rs b/tests/ui/impl-trait/precise-capturing/forgot-to-capture-const.rs
new file mode 100644
index 00000000000..1b604e6c358
--- /dev/null
+++ b/tests/ui/impl-trait/precise-capturing/forgot-to-capture-const.rs
@@ -0,0 +1,7 @@
+#![feature(precise_capturing)]
+//~^ WARN the feature `precise_capturing` is incomplete
+
+fn constant<const C: usize>() -> impl use<> Sized {}
+//~^ ERROR `impl Trait` must mention all const parameters in scope
+
+fn main() {}
diff --git a/tests/ui/impl-trait/precise-capturing/forgot-to-capture-const.stderr b/tests/ui/impl-trait/precise-capturing/forgot-to-capture-const.stderr
new file mode 100644
index 00000000000..9c99f2b711e
--- /dev/null
+++ b/tests/ui/impl-trait/precise-capturing/forgot-to-capture-const.stderr
@@ -0,0 +1,19 @@
+warning: the feature `precise_capturing` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/forgot-to-capture-const.rs:1:12
+   |
+LL | #![feature(precise_capturing)]
+   |            ^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #123432 <https://github.com/rust-lang/rust/issues/123432> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+error: `impl Trait` must mention all const parameters in scope
+  --> $DIR/forgot-to-capture-const.rs:4:13
+   |
+LL | fn constant<const C: usize>() -> impl use<> Sized {}
+   |             ^^^^^^^^^^^^^^       ---------------- const parameter is implicitly captured by this `impl Trait`
+   |
+   = note: currently, all const parameters are required to be mentioned in the precise captures list
+
+error: aborting due to 1 previous error; 1 warning emitted
+
diff --git a/tests/ui/impl-trait/precise-capturing/forgot-to-capture-lifetime.rs b/tests/ui/impl-trait/precise-capturing/forgot-to-capture-lifetime.rs
new file mode 100644
index 00000000000..cc86bf83107
--- /dev/null
+++ b/tests/ui/impl-trait/precise-capturing/forgot-to-capture-lifetime.rs
@@ -0,0 +1,10 @@
+#![feature(precise_capturing)]
+//~^ WARN the feature `precise_capturing` is incomplete
+
+fn lifetime_in_bounds<'a>(x: &'a ()) -> impl use<> Into<&'a ()> { x }
+//~^ ERROR `impl Trait` captures lifetime parameter, but it is not mentioned in `use<...>` precise captures list
+
+fn lifetime_in_hidden<'a>(x: &'a ()) -> impl use<> Sized { x }
+//~^ ERROR hidden type for `impl Sized` captures lifetime that does not appear in bounds
+
+fn main() {}
diff --git a/tests/ui/impl-trait/precise-capturing/forgot-to-capture-lifetime.stderr b/tests/ui/impl-trait/precise-capturing/forgot-to-capture-lifetime.stderr
new file mode 100644
index 00000000000..e472c898050
--- /dev/null
+++ b/tests/ui/impl-trait/precise-capturing/forgot-to-capture-lifetime.stderr
@@ -0,0 +1,35 @@
+warning: the feature `precise_capturing` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/forgot-to-capture-lifetime.rs:1:12
+   |
+LL | #![feature(precise_capturing)]
+   |            ^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #123432 <https://github.com/rust-lang/rust/issues/123432> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+error: `impl Trait` captures lifetime parameter, but it is not mentioned in `use<...>` precise captures list
+  --> $DIR/forgot-to-capture-lifetime.rs:4:58
+   |
+LL | fn lifetime_in_bounds<'a>(x: &'a ()) -> impl use<> Into<&'a ()> { x }
+   |                       --                -----------------^^----
+   |                       |                 |
+   |                       |                 lifetime captured due to being mentioned in the bounds of the `impl Trait`
+   |                       this lifetime parameter is captured
+
+error[E0700]: hidden type for `impl Sized` captures lifetime that does not appear in bounds
+  --> $DIR/forgot-to-capture-lifetime.rs:7:60
+   |
+LL | fn lifetime_in_hidden<'a>(x: &'a ()) -> impl use<> Sized { x }
+   |                       --                ----------------   ^
+   |                       |                 |
+   |                       |                 opaque type defined here
+   |                       hidden type `&'a ()` captures the lifetime `'a` as defined here
+   |
+help: to declare that `impl Sized` captures `'a`, you can add an explicit `'a` lifetime bound
+   |
+LL | fn lifetime_in_hidden<'a>(x: &'a ()) -> impl use<> Sized + 'a { x }
+   |                                                          ++++
+
+error: aborting due to 2 previous errors; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0700`.
diff --git a/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.rs b/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.rs
new file mode 100644
index 00000000000..6eaff01183d
--- /dev/null
+++ b/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.rs
@@ -0,0 +1,12 @@
+#![feature(precise_capturing)]
+//~^ WARN the feature `precise_capturing` is incomplete
+
+fn type_param<T>() -> impl use<> Sized {}
+//~^ ERROR `impl Trait` must mention all type parameters in scope
+
+trait Foo {
+//~^ ERROR `impl Trait` must mention all type parameters in scope
+    fn bar() -> impl use<> Sized;
+}
+
+fn main() {}
diff --git a/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.stderr b/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.stderr
new file mode 100644
index 00000000000..a8eb4547dcd
--- /dev/null
+++ b/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.stderr
@@ -0,0 +1,30 @@
+warning: the feature `precise_capturing` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/forgot-to-capture-type.rs:1:12
+   |
+LL | #![feature(precise_capturing)]
+   |            ^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #123432 <https://github.com/rust-lang/rust/issues/123432> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+error: `impl Trait` must mention all type parameters in scope
+  --> $DIR/forgot-to-capture-type.rs:4:15
+   |
+LL | fn type_param<T>() -> impl use<> Sized {}
+   |               ^       ---------------- type parameter is implicitly captured by this `impl Trait`
+   |
+   = note: currently, all type parameters are required to be mentioned in the precise captures list
+
+error: `impl Trait` must mention all type parameters in scope
+  --> $DIR/forgot-to-capture-type.rs:7:1
+   |
+LL | trait Foo {
+   | ^^^^^^^^^
+LL |
+LL |     fn bar() -> impl use<> Sized;
+   |                 ---------------- type parameter is implicitly captured by this `impl Trait`
+   |
+   = note: currently, all type parameters are required to be mentioned in the precise captures list
+
+error: aborting due to 2 previous errors; 1 warning emitted
+
diff --git a/tests/ui/impl-trait/precise-capturing/higher-ranked.rs b/tests/ui/impl-trait/precise-capturing/higher-ranked.rs
new file mode 100644
index 00000000000..28fb1fa4b9e
--- /dev/null
+++ b/tests/ui/impl-trait/precise-capturing/higher-ranked.rs
@@ -0,0 +1,18 @@
+//@ check-pass
+
+// Show how precise captures allow us to skip capturing a higher-ranked lifetime
+
+#![feature(lifetime_capture_rules_2024, precise_capturing)]
+//~^ WARN the feature `precise_capturing` is incomplete
+
+trait Trait<'a> {
+    type Item;
+}
+
+impl Trait<'_> for () {
+    type Item = Vec<()>;
+}
+
+fn hello() -> impl for<'a> Trait<'a, Item = impl use<> IntoIterator> {}
+
+fn main() {}
diff --git a/tests/ui/impl-trait/precise-capturing/higher-ranked.stderr b/tests/ui/impl-trait/precise-capturing/higher-ranked.stderr
new file mode 100644
index 00000000000..e48d6d42af0
--- /dev/null
+++ b/tests/ui/impl-trait/precise-capturing/higher-ranked.stderr
@@ -0,0 +1,11 @@
+warning: the feature `precise_capturing` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/higher-ranked.rs:5:41
+   |
+LL | #![feature(lifetime_capture_rules_2024, precise_capturing)]
+   |                                         ^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #123432 <https://github.com/rust-lang/rust/issues/123432> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/impl-trait/precise-capturing/ordering.rs b/tests/ui/impl-trait/precise-capturing/ordering.rs
new file mode 100644
index 00000000000..2bace798c57
--- /dev/null
+++ b/tests/ui/impl-trait/precise-capturing/ordering.rs
@@ -0,0 +1,16 @@
+#![feature(precise_capturing)]
+//~^ WARN the feature `precise_capturing` is incomplete
+
+fn lt<'a>() -> impl use<'a, 'a> Sized {}
+//~^ ERROR cannot capture parameter `'a` twice
+
+fn ty<T>() -> impl use<T, T> Sized {}
+//~^ ERROR cannot capture parameter `T` twice
+
+fn ct<const N: usize>() -> impl use<N, N> Sized {}
+//~^ ERROR cannot capture parameter `N` twice
+
+fn ordering<'a, T>() -> impl use<T, 'a> Sized {}
+//~^ ERROR lifetime parameter `'a` must be listed before non-lifetime parameters
+
+fn main() {}
diff --git a/tests/ui/impl-trait/precise-capturing/ordering.stderr b/tests/ui/impl-trait/precise-capturing/ordering.stderr
new file mode 100644
index 00000000000..3f545108df5
--- /dev/null
+++ b/tests/ui/impl-trait/precise-capturing/ordering.stderr
@@ -0,0 +1,37 @@
+warning: the feature `precise_capturing` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/ordering.rs:1:12
+   |
+LL | #![feature(precise_capturing)]
+   |            ^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #123432 <https://github.com/rust-lang/rust/issues/123432> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+error: cannot capture parameter `'a` twice
+  --> $DIR/ordering.rs:4:25
+   |
+LL | fn lt<'a>() -> impl use<'a, 'a> Sized {}
+   |                         ^^  -- parameter captured again here
+
+error: cannot capture parameter `T` twice
+  --> $DIR/ordering.rs:7:24
+   |
+LL | fn ty<T>() -> impl use<T, T> Sized {}
+   |                        ^  - parameter captured again here
+
+error: cannot capture parameter `N` twice
+  --> $DIR/ordering.rs:10:37
+   |
+LL | fn ct<const N: usize>() -> impl use<N, N> Sized {}
+   |                                     ^  - parameter captured again here
+
+error: lifetime parameter `'a` must be listed before non-lifetime parameters
+  --> $DIR/ordering.rs:13:37
+   |
+LL | fn ordering<'a, T>() -> impl use<T, 'a> Sized {}
+   |                                  -  ^^
+   |                                  |
+   |                                  move the lifetime before this parameter
+
+error: aborting due to 4 previous errors; 1 warning emitted
+
diff --git a/tests/ui/impl-trait/precise-capturing/outlives.rs b/tests/ui/impl-trait/precise-capturing/outlives.rs
new file mode 100644
index 00000000000..71e6333934e
--- /dev/null
+++ b/tests/ui/impl-trait/precise-capturing/outlives.rs
@@ -0,0 +1,16 @@
+//@ check-pass
+
+// Show that precise captures allow us to skip a lifetime param for outlives
+
+#![feature(lifetime_capture_rules_2024, precise_capturing)]
+//~^ WARN the feature `precise_capturing` is incomplete
+
+fn hello<'a: 'a, 'b: 'b>() -> impl use<'a> Sized { }
+
+fn outlives<'a, T: 'a>(_: T) {}
+
+fn test<'a, 'b>() {
+    outlives::<'a, _>(hello::<'a, 'b>());
+}
+
+fn main() {}
diff --git a/tests/ui/impl-trait/precise-capturing/outlives.stderr b/tests/ui/impl-trait/precise-capturing/outlives.stderr
new file mode 100644
index 00000000000..405c09cccd9
--- /dev/null
+++ b/tests/ui/impl-trait/precise-capturing/outlives.stderr
@@ -0,0 +1,11 @@
+warning: the feature `precise_capturing` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/outlives.rs:5:41
+   |
+LL | #![feature(lifetime_capture_rules_2024, precise_capturing)]
+   |                                         ^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #123432 <https://github.com/rust-lang/rust/issues/123432> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/impl-trait/precise-capturing/self-capture.rs b/tests/ui/impl-trait/precise-capturing/self-capture.rs
new file mode 100644
index 00000000000..ecbc388e27b
--- /dev/null
+++ b/tests/ui/impl-trait/precise-capturing/self-capture.rs
@@ -0,0 +1,10 @@
+//@ check-pass
+
+#![feature(precise_capturing)]
+//~^ WARN the feature `precise_capturing` is incomplete
+
+trait Foo {
+    fn bar<'a>() -> impl use<Self> Sized;
+}
+
+fn main() {}
diff --git a/tests/ui/impl-trait/precise-capturing/self-capture.stderr b/tests/ui/impl-trait/precise-capturing/self-capture.stderr
new file mode 100644
index 00000000000..5a058c6826d
--- /dev/null
+++ b/tests/ui/impl-trait/precise-capturing/self-capture.stderr
@@ -0,0 +1,11 @@
+warning: the feature `precise_capturing` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/self-capture.rs:3:12
+   |
+LL | #![feature(precise_capturing)]
+   |            ^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #123432 <https://github.com/rust-lang/rust/issues/123432> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/intrinsics/incorrect-read_via_copy-defn.rs b/tests/ui/intrinsics/incorrect-read_via_copy-defn.rs
new file mode 100644
index 00000000000..66de1f60ed9
--- /dev/null
+++ b/tests/ui/intrinsics/incorrect-read_via_copy-defn.rs
@@ -0,0 +1,7 @@
+fn main() {
+    read_via_copy();
+}
+
+extern "rust-intrinsic" fn read_via_copy() {}
+//~^ ERROR intrinsics are subject to change
+//~| ERROR intrinsic must be in `extern "rust-intrinsic" { ... }` block
diff --git a/tests/ui/intrinsics/incorrect-read_via_copy-defn.stderr b/tests/ui/intrinsics/incorrect-read_via_copy-defn.stderr
new file mode 100644
index 00000000000..362ee185b7b
--- /dev/null
+++ b/tests/ui/intrinsics/incorrect-read_via_copy-defn.stderr
@@ -0,0 +1,18 @@
+error[E0658]: intrinsics are subject to change
+  --> $DIR/incorrect-read_via_copy-defn.rs:5:8
+   |
+LL | extern "rust-intrinsic" fn read_via_copy() {}
+   |        ^^^^^^^^^^^^^^^^
+   |
+   = help: add `#![feature(intrinsics)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error: intrinsic must be in `extern "rust-intrinsic" { ... }` block
+  --> $DIR/incorrect-read_via_copy-defn.rs:5:44
+   |
+LL | extern "rust-intrinsic" fn read_via_copy() {}
+   |                                            ^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/intrinsics/incorrect-transmute.rs b/tests/ui/intrinsics/incorrect-transmute.rs
index 4f1d1491ec9..eed524ae8a8 100644
--- a/tests/ui/intrinsics/incorrect-transmute.rs
+++ b/tests/ui/intrinsics/incorrect-transmute.rs
@@ -3,6 +3,5 @@ fn main() {
 }
 
 extern "rust-intrinsic" fn transmute() {}
-//~^ ERROR intrinsic has wrong number of type parameters: found 0, expected 2
-//~| ERROR intrinsics are subject to change
+//~^ ERROR intrinsics are subject to change
 //~| ERROR intrinsic must be in `extern "rust-intrinsic" { ... }` block
diff --git a/tests/ui/intrinsics/incorrect-transmute.stderr b/tests/ui/intrinsics/incorrect-transmute.stderr
index 20b95925b76..8123f3d71a2 100644
--- a/tests/ui/intrinsics/incorrect-transmute.stderr
+++ b/tests/ui/intrinsics/incorrect-transmute.stderr
@@ -7,19 +7,12 @@ LL | extern "rust-intrinsic" fn transmute() {}
    = help: add `#![feature(intrinsics)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0094]: intrinsic has wrong number of type parameters: found 0, expected 2
-  --> $DIR/incorrect-transmute.rs:5:37
-   |
-LL | extern "rust-intrinsic" fn transmute() {}
-   |                                     ^ expected 2 type parameters
-
 error: intrinsic must be in `extern "rust-intrinsic" { ... }` block
   --> $DIR/incorrect-transmute.rs:5:40
    |
 LL | extern "rust-intrinsic" fn transmute() {}
    |                                        ^^
 
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
-Some errors have detailed explanations: E0094, E0658.
-For more information about an error, try `rustc --explain E0094`.
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/loops/loop-break-value.stderr b/tests/ui/loops/loop-break-value.stderr
index 0093182422e..0912bdbb221 100644
--- a/tests/ui/loops/loop-break-value.stderr
+++ b/tests/ui/loops/loop-break-value.stderr
@@ -246,8 +246,8 @@ LL |         break;
    |
 help: give the `break` a value of the expected type
    |
-LL |         break value;
-   |               +++++
+LL |         break /* value */;
+   |               +++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/loop-break-value.rs:112:9
@@ -260,8 +260,8 @@ LL |         break;
    |
 help: give the `break` a value of the expected type
    |
-LL |         break value;
-   |               +++++
+LL |         break /* value */;
+   |               +++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/loop-break-value.rs:124:9
@@ -274,8 +274,8 @@ LL |         break 'a;
    |
 help: give the `break` a value of the expected type
    |
-LL |         break 'a value;
-   |                  +++++
+LL |         break 'a /* value */;
+   |                  +++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/loop-break-value.rs:135:15
@@ -297,8 +297,8 @@ LL |                 break 'a;
    |
 help: give the `break` a value of the expected type
    |
-LL |                 break 'a value;
-   |                          +++++
+LL |                 break 'a /* value */;
+   |                          +++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/loop-break-value.rs:147:15
@@ -320,8 +320,8 @@ LL |                 break 'a;
    |
 help: give the `break` a value of the expected type
    |
-LL |                 break 'a value;
-   |                          +++++
+LL |                 break 'a /* value */;
+   |                          +++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/loop-break-value.rs:159:15
diff --git a/tests/ui/match/ref_pat_eat_one_layer_2024/feature-gate-ref_pat_eat_one_layer_2024.rs b/tests/ui/match/ref_pat_eat_one_layer_2024/feature-gate-ref_pat_eat_one_layer_2024.rs
new file mode 100644
index 00000000000..83f1ee6a77e
--- /dev/null
+++ b/tests/ui/match/ref_pat_eat_one_layer_2024/feature-gate-ref_pat_eat_one_layer_2024.rs
@@ -0,0 +1,37 @@
+//@ edition: 2024
+//@ compile-flags: -Zunstable-options
+
+pub fn main() {
+    if let Some(Some(&x)) = &Some(&Some(0)) {
+        //~^ ERROR: mismatched types
+        let _: u32 = x;
+    }
+    if let Some(Some(&x)) = &Some(Some(&0)) {
+        let _: &u32 = x;
+        //~^ ERROR: mismatched types
+    }
+    if let Some(Some(&&x)) = &Some(Some(&0)) {
+        //~^ ERROR: mismatched types
+        let _: u32 = x;
+    }
+    if let Some(&Some(x)) = &Some(Some(0)) {
+        //~^ ERROR: mismatched types
+        let _: u32 = x;
+    }
+    if let Some(Some(&mut x)) = &mut Some(&mut Some(0)) {
+        //~^ ERROR: mismatched types
+        let _: u32 = x;
+    }
+    if let Some(Some(&x)) = &Some(&Some(0)) {
+        //~^ ERROR: mismatched types
+        let _: u32 = x;
+    }
+    if let Some(&mut Some(&x)) = &Some(&mut Some(0)) {
+        //~^ ERROR: mismatched types
+        let _: u32 = x;
+    }
+    if let Some(&Some(&mut x)) = &mut Some(&Some(0)) {
+        //~^ ERROR: mismatched types
+        let _: u32 = x;
+    }
+}
diff --git a/tests/ui/match/ref_pat_eat_one_layer_2024/feature-gate-ref_pat_eat_one_layer_2024.stderr b/tests/ui/match/ref_pat_eat_one_layer_2024/feature-gate-ref_pat_eat_one_layer_2024.stderr
new file mode 100644
index 00000000000..132fe421a18
--- /dev/null
+++ b/tests/ui/match/ref_pat_eat_one_layer_2024/feature-gate-ref_pat_eat_one_layer_2024.stderr
@@ -0,0 +1,128 @@
+error[E0308]: mismatched types
+  --> $DIR/feature-gate-ref_pat_eat_one_layer_2024.rs:5:22
+   |
+LL |     if let Some(Some(&x)) = &Some(&Some(0)) {
+   |                      ^^     --------------- this expression has type `&Option<&Option<{integer}>>`
+   |                      |
+   |                      expected integer, found `&_`
+   |
+   = note:   expected type `{integer}`
+           found reference `&_`
+help: consider removing `&` from the pattern
+   |
+LL |     if let Some(Some(x)) = &Some(&Some(0)) {
+   |                      ~
+
+error[E0308]: mismatched types
+  --> $DIR/feature-gate-ref_pat_eat_one_layer_2024.rs:10:23
+   |
+LL |         let _: &u32 = x;
+   |                ----   ^ expected `&u32`, found integer
+   |                |
+   |                expected due to this
+   |
+help: consider borrowing here
+   |
+LL |         let _: &u32 = &x;
+   |                       +
+
+error[E0308]: mismatched types
+  --> $DIR/feature-gate-ref_pat_eat_one_layer_2024.rs:13:23
+   |
+LL |     if let Some(Some(&&x)) = &Some(Some(&0)) {
+   |                       ^^     --------------- this expression has type `&Option<Option<&{integer}>>`
+   |                       |
+   |                       expected integer, found `&_`
+   |
+   = note:   expected type `{integer}`
+           found reference `&_`
+help: consider removing `&` from the pattern
+   |
+LL -     if let Some(Some(&&x)) = &Some(Some(&0)) {
+LL +     if let Some(Some(&x)) = &Some(Some(&0)) {
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/feature-gate-ref_pat_eat_one_layer_2024.rs:17:17
+   |
+LL |     if let Some(&Some(x)) = &Some(Some(0)) {
+   |                 ^^^^^^^^    -------------- this expression has type `&Option<Option<{integer}>>`
+   |                 |
+   |                 expected `Option<{integer}>`, found `&_`
+   |
+   = note:   expected enum `Option<{integer}>`
+           found reference `&_`
+
+error[E0308]: mismatched types
+  --> $DIR/feature-gate-ref_pat_eat_one_layer_2024.rs:21:22
+   |
+LL |     if let Some(Some(&mut x)) = &mut Some(&mut Some(0)) {
+   |                      ^^^^^^     ----------------------- this expression has type `&mut Option<&mut Option<{integer}>>`
+   |                      |
+   |                      expected integer, found `&mut _`
+   |
+   = note:           expected type `{integer}`
+           found mutable reference `&mut _`
+note: to declare a mutable binding use: `mut x`
+  --> $DIR/feature-gate-ref_pat_eat_one_layer_2024.rs:21:22
+   |
+LL |     if let Some(Some(&mut x)) = &mut Some(&mut Some(0)) {
+   |                      ^^^^^^
+help: consider removing `&mut` from the pattern
+   |
+LL |     if let Some(Some(x)) = &mut Some(&mut Some(0)) {
+   |                      ~
+
+error[E0308]: mismatched types
+  --> $DIR/feature-gate-ref_pat_eat_one_layer_2024.rs:25:22
+   |
+LL |     if let Some(Some(&x)) = &Some(&Some(0)) {
+   |                      ^^     --------------- this expression has type `&Option<&Option<{integer}>>`
+   |                      |
+   |                      expected integer, found `&_`
+   |
+   = note:   expected type `{integer}`
+           found reference `&_`
+help: consider removing `&` from the pattern
+   |
+LL |     if let Some(Some(x)) = &Some(&Some(0)) {
+   |                      ~
+
+error[E0308]: mismatched types
+  --> $DIR/feature-gate-ref_pat_eat_one_layer_2024.rs:29:27
+   |
+LL |     if let Some(&mut Some(&x)) = &Some(&mut Some(0)) {
+   |                           ^^     ------------------- this expression has type `&Option<&mut Option<{integer}>>`
+   |                           |
+   |                           expected integer, found `&_`
+   |
+   = note:   expected type `{integer}`
+           found reference `&_`
+help: consider removing `&` from the pattern
+   |
+LL |     if let Some(&mut Some(x)) = &Some(&mut Some(0)) {
+   |                           ~
+
+error[E0308]: mismatched types
+  --> $DIR/feature-gate-ref_pat_eat_one_layer_2024.rs:33:23
+   |
+LL |     if let Some(&Some(&mut x)) = &mut Some(&Some(0)) {
+   |                       ^^^^^^     ------------------- this expression has type `&mut Option<&Option<{integer}>>`
+   |                       |
+   |                       expected integer, found `&mut _`
+   |
+   = note:           expected type `{integer}`
+           found mutable reference `&mut _`
+note: to declare a mutable binding use: `mut x`
+  --> $DIR/feature-gate-ref_pat_eat_one_layer_2024.rs:33:23
+   |
+LL |     if let Some(&Some(&mut x)) = &mut Some(&Some(0)) {
+   |                       ^^^^^^
+help: consider removing `&mut` from the pattern
+   |
+LL |     if let Some(&Some(x)) = &mut Some(&Some(0)) {
+   |                       ~
+
+error: aborting due to 8 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2021.rs b/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2021.rs
new file mode 100644
index 00000000000..d28567f2859
--- /dev/null
+++ b/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2021.rs
@@ -0,0 +1,37 @@
+//@ edition: 2021
+#![allow(incomplete_features)]
+#![feature(ref_pat_eat_one_layer_2024)]
+pub fn main() {
+    if let Some(Some(&x)) = &Some(&Some(0)) {
+        //~^ ERROR: mismatched types
+        let _: u32 = x;
+    }
+    if let Some(Some(&x)) = &Some(Some(&0)) {
+        let _: &u32 = x;
+        //~^ ERROR: mismatched types
+    }
+    if let Some(Some(&&x)) = &Some(Some(&0)) {
+        //~^ ERROR: mismatched types
+        let _: u32 = x;
+    }
+    if let Some(&Some(x)) = &Some(Some(0)) {
+        //~^ ERROR: mismatched types
+        let _: u32 = x;
+    }
+    if let Some(Some(&mut x)) = &mut Some(&mut Some(0)) {
+        //~^ ERROR: mismatched types
+        let _: u32 = x;
+    }
+    if let Some(Some(&x)) = &Some(&Some(0)) {
+        //~^ ERROR: mismatched types
+        let _: u32 = x;
+    }
+    if let Some(&mut Some(&x)) = &Some(&mut Some(0)) {
+        //~^ ERROR: mismatched types
+        let _: u32 = x;
+    }
+    if let Some(&Some(&mut x)) = &mut Some(&Some(0)) {
+        //~^ ERROR: mismatched types
+        let _: u32 = x;
+    }
+}
diff --git a/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2021.stderr b/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2021.stderr
new file mode 100644
index 00000000000..28706f89c06
--- /dev/null
+++ b/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2021.stderr
@@ -0,0 +1,128 @@
+error[E0308]: mismatched types
+  --> $DIR/ref_pat_eat_one_layer_2021.rs:5:22
+   |
+LL |     if let Some(Some(&x)) = &Some(&Some(0)) {
+   |                      ^^     --------------- this expression has type `&Option<&Option<{integer}>>`
+   |                      |
+   |                      expected integer, found `&_`
+   |
+   = note:   expected type `{integer}`
+           found reference `&_`
+help: consider removing `&` from the pattern
+   |
+LL |     if let Some(Some(x)) = &Some(&Some(0)) {
+   |                      ~
+
+error[E0308]: mismatched types
+  --> $DIR/ref_pat_eat_one_layer_2021.rs:10:23
+   |
+LL |         let _: &u32 = x;
+   |                ----   ^ expected `&u32`, found integer
+   |                |
+   |                expected due to this
+   |
+help: consider borrowing here
+   |
+LL |         let _: &u32 = &x;
+   |                       +
+
+error[E0308]: mismatched types
+  --> $DIR/ref_pat_eat_one_layer_2021.rs:13:23
+   |
+LL |     if let Some(Some(&&x)) = &Some(Some(&0)) {
+   |                       ^^     --------------- this expression has type `&Option<Option<&{integer}>>`
+   |                       |
+   |                       expected integer, found `&_`
+   |
+   = note:   expected type `{integer}`
+           found reference `&_`
+help: consider removing `&` from the pattern
+   |
+LL -     if let Some(Some(&&x)) = &Some(Some(&0)) {
+LL +     if let Some(Some(&x)) = &Some(Some(&0)) {
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/ref_pat_eat_one_layer_2021.rs:17:17
+   |
+LL |     if let Some(&Some(x)) = &Some(Some(0)) {
+   |                 ^^^^^^^^    -------------- this expression has type `&Option<Option<{integer}>>`
+   |                 |
+   |                 expected `Option<{integer}>`, found `&_`
+   |
+   = note:   expected enum `Option<{integer}>`
+           found reference `&_`
+
+error[E0308]: mismatched types
+  --> $DIR/ref_pat_eat_one_layer_2021.rs:21:22
+   |
+LL |     if let Some(Some(&mut x)) = &mut Some(&mut Some(0)) {
+   |                      ^^^^^^     ----------------------- this expression has type `&mut Option<&mut Option<{integer}>>`
+   |                      |
+   |                      expected integer, found `&mut _`
+   |
+   = note:           expected type `{integer}`
+           found mutable reference `&mut _`
+note: to declare a mutable binding use: `mut x`
+  --> $DIR/ref_pat_eat_one_layer_2021.rs:21:22
+   |
+LL |     if let Some(Some(&mut x)) = &mut Some(&mut Some(0)) {
+   |                      ^^^^^^
+help: consider removing `&mut` from the pattern
+   |
+LL |     if let Some(Some(x)) = &mut Some(&mut Some(0)) {
+   |                      ~
+
+error[E0308]: mismatched types
+  --> $DIR/ref_pat_eat_one_layer_2021.rs:25:22
+   |
+LL |     if let Some(Some(&x)) = &Some(&Some(0)) {
+   |                      ^^     --------------- this expression has type `&Option<&Option<{integer}>>`
+   |                      |
+   |                      expected integer, found `&_`
+   |
+   = note:   expected type `{integer}`
+           found reference `&_`
+help: consider removing `&` from the pattern
+   |
+LL |     if let Some(Some(x)) = &Some(&Some(0)) {
+   |                      ~
+
+error[E0308]: mismatched types
+  --> $DIR/ref_pat_eat_one_layer_2021.rs:29:27
+   |
+LL |     if let Some(&mut Some(&x)) = &Some(&mut Some(0)) {
+   |                           ^^     ------------------- this expression has type `&Option<&mut Option<{integer}>>`
+   |                           |
+   |                           expected integer, found `&_`
+   |
+   = note:   expected type `{integer}`
+           found reference `&_`
+help: consider removing `&` from the pattern
+   |
+LL |     if let Some(&mut Some(x)) = &Some(&mut Some(0)) {
+   |                           ~
+
+error[E0308]: mismatched types
+  --> $DIR/ref_pat_eat_one_layer_2021.rs:33:23
+   |
+LL |     if let Some(&Some(&mut x)) = &mut Some(&Some(0)) {
+   |                       ^^^^^^     ------------------- this expression has type `&mut Option<&Option<{integer}>>`
+   |                       |
+   |                       expected integer, found `&mut _`
+   |
+   = note:           expected type `{integer}`
+           found mutable reference `&mut _`
+note: to declare a mutable binding use: `mut x`
+  --> $DIR/ref_pat_eat_one_layer_2021.rs:33:23
+   |
+LL |     if let Some(&Some(&mut x)) = &mut Some(&Some(0)) {
+   |                       ^^^^^^
+help: consider removing `&mut` from the pattern
+   |
+LL |     if let Some(&Some(x)) = &mut Some(&Some(0)) {
+   |                       ~
+
+error: aborting due to 8 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024.rs b/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024.rs
new file mode 100644
index 00000000000..f1ac3e340e9
--- /dev/null
+++ b/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024.rs
@@ -0,0 +1,65 @@
+//@ run-pass
+//@ edition: 2024
+//@ compile-flags: -Zunstable-options
+#![allow(incomplete_features)]
+#![feature(ref_pat_eat_one_layer_2024)]
+
+pub fn main() {
+    if let Some(Some(&x)) = &Some(&Some(0)) {
+        let _: u32 = x;
+    }
+    if let Some(Some(&x)) = &Some(Some(&0)) {
+        let _: &u32 = x;
+    }
+    if let Some(Some(&&x)) = &Some(Some(&0)) {
+        let _: u32 = x;
+    }
+    if let Some(&Some(x)) = &Some(Some(0)) {
+        let _: u32 = x;
+    }
+    if let Some(Some(&mut x)) = &mut Some(&mut Some(0)) {
+        let _: u32 = x;
+    }
+    if let Some(Some(&x)) = &Some(&Some(0)) {
+        let _: u32 = x;
+    }
+    if let Some(&mut Some(&x)) = &Some(&mut Some(0)) {
+        let _: u32 = x;
+    }
+    if let Some(&Some(&x)) = &mut Some(&Some(0)) {
+        let _: u32 = x;
+    }
+    if let Some(&Some(x)) = &mut Some(&Some(0)) {
+        let _: &u32 = x;
+    }
+    if let Some(&Some(&mut ref x)) = Some(&Some(&mut 0)) {
+        let _: &u32 = x;
+    }
+    if let Some(Some(&mut x)) = &Some(Some(&mut 0)) {
+        let _: &u32 = x;
+    }
+    if let &Some(Some(x)) = &Some(&mut Some(0)) {
+        let _: &u32 = x;
+    }
+    if let Some(&Some(&x)) = &Some(&mut Some(0)) {
+        let _: u32 = x;
+    }
+    if let Some(&Some(&x)) = &Some(&Some(0)) {
+        let _: u32 = x;
+    }
+    if let Some(&Some(&x)) = &Some(&mut Some(0)) {
+        let _: u32 = x;
+    }
+    if let Some(&Some(Some(&x))) = &Some(Some(&mut Some(0))) {
+        let _: u32 = x;
+    }
+
+    let &mut x = &&mut 0;
+    let _: &u32 = x;
+
+    let &mut x = &&&&&&&&&&&&&&&&&&&&&&&&&&&&mut 0;
+    let _: &u32 = x;
+
+    let &mut &mut &mut &mut x = &mut &&&&mut &&&mut &mut 0;
+    let _: &u32 = x;
+}
diff --git a/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.rs b/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.rs
new file mode 100644
index 00000000000..ec091bb1746
--- /dev/null
+++ b/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.rs
@@ -0,0 +1,33 @@
+//@ edition: 2024
+//@ compile-flags: -Zunstable-options
+#![allow(incomplete_features)]
+#![feature(ref_pat_eat_one_layer_2024)]
+
+pub fn main() {
+    if let Some(&mut Some(&_)) = &Some(&Some(0)) {
+        //~^ ERROR: mismatched types
+    }
+    if let Some(&Some(&mut _)) = &Some(&mut Some(0)) {
+        //~^ ERROR: mismatched types
+    }
+    if let Some(&Some(x)) = &mut Some(&Some(0)) {
+        let _: &mut u32 = x;
+        //~^ ERROR: mismatched types
+    }
+    if let Some(&Some(&_)) = Some(&Some(&mut 0)) {
+        //~^ ERROR: mismatched types
+    }
+    if let Some(&Some(&mut _)) = &mut Some(&Some(0)) {
+        //~^ ERROR: mismatched types
+    }
+    if let Some(&Some(Some((&mut _)))) = &Some(Some(&mut Some(0))) {
+        //~^ ERROR: mismatched types
+    }
+
+
+    let &mut _= &&0;
+    //~^ ERROR: mismatched types
+
+    let &mut _ = &&&&&&&&&&&&&&&&&&&&&&&&&&&&0;
+    //~^ ERROR: mismatched types
+}
diff --git a/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.stderr b/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.stderr
new file mode 100644
index 00000000000..be71ee606c7
--- /dev/null
+++ b/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.stderr
@@ -0,0 +1,91 @@
+error[E0308]: mismatched types
+  --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:7:17
+   |
+LL |     if let Some(&mut Some(&_)) = &Some(&Some(0)) {
+   |                 ^^^^^^^^^^^^^    --------------- this expression has type `&Option<&Option<{integer}>>`
+   |                 |
+   |                 expected `Option<{integer}>`, found `&mut _`
+   |
+   = note:           expected enum `Option<{integer}>`
+           found mutable reference `&mut _`
+
+error[E0308]: mismatched types
+  --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:10:23
+   |
+LL |     if let Some(&Some(&mut _)) = &Some(&mut Some(0)) {
+   |                       ^^^^^^     ------------------- this expression has type `&Option<&mut Option<{integer}>>`
+   |                       |
+   |                       expected integer, found `&mut _`
+   |
+   = note:           expected type `{integer}`
+           found mutable reference `&mut _`
+
+error[E0308]: mismatched types
+  --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:14:27
+   |
+LL |         let _: &mut u32 = x;
+   |                --------   ^ types differ in mutability
+   |                |
+   |                expected due to this
+   |
+   = note: expected mutable reference `&mut u32`
+                      found reference `&{integer}`
+
+error[E0308]: mismatched types
+  --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:17:23
+   |
+LL |     if let Some(&Some(&_)) = Some(&Some(&mut 0)) {
+   |                       ^^     ------------------- this expression has type `Option<&Option<&mut {integer}>>`
+   |                       |
+   |                       types differ in mutability
+   |
+   = note: expected mutable reference `&mut {integer}`
+                      found reference `&_`
+
+error[E0308]: mismatched types
+  --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:20:23
+   |
+LL |     if let Some(&Some(&mut _)) = &mut Some(&Some(0)) {
+   |                       ^^^^^^     ------------------- this expression has type `&mut Option<&Option<{integer}>>`
+   |                       |
+   |                       expected integer, found `&mut _`
+   |
+   = note:           expected type `{integer}`
+           found mutable reference `&mut _`
+
+error[E0308]: mismatched types
+  --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:23:29
+   |
+LL |     if let Some(&Some(Some((&mut _)))) = &Some(Some(&mut Some(0))) {
+   |                             ^^^^^^       ------------------------- this expression has type `&Option<Option<&mut Option<{integer}>>>`
+   |                             |
+   |                             expected integer, found `&mut _`
+   |
+   = note:           expected type `{integer}`
+           found mutable reference `&mut _`
+
+error[E0308]: mismatched types
+  --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:28:9
+   |
+LL |     let &mut _= &&0;
+   |         ^^^^^^  --- this expression has type `&&{integer}`
+   |         |
+   |         expected integer, found `&mut _`
+   |
+   = note:           expected type `{integer}`
+           found mutable reference `&mut _`
+
+error[E0308]: mismatched types
+  --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:31:9
+   |
+LL |     let &mut _ = &&&&&&&&&&&&&&&&&&&&&&&&&&&&0;
+   |         ^^^^^^   ----------------------------- this expression has type `&&&&&&&&&&&&&&&&&&&&&&&&&&&&{integer}`
+   |         |
+   |         expected integer, found `&mut _`
+   |
+   = note:           expected type `{integer}`
+           found mutable reference `&mut _`
+
+error: aborting due to 8 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail2.rs b/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail2.rs
new file mode 100644
index 00000000000..36455488407
--- /dev/null
+++ b/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail2.rs
@@ -0,0 +1,11 @@
+//@ edition: 2024
+//@ compile-flags: -Zunstable-options
+#![allow(incomplete_features)]
+#![feature(ref_pat_eat_one_layer_2024)]
+
+pub fn main() {
+    if let Some(&Some(x)) = Some(&Some(&mut 0)) {
+        //~^ ERROR: cannot move out of a shared reference [E0507]
+        let _: &u32 = x;
+    }
+}
diff --git a/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail2.stderr b/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail2.stderr
new file mode 100644
index 00000000000..ccfb5c7a0c0
--- /dev/null
+++ b/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail2.stderr
@@ -0,0 +1,17 @@
+error[E0507]: cannot move out of a shared reference
+  --> $DIR/ref_pat_eat_one_layer_2024_fail2.rs:7:29
+   |
+LL |     if let Some(&Some(x)) = Some(&Some(&mut 0)) {
+   |                       -     ^^^^^^^^^^^^^^^^^^^
+   |                       |
+   |                       data moved here
+   |                       move occurs because `x` has type `&mut u32`, which does not implement the `Copy` trait
+   |
+help: consider borrowing the pattern binding
+   |
+LL |     if let Some(&Some(ref x)) = Some(&Some(&mut 0)) {
+   |                       +++
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/tests/ui/moves/issue-72649-uninit-in-loop.stderr b/tests/ui/moves/issue-72649-uninit-in-loop.stderr
index 35216f8a66f..a613f35a35e 100644
--- a/tests/ui/moves/issue-72649-uninit-in-loop.stderr
+++ b/tests/ui/moves/issue-72649-uninit-in-loop.stderr
@@ -80,8 +80,8 @@ LL |         let _used = value;
    |
 help: consider assigning a value
    |
-LL |         let value: NonCopy = value;
-   |                            +++++++
+LL |         let value: NonCopy = /* value */;
+   |                            +++++++++++++
 
 error[E0381]: used binding `value` isn't initialized
   --> $DIR/issue-72649-uninit-in-loop.rs:73:21
@@ -94,8 +94,8 @@ LL |         let _used = value;
    |
 help: consider assigning a value
    |
-LL |     let mut value: NonCopy = value;
-   |                            +++++++
+LL |     let mut value: NonCopy = /* value */;
+   |                            +++++++++++++
 
 error: aborting due to 6 previous errors
 
diff --git a/tests/ui/moves/move-into-dead-array-1.stderr b/tests/ui/moves/move-into-dead-array-1.stderr
index d9b719730d6..14208f5e7aa 100644
--- a/tests/ui/moves/move-into-dead-array-1.stderr
+++ b/tests/ui/moves/move-into-dead-array-1.stderr
@@ -8,8 +8,8 @@ LL |     a[i] = d();
    |
 help: consider assigning a value
    |
-LL |     let mut a: [D; 4] = [value; 4];
-   |                       ++++++++++++
+LL |     let mut a: [D; 4] = /* value */;
+   |                       +++++++++++++
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/moves/move-of-addr-of-mut.stderr b/tests/ui/moves/move-of-addr-of-mut.stderr
index 46f7d39a61a..c36ace6ca0f 100644
--- a/tests/ui/moves/move-of-addr-of-mut.stderr
+++ b/tests/ui/moves/move-of-addr-of-mut.stderr
@@ -9,8 +9,8 @@ LL |     std::ptr::addr_of_mut!(x);
    = note: this error originates in the macro `std::ptr::addr_of_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
 help: consider assigning a value
    |
-LL |     let mut x: S = value;
-   |                  +++++++
+LL |     let mut x: S = /* value */;
+   |                  +++++++++++++
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/nll/match-on-borrowed.stderr b/tests/ui/nll/match-on-borrowed.stderr
index 4e0b048fb4b..81163ebe2bc 100644
--- a/tests/ui/nll/match-on-borrowed.stderr
+++ b/tests/ui/nll/match-on-borrowed.stderr
@@ -43,8 +43,8 @@ LL |     match n {}
    |
 help: consider assigning a value
    |
-LL |     let n: Never = value;
-   |                  +++++++
+LL |     let n: Never = /* value */;
+   |                  +++++++++++++
 
 error: aborting due to 4 previous errors
 
diff --git a/tests/ui/pattern/feature-gate-mut_preserve_binding_mode_2024.rs b/tests/ui/pattern/feature-gate-mut_preserve_binding_mode_2024.rs
new file mode 100644
index 00000000000..15c542e6bf1
--- /dev/null
+++ b/tests/ui/pattern/feature-gate-mut_preserve_binding_mode_2024.rs
@@ -0,0 +1,14 @@
+//@ edition: 2024
+//@ compile-flags: -Zunstable-options
+
+struct Foo(u8);
+
+fn main() {
+    let Foo(mut a) = &Foo(0);
+    a = &42;
+    //~^ ERROR: mismatched types
+
+    let Foo(mut a) = &mut Foo(0);
+    a = &mut 42;
+    //~^ ERROR: mismatched types
+}
diff --git a/tests/ui/pattern/feature-gate-mut_preserve_binding_mode_2024.stderr b/tests/ui/pattern/feature-gate-mut_preserve_binding_mode_2024.stderr
new file mode 100644
index 00000000000..6d0a034be21
--- /dev/null
+++ b/tests/ui/pattern/feature-gate-mut_preserve_binding_mode_2024.stderr
@@ -0,0 +1,31 @@
+error[E0308]: mismatched types
+  --> $DIR/feature-gate-mut_preserve_binding_mode_2024.rs:8:9
+   |
+LL |     let Foo(mut a) = &Foo(0);
+   |             ----- expected due to the type of this binding
+LL |     a = &42;
+   |         ^^^ expected `u8`, found `&{integer}`
+   |
+help: consider removing the borrow
+   |
+LL -     a = &42;
+LL +     a = 42;
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/feature-gate-mut_preserve_binding_mode_2024.rs:12:9
+   |
+LL |     let Foo(mut a) = &mut Foo(0);
+   |             ----- expected due to the type of this binding
+LL |     a = &mut 42;
+   |         ^^^^^^^ expected `u8`, found `&mut {integer}`
+   |
+help: consider removing the borrow
+   |
+LL -     a = &mut 42;
+LL +     a = 42;
+   |
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/pattern/mut_preserve_binding_mode_2021.rs b/tests/ui/pattern/mut_preserve_binding_mode_2021.rs
new file mode 100644
index 00000000000..befa49fdc24
--- /dev/null
+++ b/tests/ui/pattern/mut_preserve_binding_mode_2021.rs
@@ -0,0 +1,16 @@
+//@ edition: 2021
+//@ compile-flags: -Zunstable-options
+#![feature(mut_preserve_binding_mode_2024)]
+#![allow(incomplete_features)]
+
+struct Foo(u8);
+
+fn main() {
+    let Foo(mut a) = &Foo(0);
+    a = &42;
+    //~^ ERROR: mismatched types
+
+    let Foo(mut a) = &mut Foo(0);
+    a = &mut 42;
+    //~^ ERROR: mismatched types
+}
diff --git a/tests/ui/pattern/mut_preserve_binding_mode_2021.stderr b/tests/ui/pattern/mut_preserve_binding_mode_2021.stderr
new file mode 100644
index 00000000000..b800cc4a0f4
--- /dev/null
+++ b/tests/ui/pattern/mut_preserve_binding_mode_2021.stderr
@@ -0,0 +1,31 @@
+error[E0308]: mismatched types
+  --> $DIR/mut_preserve_binding_mode_2021.rs:10:9
+   |
+LL |     let Foo(mut a) = &Foo(0);
+   |             ----- expected due to the type of this binding
+LL |     a = &42;
+   |         ^^^ expected `u8`, found `&{integer}`
+   |
+help: consider removing the borrow
+   |
+LL -     a = &42;
+LL +     a = 42;
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/mut_preserve_binding_mode_2021.rs:14:9
+   |
+LL |     let Foo(mut a) = &mut Foo(0);
+   |             ----- expected due to the type of this binding
+LL |     a = &mut 42;
+   |         ^^^^^^^ expected `u8`, found `&mut {integer}`
+   |
+help: consider removing the borrow
+   |
+LL -     a = &mut 42;
+LL +     a = 42;
+   |
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/pattern/mut_preserve_binding_mode_2024.rs b/tests/ui/pattern/mut_preserve_binding_mode_2024.rs
new file mode 100644
index 00000000000..5454962e16c
--- /dev/null
+++ b/tests/ui/pattern/mut_preserve_binding_mode_2024.rs
@@ -0,0 +1,15 @@
+//@ run-pass
+//@ edition: 2024
+//@ compile-flags: -Zunstable-options
+#![feature(mut_preserve_binding_mode_2024)]
+#![allow(incomplete_features, unused)]
+
+struct Foo(u8);
+
+fn main() {
+    let Foo(mut a) = &Foo(0);
+    a = &42;
+
+    let Foo(mut a) = &mut Foo(0);
+    a = &mut 42;
+}
diff --git a/tests/ui/pattern/mut_preserve_binding_mode_2024_lint.rs b/tests/ui/pattern/mut_preserve_binding_mode_2024_lint.rs
new file mode 100644
index 00000000000..249f251d2cd
--- /dev/null
+++ b/tests/ui/pattern/mut_preserve_binding_mode_2024_lint.rs
@@ -0,0 +1,16 @@
+//@ edition: 2021
+#![feature(mut_preserve_binding_mode_2024)]
+#![allow(incomplete_features, unused)]
+#![forbid(dereferencing_mut_binding)]
+
+struct Foo(u8);
+
+fn main() {
+    let Foo(mut a) = &Foo(0);
+    //~^ ERROR: dereferencing `mut` binding
+    a = 42;
+
+    let Foo(mut a) = &mut Foo(0);
+    //~^ ERROR: dereferencing `mut` binding
+    a = 42;
+}
diff --git a/tests/ui/pattern/mut_preserve_binding_mode_2024_lint.stderr b/tests/ui/pattern/mut_preserve_binding_mode_2024_lint.stderr
new file mode 100644
index 00000000000..e8d11acd83e
--- /dev/null
+++ b/tests/ui/pattern/mut_preserve_binding_mode_2024_lint.stderr
@@ -0,0 +1,31 @@
+error: dereferencing `mut` binding
+  --> $DIR/mut_preserve_binding_mode_2024_lint.rs:9:13
+   |
+LL |     let Foo(mut a) = &Foo(0);
+   |             ^^^^^ `mut` dereferences the type of this binding
+   |
+help: this will change in edition 2024
+  --> $DIR/mut_preserve_binding_mode_2024_lint.rs:9:13
+   |
+LL |     let Foo(mut a) = &Foo(0);
+   |             ^^^^^
+note: the lint level is defined here
+  --> $DIR/mut_preserve_binding_mode_2024_lint.rs:4:11
+   |
+LL | #![forbid(dereferencing_mut_binding)]
+   |           ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: dereferencing `mut` binding
+  --> $DIR/mut_preserve_binding_mode_2024_lint.rs:13:13
+   |
+LL |     let Foo(mut a) = &mut Foo(0);
+   |             ^^^^^ `mut` dereferences the type of this binding
+   |
+help: this will change in edition 2024
+  --> $DIR/mut_preserve_binding_mode_2024_lint.rs:13:13
+   |
+LL |     let Foo(mut a) = &mut Foo(0);
+   |             ^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/sized/ensure-overriding-bindings-in-pattern-with-ty-err-doesnt-ice.rs b/tests/ui/sized/ensure-overriding-bindings-in-pattern-with-ty-err-doesnt-ice.rs
index 5c96c653df5..196da30b864 100644
--- a/tests/ui/sized/ensure-overriding-bindings-in-pattern-with-ty-err-doesnt-ice.rs
+++ b/tests/ui/sized/ensure-overriding-bindings-in-pattern-with-ty-err-doesnt-ice.rs
@@ -3,5 +3,5 @@ fn main() {
 //~^ ERROR expected a pattern, found an expression
 //~| ERROR cannot find type `T` in this scope
 //~| ERROR const and type arguments are not allowed on builtin type `str`
-//~| ERROR expected unit struct, unit variant or constant, found associated function `str<, T>::as_bytes`
+//~| ERROR expected unit struct, unit variant or constant, found associated function `str<
 }
diff --git a/tests/ui/sized/ensure-overriding-bindings-in-pattern-with-ty-err-doesnt-ice.stderr b/tests/ui/sized/ensure-overriding-bindings-in-pattern-with-ty-err-doesnt-ice.stderr
index d62c019a1e1..8df0613695b 100644
--- a/tests/ui/sized/ensure-overriding-bindings-in-pattern-with-ty-err-doesnt-ice.stderr
+++ b/tests/ui/sized/ensure-overriding-bindings-in-pattern-with-ty-err-doesnt-ice.stderr
@@ -24,7 +24,9 @@ LL -     let str::<{fn str() { let str::T>>::as_bytes; }}, T>::as_bytes;
 LL +     let str::as_bytes;
    |
 
-error[E0533]: expected unit struct, unit variant or constant, found associated function `str<, T>::as_bytes`
+error[E0533]: expected unit struct, unit variant or constant, found associated function `str<{
+                      fn str() { let (/*ERROR*/); }
+                  }, T>::as_bytes`
   --> $DIR/ensure-overriding-bindings-in-pattern-with-ty-err-doesnt-ice.rs:2:9
    |
 LL |     let str::<{fn str() { let str::T>>::as_bytes; }}, T>::as_bytes;
diff --git a/tests/ui/specialization/issue-68830-spurious-diagnostics.rs b/tests/ui/specialization/issue-68830-spurious-diagnostics.rs
index d11ec798332..a7487b8aecb 100644
--- a/tests/ui/specialization/issue-68830-spurious-diagnostics.rs
+++ b/tests/ui/specialization/issue-68830-spurious-diagnostics.rs
@@ -17,6 +17,7 @@ impl<T, D> MyTrait<T> for D {
 }
 
 impl<T> MyTrait<T> for BadStruct {
+//~^ ERROR: conflicting implementations of trait `MyTrait<_>` for type `BadStruct`
     fn foo() {}
 }
 
diff --git a/tests/ui/specialization/issue-68830-spurious-diagnostics.stderr b/tests/ui/specialization/issue-68830-spurious-diagnostics.stderr
index 0ecec03a023..13f6ae0805d 100644
--- a/tests/ui/specialization/issue-68830-spurious-diagnostics.stderr
+++ b/tests/ui/specialization/issue-68830-spurious-diagnostics.stderr
@@ -4,6 +4,16 @@ error[E0412]: cannot find type `MissingType` in this scope
 LL |     err: MissingType
    |          ^^^^^^^^^^^ not found in this scope
 
-error: aborting due to 1 previous error
+error[E0119]: conflicting implementations of trait `MyTrait<_>` for type `BadStruct`
+  --> $DIR/issue-68830-spurious-diagnostics.rs:19:1
+   |
+LL | impl<T, D> MyTrait<T> for D {
+   | --------------------------- first implementation here
+...
+LL | impl<T> MyTrait<T> for BadStruct {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `BadStruct`
+
+error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0412`.
+Some errors have detailed explanations: E0119, E0412.
+For more information about an error, try `rustc --explain E0119`.
diff --git a/tests/ui/statics/unsized_type2.rs b/tests/ui/statics/unsized_type2.rs
new file mode 100644
index 00000000000..303926849e6
--- /dev/null
+++ b/tests/ui/statics/unsized_type2.rs
@@ -0,0 +1,21 @@
+//! This test used to actually start evaluating the static even though
+//! there were errors in typeck.
+//! issue: rust-lang/rust#123153
+
+pub struct Foo {
+    pub version: str,
+}
+
+pub struct Bar {
+    pub ok: &'static [&'static Bar],
+    pub bad: &'static Foo,
+}
+
+pub static WITH_ERROR: Foo = Foo { version: 0 };
+//~^ ERROR the size for values of type `str` cannot be known at compilation time
+//~| ERROR the size for values of type `str` cannot be known at compilation time
+//~| ERROR mismatched types
+
+pub static USE_WITH_ERROR: Bar = Bar { ok: &[], bad: &WITH_ERROR };
+
+fn main() {}
diff --git a/tests/ui/statics/unsized_type2.stderr b/tests/ui/statics/unsized_type2.stderr
new file mode 100644
index 00000000000..4e47b37afdc
--- /dev/null
+++ b/tests/ui/statics/unsized_type2.stderr
@@ -0,0 +1,37 @@
+error[E0277]: the size for values of type `str` cannot be known at compilation time
+  --> $DIR/unsized_type2.rs:14:24
+   |
+LL | pub static WITH_ERROR: Foo = Foo { version: 0 };
+   |                        ^^^ doesn't have a size known at compile-time
+   |
+   = help: within `Foo`, the trait `Sized` is not implemented for `str`, which is required by `Foo: Sized`
+note: required because it appears within the type `Foo`
+  --> $DIR/unsized_type2.rs:5:12
+   |
+LL | pub struct Foo {
+   |            ^^^
+
+error[E0277]: the size for values of type `str` cannot be known at compilation time
+  --> $DIR/unsized_type2.rs:14:30
+   |
+LL | pub static WITH_ERROR: Foo = Foo { version: 0 };
+   |                              ^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: within `Foo`, the trait `Sized` is not implemented for `str`, which is required by `Foo: Sized`
+note: required because it appears within the type `Foo`
+  --> $DIR/unsized_type2.rs:5:12
+   |
+LL | pub struct Foo {
+   |            ^^^
+   = note: constant expressions must have a statically known size
+
+error[E0308]: mismatched types
+  --> $DIR/unsized_type2.rs:14:45
+   |
+LL | pub static WITH_ERROR: Foo = Foo { version: 0 };
+   |                                             ^ expected `str`, found integer
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0277, E0308.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/triagebot.toml b/triagebot.toml
index b96225c4520..731642ca74c 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -384,7 +384,7 @@ trigger_files = [
 
 [autolabel."PG-exploit-mitigations"]
 trigger_files = [
-    "compiler/rustc_symbol_mangling/src/typeid",
+    "compiler/rustc_sanitizers",
     "src/doc/rustc/src/exploit-mitigations.md",
     "src/doc/unstable-book/src/compiler-flags/branch-protection.md",
     "src/doc/unstable-book/src/compiler-flags/cf-protection.md",
@@ -701,7 +701,7 @@ cc = ["@nnethercote"]
 message = "Changes to the size of AST and/or HIR nodes."
 cc = ["@nnethercote"]
 
-[mentions."compiler/rustc_symbol_mangling/src/typeid"]
+[mentions."compiler/rustc_sanitizers"]
 cc = ["@rust-lang/project-exploit-mitigations", "@rcvalle"]
 
 [mentions."src/doc/rustc/src/exploit-mitigations.md"]
@@ -728,7 +728,7 @@ cc = ["@rust-lang/project-exploit-mitigations", "@rcvalle"]
 [mentions."src/doc/unstable-book/src/language-features/no-sanitize.md"]
 cc = ["@rust-lang/project-exploit-mitigations", "@rcvalle"]
 
-[mentions."src/doc/unstable-book/src/compiler-flags/check-cfg.md"]
+[mentions."src/doc/rustc/src/check-cfg.md"]
 cc = ["@Urgau"]
 
 [mentions."src/doc/rustc/src/platform-support"]
@@ -800,6 +800,7 @@ compiler-team = [
 compiler-team-contributors = [
     "@TaKO8Ki",
     "@Nadrieril",
+    "@nnethercote",
     "@fmease",
     "@fee1-dead",
     "@BoxyUwU",
@@ -857,14 +858,17 @@ parser = [
     "@compiler-errors",
     "@davidtwco",
     "@estebank",
+    "@nnethercote",
     "@petrochenkov",
     "@spastorino",
 ]
 lexer = [
+    "@nnethercote",
     "@petrochenkov",
     "@estebank",
 ]
 arena = [
+    "@nnethercote",
     "@spastorino",
 ]
 mir = [