about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/ci.yml4
-rw-r--r--Cargo.lock1
-rw-r--r--compiler/rustc_abi/src/layout.rs10
-rw-r--r--compiler/rustc_abi/src/lib.rs9
-rw-r--r--compiler/rustc_ast/src/node_id.rs8
-rw-r--r--compiler/rustc_ast_lowering/src/item.rs10
-rw-r--r--compiler/rustc_ast_passes/messages.ftl2
-rw-r--r--compiler/rustc_ast_passes/src/errors.rs2
-rw-r--r--compiler/rustc_borrowck/messages.ftl150
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs188
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/mod.rs246
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/move_errors.rs53
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs26
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/var_name.rs4
-rw-r--r--compiler/rustc_borrowck/src/facts.rs5
-rw-r--r--compiler/rustc_borrowck/src/location.rs8
-rw-r--r--compiler/rustc_borrowck/src/nll.rs8
-rw-r--r--compiler/rustc_borrowck/src/session_diagnostics.rs207
-rw-r--r--compiler/rustc_borrowck/src/type_check/input_output.rs3
-rw-r--r--compiler/rustc_borrowck/src/universal_regions.rs4
-rw-r--r--compiler/rustc_codegen_llvm/src/common.rs4
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs4
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/mod.rs3
-rw-r--r--compiler/rustc_codegen_llvm/src/lib.rs2
-rw-r--r--compiler/rustc_codegen_ssa/messages.ftl2
-rw-r--r--compiler/rustc_codegen_ssa/src/back/write.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/codegen_attrs.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs5
-rw-r--r--compiler/rustc_codegen_ssa/src/errors.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/block.rs3
-rw-r--r--compiler/rustc_const_eval/src/interpret/discriminant.rs17
-rw-r--r--compiler/rustc_const_eval/src/interpret/intrinsics.rs2
-rw-r--r--compiler/rustc_const_eval/src/interpret/validity.rs4
-rw-r--r--compiler/rustc_const_eval/src/transform/validate.rs2
-rw-r--r--compiler/rustc_data_structures/Cargo.toml1
-rw-r--r--compiler/rustc_data_structures/src/aligned.rs33
-rw-r--r--compiler/rustc_data_structures/src/fingerprint.rs43
-rw-r--r--compiler/rustc_data_structures/src/fingerprint/tests.rs7
-rw-r--r--compiler/rustc_data_structures/src/hashes.rs132
-rw-r--r--compiler/rustc_data_structures/src/lib.rs4
-rw-r--r--compiler/rustc_data_structures/src/profiling.rs43
-rw-r--r--compiler/rustc_data_structures/src/profiling/tests.rs19
-rw-r--r--compiler/rustc_data_structures/src/stable_hasher.rs30
-rw-r--r--compiler/rustc_data_structures/src/stable_hasher/tests.rs2
-rw-r--r--compiler/rustc_data_structures/src/svh.rs2
-rw-r--r--compiler/rustc_data_structures/src/tagged_ptr.rs270
-rw-r--r--compiler/rustc_data_structures/src/tagged_ptr/copy.rs312
-rw-r--r--compiler/rustc_data_structures/src/tagged_ptr/copy/tests.rs50
-rw-r--r--compiler/rustc_data_structures/src/tagged_ptr/drop.rs116
-rw-r--r--compiler/rustc_data_structures/src/tagged_ptr/drop/tests.rs71
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0026.md2
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0208.md4
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0311.md2
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0457.md2
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0576.md2
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0609.md2
-rw-r--r--compiler/rustc_errors/src/emitter.rs2
-rw-r--r--compiler/rustc_errors/src/lib.rs4
-rw-r--r--compiler/rustc_expand/src/mbe/macro_rules.rs4
-rw-r--r--compiler/rustc_expand/src/tests.rs4
-rw-r--r--compiler/rustc_feature/src/removed.rs2
-rw-r--r--compiler/rustc_hir/src/definitions.rs6
-rw-r--r--compiler/rustc_hir/src/hir.rs2
-rw-r--r--compiler/rustc_hir/src/tests.rs3
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/mod.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/builtin.rs9
-rw-r--r--compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/coercion.rs4
-rw-r--r--compiler/rustc_hir_typeck/src/demand.rs3
-rw-r--r--compiler/rustc_hir_typeck/src/errors.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/expr.rs90
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/generator_interior/mod.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/intrinsicck.rs4
-rw-r--r--compiler/rustc_hir_typeck/src/method/suggest.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/pat.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/upvar.rs4
-rw-r--r--compiler/rustc_incremental/src/persist/dirty_clean.rs2
-rw-r--r--compiler/rustc_incremental/src/persist/fs.rs2
-rw-r--r--compiler/rustc_infer/messages.ftl10
-rw-r--r--compiler/rustc_infer/src/errors/mod.rs14
-rw-r--r--compiler/rustc_infer/src/infer/canonical/query_response.rs4
-rw-r--r--compiler/rustc_infer/src/infer/combine.rs2
-rw-r--r--compiler/rustc_infer/src/infer/equate.rs2
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/mod.rs4
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs6
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs5
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/suggest.rs3
-rw-r--r--compiler/rustc_infer/src/infer/higher_ranked/mod.rs2
-rw-r--r--compiler/rustc_infer/src/infer/opaque_types.rs7
-rw-r--r--compiler/rustc_infer/src/infer/sub.rs2
-rw-r--r--compiler/rustc_infer/src/traits/project.rs2
-rw-r--r--compiler/rustc_lint/messages.ftl2
-rw-r--r--compiler/rustc_lint/src/builtin.rs14
-rw-r--r--compiler/rustc_lint/src/errors.rs2
-rw-r--r--compiler/rustc_lint/src/unused.rs50
-rw-r--r--compiler/rustc_lint_defs/src/builtin.rs4
-rw-r--r--compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp2
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder.rs7
-rw-r--r--compiler/rustc_metadata/src/rmeta/encoder.rs16
-rw-r--r--compiler/rustc_middle/src/dep_graph/dep_node.rs5
-rw-r--r--compiler/rustc_middle/src/infer/canonical.rs6
-rw-r--r--compiler/rustc_middle/src/lib.rs1
-rw-r--r--compiler/rustc_middle/src/macros.rs34
-rw-r--r--compiler/rustc_middle/src/metadata.rs3
-rw-r--r--compiler/rustc_middle/src/middle/exported_symbols.rs2
-rw-r--r--compiler/rustc_middle/src/mir/interpret/allocation/init_mask.rs32
-rw-r--r--compiler/rustc_middle/src/mir/interpret/pointer.rs2
-rw-r--r--compiler/rustc_middle/src/mir/mod.rs4
-rw-r--r--compiler/rustc_middle/src/mir/mono.rs19
-rw-r--r--compiler/rustc_middle/src/mir/syntax.rs4
-rw-r--r--compiler/rustc_middle/src/mir/type_foldable.rs4
-rw-r--r--compiler/rustc_middle/src/ty/abstract_const.rs2
-rw-r--r--compiler/rustc_middle/src/ty/consts/int.rs10
-rw-r--r--compiler/rustc_middle/src/ty/context.rs11
-rw-r--r--compiler/rustc_middle/src/ty/fast_reject.rs2
-rw-r--r--compiler/rustc_middle/src/ty/layout.rs6
-rw-r--r--compiler/rustc_middle/src/ty/list.rs30
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs14
-rw-r--r--compiler/rustc_middle/src/ty/structural_impls.rs6
-rw-r--r--compiler/rustc_middle/src/ty/util.rs8
-rw-r--r--compiler/rustc_middle/src/ty/visit.rs8
-rw-r--r--compiler/rustc_mir_build/src/build/expr/into.rs4
-rw-r--r--compiler/rustc_mir_build/src/build/matches/test.rs12
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs2
-rw-r--r--compiler/rustc_mir_dataflow/src/value_analysis.rs2
-rw-r--r--compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs4
-rw-r--r--compiler/rustc_mir_transform/src/add_retag.rs2
-rw-r--r--compiler/rustc_mir_transform/src/const_debuginfo.rs4
-rw-r--r--compiler/rustc_mir_transform/src/const_prop.rs2
-rw-r--r--compiler/rustc_mir_transform/src/coverage/graph.rs2
-rw-r--r--compiler/rustc_mir_transform/src/coverage/mod.rs7
-rw-r--r--compiler/rustc_mir_transform/src/dataflow_const_prop.rs2
-rw-r--r--compiler/rustc_mir_transform/src/deduce_param_attrs.rs5
-rw-r--r--compiler/rustc_mir_transform/src/dest_prop.rs4
-rw-r--r--compiler/rustc_mir_transform/src/elaborate_drops.rs2
-rw-r--r--compiler/rustc_mir_transform/src/generator.rs2
-rw-r--r--compiler/rustc_mir_transform/src/ssa.rs2
-rw-r--r--compiler/rustc_monomorphize/src/collector.rs2
-rw-r--r--compiler/rustc_monomorphize/src/partitioning/default.rs2
-rw-r--r--compiler/rustc_parse/src/lexer/mod.rs2
-rw-r--r--compiler/rustc_parse/src/validate_attr.rs2
-rw-r--r--compiler/rustc_passes/messages.ftl6
-rw-r--r--compiler/rustc_passes/src/check_attr.rs12
-rw-r--r--compiler/rustc_passes/src/errors.rs4
-rw-r--r--compiler/rustc_query_impl/src/on_disk_cache.rs7
-rw-r--r--compiler/rustc_query_impl/src/plumbing.rs4
-rw-r--r--compiler/rustc_query_system/messages.ftl2
-rw-r--r--compiler/rustc_query_system/src/dep_graph/graph.rs2
-rw-r--r--compiler/rustc_query_system/src/dep_graph/query.rs5
-rw-r--r--compiler/rustc_query_system/src/query/config.rs2
-rw-r--r--compiler/rustc_query_system/src/query/mod.rs5
-rw-r--r--compiler/rustc_query_system/src/query/plumbing.rs4
-rw-r--r--compiler/rustc_resolve/src/build_reduced_graph.rs8
-rw-r--r--compiler/rustc_resolve/src/effective_visibilities.rs2
-rw-r--r--compiler/rustc_resolve/src/errors.rs2
-rw-r--r--compiler/rustc_resolve/src/imports.rs8
-rw-r--r--compiler/rustc_resolve/src/late.rs4
-rw-r--r--compiler/rustc_resolve/src/late/diagnostics.rs4
-rw-r--r--compiler/rustc_session/src/session.rs2
-rw-r--r--compiler/rustc_span/src/def_id.rs39
-rw-r--r--compiler/rustc_span/src/hygiene.rs14
-rw-r--r--compiler/rustc_span/src/lib.rs22
-rw-r--r--compiler/rustc_span/src/source_map.rs10
-rw-r--r--compiler/rustc_span/src/symbol.rs1
-rw-r--r--compiler/rustc_span/src/tests.rs8
-rw-r--r--compiler/rustc_symbol_mangling/src/legacy.rs8
-rw-r--r--compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs2
-rw-r--r--compiler/rustc_symbol_mangling/src/v0.rs2
-rw-r--r--compiler/rustc_target/src/abi/call/avr.rs2
-rw-r--r--compiler/rustc_target/src/spec/mod.rs6
-rw-r--r--compiler/rustc_target/src/spec/thumb_base.rs2
-rw-r--r--compiler/rustc_trait_selection/src/solve/assembly/mod.rs4
-rw-r--r--compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs19
-rw-r--r--compiler/rustc_trait_selection/src/solve/trait_goals.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/misc.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/mod.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/mod.rs2
-rw-r--r--compiler/rustc_ty_utils/src/layout_sanity_check.rs2
-rw-r--r--compiler/rustc_ty_utils/src/needs_drop.rs2
-rw-r--r--compiler/rustc_type_ir/src/macros.rs141
-rw-r--r--compiler/rustc_type_ir/src/structural_impls.rs58
-rw-r--r--library/core/src/ops/index.rs1
-rw-r--r--library/core/src/ptr/const_ptr.rs6
-rw-r--r--library/core/src/ptr/mut_ptr.rs6
-rw-r--r--src/bootstrap/bin/main.rs6
-rw-r--r--src/bootstrap/bin/rustc.rs2
-rw-r--r--src/bootstrap/bolt.rs2
-rw-r--r--src/bootstrap/builder.rs19
-rw-r--r--src/bootstrap/check.rs14
-rw-r--r--src/bootstrap/compile.rs52
-rw-r--r--src/bootstrap/download-ci-llvm-stamp2
-rw-r--r--src/bootstrap/download.rs29
-rw-r--r--src/bootstrap/metrics.rs23
-rw-r--r--src/bootstrap/render_tests.rs1
-rw-r--r--src/bootstrap/test.rs29
-rw-r--r--src/bootstrap/tool.rs6
-rw-r--r--src/ci/docker/host-x86_64/dist-x86_64-illumos/Dockerfile5
-rw-r--r--src/ci/docker/host-x86_64/x86_64-gnu-llvm-15/Dockerfile6
-rw-r--r--src/ci/docker/host-x86_64/x86_64-gnu-llvm-16/Dockerfile64
-rw-r--r--src/ci/github-actions/ci.yml5
-rw-r--r--src/doc/rustc/src/codegen-options/index.md4
-rw-r--r--src/doc/rustdoc/src/write-documentation/linking-to-items-by-name.md9
-rw-r--r--src/librustdoc/passes/collect_intra_doc_links.rs2
-rw-r--r--src/librustdoc/visit_ast.rs48
-rw-r--r--src/tools/compiletest/src/common.rs7
-rw-r--r--src/tools/compiletest/src/header/needs.rs5
-rw-r--r--src/tools/compiletest/src/header/tests.rs10
-rw-r--r--src/tools/compiletest/src/main.rs2
-rw-r--r--src/tools/compiletest/src/runtest.rs3
-rw-r--r--src/tools/tidy/src/ui_tests.rs2
-rw-r--r--tests/codegen/align-fn.rs40
-rw-r--r--tests/codegen/optimize-attr-1.rs2
-rw-r--r--tests/codegen/option-as-slice.rs2
-rw-r--r--tests/codegen/thread-local.rs8
-rw-r--r--tests/debuginfo/unsized.rs2
-rw-r--r--tests/run-make/issue-107094/Makefile7
-rw-r--r--tests/rustdoc-ui/error-in-impl-trait/infinite-recursive-type-2.rs9
-rw-r--r--tests/rustdoc-ui/error-in-impl-trait/infinite-recursive-type-impl-trait-return.rs (renamed from tests/rustdoc-ui/infinite-recursive-type-impl-trait-return.rs)0
-rw-r--r--tests/rustdoc-ui/error-in-impl-trait/infinite-recursive-type-impl-trait-return.stderr (renamed from tests/rustdoc-ui/infinite-recursive-type-impl-trait-return.stderr)0
-rw-r--r--tests/rustdoc-ui/error-in-impl-trait/infinite-recursive-type.rs (renamed from tests/rustdoc-ui/infinite-recursive-type-impl-trait.rs)5
-rw-r--r--tests/rustdoc-ui/infinite-recursive-type-impl-trait.stderr16
-rw-r--r--tests/rustdoc/issue-110422-inner-private.rs64
-rw-r--r--tests/ui-fulldeps/compiler-calls.rs1
-rw-r--r--tests/ui-fulldeps/hash-stable-is-unstable.rs1
-rw-r--r--tests/ui-fulldeps/hash-stable-is-unstable.stderr10
-rw-r--r--tests/ui-fulldeps/pathless-extern-unstable.rs1
-rw-r--r--tests/ui-fulldeps/pathless-extern-unstable.stderr2
-rw-r--r--tests/ui-fulldeps/plugin/auxiliary/empty-plugin.rs (renamed from tests/ui-fulldeps/auxiliary/empty-plugin.rs)0
-rw-r--r--tests/ui-fulldeps/plugin/auxiliary/issue-40001-plugin.rs (renamed from tests/ui-fulldeps/auxiliary/issue-40001-plugin.rs)0
-rw-r--r--tests/ui-fulldeps/plugin/auxiliary/lint-for-crate.rs (renamed from tests/ui-fulldeps/auxiliary/lint-for-crate.rs)0
-rw-r--r--tests/ui-fulldeps/plugin/auxiliary/lint-group-plugin-test.rs (renamed from tests/ui-fulldeps/auxiliary/lint-group-plugin-test.rs)0
-rw-r--r--tests/ui-fulldeps/plugin/auxiliary/lint-plugin-test.rs (renamed from tests/ui-fulldeps/auxiliary/lint-plugin-test.rs)0
-rw-r--r--tests/ui-fulldeps/plugin/auxiliary/lint-tool-test.rs (renamed from tests/ui-fulldeps/auxiliary/lint-tool-test.rs)0
-rw-r--r--tests/ui-fulldeps/plugin/auxiliary/lto-syntax-extension-lib.rs (renamed from tests/ui-fulldeps/auxiliary/lto-syntax-extension-lib.rs)0
-rw-r--r--tests/ui-fulldeps/plugin/auxiliary/lto-syntax-extension-plugin.rs (renamed from tests/ui-fulldeps/auxiliary/lto-syntax-extension-plugin.rs)0
-rw-r--r--tests/ui-fulldeps/plugin/auxiliary/multiple-plugins-1.rs (renamed from tests/ui-fulldeps/auxiliary/multiple-plugins-1.rs)0
-rw-r--r--tests/ui-fulldeps/plugin/auxiliary/multiple-plugins-2.rs (renamed from tests/ui-fulldeps/auxiliary/multiple-plugins-2.rs)0
-rw-r--r--tests/ui-fulldeps/plugin/auxiliary/outlive-expansion-phase.rs (renamed from tests/ui-fulldeps/auxiliary/outlive-expansion-phase.rs)0
-rw-r--r--tests/ui-fulldeps/plugin/auxiliary/rlib-crate-test.rs (renamed from tests/ui-fulldeps/auxiliary/rlib-crate-test.rs)0
-rw-r--r--tests/ui-fulldeps/plugin/feature-gate-plugin.rs (renamed from tests/ui-fulldeps/feature-gate-plugin.rs)0
-rw-r--r--tests/ui-fulldeps/plugin/feature-gate-plugin.stderr (renamed from tests/ui-fulldeps/feature-gate-plugin.stderr)0
-rw-r--r--tests/ui-fulldeps/plugin/gated-plugin.rs (renamed from tests/ui-fulldeps/gated-plugin.rs)0
-rw-r--r--tests/ui-fulldeps/plugin/gated-plugin.stderr (renamed from tests/ui-fulldeps/gated-plugin.stderr)0
-rw-r--r--tests/ui-fulldeps/plugin/issue-15778-fail.rs (renamed from tests/ui-fulldeps/issue-15778-fail.rs)0
-rw-r--r--tests/ui-fulldeps/plugin/issue-15778-fail.stderr (renamed from tests/ui-fulldeps/issue-15778-fail.stderr)0
-rw-r--r--tests/ui-fulldeps/plugin/issue-40001.rs (renamed from tests/ui-fulldeps/issue-40001.rs)0
-rw-r--r--tests/ui-fulldeps/plugin/issue-40001.stderr (renamed from tests/ui-fulldeps/issue-40001.stderr)0
-rw-r--r--tests/ui-fulldeps/plugin/lint-group-plugin-deny-cmdline.rs (renamed from tests/ui-fulldeps/lint-group-plugin-deny-cmdline.rs)0
-rw-r--r--tests/ui-fulldeps/plugin/lint-group-plugin-deny-cmdline.stderr (renamed from tests/ui-fulldeps/lint-group-plugin-deny-cmdline.stderr)0
-rw-r--r--tests/ui-fulldeps/plugin/lint-group-plugin.rs (renamed from tests/ui-fulldeps/lint-group-plugin.rs)0
-rw-r--r--tests/ui-fulldeps/plugin/lint-group-plugin.stderr (renamed from tests/ui-fulldeps/lint-group-plugin.stderr)0
-rw-r--r--tests/ui-fulldeps/plugin/lint-plugin-cmdline-allow.rs (renamed from tests/ui-fulldeps/lint-plugin-cmdline-allow.rs)0
-rw-r--r--tests/ui-fulldeps/plugin/lint-plugin-cmdline-allow.stderr (renamed from tests/ui-fulldeps/lint-plugin-cmdline-allow.stderr)0
-rw-r--r--tests/ui-fulldeps/plugin/lint-plugin-cmdline-load.rs (renamed from tests/ui-fulldeps/lint-plugin-cmdline-load.rs)0
-rw-r--r--tests/ui-fulldeps/plugin/lint-plugin-cmdline-load.stderr (renamed from tests/ui-fulldeps/lint-plugin-cmdline-load.stderr)0
-rw-r--r--tests/ui-fulldeps/plugin/lint-plugin-deny-attr.rs (renamed from tests/ui-fulldeps/lint-plugin-deny-attr.rs)0
-rw-r--r--tests/ui-fulldeps/plugin/lint-plugin-deny-attr.stderr (renamed from tests/ui-fulldeps/lint-plugin-deny-attr.stderr)0
-rw-r--r--tests/ui-fulldeps/plugin/lint-plugin-deny-cmdline.rs (renamed from tests/ui-fulldeps/lint-plugin-deny-cmdline.rs)0
-rw-r--r--tests/ui-fulldeps/plugin/lint-plugin-deny-cmdline.stderr (renamed from tests/ui-fulldeps/lint-plugin-deny-cmdline.stderr)0
-rw-r--r--tests/ui-fulldeps/plugin/lint-plugin-forbid-attrs.rs (renamed from tests/ui-fulldeps/lint-plugin-forbid-attrs.rs)0
-rw-r--r--tests/ui-fulldeps/plugin/lint-plugin-forbid-attrs.stderr (renamed from tests/ui-fulldeps/lint-plugin-forbid-attrs.stderr)0
-rw-r--r--tests/ui-fulldeps/plugin/lint-plugin-forbid-cmdline.rs (renamed from tests/ui-fulldeps/lint-plugin-forbid-cmdline.rs)0
-rw-r--r--tests/ui-fulldeps/plugin/lint-plugin-forbid-cmdline.stderr (renamed from tests/ui-fulldeps/lint-plugin-forbid-cmdline.stderr)0
-rw-r--r--tests/ui-fulldeps/plugin/lint-plugin.rs (renamed from tests/ui-fulldeps/lint-plugin.rs)0
-rw-r--r--tests/ui-fulldeps/plugin/lint-plugin.stderr (renamed from tests/ui-fulldeps/lint-plugin.stderr)0
-rw-r--r--tests/ui-fulldeps/plugin/lint-tool-cmdline-allow.rs (renamed from tests/ui-fulldeps/lint-tool-cmdline-allow.rs)0
-rw-r--r--tests/ui-fulldeps/plugin/lint-tool-cmdline-allow.stderr (renamed from tests/ui-fulldeps/lint-tool-cmdline-allow.stderr)0
-rw-r--r--tests/ui-fulldeps/plugin/lint-tool-test.rs (renamed from tests/ui-fulldeps/lint-tool-test.rs)0
-rw-r--r--tests/ui-fulldeps/plugin/lint-tool-test.stderr (renamed from tests/ui-fulldeps/lint-tool-test.stderr)0
-rw-r--r--tests/ui-fulldeps/plugin/lto-syntax-extension.rs (renamed from tests/ui-fulldeps/lto-syntax-extension.rs)0
-rw-r--r--tests/ui-fulldeps/plugin/lto-syntax-extension.stderr (renamed from tests/ui-fulldeps/lto-syntax-extension.stderr)0
-rw-r--r--tests/ui-fulldeps/plugin/macro-crate-rlib.rs (renamed from tests/ui-fulldeps/macro-crate-rlib.rs)1
-rw-r--r--tests/ui-fulldeps/plugin/macro-crate-rlib.stderr (renamed from tests/ui-fulldeps/macro-crate-rlib.stderr)2
-rw-r--r--tests/ui-fulldeps/plugin/multiple-plugins.rs (renamed from tests/ui-fulldeps/multiple-plugins.rs)0
-rw-r--r--tests/ui-fulldeps/plugin/multiple-plugins.stderr (renamed from tests/ui-fulldeps/multiple-plugins.stderr)0
-rw-r--r--tests/ui-fulldeps/plugin/outlive-expansion-phase.rs (renamed from tests/ui-fulldeps/outlive-expansion-phase.rs)0
-rw-r--r--tests/ui-fulldeps/plugin/outlive-expansion-phase.stderr (renamed from tests/ui-fulldeps/outlive-expansion-phase.stderr)0
-rw-r--r--tests/ui-fulldeps/plugin/plugin-args.rs (renamed from tests/ui-fulldeps/plugin-args.rs)0
-rw-r--r--tests/ui-fulldeps/plugin/plugin-args.stderr (renamed from tests/ui-fulldeps/plugin-args.stderr)0
-rw-r--r--tests/ui-fulldeps/plugin/plugin-as-extern-crate.rs (renamed from tests/ui-fulldeps/plugin-as-extern-crate.rs)0
-rw-r--r--tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs1
-rw-r--r--tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr182
-rw-r--r--tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs1
-rw-r--r--tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr182
-rw-r--r--tests/ui/attributes/invalid-repr.rs5
-rw-r--r--tests/ui/attributes/invalid-repr.stderr12
-rw-r--r--tests/ui/borrowck/borrowck-block-uninit.rs (renamed from tests/ui/borrowck/borrowck-block-unint.rs)0
-rw-r--r--tests/ui/borrowck/borrowck-block-uninit.stderr (renamed from tests/ui/borrowck/borrowck-block-unint.stderr)2
-rw-r--r--tests/ui/codegen/freeze-on-polymorphic-projection.rs19
-rw-r--r--tests/ui/codegen/freeze-on-polymorphic-projection.stderr12
-rw-r--r--tests/ui/consts/auxiliary/foreign-generic-mismatch-with-const-arg.rs1
-rw-r--r--tests/ui/consts/foreign-generic-mismatch-with-const-arg.rs8
-rw-r--r--tests/ui/consts/foreign-generic-mismatch-with-const-arg.stderr21
-rw-r--r--tests/ui/error-codes/E0026-teach.stderr2
-rw-r--r--tests/ui/lint-group-denied-lint-allowed.rs (renamed from tests/ui-fulldeps/lint-group-denied-lint-allowed.rs)1
-rw-r--r--tests/ui/lint-group-forbid-always-trumps-cli.rs (renamed from tests/ui-fulldeps/lint-group-forbid-always-trumps-cli.rs)1
-rw-r--r--tests/ui/lint-group-forbid-always-trumps-cli.stderr (renamed from tests/ui-fulldeps/lint-group-forbid-always-trumps-cli.stderr)2
-rw-r--r--tests/ui/lint/unused/issue-54538-unused-parens-lint.fixed19
-rw-r--r--tests/ui/lint/unused/issue-54538-unused-parens-lint.rs19
-rw-r--r--tests/ui/lint/unused/issue-54538-unused-parens-lint.stderr62
-rw-r--r--tests/ui/meta/no_std-extern-libc.rs7
-rw-r--r--tests/ui/type-alias-enum-variants/enum-variant-generic-args.stderr12
-rw-r--r--tests/ui/typeck/bad-index-due-to-nested.rs27
-rw-r--r--tests/ui/typeck/bad-index-due-to-nested.stderr64
310 files changed, 2974 insertions, 1427 deletions
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index bce88472f96..dacf929278a 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -292,6 +292,10 @@ jobs:
           - name: x86_64-gnu-distcheck
             os: ubuntu-20.04-8core-32gb
             env: {}
+          - name: x86_64-gnu-llvm-16
+            env:
+              RUST_BACKTRACE: 1
+            os: ubuntu-20.04-8core-32gb
           - name: x86_64-gnu-llvm-15
             env:
               RUST_BACKTRACE: 1
diff --git a/Cargo.lock b/Cargo.lock
index 358b2f2e924..da2e483fe61 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -3181,7 +3181,6 @@ dependencies = [
  "rustc_index",
  "rustc_macros",
  "rustc_serialize",
- "serde_json",
  "smallvec",
  "stable_deref_trait",
  "stacker",
diff --git a/compiler/rustc_abi/src/layout.rs b/compiler/rustc_abi/src/layout.rs
index c863acde7b0..f3af031ade4 100644
--- a/compiler/rustc_abi/src/layout.rs
+++ b/compiler/rustc_abi/src/layout.rs
@@ -79,7 +79,8 @@ pub trait LayoutCalculator {
                 {
                     // `ReprOptions.layout_seed` is a deterministic seed that we can use to
                     // randomize field ordering with
-                    let mut rng = Xoshiro128StarStar::seed_from_u64(repr.field_shuffle_seed);
+                    let mut rng =
+                        Xoshiro128StarStar::seed_from_u64(repr.field_shuffle_seed.as_u64());
 
                     // Shuffle the ordering of the fields
                     optimizing.shuffle(&mut rng);
@@ -461,8 +462,8 @@ pub trait LayoutCalculator {
             let all_indices = variants.indices();
             let needs_disc =
                 |index: VariantIdx| index != largest_variant_index && !absent(&variants[index]);
-            let niche_variants = all_indices.clone().find(|v| needs_disc(*v)).unwrap().index()
-                ..=all_indices.rev().find(|v| needs_disc(*v)).unwrap().index();
+            let niche_variants = all_indices.clone().find(|v| needs_disc(*v)).unwrap()
+                ..=all_indices.rev().find(|v| needs_disc(*v)).unwrap();
 
             let count = niche_variants.size_hint().1.unwrap() as u128;
 
@@ -560,8 +561,7 @@ pub trait LayoutCalculator {
                     tag: niche_scalar,
                     tag_encoding: TagEncoding::Niche {
                         untagged_variant: largest_variant_index,
-                        niche_variants: (VariantIdx::new(*niche_variants.start())
-                            ..=VariantIdx::new(*niche_variants.end())),
+                        niche_variants,
                         niche_start,
                     },
                     tag_field: 0,
diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs
index 7a3defd2a5d..a5cdaa547d8 100644
--- a/compiler/rustc_abi/src/lib.rs
+++ b/compiler/rustc_abi/src/lib.rs
@@ -9,9 +9,10 @@ use std::str::FromStr;
 
 use bitflags::bitflags;
 use rustc_data_structures::intern::Interned;
+use rustc_data_structures::stable_hasher::Hash64;
 #[cfg(feature = "nightly")]
 use rustc_data_structures::stable_hasher::StableOrd;
-use rustc_index::vec::{Idx, IndexSlice, IndexVec};
+use rustc_index::vec::{IndexSlice, IndexVec};
 #[cfg(feature = "nightly")]
 use rustc_macros::HashStable_Generic;
 #[cfg(feature = "nightly")]
@@ -77,12 +78,12 @@ pub struct ReprOptions {
     pub flags: ReprFlags,
     /// The seed to be used for randomizing a type's layout
     ///
-    /// Note: This could technically be a `[u8; 16]` (a `u128`) which would
+    /// Note: This could technically be a `Hash128` which would
     /// be the "most accurate" hash as it'd encompass the item and crate
     /// hash without loss, but it does pay the price of being larger.
-    /// Everything's a tradeoff, a `u64` seed should be sufficient for our
+    /// Everything's a tradeoff, a 64-bit seed should be sufficient for our
     /// purposes (primarily `-Z randomize-layout`)
-    pub field_shuffle_seed: u64,
+    pub field_shuffle_seed: Hash64,
 }
 
 impl ReprOptions {
diff --git a/compiler/rustc_ast/src/node_id.rs b/compiler/rustc_ast/src/node_id.rs
index daa82996b3d..d16741757d1 100644
--- a/compiler/rustc_ast/src/node_id.rs
+++ b/compiler/rustc_ast/src/node_id.rs
@@ -9,14 +9,14 @@ rustc_index::newtype_index! {
     ///
     /// [`DefId`]: rustc_span::def_id::DefId
     #[debug_format = "NodeId({})"]
-    pub struct NodeId {}
+    pub struct NodeId {
+        /// The [`NodeId`] used to represent the root of the crate.
+        const CRATE_NODE_ID = 0;
+    }
 }
 
 rustc_data_structures::define_id_collections!(NodeMap, NodeSet, NodeMapEntry, NodeId);
 
-/// The [`NodeId`] used to represent the root of the crate.
-pub const CRATE_NODE_ID: NodeId = NodeId::from_u32(0);
-
 /// When parsing and at the beginning of doing expansions, we initially give all AST nodes
 /// this dummy AST [`NodeId`]. Then, during a later phase of expansion, we renumber them
 /// to have small, positive IDs.
diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs
index c061a244cf5..08e7a4dfe5d 100644
--- a/compiler/rustc_ast_lowering/src/item.rs
+++ b/compiler/rustc_ast_lowering/src/item.rs
@@ -138,12 +138,10 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> {
             // Evaluate with the lifetimes in `params` in-scope.
             // This is used to track which lifetimes have already been defined,
             // and which need to be replicated when lowering an async fn.
-            match parent_hir.node().expect_item().kind {
-                hir::ItemKind::Impl(hir::Impl { of_trait, .. }) => {
-                    lctx.is_in_trait_impl = of_trait.is_some();
-                }
-                _ => {}
-            };
+
+            if let hir::ItemKind::Impl(impl_) = parent_hir.node().expect_item().kind {
+                lctx.is_in_trait_impl = impl_.of_trait.is_some();
+            }
 
             match ctxt {
                 AssocCtxt::Trait => hir::OwnerNode::TraitItem(lctx.lower_trait_item(item)),
diff --git a/compiler/rustc_ast_passes/messages.ftl b/compiler/rustc_ast_passes/messages.ftl
index a349fe6a3c4..ffca37ae9d5 100644
--- a/compiler/rustc_ast_passes/messages.ftl
+++ b/compiler/rustc_ast_passes/messages.ftl
@@ -231,7 +231,7 @@ ast_passes_feature_on_non_nightly = `#![feature]` may not be used on the {$chann
     .suggestion = remove the attribute
     .stable_since = the feature `{$name}` has been stable since `{$since}` and no longer requires an attribute to enable
 
-ast_passes_incompatbile_features = `{$f1}` and `{$f2}` are incompatible, using them at the same time is not allowed
+ast_passes_incompatible_features = `{$f1}` and `{$f2}` are incompatible, using them at the same time is not allowed
     .help = remove one of these features
 
 ast_passes_show_span = {$msg}
diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs
index 27bbd237961..1732865f0bb 100644
--- a/compiler/rustc_ast_passes/src/errors.rs
+++ b/compiler/rustc_ast_passes/src/errors.rs
@@ -677,7 +677,7 @@ impl AddToDiagnostic for StableFeature {
 }
 
 #[derive(Diagnostic)]
-#[diag(ast_passes_incompatbile_features)]
+#[diag(ast_passes_incompatible_features)]
 #[help]
 pub struct IncompatibleFeatures {
     #[primary_span]
diff --git a/compiler/rustc_borrowck/messages.ftl b/compiler/rustc_borrowck/messages.ftl
index a3b6b5e8138..0b8123c9703 100644
--- a/compiler/rustc_borrowck/messages.ftl
+++ b/compiler/rustc_borrowck/messages.ftl
@@ -56,18 +56,6 @@ borrowck_returned_lifetime_short =
 borrowck_used_impl_require_static =
     the used `impl` has a `'static` requirement
 
-borrowck_capture_kind_label =
-    capture is {$kind_desc} because of use here
-
-borrowck_var_borrow_by_use_place_in_generator =
-    borrow occurs due to use of {$place} in closure in generator
-
-borrowck_var_borrow_by_use_place_in_closure =
-    borrow occurs due to use of {$place} in closure
-
-borrowck_var_borrow_by_use_place =
-    borrow occurs due to use of {$place}
-
 borrowck_borrow_due_to_use_generator =
     borrow occurs due to use in generator
 
@@ -101,12 +89,63 @@ borrowck_capture_mut =
 borrowck_capture_move =
     capture is moved because of use here
 
+borrowck_var_borrow_by_use_place_in_generator =
+    {$is_single_var ->
+        *[true] borrow occurs
+        [false] borrows occur
+    } due to use of {$place} in generator
+
+borrowck_var_borrow_by_use_place_in_closure =
+    {$is_single_var ->
+        *[true] borrow occurs
+        [false] borrows occur
+    } due to use of {$place} in closure
+
+borrowck_var_borrow_by_use_in_generator =
+    borrow occurs due to use in generator
+
+borrowck_var_borrow_by_use_in_closure =
+    borrow occurs due to use in closure
+
 borrowck_var_move_by_use_place_in_generator =
     move occurs due to use of {$place} in generator
 
 borrowck_var_move_by_use_place_in_closure =
     move occurs due to use of {$place} in closure
 
+borrowck_var_move_by_use_in_generator =
+    move occurs due to use in generator
+
+borrowck_var_move_by_use_in_closure =
+    move occurs due to use in closure
+
+borrowck_partial_var_move_by_use_in_generator =
+    variable {$is_partial ->
+        [true] partially moved
+        *[false] moved
+    } due to use in generator
+
+borrowck_partial_var_move_by_use_in_closure =
+    variable {$is_partial ->
+        [true] partially moved
+        *[false] moved
+    } due to use in closure
+
+borrowck_var_first_borrow_by_use_place_in_generator =
+    first borrow occurs due to use of {$place} in generator
+
+borrowck_var_first_borrow_by_use_place_in_closure =
+    first borrow occurs due to use of {$place} in closure
+
+borrowck_var_second_borrow_by_use_place_in_generator =
+    second borrow occurs due to use of {$place} in generator
+
+borrowck_var_second_borrow_by_use_place_in_closure =
+    second borrow occurs due to use of {$place} in closure
+
+borrowck_var_mutable_borrow_by_use_place_in_closure =
+    mutable borrow occurs due to use of {$place} in closure
+
 borrowck_cannot_move_when_borrowed =
     cannot move out of {$place ->
         [value] value
@@ -127,3 +166,90 @@ borrowck_opaque_type_non_generic_param =
         [true] cannot use static lifetime; use a bound lifetime instead or remove the lifetime parameter from the opaque type
         *[other] this generic parameter must be used with a generic {$kind} parameter
     }
+
+borrowck_moved_due_to_call =
+    {$place_name} {$is_partial ->
+        [true] partially moved
+        *[false] moved
+    } due to this {$is_loop_message ->
+        [true] call, in previous iteration of loop
+        *[false] call
+    }
+
+borrowck_moved_due_to_usage_in_operator =
+    {$place_name} {$is_partial ->
+        [true] partially moved
+        *[false] moved
+    } due to usage in {$is_loop_message ->
+        [true] operator, in previous iteration of loop
+        *[false] operator
+    }
+
+borrowck_moved_due_to_implicit_into_iter_call =
+    {$place_name} {$is_partial ->
+        [true] partially moved
+        *[false] moved
+    } due to this implicit call to {$is_loop_message ->
+        [true] `.into_iter()`, in previous iteration of loop
+        *[false] `.into_iter()`
+    }
+
+borrowck_moved_due_to_method_call =
+    {$place_name} {$is_partial ->
+        [true] partially moved
+        *[false] moved
+    } due to this method {$is_loop_message ->
+        [true] call, in previous iteration of loop
+        *[false] call
+    }
+
+borrowck_value_moved_here =
+    value {$is_partial ->
+        [true] partially moved
+        *[false] moved
+    } {$is_move_msg ->
+        [true] into closure here
+        *[false] here
+    }{$is_loop_message ->
+        [true] , in previous iteration of loop
+        *[false] {""}
+    }
+
+borrowck_consider_borrow_type_contents =
+    help: consider calling `.as_ref()` or `.as_mut()` to borrow the type's contents
+
+borrowck_moved_a_fn_once_in_call =
+    this value implements `FnOnce`, which causes it to be moved when called
+
+borrowck_calling_operator_moves_lhs =
+    calling this operator moves the left-hand side
+
+borrowck_func_take_self_moved_place =
+    `{$func}` takes ownership of the receiver `self`, which moves {$place_name}
+
+borrowck_suggest_iterate_over_slice =
+    consider iterating over a slice of the `{$ty}`'s content to avoid moving into the `for` loop
+
+borrowck_suggest_create_freash_reborrow =
+    consider reborrowing the `Pin` instead of moving it
+
+borrowck_value_capture_here =
+    value captured {$is_within ->
+        [true] here by generator
+        *[false] here
+    }
+
+borrowck_move_out_place_here =
+    {$place} is moved here
+
+borrowck_closure_invoked_twice =
+    closure cannot be invoked more than once because it moves the variable `{$place_name}` out of its environment
+
+borrowck_closure_moved_twice =
+    closure cannot be moved more than once as it is not `Copy` due to moving the variable `{$place_name}` out of its environment
+
+borrowck_ty_no_impl_copy =
+    {$is_partial_move ->
+        [true] partial move
+        *[false] move
+    } occurs because {$place} has type `{$ty}`, which does not implement the `Copy` trait
diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index 6259ae47e89..a4a3c738f47 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -30,8 +30,8 @@ use crate::borrow_set::TwoPhaseActivation;
 use crate::borrowck_errors;
 
 use crate::diagnostics::conflict_errors::StorageDeadOrDrop::LocalStorageDead;
-use crate::diagnostics::find_all_local_uses;
 use crate::diagnostics::mutability_errors::mut_borrow_of_mutable_ref;
+use crate::diagnostics::{find_all_local_uses, CapturedMessageOpt};
 use crate::{
     borrow_set::BorrowData, diagnostics::Instance, prefixes::IsPrefixOf,
     InitializationRequiringAction, MirBorrowckCtxt, PrefixSet, WriteKind,
@@ -183,13 +183,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                 let move_spans = self.move_spans(moved_place.as_ref(), move_out.source);
                 let move_span = move_spans.args_or_use();
 
-                let move_msg = if move_spans.for_closure() { " into closure" } else { "" };
+                let is_move_msg = move_spans.for_closure();
 
-                let loop_message = if location == move_out.source || move_site.traversed_back_edge {
-                    ", in previous iteration of loop"
-                } else {
-                    ""
-                };
+                let is_loop_message = location == move_out.source || move_site.traversed_back_edge;
 
                 if location == move_out.source {
                     is_loop_move = true;
@@ -206,17 +202,21 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                         );
                     }
 
+                    let msg_opt = CapturedMessageOpt {
+                        is_partial_move,
+                        is_loop_message,
+                        is_move_msg,
+                        is_loop_move,
+                        maybe_reinitialized_locations_is_empty: maybe_reinitialized_locations
+                            .is_empty(),
+                    };
                     self.explain_captures(
                         &mut err,
                         span,
                         move_span,
                         move_spans,
                         *moved_place,
-                        partially_str,
-                        loop_message,
-                        move_msg,
-                        is_loop_move,
-                        maybe_reinitialized_locations.is_empty(),
+                        msg_opt,
                     );
                 }
                 seen_spans.insert(move_span);
@@ -282,12 +282,21 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             }
 
             if needs_note {
-                let span = if let Some(local) = place.as_local() {
-                    Some(self.body.local_decls[local].source_info.span)
+                if let Some(local) = place.as_local() {
+                    let span = self.body.local_decls[local].source_info.span;
+                    err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Label {
+                        is_partial_move,
+                        ty,
+                        place: &note_msg,
+                        span,
+                    });
                 } else {
-                    None
+                    err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Note {
+                        is_partial_move,
+                        ty,
+                        place: &note_msg,
+                    });
                 };
-                self.note_type_does_not_implement_copy(&mut err, &note_msg, ty, span, partial_str);
             }
 
             if let UseSpans::FnSelfUse {
@@ -827,11 +836,13 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
 
         borrow_spans.var_path_only_subdiag(&mut err, crate::InitializationRequiringAction::Borrow);
 
-        move_spans.var_span_label(
-            &mut err,
-            format!("move occurs due to use{}", move_spans.describe()),
-            "moved",
-        );
+        move_spans.var_subdiag(None, &mut err, None, |kind, var_span| {
+            use crate::session_diagnostics::CaptureVarCause::*;
+            match kind {
+                Some(_) => MoveUseInGenerator { var_span },
+                None => MoveUseInClosure { var_span },
+            }
+        });
 
         self.explain_why_borrow_contains_point(location, borrow, None)
             .add_explanation_to_diagnostic(
@@ -868,13 +879,15 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             borrow_span,
             &self.describe_any_place(borrow.borrowed_place.as_ref()),
         );
-        borrow_spans.var_subdiag(&mut err, Some(borrow.kind), |kind, var_span| {
+        borrow_spans.var_subdiag(None, &mut err, Some(borrow.kind), |kind, var_span| {
             use crate::session_diagnostics::CaptureVarCause::*;
             let place = &borrow.borrowed_place;
             let desc_place = self.describe_any_place(place.as_ref());
             match kind {
-                Some(_) => BorrowUsePlaceGenerator { place: desc_place, var_span },
-                None => BorrowUsePlaceClosure { place: desc_place, var_span },
+                Some(_) => {
+                    BorrowUsePlaceGenerator { place: desc_place, var_span, is_single_var: true }
+                }
+                None => BorrowUsePlaceClosure { place: desc_place, var_span, is_single_var: true },
             }
         });
 
@@ -988,16 +1001,26 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                         immutable_section_description,
                         "mutably borrow",
                     );
-                    borrow_spans.var_span_label(
+                    borrow_spans.var_subdiag(
+                        None,
                         &mut err,
-                        format!(
-                            "borrow occurs due to use of {}{}",
-                            desc_place,
-                            borrow_spans.describe(),
-                        ),
-                        "immutable",
+                        Some(BorrowKind::Unique),
+                        |kind, var_span| {
+                            use crate::session_diagnostics::CaptureVarCause::*;
+                            match kind {
+                                Some(_) => BorrowUsePlaceGenerator {
+                                    place: desc_place,
+                                    var_span,
+                                    is_single_var: true,
+                                },
+                                None => BorrowUsePlaceClosure {
+                                    place: desc_place,
+                                    var_span,
+                                    is_single_var: true,
+                                },
+                            }
+                        },
                     );
-
                     return err;
                 } else {
                     first_borrow_desc = "immutable ";
@@ -1070,32 +1093,48 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         };
 
         if issued_spans == borrow_spans {
-            borrow_spans.var_span_label(
-                &mut err,
-                format!("borrows occur due to use of {}{}", desc_place, borrow_spans.describe(),),
-                gen_borrow_kind.describe_mutability(),
-            );
+            borrow_spans.var_subdiag(None, &mut err, Some(gen_borrow_kind), |kind, var_span| {
+                use crate::session_diagnostics::CaptureVarCause::*;
+                match kind {
+                    Some(_) => BorrowUsePlaceGenerator {
+                        place: desc_place,
+                        var_span,
+                        is_single_var: false,
+                    },
+                    None => {
+                        BorrowUsePlaceClosure { place: desc_place, var_span, is_single_var: false }
+                    }
+                }
+            });
         } else {
-            let borrow_place = &issued_borrow.borrowed_place;
-            let borrow_place_desc = self.describe_any_place(borrow_place.as_ref());
-            issued_spans.var_span_label(
+            issued_spans.var_subdiag(
+                Some(&self.infcx.tcx.sess.parse_sess.span_diagnostic),
                 &mut err,
-                format!(
-                    "first borrow occurs due to use of {}{}",
-                    borrow_place_desc,
-                    issued_spans.describe(),
-                ),
-                issued_borrow.kind.describe_mutability(),
+                Some(issued_borrow.kind),
+                |kind, var_span| {
+                    use crate::session_diagnostics::CaptureVarCause::*;
+                    let borrow_place = &issued_borrow.borrowed_place;
+                    let borrow_place_desc = self.describe_any_place(borrow_place.as_ref());
+                    match kind {
+                        Some(_) => {
+                            FirstBorrowUsePlaceGenerator { place: borrow_place_desc, var_span }
+                        }
+                        None => FirstBorrowUsePlaceClosure { place: borrow_place_desc, var_span },
+                    }
+                },
             );
 
-            borrow_spans.var_span_label(
+            borrow_spans.var_subdiag(
+                Some(&self.infcx.tcx.sess.parse_sess.span_diagnostic),
                 &mut err,
-                format!(
-                    "second borrow occurs due to use of {}{}",
-                    desc_place,
-                    borrow_spans.describe(),
-                ),
-                gen_borrow_kind.describe_mutability(),
+                Some(gen_borrow_kind),
+                |kind, var_span| {
+                    use crate::session_diagnostics::CaptureVarCause::*;
+                    match kind {
+                        Some(_) => SecondBorrowUsePlaceGenerator { place: desc_place, var_span },
+                        None => SecondBorrowUsePlaceClosure { place: desc_place, var_span },
+                    }
+                },
             );
         }
 
@@ -1731,9 +1770,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             err.span_label(borrow_span, "borrowed value does not live long enough");
             err.span_label(drop_span, format!("`{}` dropped here while still borrowed", name));
 
-            let within = if borrow_spans.for_generator() { " by generator" } else { "" };
-
-            borrow_spans.args_span_label(&mut err, format!("value captured here{}", within));
+            borrow_spans.args_subdiag(&mut err, |args_span| {
+                crate::session_diagnostics::CaptureArgLabel::Capture {
+                    is_within: borrow_spans.for_generator(),
+                    args_span,
+                }
+            });
 
             explanation.add_explanation_to_diagnostic(
                 self.infcx.tcx,
@@ -1947,9 +1989,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             None,
         );
 
-        let within = if borrow_spans.for_generator() { " by generator" } else { "" };
-
-        borrow_spans.args_span_label(&mut err, format!("value captured here{}", within));
+        borrow_spans.args_subdiag(&mut err, |args_span| {
+            crate::session_diagnostics::CaptureArgLabel::Capture {
+                is_within: borrow_spans.for_generator(),
+                args_span,
+            }
+        });
 
         err
     }
@@ -2382,11 +2427,14 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                     section,
                     "assign",
                 );
-                loan_spans.var_span_label(
-                    &mut err,
-                    format!("borrow occurs due to use{}", loan_spans.describe()),
-                    loan.kind.describe_mutability(),
-                );
+
+                loan_spans.var_subdiag(None, &mut err, Some(loan.kind), |kind, var_span| {
+                    use crate::session_diagnostics::CaptureVarCause::*;
+                    match kind {
+                        Some(_) => BorrowUseInGenerator { var_span },
+                        None => BorrowUseInClosure { var_span },
+                    }
+                });
 
                 self.buffer_error(err);
 
@@ -2396,11 +2444,13 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
 
         let mut err = self.cannot_assign_to_borrowed(span, loan_span, &descr_place);
 
-        loan_spans.var_span_label(
-            &mut err,
-            format!("borrow occurs due to use{}", loan_spans.describe()),
-            loan.kind.describe_mutability(),
-        );
+        loan_spans.var_subdiag(None, &mut err, Some(loan.kind), |kind, var_span| {
+            use crate::session_diagnostics::CaptureVarCause::*;
+            match kind {
+                Some(_) => BorrowUseInGenerator { var_span },
+                None => BorrowUseInClosure { var_span },
+            }
+        });
 
         self.explain_why_borrow_contains_point(location, loan, None).add_explanation_to_diagnostic(
             self.infcx.tcx,
diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs
index dd003b5b040..4a85df9f8c0 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mod.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs
@@ -1,5 +1,9 @@
 //! Borrow checker diagnostics.
 
+use crate::session_diagnostics::{
+    CaptureArgLabel, CaptureReasonLabel, CaptureReasonNote, CaptureReasonSuggest, CaptureVarCause,
+    CaptureVarKind, CaptureVarPathUseCause, OnClosureNote,
+};
 use itertools::Itertools;
 use rustc_errors::{Applicability, Diagnostic};
 use rustc_hir as hir;
@@ -117,13 +121,15 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                     if let ty::Closure(did, _) = self.body.local_decls[closure].ty.kind() {
                         let did = did.expect_local();
                         if let Some((span, hir_place)) = self.infcx.tcx.closure_kind_origin(did) {
-                            diag.span_note(
-                                *span,
-                                &format!(
-                                    "closure cannot be invoked more than once because it moves the \
-                                    variable `{}` out of its environment",
-                                    ty::place_to_string_for_capture(self.infcx.tcx, hir_place)
-                                ),
+                            diag.eager_subdiagnostic(
+                                &self.infcx.tcx.sess.parse_sess.span_diagnostic,
+                                OnClosureNote::InvokedTwice {
+                                    place_name: &ty::place_to_string_for_capture(
+                                        self.infcx.tcx,
+                                        hir_place,
+                                    ),
+                                    span: *span,
+                                },
                             );
                             return true;
                         }
@@ -137,13 +143,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             if let ty::Closure(did, _) = self.body.local_decls[target].ty.kind() {
                 let did = did.expect_local();
                 if let Some((span, hir_place)) = self.infcx.tcx.closure_kind_origin(did) {
-                    diag.span_note(
-                        *span,
-                        &format!(
-                            "closure cannot be moved more than once as it is not `Copy` due to \
-                             moving the variable `{}` out of its environment",
-                            ty::place_to_string_for_capture(self.infcx.tcx, hir_place)
-                        ),
+                    diag.eager_subdiagnostic(
+                        &self.infcx.tcx.sess.parse_sess.span_diagnostic,
+                        OnClosureNote::MovedTwice {
+                            place_name: &ty::place_to_string_for_capture(self.infcx.tcx, hir_place),
+                            span: *span,
+                        },
                     );
                     return true;
                 }
@@ -380,25 +385,6 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         }
     }
 
-    /// Add a note that a type does not implement `Copy`
-    pub(super) fn note_type_does_not_implement_copy(
-        &self,
-        err: &mut Diagnostic,
-        place_desc: &str,
-        ty: Ty<'tcx>,
-        span: Option<Span>,
-        move_prefix: &str,
-    ) {
-        let message = format!(
-            "{move_prefix}move occurs because {place_desc} has type `{ty}`, which does not implement the `Copy` trait",
-        );
-        if let Some(span) = span {
-            err.span_label(span, message);
-        } else {
-            err.note(&message);
-        }
-    }
-
     pub(super) fn borrowed_content_source(
         &self,
         deref_base: PlaceRef<'tcx>,
@@ -582,9 +568,13 @@ impl UseSpans<'_> {
     }
 
     /// Add a span label to the arguments of the closure, if it exists.
-    pub(super) fn args_span_label(self, err: &mut Diagnostic, message: impl Into<String>) {
+    pub(super) fn args_subdiag(
+        self,
+        err: &mut Diagnostic,
+        f: impl FnOnce(Span) -> CaptureArgLabel,
+    ) {
         if let UseSpans::ClosureUse { args_span, .. } = self {
-            err.span_label(args_span, message);
+            err.subdiagnostic(f(args_span));
         }
     }
 
@@ -595,8 +585,8 @@ impl UseSpans<'_> {
         err: &mut Diagnostic,
         action: crate::InitializationRequiringAction,
     ) {
-        use crate::session_diagnostics::CaptureVarPathUseCause::*;
         use crate::InitializationRequiringAction::*;
+        use CaptureVarPathUseCause::*;
         if let UseSpans::ClosureUse { generator_kind, path_span, .. } = self {
             match generator_kind {
                 Some(_) => {
@@ -619,34 +609,14 @@ impl UseSpans<'_> {
         }
     }
 
-    /// Add a span label to the use of the captured variable, if it exists.
-    pub(super) fn var_span_label(
-        self,
-        err: &mut Diagnostic,
-        message: impl Into<String>,
-        kind_desc: impl Into<String>,
-    ) {
-        if let UseSpans::ClosureUse { capture_kind_span, path_span, .. } = self {
-            if capture_kind_span == path_span {
-                err.span_label(capture_kind_span, message);
-            } else {
-                let capture_kind_label =
-                    format!("capture is {} because of use here", kind_desc.into());
-                let path_label = message;
-                err.span_label(capture_kind_span, capture_kind_label);
-                err.span_label(path_span, path_label);
-            }
-        }
-    }
-
     /// Add a subdiagnostic to the use of the captured variable, if it exists.
     pub(super) fn var_subdiag(
         self,
+        handler: Option<&rustc_errors::Handler>,
         err: &mut Diagnostic,
         kind: Option<rustc_middle::mir::BorrowKind>,
-        f: impl Fn(Option<GeneratorKind>, Span) -> crate::session_diagnostics::CaptureVarCause,
+        f: impl FnOnce(Option<GeneratorKind>, Span) -> CaptureVarCause,
     ) {
-        use crate::session_diagnostics::CaptureVarKind::*;
         if let UseSpans::ClosureUse { generator_kind, capture_kind_span, path_span, .. } = self {
             if capture_kind_span != path_span {
                 err.subdiagnostic(match kind {
@@ -654,17 +624,21 @@ impl UseSpans<'_> {
                         rustc_middle::mir::BorrowKind::Shared
                         | rustc_middle::mir::BorrowKind::Shallow
                         | rustc_middle::mir::BorrowKind::Unique => {
-                            Immute { kind_span: capture_kind_span }
+                            CaptureVarKind::Immut { kind_span: capture_kind_span }
                         }
 
                         rustc_middle::mir::BorrowKind::Mut { .. } => {
-                            Mut { kind_span: capture_kind_span }
+                            CaptureVarKind::Mut { kind_span: capture_kind_span }
                         }
                     },
-                    None => Move { kind_span: capture_kind_span },
+                    None => CaptureVarKind::Move { kind_span: capture_kind_span },
                 });
             };
-            err.subdiagnostic(f(generator_kind, path_span));
+            let diag = f(generator_kind, path_span);
+            match handler {
+                Some(hd) => err.eager_subdiagnostic(hd, diag),
+                None => err.subdiagnostic(diag),
+            };
         }
     }
 
@@ -684,20 +658,6 @@ impl UseSpans<'_> {
         }
     }
 
-    /// Describe the span associated with a use of a place.
-    pub(super) fn describe(&self) -> &str {
-        match *self {
-            UseSpans::ClosureUse { generator_kind, .. } => {
-                if generator_kind.is_some() {
-                    " in generator"
-                } else {
-                    " in closure"
-                }
-            }
-            _ => "",
-        }
-    }
-
     pub(super) fn or_else<F>(self, if_other: F) -> Self
     where
         F: FnOnce() -> Self,
@@ -788,6 +748,15 @@ impl<'tcx> BorrowedContentSource<'tcx> {
     }
 }
 
+///helper struct for explain_captures()
+struct CapturedMessageOpt {
+    is_partial_move: bool,
+    is_loop_message: bool,
+    is_move_msg: bool,
+    is_loop_move: bool,
+    maybe_reinitialized_locations_is_empty: bool,
+}
+
 impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
     /// Finds the spans associated to a move or copy of move_place at location.
     pub(super) fn move_spans(
@@ -1027,12 +996,15 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         move_span: Span,
         move_spans: UseSpans<'tcx>,
         moved_place: Place<'tcx>,
-        partially_str: &str,
-        loop_message: &str,
-        move_msg: &str,
-        is_loop_move: bool,
-        maybe_reinitialized_locations_is_empty: bool,
+        msg_opt: CapturedMessageOpt,
     ) {
+        let CapturedMessageOpt {
+            is_partial_move: is_partial,
+            is_loop_message,
+            is_move_msg,
+            is_loop_move,
+            maybe_reinitialized_locations_is_empty,
+        } = msg_opt;
         if let UseSpans::FnSelfUse { var_span, fn_call_span, fn_span, kind } = move_spans {
             let place_name = self
                 .describe_place(moved_place.as_ref())
@@ -1042,30 +1014,26 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                 CallKind::FnCall { fn_trait_id, .. }
                     if Some(fn_trait_id) == self.infcx.tcx.lang_items().fn_once_trait() =>
                 {
-                    err.span_label(
+                    err.subdiagnostic(CaptureReasonLabel::Call {
                         fn_call_span,
-                        &format!(
-                            "{place_name} {partially_str}moved due to this call{loop_message}",
-                        ),
-                    );
-                    err.span_note(
-                        var_span,
-                        "this value implements `FnOnce`, which causes it to be moved when called",
-                    );
+                        place_name: &place_name,
+                        is_partial,
+                        is_loop_message,
+                    });
+                    err.subdiagnostic(CaptureReasonNote::FnOnceMoveInCall { var_span });
                 }
                 CallKind::Operator { self_arg, .. } => {
                     let self_arg = self_arg.unwrap();
-                    err.span_label(
+                    err.subdiagnostic(CaptureReasonLabel::OperatorUse {
                         fn_call_span,
-                        &format!(
-                            "{place_name} {partially_str}moved due to usage in operator{loop_message}",
-                        ),
-                    );
+                        place_name: &place_name,
+                        is_partial,
+                        is_loop_message,
+                    });
                     if self.fn_self_span_reported.insert(fn_span) {
-                        err.span_note(
-                            self_arg.span,
-                            "calling this operator moves the left-hand side",
-                        );
+                        err.subdiagnostic(CaptureReasonNote::LhsMoveByOperator {
+                            span: self_arg.span,
+                        });
                     }
                 }
                 CallKind::Normal { self_arg, desugaring, method_did, method_substs } => {
@@ -1086,23 +1054,18 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                             _ => false,
                         };
                         if suggest {
-                            err.span_suggestion_verbose(
-                                move_span.shrink_to_lo(),
-                                &format!(
-                                    "consider iterating over a slice of the `{ty}`'s content to \
-                                     avoid moving into the `for` loop",
-                                ),
-                                "&",
-                                Applicability::MaybeIncorrect,
-                            );
+                            err.subdiagnostic(CaptureReasonSuggest::IterateSlice {
+                                ty,
+                                span: move_span.shrink_to_lo(),
+                            });
                         }
 
-                        err.span_label(
+                        err.subdiagnostic(CaptureReasonLabel::ImplicitCall {
                             fn_call_span,
-                            &format!(
-                                "{place_name} {partially_str}moved due to this implicit call to `.into_iter()`{loop_message}",
-                            ),
-                        );
+                            place_name: &place_name,
+                            is_partial,
+                            is_loop_message,
+                        });
                         // If the moved place was a `&mut` ref, then we can
                         // suggest to reborrow it where it was moved, so it
                         // will still be valid by the time we get to the usage.
@@ -1125,13 +1088,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                             }
                         }
                     } else {
-                        err.span_label(
+                        err.subdiagnostic(CaptureReasonLabel::MethodCall {
                             fn_call_span,
-                            &format!(
-                                "{place_name} {partially_str}moved due to this method call{loop_message}",
-                            ),
-                        );
-
+                            place_name: &place_name,
+                            is_partial,
+                            is_loop_message,
+                        });
                         let infcx = tcx.infer_ctxt().build();
                         // Erase and shadow everything that could be passed to the new infcx.
                         let ty = tcx.erase_regions(moved_place.ty(self.body, tcx).ty);
@@ -1147,12 +1109,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                             )
                             && infcx.can_eq(self.param_env, ty, self_ty)
                         {
-                            err.span_suggestion_verbose(
-                                fn_call_span.shrink_to_lo(),
-                                "consider reborrowing the `Pin` instead of moving it",
-                                "as_mut().".to_string(),
-                                Applicability::MaybeIncorrect,
-                            );
+                            err.eager_subdiagnostic(
+                                &self.infcx.tcx.sess.parse_sess.span_diagnostic,
+                                CaptureReasonSuggest::FreshReborrow {
+                                    span: fn_call_span.shrink_to_lo(),
+                                });
                         }
                         if let Some(clone_trait) = tcx.lang_items().clone_trait()
                             && let trait_ref = tcx.mk_trait_ref(clone_trait, [ty])
@@ -1177,10 +1138,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                     // error messages.
                     if span != DUMMY_SP && self.fn_self_span_reported.insert(self_arg.span) {
                         let func = tcx.def_path_str(method_did);
-                        err.span_note(
-                            self_arg.span,
-                            &format!("`{func}` takes ownership of the receiver `self`, which moves {place_name}")
-                        );
+                        err.subdiagnostic(CaptureReasonNote::FuncTakeSelf {
+                            func,
+                            place_name,
+                            span: self_arg.span,
+                        });
                     }
                     let parent_did = tcx.parent(method_did);
                     let parent_self_ty =
@@ -1194,30 +1156,28 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                         matches!(tcx.get_diagnostic_name(def_id), Some(sym::Option | sym::Result))
                     });
                     if is_option_or_result && maybe_reinitialized_locations_is_empty {
-                        err.span_label(
-                            var_span,
-                            "help: consider calling `.as_ref()` or `.as_mut()` to borrow the type's contents",
-                        );
+                        err.subdiagnostic(CaptureReasonLabel::BorrowContent { var_span });
                     }
                 }
                 // Other desugarings takes &self, which cannot cause a move
                 _ => {}
             }
         } else {
-            if move_span != span || !loop_message.is_empty() {
-                err.span_label(
+            if move_span != span || is_loop_message {
+                err.subdiagnostic(CaptureReasonLabel::MovedHere {
                     move_span,
-                    format!("value {partially_str}moved{move_msg} here{loop_message}"),
-                );
+                    is_partial,
+                    is_move_msg,
+                    is_loop_message,
+                });
             }
             // If the move error occurs due to a loop, don't show
             // another message for the same span
-            if loop_message.is_empty() {
-                move_spans.var_span_label(
-                    err,
-                    format!("variable {partially_str}moved due to use{}", move_spans.describe()),
-                    "moved",
-                );
+            if !is_loop_message {
+                move_spans.var_subdiag(None, err, None, |kind, var_span| match kind {
+                    Some(_) => CaptureVarCause::PartialMoveUseInGenerator { var_span, is_partial },
+                    None => CaptureVarCause::PartialMoveUseInClosure { var_span, is_partial },
+                })
             }
         }
     }
diff --git a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs
index 3662bec0c76..67af96a71e3 100644
--- a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs
@@ -6,6 +6,7 @@ use rustc_mir_dataflow::move_paths::{
 };
 use rustc_span::{BytePos, Span};
 
+use crate::diagnostics::CapturedMessageOpt;
 use crate::diagnostics::{DescribePlaceOpt, UseSpans};
 use crate::prefixes::PrefixSet;
 use crate::MirBorrowckCtxt;
@@ -397,10 +398,15 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
                 }
             }
         };
+        let msg_opt = CapturedMessageOpt {
+            is_partial_move: false,
+            is_loop_message: false,
+            is_move_msg: false,
+            is_loop_move: false,
+            maybe_reinitialized_locations_is_empty: true,
+        };
         if let Some(use_spans) = use_spans {
-            self.explain_captures(
-                &mut err, span, span, use_spans, move_place, "", "", "", false, true,
-            );
+            self.explain_captures(&mut err, span, span, use_spans, move_place, msg_opt);
         }
         err
     }
@@ -416,13 +422,12 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
                         None => "value".to_string(),
                     };
 
-                    self.note_type_does_not_implement_copy(
-                        err,
-                        &place_desc,
-                        place_ty,
-                        Some(span),
-                        "",
-                    );
+                    err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Label {
+                        is_partial_move: false,
+                        ty: place_ty,
+                        place: &place_desc,
+                        span,
+                    });
                 } else {
                     binds_to.sort();
                     binds_to.dedup();
@@ -444,9 +449,19 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
                     Some(desc) => format!("`{desc}`"),
                     None => "value".to_string(),
                 };
-                self.note_type_does_not_implement_copy(err, &place_desc, place_ty, Some(span), "");
+                err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Label {
+                    is_partial_move: false,
+                    ty: place_ty,
+                    place: &place_desc,
+                    span,
+                });
 
-                use_spans.args_span_label(err, format!("{place_desc} is moved here"));
+                use_spans.args_subdiag(err, |args_span| {
+                    crate::session_diagnostics::CaptureArgLabel::MoveOutPlace {
+                        place: place_desc,
+                        args_span,
+                    }
+                });
             }
         }
     }
@@ -534,13 +549,13 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
             }
 
             if binds_to.len() == 1 {
-                self.note_type_does_not_implement_copy(
-                    err,
-                    &format!("`{}`", self.local_names[*local].unwrap()),
-                    bind_to.ty,
-                    Some(binding_span),
-                    "",
-                );
+                let place_desc = &format!("`{}`", self.local_names[*local].unwrap());
+                err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Label {
+                    is_partial_move: false,
+                    ty: bind_to.ty,
+                    place: &place_desc,
+                    span: binding_span,
+                });
             }
         }
 
diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
index 9c907147e5a..e3d81194ac8 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
@@ -231,14 +231,18 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
                     }
                 }
                 if suggest {
-                    borrow_spans.var_span_label(
-                        &mut err,
-                        format!(
-                            "mutable borrow occurs due to use of {} in closure",
-                            self.describe_any_place(access_place.as_ref()),
-                        ),
-                        "mutable",
-                    );
+                    borrow_spans.var_subdiag(
+                    None,
+                    &mut err,
+                    Some(mir::BorrowKind::Mut { allow_two_phase_borrow: false }),
+                    |_kind, var_span| {
+                        let place = self.describe_any_place(access_place.as_ref());
+                        crate::session_diagnostics::CaptureVarCause::MutableBorrowUsePlaceClosure {
+                            place,
+                            var_span,
+                        }
+                    },
+                );
                 }
                 borrow_span
             }
@@ -1143,7 +1147,7 @@ pub fn mut_borrow_of_mutable_ref(local_decl: &LocalDecl<'_>, local_name: Option<
             // suggest removing the `&mut`.
             //
             // Deliberately fall into this case for all implicit self types,
-            // so that we don't fall in to the next case with them.
+            // so that we don't fall into the next case with them.
             kind == hir::ImplicitSelfKind::MutRef
         }
         _ if Some(kw::SelfLower) == local_name => {
@@ -1231,7 +1235,7 @@ fn suggest_ampmut<'tcx>(
         }
     }
 
-    let (suggestability, highlight_span) = match opt_ty_info {
+    let (suggestibility, highlight_span) = match opt_ty_info {
         // if this is a variable binding with an explicit type,
         // try to highlight that for the suggestion.
         Some(ty_span) => (true, ty_span),
@@ -1252,7 +1256,7 @@ fn suggest_ampmut<'tcx>(
     let ty_mut = local_decl.ty.builtin_deref(true).unwrap();
     assert_eq!(ty_mut.mutbl, hir::Mutability::Not);
     (
-        suggestability,
+        suggestibility,
         highlight_span,
         if local_decl.ty.is_ref() {
             format!("&mut {}", ty_mut.ty)
diff --git a/compiler/rustc_borrowck/src/diagnostics/var_name.rs b/compiler/rustc_borrowck/src/diagnostics/var_name.rs
index 376415e3d32..aa7cf3578ea 100644
--- a/compiler/rustc_borrowck/src/diagnostics/var_name.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/var_name.rs
@@ -3,7 +3,7 @@
 
 use crate::region_infer::RegionInferenceContext;
 use crate::Upvar;
-use rustc_index::vec::{Idx, IndexSlice};
+use rustc_index::vec::IndexSlice;
 use rustc_middle::mir::{Body, Local};
 use rustc_middle::ty::{RegionVid, TyCtxt};
 use rustc_span::source_map::Span;
@@ -117,7 +117,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         argument_index: usize,
     ) -> (Option<Symbol>, Span) {
         let implicit_inputs = self.universal_regions().defining_ty.implicit_inputs();
-        let argument_local = Local::new(implicit_inputs + argument_index + 1);
+        let argument_local = Local::from_usize(implicit_inputs + argument_index + 1);
         debug!("get_argument_name_and_span_for_region: argument_local={argument_local:?}");
 
         let argument_name = local_names[argument_local];
diff --git a/compiler/rustc_borrowck/src/facts.rs b/compiler/rustc_borrowck/src/facts.rs
index 02ffb51fbb7..87fad9a355d 100644
--- a/compiler/rustc_borrowck/src/facts.rs
+++ b/compiler/rustc_borrowck/src/facts.rs
@@ -4,7 +4,6 @@ use crate::location::{LocationIndex, LocationTable};
 use crate::BorrowIndex;
 use polonius_engine::AllFacts as PoloniusFacts;
 use polonius_engine::Atom;
-use rustc_index::vec::Idx;
 use rustc_middle::mir::Local;
 use rustc_middle::ty::{RegionVid, TyCtxt};
 use rustc_mir_dataflow::move_paths::MovePathIndex;
@@ -93,13 +92,13 @@ impl AllFactsExt for AllFacts {
 
 impl Atom for BorrowIndex {
     fn index(self) -> usize {
-        Idx::index(self)
+        self.as_usize()
     }
 }
 
 impl Atom for LocationIndex {
     fn index(self) -> usize {
-        Idx::index(self)
+        self.as_usize()
     }
 }
 
diff --git a/compiler/rustc_borrowck/src/location.rs b/compiler/rustc_borrowck/src/location.rs
index 288b7d85be2..08fa912f368 100644
--- a/compiler/rustc_borrowck/src/location.rs
+++ b/compiler/rustc_borrowck/src/location.rs
@@ -1,6 +1,6 @@
 #![deny(rustc::untranslatable_diagnostic)]
 #![deny(rustc::diagnostic_outside_of_impl)]
-use rustc_index::vec::{Idx, IndexVec};
+use rustc_index::vec::IndexVec;
 use rustc_middle::mir::{BasicBlock, Body, Location};
 
 /// Maps between a MIR Location, which identifies a particular
@@ -50,19 +50,19 @@ impl LocationTable {
     }
 
     pub fn all_points(&self) -> impl Iterator<Item = LocationIndex> {
-        (0..self.num_points).map(LocationIndex::new)
+        (0..self.num_points).map(LocationIndex::from_usize)
     }
 
     pub fn start_index(&self, location: Location) -> LocationIndex {
         let Location { block, statement_index } = location;
         let start_index = self.statements_before_block[block];
-        LocationIndex::new(start_index + statement_index * 2)
+        LocationIndex::from_usize(start_index + statement_index * 2)
     }
 
     pub fn mid_index(&self, location: Location) -> LocationIndex {
         let Location { block, statement_index } = location;
         let start_index = self.statements_before_block[block];
-        LocationIndex::new(start_index + statement_index * 2 + 1)
+        LocationIndex::from_usize(start_index + statement_index * 2 + 1)
     }
 
     pub fn to_location(&self, index: LocationIndex) -> RichLocation {
diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs
index 59a3ab3189d..73b8765e57d 100644
--- a/compiler/rustc_borrowck/src/nll.rs
+++ b/compiler/rustc_borrowck/src/nll.rs
@@ -7,8 +7,8 @@ use rustc_hir::def_id::LocalDefId;
 use rustc_index::vec::IndexSlice;
 use rustc_middle::mir::{create_dump_file, dump_enabled, dump_mir, PassWhere};
 use rustc_middle::mir::{
-    BasicBlock, Body, ClosureOutlivesSubject, ClosureRegionRequirements, LocalKind, Location,
-    Promoted,
+    Body, ClosureOutlivesSubject, ClosureRegionRequirements, LocalKind, Location, Promoted,
+    START_BLOCK,
 };
 use rustc_middle::ty::{self, OpaqueHiddenType, TyCtxt};
 use rustc_span::symbol::sym;
@@ -94,8 +94,8 @@ fn populate_polonius_move_facts(
         }
     }
 
-    let fn_entry_start = location_table
-        .start_index(Location { block: BasicBlock::from_u32(0u32), statement_index: 0 });
+    let fn_entry_start =
+        location_table.start_index(Location { block: START_BLOCK, statement_index: 0 });
 
     // initialized_at
     for init in move_data.inits.iter() {
diff --git a/compiler/rustc_borrowck/src/session_diagnostics.rs b/compiler/rustc_borrowck/src/session_diagnostics.rs
index a3678929099..bb95101845f 100644
--- a/compiler/rustc_borrowck/src/session_diagnostics.rs
+++ b/compiler/rustc_borrowck/src/session_diagnostics.rs
@@ -184,7 +184,7 @@ pub(crate) enum CaptureVarPathUseCause {
 #[derive(Subdiagnostic)]
 pub(crate) enum CaptureVarKind {
     #[label(borrowck_capture_immute)]
-    Immute {
+    Immut {
         #[primary_span]
         kind_span: Span,
     },
@@ -204,16 +204,80 @@ pub(crate) enum CaptureVarKind {
 pub(crate) enum CaptureVarCause {
     #[label(borrowck_var_borrow_by_use_place_in_generator)]
     BorrowUsePlaceGenerator {
+        is_single_var: bool,
         place: String,
         #[primary_span]
         var_span: Span,
     },
     #[label(borrowck_var_borrow_by_use_place_in_closure)]
     BorrowUsePlaceClosure {
+        is_single_var: bool,
         place: String,
         #[primary_span]
         var_span: Span,
     },
+    #[label(borrowck_var_borrow_by_use_in_generator)]
+    BorrowUseInGenerator {
+        #[primary_span]
+        var_span: Span,
+    },
+    #[label(borrowck_var_borrow_by_use_in_closure)]
+    BorrowUseInClosure {
+        #[primary_span]
+        var_span: Span,
+    },
+    #[label(borrowck_var_move_by_use_in_generator)]
+    MoveUseInGenerator {
+        #[primary_span]
+        var_span: Span,
+    },
+    #[label(borrowck_var_move_by_use_in_closure)]
+    MoveUseInClosure {
+        #[primary_span]
+        var_span: Span,
+    },
+    #[label(borrowck_var_first_borrow_by_use_place_in_generator)]
+    FirstBorrowUsePlaceGenerator {
+        place: String,
+        #[primary_span]
+        var_span: Span,
+    },
+    #[label(borrowck_var_first_borrow_by_use_place_in_closure)]
+    FirstBorrowUsePlaceClosure {
+        place: String,
+        #[primary_span]
+        var_span: Span,
+    },
+    #[label(borrowck_var_second_borrow_by_use_place_in_generator)]
+    SecondBorrowUsePlaceGenerator {
+        place: String,
+        #[primary_span]
+        var_span: Span,
+    },
+    #[label(borrowck_var_second_borrow_by_use_place_in_closure)]
+    SecondBorrowUsePlaceClosure {
+        place: String,
+        #[primary_span]
+        var_span: Span,
+    },
+    #[label(borrowck_var_mutable_borrow_by_use_place_in_closure)]
+    MutableBorrowUsePlaceClosure {
+        place: String,
+        #[primary_span]
+        var_span: Span,
+    },
+    #[label(borrowck_partial_var_move_by_use_in_generator)]
+    PartialMoveUseInGenerator {
+        #[primary_span]
+        var_span: Span,
+        is_partial: bool,
+    },
+    #[label(borrowck_partial_var_move_by_use_in_closure)]
+    PartialMoveUseInClosure {
+        #[primary_span]
+        var_span: Span,
+        is_partial: bool,
+    },
 }
 
 #[derive(Diagnostic)]
@@ -239,3 +303,144 @@ pub(crate) struct NonGenericOpaqueTypeParam<'a, 'tcx> {
     #[label]
     pub param_span: Span,
 }
+
+#[derive(Subdiagnostic)]
+pub(crate) enum CaptureReasonLabel<'a> {
+    #[label(borrowck_moved_due_to_call)]
+    Call {
+        #[primary_span]
+        fn_call_span: Span,
+        place_name: &'a str,
+        is_partial: bool,
+        is_loop_message: bool,
+    },
+    #[label(borrowck_moved_due_to_usage_in_operator)]
+    OperatorUse {
+        #[primary_span]
+        fn_call_span: Span,
+        place_name: &'a str,
+        is_partial: bool,
+        is_loop_message: bool,
+    },
+    #[label(borrowck_moved_due_to_implicit_into_iter_call)]
+    ImplicitCall {
+        #[primary_span]
+        fn_call_span: Span,
+        place_name: &'a str,
+        is_partial: bool,
+        is_loop_message: bool,
+    },
+    #[label(borrowck_moved_due_to_method_call)]
+    MethodCall {
+        #[primary_span]
+        fn_call_span: Span,
+        place_name: &'a str,
+        is_partial: bool,
+        is_loop_message: bool,
+    },
+    #[label(borrowck_value_moved_here)]
+    MovedHere {
+        #[primary_span]
+        move_span: Span,
+        is_partial: bool,
+        is_move_msg: bool,
+        is_loop_message: bool,
+    },
+    #[label(borrowck_consider_borrow_type_contents)]
+    BorrowContent {
+        #[primary_span]
+        var_span: Span,
+    },
+}
+
+#[derive(Subdiagnostic)]
+pub(crate) enum CaptureReasonNote {
+    #[note(borrowck_moved_a_fn_once_in_call)]
+    FnOnceMoveInCall {
+        #[primary_span]
+        var_span: Span,
+    },
+    #[note(borrowck_calling_operator_moves_lhs)]
+    LhsMoveByOperator {
+        #[primary_span]
+        span: Span,
+    },
+    #[note(borrowck_func_take_self_moved_place)]
+    FuncTakeSelf {
+        func: String,
+        place_name: String,
+        #[primary_span]
+        span: Span,
+    },
+}
+
+#[derive(Subdiagnostic)]
+pub(crate) enum CaptureReasonSuggest<'tcx> {
+    #[suggestion(
+        borrowck_suggest_iterate_over_slice,
+        applicability = "maybe-incorrect",
+        code = "&",
+        style = "verbose"
+    )]
+    IterateSlice {
+        ty: Ty<'tcx>,
+        #[primary_span]
+        span: Span,
+    },
+    #[suggestion(
+        borrowck_suggest_create_freash_reborrow,
+        applicability = "maybe-incorrect",
+        code = "as_mut().",
+        style = "verbose"
+    )]
+    FreshReborrow {
+        #[primary_span]
+        span: Span,
+    },
+}
+
+#[derive(Subdiagnostic)]
+pub(crate) enum CaptureArgLabel {
+    #[label(borrowck_value_capture_here)]
+    Capture {
+        is_within: bool,
+        #[primary_span]
+        args_span: Span,
+    },
+    #[label(borrowck_move_out_place_here)]
+    MoveOutPlace {
+        place: String,
+        #[primary_span]
+        args_span: Span,
+    },
+}
+
+#[derive(Subdiagnostic)]
+pub(crate) enum OnClosureNote<'a> {
+    #[note(borrowck_closure_invoked_twice)]
+    InvokedTwice {
+        place_name: &'a str,
+        #[primary_span]
+        span: Span,
+    },
+    #[note(borrowck_closure_moved_twice)]
+    MovedTwice {
+        place_name: &'a str,
+        #[primary_span]
+        span: Span,
+    },
+}
+
+#[derive(Subdiagnostic)]
+pub(crate) enum TypeNoCopy<'a, 'tcx> {
+    #[label(borrowck_ty_no_impl_copy)]
+    Label {
+        is_partial_move: bool,
+        ty: Ty<'tcx>,
+        place: &'a str,
+        #[primary_span]
+        span: Span,
+    },
+    #[note(borrowck_ty_no_impl_copy)]
+    Note { is_partial_move: bool, ty: Ty<'tcx>, place: &'a str },
+}
diff --git a/compiler/rustc_borrowck/src/type_check/input_output.rs b/compiler/rustc_borrowck/src/type_check/input_output.rs
index 17e702eb8c5..9250b8d3eaf 100644
--- a/compiler/rustc_borrowck/src/type_check/input_output.rs
+++ b/compiler/rustc_borrowck/src/type_check/input_output.rs
@@ -7,7 +7,6 @@
 //! `RETURN_PLACE` the MIR arguments) are always fully normalized (and
 //! contain revealed `impl Trait` values).
 
-use rustc_index::vec::Idx;
 use rustc_infer::infer::LateBoundRegionConversionTime;
 use rustc_middle::mir::*;
 use rustc_middle::ty::{self, Ty};
@@ -83,7 +82,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
             }
 
             // In MIR, argument N is stored in local N+1.
-            let local = Local::new(argument_index + 1);
+            let local = Local::from_usize(argument_index + 1);
 
             let mir_input_ty = body.local_decls[local].ty;
 
diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs
index 70fddb1057c..74241f722a6 100644
--- a/compiler/rustc_borrowck/src/universal_regions.rs
+++ b/compiler/rustc_borrowck/src/universal_regions.rs
@@ -19,7 +19,7 @@ use rustc_hir as hir;
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::lang_items::LangItem;
 use rustc_hir::BodyOwnerKind;
-use rustc_index::vec::{Idx, IndexVec};
+use rustc_index::vec::IndexVec;
 use rustc_infer::infer::NllRegionVariableOrigin;
 use rustc_middle::ty::fold::TypeFoldable;
 use rustc_middle::ty::{self, InlineConstSubsts, InlineConstSubstsParts, RegionVid, Ty, TyCtxt};
@@ -289,7 +289,7 @@ impl<'tcx> UniversalRegions<'tcx> {
     /// Returns an iterator over all the RegionVids corresponding to
     /// universally quantified free regions.
     pub fn universal_regions(&self) -> impl Iterator<Item = RegionVid> {
-        (FIRST_GLOBAL_INDEX..self.num_universals).map(RegionVid::new)
+        (FIRST_GLOBAL_INDEX..self.num_universals).map(RegionVid::from_usize)
     }
 
     /// Returns `true` if `r` is classified as an local region.
diff --git a/compiler/rustc_codegen_llvm/src/common.rs b/compiler/rustc_codegen_llvm/src/common.rs
index 4f8b5abd901..9127fba388b 100644
--- a/compiler/rustc_codegen_llvm/src/common.rs
+++ b/compiler/rustc_codegen_llvm/src/common.rs
@@ -10,7 +10,7 @@ use crate::value::Value;
 use rustc_ast::Mutability;
 use rustc_codegen_ssa::mir::place::PlaceRef;
 use rustc_codegen_ssa::traits::*;
-use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
+use rustc_data_structures::stable_hasher::{Hash128, HashStable, StableHasher};
 use rustc_hir::def_id::DefId;
 use rustc_middle::bug;
 use rustc_middle::mir::interpret::{ConstAllocation, GlobalAlloc, Scalar};
@@ -261,7 +261,7 @@ impl<'ll, 'tcx> ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> {
                             let hash = self.tcx.with_stable_hashing_context(|mut hcx| {
                                 let mut hasher = StableHasher::new();
                                 alloc.hash_stable(&mut hcx, &mut hasher);
-                                hasher.finish::<u128>()
+                                hasher.finish::<Hash128>()
                             });
                             llvm::set_value_name(value, format!("alloc_{hash:032x}").as_bytes());
                         }
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs b/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs
index ff2b005d757..aaf5dbd9930 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs
@@ -22,9 +22,9 @@ pub fn insert_reference_to_gdb_debug_scripts_section_global(bx: &mut Builder<'_,
             bx.const_bitcast(get_or_insert_gdb_debug_scripts_section_global(bx), bx.type_i8p());
         // Load just the first byte as that's all that's necessary to force
         // LLVM to keep around the reference to the global.
-        let volative_load_instruction = bx.volatile_load(bx.type_i8(), gdb_debug_scripts_section);
+        let volatile_load_instruction = bx.volatile_load(bx.type_i8(), gdb_debug_scripts_section);
         unsafe {
-            llvm::LLVMSetAlignment(volative_load_instruction, 1);
+            llvm::LLVMSetAlignment(volatile_load_instruction, 1);
         }
     }
 }
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs
index 69443b9b828..38ad42370d3 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs
@@ -62,7 +62,7 @@ const SINGLE_VARIANT_VIRTUAL_DISR: u64 = 0;
 
 /// In CPP-like mode, we generate a union with a field for each variant and an
 /// explicit tag field. The field of each variant has a struct type
-/// that encodes the discrimiant of the variant and it's data layout.
+/// that encodes the discriminant of the variant and it's data layout.
 /// The union also has a nested enumeration type that is only used for encoding
 /// variant names in an efficient way. Its enumerator values do _not_ correspond
 /// to the enum's discriminant values.
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
index d56c414cf65..56844c7951f 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
@@ -21,6 +21,7 @@ use rustc_codegen_ssa::debuginfo::type_names;
 use rustc_codegen_ssa::mir::debuginfo::{DebugScope, FunctionDebugContext, VariableKind};
 use rustc_codegen_ssa::traits::*;
 use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::stable_hasher::Hash128;
 use rustc_data_structures::sync::Lrc;
 use rustc_hir::def_id::{DefId, DefIdMap};
 use rustc_index::vec::IndexVec;
@@ -61,7 +62,7 @@ pub struct CodegenUnitDebugContext<'ll, 'tcx> {
     llcontext: &'ll llvm::Context,
     llmod: &'ll llvm::Module,
     builder: &'ll mut DIBuilder<'ll>,
-    created_files: RefCell<FxHashMap<Option<(u128, SourceFileHash)>, &'ll DIFile>>,
+    created_files: RefCell<FxHashMap<Option<(Hash128, SourceFileHash)>, &'ll DIFile>>,
 
     type_map: metadata::TypeMap<'ll, 'tcx>,
     namespace_map: RefCell<DefIdMap<&'ll DIScope>>,
diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs
index 3f77ea77eff..4926f4e50c4 100644
--- a/compiler/rustc_codegen_llvm/src/lib.rs
+++ b/compiler/rustc_codegen_llvm/src/lib.rs
@@ -69,7 +69,7 @@ mod declare;
 mod errors;
 mod intrinsic;
 
-// The following is a work around that replaces `pub mod llvm;` and that fixes issue 53912.
+// The following is a workaround that replaces `pub mod llvm;` and that fixes issue 53912.
 #[path = "llvm/mod.rs"]
 mod llvm_;
 pub mod llvm {
diff --git a/compiler/rustc_codegen_ssa/messages.ftl b/compiler/rustc_codegen_ssa/messages.ftl
index 243be0e1f70..85a96e3e89c 100644
--- a/compiler/rustc_codegen_ssa/messages.ftl
+++ b/compiler/rustc_codegen_ssa/messages.ftl
@@ -148,7 +148,7 @@ codegen_ssa_processing_dymutil_failed = processing debug info with `dsymutil` fa
 
 codegen_ssa_unable_to_run_dsymutil = unable to run `dsymutil`: {$error}
 
-codegen_ssa_stripping_debu_info_failed = stripping debug info with `{$util}` failed: {$status}
+codegen_ssa_stripping_debug_info_failed = stripping debug info with `{$util}` failed: {$status}
     .note = {$output}
 
 codegen_ssa_unable_to_run = unable to run `{$util}`: {$error}
diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs
index 2dda4cd1694..c80347448cb 100644
--- a/compiler/rustc_codegen_ssa/src/back/write.rs
+++ b/compiler/rustc_codegen_ssa/src/back/write.rs
@@ -872,7 +872,7 @@ fn execute_copy_from_cache_work_item<B: ExtraBackendMethods>(
     let load_from_incr_comp_dir = |output_path: PathBuf, saved_path: &str| {
         let source_file = in_incr_comp_dir(&incr_comp_session_dir, saved_path);
         debug!(
-            "copying pre-existing module `{}` from {:?} to {}",
+            "copying preexisting module `{}` from {:?} to {}",
             module.name,
             source_file,
             output_path.display()
diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
index 8542bab689d..9bfe426c007 100644
--- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
+++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
@@ -156,7 +156,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
                     None => {
                         // Unfortunately, unconditionally using `llvm.used` causes
                         // issues in handling `.init_array` with the gold linker,
-                        // but using `llvm.compiler.used` caused a nontrival amount
+                        // but using `llvm.compiler.used` caused a nontrivial amount
                         // of unintentional ecosystem breakage -- particularly on
                         // Mach-O targets.
                         //
diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
index f2469fde3b6..03f33d8d8aa 100644
--- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
+++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
@@ -12,7 +12,7 @@
 // * `"` is treated as the start of a string.
 
 use rustc_data_structures::fx::FxHashSet;
-use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
+use rustc_data_structures::stable_hasher::{Hash64, HashStable, StableHasher};
 use rustc_hir::def_id::DefId;
 use rustc_hir::definitions::{DefPathData, DefPathDataName, DisambiguatedDefPathData};
 use rustc_hir::{AsyncGeneratorKind, GeneratorKind, Mutability};
@@ -675,8 +675,7 @@ fn push_const_param<'tcx>(tcx: TyCtxt<'tcx>, ct: ty::Const<'tcx>, output: &mut S
                     hcx.while_hashing_spans(false, |hcx| {
                         ct.to_valtree().hash_stable(hcx, &mut hasher)
                     });
-                    let hash: u64 = hasher.finish();
-                    hash
+                    hasher.finish::<Hash64>()
                 });
 
                 if cpp_like_debuginfo(tcx) {
diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs
index 66e7e314f79..44931766678 100644
--- a/compiler/rustc_codegen_ssa/src/errors.rs
+++ b/compiler/rustc_codegen_ssa/src/errors.rs
@@ -424,7 +424,7 @@ pub struct UnableToRunDsymutil {
 }
 
 #[derive(Diagnostic)]
-#[diag(codegen_ssa_stripping_debu_info_failed)]
+#[diag(codegen_ssa_stripping_debug_info_failed)]
 #[note]
 pub struct StrippingDebugInfoFailed<'a> {
     pub util: &'a str,
diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs
index dd86977817f..a0a8246be15 100644
--- a/compiler/rustc_codegen_ssa/src/mir/block.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/block.rs
@@ -12,7 +12,6 @@ use crate::MemFlags;
 use rustc_ast as ast;
 use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
 use rustc_hir::lang_items::LangItem;
-use rustc_index::vec::Idx;
 use rustc_middle::mir::{self, AssertKind, SwitchTargets};
 use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, ValidityRequirement};
 use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths};
@@ -369,7 +368,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         if self.fn_abi.c_variadic {
             // The `VaList` "spoofed" argument is just after all the real arguments.
             let va_list_arg_idx = self.fn_abi.args.len();
-            match self.locals[mir::Local::new(1 + va_list_arg_idx)] {
+            match self.locals[mir::Local::from_usize(1 + va_list_arg_idx)] {
                 LocalRef::Place(va_list) => {
                     bx.va_end(va_list.llval);
                 }
diff --git a/compiler/rustc_const_eval/src/interpret/discriminant.rs b/compiler/rustc_const_eval/src/interpret/discriminant.rs
index 557e721249d..015a9beab83 100644
--- a/compiler/rustc_const_eval/src/interpret/discriminant.rs
+++ b/compiler/rustc_const_eval/src/interpret/discriminant.rs
@@ -211,18 +211,19 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                             let variant_index_relative = u32::try_from(variant_index_relative)
                                 .expect("we checked that this fits into a u32");
                             // Then computing the absolute variant idx should not overflow any more.
-                            let variant_index = variants_start
-                                .checked_add(variant_index_relative)
-                                .expect("overflow computing absolute variant idx");
-                            let variants_len = op
+                            let variant_index = VariantIdx::from_u32(
+                                variants_start
+                                    .checked_add(variant_index_relative)
+                                    .expect("overflow computing absolute variant idx"),
+                            );
+                            let variants = op
                                 .layout
                                 .ty
                                 .ty_adt_def()
                                 .expect("tagged layout for non adt")
-                                .variants()
-                                .len();
-                            assert!(usize::try_from(variant_index).unwrap() < variants_len);
-                            VariantIdx::from_u32(variant_index)
+                                .variants();
+                            assert!(variant_index < variants.next_index());
+                            variant_index
                         } else {
                             untagged_variant
                         }
diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs
index 26fb041b455..eada75ae391 100644
--- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs
+++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs
@@ -75,7 +75,7 @@ pub(crate) fn eval_nullary_intrinsic<'tcx>(
         }
         sym::type_id => {
             ensure_monomorphic_enough(tcx, tp_ty)?;
-            ConstValue::from_u64(tcx.type_id_hash(tp_ty))
+            ConstValue::from_u64(tcx.type_id_hash(tp_ty).as_u64())
         }
         sym::variant_count => match tp_ty.kind() {
             // Correctly handles non-monomorphic calls, so there is no need for ensure_monomorphic_enough.
diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs
index 93b5273e1b1..e06b634cdc3 100644
--- a/compiler/rustc_const_eval/src/interpret/validity.rs
+++ b/compiler/rustc_const_eval/src/interpret/validity.rs
@@ -784,7 +784,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
             Abi::Scalar(scalar_layout) => {
                 if !scalar_layout.is_uninit_valid() {
                     // There is something to check here.
-                    let scalar = self.read_scalar(op, "initiailized scalar value")?;
+                    let scalar = self.read_scalar(op, "initialized scalar value")?;
                     self.visit_scalar(scalar, scalar_layout)?;
                 }
             }
@@ -794,7 +794,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
                 // the other must be init.
                 if !a_layout.is_uninit_valid() && !b_layout.is_uninit_valid() {
                     let (a, b) =
-                        self.read_immediate(op, "initiailized scalar value")?.to_scalar_pair();
+                        self.read_immediate(op, "initialized scalar value")?.to_scalar_pair();
                     self.visit_scalar(a, a_layout)?;
                     self.visit_scalar(b, b_layout)?;
                 }
diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs
index d4bed97380b..8aee019e994 100644
--- a/compiler/rustc_const_eval/src/transform/validate.rs
+++ b/compiler/rustc_const_eval/src/transform/validate.rs
@@ -262,7 +262,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         // We sometimes have to use `defining_opaque_types` for subtyping
         // to succeed here and figuring out how exactly that should work
         // is annoying. It is harmless enough to just not validate anything
-        // in that case. We still check this after analysis as all opque
+        // in that case. We still check this after analysis as all opaque
         // types have been revealed at this point.
         if (src, dest).has_opaque_types() {
             return true;
diff --git a/compiler/rustc_data_structures/Cargo.toml b/compiler/rustc_data_structures/Cargo.toml
index 2102f09c56a..39f4bc63c88 100644
--- a/compiler/rustc_data_structures/Cargo.toml
+++ b/compiler/rustc_data_structures/Cargo.toml
@@ -21,7 +21,6 @@ rustc-hash = "1.1.0"
 rustc_index = { path = "../rustc_index", package = "rustc_index" }
 rustc_macros = { path = "../rustc_macros" }
 rustc_serialize = { path = "../rustc_serialize" }
-serde_json = "1.0.59"
 smallvec = { version = "1.8.1", features = [
     "const_generics",
     "union",
diff --git a/compiler/rustc_data_structures/src/aligned.rs b/compiler/rustc_data_structures/src/aligned.rs
new file mode 100644
index 00000000000..0e5ecfd9bff
--- /dev/null
+++ b/compiler/rustc_data_structures/src/aligned.rs
@@ -0,0 +1,33 @@
+use std::ptr::Alignment;
+
+/// Returns the ABI-required minimum alignment of a type in bytes.
+///
+/// This is equivalent to [`mem::align_of`], but also works for some unsized
+/// types (e.g. slices or rustc's `List`s).
+///
+/// [`mem::align_of`]: std::mem::align_of
+pub const fn align_of<T: ?Sized + Aligned>() -> Alignment {
+    T::ALIGN
+}
+
+/// A type with a statically known alignment.
+///
+/// # Safety
+///
+/// `Self::ALIGN` must be equal to the alignment of `Self`. For sized types it
+/// is [`mem::align_of<Self>()`], for unsized types it depends on the type, for
+/// example `[T]` has alignment of `T`.
+///
+/// [`mem::align_of<Self>()`]: std::mem::align_of
+pub unsafe trait Aligned {
+    /// Alignment of `Self`.
+    const ALIGN: Alignment;
+}
+
+unsafe impl<T> Aligned for T {
+    const ALIGN: Alignment = Alignment::of::<Self>();
+}
+
+unsafe impl<T> Aligned for [T] {
+    const ALIGN: Alignment = Alignment::of::<T>();
+}
diff --git a/compiler/rustc_data_structures/src/fingerprint.rs b/compiler/rustc_data_structures/src/fingerprint.rs
index b6e866f15ef..6fa76981408 100644
--- a/compiler/rustc_data_structures/src/fingerprint.rs
+++ b/compiler/rustc_data_structures/src/fingerprint.rs
@@ -1,4 +1,4 @@
-use crate::stable_hasher;
+use crate::stable_hasher::{Hash64, StableHasher, StableHasherResult};
 use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
 use std::hash::{Hash, Hasher};
 
@@ -9,32 +9,49 @@ mod tests;
 #[repr(C)]
 pub struct Fingerprint(u64, u64);
 
-impl Fingerprint {
-    pub const ZERO: Fingerprint = Fingerprint(0, 0);
+pub trait FingerprintComponent {
+    fn as_u64(&self) -> u64;
+}
 
+impl FingerprintComponent for Hash64 {
     #[inline]
-    pub fn new(_0: u64, _1: u64) -> Fingerprint {
-        Fingerprint(_0, _1)
+    fn as_u64(&self) -> u64 {
+        Hash64::as_u64(*self)
+    }
+}
+
+impl FingerprintComponent for u64 {
+    #[inline]
+    fn as_u64(&self) -> u64 {
+        *self
     }
+}
+
+impl Fingerprint {
+    pub const ZERO: Fingerprint = Fingerprint(0, 0);
 
     #[inline]
-    pub fn from_smaller_hash(hash: u64) -> Fingerprint {
-        Fingerprint(hash, hash)
+    pub fn new<A, B>(_0: A, _1: B) -> Fingerprint
+    where
+        A: FingerprintComponent,
+        B: FingerprintComponent,
+    {
+        Fingerprint(_0.as_u64(), _1.as_u64())
     }
 
     #[inline]
-    pub fn to_smaller_hash(&self) -> u64 {
+    pub fn to_smaller_hash(&self) -> Hash64 {
         // Even though both halves of the fingerprint are expected to be good
         // quality hash values, let's still combine the two values because the
         // Fingerprints in DefPathHash have the StableCrateId portion which is
         // the same for all DefPathHashes from the same crate. Combining the
         // two halves makes sure we get a good quality hash in such cases too.
-        self.0.wrapping_mul(3).wrapping_add(self.1)
+        Hash64::new(self.0.wrapping_mul(3).wrapping_add(self.1))
     }
 
     #[inline]
-    pub fn as_value(&self) -> (u64, u64) {
-        (self.0, self.1)
+    pub fn split(&self) -> (Hash64, Hash64) {
+        (Hash64::new(self.0), Hash64::new(self.1))
     }
 
     #[inline]
@@ -131,9 +148,9 @@ impl FingerprintHasher for crate::unhash::Unhasher {
     }
 }
 
-impl stable_hasher::StableHasherResult for Fingerprint {
+impl StableHasherResult for Fingerprint {
     #[inline]
-    fn finish(hasher: stable_hasher::StableHasher) -> Self {
+    fn finish(hasher: StableHasher) -> Self {
         let (_0, _1) = hasher.finalize();
         Fingerprint(_0, _1)
     }
diff --git a/compiler/rustc_data_structures/src/fingerprint/tests.rs b/compiler/rustc_data_structures/src/fingerprint/tests.rs
index 9b0783e33ab..09ec2622a65 100644
--- a/compiler/rustc_data_structures/src/fingerprint/tests.rs
+++ b/compiler/rustc_data_structures/src/fingerprint/tests.rs
@@ -1,11 +1,12 @@
 use super::*;
+use crate::stable_hasher::Hash64;
 
 // Check that `combine_commutative` is order independent.
 #[test]
 fn combine_commutative_is_order_independent() {
-    let a = Fingerprint::new(0xf6622fb349898b06, 0x70be9377b2f9c610);
-    let b = Fingerprint::new(0xa9562bf5a2a5303c, 0x67d9b6c82034f13d);
-    let c = Fingerprint::new(0x0d013a27811dbbc3, 0x9a3f7b3d9142ec43);
+    let a = Fingerprint::new(Hash64::new(0xf6622fb349898b06), Hash64::new(0x70be9377b2f9c610));
+    let b = Fingerprint::new(Hash64::new(0xa9562bf5a2a5303c), Hash64::new(0x67d9b6c82034f13d));
+    let c = Fingerprint::new(Hash64::new(0x0d013a27811dbbc3), Hash64::new(0x9a3f7b3d9142ec43));
     let permutations = [(a, b, c), (a, c, b), (b, a, c), (b, c, a), (c, a, b), (c, b, a)];
     let f = a.combine_commutative(b).combine_commutative(c);
     for p in &permutations {
diff --git a/compiler/rustc_data_structures/src/hashes.rs b/compiler/rustc_data_structures/src/hashes.rs
new file mode 100644
index 00000000000..ad068cdbc98
--- /dev/null
+++ b/compiler/rustc_data_structures/src/hashes.rs
@@ -0,0 +1,132 @@
+//! rustc encodes a lot of hashes. If hashes are stored as `u64` or `u128`, a `derive(Encodable)`
+//! will apply varint encoding to the hashes, which is less efficient than directly encoding the 8
+//! or 16 bytes of the hash.
+//!
+//! The types in this module represent 64-bit or 128-bit hashes produced by a `StableHasher`.
+//! `Hash64` and `Hash128` expose some utilty functions to encourage users to not extract the inner
+//! hash value as an integer type and accidentally apply varint encoding to it.
+//!
+//! In contrast with `Fingerprint`, users of these types cannot and should not attempt to construct
+//! and decompose these types into constitutent pieces. The point of these types is only to
+//! connect the fact that they can only be produced by a `StableHasher` to their
+//! `Encode`/`Decode` impls.
+
+use crate::stable_hasher::{StableHasher, StableHasherResult};
+use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
+use std::fmt;
+use std::ops::BitXorAssign;
+
+#[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Default)]
+pub struct Hash64 {
+    inner: u64,
+}
+
+impl Hash64 {
+    pub const ZERO: Hash64 = Hash64 { inner: 0 };
+
+    #[inline]
+    pub(crate) fn new(n: u64) -> Self {
+        Self { inner: n }
+    }
+
+    #[inline]
+    pub fn as_u64(self) -> u64 {
+        self.inner
+    }
+}
+
+impl BitXorAssign<u64> for Hash64 {
+    #[inline]
+    fn bitxor_assign(&mut self, rhs: u64) {
+        self.inner ^= rhs;
+    }
+}
+
+impl<S: Encoder> Encodable<S> for Hash64 {
+    #[inline]
+    fn encode(&self, s: &mut S) {
+        s.emit_raw_bytes(&self.inner.to_le_bytes());
+    }
+}
+
+impl<D: Decoder> Decodable<D> for Hash64 {
+    #[inline]
+    fn decode(d: &mut D) -> Self {
+        Self { inner: u64::from_le_bytes(d.read_raw_bytes(8).try_into().unwrap()) }
+    }
+}
+
+impl StableHasherResult for Hash64 {
+    #[inline]
+    fn finish(hasher: StableHasher) -> Self {
+        Self { inner: hasher.finalize().0 }
+    }
+}
+
+impl fmt::Debug for Hash64 {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        self.inner.fmt(f)
+    }
+}
+
+impl fmt::LowerHex for Hash64 {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        fmt::LowerHex::fmt(&self.inner, f)
+    }
+}
+
+#[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Default)]
+pub struct Hash128 {
+    inner: u128,
+}
+
+impl Hash128 {
+    #[inline]
+    pub fn truncate(self) -> Hash64 {
+        Hash64 { inner: self.inner as u64 }
+    }
+
+    #[inline]
+    pub fn wrapping_add(self, other: Self) -> Self {
+        Self { inner: self.inner.wrapping_add(other.inner) }
+    }
+
+    #[inline]
+    pub fn as_u128(self) -> u128 {
+        self.inner
+    }
+}
+
+impl<S: Encoder> Encodable<S> for Hash128 {
+    #[inline]
+    fn encode(&self, s: &mut S) {
+        s.emit_raw_bytes(&self.inner.to_le_bytes());
+    }
+}
+
+impl<D: Decoder> Decodable<D> for Hash128 {
+    #[inline]
+    fn decode(d: &mut D) -> Self {
+        Self { inner: u128::from_le_bytes(d.read_raw_bytes(16).try_into().unwrap()) }
+    }
+}
+
+impl StableHasherResult for Hash128 {
+    #[inline]
+    fn finish(hasher: StableHasher) -> Self {
+        let (_0, _1) = hasher.finalize();
+        Self { inner: u128::from(_0) | (u128::from(_1) << 64) }
+    }
+}
+
+impl fmt::Debug for Hash128 {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        self.inner.fmt(f)
+    }
+}
+
+impl fmt::LowerHex for Hash128 {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        fmt::LowerHex::fmt(&self.inner, f)
+    }
+}
diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs
index e373bd18402..405ae99395b 100644
--- a/compiler/rustc_data_structures/src/lib.rs
+++ b/compiler/rustc_data_structures/src/lib.rs
@@ -29,6 +29,8 @@
 #![feature(get_mut_unchecked)]
 #![feature(lint_reasons)]
 #![feature(unwrap_infallible)]
+#![feature(strict_provenance)]
+#![feature(ptr_alignment_type)]
 #![allow(rustc::default_hash_types)]
 #![allow(rustc::potential_query_instability)]
 #![deny(rustc::untranslatable_diagnostic)]
@@ -82,7 +84,9 @@ pub mod transitive_relation;
 pub mod vec_linked_list;
 pub mod work_queue;
 pub use atomic_ref::AtomicRef;
+pub mod aligned;
 pub mod frozen;
+mod hashes;
 pub mod owned_slice;
 pub mod sso;
 pub mod steal;
diff --git a/compiler/rustc_data_structures/src/profiling.rs b/compiler/rustc_data_structures/src/profiling.rs
index 1ed584eafad..572bd4ac21c 100644
--- a/compiler/rustc_data_structures/src/profiling.rs
+++ b/compiler/rustc_data_structures/src/profiling.rs
@@ -87,6 +87,7 @@ use crate::fx::FxHashMap;
 use std::borrow::Borrow;
 use std::collections::hash_map::Entry;
 use std::error::Error;
+use std::fmt::Display;
 use std::fs;
 use std::intrinsics::unlikely;
 use std::path::Path;
@@ -97,7 +98,6 @@ use std::time::{Duration, Instant};
 pub use measureme::EventId;
 use measureme::{EventIdBuilder, Profiler, SerializableString, StringId};
 use parking_lot::RwLock;
-use serde_json::json;
 use smallvec::SmallVec;
 
 bitflags::bitflags! {
@@ -557,7 +557,7 @@ impl SelfProfiler {
         let crate_name = crate_name.unwrap_or("unknown-crate");
         // HACK(eddyb) we need to pad the PID, strange as it may seem, as its
         // length can behave as a source of entropy for heap addresses, when
-        // ASLR is disabled and the heap is otherwise determinic.
+        // ASLR is disabled and the heap is otherwise deterministic.
         let pid: u32 = process::id();
         let filename = format!("{crate_name}-{pid:07}.rustc_profile");
         let path = output_directory.join(&filename);
@@ -763,6 +763,31 @@ impl Drop for VerboseTimingGuard<'_> {
     }
 }
 
+struct JsonTimePassesEntry<'a> {
+    pass: &'a str,
+    time: f64,
+    start_rss: Option<usize>,
+    end_rss: Option<usize>,
+}
+
+impl Display for JsonTimePassesEntry<'_> {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        let Self { pass: what, time, start_rss, end_rss } = self;
+        write!(f, r#"{{"pass":"{what}","time":{time},"rss_start":"#).unwrap();
+        match start_rss {
+            Some(rss) => write!(f, "{rss}")?,
+            None => write!(f, "null")?,
+        }
+        write!(f, r#","rss_end":"#)?;
+        match end_rss {
+            Some(rss) => write!(f, "{rss}")?,
+            None => write!(f, "null")?,
+        }
+        write!(f, "}}")?;
+        Ok(())
+    }
+}
+
 pub fn print_time_passes_entry(
     what: &str,
     dur: Duration,
@@ -772,13 +797,10 @@ pub fn print_time_passes_entry(
 ) {
     match format {
         TimePassesFormat::Json => {
-            let json = json!({
-                "pass": what,
-                "time": dur.as_secs_f64(),
-                "rss_start": start_rss,
-                "rss_end": end_rss,
-            });
-            eprintln!("time: {json}");
+            let entry =
+                JsonTimePassesEntry { pass: what, time: dur.as_secs_f64(), start_rss, end_rss };
+
+            eprintln!(r#"time: {entry}"#);
             return;
         }
         TimePassesFormat::Text => (),
@@ -894,3 +916,6 @@ cfg_if! {
         }
     }
 }
+
+#[cfg(test)]
+mod tests;
diff --git a/compiler/rustc_data_structures/src/profiling/tests.rs b/compiler/rustc_data_structures/src/profiling/tests.rs
new file mode 100644
index 00000000000..2b09de085da
--- /dev/null
+++ b/compiler/rustc_data_structures/src/profiling/tests.rs
@@ -0,0 +1,19 @@
+use super::JsonTimePassesEntry;
+
+#[test]
+fn with_rss() {
+    let entry =
+        JsonTimePassesEntry { pass: "typeck", time: 56.1, start_rss: Some(10), end_rss: Some(20) };
+
+    assert_eq!(entry.to_string(), r#"{"pass":"typeck","time":56.1,"rss_start":10,"rss_end":20}"#)
+}
+
+#[test]
+fn no_rss() {
+    let entry = JsonTimePassesEntry { pass: "typeck", time: 56.1, start_rss: None, end_rss: None };
+
+    assert_eq!(
+        entry.to_string(),
+        r#"{"pass":"typeck","time":56.1,"rss_start":null,"rss_end":null}"#
+    )
+}
diff --git a/compiler/rustc_data_structures/src/stable_hasher.rs b/compiler/rustc_data_structures/src/stable_hasher.rs
index 3ed1de1bc3c..b2bd0bfe714 100644
--- a/compiler/rustc_data_structures/src/stable_hasher.rs
+++ b/compiler/rustc_data_structures/src/stable_hasher.rs
@@ -2,6 +2,7 @@ use crate::sip128::SipHasher128;
 use rustc_index::bit_set;
 use rustc_index::vec;
 use smallvec::SmallVec;
+use std::fmt;
 use std::hash::{BuildHasher, Hash, Hasher};
 use std::marker::PhantomData;
 use std::mem;
@@ -9,6 +10,8 @@ use std::mem;
 #[cfg(test)]
 mod tests;
 
+pub use crate::hashes::{Hash128, Hash64};
+
 /// When hashing something that ends up affecting properties like symbol names,
 /// we want these symbol names to be calculated independently of other factors
 /// like what architecture you're compiling *from*.
@@ -20,8 +23,8 @@ pub struct StableHasher {
     state: SipHasher128,
 }
 
-impl ::std::fmt::Debug for StableHasher {
-    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+impl fmt::Debug for StableHasher {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         write!(f, "{:?}", self.state)
     }
 }
@@ -42,21 +45,6 @@ impl StableHasher {
     }
 }
 
-impl StableHasherResult for u128 {
-    #[inline]
-    fn finish(hasher: StableHasher) -> Self {
-        let (_0, _1) = hasher.finalize();
-        u128::from(_0) | (u128::from(_1) << 64)
-    }
-}
-
-impl StableHasherResult for u64 {
-    #[inline]
-    fn finish(hasher: StableHasher) -> Self {
-        hasher.finalize().0
-    }
-}
-
 impl StableHasher {
     #[inline]
     pub fn finalize(self) -> (u64, u64) {
@@ -107,7 +95,8 @@ impl Hasher for StableHasher {
 
     #[inline]
     fn write_u128(&mut self, i: u128) {
-        self.state.write(&i.to_le_bytes());
+        self.write_u64(i as u64);
+        self.write_u64((i >> 64) as u64);
     }
 
     #[inline]
@@ -286,6 +275,9 @@ impl_stable_traits_for_trivial_type!(i128);
 impl_stable_traits_for_trivial_type!(char);
 impl_stable_traits_for_trivial_type!(());
 
+impl_stable_traits_for_trivial_type!(Hash64);
+impl_stable_traits_for_trivial_type!(Hash128);
+
 impl<CTX> HashStable<CTX> for ! {
     fn hash_stable(&self, _ctx: &mut CTX, _hasher: &mut StableHasher) {
         unreachable!()
@@ -668,7 +660,7 @@ fn stable_hash_reduce<HCX, I, C, F>(
                 .map(|value| {
                     let mut hasher = StableHasher::new();
                     hash_function(&mut hasher, hcx, value);
-                    hasher.finish::<u128>()
+                    hasher.finish::<Hash128>()
                 })
                 .reduce(|accum, value| accum.wrapping_add(value));
             hash.hash_stable(hcx, hasher);
diff --git a/compiler/rustc_data_structures/src/stable_hasher/tests.rs b/compiler/rustc_data_structures/src/stable_hasher/tests.rs
index a98b1bc3626..c8921f6a778 100644
--- a/compiler/rustc_data_structures/src/stable_hasher/tests.rs
+++ b/compiler/rustc_data_structures/src/stable_hasher/tests.rs
@@ -72,7 +72,7 @@ fn test_hash_isize() {
     assert_eq!(h.finalize(), expected);
 }
 
-fn hash<T: HashStable<()>>(t: &T) -> u128 {
+fn hash<T: HashStable<()>>(t: &T) -> Hash128 {
     let mut h = StableHasher::new();
     let ctx = &mut ();
     t.hash_stable(ctx, &mut h);
diff --git a/compiler/rustc_data_structures/src/svh.rs b/compiler/rustc_data_structures/src/svh.rs
index b955df94f16..a3d2724fcdb 100644
--- a/compiler/rustc_data_structures/src/svh.rs
+++ b/compiler/rustc_data_structures/src/svh.rs
@@ -24,7 +24,7 @@ impl Svh {
     }
 
     pub fn as_u64(&self) -> u64 {
-        self.hash.to_smaller_hash()
+        self.hash.to_smaller_hash().as_u64()
     }
 
     pub fn to_string(&self) -> String {
diff --git a/compiler/rustc_data_structures/src/tagged_ptr.rs b/compiler/rustc_data_structures/src/tagged_ptr.rs
index 651bc556c98..c26bffac678 100644
--- a/compiler/rustc_data_structures/src/tagged_ptr.rs
+++ b/compiler/rustc_data_structures/src/tagged_ptr.rs
@@ -3,166 +3,262 @@
 //! In order to utilize the pointer packing, you must have two types: a pointer,
 //! and a tag.
 //!
-//! The pointer must implement the `Pointer` trait, with the primary requirement
-//! being conversion to and from a usize. Note that the pointer must be
-//! dereferenceable, so raw pointers generally cannot implement the `Pointer`
-//! trait. This implies that the pointer must also be nonzero.
+//! The pointer must implement the [`Pointer`] trait, with the primary
+//! requirement being convertible to and from a raw pointer. Note that the
+//! pointer must be dereferenceable, so raw pointers generally cannot implement
+//! the [`Pointer`] trait. This implies that the pointer must also be non-null.
 //!
-//! Many common pointer types already implement the `Pointer` trait.
+//! Many common pointer types already implement the [`Pointer`] trait.
 //!
-//! The tag must implement the `Tag` trait. We assert that the tag and `Pointer`
-//! are compatible at compile time.
+//! The tag must implement the [`Tag`] trait.
+//!
+//! We assert that the tag and the [`Pointer`] types are compatible at compile
+//! time.
 
-use std::mem::ManuallyDrop;
 use std::ops::Deref;
+use std::ptr::NonNull;
 use std::rc::Rc;
 use std::sync::Arc;
 
+use crate::aligned::Aligned;
+
 mod copy;
 mod drop;
 
 pub use copy::CopyTaggedPtr;
 pub use drop::TaggedPtr;
 
-/// This describes the pointer type encapsulated by TaggedPtr.
+/// This describes the pointer type encapsulated by [`TaggedPtr`] and
+/// [`CopyTaggedPtr`].
 ///
 /// # Safety
 ///
-/// The usize returned from `into_usize` must be a valid, dereferenceable,
-/// pointer to `<Self as Deref>::Target`. Note that pointers to `Pointee` must
-/// be thin, even though `Pointee` may not be sized.
+/// The pointer returned from [`into_ptr`] must be a [valid], pointer to
+/// [`<Self as Deref>::Target`].
 ///
-/// Note that the returned pointer from `into_usize` should be castable to `&mut
-/// <Self as Deref>::Target` if `Pointer: DerefMut`.
+/// Note that if `Self` implements [`DerefMut`] the pointer returned from
+/// [`into_ptr`] must be valid for writes (and thus calling [`NonNull::as_mut`]
+/// on it must be safe).
 ///
-/// The BITS constant must be correct. At least `BITS` bits, least-significant,
-/// must be zero on all returned pointers from `into_usize`.
+/// The [`BITS`] constant must be correct. [`BITS`] least-significant bits,
+/// must be zero on all pointers returned from [`into_ptr`].
 ///
-/// For example, if the alignment of `Pointee` is 2, then `BITS` should be 1.
+/// For example, if the alignment of [`Self::Target`] is 2, then `BITS` should be 1.
+///
+/// [`BITS`]: Pointer::BITS
+/// [`into_ptr`]: Pointer::into_ptr
+/// [valid]: std::ptr#safety
+/// [`<Self as Deref>::Target`]: Deref::Target
+/// [`Self::Target`]: Deref::Target
+/// [`DerefMut`]: std::ops::DerefMut
 pub unsafe trait Pointer: Deref {
+    /// Number of unused (always zero) **least-significant bits** in this
+    /// pointer, usually related to the pointees alignment.
+    ///
+    /// For example if [`BITS`] = `2`, then given `ptr = Self::into_ptr(..)`,
+    /// `ptr.addr() & 0b11 == 0` must be true.
+    ///
     /// Most likely the value you want to use here is the following, unless
-    /// your Pointee type is unsized (e.g., `ty::List<T>` in rustc) in which
-    /// case you'll need to manually figure out what the right type to pass to
-    /// align_of is.
+    /// your [`Self::Target`] type is unsized (e.g., `ty::List<T>` in rustc)
+    /// or your pointer is over/under aligned, in which case you'll need to
+    /// manually figure out what the right type to pass to [`bits_for`] is, or
+    /// what the value to set here.
     ///
-    /// ```ignore UNSOLVED (what to do about the Self)
+    /// ```rust
     /// # use std::ops::Deref;
-    /// std::mem::align_of::<<Self as Deref>::Target>().trailing_zeros() as usize;
+    /// # use rustc_data_structures::tagged_ptr::bits_for;
+    /// # struct T;
+    /// # impl Deref for T { type Target = u8; fn deref(&self) -> &u8 { &0 } }
+    /// # impl T {
+    /// const BITS: u32 = bits_for::<<Self as Deref>::Target>();
+    /// # }
     /// ```
-    const BITS: usize;
-    fn into_usize(self) -> usize;
+    ///
+    /// [`BITS`]: Pointer::BITS
+    /// [`Self::Target`]: Deref::Target
+    const BITS: u32;
 
-    /// # Safety
+    /// Turns this pointer into a raw, non-null pointer.
+    ///
+    /// The inverse of this function is [`from_ptr`].
     ///
-    /// The passed `ptr` must be returned from `into_usize`.
+    /// This function guarantees that the least-significant [`Self::BITS`] bits
+    /// are zero.
     ///
-    /// This acts as `ptr::read` semantically, it should not be called more than
-    /// once on non-`Copy` `Pointer`s.
-    unsafe fn from_usize(ptr: usize) -> Self;
+    /// [`from_ptr`]: Pointer::from_ptr
+    /// [`Self::BITS`]: Pointer::BITS
+    fn into_ptr(self) -> NonNull<Self::Target>;
 
-    /// This provides a reference to the `Pointer` itself, rather than the
-    /// `Deref::Target`. It is used for cases where we want to call methods that
-    /// may be implement differently for the Pointer than the Pointee (e.g.,
-    /// `Rc::clone` vs cloning the inner value).
+    /// Re-creates the original pointer, from a raw pointer returned by [`into_ptr`].
     ///
     /// # Safety
     ///
-    /// The passed `ptr` must be returned from `into_usize`.
-    unsafe fn with_ref<R, F: FnOnce(&Self) -> R>(ptr: usize, f: F) -> R;
+    /// The passed `ptr` must be returned from [`into_ptr`].
+    ///
+    /// This acts as [`ptr::read::<Self>()`] semantically, it should not be called more than
+    /// once on non-[`Copy`] `Pointer`s.
+    ///
+    /// [`into_ptr`]: Pointer::into_ptr
+    /// [`ptr::read::<Self>()`]: std::ptr::read
+    unsafe fn from_ptr(ptr: NonNull<Self::Target>) -> Self;
 }
 
-/// This describes tags that the `TaggedPtr` struct can hold.
+/// This describes tags that the [`TaggedPtr`] struct can hold.
 ///
 /// # Safety
 ///
-/// The BITS constant must be correct.
+/// The [`BITS`] constant must be correct.
+///
+/// No more than [`BITS`] least-significant bits may be set in the returned usize.
 ///
-/// No more than `BITS` least significant bits may be set in the returned usize.
+/// [`BITS`]: Tag::BITS
 pub unsafe trait Tag: Copy {
-    const BITS: usize;
+    /// Number of least-significant bits in the return value of [`into_usize`]
+    /// which may be non-zero. In other words this is the bit width of the
+    /// value.
+    ///
+    /// [`into_usize`]: Tag::into_usize
+    const BITS: u32;
 
+    /// Turns this tag into an integer.
+    ///
+    /// The inverse of this function is [`from_usize`].
+    ///
+    /// This function guarantees that only the least-significant [`Self::BITS`]
+    /// bits can be non-zero.
+    ///
+    /// [`from_usize`]: Tag::from_usize
+    /// [`Self::BITS`]: Tag::BITS
     fn into_usize(self) -> usize;
 
+    /// Re-creates the tag from the integer returned by [`into_usize`].
+    ///
     /// # Safety
     ///
-    /// The passed `tag` must be returned from `into_usize`.
+    /// The passed `tag` must be returned from [`into_usize`].
+    ///
+    /// [`into_usize`]: Tag::into_usize
     unsafe fn from_usize(tag: usize) -> Self;
 }
 
-unsafe impl<T> Pointer for Box<T> {
-    const BITS: usize = std::mem::align_of::<T>().trailing_zeros() as usize;
+unsafe impl<T: ?Sized + Aligned> Pointer for Box<T> {
+    const BITS: u32 = bits_for::<Self::Target>();
+
     #[inline]
-    fn into_usize(self) -> usize {
-        Box::into_raw(self) as usize
+    fn into_ptr(self) -> NonNull<T> {
+        // Safety: pointers from `Box::into_raw` are valid & non-null
+        unsafe { NonNull::new_unchecked(Box::into_raw(self)) }
     }
+
     #[inline]
-    unsafe fn from_usize(ptr: usize) -> Self {
-        Box::from_raw(ptr as *mut T)
-    }
-    unsafe fn with_ref<R, F: FnOnce(&Self) -> R>(ptr: usize, f: F) -> R {
-        let raw = ManuallyDrop::new(Self::from_usize(ptr));
-        f(&raw)
+    unsafe fn from_ptr(ptr: NonNull<T>) -> Self {
+        // Safety: `ptr` comes from `into_ptr` which calls `Box::into_raw`
+        Box::from_raw(ptr.as_ptr())
     }
 }
 
-unsafe impl<T> Pointer for Rc<T> {
-    const BITS: usize = std::mem::align_of::<T>().trailing_zeros() as usize;
+unsafe impl<T: ?Sized + Aligned> Pointer for Rc<T> {
+    const BITS: u32 = bits_for::<Self::Target>();
+
     #[inline]
-    fn into_usize(self) -> usize {
-        Rc::into_raw(self) as usize
+    fn into_ptr(self) -> NonNull<T> {
+        // Safety: pointers from `Rc::into_raw` are valid & non-null
+        unsafe { NonNull::new_unchecked(Rc::into_raw(self).cast_mut()) }
+    }
+
+    #[inline]
+    unsafe fn from_ptr(ptr: NonNull<T>) -> Self {
+        // Safety: `ptr` comes from `into_ptr` which calls `Rc::into_raw`
+        Rc::from_raw(ptr.as_ptr())
     }
+}
+
+unsafe impl<T: ?Sized + Aligned> Pointer for Arc<T> {
+    const BITS: u32 = bits_for::<Self::Target>();
+
     #[inline]
-    unsafe fn from_usize(ptr: usize) -> Self {
-        Rc::from_raw(ptr as *const T)
+    fn into_ptr(self) -> NonNull<T> {
+        // Safety: pointers from `Arc::into_raw` are valid & non-null
+        unsafe { NonNull::new_unchecked(Arc::into_raw(self).cast_mut()) }
     }
-    unsafe fn with_ref<R, F: FnOnce(&Self) -> R>(ptr: usize, f: F) -> R {
-        let raw = ManuallyDrop::new(Self::from_usize(ptr));
-        f(&raw)
+
+    #[inline]
+    unsafe fn from_ptr(ptr: NonNull<T>) -> Self {
+        // Safety: `ptr` comes from `into_ptr` which calls `Arc::into_raw`
+        Arc::from_raw(ptr.as_ptr())
     }
 }
 
-unsafe impl<T> Pointer for Arc<T> {
-    const BITS: usize = std::mem::align_of::<T>().trailing_zeros() as usize;
+unsafe impl<'a, T: 'a + ?Sized + Aligned> Pointer for &'a T {
+    const BITS: u32 = bits_for::<Self::Target>();
+
     #[inline]
-    fn into_usize(self) -> usize {
-        Arc::into_raw(self) as usize
+    fn into_ptr(self) -> NonNull<T> {
+        NonNull::from(self)
     }
+
     #[inline]
-    unsafe fn from_usize(ptr: usize) -> Self {
-        Arc::from_raw(ptr as *const T)
-    }
-    unsafe fn with_ref<R, F: FnOnce(&Self) -> R>(ptr: usize, f: F) -> R {
-        let raw = ManuallyDrop::new(Self::from_usize(ptr));
-        f(&raw)
+    unsafe fn from_ptr(ptr: NonNull<T>) -> Self {
+        // Safety:
+        // `ptr` comes from `into_ptr` which gets the pointer from a reference
+        ptr.as_ref()
     }
 }
 
-unsafe impl<'a, T: 'a> Pointer for &'a T {
-    const BITS: usize = std::mem::align_of::<T>().trailing_zeros() as usize;
+unsafe impl<'a, T: 'a + ?Sized + Aligned> Pointer for &'a mut T {
+    const BITS: u32 = bits_for::<Self::Target>();
+
     #[inline]
-    fn into_usize(self) -> usize {
-        self as *const T as usize
+    fn into_ptr(self) -> NonNull<T> {
+        NonNull::from(self)
     }
+
     #[inline]
-    unsafe fn from_usize(ptr: usize) -> Self {
-        &*(ptr as *const T)
-    }
-    unsafe fn with_ref<R, F: FnOnce(&Self) -> R>(ptr: usize, f: F) -> R {
-        f(&*(&ptr as *const usize as *const Self))
+    unsafe fn from_ptr(mut ptr: NonNull<T>) -> Self {
+        // Safety:
+        // `ptr` comes from `into_ptr` which gets the pointer from a reference
+        ptr.as_mut()
     }
 }
 
-unsafe impl<'a, T: 'a> Pointer for &'a mut T {
-    const BITS: usize = std::mem::align_of::<T>().trailing_zeros() as usize;
-    #[inline]
+/// Returns the number of bits available for use for tags in a pointer to `T`
+/// (this is based on `T`'s alignment).
+pub const fn bits_for<T: ?Sized + Aligned>() -> u32 {
+    crate::aligned::align_of::<T>().as_nonzero().trailing_zeros()
+}
+
+/// A tag type used in [`CopyTaggedPtr`] and [`TaggedPtr`] tests.
+#[derive(Copy, Clone, Debug, PartialEq, Eq)]
+#[cfg(test)]
+enum Tag2 {
+    B00 = 0b00,
+    B01 = 0b01,
+    B10 = 0b10,
+    B11 = 0b11,
+}
+
+#[cfg(test)]
+unsafe impl Tag for Tag2 {
+    const BITS: u32 = 2;
+
     fn into_usize(self) -> usize {
-        self as *mut T as usize
+        self as _
     }
-    #[inline]
-    unsafe fn from_usize(ptr: usize) -> Self {
-        &mut *(ptr as *mut T)
+
+    unsafe fn from_usize(tag: usize) -> Self {
+        match tag {
+            0b00 => Tag2::B00,
+            0b01 => Tag2::B01,
+            0b10 => Tag2::B10,
+            0b11 => Tag2::B11,
+            _ => unreachable!(),
+        }
     }
-    unsafe fn with_ref<R, F: FnOnce(&Self) -> R>(ptr: usize, f: F) -> R {
-        f(&*(&ptr as *const usize as *const Self))
+}
+
+#[cfg(test)]
+impl<HCX> crate::stable_hasher::HashStable<HCX> for Tag2 {
+    fn hash_stable(&self, hcx: &mut HCX, hasher: &mut crate::stable_hasher::StableHasher) {
+        (*self as u8).hash_stable(hcx, hasher);
     }
 }
diff --git a/compiler/rustc_data_structures/src/tagged_ptr/copy.rs b/compiler/rustc_data_structures/src/tagged_ptr/copy.rs
index e1d3e0bd35a..691e92f196a 100644
--- a/compiler/rustc_data_structures/src/tagged_ptr/copy.rs
+++ b/compiler/rustc_data_structures/src/tagged_ptr/copy.rs
@@ -1,78 +1,92 @@
 use super::{Pointer, Tag};
 use crate::stable_hasher::{HashStable, StableHasher};
 use std::fmt;
+use std::hash::{Hash, Hasher};
 use std::marker::PhantomData;
+use std::mem::ManuallyDrop;
 use std::num::NonZeroUsize;
+use std::ops::{Deref, DerefMut};
+use std::ptr::NonNull;
 
-/// A `Copy` TaggedPtr.
+/// A [`Copy`] tagged pointer.
 ///
-/// You should use this instead of the `TaggedPtr` type in all cases where
-/// `P: Copy`.
+/// This is essentially `{ pointer: P, tag: T }` packed in a single pointer.
+///
+/// You should use this instead of the [`TaggedPtr`] type in all cases where
+/// `P` implements [`Copy`].
 ///
 /// If `COMPARE_PACKED` is true, then the pointers will be compared and hashed without
-/// unpacking. Otherwise we don't implement PartialEq/Eq/Hash; if you want that,
-/// wrap the TaggedPtr.
+/// unpacking. Otherwise we don't implement [`PartialEq`], [`Eq`] and [`Hash`];
+/// if you want that, wrap the [`CopyTaggedPtr`].
+///
+/// [`TaggedPtr`]: crate::tagged_ptr::TaggedPtr
 pub struct CopyTaggedPtr<P, T, const COMPARE_PACKED: bool>
 where
     P: Pointer,
     T: Tag,
 {
-    packed: NonZeroUsize,
-    data: PhantomData<(P, T)>,
-}
-
-impl<P, T, const COMPARE_PACKED: bool> Copy for CopyTaggedPtr<P, T, COMPARE_PACKED>
-where
-    P: Pointer,
-    T: Tag,
-    P: Copy,
-{
-}
-
-impl<P, T, const COMPARE_PACKED: bool> Clone for CopyTaggedPtr<P, T, COMPARE_PACKED>
-where
-    P: Pointer,
-    T: Tag,
-    P: Copy,
-{
-    fn clone(&self) -> Self {
-        *self
-    }
+    /// This is semantically a pair of `pointer: P` and `tag: T` fields,
+    /// however we pack them in a single pointer, to save space.
+    ///
+    /// We pack the tag into the **most**-significant bits of the pointer to
+    /// ease retrieval of the value. A left shift is a multiplication and
+    /// those are embeddable in instruction encoding, for example:
+    ///
+    /// ```asm
+    /// // (<https://godbolt.org/z/jqcYPWEr3>)
+    /// example::shift_read3:
+    ///     mov     eax, dword ptr [8*rdi]
+    ///     ret
+    ///
+    /// example::mask_read3:
+    ///     and     rdi, -8
+    ///     mov     eax, dword ptr [rdi]
+    ///     ret
+    /// ```
+    ///
+    /// This is ASM outputted by rustc for reads of values behind tagged
+    /// pointers for different approaches of tagging:
+    /// - `shift_read3` uses `<< 3` (the tag is in the most-significant bits)
+    /// - `mask_read3` uses `& !0b111` (the tag is in the least-significant bits)
+    ///
+    /// The shift approach thus produces less instructions and is likely faster
+    /// (see <https://godbolt.org/z/Y913sMdWb>).
+    ///
+    /// Encoding diagram:
+    /// ```text
+    /// [ packed.addr                     ]
+    /// [ tag ] [ pointer.addr >> T::BITS ] <-- usize::BITS - T::BITS bits
+    ///    ^
+    ///    |
+    /// T::BITS bits
+    /// ```
+    ///
+    /// The tag can be retrieved by `packed.addr() >> T::BITS` and the pointer
+    /// can be retrieved by `packed.map_addr(|addr| addr << T::BITS)`.
+    packed: NonNull<P::Target>,
+    tag_ghost: PhantomData<T>,
 }
 
-// We pack the tag into the *upper* bits of the pointer to ease retrieval of the
-// value; a left shift is a multiplication and those are embeddable in
-// instruction encoding.
-impl<P, T, const COMPARE_PACKED: bool> CopyTaggedPtr<P, T, COMPARE_PACKED>
+// Note that even though `CopyTaggedPtr` is only really expected to work with
+// `P: Copy`, can't add `P: Copy` bound, because `CopyTaggedPtr` is used in the
+// `TaggedPtr`'s implementation.
+impl<P, T, const CP: bool> CopyTaggedPtr<P, T, CP>
 where
     P: Pointer,
     T: Tag,
 {
-    const TAG_BIT_SHIFT: usize = usize::BITS as usize - T::BITS;
-    const ASSERTION: () = {
-        assert!(T::BITS <= P::BITS);
-        // Used for the transmute_copy's below
-        assert!(std::mem::size_of::<&P::Target>() == std::mem::size_of::<usize>());
-    };
-
+    /// Tags `pointer` with `tag`.
+    ///
+    /// Note that this leaks `pointer`: it won't be dropped when
+    /// `CopyTaggedPtr` is dropped. If you have a pointer with a significant
+    /// drop, use [`TaggedPtr`] instead.
+    ///
+    /// [`TaggedPtr`]: crate::tagged_ptr::TaggedPtr
     pub fn new(pointer: P, tag: T) -> Self {
-        // Trigger assert!
-        let () = Self::ASSERTION;
-        let packed_tag = tag.into_usize() << Self::TAG_BIT_SHIFT;
-
-        Self {
-            // SAFETY: We know that the pointer is non-null, as it must be
-            // dereferenceable per `Pointer` safety contract.
-            packed: unsafe {
-                NonZeroUsize::new_unchecked((P::into_usize(pointer) >> T::BITS) | packed_tag)
-            },
-            data: PhantomData,
-        }
+        Self { packed: Self::pack(P::into_ptr(pointer), tag), tag_ghost: PhantomData }
     }
 
-    pub(super) fn pointer_raw(&self) -> usize {
-        self.packed.get() << T::BITS
-    }
+    /// Retrieves the pointer.
     pub fn pointer(self) -> P
     where
         P: Copy,
@@ -81,66 +95,138 @@ where
         //
         // Note that this isn't going to double-drop or anything because we have
         // P: Copy
-        unsafe { P::from_usize(self.pointer_raw()) }
-    }
-    pub fn pointer_ref(&self) -> &P::Target {
-        // SAFETY: pointer_raw returns the original pointer
-        unsafe { std::mem::transmute_copy(&self.pointer_raw()) }
-    }
-    pub fn pointer_mut(&mut self) -> &mut P::Target
-    where
-        P: std::ops::DerefMut,
-    {
-        // SAFETY: pointer_raw returns the original pointer
-        unsafe { std::mem::transmute_copy(&self.pointer_raw()) }
+        unsafe { P::from_ptr(self.pointer_raw()) }
     }
+
+    /// Retrieves the tag.
     #[inline]
     pub fn tag(&self) -> T {
-        unsafe { T::from_usize(self.packed.get() >> Self::TAG_BIT_SHIFT) }
+        // Unpack the tag, according to the `self.packed` encoding scheme
+        let tag = self.packed.addr().get() >> Self::TAG_BIT_SHIFT;
+
+        // Safety:
+        // The shift retrieves the original value from `T::into_usize`,
+        // satisfying `T::from_usize`'s preconditions.
+        unsafe { T::from_usize(tag) }
     }
+
+    /// Sets the tag to a new value.
     #[inline]
     pub fn set_tag(&mut self, tag: T) {
-        let mut packed = self.packed.get();
-        let new_tag = T::into_usize(tag) << Self::TAG_BIT_SHIFT;
-        let tag_mask = (1 << T::BITS) - 1;
-        packed &= !(tag_mask << Self::TAG_BIT_SHIFT);
-        packed |= new_tag;
-        self.packed = unsafe { NonZeroUsize::new_unchecked(packed) };
+        self.packed = Self::pack(self.pointer_raw(), tag);
+    }
+
+    const TAG_BIT_SHIFT: u32 = usize::BITS - T::BITS;
+    const ASSERTION: () = { assert!(T::BITS <= P::BITS) };
+
+    /// Pack pointer `ptr` that comes from [`P::into_ptr`] with a `tag`,
+    /// according to `self.packed` encoding scheme.
+    ///
+    /// [`P::into_ptr`]: Pointer::into_ptr
+    fn pack(ptr: NonNull<P::Target>, tag: T) -> NonNull<P::Target> {
+        // Trigger assert!
+        let () = Self::ASSERTION;
+
+        let packed_tag = tag.into_usize() << Self::TAG_BIT_SHIFT;
+
+        ptr.map_addr(|addr| {
+            // Safety:
+            // - The pointer is `NonNull` => it's address is `NonZeroUsize`
+            // - `P::BITS` least significant bits are always zero (`Pointer` contract)
+            // - `T::BITS <= P::BITS` (from `Self::ASSERTION`)
+            //
+            // Thus `addr >> T::BITS` is guaranteed to be non-zero.
+            //
+            // `{non_zero} | packed_tag` can't make the value zero.
+
+            let packed = (addr.get() >> T::BITS) | packed_tag;
+            unsafe { NonZeroUsize::new_unchecked(packed) }
+        })
+    }
+
+    /// Retrieves the original raw pointer from `self.packed`.
+    pub(super) fn pointer_raw(&self) -> NonNull<P::Target> {
+        self.packed.map_addr(|addr| unsafe { NonZeroUsize::new_unchecked(addr.get() << T::BITS) })
+    }
+
+    /// This provides a reference to the `P` pointer itself, rather than the
+    /// `Deref::Target`. It is used for cases where we want to call methods
+    /// that may be implement differently for the Pointer than the Pointee
+    /// (e.g., `Rc::clone` vs cloning the inner value).
+    pub(super) fn with_pointer_ref<R>(&self, f: impl FnOnce(&P) -> R) -> R {
+        // Safety:
+        // - `self.raw.pointer_raw()` is originally returned from `P::into_ptr`
+        //   and as such is valid for `P::from_ptr`.
+        //   - This also allows us to not care whatever `f` panics or not.
+        // - Even though we create a copy of the pointer, we store it inside
+        //   `ManuallyDrop` and only access it by-ref, so we don't double-drop.
+        //
+        // Semantically this is just `f(&self.pointer)` (where `self.pointer`
+        // is non-packed original pointer).
+        //
+        // Note that even though `CopyTaggedPtr` is only really expected to
+        // work with `P: Copy`, we have to assume `P: ?Copy`, because
+        // `CopyTaggedPtr` is used in the `TaggedPtr`'s implementation.
+        let ptr = unsafe { ManuallyDrop::new(P::from_ptr(self.pointer_raw())) };
+        f(&ptr)
     }
 }
 
-impl<P, T, const COMPARE_PACKED: bool> std::ops::Deref for CopyTaggedPtr<P, T, COMPARE_PACKED>
+impl<P, T, const CP: bool> Copy for CopyTaggedPtr<P, T, CP>
+where
+    P: Pointer + Copy,
+    T: Tag,
+{
+}
+
+impl<P, T, const CP: bool> Clone for CopyTaggedPtr<P, T, CP>
+where
+    P: Pointer + Copy,
+    T: Tag,
+{
+    fn clone(&self) -> Self {
+        *self
+    }
+}
+
+impl<P, T, const CP: bool> Deref for CopyTaggedPtr<P, T, CP>
 where
     P: Pointer,
     T: Tag,
 {
     type Target = P::Target;
+
     fn deref(&self) -> &Self::Target {
-        self.pointer_ref()
+        // Safety:
+        // `pointer_raw` returns the original pointer from `P::into_ptr` which,
+        // by the `Pointer`'s contract, must be valid.
+        unsafe { self.pointer_raw().as_ref() }
     }
 }
 
-impl<P, T, const COMPARE_PACKED: bool> std::ops::DerefMut for CopyTaggedPtr<P, T, COMPARE_PACKED>
+impl<P, T, const CP: bool> DerefMut for CopyTaggedPtr<P, T, CP>
 where
-    P: Pointer + std::ops::DerefMut,
+    P: Pointer + DerefMut,
     T: Tag,
 {
     fn deref_mut(&mut self) -> &mut Self::Target {
-        self.pointer_mut()
+        // Safety:
+        // `pointer_raw` returns the original pointer from `P::into_ptr` which,
+        // by the `Pointer`'s contract, must be valid for writes if
+        // `P: DerefMut`.
+        unsafe { self.pointer_raw().as_mut() }
     }
 }
 
-impl<P, T, const COMPARE_PACKED: bool> fmt::Debug for CopyTaggedPtr<P, T, COMPARE_PACKED>
+impl<P, T, const CP: bool> fmt::Debug for CopyTaggedPtr<P, T, CP>
 where
-    P: Pointer,
-    P::Target: fmt::Debug,
+    P: Pointer + fmt::Debug,
     T: Tag + fmt::Debug,
 {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.debug_struct("CopyTaggedPtr")
-            .field("pointer", &self.pointer_ref())
-            .field("tag", &self.tag())
-            .finish()
+        self.with_pointer_ref(|ptr| {
+            f.debug_struct("CopyTaggedPtr").field("pointer", ptr).field("tag", &self.tag()).finish()
+        })
     }
 }
 
@@ -161,25 +247,73 @@ where
 {
 }
 
-impl<P, T> std::hash::Hash for CopyTaggedPtr<P, T, true>
+impl<P, T> Hash for CopyTaggedPtr<P, T, true>
 where
     P: Pointer,
     T: Tag,
 {
-    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
+    fn hash<H: Hasher>(&self, state: &mut H) {
         self.packed.hash(state);
     }
 }
 
-impl<P, T, HCX, const COMPARE_PACKED: bool> HashStable<HCX> for CopyTaggedPtr<P, T, COMPARE_PACKED>
+impl<P, T, HCX, const CP: bool> HashStable<HCX> for CopyTaggedPtr<P, T, CP>
 where
     P: Pointer + HashStable<HCX>,
     T: Tag + HashStable<HCX>,
 {
     fn hash_stable(&self, hcx: &mut HCX, hasher: &mut StableHasher) {
-        unsafe {
-            Pointer::with_ref(self.pointer_raw(), |p: &P| p.hash_stable(hcx, hasher));
-        }
+        self.with_pointer_ref(|ptr| ptr.hash_stable(hcx, hasher));
         self.tag().hash_stable(hcx, hasher);
     }
 }
+
+// Safety:
+// `CopyTaggedPtr<P, T, ..>` is semantically just `{ ptr: P, tag: T }`, as such
+// it's ok to implement `Sync` as long as `P: Sync, T: Sync`
+unsafe impl<P, T, const CP: bool> Sync for CopyTaggedPtr<P, T, CP>
+where
+    P: Sync + Pointer,
+    T: Sync + Tag,
+{
+}
+
+// Safety:
+// `CopyTaggedPtr<P, T, ..>` is semantically just `{ ptr: P, tag: T }`, as such
+// it's ok to implement `Send` as long as `P: Send, T: Send`
+unsafe impl<P, T, const CP: bool> Send for CopyTaggedPtr<P, T, CP>
+where
+    P: Send + Pointer,
+    T: Send + Tag,
+{
+}
+
+/// Test that `new` does not compile if there is not enough alignment for the
+/// tag in the pointer.
+///
+/// ```compile_fail,E0080
+/// use rustc_data_structures::tagged_ptr::{CopyTaggedPtr, Tag};
+///
+/// #[derive(Copy, Clone, Debug, PartialEq, Eq)]
+/// enum Tag2 { B00 = 0b00, B01 = 0b01, B10 = 0b10, B11 = 0b11 };
+///
+/// unsafe impl Tag for Tag2 {
+///     const BITS: u32 = 2;
+///
+///     fn into_usize(self) -> usize { todo!() }
+///     unsafe fn from_usize(tag: usize) -> Self { todo!() }
+/// }
+///
+/// let value = 12u16;
+/// let reference = &value;
+/// let tag = Tag2::B01;
+///
+/// let _ptr = CopyTaggedPtr::<_, _, true>::new(reference, tag);
+/// ```
+// For some reason miri does not get the compile error
+// probably it `check`s instead of `build`ing?
+#[cfg(not(miri))]
+const _: () = ();
+
+#[cfg(test)]
+mod tests;
diff --git a/compiler/rustc_data_structures/src/tagged_ptr/copy/tests.rs b/compiler/rustc_data_structures/src/tagged_ptr/copy/tests.rs
new file mode 100644
index 00000000000..bfcc2e603de
--- /dev/null
+++ b/compiler/rustc_data_structures/src/tagged_ptr/copy/tests.rs
@@ -0,0 +1,50 @@
+use std::ptr;
+
+use crate::stable_hasher::{HashStable, StableHasher};
+use crate::tagged_ptr::{CopyTaggedPtr, Pointer, Tag, Tag2};
+
+#[test]
+fn smoke() {
+    let value = 12u32;
+    let reference = &value;
+    let tag = Tag2::B01;
+
+    let ptr = tag_ptr(reference, tag);
+
+    assert_eq!(ptr.tag(), tag);
+    assert_eq!(*ptr, 12);
+    assert!(ptr::eq(ptr.pointer(), reference));
+
+    let copy = ptr;
+
+    let mut ptr = ptr;
+    ptr.set_tag(Tag2::B00);
+    assert_eq!(ptr.tag(), Tag2::B00);
+
+    assert_eq!(copy.tag(), tag);
+    assert_eq!(*copy, 12);
+    assert!(ptr::eq(copy.pointer(), reference));
+}
+
+#[test]
+fn stable_hash_hashes_as_tuple() {
+    let hash_packed = {
+        let mut hasher = StableHasher::new();
+        tag_ptr(&12, Tag2::B11).hash_stable(&mut (), &mut hasher);
+
+        hasher.finalize()
+    };
+
+    let hash_tupled = {
+        let mut hasher = StableHasher::new();
+        (&12, Tag2::B11).hash_stable(&mut (), &mut hasher);
+        hasher.finalize()
+    };
+
+    assert_eq!(hash_packed, hash_tupled);
+}
+
+/// Helper to create tagged pointers without specifying `COMPARE_PACKED` if it does not matter.
+fn tag_ptr<P: Pointer, T: Tag>(ptr: P, tag: T) -> CopyTaggedPtr<P, T, true> {
+    CopyTaggedPtr::new(ptr, tag)
+}
diff --git a/compiler/rustc_data_structures/src/tagged_ptr/drop.rs b/compiler/rustc_data_structures/src/tagged_ptr/drop.rs
index b0315c93d93..d418c06b7eb 100644
--- a/compiler/rustc_data_structures/src/tagged_ptr/drop.rs
+++ b/compiler/rustc_data_structures/src/tagged_ptr/drop.rs
@@ -1,14 +1,21 @@
-use super::{Pointer, Tag};
-use crate::stable_hasher::{HashStable, StableHasher};
 use std::fmt;
+use std::hash::{Hash, Hasher};
+use std::ops::{Deref, DerefMut};
 
 use super::CopyTaggedPtr;
+use super::{Pointer, Tag};
+use crate::stable_hasher::{HashStable, StableHasher};
 
-/// A TaggedPtr implementing `Drop`.
+/// A tagged pointer that supports pointers that implement [`Drop`].
+///
+/// This is essentially `{ pointer: P, tag: T }` packed in a single pointer.
+///
+/// You should use [`CopyTaggedPtr`] instead of the this type in all cases
+/// where `P` implements [`Copy`].
 ///
 /// If `COMPARE_PACKED` is true, then the pointers will be compared and hashed without
-/// unpacking. Otherwise we don't implement PartialEq/Eq/Hash; if you want that,
-/// wrap the TaggedPtr.
+/// unpacking. Otherwise we don't implement [`PartialEq`], [`Eq`] and [`Hash`];
+/// if you want that, wrap the [`TaggedPtr`].
 pub struct TaggedPtr<P, T, const COMPARE_PACKED: bool>
 where
     P: Pointer,
@@ -17,58 +24,61 @@ where
     raw: CopyTaggedPtr<P, T, COMPARE_PACKED>,
 }
 
-impl<P, T, const COMPARE_PACKED: bool> Clone for TaggedPtr<P, T, COMPARE_PACKED>
-where
-    P: Pointer + Clone,
-    T: Tag,
-{
-    fn clone(&self) -> Self {
-        unsafe { Self::new(P::with_ref(self.raw.pointer_raw(), |p| p.clone()), self.raw.tag()) }
-    }
-}
-
-// We pack the tag into the *upper* bits of the pointer to ease retrieval of the
-// value; a right shift is a multiplication and those are embeddable in
-// instruction encoding.
-impl<P, T, const COMPARE_PACKED: bool> TaggedPtr<P, T, COMPARE_PACKED>
+impl<P, T, const CP: bool> TaggedPtr<P, T, CP>
 where
     P: Pointer,
     T: Tag,
 {
+    /// Tags `pointer` with `tag`.
     pub fn new(pointer: P, tag: T) -> Self {
         TaggedPtr { raw: CopyTaggedPtr::new(pointer, tag) }
     }
 
-    pub fn pointer_ref(&self) -> &P::Target {
-        self.raw.pointer_ref()
-    }
+    /// Retrieves the tag.
     pub fn tag(&self) -> T {
         self.raw.tag()
     }
+
+    /// Sets the tag to a new value.
+    pub fn set_tag(&mut self, tag: T) {
+        self.raw.set_tag(tag)
+    }
 }
 
-impl<P, T, const COMPARE_PACKED: bool> std::ops::Deref for TaggedPtr<P, T, COMPARE_PACKED>
+impl<P, T, const CP: bool> Clone for TaggedPtr<P, T, CP>
+where
+    P: Pointer + Clone,
+    T: Tag,
+{
+    fn clone(&self) -> Self {
+        let ptr = self.raw.with_pointer_ref(P::clone);
+
+        Self::new(ptr, self.tag())
+    }
+}
+
+impl<P, T, const CP: bool> Deref for TaggedPtr<P, T, CP>
 where
     P: Pointer,
     T: Tag,
 {
     type Target = P::Target;
     fn deref(&self) -> &Self::Target {
-        self.raw.pointer_ref()
+        self.raw.deref()
     }
 }
 
-impl<P, T, const COMPARE_PACKED: bool> std::ops::DerefMut for TaggedPtr<P, T, COMPARE_PACKED>
+impl<P, T, const CP: bool> DerefMut for TaggedPtr<P, T, CP>
 where
-    P: Pointer + std::ops::DerefMut,
+    P: Pointer + DerefMut,
     T: Tag,
 {
     fn deref_mut(&mut self) -> &mut Self::Target {
-        self.raw.pointer_mut()
+        self.raw.deref_mut()
     }
 }
 
-impl<P, T, const COMPARE_PACKED: bool> Drop for TaggedPtr<P, T, COMPARE_PACKED>
+impl<P, T, const CP: bool> Drop for TaggedPtr<P, T, CP>
 where
     P: Pointer,
     T: Tag,
@@ -76,22 +86,20 @@ where
     fn drop(&mut self) {
         // No need to drop the tag, as it's Copy
         unsafe {
-            drop(P::from_usize(self.raw.pointer_raw()));
+            drop(P::from_ptr(self.raw.pointer_raw()));
         }
     }
 }
 
-impl<P, T, const COMPARE_PACKED: bool> fmt::Debug for TaggedPtr<P, T, COMPARE_PACKED>
+impl<P, T, const CP: bool> fmt::Debug for TaggedPtr<P, T, CP>
 where
-    P: Pointer,
-    P::Target: fmt::Debug,
+    P: Pointer + fmt::Debug,
     T: Tag + fmt::Debug,
 {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.debug_struct("TaggedPtr")
-            .field("pointer", &self.pointer_ref())
-            .field("tag", &self.tag())
-            .finish()
+        self.raw.with_pointer_ref(|ptr| {
+            f.debug_struct("TaggedPtr").field("pointer", ptr).field("tag", &self.tag()).finish()
+        })
     }
 }
 
@@ -112,17 +120,17 @@ where
 {
 }
 
-impl<P, T> std::hash::Hash for TaggedPtr<P, T, true>
+impl<P, T> Hash for TaggedPtr<P, T, true>
 where
     P: Pointer,
     T: Tag,
 {
-    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
+    fn hash<H: Hasher>(&self, state: &mut H) {
         self.raw.hash(state);
     }
 }
 
-impl<P, T, HCX, const COMPARE_PACKED: bool> HashStable<HCX> for TaggedPtr<P, T, COMPARE_PACKED>
+impl<P, T, HCX, const CP: bool> HashStable<HCX> for TaggedPtr<P, T, CP>
 where
     P: Pointer + HashStable<HCX>,
     T: Tag + HashStable<HCX>,
@@ -131,3 +139,33 @@ where
         self.raw.hash_stable(hcx, hasher);
     }
 }
+
+/// Test that `new` does not compile if there is not enough alignment for the
+/// tag in the pointer.
+///
+/// ```compile_fail,E0080
+/// use rustc_data_structures::tagged_ptr::{TaggedPtr, Tag};
+///
+/// #[derive(Copy, Clone, Debug, PartialEq, Eq)]
+/// enum Tag2 { B00 = 0b00, B01 = 0b01, B10 = 0b10, B11 = 0b11 };
+///
+/// unsafe impl Tag for Tag2 {
+///     const BITS: u32 = 2;
+///
+///     fn into_usize(self) -> usize { todo!() }
+///     unsafe fn from_usize(tag: usize) -> Self { todo!() }
+/// }
+///
+/// let value = 12u16;
+/// let reference = &value;
+/// let tag = Tag2::B01;
+///
+/// let _ptr = TaggedPtr::<_, _, true>::new(reference, tag);
+/// ```
+// For some reason miri does not get the compile error
+// probably it `check`s instead of `build`ing?
+#[cfg(not(miri))]
+const _: () = ();
+
+#[cfg(test)]
+mod tests;
diff --git a/compiler/rustc_data_structures/src/tagged_ptr/drop/tests.rs b/compiler/rustc_data_structures/src/tagged_ptr/drop/tests.rs
new file mode 100644
index 00000000000..2c17d678d3a
--- /dev/null
+++ b/compiler/rustc_data_structures/src/tagged_ptr/drop/tests.rs
@@ -0,0 +1,71 @@
+use std::{ptr, sync::Arc};
+
+use crate::tagged_ptr::{Pointer, Tag, Tag2, TaggedPtr};
+
+#[test]
+fn smoke() {
+    let value = 12u32;
+    let reference = &value;
+    let tag = Tag2::B01;
+
+    let ptr = tag_ptr(reference, tag);
+
+    assert_eq!(ptr.tag(), tag);
+    assert_eq!(*ptr, 12);
+
+    let clone = ptr.clone();
+    assert_eq!(clone.tag(), tag);
+    assert_eq!(*clone, 12);
+
+    let mut ptr = ptr;
+    ptr.set_tag(Tag2::B00);
+    assert_eq!(ptr.tag(), Tag2::B00);
+
+    assert_eq!(clone.tag(), tag);
+    assert_eq!(*clone, 12);
+    assert!(ptr::eq(&*ptr, &*clone))
+}
+
+#[test]
+fn boxed() {
+    let value = 12u32;
+    let boxed = Box::new(value);
+    let tag = Tag2::B01;
+
+    let ptr = tag_ptr(boxed, tag);
+
+    assert_eq!(ptr.tag(), tag);
+    assert_eq!(*ptr, 12);
+
+    let clone = ptr.clone();
+    assert_eq!(clone.tag(), tag);
+    assert_eq!(*clone, 12);
+
+    let mut ptr = ptr;
+    ptr.set_tag(Tag2::B00);
+    assert_eq!(ptr.tag(), Tag2::B00);
+
+    assert_eq!(clone.tag(), tag);
+    assert_eq!(*clone, 12);
+    assert!(!ptr::eq(&*ptr, &*clone))
+}
+
+#[test]
+fn arclones() {
+    let value = 12u32;
+    let arc = Arc::new(value);
+    let tag = Tag2::B01;
+
+    let ptr = tag_ptr(arc, tag);
+
+    assert_eq!(ptr.tag(), tag);
+    assert_eq!(*ptr, 12);
+
+    let clone = ptr.clone();
+    assert!(ptr::eq(&*ptr, &*clone))
+}
+
+/// Helper to create tagged pointers without specifying `COMPARE_PACKED` if it does not matter.
+fn tag_ptr<P: Pointer, T: Tag>(ptr: P, tag: T) -> TaggedPtr<P, T, true> {
+    TaggedPtr::new(ptr, tag)
+}
diff --git a/compiler/rustc_error_codes/src/error_codes/E0026.md b/compiler/rustc_error_codes/src/error_codes/E0026.md
index 72c575aabb6..f485112cca2 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0026.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0026.md
@@ -1,4 +1,4 @@
-A struct pattern attempted to extract a non-existent field from a struct.
+A struct pattern attempted to extract a nonexistent field from a struct.
 
 Erroneous code example:
 
diff --git a/compiler/rustc_error_codes/src/error_codes/E0208.md b/compiler/rustc_error_codes/src/error_codes/E0208.md
index 1ae01106f20..c6db9b5d61b 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0208.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0208.md
@@ -32,7 +32,7 @@ error: [-, o]
 This error is deliberately triggered with the `#[rustc_variance]` attribute
 (`#![feature(rustc_attrs)]` must be enabled) and helps to show you the variance
 of the type's generic parameters. You can read more about variance and
-subtyping in [this section of the Rustnomicon]. For a more in depth look at
+subtyping in [this section of the Rustonomicon]. For a more in depth look at
 variance (including a more complete list of common variances) see
 [this section of the Reference]. For information on how variance is implemented
 in the compiler, see [this section of `rustc-dev-guide`].
@@ -41,6 +41,6 @@ This error can be easily fixed by removing the `#[rustc_variance]` attribute,
 the compiler's suggestion to comment it out can be applied automatically with
 `rustfix`.
 
-[this section of the Rustnomicon]: https://doc.rust-lang.org/nomicon/subtyping.html
+[this section of the Rustonomicon]: https://doc.rust-lang.org/nomicon/subtyping.html
 [this section of the Reference]: https://doc.rust-lang.org/reference/subtyping.html#variance
 [this section of `rustc-dev-guide`]: https://rustc-dev-guide.rust-lang.org/variance.html
diff --git a/compiler/rustc_error_codes/src/error_codes/E0311.md b/compiler/rustc_error_codes/src/error_codes/E0311.md
index 08159d3f469..c1104a88a76 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0311.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0311.md
@@ -29,7 +29,7 @@ If `no_restriction()` were to use `&T` instead of `&()` as an argument, the
 compiler would have added an implied bound, causing this to compile.
 
 This error can be resolved by explicitly naming the elided lifetime for `x` and
-then explicily requiring that the generic parameter `T` outlives that lifetime:
+then explicitly requiring that the generic parameter `T` outlives that lifetime:
 
 ```
 fn no_restriction<'a, T: 'a>(x: &'a ()) -> &'a () {
diff --git a/compiler/rustc_error_codes/src/error_codes/E0457.md b/compiler/rustc_error_codes/src/error_codes/E0457.md
index 53d384d36c4..2c33d1e6a24 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0457.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0457.md
@@ -1,6 +1,6 @@
 Plugin `..` only found in rlib format, but must be available in dylib format.
 
-Erroronous code example:
+Erroneous code example:
 
 `rlib-plugin.rs`
 ```ignore (needs-linkage-with-other-tests)
diff --git a/compiler/rustc_error_codes/src/error_codes/E0576.md b/compiler/rustc_error_codes/src/error_codes/E0576.md
index 8eead4e7e3b..300a57a1985 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0576.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0576.md
@@ -10,7 +10,7 @@ trait Hello {
 }
 ```
 
-In this example, we tried to use the non-existent associated type `You` of the
+In this example, we tried to use the nonexistent associated type `You` of the
 `Hello` trait. To fix this error, use an existing associated type:
 
 ```
diff --git a/compiler/rustc_error_codes/src/error_codes/E0609.md b/compiler/rustc_error_codes/src/error_codes/E0609.md
index a9db34f474e..0f5ac94e6d5 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0609.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0609.md
@@ -1,4 +1,4 @@
-Attempted to access a non-existent field in a struct.
+Attempted to access a nonexistent field in a struct.
 
 Erroneous code example:
 
diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs
index fe44799efdb..8c76d5e010f 100644
--- a/compiler/rustc_errors/src/emitter.rs
+++ b/compiler/rustc_errors/src/emitter.rs
@@ -1980,7 +1980,7 @@ impl EmitterWriter {
             }
             if let DisplaySuggestion::Add = show_code_change && is_item_attribute {
                 // The suggestion adds an entire line of code, ending on a newline, so we'll also
-                // print the *following* line, to provide context of what we're advicing people to
+                // print the *following* line, to provide context of what we're advising people to
                 // do. Otherwise you would only see contextless code that can be confused for
                 // already existing code, despite the colors and UI elements.
                 // We special case `#[derive(_)]\n` and other attribute suggestions, because those
diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs
index d20b168904d..26791304ef1 100644
--- a/compiler/rustc_errors/src/lib.rs
+++ b/compiler/rustc_errors/src/lib.rs
@@ -31,7 +31,7 @@ use Level::*;
 use emitter::{is_case_difference, Emitter, EmitterWriter};
 use registry::Registry;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet};
-use rustc_data_structures::stable_hasher::StableHasher;
+use rustc_data_structures::stable_hasher::{Hash128, StableHasher};
 use rustc_data_structures::sync::{self, Lock, Lrc};
 use rustc_data_structures::AtomicRef;
 pub use rustc_error_messages::{
@@ -427,7 +427,7 @@ struct HandlerInner {
     /// This set contains a hash of every diagnostic that has been emitted by
     /// this handler. These hashes is used to avoid emitting the same error
     /// twice.
-    emitted_diagnostics: FxHashSet<u128>,
+    emitted_diagnostics: FxHashSet<Hash128>,
 
     /// Stashed diagnostics emitted in one stage of the compiler that may be
     /// stolen by other stages (e.g. to improve them and add more information).
diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs
index 5679cdcbbd0..3aeb2edb54c 100644
--- a/compiler/rustc_expand/src/mbe/macro_rules.rs
+++ b/compiler/rustc_expand/src/mbe/macro_rules.rs
@@ -341,7 +341,7 @@ pub(super) fn try_match_macro<'matcher, T: Tracker<'matcher>>(
             Success(named_matches) => {
                 debug!("Parsed arm successfully");
                 // The matcher was `Success(..)`ful.
-                // Merge the gated spans from parsing the matcher with the pre-existing ones.
+                // Merge the gated spans from parsing the matcher with the preexisting ones.
                 sess.gated_spans.merge(gated_spans_snapshot);
 
                 return Ok((i, named_matches));
@@ -873,7 +873,7 @@ impl<'tt> FirstSets<'tt> {
     }
 }
 
-// Most `mbe::TokenTree`s are pre-existing in the matcher, but some are defined
+// Most `mbe::TokenTree`s are preexisting in the matcher, but some are defined
 // implicitly, such as opening/closing delimiters and sequence repetition ops.
 // This type encapsulates both kinds. It implements `Clone` while avoiding the
 // need for `mbe::TokenTree` to implement `Clone`.
diff --git a/compiler/rustc_expand/src/tests.rs b/compiler/rustc_expand/src/tests.rs
index 480d95b77e9..8a5e09475ff 100644
--- a/compiler/rustc_expand/src/tests.rs
+++ b/compiler/rustc_expand/src/tests.rs
@@ -513,7 +513,7 @@ error: foo
 }
 
 #[test]
-fn non_overlaping() {
+fn non_overlapping() {
     test_harness(
         r#"
 fn foo() {
@@ -552,7 +552,7 @@ error: foo
 }
 
 #[test]
-fn overlaping_start_and_end() {
+fn overlapping_start_and_end() {
     test_harness(
         r#"
 fn foo() {
diff --git a/compiler/rustc_feature/src/removed.rs b/compiler/rustc_feature/src/removed.rs
index 48d9fbfa6d2..876a31abdf8 100644
--- a/compiler/rustc_feature/src/removed.rs
+++ b/compiler/rustc_feature/src/removed.rs
@@ -139,7 +139,7 @@ declare_features! (
     /// Allows using `#[on_unimplemented(..)]` on traits.
     /// (Moved to `rustc_attrs`.)
     (removed, on_unimplemented, "1.40.0", None, None, None),
-    /// A way to temporarily opt out of opt in copy. This will *never* be accepted.
+    /// A way to temporarily opt out of opt-in copy. This will *never* be accepted.
     (removed, opt_out_copy, "1.0.0", None, None, None),
     /// Allows features specific to OIBIT (now called auto traits).
     /// Renamed to `auto_traits`.
diff --git a/compiler/rustc_hir/src/definitions.rs b/compiler/rustc_hir/src/definitions.rs
index 8ceb176491b..5a5a1e44f12 100644
--- a/compiler/rustc_hir/src/definitions.rs
+++ b/compiler/rustc_hir/src/definitions.rs
@@ -9,7 +9,7 @@ use crate::def_id::{CrateNum, DefIndex, LocalDefId, StableCrateId, CRATE_DEF_IND
 use crate::def_path_hash_map::DefPathHashMap;
 
 use rustc_data_structures::fx::FxHashMap;
-use rustc_data_structures::stable_hasher::StableHasher;
+use rustc_data_structures::stable_hasher::{Hash64, StableHasher};
 use rustc_index::vec::IndexVec;
 use rustc_span::symbol::{kw, sym, Symbol};
 
@@ -130,7 +130,7 @@ impl DefKey {
 
         disambiguator.hash(&mut hasher);
 
-        let local_hash: u64 = hasher.finish();
+        let local_hash = hasher.finish();
 
         // Construct the new DefPathHash, making sure that the `crate_id`
         // portion of the hash is properly copied from the parent. This way the
@@ -325,7 +325,7 @@ impl Definitions {
             },
         };
 
-        let parent_hash = DefPathHash::new(stable_crate_id, 0);
+        let parent_hash = DefPathHash::new(stable_crate_id, Hash64::ZERO);
         let def_path_hash = key.compute_stable_hash(parent_hash);
 
         // Create the root definition.
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index b274e628079..fb0c087bfb4 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -3146,7 +3146,6 @@ impl<'hir> Item<'hir> {
         (ty, gen)
     }
 
-    /// An opaque `impl Trait` type alias, e.g., `type Foo = impl Bar;`.
     /// Expect an [`ItemKind::OpaqueTy`] or panic.
     #[track_caller]
     pub fn expect_opaque_ty(&self) -> &OpaqueTy<'hir> {
@@ -3168,7 +3167,6 @@ impl<'hir> Item<'hir> {
         (data, gen)
     }
 
-    /// A union definition, e.g., `union Foo<A, B> {x: A, y: B}`.
     /// Expect an [`ItemKind::Union`] or panic.
     #[track_caller]
     pub fn expect_union(&self) -> (&VariantData<'hir>, &'hir Generics<'hir>) {
diff --git a/compiler/rustc_hir/src/tests.rs b/compiler/rustc_hir/src/tests.rs
index d4791150947..c7ac01b3334 100644
--- a/compiler/rustc_hir/src/tests.rs
+++ b/compiler/rustc_hir/src/tests.rs
@@ -1,4 +1,5 @@
 use crate::definitions::{DefKey, DefPathData, DisambiguatedDefPathData};
+use rustc_data_structures::stable_hasher::Hash64;
 use rustc_span::def_id::{DefPathHash, StableCrateId};
 use rustc_span::edition::Edition;
 use rustc_span::{create_session_if_not_set_then, Symbol};
@@ -24,7 +25,7 @@ fn def_path_hash_depends_on_crate_id() {
         assert_ne!(h0.local_hash(), h1.local_hash());
 
         fn mk_test_hash(stable_crate_id: StableCrateId) -> DefPathHash {
-            let parent_hash = DefPathHash::new(stable_crate_id, 0);
+            let parent_hash = DefPathHash::new(stable_crate_id, Hash64::ZERO);
 
             let key = DefKey {
                 parent: None,
diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs
index 8d1156c1771..7eb12d380a7 100644
--- a/compiler/rustc_hir_analysis/src/astconv/mod.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs
@@ -2061,7 +2061,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                             err.note("enum variants can't have type parameters");
                             let type_name = tcx.item_name(adt_def.did());
                             let msg = format!(
-                                "you might have meant to specity type parameters on enum \
+                                "you might have meant to specify type parameters on enum \
                                  `{type_name}`"
                             );
                             let Some(args) = assoc_segment.args else { return; };
diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs
index 0f40cca9427..611ce13b739 100644
--- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs
@@ -74,16 +74,15 @@ fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
 
     debug!("visit_implementation_of_copy: self_type={:?} (free)", self_type);
 
-    let span = match tcx.hir().expect_item(impl_did).kind {
-        ItemKind::Impl(hir::Impl { polarity: hir::ImplPolarity::Negative(_), .. }) => return,
-        ItemKind::Impl(impl_) => impl_.self_ty.span,
-        _ => bug!("expected Copy impl item"),
+    let span = match tcx.hir().expect_item(impl_did).expect_impl() {
+        hir::Impl { polarity: hir::ImplPolarity::Negative(_), .. } => return,
+        hir::Impl { self_ty, .. } => self_ty.span,
     };
 
     let cause = traits::ObligationCause::misc(span, impl_did);
     match type_allowed_to_implement_copy(tcx, param_env, self_type, cause) {
         Ok(()) => {}
-        Err(CopyImplementationError::InfrigingFields(fields)) => {
+        Err(CopyImplementationError::InfringingFields(fields)) => {
             let mut err = struct_span_err!(
                 tcx.sess,
                 span,
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 e758fe95d9c..3cb217335bd 100644
--- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
+++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
@@ -1333,7 +1333,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
 
         // We may fail to resolve higher-ranked lifetimes that are mentioned by APIT.
         // AST-based resolution does not care for impl-trait desugaring, which are the
-        // responibility of lowering. This may create a mismatch between the resolution
+        // responsibility of lowering. This may create a mismatch between the resolution
         // AST found (`region_def_id`) which points to HRTB, and what HIR allows.
         // ```
         // fn foo(x: impl for<'a> Trait<'a, Assoc = impl Copy + 'a>) {}
diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs
index 8fa3bcd68c3..507c24d540c 100644
--- a/compiler/rustc_hir_typeck/src/coercion.rs
+++ b/compiler/rustc_hir_typeck/src/coercion.rs
@@ -976,7 +976,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     /// Attempt to coerce an expression to a type, and return the
     /// adjusted type of the expression, if successful.
     /// Adjustments are only recorded if the coercion succeeded.
-    /// The expressions *must not* have any pre-existing adjustments.
+    /// The expressions *must not* have any preexisting adjustments.
     pub fn try_coerce(
         &self,
         expr: &hir::Expr<'_>,
@@ -1340,7 +1340,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
     }
 
     /// As an optimization, you can create a `CoerceMany` with a
-    /// pre-existing slice of expressions. In this case, you are
+    /// preexisting slice of expressions. In this case, you are
     /// expected to pass each element in the slice to `coerce(...)` in
     /// order. This is used with arrays in particular to avoid
     /// needlessly cloning the slice.
diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs
index 13442c31649..525acfdaa81 100644
--- a/compiler/rustc_hir_typeck/src/demand.rs
+++ b/compiler/rustc_hir_typeck/src/demand.rs
@@ -17,7 +17,6 @@ use rustc_middle::ty::print::with_no_trimmed_paths;
 use rustc_middle::ty::{self, Article, AssocItem, Ty, TypeAndMut, TypeFoldable};
 use rustc_span::symbol::{sym, Symbol};
 use rustc_span::{BytePos, Span, DUMMY_SP};
-use rustc_target::abi::FieldIdx;
 use rustc_trait_selection::infer::InferCtxtExt as _;
 use rustc_trait_selection::traits::ObligationCause;
 
@@ -875,7 +874,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     variant.fields.len() == 1
                 })
                 .filter_map(|variant| {
-                    let sole_field = &variant.fields[FieldIdx::from_u32(0)];
+                    let sole_field = &variant.single_field();
 
                     let field_is_local = sole_field.did.is_local();
                     let field_is_accessible =
diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs
index 3eee2278dca..5be78416e61 100644
--- a/compiler/rustc_hir_typeck/src/errors.rs
+++ b/compiler/rustc_hir_typeck/src/errors.rs
@@ -108,7 +108,7 @@ pub enum ExpectedReturnTypeLabel<'tcx> {
 
 #[derive(Diagnostic)]
 #[diag(hir_typeck_missing_parentheses_in_range, code = "E0689")]
-pub struct MissingParentheseInRange {
+pub struct MissingParenthesesInRange {
     #[primary_span]
     #[label(hir_typeck_missing_parentheses_in_range)]
     pub span: Span,
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index ffc73d64fc0..0c0a7515d9c 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -38,6 +38,7 @@ use rustc_infer::infer;
 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use rustc_infer::infer::DefineOpaqueTypes;
 use rustc_infer::infer::InferOk;
+use rustc_infer::traits::query::NoSolution;
 use rustc_infer::traits::ObligationCause;
 use rustc_middle::middle::stability;
 use rustc_middle::ty::adjustment::{Adjust, Adjustment, AllowTwoPhase};
@@ -53,6 +54,8 @@ use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_target::abi::FieldIdx;
 use rustc_target::spec::abi::Abi::RustIntrinsic;
 use rustc_trait_selection::infer::InferCtxtExt;
+use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
+use rustc_trait_selection::traits::ObligationCtxt;
 use rustc_trait_selection::traits::{self, ObligationCauseCode};
 
 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
@@ -2800,6 +2803,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     element_ty
                 }
                 None => {
+                    // Attempt to *shallowly* search for an impl which matches,
+                    // but has nested obligations which are unsatisfied.
+                    for (base_t, _) in self.autoderef(base.span, base_t).silence_errors() {
+                        if let Some((_, index_ty, element_ty)) =
+                            self.find_and_report_unsatisfied_index_impl(expr.hir_id, base, base_t)
+                        {
+                            self.demand_coerce(idx, idx_t, index_ty, None, AllowTwoPhase::No);
+                            return element_ty;
+                        }
+                    }
+
                     let mut err = type_error_struct!(
                         self.tcx.sess,
                         expr.span,
@@ -2843,6 +2857,82 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         }
     }
 
+    /// Try to match an implementation of `Index` against a self type, and report
+    /// the unsatisfied predicates that result from confirming this impl.
+    ///
+    /// Given an index expression, sometimes the `Self` type shallowly but does not
+    /// deeply satisfy an impl predicate. Instead of simply saying that the type
+    /// does not support being indexed, we want to point out exactly what nested
+    /// predicates cause this to be, so that the user can add them to fix their code.
+    fn find_and_report_unsatisfied_index_impl(
+        &self,
+        index_expr_hir_id: HirId,
+        base_expr: &hir::Expr<'_>,
+        base_ty: Ty<'tcx>,
+    ) -> Option<(ErrorGuaranteed, Ty<'tcx>, Ty<'tcx>)> {
+        let index_trait_def_id = self.tcx.lang_items().index_trait()?;
+        let index_trait_output_def_id = self.tcx.get_diagnostic_item(sym::IndexOutput)?;
+
+        let mut relevant_impls = vec![];
+        self.tcx.for_each_relevant_impl(index_trait_def_id, base_ty, |impl_def_id| {
+            relevant_impls.push(impl_def_id);
+        });
+        let [impl_def_id] = relevant_impls[..] else {
+            // Only report unsatisfied impl predicates if there's one impl
+            return None;
+        };
+
+        self.commit_if_ok(|_| {
+            let ocx = ObligationCtxt::new_in_snapshot(self);
+            let impl_substs = self.fresh_substs_for_item(base_expr.span, impl_def_id);
+            let impl_trait_ref =
+                self.tcx.impl_trait_ref(impl_def_id).unwrap().subst(self.tcx, impl_substs);
+            let cause = self.misc(base_expr.span);
+
+            // Match the impl self type against the base ty. If this fails,
+            // we just skip this impl, since it's not particularly useful.
+            let impl_trait_ref = ocx.normalize(&cause, self.param_env, impl_trait_ref);
+            ocx.eq(&cause, self.param_env, impl_trait_ref.self_ty(), base_ty)?;
+
+            // Register the impl's predicates. One of these predicates
+            // must be unsatisfied, or else we wouldn't have gotten here
+            // in the first place.
+            ocx.register_obligations(traits::predicates_for_generics(
+                |idx, span| {
+                    traits::ObligationCause::new(
+                        base_expr.span,
+                        self.body_id,
+                        if span.is_dummy() {
+                            traits::ExprItemObligation(impl_def_id, index_expr_hir_id, idx)
+                        } else {
+                            traits::ExprBindingObligation(impl_def_id, span, index_expr_hir_id, idx)
+                        },
+                    )
+                },
+                self.param_env,
+                self.tcx.predicates_of(impl_def_id).instantiate(self.tcx, impl_substs),
+            ));
+
+            // Normalize the output type, which we can use later on as the
+            // return type of the index expression...
+            let element_ty = ocx.normalize(
+                &cause,
+                self.param_env,
+                self.tcx.mk_projection(index_trait_output_def_id, impl_trait_ref.substs),
+            );
+
+            let errors = ocx.select_where_possible();
+            // There should be at least one error reported. If not, we
+            // will still delay a span bug in `report_fulfillment_errors`.
+            Ok::<_, NoSolution>((
+                self.err_ctxt().report_fulfillment_errors(&errors),
+                impl_trait_ref.substs.type_at(1),
+                element_ty,
+            ))
+        })
+        .ok()
+    }
+
     fn point_at_index_if_possible(
         &self,
         errors: &mut Vec<traits::FulfillmentError<'tcx>>,
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
index f736f7a9620..13a869caa8f 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
@@ -827,7 +827,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             }
             QPath::TypeRelative(ref qself, ref segment) => {
                 // Don't use `self.to_ty`, since this will register a WF obligation.
-                // If we're trying to call a non-existent method on a trait
+                // If we're trying to call a nonexistent method on a trait
                 // (e.g. `MyTrait::missing_method`), then resolution will
                 // give us a `QPath::TypeRelative` with a trait object as
                 // `qself`. In that case, we want to avoid registering a WF obligation
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 c3e5f9cb745..56c94505727 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
@@ -330,7 +330,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     /// expression mentioned.
     ///
     /// `blame_specific_arg_if_possible` will find the most-specific expression anywhere inside
-    /// the provided function call expression, and mark it as responsible for the fullfillment
+    /// the provided function call expression, and mark it as responsible for the fulfillment
     /// error.
     fn blame_specific_arg_if_possible(
         &self,
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
index e82821850d6..eef2b5009c8 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
@@ -794,7 +794,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             return;
         };
 
-        // get all where BoundPredicates here, because they are used in to cases below
+        // get all where BoundPredicates here, because they are used in two cases below
         let where_predicates = predicates
             .iter()
             .filter_map(|p| match p {
diff --git a/compiler/rustc_hir_typeck/src/generator_interior/mod.rs b/compiler/rustc_hir_typeck/src/generator_interior/mod.rs
index f3971080443..8feef332de8 100644
--- a/compiler/rustc_hir_typeck/src/generator_interior/mod.rs
+++ b/compiler/rustc_hir_typeck/src/generator_interior/mod.rs
@@ -650,7 +650,7 @@ fn check_must_not_suspend_ty<'tcx>(
                 },
             )
         }
-        // If drop tracking is enabled, we want to look through references, since the referrent
+        // If drop tracking is enabled, we want to look through references, since the referent
         // may not be considered live across the await point.
         ty::Ref(_region, ty, _mutability) if fcx.sess().opts.unstable_opts.drop_tracking => {
             let descr_pre = &format!("{}reference{} to ", data.descr_pre, plural_suffix);
diff --git a/compiler/rustc_hir_typeck/src/intrinsicck.rs b/compiler/rustc_hir_typeck/src/intrinsicck.rs
index 106f5bcd755..0fdb29a5e48 100644
--- a/compiler/rustc_hir_typeck/src/intrinsicck.rs
+++ b/compiler/rustc_hir_typeck/src/intrinsicck.rs
@@ -4,7 +4,7 @@ use rustc_hir as hir;
 use rustc_index::vec::Idx;
 use rustc_middle::ty::layout::{LayoutError, SizeSkeleton};
 use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
-use rustc_target::abi::{FieldIdx, Pointer, VariantIdx};
+use rustc_target::abi::{Pointer, VariantIdx};
 
 use super::FnCtxt;
 
@@ -28,7 +28,7 @@ fn unpack_option_like<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
         }
 
         if def.variant(data_idx).fields.len() == 1 {
-            return def.variant(data_idx).fields[FieldIdx::from_u32(0)].ty(tcx, substs);
+            return def.variant(data_idx).single_field().ty(tcx, substs);
         }
     }
 
diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs
index 900a6fa0d8d..db1f10f645f 100644
--- a/compiler/rustc_hir_typeck/src/method/suggest.rs
+++ b/compiler/rustc_hir_typeck/src/method/suggest.rs
@@ -1530,7 +1530,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     );
                     if pick.is_ok() {
                         let range_span = parent_expr.span.with_hi(expr.span.hi());
-                        tcx.sess.emit_err(errors::MissingParentheseInRange {
+                        tcx.sess.emit_err(errors::MissingParenthesesInRange {
                             span,
                             ty_str: ty_str.to_string(),
                             method_name: item_name.as_str().to_string(),
diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs
index af0bd26dec5..7160d1c67b2 100644
--- a/compiler/rustc_hir_typeck/src/pat.rs
+++ b/compiler/rustc_hir_typeck/src/pat.rs
@@ -1659,7 +1659,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         if tcx.sess.teach(&err.get_code().unwrap()) {
             err.note(
                 "This error indicates that a struct pattern attempted to \
-                 extract a non-existent field from a struct. Struct fields \
+                 extract a nonexistent field from a struct. Struct fields \
                  are identified by the name used before the colon : so struct \
                  patterns should resemble the declaration of the struct type \
                  being matched.\n\n\
diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs
index 41a6ad80b65..147b3e74d0f 100644
--- a/compiler/rustc_hir_typeck/src/upvar.rs
+++ b/compiler/rustc_hir_typeck/src/upvar.rs
@@ -223,7 +223,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let closure_hir_id = self.tcx.hir().local_def_id_to_hir_id(closure_def_id);
 
         if should_do_rust_2021_incompatible_closure_captures_analysis(self.tcx, closure_hir_id) {
-            self.perform_2229_migration_anaysis(closure_def_id, body_id, capture_clause, span);
+            self.perform_2229_migration_analysis(closure_def_id, body_id, capture_clause, span);
         }
 
         let after_feature_tys = self.final_upvar_tys(closure_def_id);
@@ -731,7 +731,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
     /// Perform the migration analysis for RFC 2229, and emit lint
     /// `disjoint_capture_drop_reorder` if needed.
-    fn perform_2229_migration_anaysis(
+    fn perform_2229_migration_analysis(
         &self,
         closure_def_id: LocalDefId,
         body_id: hir::BodyId,
diff --git a/compiler/rustc_incremental/src/persist/dirty_clean.rs b/compiler/rustc_incremental/src/persist/dirty_clean.rs
index 1d88dfd20c8..43274091cb8 100644
--- a/compiler/rustc_incremental/src/persist/dirty_clean.rs
+++ b/compiler/rustc_incremental/src/persist/dirty_clean.rs
@@ -139,7 +139,7 @@ pub fn check_dirty_clean_annotations(tcx: TyCtxt<'_>) {
         return;
     }
 
-    // can't add `#[rustc_clean]` etc without opting in to this feature
+    // can't add `#[rustc_clean]` etc without opting into this feature
     if !tcx.features().rustc_attrs {
         return;
     }
diff --git a/compiler/rustc_incremental/src/persist/fs.rs b/compiler/rustc_incremental/src/persist/fs.rs
index d6f83838a04..ec6d61f9e5f 100644
--- a/compiler/rustc_incremental/src/persist/fs.rs
+++ b/compiler/rustc_incremental/src/persist/fs.rs
@@ -601,7 +601,7 @@ fn string_to_timestamp(s: &str) -> Result<SystemTime, ()> {
 fn crate_path(sess: &Session, crate_name: Symbol, stable_crate_id: StableCrateId) -> PathBuf {
     let incr_dir = sess.opts.incremental.as_ref().unwrap().clone();
 
-    let stable_crate_id = base_n::encode(stable_crate_id.to_u64() as u128, INT_ENCODE_BASE);
+    let stable_crate_id = base_n::encode(stable_crate_id.as_u64() as u128, INT_ENCODE_BASE);
 
     let crate_name = format!("{}-{}", crate_name, stable_crate_id);
     incr_dir.join(crate_name)
diff --git a/compiler/rustc_infer/messages.ftl b/compiler/rustc_infer/messages.ftl
index c8998ea91bf..fdc4ff0896f 100644
--- a/compiler/rustc_infer/messages.ftl
+++ b/compiler/rustc_infer/messages.ftl
@@ -80,7 +80,7 @@ infer_subtype = ...so that the {$requirement ->
     [no_else] `if` missing an `else` returns `()`
     [fn_main_correct_type] `main` function has the correct type
     [fn_start_correct_type] `#[start]` function has the correct type
-    [intristic_correct_type] intrinsic has the correct type
+    [intrinsic_correct_type] intrinsic has the correct type
     [method_correct_type] method receiver has the correct type
     *[other] types are compatible
 }
@@ -93,7 +93,7 @@ infer_subtype_2 = ...so that {$requirement ->
     [no_else] `if` missing an `else` returns `()`
     [fn_main_correct_type] `main` function has the correct type
     [fn_start_correct_type] `#[start]` function has the correct type
-    [intristic_correct_type] intrinsic has the correct type
+    [intrinsic_correct_type] intrinsic has the correct type
     [method_correct_type] method receiver has the correct type
     *[other] types are compatible
 }
@@ -341,8 +341,8 @@ infer_await_note = calling an async function returns a future
 
 infer_prlf_defined_with_sub = the lifetime `{$sub_symbol}` defined here...
 infer_prlf_defined_without_sub = the lifetime defined here...
-infer_prlf_must_oultive_with_sup = ...must outlive the lifetime `{$sup_symbol}` defined here
-infer_prlf_must_oultive_without_sup = ...must outlive the lifetime defined here
+infer_prlf_must_outlive_with_sup = ...must outlive the lifetime `{$sup_symbol}` defined here
+infer_prlf_must_outlive_without_sup = ...must outlive the lifetime defined here
 infer_prlf_known_limitation = this is a known limitation that will be removed in the future (see issue #100013 <https://github.com/rust-lang/rust/issues/100013> for more information)
 
 infer_opaque_captures_lifetime = hidden type for `{$opaque_ty}` captures lifetime that does not appear in bounds
@@ -380,7 +380,7 @@ infer_oc_no_else = `if` may be missing an `else` clause
 infer_oc_no_diverge = `else` clause of `let...else` does not diverge
 infer_oc_fn_main_correct_type = `main` function has wrong type
 infer_oc_fn_start_correct_type = `#[start]` function has wrong type
-infer_oc_intristic_correct_type = intrinsic has wrong type
+infer_oc_intrinsic_correct_type = intrinsic has wrong type
 infer_oc_method_correct_type = mismatched `self` parameter type
 infer_oc_closure_selfref = closure/generator type that references itself
 infer_oc_cant_coerce = cannot coerce intrinsics to function pointers
diff --git a/compiler/rustc_infer/src/errors/mod.rs b/compiler/rustc_infer/src/errors/mod.rs
index 65b3dd1a892..b1e819e83f1 100644
--- a/compiler/rustc_infer/src/errors/mod.rs
+++ b/compiler/rustc_infer/src/errors/mod.rs
@@ -71,7 +71,7 @@ pub struct AmbiguousImpl<'a> {
 // Copy of `AnnotationRequired` for E0284
 #[derive(Diagnostic)]
 #[diag(infer_type_annotations_needed, code = "E0284")]
-pub struct AmbigousReturn<'a> {
+pub struct AmbiguousReturn<'a> {
     #[primary_span]
     pub span: Span,
     pub source_kind: &'static str,
@@ -1085,7 +1085,7 @@ pub enum PlaceholderRelationLfNotSatisfied {
         span: Span,
         #[note(infer_prlf_defined_with_sub)]
         sub_span: Span,
-        #[note(infer_prlf_must_oultive_with_sup)]
+        #[note(infer_prlf_must_outlive_with_sup)]
         sup_span: Span,
         sub_symbol: Symbol,
         sup_symbol: Symbol,
@@ -1098,7 +1098,7 @@ pub enum PlaceholderRelationLfNotSatisfied {
         span: Span,
         #[note(infer_prlf_defined_with_sub)]
         sub_span: Span,
-        #[note(infer_prlf_must_oultive_without_sup)]
+        #[note(infer_prlf_must_outlive_without_sup)]
         sup_span: Span,
         sub_symbol: Symbol,
         #[note(infer_prlf_known_limitation)]
@@ -1110,7 +1110,7 @@ pub enum PlaceholderRelationLfNotSatisfied {
         span: Span,
         #[note(infer_prlf_defined_without_sub)]
         sub_span: Span,
-        #[note(infer_prlf_must_oultive_with_sup)]
+        #[note(infer_prlf_must_outlive_with_sup)]
         sup_span: Span,
         sup_symbol: Symbol,
         #[note(infer_prlf_known_limitation)]
@@ -1122,7 +1122,7 @@ pub enum PlaceholderRelationLfNotSatisfied {
         span: Span,
         #[note(infer_prlf_defined_without_sub)]
         sub_span: Span,
-        #[note(infer_prlf_must_oultive_without_sup)]
+        #[note(infer_prlf_must_outlive_without_sup)]
         sup_span: Span,
         #[note(infer_prlf_known_limitation)]
         note: (),
@@ -1488,8 +1488,8 @@ pub enum ObligationCauseFailureCode {
         #[subdiagnostic]
         subdiags: Vec<TypeErrorAdditionalDiags>,
     },
-    #[diag(infer_oc_intristic_correct_type, code = "E0308")]
-    IntristicCorrectType {
+    #[diag(infer_oc_intrinsic_correct_type, code = "E0308")]
+    IntrinsicCorrectType {
         #[primary_span]
         span: Span,
         #[subdiagnostic]
diff --git a/compiler/rustc_infer/src/infer/canonical/query_response.rs b/compiler/rustc_infer/src/infer/canonical/query_response.rs
index e98f68ae5a8..257d3625929 100644
--- a/compiler/rustc_infer/src/infer/canonical/query_response.rs
+++ b/compiler/rustc_infer/src/infer/canonical/query_response.rs
@@ -467,11 +467,11 @@ impl<'tcx> InferCtxt<'tcx> {
                     }
                 }
                 GenericArgKind::Const(result_value) => {
-                    if let ty::ConstKind::Bound(debrujin, b) = result_value.kind() {
+                    if let ty::ConstKind::Bound(debruijn, b) = result_value.kind() {
                         // ...in which case we would set `canonical_vars[0]` to `Some(const X)`.
 
                         // We only allow a `ty::INNERMOST` index in substitutions.
-                        assert_eq!(debrujin, ty::INNERMOST);
+                        assert_eq!(debruijn, ty::INNERMOST);
                         opt_values[b] = Some(*original_value);
                     }
                 }
diff --git a/compiler/rustc_infer/src/infer/combine.rs b/compiler/rustc_infer/src/infer/combine.rs
index fe45b5ebe61..9b670c76a18 100644
--- a/compiler/rustc_infer/src/infer/combine.rs
+++ b/compiler/rustc_infer/src/infer/combine.rs
@@ -832,7 +832,7 @@ pub trait ObligationEmittingRelation<'tcx>: TypeRelation<'tcx> {
 
     /// Register predicates that must hold in order for this relation to hold. Uses
     /// a default obligation cause, [`ObligationEmittingRelation::register_obligations`] should
-    /// be used if control over the obligaton causes is required.
+    /// be used if control over the obligation causes is required.
     fn register_predicates(&mut self, obligations: impl IntoIterator<Item: ToPredicate<'tcx>>);
 
     /// Register an obligation that both constants must be equal to each other.
diff --git a/compiler/rustc_infer/src/infer/equate.rs b/compiler/rustc_infer/src/infer/equate.rs
index fe4a2dd3800..f90f7674b55 100644
--- a/compiler/rustc_infer/src/infer/equate.rs
+++ b/compiler/rustc_infer/src/infer/equate.rs
@@ -178,7 +178,7 @@ impl<'tcx> TypeRelation<'tcx> for Equate<'_, '_, 'tcx> {
     where
         T: Relate<'tcx>,
     {
-        // A binder is equal to itself if it's structually equal to itself
+        // A binder is equal to itself if it's structurally equal to itself
         if a == b {
             return Ok(a);
         }
diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
index 992b07db154..f6a4ddd7855 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
@@ -2886,7 +2886,7 @@ impl<'tcx> ObligationCauseExt<'tcx> for ObligationCause<'tcx> {
             LetElse => ObligationCauseFailureCode::NoDiverge { span, subdiags },
             MainFunctionType => ObligationCauseFailureCode::FnMainCorrectType { span },
             StartFunctionType => ObligationCauseFailureCode::FnStartCorrectType { span, subdiags },
-            IntrinsicType => ObligationCauseFailureCode::IntristicCorrectType { span, subdiags },
+            IntrinsicType => ObligationCauseFailureCode::IntrinsicCorrectType { span, subdiags },
             MethodReceiver => ObligationCauseFailureCode::MethodCorrectType { span, subdiags },
 
             // In the case where we have no more specific thing to
@@ -2943,7 +2943,7 @@ impl IntoDiagnosticArg for ObligationCauseAsDiagArg<'_> {
             IfExpressionWithNoElse => "no_else",
             MainFunctionType => "fn_main_correct_type",
             StartFunctionType => "fn_start_correct_type",
-            IntrinsicType => "intristic_correct_type",
+            IntrinsicType => "intrinsic_correct_type",
             MethodReceiver => "method_correct_type",
             _ => "other",
         }
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 75cc4e257bd..58e3159a4e2 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
@@ -1,5 +1,5 @@
 use crate::errors::{
-    AmbigousReturn, AmbiguousImpl, AnnotationRequired, InferenceBadError, NeedTypeInfoInGenerator,
+    AmbiguousImpl, AmbiguousReturn, AnnotationRequired, InferenceBadError, NeedTypeInfoInGenerator,
     SourceKindMultiSuggestion, SourceKindSubdiag,
 };
 use crate::infer::error_reporting::TypeErrCtxt;
@@ -368,7 +368,7 @@ impl<'tcx> InferCtxt<'tcx> {
                 bad_label,
             }
             .into_diagnostic(&self.tcx.sess.parse_sess.span_diagnostic),
-            TypeAnnotationNeeded::E0284 => AmbigousReturn {
+            TypeAnnotationNeeded::E0284 => AmbiguousReturn {
                 span,
                 source_kind,
                 source_name,
@@ -573,7 +573,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                 bad_label: None,
             }
             .into_diagnostic(&self.tcx.sess.parse_sess.span_diagnostic),
-            TypeAnnotationNeeded::E0284 => AmbigousReturn {
+            TypeAnnotationNeeded::E0284 => AmbiguousReturn {
                 span,
                 source_kind,
                 source_name: &name,
diff --git a/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs b/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs
index b38bbdfe7bb..e410172c8c8 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs
@@ -462,10 +462,7 @@ fn foo(&self) -> Self::T { String::new() }
         if let ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) = *proj_ty.self_ty().kind() {
             let opaque_local_def_id = def_id.as_local();
             let opaque_hir_ty = if let Some(opaque_local_def_id) = opaque_local_def_id {
-                match &tcx.hir().expect_item(opaque_local_def_id).kind {
-                    hir::ItemKind::OpaqueTy(opaque_hir_ty) => opaque_hir_ty,
-                    _ => bug!("The HirId comes from a `ty::Opaque`"),
-                }
+                tcx.hir().expect_item(opaque_local_def_id).expect_opaque_ty()
             } else {
                 return false;
             };
diff --git a/compiler/rustc_infer/src/infer/error_reporting/suggest.rs b/compiler/rustc_infer/src/infer/error_reporting/suggest.rs
index 4dc5fc451dd..d885d040707 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/suggest.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/suggest.rs
@@ -10,7 +10,6 @@ use rustc_middle::traits::{
 use rustc_middle::ty::print::with_no_trimmed_paths;
 use rustc_middle::ty::{self as ty, GenericArgKind, IsSuggestable, Ty, TypeVisitableExt};
 use rustc_span::{sym, BytePos, Span};
-use rustc_target::abi::FieldIdx;
 
 use crate::errors::{
     ConsiderAddingAwait, FnConsiderCasting, FnItemsAreDistinct, FnUniqTypes,
@@ -114,7 +113,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                         variant.fields.len() == 1 && variant.ctor_kind() == Some(CtorKind::Fn)
                     })
                     .filter_map(|variant| {
-                        let sole_field = &variant.fields[FieldIdx::from_u32(0)];
+                        let sole_field = &variant.single_field();
                         let sole_field_ty = sole_field.ty(self.tcx, substs);
                         if self.same_type_modulo_infer(sole_field_ty, exp_found.found) {
                             let variant_path =
diff --git a/compiler/rustc_infer/src/infer/higher_ranked/mod.rs b/compiler/rustc_infer/src/infer/higher_ranked/mod.rs
index a63cfbc919c..c304cd25c9c 100644
--- a/compiler/rustc_infer/src/infer/higher_ranked/mod.rs
+++ b/compiler/rustc_infer/src/infer/higher_ranked/mod.rs
@@ -42,7 +42,7 @@ impl<'a, 'tcx> CombineFields<'a, 'tcx> {
 
         // Next, we instantiate each bound region in the subtype
         // with a fresh region variable. These region variables --
-        // but no other pre-existing region variables -- can name
+        // but no other preexisting region variables -- can name
         // the placeholders.
         let sub_prime = self.infcx.instantiate_binder_with_fresh_vars(span, HigherRankedType, sub);
 
diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs
index 3a0a0494a7e..680465bdab6 100644
--- a/compiler/rustc_infer/src/infer/opaque_types.rs
+++ b/compiler/rustc_infer/src/infer/opaque_types.rs
@@ -392,12 +392,7 @@ impl<'tcx> InferCtxt<'tcx> {
     /// defining scope.
     #[instrument(skip(self), level = "trace", ret)]
     fn opaque_type_origin_unchecked(&self, def_id: LocalDefId) -> OpaqueTyOrigin {
-        match self.tcx.hir().expect_item(def_id).kind {
-            hir::ItemKind::OpaqueTy(hir::OpaqueTy { origin, .. }) => origin,
-            ref itemkind => {
-                bug!("weird opaque type: {:?}, {:#?}", def_id, itemkind)
-            }
-        }
+        self.tcx.hir().expect_item(def_id).expect_opaque_ty().origin
     }
 }
 
diff --git a/compiler/rustc_infer/src/infer/sub.rs b/compiler/rustc_infer/src/infer/sub.rs
index 0dd73a6e999..3766c250a9c 100644
--- a/compiler/rustc_infer/src/infer/sub.rs
+++ b/compiler/rustc_infer/src/infer/sub.rs
@@ -210,7 +210,7 @@ impl<'tcx> TypeRelation<'tcx> for Sub<'_, '_, 'tcx> {
     where
         T: Relate<'tcx>,
     {
-        // A binder is always a subtype of itself if it's structually equal to itself
+        // A binder is always a subtype of itself if it's structurally equal to itself
         if a == b {
             return Ok(a);
         }
diff --git a/compiler/rustc_infer/src/traits/project.rs b/compiler/rustc_infer/src/traits/project.rs
index ac455055b43..8d0af738dd1 100644
--- a/compiler/rustc_infer/src/traits/project.rs
+++ b/compiler/rustc_infer/src/traits/project.rs
@@ -103,7 +103,7 @@ pub enum ProjectionCacheEntry<'tcx> {
         /// if this field is set. Evaluation only
         /// cares about the final result, so we don't
         /// care about any region constraint side-effects
-        /// produced by evaluating the sub-boligations.
+        /// produced by evaluating the sub-obligations.
         ///
         /// Additionally, we will clear out the sub-obligations
         /// entirely if we ever evaluate the cache entry (along
diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl
index db15b176df0..3d1b8f8ed95 100644
--- a/compiler/rustc_lint/messages.ftl
+++ b/compiler/rustc_lint/messages.ftl
@@ -445,7 +445,7 @@ lint_builtin_incomplete_features = the feature `{$name}` is incomplete and may n
     .help = consider using `min_{$name}` instead, which is more stable and complete
 
 lint_builtin_unpermitted_type_init_zeroed = the type `{$ty}` does not permit zero-initialization
-lint_builtin_unpermitted_type_init_unint = the type `{$ty}` does not permit being left uninitialized
+lint_builtin_unpermitted_type_init_uninit = the type `{$ty}` does not permit being left uninitialized
 
 lint_builtin_unpermitted_type_init_label = this code causes undefined behavior when executed
 lint_builtin_unpermitted_type_init_label_suggestion = help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index 6b387df785e..55bef6d3b3d 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -22,7 +22,7 @@
 
 use crate::fluent_generated as fluent;
 use crate::{
-    errors::BuiltinEllpisisInclusiveRangePatterns,
+    errors::BuiltinEllipsisInclusiveRangePatterns,
     lints::{
         BuiltinAnonymousParams, BuiltinBoxPointers, BuiltinClashingExtern,
         BuiltinClashingExternSub, BuiltinConstNoMangle, BuiltinDeprecatedAttrLink,
@@ -1711,13 +1711,13 @@ impl EarlyLintPass for EllipsisInclusiveRangePatterns {
             }
         }
 
-        let (parenthesise, endpoints) = match &pat.kind {
+        let (parentheses, endpoints) = match &pat.kind {
             PatKind::Ref(subpat, _) => (true, matches_ellipsis_pat(&subpat)),
             _ => (false, matches_ellipsis_pat(pat)),
         };
 
         if let Some((start, end, join)) = endpoints {
-            if parenthesise {
+            if parentheses {
                 self.node_id = Some(pat.id);
                 let end = expr_to_string(&end);
                 let replace = match start {
@@ -1725,7 +1725,7 @@ impl EarlyLintPass for EllipsisInclusiveRangePatterns {
                     None => format!("&(..={})", end),
                 };
                 if join.edition() >= Edition::Edition2021 {
-                    cx.sess().emit_err(BuiltinEllpisisInclusiveRangePatterns {
+                    cx.sess().emit_err(BuiltinEllipsisInclusiveRangePatterns {
                         span: pat.span,
                         suggestion: pat.span,
                         replace,
@@ -1743,7 +1743,7 @@ impl EarlyLintPass for EllipsisInclusiveRangePatterns {
             } else {
                 let replace = "..=";
                 if join.edition() >= Edition::Edition2021 {
-                    cx.sess().emit_err(BuiltinEllpisisInclusiveRangePatterns {
+                    cx.sess().emit_err(BuiltinEllipsisInclusiveRangePatterns {
                         span: pat.span,
                         suggestion: join,
                         replace: replace.to_string(),
@@ -2560,7 +2560,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue {
                             .subst(cx.tcx, substs)
                             .apply_any_module(cx.tcx, cx.param_env)
                         {
-                            // Entirely skip uninhbaited variants.
+                            // Entirely skip uninhabited variants.
                             Some(false) => return None,
                             // Forward the others, but remember which ones are definitely inhabited.
                             Some(true) => true,
@@ -2628,7 +2628,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue {
             if let Some(err) = with_no_trimmed_paths!(ty_find_init_error(cx, conjured_ty, init)) {
                 let msg = match init {
                     InitKind::Zeroed => fluent::lint_builtin_unpermitted_type_init_zeroed,
-                    InitKind::Uninit => fluent::lint_builtin_unpermitted_type_init_unint,
+                    InitKind::Uninit => fluent::lint_builtin_unpermitted_type_init_uninit,
                 };
                 let sub = BuiltinUnpermittedTypeInitSub { err };
                 cx.emit_spanned_lint(
diff --git a/compiler/rustc_lint/src/errors.rs b/compiler/rustc_lint/src/errors.rs
index 9af5284df1e..bbae3d368f4 100644
--- a/compiler/rustc_lint/src/errors.rs
+++ b/compiler/rustc_lint/src/errors.rs
@@ -81,7 +81,7 @@ pub struct UnknownToolInScopedLint {
 
 #[derive(Diagnostic)]
 #[diag(lint_builtin_ellipsis_inclusive_range_patterns, code = "E0783")]
-pub struct BuiltinEllpisisInclusiveRangePatterns {
+pub struct BuiltinEllipsisInclusiveRangePatterns {
     #[primary_span]
     pub span: Span,
     #[suggestion(style = "short", code = "{replace}", applicability = "machine-applicable")]
diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs
index 80a64e59c0f..d677d51881e 100644
--- a/compiler/rustc_lint/src/unused.rs
+++ b/compiler/rustc_lint/src/unused.rs
@@ -569,36 +569,50 @@ trait UnusedDelimLint {
             }
         }
 
-        // Prevent false-positives in cases like `fn x() -> u8 { ({ 0 } + 1) }`
-        let lhs_needs_parens = {
+        // Check if LHS needs parens to prevent false-positives in cases like `fn x() -> u8 { ({ 0 } + 1) }`.
+        {
             let mut innermost = inner;
             loop {
                 innermost = match &innermost.kind {
-                    ExprKind::Binary(_, lhs, _rhs) => lhs,
+                    ExprKind::Binary(_op, lhs, _rhs) => lhs,
                     ExprKind::Call(fn_, _params) => fn_,
                     ExprKind::Cast(expr, _ty) => expr,
                     ExprKind::Type(expr, _ty) => expr,
                     ExprKind::Index(base, _subscript) => base,
-                    _ => break false,
+                    _ => break,
                 };
                 if !classify::expr_requires_semi_to_be_stmt(innermost) {
-                    break true;
+                    return true;
                 }
             }
-        };
+        }
 
-        lhs_needs_parens
-            || (followed_by_block
-                && match &inner.kind {
-                    ExprKind::Ret(_)
-                    | ExprKind::Break(..)
-                    | ExprKind::Yield(..)
-                    | ExprKind::Yeet(..) => true,
-                    ExprKind::Range(_lhs, Some(rhs), _limits) => {
-                        matches!(rhs.kind, ExprKind::Block(..))
-                    }
-                    _ => parser::contains_exterior_struct_lit(&inner),
-                })
+        // Check if RHS needs parens to prevent false-positives in cases like `if (() == return) {}`.
+        if !followed_by_block {
+            return false;
+        }
+        let mut innermost = inner;
+        loop {
+            innermost = match &innermost.kind {
+                ExprKind::Unary(_op, expr) => expr,
+                ExprKind::Binary(_op, _lhs, rhs) => rhs,
+                ExprKind::AssignOp(_op, _lhs, rhs) => rhs,
+                ExprKind::Assign(_lhs, rhs, _span) => rhs,
+
+                ExprKind::Ret(_) | ExprKind::Yield(..) | ExprKind::Yeet(..) => return true,
+
+                ExprKind::Break(_label, None) => return false,
+                ExprKind::Break(_label, Some(break_expr)) => {
+                    return matches!(break_expr.kind, ExprKind::Block(..));
+                }
+
+                ExprKind::Range(_lhs, Some(rhs), _limits) => {
+                    return matches!(rhs.kind, ExprKind::Block(..));
+                }
+
+                _ => return parser::contains_exterior_struct_lit(&inner),
+            }
+        }
     }
 
     fn emit_unused_delims_expr(
diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs
index 9d6ab0b75df..b223b8c137a 100644
--- a/compiler/rustc_lint_defs/src/builtin.rs
+++ b/compiler/rustc_lint_defs/src/builtin.rs
@@ -1021,7 +1021,7 @@ declare_lint! {
 
 declare_lint! {
     /// The `invalid_alignment` lint detects dereferences of misaligned pointers during
-    /// constant evluation.
+    /// constant evaluation.
     ///
     /// ### Example
     ///
@@ -1854,7 +1854,7 @@ declare_lint! {
     /// When new methods are added to traits in the standard library, they are
     /// usually added in an "unstable" form which is only available on the
     /// [nightly channel] with a [`feature` attribute]. If there is any
-    /// pre-existing code which extends a trait to have a method with the same
+    /// preexisting code which extends a trait to have a method with the same
     /// name, then the names will collide. In the future, when the method is
     /// stabilized, this will cause an error due to the ambiguity. This lint
     /// is an early-warning to let you know that there may be a collision in
diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
index 08e38b0c9d5..c9acbab253e 100644
--- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
@@ -811,7 +811,7 @@ LLVMRustOptimize(
   ModulePassManager MPM;
   bool NeedThinLTOBufferPasses = UseThinLTOBuffers;
   if (!NoPrepopulatePasses) {
-    // The pre-link pipelines don't support O0 and require using budilO0DefaultPipeline() instead.
+    // The pre-link pipelines don't support O0 and require using buildO0DefaultPipeline() instead.
     // At the same time, the LTO pipelines do support O0 and using them is required.
     bool IsLTO = OptStage == LLVMRustOptStage::ThinLTO || OptStage == LLVMRustOptStage::FatLTO;
     if (OptLevel == OptimizationLevel::O0 && !IsLTO) {
diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs
index 2930ce75028..951fb303e3c 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder.rs
@@ -117,7 +117,7 @@ pub(crate) struct CrateMetadata {
 
     /// Additional data used for decoding `HygieneData` (e.g. `SyntaxContext`
     /// and `ExpnId`).
-    /// Note that we store a `HygieneDecodeContext` for each `CrateMetadat`. This is
+    /// Note that we store a `HygieneDecodeContext` for each `CrateMetadata`. This is
     /// because `SyntaxContext` ids are not globally unique, so we need
     /// to track which ids we've decoded on a per-crate basis.
     hygiene_context: HygieneDecodeContext,
@@ -627,7 +627,7 @@ impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for Symbol {
                 let pos = d.read_usize();
                 let old_pos = d.opaque.position();
 
-                // move to str ofset and read
+                // move to str offset and read
                 d.opaque.set_position(pos);
                 let s = d.read_str();
                 let sym = Symbol::intern(s);
@@ -998,9 +998,8 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
         let ident = self.item_ident(id, sess);
         let res = Res::Def(self.def_kind(id), self.local_def_id(id));
         let vis = self.get_visibility(id);
-        let span = self.get_span(id, sess);
 
-        ModChild { ident, res, vis, span, reexport_chain: Default::default() }
+        ModChild { ident, res, vis, reexport_chain: Default::default() }
     }
 
     /// Iterates over all named children of the given module,
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index 657b903e0a8..d6500cd93a7 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -7,7 +7,7 @@ use rustc_ast::Attribute;
 use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_data_structures::fx::{FxHashMap, FxIndexSet};
 use rustc_data_structures::memmap::{Mmap, MmapMut};
-use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
+use rustc_data_structures::stable_hasher::{Hash128, HashStable, StableHasher};
 use rustc_data_structures::sync::{join, par_iter, Lrc, ParallelIterator};
 use rustc_data_structures::temp_dir::MaybeTempDir;
 use rustc_hir as hir;
@@ -531,7 +531,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
                         adapted.name_hash = {
                             let mut hasher: StableHasher = StableHasher::new();
                             adapted.name.hash(&mut hasher);
-                            hasher.finish::<u128>()
+                            hasher.finish::<Hash128>()
                         };
                         Lrc::new(adapted)
                     } else {
@@ -823,6 +823,7 @@ fn should_encode_span(def_kind: DefKind) -> bool {
         | DefKind::TraitAlias
         | DefKind::AssocTy
         | DefKind::TyParam
+        | DefKind::ConstParam
         | DefKind::Fn
         | DefKind::Const
         | DefKind::Static(_)
@@ -830,6 +831,8 @@ fn should_encode_span(def_kind: DefKind) -> bool {
         | DefKind::AssocFn
         | DefKind::AssocConst
         | DefKind::Macro(_)
+        | DefKind::ExternCrate
+        | DefKind::Use
         | DefKind::AnonConst
         | DefKind::InlineConst
         | DefKind::OpaqueTy
@@ -837,10 +840,7 @@ fn should_encode_span(def_kind: DefKind) -> bool {
         | DefKind::Impl { .. }
         | DefKind::Closure
         | DefKind::Generator => true,
-        DefKind::ConstParam
-        | DefKind::ExternCrate
-        | DefKind::Use
-        | DefKind::ForeignMod
+        DefKind::ForeignMod
         | DefKind::ImplTraitPlaceholder
         | DefKind::LifetimeParam
         | DefKind::GlobalAsm => false,
@@ -1469,8 +1469,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
 
         match impl_item.kind {
             ty::AssocKind::Fn => {
-                let ast_item = self.tcx.hir().expect_impl_item(def_id.expect_local());
-                let hir::ImplItemKind::Fn(ref sig, body) = ast_item.kind else { bug!() };
+                let (sig, body) =
+                    self.tcx.hir().expect_impl_item(def_id.expect_local()).expect_fn();
                 self.tables.asyncness.set_some(def_id.index, sig.header.asyncness);
                 record_array!(self.tables.fn_arg_names[def_id] <- self.tcx.hir().body_param_names(body));
                 // Can be inside `impl const Trait`, so using sig.header.constness is not reliable
diff --git a/compiler/rustc_middle/src/dep_graph/dep_node.rs b/compiler/rustc_middle/src/dep_graph/dep_node.rs
index 865bb70afb5..82e396a9dd3 100644
--- a/compiler/rustc_middle/src/dep_graph/dep_node.rs
+++ b/compiler/rustc_middle/src/dep_graph/dep_node.rs
@@ -357,7 +357,7 @@ impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for HirId {
         Fingerprint::new(
             // `owner` is local, so is completely defined by the local hash
             def_path_hash.local_hash(),
-            local_id.as_u32().into(),
+            local_id.as_u32() as u64,
         )
     }
 
@@ -370,7 +370,7 @@ impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for HirId {
     #[inline(always)]
     fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self> {
         if tcx.fingerprint_style(dep_node.kind) == FingerprintStyle::HirId {
-            let (local_hash, local_id) = Fingerprint::from(dep_node.hash).as_value();
+            let (local_hash, local_id) = Fingerprint::from(dep_node.hash).split();
             let def_path_hash = DefPathHash::new(tcx.sess.local_stable_crate_id(), local_hash);
             let def_id = tcx
                 .def_path_hash_to_def_id(def_path_hash, &mut || {
@@ -378,6 +378,7 @@ impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for HirId {
                 })
                 .expect_local();
             let local_id = local_id
+                .as_u64()
                 .try_into()
                 .unwrap_or_else(|_| panic!("local id should be u32, found {:?}", local_id));
             Some(HirId { owner: OwnerId { def_id }, local_id: ItemLocalId::from_u32(local_id) })
diff --git a/compiler/rustc_middle/src/infer/canonical.rs b/compiler/rustc_middle/src/infer/canonical.rs
index e63121475a1..c4e41e00520 100644
--- a/compiler/rustc_middle/src/infer/canonical.rs
+++ b/compiler/rustc_middle/src/infer/canonical.rs
@@ -392,10 +392,8 @@ pub type QueryOutlivesConstraint<'tcx> =
     (ty::OutlivesPredicate<GenericArg<'tcx>, Region<'tcx>>, ConstraintCategory<'tcx>);
 
 TrivialTypeTraversalAndLiftImpls! {
-    for <'tcx> {
-        crate::infer::canonical::Certainty,
-        crate::infer::canonical::CanonicalTyVarKind,
-    }
+    crate::infer::canonical::Certainty,
+    crate::infer::canonical::CanonicalTyVarKind,
 }
 
 impl<'tcx> CanonicalVarValues<'tcx> {
diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs
index 1ddc08eac7d..2fa769d3abb 100644
--- a/compiler/rustc_middle/src/lib.rs
+++ b/compiler/rustc_middle/src/lib.rs
@@ -59,6 +59,7 @@
 #![feature(result_option_inspect)]
 #![feature(const_option)]
 #![feature(trait_alias)]
+#![feature(ptr_alignment_type)]
 #![recursion_limit = "512"]
 #![allow(rustc::potential_query_instability)]
 
diff --git a/compiler/rustc_middle/src/macros.rs b/compiler/rustc_middle/src/macros.rs
index 89014f62d4d..cd1c6c330bc 100644
--- a/compiler/rustc_middle/src/macros.rs
+++ b/compiler/rustc_middle/src/macros.rs
@@ -43,34 +43,26 @@ macro_rules! span_bug {
 
 #[macro_export]
 macro_rules! CloneLiftImpls {
-    (for <$tcx:lifetime> { $($ty:ty,)+ }) => {
+    ($($ty:ty,)+) => {
         $(
-            impl<$tcx> $crate::ty::Lift<$tcx> for $ty {
+            impl<'tcx> $crate::ty::Lift<'tcx> for $ty {
                 type Lifted = Self;
-                fn lift_to_tcx(self, _: $crate::ty::TyCtxt<$tcx>) -> Option<Self> {
+                fn lift_to_tcx(self, _: $crate::ty::TyCtxt<'tcx>) -> Option<Self> {
                     Some(self)
                 }
             }
         )+
     };
-
-    ($($ty:ty,)+) => {
-        CloneLiftImpls! {
-            for <'tcx> {
-                $($ty,)+
-            }
-        }
-    };
 }
 
 /// Used for types that are `Copy` and which **do not care arena
 /// allocated data** (i.e., don't need to be folded).
 #[macro_export]
 macro_rules! TrivialTypeTraversalImpls {
-    (for <$tcx:lifetime> { $($ty:ty,)+ }) => {
+    ($($ty:ty,)+) => {
         $(
-            impl<$tcx> $crate::ty::fold::TypeFoldable<$crate::ty::TyCtxt<$tcx>> for $ty {
-                fn try_fold_with<F: $crate::ty::fold::FallibleTypeFolder<$crate::ty::TyCtxt<$tcx>>>(
+            impl<'tcx> $crate::ty::fold::TypeFoldable<$crate::ty::TyCtxt<'tcx>> for $ty {
+                fn try_fold_with<F: $crate::ty::fold::FallibleTypeFolder<$crate::ty::TyCtxt<'tcx>>>(
                     self,
                     _: &mut F,
                 ) -> ::std::result::Result<Self, F::Error> {
@@ -78,7 +70,7 @@ macro_rules! TrivialTypeTraversalImpls {
                 }
 
                 #[inline]
-                fn fold_with<F: $crate::ty::fold::TypeFolder<$crate::ty::TyCtxt<$tcx>>>(
+                fn fold_with<F: $crate::ty::fold::TypeFolder<$crate::ty::TyCtxt<'tcx>>>(
                     self,
                     _: &mut F,
                 ) -> Self {
@@ -86,9 +78,9 @@ macro_rules! TrivialTypeTraversalImpls {
                 }
             }
 
-            impl<$tcx> $crate::ty::visit::TypeVisitable<$crate::ty::TyCtxt<$tcx>> for $ty {
+            impl<'tcx> $crate::ty::visit::TypeVisitable<$crate::ty::TyCtxt<'tcx>> for $ty {
                 #[inline]
-                fn visit_with<F: $crate::ty::visit::TypeVisitor<$crate::ty::TyCtxt<$tcx>>>(
+                fn visit_with<F: $crate::ty::visit::TypeVisitor<$crate::ty::TyCtxt<'tcx>>>(
                     &self,
                     _: &mut F)
                     -> ::std::ops::ControlFlow<F::BreakTy>
@@ -98,14 +90,6 @@ macro_rules! TrivialTypeTraversalImpls {
             }
         )+
     };
-
-    ($($ty:ty,)+) => {
-        TrivialTypeTraversalImpls! {
-            for<'tcx> {
-                $($ty,)+
-            }
-        }
-    };
 }
 
 #[macro_export]
diff --git a/compiler/rustc_middle/src/metadata.rs b/compiler/rustc_middle/src/metadata.rs
index f3170e0ec0e..674402cb4bf 100644
--- a/compiler/rustc_middle/src/metadata.rs
+++ b/compiler/rustc_middle/src/metadata.rs
@@ -4,7 +4,6 @@ use rustc_hir::def::Res;
 use rustc_macros::HashStable;
 use rustc_span::def_id::DefId;
 use rustc_span::symbol::Ident;
-use rustc_span::Span;
 use smallvec::SmallVec;
 
 /// A simplified version of `ImportKind` from resolve.
@@ -41,8 +40,6 @@ pub struct ModChild {
     pub res: Res<!>,
     /// Visibility of the item.
     pub vis: ty::Visibility<DefId>,
-    /// Span of the item.
-    pub span: Span,
     /// Reexport chain linking this module child to its original reexported item.
     /// Empty if the module child is a proper item.
     pub reexport_chain: SmallVec<[Reexport; 2]>,
diff --git a/compiler/rustc_middle/src/middle/exported_symbols.rs b/compiler/rustc_middle/src/middle/exported_symbols.rs
index c0c0fd07b6e..9041da9a060 100644
--- a/compiler/rustc_middle/src/middle/exported_symbols.rs
+++ b/compiler/rustc_middle/src/middle/exported_symbols.rs
@@ -72,6 +72,6 @@ pub fn metadata_symbol_name(tcx: TyCtxt<'_>) -> String {
     format!(
         "rust_metadata_{}_{:08x}",
         tcx.crate_name(LOCAL_CRATE),
-        tcx.sess.local_stable_crate_id().to_u64(),
+        tcx.sess.local_stable_crate_id(),
     )
 }
diff --git a/compiler/rustc_middle/src/mir/interpret/allocation/init_mask.rs b/compiler/rustc_middle/src/mir/interpret/allocation/init_mask.rs
index dcb56a1755e..d4dd56a42c1 100644
--- a/compiler/rustc_middle/src/mir/interpret/allocation/init_mask.rs
+++ b/compiler/rustc_middle/src/mir/interpret/allocation/init_mask.rs
@@ -5,7 +5,9 @@ use std::hash;
 use std::iter;
 use std::ops::Range;
 
+use rustc_serialize::{Decodable, Encodable};
 use rustc_target::abi::Size;
+use rustc_type_ir::{TyDecoder, TyEncoder};
 
 use super::AllocRange;
 
@@ -182,11 +184,39 @@ impl InitMask {
 /// The actual materialized blocks of the bitmask, when we can't keep the `InitMask` lazy.
 // Note: for performance reasons when interning, some of the fields can be partially
 // hashed. (see the `Hash` impl below for more details), so the impl is not derived.
-#[derive(Clone, Debug, Eq, PartialEq, TyEncodable, TyDecodable, HashStable)]
+#[derive(Clone, Debug, Eq, PartialEq, HashStable)]
 struct InitMaskMaterialized {
     blocks: Vec<Block>,
 }
 
+// `Block` is a `u64`, but it is a bitmask not a numeric value. If we were to just derive
+// Encodable and Decodable we would apply varint encoding to the bitmasks, which is slower
+// and also produces more output when the high bits of each `u64` are occupied.
+// Note: There is probably a remaining optimization for masks that do not use an entire
+// `Block`.
+impl<E: TyEncoder> Encodable<E> for InitMaskMaterialized {
+    fn encode(&self, encoder: &mut E) {
+        encoder.emit_usize(self.blocks.len());
+        for block in &self.blocks {
+            encoder.emit_raw_bytes(&block.to_le_bytes());
+        }
+    }
+}
+
+// This implementation is deliberately not derived, see the matching `Encodable` impl.
+impl<D: TyDecoder> Decodable<D> for InitMaskMaterialized {
+    fn decode(decoder: &mut D) -> Self {
+        let num_blocks = decoder.read_usize();
+        let mut blocks = Vec::with_capacity(num_blocks);
+        for _ in 0..num_blocks {
+            let bytes = decoder.read_raw_bytes(8);
+            let block = u64::from_le_bytes(bytes.try_into().unwrap());
+            blocks.push(block);
+        }
+        InitMaskMaterialized { blocks }
+    }
+}
+
 // Const allocations are only hashed for interning. However, they can be large, making the hashing
 // expensive especially since it uses `FxHash`: it's better suited to short keys, not potentially
 // big buffers like the allocation's init mask. We can partially hash some fields when they're
diff --git a/compiler/rustc_middle/src/mir/interpret/pointer.rs b/compiler/rustc_middle/src/mir/interpret/pointer.rs
index 60927eed85d..65d04919357 100644
--- a/compiler/rustc_middle/src/mir/interpret/pointer.rs
+++ b/compiler/rustc_middle/src/mir/interpret/pointer.rs
@@ -102,7 +102,7 @@ impl<T: HasDataLayout> PointerArithmetic for T {}
 /// This trait abstracts over the kind of provenance that is associated with a `Pointer`. It is
 /// mostly opaque; the `Machine` trait extends it with some more operations that also have access to
 /// some global state.
-/// The `Debug` rendering is used to distplay bare provenance, and for the default impl of `fmt`.
+/// The `Debug` rendering is used to display bare provenance, and for the default impl of `fmt`.
 pub trait Provenance: Copy + fmt::Debug {
     /// Says whether the `offset` field of `Pointer`s with this provenance is the actual physical address.
     /// - If `false`, the offset *must* be relative. This means the bytes representing a pointer are
diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs
index 2ea8602af12..f985aae9a22 100644
--- a/compiler/rustc_middle/src/mir/mod.rs
+++ b/compiler/rustc_middle/src/mir/mod.rs
@@ -714,9 +714,7 @@ pub enum BindingForm<'tcx> {
 }
 
 TrivialTypeTraversalAndLiftImpls! {
-    for<'tcx> {
-        BindingForm<'tcx>,
-    }
+    BindingForm<'tcx>,
 }
 
 mod binding_form_impl {
diff --git a/compiler/rustc_middle/src/mir/mono.rs b/compiler/rustc_middle/src/mir/mono.rs
index f592f1515c1..a9468a90b53 100644
--- a/compiler/rustc_middle/src/mir/mono.rs
+++ b/compiler/rustc_middle/src/mir/mono.rs
@@ -4,7 +4,7 @@ use rustc_attr::InlineAttr;
 use rustc_data_structures::base_n;
 use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_data_structures::fx::FxHashMap;
-use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
+use rustc_data_structures::stable_hasher::{Hash128, HashStable, StableHasher};
 use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
 use rustc_hir::ItemId;
 use rustc_index::vec::Idx;
@@ -313,8 +313,8 @@ impl<'tcx> CodegenUnit<'tcx> {
         // avoid collisions and is still reasonably short for filenames.
         let mut hasher = StableHasher::new();
         human_readable_name.hash(&mut hasher);
-        let hash: u128 = hasher.finish();
-        let hash = hash & ((1u128 << 80) - 1);
+        let hash: Hash128 = hasher.finish();
+        let hash = hash.as_u128() & ((1u128 << 80) - 1);
         base_n::encode(hash, base_n::CASE_INSENSITIVE)
     }
 
@@ -505,22 +505,13 @@ impl<'tcx> CodegenUnitNameBuilder<'tcx> {
             // instantiating stuff for upstream crates.
             let local_crate_id = if cnum != LOCAL_CRATE {
                 let local_stable_crate_id = tcx.sess.local_stable_crate_id();
-                format!(
-                    "-in-{}.{:08x}",
-                    tcx.crate_name(LOCAL_CRATE),
-                    local_stable_crate_id.to_u64() as u32,
-                )
+                format!("-in-{}.{:08x}", tcx.crate_name(LOCAL_CRATE), local_stable_crate_id)
             } else {
                 String::new()
             };
 
             let stable_crate_id = tcx.sess.local_stable_crate_id();
-            format!(
-                "{}.{:08x}{}",
-                tcx.crate_name(cnum),
-                stable_crate_id.to_u64() as u32,
-                local_crate_id,
-            )
+            format!("{}.{:08x}{}", tcx.crate_name(cnum), stable_crate_id, local_crate_id)
         });
 
         write!(cgu_name, "{}", crate_prefix).unwrap();
diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs
index 135889d0da8..c38a347809f 100644
--- a/compiler/rustc_middle/src/mir/syntax.rs
+++ b/compiler/rustc_middle/src/mir/syntax.rs
@@ -251,7 +251,7 @@ pub enum StatementKind<'tcx> {
     /// **Needs clarification**: The implication of the above idea would be that assignment implies
     /// that the resulting value is initialized. I believe we could commit to this separately from
     /// committing to whatever part of the memory model we would need to decide on to make the above
-    /// paragragh precise. Do we want to?
+    /// paragraph precise. Do we want to?
     ///
     /// Assignments in which the types of the place and rvalue differ are not well-formed.
     ///
@@ -997,7 +997,7 @@ pub type PlaceElem<'tcx> = ProjectionElem<Local, Ty<'tcx>>;
 /// This is what is implemented in miri today. Are these the semantics we want for MIR? Is this
 /// something we can even decide without knowing more about Rust's memory model?
 ///
-/// **Needs clarifiation:** Is loading a place that has its variant index set well-formed? Miri
+/// **Needs clarification:** Is loading a place that has its variant index set well-formed? Miri
 /// currently implements it, but it seems like this may be something to check against in the
 /// validator.
 #[derive(Clone, PartialEq, TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable, TypeVisitable)]
diff --git a/compiler/rustc_middle/src/mir/type_foldable.rs b/compiler/rustc_middle/src/mir/type_foldable.rs
index 9881583214e..ace856b9f95 100644
--- a/compiler/rustc_middle/src/mir/type_foldable.rs
+++ b/compiler/rustc_middle/src/mir/type_foldable.rs
@@ -25,9 +25,7 @@ TrivialTypeTraversalAndLiftImpls! {
 }
 
 TrivialTypeTraversalImpls! {
-    for <'tcx> {
-        ConstValue<'tcx>,
-    }
+    ConstValue<'tcx>,
 }
 
 impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for &'tcx [InlineAsmTemplatePiece] {
diff --git a/compiler/rustc_middle/src/ty/abstract_const.rs b/compiler/rustc_middle/src/ty/abstract_const.rs
index f889ce82706..223b763e34b 100644
--- a/compiler/rustc_middle/src/ty/abstract_const.rs
+++ b/compiler/rustc_middle/src/ty/abstract_const.rs
@@ -1,4 +1,4 @@
-//! A subset of a mir body used for const evaluatability checking.
+//! A subset of a mir body used for const evaluability checking.
 use crate::ty::{
     self, Const, EarlyBinder, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable,
     TypeVisitableExt,
diff --git a/compiler/rustc_middle/src/ty/consts/int.rs b/compiler/rustc_middle/src/ty/consts/int.rs
index c0e557d480d..d1dbc531edf 100644
--- a/compiler/rustc_middle/src/ty/consts/int.rs
+++ b/compiler/rustc_middle/src/ty/consts/int.rs
@@ -141,14 +141,18 @@ impl<CTX> crate::ty::HashStable<CTX> for ScalarInt {
 
 impl<S: Encoder> Encodable<S> for ScalarInt {
     fn encode(&self, s: &mut S) {
-        s.emit_u128(self.data);
-        s.emit_u8(self.size.get());
+        let size = self.size.get();
+        s.emit_u8(size);
+        s.emit_raw_bytes(&self.data.to_le_bytes()[..size as usize]);
     }
 }
 
 impl<D: Decoder> Decodable<D> for ScalarInt {
     fn decode(d: &mut D) -> ScalarInt {
-        ScalarInt { data: d.read_u128(), size: NonZeroU8::new(d.read_u8()).unwrap() }
+        let mut data = [0u8; 16];
+        let size = d.read_u8();
+        data[..size as usize].copy_from_slice(d.read_raw_bytes(size as usize));
+        ScalarInt { data: u128::from_le_bytes(data), size: NonZeroU8::new(size).unwrap() }
     }
 }
 
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 63f7cc2ee73..1871775ee4a 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -925,7 +925,7 @@ impl<'tcx> TyCtxt<'tcx> {
             crate_name,
             // Don't print the whole stable crate id. That's just
             // annoying in debug output.
-            stable_crate_id.to_u64() >> (8 * 6),
+            stable_crate_id.as_u64() >> (8 * 6),
             self.def_path(def_id).to_string_no_crate_verbose()
         )
     }
@@ -1329,9 +1329,12 @@ nop_list_lift! {bound_variable_kinds; ty::BoundVariableKind => ty::BoundVariable
 // This is the impl for `&'a InternalSubsts<'a>`.
 nop_list_lift! {substs; GenericArg<'a> => GenericArg<'tcx>}
 
-CloneLiftImpls! { for<'tcx> {
-    Constness, traits::WellFormedLoc, ImplPolarity, crate::mir::ReturnConstraint,
-} }
+CloneLiftImpls! {
+    Constness,
+    traits::WellFormedLoc,
+    ImplPolarity,
+    crate::mir::ReturnConstraint,
+}
 
 macro_rules! sty_debug_print {
     ($fmt: expr, $ctxt: expr, $($variant: ident),*) => {{
diff --git a/compiler/rustc_middle/src/ty/fast_reject.rs b/compiler/rustc_middle/src/ty/fast_reject.rs
index 31d00b65e98..76f61d9ac9c 100644
--- a/compiler/rustc_middle/src/ty/fast_reject.rs
+++ b/compiler/rustc_middle/src/ty/fast_reject.rs
@@ -68,7 +68,7 @@ pub enum TreatParams {
 }
 
 /// During fast-rejection, we have the choice of treating projection types
-/// as either simplifyable or not, depending on whether we expect the projection
+/// as either simplifiable or not, depending on whether we expect the projection
 /// to be normalized/rigid.
 #[derive(PartialEq, Eq, Debug, Clone, Copy)]
 pub enum TreatProjections {
diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs
index 195d951f9f3..1e2fd86e13d 100644
--- a/compiler/rustc_middle/src/ty/layout.rs
+++ b/compiler/rustc_middle/src/ty/layout.rs
@@ -235,7 +235,7 @@ impl IntoDiagnostic<'_, !> for LayoutError<'_> {
     }
 }
 
-// FIXME: Once the other errors that embed this error have been converted to translateable
+// FIXME: Once the other errors that embed this error have been converted to translatable
 // diagnostics, this Display impl should be removed.
 impl<'tcx> fmt::Display for LayoutError<'tcx> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
@@ -458,10 +458,10 @@ impl<'tcx> SizeSkeleton<'tcx> {
     }
 }
 
-/// When creating the layout for types with abstract conts in their size (i.e. [usize; 4 * N]),
+/// When creating the layout for types with abstract consts in their size (i.e. [usize; 4 * N]),
 /// to ensure that they have a canonical order and can be compared directly we combine all
 /// constants, and sort the other terms. This allows comparison of expressions of sizes,
-/// allowing for things like transmutating between types that depend on generic consts.
+/// allowing for things like transmuting between types that depend on generic consts.
 /// This returns `None` if multiplication of constants overflows.
 fn mul_sorted_consts<'tcx>(
     tcx: TyCtxt<'tcx>,
diff --git a/compiler/rustc_middle/src/ty/list.rs b/compiler/rustc_middle/src/ty/list.rs
index 79365ef281b..30f036e471c 100644
--- a/compiler/rustc_middle/src/ty/list.rs
+++ b/compiler/rustc_middle/src/ty/list.rs
@@ -1,4 +1,5 @@
 use crate::arena::Arena;
+use rustc_data_structures::aligned::{align_of, Aligned};
 use rustc_serialize::{Encodable, Encoder};
 use std::alloc::Layout;
 use std::cmp::Ordering;
@@ -198,22 +199,17 @@ impl<'a, T: Copy> IntoIterator for &'a List<T> {
 
 unsafe impl<T: Sync> Sync for List<T> {}
 
-unsafe impl<'a, T: 'a> rustc_data_structures::tagged_ptr::Pointer for &'a List<T> {
-    const BITS: usize = std::mem::align_of::<usize>().trailing_zeros() as usize;
-
-    #[inline]
-    fn into_usize(self) -> usize {
-        self as *const List<T> as usize
-    }
-
-    #[inline]
-    unsafe fn from_usize(ptr: usize) -> &'a List<T> {
-        &*(ptr as *const List<T>)
-    }
+// Safety:
+// Layouts of `Equivalent<T>` and `List<T>` are the same, modulo opaque tail,
+// thus aligns of `Equivalent<T>` and `List<T>` must be the same.
+unsafe impl<T> Aligned for List<T> {
+    const ALIGN: ptr::Alignment = {
+        #[repr(C)]
+        struct Equivalent<T> {
+            _len: usize,
+            _data: [T; 0],
+        }
 
-    unsafe fn with_ref<R, F: FnOnce(&Self) -> R>(ptr: usize, f: F) -> R {
-        // `Self` is `&'a List<T>` which impls `Copy`, so this is fine.
-        let ptr = Self::from_usize(ptr);
-        f(&ptr)
-    }
+        align_of::<Equivalent<T>>()
+    };
 }
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index bc202b027bd..1061c320793 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -1627,7 +1627,8 @@ struct ParamTag {
 }
 
 unsafe impl rustc_data_structures::tagged_ptr::Tag for ParamTag {
-    const BITS: usize = 2;
+    const BITS: u32 = 2;
+
     #[inline]
     fn into_usize(self) -> usize {
         match self {
@@ -1637,6 +1638,7 @@ unsafe impl rustc_data_structures::tagged_ptr::Tag for ParamTag {
             Self { reveal: traits::Reveal::All, constness: hir::Constness::Const } => 3,
         }
     }
+
     #[inline]
     unsafe fn from_usize(ptr: usize) -> Self {
         match ptr {
@@ -1963,6 +1965,16 @@ impl VariantDef {
     pub fn ctor_def_id(&self) -> Option<DefId> {
         self.ctor.map(|(_, def_id)| def_id)
     }
+
+    /// Returns the one field in this variant.
+    ///
+    /// `panic!`s if there are no fields or multiple fields.
+    #[inline]
+    pub fn single_field(&self) -> &FieldDef {
+        assert!(self.fields.len() == 1);
+
+        &self.fields[FieldIdx::from_u32(0)]
+    }
 }
 
 impl PartialEq for VariantDef {
diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs
index 619fcea8b7d..8a2258375ab 100644
--- a/compiler/rustc_middle/src/ty/structural_impls.rs
+++ b/compiler/rustc_middle/src/ty/structural_impls.rs
@@ -197,7 +197,7 @@ impl<'tcx> fmt::Debug for AliasTy<'tcx> {
 // Atomic structs
 //
 // For things that don't carry any arena-allocated data (and are
-// copy...), just add them to one of these lists as appropriat.
+// copy...), just add them to one of these lists as appropriate.
 
 // For things for which the type library provides traversal implementations
 // for all Interners, we only need to provide a Lift implementation:
@@ -276,9 +276,7 @@ TrivialTypeTraversalAndLiftImpls! {
 }
 
 TrivialTypeTraversalAndLiftImpls! {
-    for<'tcx> {
-        ty::ValTree<'tcx>,
-    }
+    ty::ValTree<'tcx>,
 }
 
 ///////////////////////////////////////////////////////////////////////////
diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs
index c8a78ec03d9..e09f9eeba4b 100644
--- a/compiler/rustc_middle/src/ty/util.rs
+++ b/compiler/rustc_middle/src/ty/util.rs
@@ -11,7 +11,7 @@ use crate::ty::{
 use crate::ty::{GenericArgKind, SubstsRef};
 use rustc_apfloat::Float as _;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
-use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
+use rustc_data_structures::stable_hasher::{Hash64, HashStable, StableHasher};
 use rustc_errors::ErrorGuaranteed;
 use rustc_hir as hir;
 use rustc_hir::def::{CtorOf, DefKind, Res};
@@ -124,7 +124,7 @@ impl IntTypeExt for IntegerType {
 impl<'tcx> TyCtxt<'tcx> {
     /// Creates a hash of the type `Ty` which will be the same no matter what crate
     /// context it's calculated within. This is used by the `type_id` intrinsic.
-    pub fn type_id_hash(self, ty: Ty<'tcx>) -> u64 {
+    pub fn type_id_hash(self, ty: Ty<'tcx>) -> Hash64 {
         // We want the type_id be independent of the types free regions, so we
         // erase them. The erase_regions() call will also anonymize bound
         // regions, which is desirable too.
@@ -642,7 +642,7 @@ impl<'tcx> TyCtxt<'tcx> {
         }
     }
 
-    /// Return the set of types that should be taken into accound when checking
+    /// Return the set of types that should be taken into account when checking
     /// trait bounds on a generator's internal state.
     pub fn generator_hidden_types(
         self,
@@ -1402,7 +1402,7 @@ pub fn is_trivially_const_drop(ty: Ty<'_>) -> bool {
 }
 
 /// Does the equivalent of
-/// ```ignore (ilustrative)
+/// ```ignore (illustrative)
 /// let v = self.iter().map(|p| p.fold_with(folder)).collect::<SmallVec<[_; 8]>>();
 /// folder.tcx().intern_*(&v)
 /// ```
diff --git a/compiler/rustc_middle/src/ty/visit.rs b/compiler/rustc_middle/src/ty/visit.rs
index 24a1f04c7e3..1b07f52afca 100644
--- a/compiler/rustc_middle/src/ty/visit.rs
+++ b/compiler/rustc_middle/src/ty/visit.rs
@@ -33,6 +33,14 @@ pub trait TypeVisitableExt<'tcx>: TypeVisitable<TyCtxt<'tcx>> {
     }
 
     fn has_type_flags(&self, flags: TypeFlags) -> bool {
+        // N.B. Even though this uses a visitor, the visitor does not actually
+        //      recurse through the whole `TypeVisitable` implementor type.
+        //
+        //      Instead it stops on the first "level", visiting types, regions,
+        //      consts and predicates just fetches their type flags.
+        //
+        //      Thus this is a lot faster than it might seem and should be
+        //      optimized to a simple field access.
         let res =
             self.visit_with(&mut HasTypeFlagsVisitor { flags }).break_value() == Some(FoundFlags);
         trace!(?self, ?flags, ?res, "has_type_flags");
diff --git a/compiler/rustc_mir_build/src/build/expr/into.rs b/compiler/rustc_mir_build/src/build/expr/into.rs
index 05a723a6b67..9b38ac1cc4c 100644
--- a/compiler/rustc_mir_build/src/build/expr/into.rs
+++ b/compiler/rustc_mir_build/src/build/expr/into.rs
@@ -163,13 +163,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 //
                 // [block: If(lhs)] -true-> [else_block: dest = (rhs)]
                 //        | (false)
-                //  [shortcurcuit_block: dest = false]
+                //  [shortcircuit_block: dest = false]
                 //
                 // Or:
                 //
                 // [block: If(lhs)] -false-> [else_block: dest = (rhs)]
                 //        | (true)
-                //  [shortcurcuit_block: dest = true]
+                //  [shortcircuit_block: dest = true]
 
                 let (shortcircuit_block, mut else_block, join_block) = (
                     this.cfg.start_new_block(),
diff --git a/compiler/rustc_mir_build/src/build/matches/test.rs b/compiler/rustc_mir_build/src/build/matches/test.rs
index 8a03ea7e2cc..4536ecf17b8 100644
--- a/compiler/rustc_mir_build/src/build/matches/test.rs
+++ b/compiler/rustc_mir_build/src/build/matches/test.rs
@@ -77,7 +77,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             | PatKind::Wild
             | PatKind::Binding { .. }
             | PatKind::Leaf { .. }
-            | PatKind::Deref { .. } => self.error_simplifyable(match_pair),
+            | PatKind::Deref { .. } => self.error_simplifiable(match_pair),
         }
     }
 
@@ -173,7 +173,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                             debug_assert_ne!(
                                 target_blocks[idx.index()],
                                 otherwise_block,
-                                "no canididates for tested discriminant: {:?}",
+                                "no candidates for tested discriminant: {:?}",
                                 discr,
                             );
                             Some((discr.val, target_blocks[idx.index()]))
@@ -181,7 +181,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                             debug_assert_eq!(
                                 target_blocks[idx.index()],
                                 otherwise_block,
-                                "found canididates for untested discriminant: {:?}",
+                                "found candidates for untested discriminant: {:?}",
                                 discr,
                             );
                             None
@@ -499,7 +499,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     /// However, in some cases, the test may just not be relevant to candidate.
     /// For example, suppose we are testing whether `foo.x == 22`, but in one
     /// match arm we have `Foo { x: _, ... }`... in that case, the test for
-    /// what value `x` has has no particular relevance to this candidate. In
+    /// the value of `x` has no particular relevance to this candidate. In
     /// such cases, this function just returns None without doing anything.
     /// This is used by the overall `match_candidates` algorithm to structure
     /// the match as a whole. See `match_candidates` for more details.
@@ -763,8 +763,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         candidate.match_pairs.extend(consequent_match_pairs);
     }
 
-    fn error_simplifyable<'pat>(&mut self, match_pair: &MatchPair<'pat, 'tcx>) -> ! {
-        span_bug!(match_pair.pattern.span, "simplifyable pattern found: {:?}", match_pair.pattern)
+    fn error_simplifiable<'pat>(&mut self, match_pair: &MatchPair<'pat, 'tcx>) -> ! {
+        span_bug!(match_pair.pattern.span, "simplifiable pattern found: {:?}", match_pair.pattern)
     }
 
     fn const_range_contains(
diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
index 32d0404bd07..c99fc73fe8a 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
@@ -156,7 +156,7 @@ impl<'tcx> ConstToPat<'tcx> {
 
             if let Some(non_sm_ty) = structural {
                 if !self.type_may_have_partial_eq_impl(cv.ty()) {
-                    // fatal avoids ICE from resolution of non-existent method (rare case).
+                    // fatal avoids ICE from resolution of nonexistent method (rare case).
                     self.tcx()
                         .sess
                         .emit_fatal(TypeNotStructural { span: self.span, non_sm_ty: non_sm_ty });
diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs
index 98bebc9b13b..d8fd06eab86 100644
--- a/compiler/rustc_mir_dataflow/src/value_analysis.rs
+++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs
@@ -366,7 +366,7 @@ where
 rustc_index::newtype_index!(
     /// This index uniquely identifies a place.
     ///
-    /// Not every place has a `PlaceIndex`, and not every `PlaceIndex` correspondends to a tracked
+    /// Not every place has a `PlaceIndex`, and not every `PlaceIndex` corresponds to a tracked
     /// place. However, every tracked place and all places along its projection have a `PlaceIndex`.
     pub struct PlaceIndex {}
 );
diff --git a/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs b/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs
index 896fcd9cdd6..b29ffcc70f9 100644
--- a/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs
+++ b/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs
@@ -10,7 +10,7 @@ use rustc_middle::mir::patch::MirPatch;
 /// they are dropped from an aligned address.
 ///
 /// For example, if we have something like
-/// ```ignore (ilustrative)
+/// ```ignore (illustrative)
 /// #[repr(packed)]
 /// struct Foo {
 ///     dealign: u8,
@@ -25,7 +25,7 @@ use rustc_middle::mir::patch::MirPatch;
 /// its address is not aligned.
 ///
 /// Instead, we move `foo.data` to a local and drop that:
-/// ```ignore (ilustrative)
+/// ```ignore (illustrative)
 ///     storage.live(drop_temp)
 ///     drop_temp = foo.data;
 ///     drop(drop_temp) -> next
diff --git a/compiler/rustc_mir_transform/src/add_retag.rs b/compiler/rustc_mir_transform/src/add_retag.rs
index 916f2904dda..187d38b385b 100644
--- a/compiler/rustc_mir_transform/src/add_retag.rs
+++ b/compiler/rustc_mir_transform/src/add_retag.rs
@@ -59,7 +59,7 @@ impl<'tcx> MirPass<'tcx> for AddRetag {
         let basic_blocks = body.basic_blocks.as_mut();
         let local_decls = &body.local_decls;
         let needs_retag = |place: &Place<'tcx>| {
-            !place.has_deref() // we're not eally interested in stores to "outside" locations, they are hard to keep track of anyway
+            !place.has_deref() // we're not really interested in stores to "outside" locations, they are hard to keep track of anyway
                 && may_contain_reference(place.ty(&*local_decls, tcx).ty, /*depth*/ 3, tcx)
                 && !local_decls[place.local].is_deref_temp()
         };
diff --git a/compiler/rustc_mir_transform/src/const_debuginfo.rs b/compiler/rustc_mir_transform/src/const_debuginfo.rs
index 6f0ae4f07ab..692b3182f7d 100644
--- a/compiler/rustc_mir_transform/src/const_debuginfo.rs
+++ b/compiler/rustc_mir_transform/src/const_debuginfo.rs
@@ -22,7 +22,7 @@ impl<'tcx> MirPass<'tcx> for ConstDebugInfo {
     fn run_pass(&self, _tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
         trace!("running ConstDebugInfo on {:?}", body.source);
 
-        for (local, constant) in find_optimization_oportunities(body) {
+        for (local, constant) in find_optimization_opportunities(body) {
             for debuginfo in &mut body.var_debug_info {
                 if let VarDebugInfoContents::Place(p) = debuginfo.value {
                     if p.local == local && p.projection.is_empty() {
@@ -45,7 +45,7 @@ struct LocalUseVisitor {
     local_assignment_locations: IndexVec<Local, Option<Location>>,
 }
 
-fn find_optimization_oportunities<'tcx>(body: &Body<'tcx>) -> Vec<(Local, Constant<'tcx>)> {
+fn find_optimization_opportunities<'tcx>(body: &Body<'tcx>) -> Vec<(Local, Constant<'tcx>)> {
     let mut visitor = LocalUseVisitor {
         local_mutating_uses: IndexVec::from_elem(0, &body.local_decls),
         local_assignment_locations: IndexVec::from_elem(None, &body.local_decls),
diff --git a/compiler/rustc_mir_transform/src/const_prop.rs b/compiler/rustc_mir_transform/src/const_prop.rs
index c0146e3efb0..c9537f9a61c 100644
--- a/compiler/rustc_mir_transform/src/const_prop.rs
+++ b/compiler/rustc_mir_transform/src/const_prop.rs
@@ -826,7 +826,7 @@ impl Visitor<'_> for CanConstProp {
             | NonMutatingUse(NonMutatingUseContext::AddressOf)
             | MutatingUse(MutatingUseContext::Borrow)
             | MutatingUse(MutatingUseContext::AddressOf) => {
-                trace!("local {:?} can't be propagaged because it's used: {:?}", local, context);
+                trace!("local {:?} can't be propagated because it's used: {:?}", local, context);
                 self.can_const_prop[local] = ConstPropMode::NoPropagation;
             }
         }
diff --git a/compiler/rustc_mir_transform/src/coverage/graph.rs b/compiler/rustc_mir_transform/src/coverage/graph.rs
index 7391a77b0a6..8ff67b5f8d3 100644
--- a/compiler/rustc_mir_transform/src/coverage/graph.rs
+++ b/compiler/rustc_mir_transform/src/coverage/graph.rs
@@ -111,7 +111,7 @@ impl CoverageGraph {
                         if predecessors.len() > 1 {
                             "predecessors.len() > 1".to_owned()
                         } else {
-                            format!("bb {} is not in precessors: {:?}", bb.index(), predecessors)
+                            format!("bb {} is not in predecessors: {:?}", bb.index(), predecessors)
                         }
                     );
                 }
diff --git a/compiler/rustc_mir_transform/src/coverage/mod.rs b/compiler/rustc_mir_transform/src/coverage/mod.rs
index 5ecb2d6a631..444b1565d36 100644
--- a/compiler/rustc_mir_transform/src/coverage/mod.rs
+++ b/compiler/rustc_mir_transform/src/coverage/mod.rs
@@ -577,5 +577,10 @@ fn get_body_span<'tcx>(
 fn hash_mir_source<'tcx>(tcx: TyCtxt<'tcx>, hir_body: &'tcx rustc_hir::Body<'tcx>) -> u64 {
     // FIXME(cjgillot) Stop hashing HIR manually here.
     let owner = hir_body.id().hir_id.owner;
-    tcx.hir_owner_nodes(owner).unwrap().opt_hash_including_bodies.unwrap().to_smaller_hash()
+    tcx.hir_owner_nodes(owner)
+        .unwrap()
+        .opt_hash_including_bodies
+        .unwrap()
+        .to_smaller_hash()
+        .as_u64()
 }
diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs
index d4db7e2de40..a56c5cc5c12 100644
--- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs
+++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs
@@ -351,7 +351,7 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> {
             }
             (FlatSet::Bottom, _) | (_, FlatSet::Bottom) => (FlatSet::Bottom, FlatSet::Bottom),
             (_, _) => {
-                // Could attempt some algebraic simplifcations here.
+                // Could attempt some algebraic simplifications here.
                 (FlatSet::Top, FlatSet::Top)
             }
         }
diff --git a/compiler/rustc_mir_transform/src/deduce_param_attrs.rs b/compiler/rustc_mir_transform/src/deduce_param_attrs.rs
index e5c3fa5646a..8ee08c5be34 100644
--- a/compiler/rustc_mir_transform/src/deduce_param_attrs.rs
+++ b/compiler/rustc_mir_transform/src/deduce_param_attrs.rs
@@ -9,7 +9,7 @@ use rustc_hir::def_id::LocalDefId;
 use rustc_index::bit_set::BitSet;
 use rustc_middle::mir::visit::{NonMutatingUseContext, PlaceContext, Visitor};
 use rustc_middle::mir::{Body, Local, Location, Operand, Terminator, TerminatorKind, RETURN_PLACE};
-use rustc_middle::ty::{self, DeducedParamAttrs, ParamEnv, Ty, TyCtxt};
+use rustc_middle::ty::{self, DeducedParamAttrs, Ty, TyCtxt};
 use rustc_session::config::OptLevel;
 
 /// A visitor that determines which arguments have been mutated. We can't use the mutability field
@@ -198,11 +198,12 @@ pub fn deduced_param_attrs<'tcx>(
     // see [1].
     //
     // [1]: https://github.com/rust-lang/rust/pull/103172#discussion_r999139997
+    let param_env = tcx.param_env_reveal_all_normalized(def_id);
     let mut deduced_param_attrs = tcx.arena.alloc_from_iter(
         body.local_decls.iter().skip(1).take(body.arg_count).enumerate().map(
             |(arg_index, local_decl)| DeducedParamAttrs {
                 read_only: !deduce_read_only.mutable_args.contains(arg_index)
-                    && local_decl.ty.is_freeze(tcx, ParamEnv::reveal_all()),
+                    && local_decl.ty.is_freeze(tcx, param_env),
             },
         ),
     );
diff --git a/compiler/rustc_mir_transform/src/dest_prop.rs b/compiler/rustc_mir_transform/src/dest_prop.rs
index 39164917770..5a842714e5d 100644
--- a/compiler/rustc_mir_transform/src/dest_prop.rs
+++ b/compiler/rustc_mir_transform/src/dest_prop.rs
@@ -69,7 +69,7 @@
 //!   of this is that such liveness analysis can report more accurate results about whole locals at
 //!   a time. For example, consider:
 //!
-//!   ```ignore (syntax-highliting-only)
+//!   ```ignore (syntax-highlighting-only)
 //!   _1 = u;
 //!   // unrelated code
 //!   _1.f1 = v;
@@ -360,7 +360,7 @@ struct FilterInformation<'a, 'body, 'alloc, 'tcx> {
 }
 
 // We first implement some utility functions which we will expose removing candidates according to
-// different needs. Throughout the livenss filtering, the `candidates` are only ever accessed
+// different needs. Throughout the liveness filtering, the `candidates` are only ever accessed
 // through these methods, and not directly.
 impl<'alloc> Candidates<'alloc> {
     /// Just `Vec::retain`, but the condition is inverted and we add debugging output
diff --git a/compiler/rustc_mir_transform/src/elaborate_drops.rs b/compiler/rustc_mir_transform/src/elaborate_drops.rs
index a702113bd99..1e115be2c2a 100644
--- a/compiler/rustc_mir_transform/src/elaborate_drops.rs
+++ b/compiler/rustc_mir_transform/src/elaborate_drops.rs
@@ -24,7 +24,7 @@ use std::fmt;
 /// In general, the compiler cannot determine at compile time whether a destructor will run or not.
 ///
 /// At a high level, this pass refines Drop to only run the destructor if the
-/// target is initialized. The way this is achievied is by inserting drop flags for every variable
+/// target is initialized. The way this is achieved is by inserting drop flags for every variable
 /// that may be dropped, and then using those flags to determine whether a destructor should run.
 /// Once this is complete, Drop terminators in the MIR correspond to a call to the "drop glue" or
 /// "drop shim" for the type of the dropped place.
diff --git a/compiler/rustc_mir_transform/src/generator.rs b/compiler/rustc_mir_transform/src/generator.rs
index 4c4423721fb..507e12d7238 100644
--- a/compiler/rustc_mir_transform/src/generator.rs
+++ b/compiler/rustc_mir_transform/src/generator.rs
@@ -1869,7 +1869,7 @@ fn check_must_not_suspend_ty<'tcx>(
                 },
             )
         }
-        // If drop tracking is enabled, we want to look through references, since the referrent
+        // If drop tracking is enabled, we want to look through references, since the referent
         // may not be considered live across the await point.
         ty::Ref(_region, ty, _mutability) => {
             let descr_pre = &format!("{}reference{} to ", data.descr_pre, plural_suffix);
diff --git a/compiler/rustc_mir_transform/src/ssa.rs b/compiler/rustc_mir_transform/src/ssa.rs
index be026402dd5..9d9c5d54038 100644
--- a/compiler/rustc_mir_transform/src/ssa.rs
+++ b/compiler/rustc_mir_transform/src/ssa.rs
@@ -21,7 +21,7 @@ pub struct SsaLocals {
 
 /// We often encounter MIR bodies with 1 or 2 basic blocks. In those cases, it's unnecessary to
 /// actually compute dominators, we can just compare block indices because bb0 is always the first
-/// block, and in any body all other blocks are always always dominated by bb0.
+/// block, and in any body all other blocks are always dominated by bb0.
 struct SmallDominators {
     inner: Option<Dominators<BasicBlock>>,
 }
diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs
index 7bcff7e07fb..2ed628871d2 100644
--- a/compiler/rustc_monomorphize/src/collector.rs
+++ b/compiler/rustc_monomorphize/src/collector.rs
@@ -402,7 +402,7 @@ fn collect_roots(tcx: TyCtxt<'_>, mode: MonoItemCollectionMode) -> Vec<MonoItem<
 }
 
 /// Collect all monomorphized items reachable from `starting_point`, and emit a note diagnostic if a
-/// post-monorphization error is encountered during a collection step.
+/// post-monomorphization error is encountered during a collection step.
 #[instrument(skip(tcx, visited, recursion_depths, recursion_limit, inlining_map), level = "debug")]
 fn collect_items_rec<'tcx>(
     tcx: TyCtxt<'tcx>,
diff --git a/compiler/rustc_monomorphize/src/partitioning/default.rs b/compiler/rustc_monomorphize/src/partitioning/default.rs
index 769e12f77bf..49126045d0c 100644
--- a/compiler/rustc_monomorphize/src/partitioning/default.rs
+++ b/compiler/rustc_monomorphize/src/partitioning/default.rs
@@ -424,7 +424,7 @@ fn mono_item_visibility<'tcx>(
         InstanceDef::Item(def) => def.did,
         InstanceDef::DropGlue(def_id, Some(_)) => def_id,
 
-        // We match the visiblity of statics here
+        // We match the visibility of statics here
         InstanceDef::ThreadLocalShim(def_id) => {
             return static_visibility(tcx, can_be_internalized, def_id);
         }
diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs
index 9e856c9f212..ad9b20f9c76 100644
--- a/compiler/rustc_parse/src/lexer/mod.rs
+++ b/compiler/rustc_parse/src/lexer/mod.rs
@@ -67,7 +67,7 @@ pub(crate) fn parse_token_trees<'a>(
     match token_trees {
         Ok(stream) if unmatched_delims.is_empty() => Ok(stream),
         _ => {
-            // Return error if there are unmatched delimiters or unclosng delimiters.
+            // Return error if there are unmatched delimiters or unclosed delimiters.
             // We emit delimiter mismatch errors first, then emit the unclosing delimiter mismatch
             // because the delimiter mismatch is more likely to be the root cause of error
 
diff --git a/compiler/rustc_parse/src/validate_attr.rs b/compiler/rustc_parse/src/validate_attr.rs
index 72402a20090..2f397e303e5 100644
--- a/compiler/rustc_parse/src/validate_attr.rs
+++ b/compiler/rustc_parse/src/validate_attr.rs
@@ -68,7 +68,7 @@ pub fn parse_meta<'a>(sess: &'a ParseSess, attr: &Attribute) -> PResult<'a, Meta
                     }
                 } else {
                     // The non-error case can happen with e.g. `#[foo = 1+1]`. The error case can
-                    // happen with e.g. `#[foo = include_str!("non-existent-file.rs")]`; in that
+                    // happen with e.g. `#[foo = include_str!("nonexistent-file.rs")]`; in that
                     // case we delay the error because an earlier error will have already been
                     // reported.
                     let msg = format!("unexpected expression: `{}`", pprust::expr_to_string(expr));
diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl
index b354dca7cc4..055682a1509 100644
--- a/compiler/rustc_passes/messages.ftl
+++ b/compiler/rustc_passes/messages.ftl
@@ -627,9 +627,9 @@ passes_attr_application_struct_enum_union =
     attribute should be applied to a struct, enum, or union
     .label = not a struct, enum, or union
 
-passes_attr_application_struct_enum_function_union =
-    attribute should be applied to a struct, enum, function, or union
-    .label = not a struct, enum, function, or union
+passes_attr_application_struct_enum_function_method_union =
+    attribute should be applied to a struct, enum, function, associated function, or union
+    .label = not a struct, enum, function, associated function, or union
 
 passes_transparent_incompatible =
     transparent {$target} cannot have other repr hints
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index 80a93da2b45..085a28626ea 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -1728,7 +1728,9 @@ impl CheckAttrVisitor<'_> {
                     }
                 }
                 sym::align => {
-                    if let (Target::Fn, false) = (target, self.tcx.features().fn_align) {
+                    if let (Target::Fn | Target::Method(MethodKind::Inherent), false) =
+                        (target, self.tcx.features().fn_align)
+                    {
                         feature_err(
                             &self.tcx.sess.parse_sess,
                             sym::fn_align,
@@ -1739,10 +1741,14 @@ impl CheckAttrVisitor<'_> {
                     }
 
                     match target {
-                        Target::Struct | Target::Union | Target::Enum | Target::Fn => continue,
+                        Target::Struct
+                        | Target::Union
+                        | Target::Enum
+                        | Target::Fn
+                        | Target::Method(_) => continue,
                         _ => {
                             self.tcx.sess.emit_err(
-                                errors::AttrApplication::StructEnumFunctionUnion {
+                                errors::AttrApplication::StructEnumFunctionMethodUnion {
                                     hint_span: hint.span(),
                                     span,
                                 },
diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs
index 139ba8c9677..e8603b3a2f1 100644
--- a/compiler/rustc_passes/src/errors.rs
+++ b/compiler/rustc_passes/src/errors.rs
@@ -1355,8 +1355,8 @@ pub enum AttrApplication {
         #[label]
         span: Span,
     },
-    #[diag(passes_attr_application_struct_enum_function_union, code = "E0517")]
-    StructEnumFunctionUnion {
+    #[diag(passes_attr_application_struct_enum_function_method_union, code = "E0517")]
+    StructEnumFunctionMethodUnion {
         #[primary_span]
         hint_span: Span,
         #[label]
diff --git a/compiler/rustc_query_impl/src/on_disk_cache.rs b/compiler/rustc_query_impl/src/on_disk_cache.rs
index 30477c7bd44..d43af643b3b 100644
--- a/compiler/rustc_query_impl/src/on_disk_cache.rs
+++ b/compiler/rustc_query_impl/src/on_disk_cache.rs
@@ -1,6 +1,7 @@
 use crate::QueryCtxt;
 use rustc_data_structures::fx::{FxHashMap, FxIndexSet};
 use rustc_data_structures::memmap::Mmap;
+use rustc_data_structures::stable_hasher::Hash64;
 use rustc_data_structures::sync::{HashMapExt, Lock, Lrc, RwLock};
 use rustc_data_structures::unhash::UnhashMap;
 use rustc_data_structures::unord::UnordSet;
@@ -138,7 +139,7 @@ impl AbsoluteBytePos {
 /// is the only thing available when decoding the cache's [Footer].
 #[derive(Encodable, Decodable, Clone, Debug)]
 struct EncodedSourceFileId {
-    file_name_hash: u64,
+    file_name_hash: Hash64,
     stable_crate_id: StableCrateId,
 }
 
@@ -667,7 +668,7 @@ impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for ExpnId {
             #[cfg(debug_assertions)]
             {
                 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
-                let local_hash: u64 = decoder.tcx.with_stable_hashing_context(|mut hcx| {
+                let local_hash = decoder.tcx.with_stable_hashing_context(|mut hcx| {
                     let mut hasher = StableHasher::new();
                     expn_id.expn_data().hash_stable(&mut hcx, &mut hasher);
                     hasher.finish()
@@ -744,7 +745,7 @@ impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for Symbol {
                 let pos = d.read_usize();
                 let old_pos = d.opaque.position();
 
-                // move to str ofset and read
+                // move to str offset and read
                 d.opaque.set_position(pos);
                 let s = d.read_str();
                 let sym = Symbol::intern(s);
diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs
index afbead7d1ae..32222df25d4 100644
--- a/compiler/rustc_query_impl/src/plumbing.rs
+++ b/compiler/rustc_query_impl/src/plumbing.rs
@@ -5,7 +5,7 @@
 use crate::on_disk_cache::{CacheDecoder, CacheEncoder, EncodedDepNodeIndex};
 use crate::profiling_support::QueryKeyStringCache;
 use crate::{on_disk_cache, Queries};
-use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
+use rustc_data_structures::stable_hasher::{Hash64, HashStable, StableHasher};
 use rustc_data_structures::sync::{AtomicU64, Lock};
 use rustc_errors::{Diagnostic, Handler};
 use rustc_middle::dep_graph::{
@@ -342,7 +342,7 @@ pub(crate) fn create_query_frame<
             let mut hasher = StableHasher::new();
             std::mem::discriminant(&kind).hash_stable(&mut hcx, &mut hasher);
             key.hash_stable(&mut hcx, &mut hasher);
-            hasher.finish::<u64>()
+            hasher.finish::<Hash64>()
         })
     };
     let ty_adt_id = key.ty_adt_id();
diff --git a/compiler/rustc_query_system/messages.ftl b/compiler/rustc_query_system/messages.ftl
index 870e824039c..0d01123ad88 100644
--- a/compiler/rustc_query_system/messages.ftl
+++ b/compiler/rustc_query_system/messages.ftl
@@ -1,4 +1,4 @@
-query_system_reentrant = internal compiler error: re-entrant incremental verify failure, suppressing message
+query_system_reentrant = internal compiler error: reentrant incremental verify failure, suppressing message
 
 query_system_increment_compilation = internal compiler error: encountered incremental compilation error with {$dep_node}
     .help = This is a known issue with the compiler. Run {$run_cmd} to allow your project to compile
diff --git a/compiler/rustc_query_system/src/dep_graph/graph.rs b/compiler/rustc_query_system/src/dep_graph/graph.rs
index a9a2e6dd04c..fd9e685ab80 100644
--- a/compiler/rustc_query_system/src/dep_graph/graph.rs
+++ b/compiler/rustc_query_system/src/dep_graph/graph.rs
@@ -249,7 +249,7 @@ impl<K: DepKind> DepGraph<K> {
     /// get an ICE. Normally, we would have tried (and failed) to mark
     /// some other query green (e.g. `item_children`) which was used
     /// to obtain `C`, which would prevent us from ever trying to force
-    /// a non-existent `D`.
+    /// a nonexistent `D`.
     ///
     /// It might be possible to enforce that all `DepNode`s read during
     /// deserialization already exist in the previous `DepGraph`. In
diff --git a/compiler/rustc_query_system/src/dep_graph/query.rs b/compiler/rustc_query_system/src/dep_graph/query.rs
index 27b3b5e1366..9dcc41e2726 100644
--- a/compiler/rustc_query_system/src/dep_graph/query.rs
+++ b/compiler/rustc_query_system/src/dep_graph/query.rs
@@ -24,10 +24,7 @@ impl<K: DepKind> DepGraphQuery<K> {
 
     pub fn push(&mut self, index: DepNodeIndex, node: DepNode<K>, edges: &[DepNodeIndex]) {
         let source = self.graph.add_node(node);
-        if index.index() >= self.dep_index_to_index.len() {
-            self.dep_index_to_index.resize(index.index() + 1, None);
-        }
-        self.dep_index_to_index[index] = Some(source);
+        self.dep_index_to_index.insert(index, source);
         self.indices.insert(node, source);
 
         for &target in edges.iter() {
diff --git a/compiler/rustc_query_system/src/query/config.rs b/compiler/rustc_query_system/src/query/config.rs
index c8d77938510..bb9ea50a1ea 100644
--- a/compiler/rustc_query_system/src/query/config.rs
+++ b/compiler/rustc_query_system/src/query/config.rs
@@ -63,7 +63,7 @@ pub trait QueryConfig<Qcx: QueryContext>: Copy {
     fn handle_cycle_error(self) -> HandleCycleError;
     fn hash_result(self) -> HashResult<Self::Value>;
 
-    // Just here for convernience and checking that the key matches the kind, don't override this.
+    // Just here for convenience and checking that the key matches the kind, don't override this.
     fn construct_dep_node(self, tcx: Qcx::DepContext, key: &Self::Key) -> DepNode<Qcx::DepKind> {
         DepNode::construct(tcx, self.dep_kind(), key)
     }
diff --git a/compiler/rustc_query_system/src/query/mod.rs b/compiler/rustc_query_system/src/query/mod.rs
index 312b0e1688d..fa1f51b04da 100644
--- a/compiler/rustc_query_system/src/query/mod.rs
+++ b/compiler/rustc_query_system/src/query/mod.rs
@@ -16,6 +16,7 @@ pub use self::config::{HashResult, QueryConfig, TryLoadFromDisk};
 
 use crate::dep_graph::DepKind;
 use crate::dep_graph::{DepNodeIndex, HasDepContext, SerializedDepNodeIndex};
+use rustc_data_structures::stable_hasher::Hash64;
 use rustc_data_structures::sync::Lock;
 use rustc_errors::Diagnostic;
 use rustc_hir::def::DefKind;
@@ -37,7 +38,7 @@ pub struct QueryStackFrame<D: DepKind> {
     /// This hash is used to deterministically pick
     /// a query to remove cycles in the parallel compiler.
     #[cfg(parallel_compiler)]
-    hash: u64,
+    hash: Hash64,
 }
 
 impl<D: DepKind> QueryStackFrame<D> {
@@ -49,7 +50,7 @@ impl<D: DepKind> QueryStackFrame<D> {
         def_kind: Option<DefKind>,
         dep_kind: D,
         ty_adt_id: Option<DefId>,
-        _hash: impl FnOnce() -> u64,
+        _hash: impl FnOnce() -> Hash64,
     ) -> Self {
         Self {
             description,
diff --git a/compiler/rustc_query_system/src/query/plumbing.rs b/compiler/rustc_query_system/src/query/plumbing.rs
index 20310483d7e..4a6d07a03cc 100644
--- a/compiler/rustc_query_system/src/query/plumbing.rs
+++ b/compiler/rustc_query_system/src/query/plumbing.rs
@@ -573,7 +573,7 @@ where
             // from disk. Re-hashing results is fairly expensive, so we can't
             // currently afford to verify every hash. This subset should still
             // give us some coverage of potential bugs though.
-            let try_verify = prev_fingerprint.as_value().1 % 32 == 0;
+            let try_verify = prev_fingerprint.split().1.as_u64() % 32 == 0;
             if std::intrinsics::unlikely(
                 try_verify || qcx.dep_context().sess().opts.unstable_opts.incremental_verify_ich,
             ) {
@@ -691,7 +691,7 @@ fn incremental_verify_ich_failed<Tcx>(
     // which may result in another fingerprint mismatch while we're in the middle
     // of processing this one. To avoid a double-panic (which kills the process
     // before we can print out the query static), we print out a terse
-    // but 'safe' message if we detect a re-entrant call to this method.
+    // but 'safe' message if we detect a reentrant call to this method.
     thread_local! {
         static INSIDE_VERIFY_PANIC: Cell<bool> = const { Cell::new(false) };
     };
diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs
index ff0f1f55975..f905cec1011 100644
--- a/compiler/rustc_resolve/src/build_reduced_graph.rs
+++ b/compiler/rustc_resolve/src/build_reduced_graph.rs
@@ -931,7 +931,13 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
     /// Builds the reduced graph for a single item in an external crate.
     fn build_reduced_graph_for_external_crate_res(&mut self, child: ModChild) {
         let parent = self.parent_scope.module;
-        let ModChild { ident, res, vis, span, .. } = child;
+        let ModChild { ident, res, vis, reexport_chain } = child;
+        let span = self.r.def_span(
+            reexport_chain
+                .first()
+                .and_then(|reexport| reexport.id())
+                .unwrap_or_else(|| res.def_id()),
+        );
         let res = res.expect_non_local();
         let expansion = self.parent_scope.expansion;
         // Record primary definitions.
diff --git a/compiler/rustc_resolve/src/effective_visibilities.rs b/compiler/rustc_resolve/src/effective_visibilities.rs
index bed579f6b92..87067189a77 100644
--- a/compiler/rustc_resolve/src/effective_visibilities.rs
+++ b/compiler/rustc_resolve/src/effective_visibilities.rs
@@ -175,7 +175,7 @@ impl<'r, 'a, 'tcx> EffectiveVisibilitiesVisitor<'r, 'a, 'tcx> {
     /// to not update anything and we can skip it.
     ///
     /// We are checking this condition only if the correct value of private visibility is
-    /// cheaply available, otherwise it does't make sense performance-wise.
+    /// cheaply available, otherwise it doesn't make sense performance-wise.
     ///
     /// `None` is returned if the update can be skipped,
     /// and cheap private visibility is returned otherwise.
diff --git a/compiler/rustc_resolve/src/errors.rs b/compiler/rustc_resolve/src/errors.rs
index afa796cb645..af0ec236df0 100644
--- a/compiler/rustc_resolve/src/errors.rs
+++ b/compiler/rustc_resolve/src/errors.rs
@@ -22,7 +22,7 @@ pub(crate) struct UnderscoreLifetimeNameCannotBeUsedHere(#[primary_span] pub(cra
 
 #[derive(Diagnostic)]
 #[diag(resolve_crate_may_not_be_imported)]
-pub(crate) struct CrateMayNotBeImprted(#[primary_span] pub(crate) Span);
+pub(crate) struct CrateMayNotBeImported(#[primary_span] pub(crate) Span);
 
 #[derive(Diagnostic)]
 #[diag(resolve_crate_root_imports_must_be_named_explicitly)]
diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs
index 3c22d51c3d4..d7c518fbdd0 100644
--- a/compiler/rustc_resolve/src/imports.rs
+++ b/compiler/rustc_resolve/src/imports.rs
@@ -1276,13 +1276,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                         next_binding = binding;
                     }
 
-                    reexports.push(ModChild {
-                        ident,
-                        res,
-                        vis: binding.vis,
-                        span: binding.span,
-                        reexport_chain,
-                    });
+                    reexports.push(ModChild { ident, res, vis: binding.vis, reexport_chain });
                 }
             });
 
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index 90a2fa89cd2..a97857e05e2 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -1079,7 +1079,7 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast,
                     for rib in self.lifetime_ribs.iter().rev() {
                         match rib.kind {
                             // We are inside a `PolyTraitRef`. The lifetimes are
-                            // to be intoduced in that (maybe implicit) `for<>` binder.
+                            // to be introduced in that (maybe implicit) `for<>` binder.
                             LifetimeRibKind::Generics {
                                 binder,
                                 kind: LifetimeBinderKind::PolyTrait,
@@ -3803,7 +3803,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
             // use std::u8; // bring module u8 in scope
             // fn f() -> u8 { // OK, resolves to primitive u8, not to std::u8
             //     u8::max_value() // OK, resolves to associated function <u8>::max_value,
-            //                     // not to non-existent std::u8::max_value
+            //                     // not to nonexistent std::u8::max_value
             // }
             //
             // Such behavior is required for backward compatibility.
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index 37fbfad2de6..e824a6ddc07 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -91,7 +91,7 @@ fn import_candidate_to_enum_paths(suggestion: &ImportSuggestion) -> (String, Str
 /// Description of an elided lifetime.
 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug)]
 pub(super) struct MissingLifetime {
-    /// Used to overwrite the resolution with the suggestion, to avoid cascasing errors.
+    /// Used to overwrite the resolution with the suggestion, to avoid cascading errors.
     pub id: NodeId,
     /// Where to suggest adding the lifetime.
     pub span: Span,
@@ -408,7 +408,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
         }
         let Some(path_last_segment) = path.last() else { return };
         let item_str = path_last_segment.ident;
-        // Emit help message for fake-self from other languages (e.g., `this` in Javascript).
+        // Emit help message for fake-self from other languages (e.g., `this` in JavaScript).
         if ["this", "my"].contains(&item_str.as_str()) {
             err.span_suggestion_short(
                 span,
diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs
index 340bb158e17..14a8e8ff727 100644
--- a/compiler/rustc_session/src/session.rs
+++ b/compiler/rustc_session/src/session.rs
@@ -811,7 +811,7 @@ impl Session {
     }
 
     pub fn generate_proc_macro_decls_symbol(&self, stable_crate_id: StableCrateId) -> String {
-        format!("__rustc_proc_macro_decls_{:08x}__", stable_crate_id.to_u64())
+        format!("__rustc_proc_macro_decls_{:08x}__", stable_crate_id.as_u64())
     }
 
     pub fn target_filesearch(&self, kind: PathKind) -> filesearch::FileSearch<'_> {
diff --git a/compiler/rustc_span/src/def_id.rs b/compiler/rustc_span/src/def_id.rs
index b2c58caff2e..6004009c6ff 100644
--- a/compiler/rustc_span/src/def_id.rs
+++ b/compiler/rustc_span/src/def_id.rs
@@ -1,12 +1,11 @@
 use crate::{HashStableContext, Symbol};
 use rustc_data_structures::fingerprint::Fingerprint;
-use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey};
+use rustc_data_structures::stable_hasher::{Hash64, HashStable, StableHasher, ToStableHashKey};
 use rustc_data_structures::unhash::Unhasher;
 use rustc_data_structures::AtomicRef;
 use rustc_index::vec::Idx;
 use rustc_macros::HashStable_Generic;
 use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
-use std::borrow::Borrow;
 use std::fmt;
 use std::hash::{BuildHasherDefault, Hash, Hasher};
 
@@ -105,20 +104,20 @@ impl DefPathHash {
     /// originates from.
     #[inline]
     pub fn stable_crate_id(&self) -> StableCrateId {
-        StableCrateId(self.0.as_value().0)
+        StableCrateId(self.0.split().0)
     }
 
     /// Returns the crate-local part of the [DefPathHash].
     ///
     /// Used for tests.
     #[inline]
-    pub fn local_hash(&self) -> u64 {
-        self.0.as_value().1
+    pub fn local_hash(&self) -> Hash64 {
+        self.0.split().1
     }
 
     /// Builds a new [DefPathHash] with the given [StableCrateId] and
     /// `local_hash`, where `local_hash` must be unique within its crate.
-    pub fn new(stable_crate_id: StableCrateId, local_hash: u64) -> DefPathHash {
+    pub fn new(stable_crate_id: StableCrateId, local_hash: Hash64) -> DefPathHash {
         DefPathHash(Fingerprint::new(stable_crate_id.0, local_hash))
     }
 }
@@ -129,13 +128,6 @@ impl Default for DefPathHash {
     }
 }
 
-impl Borrow<Fingerprint> for DefPathHash {
-    #[inline]
-    fn borrow(&self) -> &Fingerprint {
-        &self.0
-    }
-}
-
 /// A [`StableCrateId`] is a 64-bit hash of a crate name, together with all
 /// `-Cmetadata` arguments, and some other data. It is to [`CrateNum`] what [`DefPathHash`] is to
 /// [`DefId`]. It is stable across compilation sessions.
@@ -147,15 +139,11 @@ impl Borrow<Fingerprint> for DefPathHash {
 ///
 /// For more information on the possibility of hash collisions in rustc,
 /// see the discussion in [`DefId`].
-#[derive(Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Debug)]
-#[derive(HashStable_Generic, Encodable, Decodable)]
-pub struct StableCrateId(pub(crate) u64);
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug)]
+#[derive(Hash, HashStable_Generic, Encodable, Decodable)]
+pub struct StableCrateId(pub(crate) Hash64);
 
 impl StableCrateId {
-    pub fn to_u64(self) -> u64 {
-        self.0
-    }
-
     /// Computes the stable ID for a crate with the given name and
     /// `-Cmetadata` arguments.
     pub fn new(crate_name: Symbol, is_exe: bool, mut metadata: Vec<String>) -> StableCrateId {
@@ -197,6 +185,17 @@ impl StableCrateId {
 
         StableCrateId(hasher.finish())
     }
+
+    #[inline]
+    pub fn as_u64(self) -> u64 {
+        self.0.as_u64()
+    }
+}
+
+impl fmt::LowerHex for StableCrateId {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        fmt::LowerHex::fmt(&self.0, f)
+    }
 }
 
 rustc_index::newtype_index! {
diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs
index 08c4414034a..f8741d85934 100644
--- a/compiler/rustc_span/src/hygiene.rs
+++ b/compiler/rustc_span/src/hygiene.rs
@@ -33,7 +33,7 @@ use crate::def_id::{CrateNum, DefId, StableCrateId, CRATE_DEF_ID, LOCAL_CRATE};
 use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::stable_hasher::HashingControls;
-use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
+use rustc_data_structures::stable_hasher::{Hash64, HashStable, StableHasher};
 use rustc_data_structures::sync::{Lock, Lrc};
 use rustc_data_structures::unhash::UnhashMap;
 use rustc_index::vec::IndexVec;
@@ -123,15 +123,15 @@ impl ExpnHash {
     /// originates from.
     #[inline]
     pub fn stable_crate_id(self) -> StableCrateId {
-        StableCrateId(self.0.as_value().0)
+        StableCrateId(self.0.split().0)
     }
 
     /// Returns the crate-local part of the [ExpnHash].
     ///
     /// Used for tests.
     #[inline]
-    pub fn local_hash(self) -> u64 {
-        self.0.as_value().1
+    pub fn local_hash(self) -> Hash64 {
+        self.0.split().1
     }
 
     #[inline]
@@ -141,7 +141,7 @@ impl ExpnHash {
 
     /// Builds a new [ExpnHash] with the given [StableCrateId] and
     /// `local_hash`, where `local_hash` must be unique within its crate.
-    fn new(stable_crate_id: StableCrateId, local_hash: u64) -> ExpnHash {
+    fn new(stable_crate_id: StableCrateId, local_hash: Hash64) -> ExpnHash {
         ExpnHash(Fingerprint::new(stable_crate_id.0, local_hash))
     }
 }
@@ -350,7 +350,7 @@ pub struct HygieneData {
     /// would have collisions without a disambiguator.
     /// The keys of this map are always computed with `ExpnData.disambiguator`
     /// set to 0.
-    expn_data_disambiguators: FxHashMap<u64, u32>,
+    expn_data_disambiguators: FxHashMap<Hash64, u32>,
 }
 
 impl HygieneData {
@@ -1040,7 +1040,7 @@ impl ExpnData {
     }
 
     #[inline]
-    fn hash_expn(&self, ctx: &mut impl HashStableContext) -> u64 {
+    fn hash_expn(&self, ctx: &mut impl HashStableContext) -> Hash64 {
         let mut hasher = StableHasher::new();
         self.hash_stable(ctx, &mut hasher);
         hasher.finish()
diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs
index 911d6902c98..83f4907d517 100644
--- a/compiler/rustc_span/src/lib.rs
+++ b/compiler/rustc_span/src/lib.rs
@@ -59,7 +59,7 @@ pub mod fatal_error;
 
 pub mod profiling;
 
-use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
+use rustc_data_structures::stable_hasher::{Hash128, Hash64, HashStable, StableHasher};
 use rustc_data_structures::sync::{Lock, Lrc};
 
 use std::borrow::Cow;
@@ -282,22 +282,22 @@ impl RealFileName {
 pub enum FileName {
     Real(RealFileName),
     /// Call to `quote!`.
-    QuoteExpansion(u64),
+    QuoteExpansion(Hash64),
     /// Command line.
-    Anon(u64),
+    Anon(Hash64),
     /// Hack in `src/librustc_ast/parse.rs`.
     // FIXME(jseyfried)
-    MacroExpansion(u64),
-    ProcMacroSourceCode(u64),
+    MacroExpansion(Hash64),
+    ProcMacroSourceCode(Hash64),
     /// Strings provided as `--cfg [cfgspec]` stored in a `crate_cfg`.
-    CfgSpec(u64),
+    CfgSpec(Hash64),
     /// Strings provided as crate attributes in the CLI.
-    CliCrateAttr(u64),
+    CliCrateAttr(Hash64),
     /// Custom sources for explicit parser calls from plugins and drivers.
     Custom(String),
     DocTest(PathBuf, isize),
     /// Post-substitution inline assembly from LLVM.
-    InlineAsm(u64),
+    InlineAsm(Hash64),
 }
 
 impl From<PathBuf> for FileName {
@@ -1343,7 +1343,7 @@ pub struct SourceFile {
     /// Locations of characters removed during normalization.
     pub normalized_pos: Vec<NormalizedPos>,
     /// A hash of the filename, used for speeding up hashing in incremental compilation.
-    pub name_hash: u128,
+    pub name_hash: Hash128,
     /// Indicates which crate this `SourceFile` was imported from.
     pub cnum: CrateNum,
 }
@@ -1472,7 +1472,7 @@ impl<D: Decoder> Decodable<D> for SourceFile {
         };
         let multibyte_chars: Vec<MultiByteChar> = Decodable::decode(d);
         let non_narrow_chars: Vec<NonNarrowChar> = Decodable::decode(d);
-        let name_hash: u128 = Decodable::decode(d);
+        let name_hash = Decodable::decode(d);
         let normalized_pos: Vec<NormalizedPos> = Decodable::decode(d);
         let cnum: CrateNum = Decodable::decode(d);
         SourceFile {
@@ -1514,7 +1514,7 @@ impl SourceFile {
         let name_hash = {
             let mut hasher: StableHasher = StableHasher::new();
             name.hash(&mut hasher);
-            hasher.finish::<u128>()
+            hasher.finish()
         };
         let end_pos = start_pos.to_usize() + src.len();
         assert!(end_pos <= u32::MAX as usize);
diff --git a/compiler/rustc_span/src/source_map.rs b/compiler/rustc_span/src/source_map.rs
index 29a7e74a816..1294a8b8e6b 100644
--- a/compiler/rustc_span/src/source_map.rs
+++ b/compiler/rustc_span/src/source_map.rs
@@ -13,7 +13,7 @@ pub use crate::hygiene::{ExpnData, ExpnKind};
 pub use crate::*;
 
 use rustc_data_structures::fx::FxHashMap;
-use rustc_data_structures::stable_hasher::StableHasher;
+use rustc_data_structures::stable_hasher::{Hash128, Hash64, StableHasher};
 use rustc_data_structures::sync::{AtomicU32, Lrc, MappedReadGuard, ReadGuard, RwLock};
 use std::cmp;
 use std::hash::Hash;
@@ -138,7 +138,7 @@ impl FileLoader for RealFileLoader {
 pub struct StableSourceFileId {
     /// A hash of the source file's [`FileName`]. This is hash so that it's size
     /// is more predictable than if we included the actual [`FileName`] value.
-    pub file_name_hash: u64,
+    pub file_name_hash: Hash64,
 
     /// The [`CrateNum`] of the crate this source file was originally parsed for.
     /// We cannot include this information in the hash because at the time
@@ -331,7 +331,7 @@ impl SourceMap {
         &self,
         filename: FileName,
         src_hash: SourceFileHash,
-        name_hash: u128,
+        name_hash: Hash128,
         source_len: usize,
         cnum: CrateNum,
         file_local_lines: Lock<SourceFileLines>,
@@ -483,7 +483,7 @@ impl SourceMap {
         self.span_to_string(sp, FileNameDisplayPreference::Remapped)
     }
 
-    /// Format the span location suitable for pretty printing anotations with relative line numbers
+    /// Format the span location suitable for pretty printing annotations with relative line numbers
     pub fn span_to_relative_line_string(&self, sp: Span, relative_to: Span) -> String {
         if self.files.borrow().source_files.is_empty() || sp.is_dummy() || relative_to.is_dummy() {
             return "no-location".to_string();
@@ -777,7 +777,7 @@ impl SourceMap {
 
     /// Given a 'Span', tries to tell if it's wrapped by "<>" or "()"
     /// the algorithm searches if the next character is '>' or ')' after skipping white space
-    /// then searches the previous charactoer to match '<' or '(' after skipping white space
+    /// then searches the previous character to match '<' or '(' after skipping white space
     /// return true if wrapped by '<>' or '()'
     pub fn span_wrapped_by_angle_or_parentheses(&self, span: Span) -> bool {
         self.span_to_source(span, |src, start_index, end_index| {
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 6ce0b66ef6a..d6ee7ac34aa 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -204,6 +204,7 @@ symbols! {
         HashSet,
         Hasher,
         Implied,
+        IndexOutput,
         Input,
         Into,
         IntoDiagnostic,
diff --git a/compiler/rustc_span/src/tests.rs b/compiler/rustc_span/src/tests.rs
index 5b3915c3338..a242ad6d1d7 100644
--- a/compiler/rustc_span/src/tests.rs
+++ b/compiler/rustc_span/src/tests.rs
@@ -3,8 +3,12 @@ use super::*;
 #[test]
 fn test_lookup_line() {
     let source = "abcdefghijklm\nabcdefghij\n...".to_owned();
-    let sf =
-        SourceFile::new(FileName::Anon(0), source, BytePos(3), SourceFileHashAlgorithm::Sha256);
+    let sf = SourceFile::new(
+        FileName::Anon(Hash64::ZERO),
+        source,
+        BytePos(3),
+        SourceFileHashAlgorithm::Sha256,
+    );
     sf.lines(|lines| assert_eq!(lines, &[BytePos(3), BytePos(17), BytePos(28)]));
 
     assert_eq!(sf.lookup_line(BytePos(0)), None);
diff --git a/compiler/rustc_symbol_mangling/src/legacy.rs b/compiler/rustc_symbol_mangling/src/legacy.rs
index 5cbca81926b..6a0ca06f69c 100644
--- a/compiler/rustc_symbol_mangling/src/legacy.rs
+++ b/compiler/rustc_symbol_mangling/src/legacy.rs
@@ -1,4 +1,4 @@
-use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
+use rustc_data_structures::stable_hasher::{Hash64, HashStable, StableHasher};
 use rustc_hir::def_id::CrateNum;
 use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData};
 use rustc_middle::ty::print::{PrettyPrinter, Print, Printer};
@@ -93,7 +93,7 @@ fn get_symbol_hash<'tcx>(
     item_type: Ty<'tcx>,
 
     instantiating_crate: Option<CrateNum>,
-) -> u64 {
+) -> Hash64 {
     let def_id = instance.def_id();
     let substs = instance.substs;
     debug!("get_symbol_hash(def_id={:?}, parameters={:?})", def_id, substs);
@@ -138,7 +138,7 @@ fn get_symbol_hash<'tcx>(
         });
 
         // 64 bits should be enough to avoid collisions.
-        hasher.finish::<u64>()
+        hasher.finish::<Hash64>()
     })
 }
 
@@ -176,7 +176,7 @@ impl SymbolPath {
         }
     }
 
-    fn finish(mut self, hash: u64) -> String {
+    fn finish(mut self, hash: Hash64) -> String {
         self.finalize_pending_component();
         // E = end name-sequence
         let _ = write!(self.result, "17h{hash:016x}E");
diff --git a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs
index 1a679f32ca5..262e8546a5d 100644
--- a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs
+++ b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs
@@ -406,7 +406,7 @@ fn encode_ty_name(tcx: TyCtxt<'_>, def_id: DefId) -> String {
 
     // Crate disambiguator and name
     s.push('C');
-    s.push_str(&to_disambiguator(tcx.stable_crate_id(def_path.krate).to_u64()));
+    s.push_str(&to_disambiguator(tcx.stable_crate_id(def_path.krate).as_u64()));
     let crate_name = tcx.crate_name(def_path.krate).to_string();
     let _ = write!(s, "{}{}", crate_name.len(), &crate_name);
 
diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs
index ee883285531..2235524129e 100644
--- a/compiler/rustc_symbol_mangling/src/v0.rs
+++ b/compiler/rustc_symbol_mangling/src/v0.rs
@@ -731,7 +731,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> {
     fn path_crate(self, cnum: CrateNum) -> Result<Self::Path, Self::Error> {
         self.push("C");
         let stable_crate_id = self.tcx.def_path_hash(cnum.as_def_id()).stable_crate_id();
-        self.push_disambiguator(stable_crate_id.to_u64());
+        self.push_disambiguator(stable_crate_id.as_u64());
         let name = self.tcx.crate_name(cnum);
         self.push_ident(name.as_str());
         Ok(self)
diff --git a/compiler/rustc_target/src/abi/call/avr.rs b/compiler/rustc_target/src/abi/call/avr.rs
index e20f01355a4..b01dac8c70d 100644
--- a/compiler/rustc_target/src/abi/call/avr.rs
+++ b/compiler/rustc_target/src/abi/call/avr.rs
@@ -10,7 +10,7 @@
 //! > self-consistent and sensible LLVM IR generation, but does not
 //! > conform to any particular ABI.
 //! >
-//! > - Doxygen Doxumentation of `clang::DefaultABIInfo`
+//! > - Doxygen Documentation of `clang::DefaultABIInfo`
 //!
 //! This calling convention may not match AVR-GCC in all cases.
 //!
diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs
index 4e5a821f0f6..3ee3a8ea227 100644
--- a/compiler/rustc_target/src/spec/mod.rs
+++ b/compiler/rustc_target/src/spec/mod.rs
@@ -2285,13 +2285,13 @@ impl Target {
                     }
                 }
             } );
-            ($key_name:ident, falliable_list) => ( {
+            ($key_name:ident, fallible_list) => ( {
                 let name = (stringify!($key_name)).replace("_", "-");
                 obj.remove(&name).and_then(|j| {
                     if let Some(v) = j.as_array() {
                         match v.iter().map(|a| FromStr::from_str(a.as_str().unwrap())).collect() {
                             Ok(l) => { base.$key_name = l },
-                            // FIXME: `falliable_list` can't re-use the `key!` macro for list
+                            // FIXME: `fallible_list` can't re-use the `key!` macro for list
                             // elements and the error messages from that macro, so it has a bad
                             // generic message instead
                             Err(_) => return Some(Err(
@@ -2610,7 +2610,7 @@ impl Target {
         key!(has_thumb_interworking, bool);
         key!(debuginfo_kind, DebuginfoKind)?;
         key!(split_debuginfo, SplitDebuginfo)?;
-        key!(supported_split_debuginfo, falliable_list)?;
+        key!(supported_split_debuginfo, fallible_list)?;
         key!(supported_sanitizers, SanitizerSet)?;
         key!(default_adjusted_cabi, Option<Abi>)?;
         key!(generate_arange_section, bool);
diff --git a/compiler/rustc_target/src/spec/thumb_base.rs b/compiler/rustc_target/src/spec/thumb_base.rs
index 4dcf47fe465..2220b9326c9 100644
--- a/compiler/rustc_target/src/spec/thumb_base.rs
+++ b/compiler/rustc_target/src/spec/thumb_base.rs
@@ -12,7 +12,7 @@
 //
 // We have opted for these instead of one target per processor (e.g., `cortex-m0`, `cortex-m3`,
 // etc) because the differences between some processors like the cortex-m0 and cortex-m1 are almost
-// non-existent from the POV of codegen so it doesn't make sense to have separate targets for them.
+// nonexistent from the POV of codegen so it doesn't make sense to have separate targets for them.
 // And if differences exist between two processors under the same target, rustc flags can be used to
 // optimize for one processor or the other.
 //
diff --git a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs
index 10d817f75ac..bacb0e32efc 100644
--- a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs
+++ b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs
@@ -51,7 +51,7 @@ pub(super) enum CandidateSource {
     BuiltinImpl,
     /// An assumption from the environment.
     ///
-    /// More precicely we've used the `n-th` assumption in the `param_env`.
+    /// More precisely we've used the `n-th` assumption in the `param_env`.
     ///
     /// ## Examples
     ///
@@ -241,7 +241,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
 
         // HACK: `_: Trait` is ambiguous, because it may be satisfied via a builtin rule,
         // object bound, alias bound, etc. We are unable to determine this until we can at
-        // least structually resolve the type one layer.
+        // least structurally resolve the type one layer.
         if goal.predicate.self_ty().is_ty_var() {
             return vec![Candidate {
                 source: CandidateSource::BuiltinImpl,
diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs
index ada868705c7..23cf0f0c724 100644
--- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs
+++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs
@@ -11,12 +11,13 @@
 use super::{CanonicalGoal, Certainty, EvalCtxt, Goal};
 use crate::solve::canonicalize::{CanonicalizeMode, Canonicalizer};
 use crate::solve::{CanonicalResponse, QueryResult, Response};
+use rustc_index::vec::IndexVec;
 use rustc_infer::infer::canonical::query_response::make_query_region_constraints;
 use rustc_infer::infer::canonical::CanonicalVarValues;
 use rustc_infer::infer::canonical::{CanonicalExt, QueryRegionConstraints};
 use rustc_middle::traits::query::NoSolution;
 use rustc_middle::traits::solve::{ExternalConstraints, ExternalConstraintsData};
-use rustc_middle::ty::{self, GenericArgKind};
+use rustc_middle::ty::{self, BoundVar, GenericArgKind};
 use rustc_span::DUMMY_SP;
 use std::iter;
 use std::ops::Deref;
@@ -139,25 +140,25 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
         //
         // We therefore instantiate the existential variable in the canonical response with the
         // inference variable of the input right away, which is more performant.
-        let mut opt_values = vec![None; response.variables.len()];
+        let mut opt_values = IndexVec::from_elem_n(None, response.variables.len());
         for (original_value, result_value) in iter::zip(original_values, var_values.var_values) {
             match result_value.unpack() {
                 GenericArgKind::Type(t) => {
                     if let &ty::Bound(debruijn, b) = t.kind() {
                         assert_eq!(debruijn, ty::INNERMOST);
-                        opt_values[b.var.index()] = Some(*original_value);
+                        opt_values[b.var] = Some(*original_value);
                     }
                 }
                 GenericArgKind::Lifetime(r) => {
                     if let ty::ReLateBound(debruijn, br) = *r {
                         assert_eq!(debruijn, ty::INNERMOST);
-                        opt_values[br.var.index()] = Some(*original_value);
+                        opt_values[br.var] = Some(*original_value);
                     }
                 }
                 GenericArgKind::Const(c) => {
-                    if let ty::ConstKind::Bound(debrujin, b) = c.kind() {
-                        assert_eq!(debrujin, ty::INNERMOST);
-                        opt_values[b.index()] = Some(*original_value);
+                    if let ty::ConstKind::Bound(debruijn, b) = c.kind() {
+                        assert_eq!(debruijn, ty::INNERMOST);
+                        opt_values[b] = Some(*original_value);
                     }
                 }
             }
@@ -176,11 +177,11 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
                     // As an optimization we sometimes avoid creating a new inference variable here.
                     //
                     // All new inference variables we create start out in the current universe of the caller.
-                    // This is conceptionally wrong as these inference variables would be able to name
+                    // This is conceptually wrong as these inference variables would be able to name
                     // more placeholders then they should be able to. However the inference variables have
                     // to "come from somewhere", so by equating them with the original values of the caller
                     // later on, we pull them down into their correct universe again.
-                    if let Some(v) = opt_values[index] {
+                    if let Some(v) = opt_values[BoundVar::from_usize(index)] {
                         v
                     } else {
                         self.infcx.instantiate_canonical_var(DUMMY_SP, info, |_| prev_universe)
diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals.rs b/compiler/rustc_trait_selection/src/solve/trait_goals.rs
index abd11a15ac2..1abcc80d01a 100644
--- a/compiler/rustc_trait_selection/src/solve/trait_goals.rs
+++ b/compiler/rustc_trait_selection/src/solve/trait_goals.rs
@@ -591,7 +591,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
                 Some(self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS))
             }
 
-            // These types cannot be structurally decomposed into constitutent
+            // These types cannot be structurally decomposed into constituent
             // types, and therefore have no built-in auto impl.
             ty::Dynamic(..)
             | ty::Param(..)
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
index 0352f0f380d..726b08dc7d7 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
@@ -467,7 +467,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
             }
         }
 
-        self.tcx.sess.delay_span_bug(DUMMY_SP, "expected fullfillment errors")
+        self.tcx.sess.delay_span_bug(DUMMY_SP, "expected fulfillment errors")
     }
 
     /// Reports that an overflow has occurred and halts compilation. We
@@ -2056,7 +2056,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
         if candidates.iter().any(|c| matches!(c.similarity, CandidateSimilarity::Exact { .. })) {
             // If any of the candidates is a perfect match, we don't want to show all of them.
             // This is particularly relevant for the case of numeric types (as they all have the
-            // same cathegory).
+            // same category).
             candidates.retain(|c| matches!(c.similarity, CandidateSimilarity::Exact { .. }));
         }
         candidates
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 fb75ec76729..73207f183a1 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -1381,7 +1381,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                             }
                         }
 
-                        // Issue #104961, we need to add parentheses properly for compond expressions
+                        // Issue #104961, we need to add parentheses properly for compound expressions
                         // for example, `x.starts_with("hi".to_string() + "you")`
                         // should be `x.starts_with(&("hi".to_string() + "you"))`
                         let Some(body_id) = self.tcx.hir().maybe_body_owned_by(obligation.cause.body_id) else { return false; };
diff --git a/compiler/rustc_trait_selection/src/traits/misc.rs b/compiler/rustc_trait_selection/src/traits/misc.rs
index af567c07438..63949843aed 100644
--- a/compiler/rustc_trait_selection/src/traits/misc.rs
+++ b/compiler/rustc_trait_selection/src/traits/misc.rs
@@ -14,7 +14,7 @@ use rustc_span::DUMMY_SP;
 use super::outlives_bounds::InferCtxtExt;
 
 pub enum CopyImplementationError<'tcx> {
-    InfrigingFields(Vec<(&'tcx ty::FieldDef, Ty<'tcx>, InfringingFieldsReason<'tcx>)>),
+    InfringingFields(Vec<(&'tcx ty::FieldDef, Ty<'tcx>, InfringingFieldsReason<'tcx>)>),
     NotAnAdt,
     HasDestructor,
 }
@@ -125,7 +125,7 @@ pub fn type_allowed_to_implement_copy<'tcx>(
     }
 
     if !infringing.is_empty() {
-        return Err(CopyImplementationError::InfrigingFields(infringing));
+        return Err(CopyImplementationError::InfringingFields(infringing));
     }
 
     if adt.has_dtor(tcx) {
diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs
index ed82b9c0152..4c9df5d9d0a 100644
--- a/compiler/rustc_trait_selection/src/traits/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/mod.rs
@@ -203,7 +203,7 @@ fn do_normalize_predicates<'tcx>(
         }
     };
 
-    debug!("do_normalize_predictes: normalized predicates = {:?}", predicates);
+    debug!("do_normalize_predicates: normalized predicates = {:?}", predicates);
 
     // We can use the `elaborated_env` here; the region code only
     // cares about declarations like `'a: 'b`.
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index 6bb53418bea..0fdba524e25 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -888,7 +888,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                         let c1 = tcx.expand_abstract_consts(c1);
                         let c2 = tcx.expand_abstract_consts(c2);
                         debug!(
-                            "evalaute_predicate_recursively: equating consts:\nc1= {:?}\nc2= {:?}",
+                            "evaluate_predicate_recursively: equating consts:\nc1= {:?}\nc2= {:?}",
                             c1, c2
                         );
 
diff --git a/compiler/rustc_ty_utils/src/layout_sanity_check.rs b/compiler/rustc_ty_utils/src/layout_sanity_check.rs
index a5311dbd1b7..ed513cb3c7f 100644
--- a/compiler/rustc_ty_utils/src/layout_sanity_check.rs
+++ b/compiler/rustc_ty_utils/src/layout_sanity_check.rs
@@ -285,7 +285,7 @@ pub(super) fn sanity_check_layout<'tcx>(
             {
                 // These are never actually accessed anyway, so we can skip the coherence check
                 // for them. They also fail that check, since they have
-                // `Aggregate`/`Uninhbaited` ABI even when the main type is
+                // `Aggregate`/`Uninhabited` ABI even when the main type is
                 // `Scalar`/`ScalarPair`. (Note that sometimes, variants with fields have size
                 // 0, and sometimes, variants without fields have non-0 size.)
                 continue;
diff --git a/compiler/rustc_ty_utils/src/needs_drop.rs b/compiler/rustc_ty_utils/src/needs_drop.rs
index de7fd003176..5f436f7c9fd 100644
--- a/compiler/rustc_ty_utils/src/needs_drop.rs
+++ b/compiler/rustc_ty_utils/src/needs_drop.rs
@@ -243,7 +243,7 @@ fn drop_tys_helper<'tcx>(
         } else {
             let field_tys = adt_def.all_fields().map(|field| {
                 let r = tcx.type_of(field.did).subst(tcx, substs);
-                debug!("drop_tys_helper: Subst into {:?} with {:?} gettng {:?}", field, substs, r);
+                debug!("drop_tys_helper: Subst into {:?} with {:?} getting {:?}", field, substs, r);
                 r
             });
             if only_significant {
diff --git a/compiler/rustc_type_ir/src/macros.rs b/compiler/rustc_type_ir/src/macros.rs
index 6c181039730..8c3cb228322 100644
--- a/compiler/rustc_type_ir/src/macros.rs
+++ b/compiler/rustc_type_ir/src/macros.rs
@@ -33,144 +33,3 @@ macro_rules! TrivialTypeTraversalImpls {
         )+
     };
 }
-
-macro_rules! EnumTypeTraversalImpl {
-    (impl<$($p:tt),*> TypeFoldable<$tcx:tt> for $s:path {
-        $($variants:tt)*
-    } $(where $($wc:tt)*)*) => {
-        impl<$($p),*> $crate::fold::TypeFoldable<$tcx> for $s
-            $(where $($wc)*)*
-        {
-            fn try_fold_with<V: $crate::fold::FallibleTypeFolder<$tcx>>(
-                self,
-                folder: &mut V,
-            ) -> ::std::result::Result<Self, V::Error> {
-                EnumTypeTraversalImpl!(@FoldVariants(self, folder) input($($variants)*) output())
-            }
-        }
-    };
-
-    (impl<$($p:tt),*> TypeVisitable<$tcx:tt> for $s:path {
-        $($variants:tt)*
-    } $(where $($wc:tt)*)*) => {
-        impl<$($p),*> $crate::visit::TypeVisitable<$tcx> for $s
-            $(where $($wc)*)*
-        {
-            fn visit_with<V: $crate::visit::TypeVisitor<$tcx>>(
-                &self,
-                visitor: &mut V,
-            ) -> ::std::ops::ControlFlow<V::BreakTy> {
-                EnumTypeTraversalImpl!(@VisitVariants(self, visitor) input($($variants)*) output())
-            }
-        }
-    };
-
-    (@FoldVariants($this:expr, $folder:expr) input() output($($output:tt)*)) => {
-        Ok(match $this {
-            $($output)*
-        })
-    };
-
-    (@FoldVariants($this:expr, $folder:expr)
-     input( ($variant:path) ( $($variant_arg:ident),* ) , $($input:tt)*)
-     output( $($output:tt)*) ) => {
-        EnumTypeTraversalImpl!(
-            @FoldVariants($this, $folder)
-                input($($input)*)
-                output(
-                    $variant ( $($variant_arg),* ) => {
-                        $variant (
-                            $($crate::fold::TypeFoldable::try_fold_with($variant_arg, $folder)?),*
-                        )
-                    }
-                    $($output)*
-                )
-        )
-    };
-
-    (@FoldVariants($this:expr, $folder:expr)
-     input( ($variant:path) { $($variant_arg:ident),* $(,)? } , $($input:tt)*)
-     output( $($output:tt)*) ) => {
-        EnumTypeTraversalImpl!(
-            @FoldVariants($this, $folder)
-                input($($input)*)
-                output(
-                    $variant { $($variant_arg),* } => {
-                        $variant {
-                            $($variant_arg: $crate::fold::TypeFoldable::fold_with(
-                                $variant_arg, $folder
-                            )?),* }
-                    }
-                    $($output)*
-                )
-        )
-    };
-
-    (@FoldVariants($this:expr, $folder:expr)
-     input( ($variant:path), $($input:tt)*)
-     output( $($output:tt)*) ) => {
-        EnumTypeTraversalImpl!(
-            @FoldVariants($this, $folder)
-                input($($input)*)
-                output(
-                    $variant => { $variant }
-                    $($output)*
-                )
-        )
-    };
-
-    (@VisitVariants($this:expr, $visitor:expr) input() output($($output:tt)*)) => {
-        match $this {
-            $($output)*
-        }
-    };
-
-    (@VisitVariants($this:expr, $visitor:expr)
-     input( ($variant:path) ( $($variant_arg:ident),* ) , $($input:tt)*)
-     output( $($output:tt)*) ) => {
-        EnumTypeTraversalImpl!(
-            @VisitVariants($this, $visitor)
-                input($($input)*)
-                output(
-                    $variant ( $($variant_arg),* ) => {
-                        $($crate::visit::TypeVisitable::visit_with(
-                            $variant_arg, $visitor
-                        )?;)*
-                        ::std::ops::ControlFlow::Continue(())
-                    }
-                    $($output)*
-                )
-        )
-    };
-
-    (@VisitVariants($this:expr, $visitor:expr)
-     input( ($variant:path) { $($variant_arg:ident),* $(,)? } , $($input:tt)*)
-     output( $($output:tt)*) ) => {
-        EnumTypeTraversalImpl!(
-            @VisitVariants($this, $visitor)
-                input($($input)*)
-                output(
-                    $variant { $($variant_arg),* } => {
-                        $($crate::visit::TypeVisitable::visit_with(
-                            $variant_arg, $visitor
-                        )?;)*
-                        ::std::ops::ControlFlow::Continue(())
-                    }
-                    $($output)*
-                )
-        )
-    };
-
-    (@VisitVariants($this:expr, $visitor:expr)
-     input( ($variant:path), $($input:tt)*)
-     output( $($output:tt)*) ) => {
-        EnumTypeTraversalImpl!(
-            @VisitVariants($this, $visitor)
-                input($($input)*)
-                output(
-                    $variant => { ::std::ops::ControlFlow::Continue(()) }
-                    $($output)*
-                )
-        )
-    };
-}
diff --git a/compiler/rustc_type_ir/src/structural_impls.rs b/compiler/rustc_type_ir/src/structural_impls.rs
index 3ebe241042f..c90c86b7690 100644
--- a/compiler/rustc_type_ir/src/structural_impls.rs
+++ b/compiler/rustc_type_ir/src/structural_impls.rs
@@ -70,30 +70,40 @@ impl<I: Interner, A: TypeVisitable<I>, B: TypeVisitable<I>, C: TypeVisitable<I>>
     }
 }
 
-EnumTypeTraversalImpl! {
-    impl<I, T> TypeFoldable<I> for Option<T> {
-        (Some)(a),
-        (None),
-    } where I: Interner, T: TypeFoldable<I>
-}
-EnumTypeTraversalImpl! {
-    impl<I, T> TypeVisitable<I> for Option<T> {
-        (Some)(a),
-        (None),
-    } where I: Interner, T: TypeVisitable<I>
-}
-
-EnumTypeTraversalImpl! {
-    impl<I, T, E> TypeFoldable<I> for Result<T, E> {
-        (Ok)(a),
-        (Err)(a),
-    } where I: Interner, T: TypeFoldable<I>, E: TypeFoldable<I>,
-}
-EnumTypeTraversalImpl! {
-    impl<I, T, E> TypeVisitable<I> for Result<T, E> {
-        (Ok)(a),
-        (Err)(a),
-    } where I: Interner, T: TypeVisitable<I>, E: TypeVisitable<I>,
+impl<I: Interner, T: TypeFoldable<I>> TypeFoldable<I> for Option<T> {
+    fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
+        Ok(match self {
+            Some(v) => Some(v.try_fold_with(folder)?),
+            None => None,
+        })
+    }
+}
+
+impl<I: Interner, T: TypeVisitable<I>> TypeVisitable<I> for Option<T> {
+    fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
+        match self {
+            Some(v) => v.visit_with(visitor),
+            None => ControlFlow::Continue(()),
+        }
+    }
+}
+
+impl<I: Interner, T: TypeFoldable<I>, E: TypeFoldable<I>> TypeFoldable<I> for Result<T, E> {
+    fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
+        Ok(match self {
+            Ok(v) => Ok(v.try_fold_with(folder)?),
+            Err(e) => Err(e.try_fold_with(folder)?),
+        })
+    }
+}
+
+impl<I: Interner, T: TypeVisitable<I>, E: TypeVisitable<I>> TypeVisitable<I> for Result<T, E> {
+    fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
+        match self {
+            Ok(v) => v.visit_with(visitor),
+            Err(e) => e.visit_with(visitor),
+        }
+    }
 }
 
 impl<I: Interner, T: TypeFoldable<I>> TypeFoldable<I> for Rc<T> {
diff --git a/library/core/src/ops/index.rs b/library/core/src/ops/index.rs
index 228efb0bc0a..f3754484f6a 100644
--- a/library/core/src/ops/index.rs
+++ b/library/core/src/ops/index.rs
@@ -59,6 +59,7 @@
 pub trait Index<Idx: ?Sized> {
     /// The returned type after indexing.
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[rustc_diagnostic_item = "IndexOutput"]
     type Output: ?Sized;
 
     /// Performs the indexing (`container[index]`) operation.
diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs
index 839afc57f85..3838c39cc6a 100644
--- a/library/core/src/ptr/const_ptr.rs
+++ b/library/core/src/ptr/const_ptr.rs
@@ -132,8 +132,8 @@ impl<T: ?Sized> *const T {
     /// ```
     #[unstable(feature = "ptr_to_from_bits", issue = "91126")]
     #[deprecated(
-        since = "1.67",
-        note = "replaced by the `exposed_addr` method, or update your code \
+        since = "1.67.0",
+        note = "replaced by the `expose_addr` method, or update your code \
             to follow the strict provenance rules using its APIs"
     )]
     #[inline(always)]
@@ -161,7 +161,7 @@ impl<T: ?Sized> *const T {
     /// ```
     #[unstable(feature = "ptr_to_from_bits", issue = "91126")]
     #[deprecated(
-        since = "1.67",
+        since = "1.67.0",
         note = "replaced by the `ptr::from_exposed_addr` function, or update \
             your code to follow the strict provenance rules using its APIs"
     )]
diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs
index ece5244e9a9..e522b6dc15c 100644
--- a/library/core/src/ptr/mut_ptr.rs
+++ b/library/core/src/ptr/mut_ptr.rs
@@ -138,8 +138,8 @@ impl<T: ?Sized> *mut T {
     /// ```
     #[unstable(feature = "ptr_to_from_bits", issue = "91126")]
     #[deprecated(
-        since = "1.67",
-        note = "replaced by the `exposed_addr` method, or update your code \
+        since = "1.67.0",
+        note = "replaced by the `expose_addr` method, or update your code \
             to follow the strict provenance rules using its APIs"
     )]
     #[inline(always)]
@@ -167,7 +167,7 @@ impl<T: ?Sized> *mut T {
     /// ```
     #[unstable(feature = "ptr_to_from_bits", issue = "91126")]
     #[deprecated(
-        since = "1.67",
+        since = "1.67.0",
         note = "replaced by the `ptr::from_exposed_addr_mut` function, or \
             update your code to follow the strict provenance rules using its APIs"
     )]
diff --git a/src/bootstrap/bin/main.rs b/src/bootstrap/bin/main.rs
index 912d875e445..a80379e85c1 100644
--- a/src/bootstrap/bin/main.rs
+++ b/src/bootstrap/bin/main.rs
@@ -16,9 +16,11 @@ fn main() {
     let config = Config::parse(&args);
 
     #[cfg(all(any(unix, windows), not(target_os = "solaris")))]
+    let mut build_lock;
+    #[cfg(all(any(unix, windows), not(target_os = "solaris")))]
+    let _build_lock_guard;
+    #[cfg(all(any(unix, windows), not(target_os = "solaris")))]
     {
-        let mut build_lock;
-        let _build_lock_guard;
         let path = config.out.join("lock");
         build_lock = fd_lock::RwLock::new(t!(std::fs::File::create(&path)));
         _build_lock_guard = match build_lock.try_write() {
diff --git a/src/bootstrap/bin/rustc.rs b/src/bootstrap/bin/rustc.rs
index 040fec3615b..dd86634b47c 100644
--- a/src/bootstrap/bin/rustc.rs
+++ b/src/bootstrap/bin/rustc.rs
@@ -150,7 +150,7 @@ fn main() {
     // allow the `rustc_private` feature to link to other unstable crates
     // also in the sysroot. We also do this for host crates, since those
     // may be proc macros, in which case we might ship them.
-    if env::var_os("RUSTC_FORCE_UNSTABLE").is_some() && (stage != "0" || target.is_some()) {
+    if env::var_os("RUSTC_FORCE_UNSTABLE").is_some() {
         cmd.arg("-Z").arg("force-unstable-if-unmarked");
     }
 
diff --git a/src/bootstrap/bolt.rs b/src/bootstrap/bolt.rs
index 10e6d2e7d6d..5384181ea68 100644
--- a/src/bootstrap/bolt.rs
+++ b/src/bootstrap/bolt.rs
@@ -40,7 +40,7 @@ pub fn optimize_with_bolt(path: &Path, profile_path: &Path, output_path: &Path)
         // Reorder functions within the binary
         .arg("-reorder-functions=hfsort+")
         // Split function code into hot and code regions
-        .arg("-split-functions=2")
+        .arg("-split-functions")
         // Split as many basic blocks as possible
         .arg("-split-all-cold")
         // Move jump tables to a separate section
diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs
index e959ea06f8b..9666874d0fe 100644
--- a/src/bootstrap/builder.rs
+++ b/src/bootstrap/builder.rs
@@ -1008,9 +1008,24 @@ impl<'a> Builder<'a> {
                 // Avoid deleting the rustlib/ directory we just copied
                 // (in `impl Step for Sysroot`).
                 if !builder.download_rustc() {
+                    builder.verbose(&format!(
+                        "Removing sysroot {} to avoid caching bugs",
+                        sysroot.display()
+                    ));
                     let _ = fs::remove_dir_all(&sysroot);
                     t!(fs::create_dir_all(&sysroot));
                 }
+
+                if self.compiler.stage == 0 {
+                    // The stage 0 compiler for the build triple is always pre-built.
+                    // Ensure that `libLLVM.so` ends up in the target libdir, so that ui-fulldeps tests can use it when run.
+                    dist::maybe_install_llvm_target(
+                        builder,
+                        self.compiler.host,
+                        &builder.sysroot(self.compiler),
+                    );
+                }
+
                 INTERNER.intern_path(sysroot)
             }
         }
@@ -2030,7 +2045,7 @@ impl<'a> Builder<'a> {
         }
 
         #[cfg(feature = "build-metrics")]
-        self.metrics.enter_step(&step);
+        self.metrics.enter_step(&step, self);
 
         let (out, dur) = {
             let start = Instant::now();
@@ -2056,7 +2071,7 @@ impl<'a> Builder<'a> {
         }
 
         #[cfg(feature = "build-metrics")]
-        self.metrics.exit_step();
+        self.metrics.exit_step(self);
 
         {
             let mut stack = self.stack.borrow_mut();
diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs
index fcaa698317d..44efc502e39 100644
--- a/src/bootstrap/check.rs
+++ b/src/bootstrap/check.rs
@@ -271,17 +271,9 @@ impl Step for Rustc {
             false,
         );
 
-        // HACK: This avoids putting the newly built artifacts in the sysroot if we're using
-        // `download-rustc`, to avoid "multiple candidates for `rmeta`" errors. Technically, that's
-        // not quite right: people can set `download-rustc = true` to download even if there are
-        // changes to the compiler, and in that case ideally we would put the *new* artifacts in the
-        // sysroot, in case there are API changes that should be used by tools.  In practice,
-        // though, that should be very uncommon, and people can still disable download-rustc.
-        if !builder.download_rustc() {
-            let libdir = builder.sysroot_libdir(compiler, target);
-            let hostdir = builder.sysroot_libdir(compiler, compiler.host);
-            add_to_sysroot(&builder, &libdir, &hostdir, &librustc_stamp(builder, compiler, target));
-        }
+        let libdir = builder.sysroot_libdir(compiler, target);
+        let hostdir = builder.sysroot_libdir(compiler, compiler.host);
+        add_to_sysroot(&builder, &libdir, &hostdir, &librustc_stamp(builder, compiler, target));
     }
 }
 
diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs
index 4a4e7adcbf3..8af5927e27f 100644
--- a/src/bootstrap/compile.rs
+++ b/src/bootstrap/compile.rs
@@ -9,6 +9,7 @@
 use std::borrow::Cow;
 use std::collections::HashSet;
 use std::env;
+use std::ffi::OsStr;
 use std::fs;
 use std::io::prelude::*;
 use std::io::BufReader;
@@ -652,8 +653,19 @@ impl Step for Rustc {
         // so its artifacts can't be reused.
         if builder.download_rustc() && compiler.stage != 0 {
             // Copy the existing artifacts instead of rebuilding them.
-            // NOTE: this path is only taken for tools linking to rustc-dev.
-            builder.ensure(Sysroot { compiler });
+            // NOTE: this path is only taken for tools linking to rustc-dev (including ui-fulldeps tests).
+            let sysroot = builder.ensure(Sysroot { compiler });
+
+            let ci_rustc_dir = builder.out.join(&*builder.build.build.triple).join("ci-rustc");
+            for file in builder.config.rustc_dev_contents() {
+                let src = ci_rustc_dir.join(&file);
+                let dst = sysroot.join(file);
+                if src.is_dir() {
+                    t!(fs::create_dir_all(dst));
+                } else {
+                    builder.copy(&src, &dst);
+                }
+            }
             return;
         }
 
@@ -1260,6 +1272,7 @@ impl Step for Sysroot {
         };
         let sysroot = sysroot_dir(compiler.stage);
 
+        builder.verbose(&format!("Removing sysroot {} to avoid caching bugs", sysroot.display()));
         let _ = fs::remove_dir_all(&sysroot);
         t!(fs::create_dir_all(&sysroot));
 
@@ -1281,7 +1294,40 @@ impl Step for Sysroot {
             }
 
             // Copy the compiler into the correct sysroot.
-            builder.cp_r(&builder.ci_rustc_dir(builder.build.build), &sysroot);
+            // NOTE(#108767): We intentionally don't copy `rustc-dev` artifacts until they're requested with `builder.ensure(Rustc)`.
+            // This fixes an issue where we'd have multiple copies of libc in the sysroot with no way to tell which to load.
+            // There are a few quirks of bootstrap that interact to make this reliable:
+            // 1. The order `Step`s are run is hard-coded in `builder.rs` and not configurable. This
+            //    avoids e.g. reordering `test::UiFulldeps` before `test::Ui` and causing the latter to
+            //    fail because of duplicate metadata.
+            // 2. The sysroot is deleted and recreated between each invocation, so running `x test
+            //    ui-fulldeps && x test ui` can't cause failures.
+            let mut filtered_files = Vec::new();
+            // Don't trim directories or files that aren't loaded per-target; they can't cause conflicts.
+            let suffix = format!("lib/rustlib/{}/lib", compiler.host);
+            for path in builder.config.rustc_dev_contents() {
+                let path = Path::new(&path);
+                if path.parent().map_or(false, |parent| parent.ends_with(&suffix)) {
+                    filtered_files.push(path.file_name().unwrap().to_owned());
+                }
+            }
+
+            let filtered_extensions = [OsStr::new("rmeta"), OsStr::new("rlib"), OsStr::new("so")];
+            let ci_rustc_dir = builder.ci_rustc_dir(builder.config.build);
+            builder.cp_filtered(&ci_rustc_dir, &sysroot, &|path| {
+                if path.extension().map_or(true, |ext| !filtered_extensions.contains(&ext)) {
+                    return true;
+                }
+                if !path.parent().map_or(true, |p| p.ends_with(&suffix)) {
+                    return true;
+                }
+                if !filtered_files.iter().all(|f| f != path.file_name().unwrap()) {
+                    builder.verbose_than(1, &format!("ignoring {}", path.display()));
+                    false
+                } else {
+                    true
+                }
+            });
             return INTERNER.intern_path(sysroot);
         }
 
diff --git a/src/bootstrap/download-ci-llvm-stamp b/src/bootstrap/download-ci-llvm-stamp
index 36f9aaa595d..4111b7cc0d3 100644
--- a/src/bootstrap/download-ci-llvm-stamp
+++ b/src/bootstrap/download-ci-llvm-stamp
@@ -1,4 +1,4 @@
 Change this file to make users of the `download-ci-llvm` configuration download
 a new version of LLVM from CI, even if the LLVM submodule hasn’t changed.
 
-Last change is for: https://github.com/rust-lang/rust/pull/109373
+Last change is for: https://github.com/rust-lang/rust/pull/96971
diff --git a/src/bootstrap/download.rs b/src/bootstrap/download.rs
index 24251556584..133cda639d9 100644
--- a/src/bootstrap/download.rs
+++ b/src/bootstrap/download.rs
@@ -2,7 +2,7 @@ use std::{
     env,
     ffi::{OsStr, OsString},
     fs::{self, File},
-    io::{BufRead, BufReader, ErrorKind},
+    io::{BufRead, BufReader, BufWriter, ErrorKind, Write},
     path::{Path, PathBuf},
     process::{Command, Stdio},
 };
@@ -262,10 +262,20 @@ impl Config {
         let directory_prefix = Path::new(Path::new(uncompressed_filename).file_stem().unwrap());
 
         // decompress the file
-        let data = t!(File::open(tarball));
+        let data = t!(File::open(tarball), format!("file {} not found", tarball.display()));
         let decompressor = XzDecoder::new(BufReader::new(data));
 
         let mut tar = tar::Archive::new(decompressor);
+
+        // `compile::Sysroot` needs to know the contents of the `rustc-dev` tarball to avoid adding
+        // it to the sysroot unless it was explicitly requested. But parsing the 100 MB tarball is slow.
+        // Cache the entries when we extract it so we only have to read it once.
+        let mut recorded_entries = if dst.ends_with("ci-rustc") && pattern == "rustc-dev" {
+            Some(BufWriter::new(t!(File::create(dst.join(".rustc-dev-contents")))))
+        } else {
+            None
+        };
+
         for member in t!(tar.entries()) {
             let mut member = t!(member);
             let original_path = t!(member.path()).into_owned();
@@ -283,13 +293,19 @@ impl Config {
             if !t!(member.unpack_in(dst)) {
                 panic!("path traversal attack ??");
             }
+            if let Some(record) = &mut recorded_entries {
+                t!(writeln!(record, "{}", short_path.to_str().unwrap()));
+            }
             let src_path = dst.join(original_path);
             if src_path.is_dir() && dst_path.exists() {
                 continue;
             }
             t!(fs::rename(src_path, dst_path));
         }
-        t!(fs::remove_dir_all(dst.join(directory_prefix)));
+        let dst_dir = dst.join(directory_prefix);
+        if dst_dir.exists() {
+            t!(fs::remove_dir_all(&dst_dir), format!("failed to remove {}", dst_dir.display()));
+        }
     }
 
     /// Returns whether the SHA256 checksum of `path` matches `expected`.
@@ -365,6 +381,13 @@ impl Config {
         Some(rustfmt_path)
     }
 
+    pub(crate) fn rustc_dev_contents(&self) -> Vec<String> {
+        assert!(self.download_rustc());
+        let ci_rustc_dir = self.out.join(&*self.build.triple).join("ci-rustc");
+        let rustc_dev_contents_file = t!(File::open(ci_rustc_dir.join(".rustc-dev-contents")));
+        t!(BufReader::new(rustc_dev_contents_file).lines().collect())
+    }
+
     pub(crate) fn download_ci_rustc(&self, commit: &str) {
         self.verbose(&format!("using downloaded stage2 artifacts from CI (commit {commit})"));
 
diff --git a/src/bootstrap/metrics.rs b/src/bootstrap/metrics.rs
index 82b123ec8a5..e19d56ccd6a 100644
--- a/src/bootstrap/metrics.rs
+++ b/src/bootstrap/metrics.rs
@@ -4,7 +4,7 @@
 //! As this module requires additional dependencies not present during local builds, it's cfg'd
 //! away whenever the `build.metrics` config option is not set to `true`.
 
-use crate::builder::Step;
+use crate::builder::{Builder, Step};
 use crate::util::t;
 use crate::Build;
 use serde_derive::{Deserialize, Serialize};
@@ -33,7 +33,12 @@ impl BuildMetrics {
         BuildMetrics { state }
     }
 
-    pub(crate) fn enter_step<S: Step>(&self, step: &S) {
+    pub(crate) fn enter_step<S: Step>(&self, step: &S, builder: &Builder<'_>) {
+        // Do not record dry runs, as they'd be duplicates of the actual steps.
+        if builder.config.dry_run() {
+            return;
+        }
+
         let mut state = self.state.borrow_mut();
 
         // Consider all the stats gathered so far as the parent's.
@@ -56,7 +61,12 @@ impl BuildMetrics {
         });
     }
 
-    pub(crate) fn exit_step(&self) {
+    pub(crate) fn exit_step(&self, builder: &Builder<'_>) {
+        // Do not record dry runs, as they'd be duplicates of the actual steps.
+        if builder.config.dry_run() {
+            return;
+        }
+
         let mut state = self.state.borrow_mut();
 
         self.collect_stats(&mut *state);
@@ -74,7 +84,12 @@ impl BuildMetrics {
         }
     }
 
-    pub(crate) fn record_test(&self, name: &str, outcome: TestOutcome) {
+    pub(crate) fn record_test(&self, name: &str, outcome: TestOutcome, builder: &Builder<'_>) {
+        // Do not record dry runs, as they'd be duplicates of the actual steps.
+        if builder.config.dry_run() {
+            return;
+        }
+
         let mut state = self.state.borrow_mut();
         state
             .running_steps
diff --git a/src/bootstrap/render_tests.rs b/src/bootstrap/render_tests.rs
index 19019ad2c08..a56db9cccfe 100644
--- a/src/bootstrap/render_tests.rs
+++ b/src/bootstrap/render_tests.rs
@@ -124,6 +124,7 @@ impl<'a> Renderer<'a> {
                     ignore_reason: reason.map(|s| s.to_string()),
                 },
             },
+            self.builder,
         );
 
         if self.builder.config.verbose_tests {
diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs
index aedf1ecab13..ccf83974b8c 100644
--- a/src/bootstrap/test.rs
+++ b/src/bootstrap/test.rs
@@ -1448,7 +1448,7 @@ note: if you're sure you want to do this, please open an issue as to why. In the
             crate::detail_exit(1);
         }
 
-        let compiler = self.compiler;
+        let mut compiler = self.compiler;
         let target = self.target;
         let mode = self.mode;
         let suite = self.suite;
@@ -1461,15 +1461,28 @@ note: if you're sure you want to do this, please open an issue as to why. In the
             return;
         }
 
-        if suite == "debuginfo" {
-            builder
-                .ensure(dist::DebuggerScripts { sysroot: builder.sysroot(compiler), host: target });
-        }
+        // Support stage 1 ui-fulldeps. This is somewhat complicated: ui-fulldeps tests for the most
+        // part test the *API* of the compiler, not how it compiles a given file. As a result, we
+        // can run them against the stage 1 sources as long as we build them with the stage 0
+        // bootstrap compiler.
+        // NOTE: Only stage 1 is special cased because we need the rustc_private artifacts to match the
+        // running compiler in stage 2 when plugins run.
+        let stage_id = if suite == "ui-fulldeps" && compiler.stage == 1 {
+            compiler = builder.compiler(compiler.stage - 1, target);
+            format!("stage{}-{}", compiler.stage + 1, target)
+        } else {
+            format!("stage{}-{}", compiler.stage, target)
+        };
 
         if suite.ends_with("fulldeps") {
             builder.ensure(compile::Rustc::new(compiler, target));
         }
 
+        if suite == "debuginfo" {
+            builder
+                .ensure(dist::DebuggerScripts { sysroot: builder.sysroot(compiler), host: target });
+        }
+
         builder.ensure(compile::Std::new(compiler, target));
         // ensure that `libproc_macro` is available on the host.
         builder.ensure(compile::Std::new(compiler, compiler.host));
@@ -1528,7 +1541,7 @@ note: if you're sure you want to do this, please open an issue as to why. In the
         cmd.arg("--src-base").arg(builder.src.join("tests").join(suite));
         cmd.arg("--build-base").arg(testdir(builder, compiler.host).join(suite));
         cmd.arg("--sysroot-base").arg(builder.sysroot(compiler));
-        cmd.arg("--stage-id").arg(format!("stage{}-{}", compiler.stage, target));
+        cmd.arg("--stage-id").arg(stage_id);
         cmd.arg("--suite").arg(suite);
         cmd.arg("--mode").arg(mode);
         cmd.arg("--target").arg(target.rustc_target_arg());
@@ -1804,6 +1817,10 @@ note: if you're sure you want to do this, please open an issue as to why. In the
 
         cmd.arg("--channel").arg(&builder.config.channel);
 
+        if !builder.config.omit_git_hash {
+            cmd.arg("--git-hash");
+        }
+
         if let Some(commit) = builder.config.download_rustc_commit() {
             cmd.env("FAKE_DOWNLOAD_RUSTC_PREFIX", format!("/rustc/{commit}"));
         }
diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs
index c732fd7e833..79fab00efe7 100644
--- a/src/bootstrap/tool.rs
+++ b/src/bootstrap/tool.rs
@@ -194,6 +194,12 @@ pub fn prepare_tool_cargo(
     cargo.env("CFG_VERSION", builder.rust_version());
     cargo.env("CFG_RELEASE_NUM", &builder.version);
     cargo.env("DOC_RUST_LANG_ORG_CHANNEL", builder.doc_rust_lang_org_channel());
+    if let Some(ref ver_date) = builder.rust_info().commit_date() {
+        cargo.env("CFG_VER_DATE", ver_date);
+    }
+    if let Some(ref ver_hash) = builder.rust_info().sha() {
+        cargo.env("CFG_VER_HASH", ver_hash);
+    }
 
     let info = GitInfo::new(builder.config.omit_git_hash, &dir);
     if let Some(sha) = info.sha() {
diff --git a/src/ci/docker/host-x86_64/dist-x86_64-illumos/Dockerfile b/src/ci/docker/host-x86_64/dist-x86_64-illumos/Dockerfile
index 2089bf38716..55fefd2b725 100644
--- a/src/ci/docker/host-x86_64/dist-x86_64-illumos/Dockerfile
+++ b/src/ci/docker/host-x86_64/dist-x86_64-illumos/Dockerfile
@@ -6,12 +6,13 @@ RUN sed -i 's/^# deb-src/deb-src/' /etc/apt/sources.list
 COPY scripts/cross-apt-packages.sh /tmp/
 RUN bash /tmp/cross-apt-packages.sh
 
-# Required for cross-build gcc
+# Required for cross-build gcc, and we install python2 to test general compatibility.
 RUN apt-get update && \
     apt-get install -y --no-install-recommends \
     libgmp-dev \
     libmpfr-dev \
     libmpc-dev \
+    python2.7 \
     && rm -rf /var/lib/apt/lists/*
 
 COPY scripts/illumos-toolchain.sh /tmp/
@@ -35,4 +36,4 @@ ENV \
 ENV HOSTS=x86_64-unknown-illumos
 
 ENV RUST_CONFIGURE_ARGS --enable-extended --disable-docs
-ENV SCRIPT python3 ../x.py dist --host $HOSTS --target $HOSTS
+ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-15/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-15/Dockerfile
index fb5037e3b97..c471843b853 100644
--- a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-15/Dockerfile
+++ b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-15/Dockerfile
@@ -2,7 +2,6 @@ FROM ubuntu:22.10
 
 ARG DEBIAN_FRONTEND=noninteractive
 
-# NOTE: intentionally installs both python2 and python3 so we can test support for both.
 RUN apt-get update && apt-get install -y --no-install-recommends \
   g++ \
   gcc-multilib \
@@ -11,7 +10,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   file \
   curl \
   ca-certificates \
-  python2.7 \
   python3 \
   git \
   cmake \
@@ -63,6 +61,4 @@ ENV SCRIPT ../x.py --stage 2 test --exclude src/tools/tidy && \
            # work.
            #
            ../x.ps1 --stage 2 test tests/ui --pass=check \
-                             --host='' --target=i686-unknown-linux-gnu && \
-           # Run tidy at the very end, after all the other tests.
-           python2.7 ../x.py --stage 2 test src/tools/tidy
+                             --host='' --target=i686-unknown-linux-gnu
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-16/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-16/Dockerfile
new file mode 100644
index 00000000000..7c75d0df590
--- /dev/null
+++ b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-16/Dockerfile
@@ -0,0 +1,64 @@
+FROM ubuntu:23.04
+
+ARG DEBIAN_FRONTEND=noninteractive
+
+RUN apt-get update && apt-get install -y --no-install-recommends \
+  g++ \
+  gcc-multilib \
+  make \
+  ninja-build \
+  file \
+  curl \
+  ca-certificates \
+  python3 \
+  git \
+  cmake \
+  sudo \
+  gdb \
+  llvm-16-tools \
+  llvm-16-dev \
+  libedit-dev \
+  libssl-dev \
+  pkg-config \
+  zlib1g-dev \
+  xz-utils \
+  nodejs \
+  mingw-w64 \
+  && rm -rf /var/lib/apt/lists/*
+
+# Install powershell (universal package) so we can test x.ps1 on Linux
+RUN curl -sL "https://github.com/PowerShell/PowerShell/releases/download/v7.3.1/powershell_7.3.1-1.deb_amd64.deb" > powershell.deb && \
+    dpkg -i powershell.deb && \
+    rm -f powershell.deb
+
+COPY scripts/sccache.sh /scripts/
+RUN sh /scripts/sccache.sh
+
+# We are disabling CI LLVM since this builder is intentionally using a host
+# LLVM, rather than the typical src/llvm-project LLVM.
+ENV NO_DOWNLOAD_CI_LLVM 1
+
+# Using llvm-link-shared due to libffi issues -- see #34486
+ENV RUST_CONFIGURE_ARGS \
+      --build=x86_64-unknown-linux-gnu \
+      --llvm-root=/usr/lib/llvm-16 \
+      --enable-llvm-link-shared \
+      --set rust.thin-lto-import-instr-limit=10
+
+# NOTE: intentionally uses all of `x.py`, `x`, and `x.ps1` to make sure they all work on Linux.
+ENV SCRIPT ../x.py --stage 2 test --exclude src/tools/tidy && \
+           # Run the `mir-opt` tests again but this time for a 32-bit target.
+           # This enforces that tests using `// EMIT_MIR_FOR_EACH_BIT_WIDTH` have
+           # both 32-bit and 64-bit outputs updated by the PR author, before
+           # the PR is approved and tested for merging.
+           # It will also detect tests lacking `// EMIT_MIR_FOR_EACH_BIT_WIDTH`,
+           # despite having different output on 32-bit vs 64-bit targets.
+           ../x --stage 2 test tests/mir-opt \
+                             --host='' --target=i686-unknown-linux-gnu && \
+           # Run the UI test suite again, but in `--pass=check` mode
+           #
+           # This is intended to make sure that both `--pass=check` continues to
+           # work.
+           #
+           ../x.ps1 --stage 2 test tests/ui --pass=check \
+                             --host='' --target=i686-unknown-linux-gnu
diff --git a/src/ci/github-actions/ci.yml b/src/ci/github-actions/ci.yml
index dbf4be4be24..8c7798aad8b 100644
--- a/src/ci/github-actions/ci.yml
+++ b/src/ci/github-actions/ci.yml
@@ -457,6 +457,11 @@ jobs:
           - name: x86_64-gnu-distcheck
             <<: *job-linux-8c
 
+          - name: x86_64-gnu-llvm-16
+            env:
+              RUST_BACKTRACE: 1
+            <<: *job-linux-8c
+
           - name: x86_64-gnu-llvm-15
             env:
               RUST_BACKTRACE: 1
diff --git a/src/doc/rustc/src/codegen-options/index.md b/src/doc/rustc/src/codegen-options/index.md
index 62347f169a5..d7c6a884fc8 100644
--- a/src/doc/rustc/src/codegen-options/index.md
+++ b/src/doc/rustc/src/codegen-options/index.md
@@ -84,8 +84,8 @@ Note: The [`-g` flag][option-g-debug] is an alias for `-C debuginfo=2`.
 This flag controls whether or not the linker includes its default libraries.
 It takes one of the following values:
 
-* `y`, `yes`, `on`, `true` or no value: include default libraries (the default).
-* `n`, `no`, `off` or `false`: exclude default libraries.
+* `y`, `yes`, `on`, `true`: include default libraries.
+* `n`, `no`, `off` or `false` or no value: exclude default libraries (the default).
 
 For example, for gcc flavor linkers, this issues the `-nodefaultlibs` flag to
 the linker.
diff --git a/src/doc/rustdoc/src/write-documentation/linking-to-items-by-name.md b/src/doc/rustdoc/src/write-documentation/linking-to-items-by-name.md
index eb2285ef906..72157b5cd9b 100644
--- a/src/doc/rustdoc/src/write-documentation/linking-to-items-by-name.md
+++ b/src/doc/rustdoc/src/write-documentation/linking-to-items-by-name.md
@@ -88,13 +88,16 @@ fn Foo() {}
 ```
 
 These prefixes will be stripped when displayed in the documentation, so `[struct@Foo]` will be
-rendered as `Foo`.
+rendered as `Foo`. The following prefixes are available: `struct`, `enum`, `trait`, `union`,
+`mod`, `module`, `const`, `constant`, `fn`, `function`, `method`, `derive`, `type`, `value`,
+`macro`, `prim` or `primitive`.
 
 You can also disambiguate for functions by adding `()` after the function name,
-or for macros by adding `!` after the macro name:
+or for macros by adding `!` after the macro name. The macro `!` can be followed by `()`, `{}`,
+or `[]`. Example:
 
 ```rust
-/// This is different from [`foo!`]
+/// This is different from [`foo!()`].
 fn foo() {}
 
 /// This is different from [`foo()`]
diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs
index a835bd2de3b..33e80df9ed7 100644
--- a/src/librustdoc/passes/collect_intra_doc_links.rs
+++ b/src/librustdoc/passes/collect_intra_doc_links.rs
@@ -1419,6 +1419,7 @@ impl Disambiguator {
         if let Some(idx) = link.find('@') {
             let (prefix, rest) = link.split_at(idx);
             let d = match prefix {
+                // If you update this list, please also update the relevant rustdoc book section!
                 "struct" => Kind(DefKind::Struct),
                 "enum" => Kind(DefKind::Enum),
                 "trait" => Kind(DefKind::Trait),
@@ -1437,6 +1438,7 @@ impl Disambiguator {
             Ok(Some((d, &rest[1..], &rest[1..])))
         } else {
             let suffixes = [
+                // If you update this list, please also update the relevant rustdoc book section!
                 ("!()", DefKind::Macro(MacroKind::Bang)),
                 ("!{}", DefKind::Macro(MacroKind::Bang)),
                 ("![]", DefKind::Macro(MacroKind::Bang)),
diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs
index f54b70b417d..a6089680fae 100644
--- a/src/librustdoc/visit_ast.rs
+++ b/src/librustdoc/visit_ast.rs
@@ -10,6 +10,7 @@ use rustc_hir::{Node, CRATE_HIR_ID};
 use rustc_middle::hir::nested_filter;
 use rustc_middle::ty::TyCtxt;
 use rustc_span::def_id::{CRATE_DEF_ID, LOCAL_CRATE};
+use rustc_span::hygiene::MacroKind;
 use rustc_span::symbol::{kw, sym, Symbol};
 use rustc_span::Span;
 
@@ -87,6 +88,7 @@ pub(crate) struct RustdocVisitor<'a, 'tcx> {
     inside_public_path: bool,
     exact_paths: DefIdMap<Vec<Symbol>>,
     modules: Vec<Module<'tcx>>,
+    is_importable_from_parent: bool,
 }
 
 impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
@@ -107,6 +109,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
             inside_public_path: true,
             exact_paths: Default::default(),
             modules: vec![om],
+            is_importable_from_parent: true,
         }
     }
 
@@ -319,11 +322,23 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
         renamed: Option<Symbol>,
         parent_id: Option<LocalDefId>,
     ) {
-        self.modules
-            .last_mut()
-            .unwrap()
-            .items
-            .insert((item.owner_id.def_id, renamed), (item, renamed, parent_id));
+        if self.is_importable_from_parent
+            // If we're inside an item, only impl blocks and `macro_rules!` with the `macro_export`
+            // attribute can still be visible.
+            || match item.kind {
+                hir::ItemKind::Impl(..) => true,
+                hir::ItemKind::Macro(_, MacroKind::Bang) => {
+                    self.cx.tcx.has_attr(item.owner_id.def_id, sym::macro_export)
+                }
+                _ => false,
+            }
+        {
+            self.modules
+                .last_mut()
+                .unwrap()
+                .items
+                .insert((item.owner_id.def_id, renamed), (item, renamed, parent_id));
+        }
     }
 
     fn visit_item_inner(
@@ -331,7 +346,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
         item: &'tcx hir::Item<'_>,
         renamed: Option<Symbol>,
         import_id: Option<LocalDefId>,
-    ) -> bool {
+    ) {
         debug!("visiting item {:?}", item);
         let name = renamed.unwrap_or(item.ident.name);
         let tcx = self.cx.tcx;
@@ -448,7 +463,6 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
                 }
             }
         }
-        true
     }
 
     fn visit_foreign_item_inner(
@@ -485,9 +499,23 @@ impl<'a, 'tcx> Visitor<'tcx> for RustdocVisitor<'a, 'tcx> {
     }
 
     fn visit_item(&mut self, i: &'tcx hir::Item<'tcx>) {
-        if self.visit_item_inner(i, None, None) {
-            walk_item(self, i);
-        }
+        self.visit_item_inner(i, None, None);
+        let new_value = if self.is_importable_from_parent {
+            matches!(
+                i.kind,
+                hir::ItemKind::Mod(..)
+                    | hir::ItemKind::ForeignMod { .. }
+                    | hir::ItemKind::Impl(..)
+                    | hir::ItemKind::Trait(..)
+            )
+        } else {
+            // Whatever the context, if it's an impl block, the items inside it can be used so they
+            // should be visible.
+            matches!(i.kind, hir::ItemKind::Impl(..))
+        };
+        let prev = mem::replace(&mut self.is_importable_from_parent, new_value);
+        walk_item(self, i);
+        self.is_importable_from_parent = prev;
     }
 
     fn visit_mod(&mut self, _: &hir::Mod<'tcx>, _: Span, _: hir::HirId) {
diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs
index d2f494942cf..7166d99d792 100644
--- a/src/tools/compiletest/src/common.rs
+++ b/src/tools/compiletest/src/common.rs
@@ -303,6 +303,9 @@ pub struct Config {
     /// The current Rust channel
     pub channel: String,
 
+    /// Whether adding git commit information such as the commit hash has been enabled for building
+    pub git_hash: bool,
+
     /// The default Rust edition
     pub edition: Option<String>,
 
@@ -419,7 +422,9 @@ pub struct TargetCfgs {
 
 impl TargetCfgs {
     fn new(config: &Config) -> TargetCfgs {
-        let targets: HashMap<String, TargetCfg> = if config.stage_id.starts_with("stage0-") {
+        let targets: HashMap<String, TargetCfg> = if config.stage_id.starts_with("stage0-")
+            || (config.suite == "ui-fulldeps" && config.stage_id.starts_with("stage1-"))
+        {
             // #[cfg(bootstrap)]
             // Needed only for one cycle, remove during the bootstrap bump.
             Self::collect_all_slow(config)
diff --git a/src/tools/compiletest/src/header/needs.rs b/src/tools/compiletest/src/header/needs.rs
index 35d6179abaa..81179480ed8 100644
--- a/src/tools/compiletest/src/header/needs.rs
+++ b/src/tools/compiletest/src/header/needs.rs
@@ -115,6 +115,11 @@ pub(super) fn handle_needs(
             condition: cache.x86_64_dlltool,
             ignore_reason: "ignored when dlltool for x86_64 is not present",
         },
+        Need {
+            name: "needs-git-hash",
+            condition: config.git_hash,
+            ignore_reason: "ignored when git hashes have been omitted for building",
+        },
     ];
 
     let (name, comment) = match ln.split_once([':', ' ']) {
diff --git a/src/tools/compiletest/src/header/tests.rs b/src/tools/compiletest/src/header/tests.rs
index 9af7bd5e201..362fba11697 100644
--- a/src/tools/compiletest/src/header/tests.rs
+++ b/src/tools/compiletest/src/header/tests.rs
@@ -252,6 +252,16 @@ fn debugger() {
 }
 
 #[test]
+fn git_hash() {
+    let mut config = config();
+    config.git_hash = false;
+    assert!(check_ignore(&config, "// needs-git-hash"));
+
+    config.git_hash = true;
+    assert!(!check_ignore(&config, "// needs-git-hash"));
+}
+
+#[test]
 fn sanitizers() {
     let mut config = config();
 
diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs
index 4a2b9de8aee..c4bef998f31 100644
--- a/src/tools/compiletest/src/main.rs
+++ b/src/tools/compiletest/src/main.rs
@@ -159,6 +159,7 @@ pub fn parse_config(args: Vec<String>) -> Config {
         .optflag("", "nocapture", "")
         .optflag("h", "help", "show this message")
         .reqopt("", "channel", "current Rust channel", "CHANNEL")
+        .optflag("", "git-hash", "run tests which rely on commit version being compiled into the binaries")
         .optopt("", "edition", "default Rust edition", "EDITION");
 
     let (argv0, args_) = args.split_first().unwrap();
@@ -302,6 +303,7 @@ pub fn parse_config(args: Vec<String>) -> Config {
         rustfix_coverage: matches.opt_present("rustfix-coverage"),
         has_tidy,
         channel: matches.opt_str("channel").unwrap(),
+        git_hash: matches.opt_present("git-hash"),
         edition: matches.opt_str("edition"),
 
         cc: matches.opt_str("cc").unwrap(),
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index 0fa5c54ae8e..1a4e9b58383 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -1900,6 +1900,9 @@ impl<'test> TestCx<'test> {
         // Use a single thread for efficiency and a deterministic error message order
         rustc.arg("-Zthreads=1");
 
+        // In stage 0, make sure we use `stage0-sysroot` instead of the bootstrap sysroot.
+        rustc.arg("--sysroot").arg(&self.config.sysroot_base);
+
         // Optionally prevent default --target if specified in test compile-flags.
         let custom_target = self.props.compile_flags.iter().any(|x| x.starts_with("--target"));
 
diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs
index 29664c854c8..b1385edf13e 100644
--- a/src/tools/tidy/src/ui_tests.rs
+++ b/src/tools/tidy/src/ui_tests.rs
@@ -9,7 +9,7 @@ use std::path::{Path, PathBuf};
 
 // FIXME: The following limits should be reduced eventually.
 const ENTRY_LIMIT: usize = 885;
-const ROOT_ENTRY_LIMIT: usize = 891;
+const ROOT_ENTRY_LIMIT: usize = 894;
 const ISSUES_ENTRY_LIMIT: usize = 1977;
 
 fn check_entries(tests_path: &Path, bad: &mut bool) {
diff --git a/tests/codegen/align-fn.rs b/tests/codegen/align-fn.rs
index c5886cf2808..f3cf614e185 100644
--- a/tests/codegen/align-fn.rs
+++ b/tests/codegen/align-fn.rs
@@ -7,3 +7,43 @@
 #[no_mangle]
 #[repr(align(16))]
 pub fn fn_align() {}
+
+pub struct A;
+
+impl A {
+    // CHECK: align 16
+    #[no_mangle]
+    #[repr(align(16))]
+    pub fn method_align(self) {}
+
+    // CHECK: align 16
+    #[no_mangle]
+    #[repr(align(16))]
+    pub fn associated_fn() {}
+}
+
+trait T: Sized {
+    fn trait_fn() {}
+
+    // CHECK: align 32
+    #[repr(align(32))]
+    fn trait_method(self) {}
+}
+
+impl T for A {
+    // CHECK: align 16
+    #[no_mangle]
+    #[repr(align(16))]
+    fn trait_fn() {}
+
+    // CHECK: align 16
+    #[no_mangle]
+    #[repr(align(16))]
+    fn trait_method(self) {}
+}
+
+impl T for () {}
+
+pub fn foo() {
+    ().trait_method();
+}
diff --git a/tests/codegen/optimize-attr-1.rs b/tests/codegen/optimize-attr-1.rs
index 1d1f0a38657..d95ba853030 100644
--- a/tests/codegen/optimize-attr-1.rs
+++ b/tests/codegen/optimize-attr-1.rs
@@ -9,7 +9,7 @@
 // CHECK-LABEL: define{{.*}}i32 @nothing
 // CHECK-SAME: [[NOTHING_ATTRS:#[0-9]+]]
 // SIZE-OPT: ret i32 4
-// SPEEC-OPT: ret i32 4
+// SPEED-OPT: ret i32 4
 #[no_mangle]
 pub fn nothing() -> i32 {
     2 + 2
diff --git a/tests/codegen/option-as-slice.rs b/tests/codegen/option-as-slice.rs
index d735d558374..1edd9ba9f7d 100644
--- a/tests/codegen/option-as-slice.rs
+++ b/tests/codegen/option-as-slice.rs
@@ -1,5 +1,7 @@
 // compile-flags: -O -Z randomize-layout=no
 // only-x86_64
+// ignore-llvm-version: 16.0.0
+// ^ needs https://reviews.llvm.org/D146149 in 16.0.1
 
 #![crate_type = "lib"]
 #![feature(option_as_slice)]
diff --git a/tests/codegen/thread-local.rs b/tests/codegen/thread-local.rs
index aa7fab7fb17..caf0366d2c1 100644
--- a/tests/codegen/thread-local.rs
+++ b/tests/codegen/thread-local.rs
@@ -20,8 +20,8 @@ thread_local!(static A: Cell<u32> = const { Cell::new(1) });
 // CHECK-LABEL: @get
 #[no_mangle]
 fn get() -> u32 {
-    // CHECK: %0 = load i32, {{.*}}[[TLS]]{{.*}}
-    // CHECK-NEXT: ret i32 %0
+    // CHECK: [[RET_0:%.+]] = load i32, {{.*}}[[TLS]]{{.*}}
+    // CHECK-NEXT: ret i32 [[RET_0]]
     A.with(|a| a.get())
 }
 
@@ -36,8 +36,8 @@ fn set(v: u32) {
 // CHECK-LABEL: @get_aux
 #[no_mangle]
 fn get_aux() -> u64 {
-    // CHECK: %0 = load i64, {{.*}}[[TLS_AUX]]
-    // CHECK-NEXT: ret i64 %0
+    // CHECK: [[RET_1:%.+]] = load i64, {{.*}}[[TLS_AUX]]
+    // CHECK-NEXT: ret i64 [[RET_1]]
     aux::A.with(|a| a.get())
 }
 
diff --git a/tests/debuginfo/unsized.rs b/tests/debuginfo/unsized.rs
index b1ec9b06830..3b8280bc4a9 100644
--- a/tests/debuginfo/unsized.rs
+++ b/tests/debuginfo/unsized.rs
@@ -1,4 +1,6 @@
 // compile-flags:-g
+// ignore-gdb-version: 13.1 - 99.0
+// ^ https://sourceware.org/bugzilla/show_bug.cgi?id=30330
 
 // === GDB TESTS ===================================================================================
 
diff --git a/tests/run-make/issue-107094/Makefile b/tests/run-make/issue-107094/Makefile
new file mode 100644
index 00000000000..d614e3e1055
--- /dev/null
+++ b/tests/run-make/issue-107094/Makefile
@@ -0,0 +1,7 @@
+# needs-git-hash
+
+include ../tools.mk
+
+all:
+	$(BARE_RUSTC) --version --verbose | $(CGREP) -i -e "commit-hash: [0-9a-f]{40}" "commit-date: [0-9]{4}-[0-9]{2}-[0-9]{2}"
+	$(BARE_RUSTDOC) --version --verbose | $(CGREP) -i -e "commit-hash: [0-9a-f]{40}" "commit-date: [0-9]{4}-[0-9]{2}-[0-9]{2}"
diff --git a/tests/rustdoc-ui/error-in-impl-trait/infinite-recursive-type-2.rs b/tests/rustdoc-ui/error-in-impl-trait/infinite-recursive-type-2.rs
new file mode 100644
index 00000000000..e49fe079813
--- /dev/null
+++ b/tests/rustdoc-ui/error-in-impl-trait/infinite-recursive-type-2.rs
@@ -0,0 +1,9 @@
+// check-pass
+
+pub fn f() -> impl Sized {
+    pub enum E {
+        V(E),
+    }
+
+    unimplemented!()
+}
diff --git a/tests/rustdoc-ui/infinite-recursive-type-impl-trait-return.rs b/tests/rustdoc-ui/error-in-impl-trait/infinite-recursive-type-impl-trait-return.rs
index 939da186fbc..939da186fbc 100644
--- a/tests/rustdoc-ui/infinite-recursive-type-impl-trait-return.rs
+++ b/tests/rustdoc-ui/error-in-impl-trait/infinite-recursive-type-impl-trait-return.rs
diff --git a/tests/rustdoc-ui/infinite-recursive-type-impl-trait-return.stderr b/tests/rustdoc-ui/error-in-impl-trait/infinite-recursive-type-impl-trait-return.stderr
index aff7402bc91..aff7402bc91 100644
--- a/tests/rustdoc-ui/infinite-recursive-type-impl-trait-return.stderr
+++ b/tests/rustdoc-ui/error-in-impl-trait/infinite-recursive-type-impl-trait-return.stderr
diff --git a/tests/rustdoc-ui/infinite-recursive-type-impl-trait.rs b/tests/rustdoc-ui/error-in-impl-trait/infinite-recursive-type.rs
index ac517257498..096130d7768 100644
--- a/tests/rustdoc-ui/infinite-recursive-type-impl-trait.rs
+++ b/tests/rustdoc-ui/error-in-impl-trait/infinite-recursive-type.rs
@@ -1,6 +1,9 @@
+// check-pass
+
 fn f() -> impl Sized {
-    enum E { //~ ERROR
+    enum E {
         V(E),
     }
+
     unimplemented!()
 }
diff --git a/tests/rustdoc-ui/infinite-recursive-type-impl-trait.stderr b/tests/rustdoc-ui/infinite-recursive-type-impl-trait.stderr
deleted file mode 100644
index a61577bd14a..00000000000
--- a/tests/rustdoc-ui/infinite-recursive-type-impl-trait.stderr
+++ /dev/null
@@ -1,16 +0,0 @@
-error[E0072]: recursive type `f::E` has infinite size
-  --> $DIR/infinite-recursive-type-impl-trait.rs:2:5
-   |
-LL |     enum E {
-   |     ^^^^^^
-LL |         V(E),
-   |           - recursive without indirection
-   |
-help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle
-   |
-LL |         V(Box<E>),
-   |           ++++ +
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0072`.
diff --git a/tests/rustdoc/issue-110422-inner-private.rs b/tests/rustdoc/issue-110422-inner-private.rs
new file mode 100644
index 00000000000..ee8ed5cc6e1
--- /dev/null
+++ b/tests/rustdoc/issue-110422-inner-private.rs
@@ -0,0 +1,64 @@
+// Regression test for <https://github.com/rust-lang/rust/issues/110422>.
+// This test ensures that inner items (except for implementations and macros)
+// don't appear in documentation.
+
+// compile-flags: --document-private-items
+
+#![crate_name = "foo"]
+
+// @has 'foo/index.html'
+// Checking there is no "trait" entry.
+// @count - '//*[@id="main-content"]/*[@class="small-section-header"]' 4
+// @has - '//*[@id="main-content"]/*[@class="small-section-header"]' 'Structs'
+// @has - '//*[@id="main-content"]/*[@class="small-section-header"]' 'Constants'
+// @has - '//*[@id="main-content"]/*[@class="small-section-header"]' 'Functions'
+// @has - '//*[@id="main-content"]/*[@class="small-section-header"]' 'Macros'
+
+// @has - '//a[@href="fn.foo.html"]' 'foo'
+fn foo() {
+    fn bar() {}
+
+    // @has - '//a[@class="macro"]' 'visible_macro'
+    // @!has - '//a[@class="macro"]' 'non_visible_macro'
+    // @has 'foo/macro.visible_macro.html'
+    // @!has 'foo/macro.non_visible_macro.html'
+    #[macro_export]
+    macro_rules! visible_macro {
+        () => {}
+    }
+
+    macro_rules! non_visible_macro {
+        () => {}
+    }
+}
+
+// @has 'foo/index.html'
+// @has - '//a[@href="struct.Bar.html"]' 'Bar'
+struct Bar;
+
+const BAR: i32 = {
+    // @!has - '//a[@href="fn.yo.html"]' 'yo'
+    // @!has 'foo/fn.yo.html'
+    fn yo() {}
+
+    // @!has 'foo/index.html' '//a[@href="trait.Foo.html"]' 'Foo'
+    // @!has 'foo/trait.Foo.html'
+    trait Foo {
+        fn babar() {}
+    }
+    impl Foo for Bar {}
+
+    // @has 'foo/struct.Bar.html'
+    // @has - '//*[@id="method.foo"]/*[@class="code-header"]' 'pub(crate) fn foo()'
+    // @count - '//*[@id="main-content"]/*[@class="small-section-header"]' 3
+    // We now check that the `Foo` trait is not documented nor visible on `Bar` page.
+    // @has - '//*[@id="main-content"]/*[@class="small-section-header"]' 'Implementations'
+    // @has - '//*[@id="main-content"]/*[@class="small-section-header"]' 'Auto Trait Implementations'
+    // @has - '//*[@id="main-content"]/*[@class="small-section-header"]' 'Blanket Implementations'
+    // @!has - '//*[@href="trait.Foo.html#method.babar"]/*[@class="code-header"]' 'fn babar()'
+    impl Bar {
+        fn foo() {}
+    }
+
+    1
+};
diff --git a/tests/ui-fulldeps/compiler-calls.rs b/tests/ui-fulldeps/compiler-calls.rs
index a9520b59277..b6d3b7b040d 100644
--- a/tests/ui-fulldeps/compiler-calls.rs
+++ b/tests/ui-fulldeps/compiler-calls.rs
@@ -2,7 +2,6 @@
 // Test that the Callbacks interface to the compiler works.
 
 // ignore-cross-compile
-// ignore-stage1
 // ignore-remote
 
 #![feature(rustc_private)]
diff --git a/tests/ui-fulldeps/hash-stable-is-unstable.rs b/tests/ui-fulldeps/hash-stable-is-unstable.rs
index 11fe688f391..37d7472ec60 100644
--- a/tests/ui-fulldeps/hash-stable-is-unstable.rs
+++ b/tests/ui-fulldeps/hash-stable-is-unstable.rs
@@ -1,4 +1,3 @@
-// ignore-stage1
 // compile-flags: -Zdeduplicate-diagnostics=yes
 extern crate rustc_data_structures;
 //~^ use of unstable library feature 'rustc_private'
diff --git a/tests/ui-fulldeps/hash-stable-is-unstable.stderr b/tests/ui-fulldeps/hash-stable-is-unstable.stderr
index d25657691ed..1a8994d722e 100644
--- a/tests/ui-fulldeps/hash-stable-is-unstable.stderr
+++ b/tests/ui-fulldeps/hash-stable-is-unstable.stderr
@@ -1,5 +1,5 @@
 error[E0658]: use of unstable library feature 'rustc_private': this crate is being loaded from the sysroot, an unstable location; did you mean to load this crate from crates.io via `Cargo.toml` instead?
-  --> $DIR/hash-stable-is-unstable.rs:3:1
+  --> $DIR/hash-stable-is-unstable.rs:2:1
    |
 LL | extern crate rustc_data_structures;
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -8,7 +8,7 @@ LL | extern crate rustc_data_structures;
    = help: add `#![feature(rustc_private)]` to the crate attributes to enable
 
 error[E0658]: use of unstable library feature 'rustc_private': this crate is being loaded from the sysroot, an unstable location; did you mean to load this crate from crates.io via `Cargo.toml` instead?
-  --> $DIR/hash-stable-is-unstable.rs:5:1
+  --> $DIR/hash-stable-is-unstable.rs:4:1
    |
 LL | extern crate rustc_macros;
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -17,7 +17,7 @@ LL | extern crate rustc_macros;
    = help: add `#![feature(rustc_private)]` to the crate attributes to enable
 
 error[E0658]: use of unstable library feature 'rustc_private': this crate is being loaded from the sysroot, an unstable location; did you mean to load this crate from crates.io via `Cargo.toml` instead?
-  --> $DIR/hash-stable-is-unstable.rs:7:1
+  --> $DIR/hash-stable-is-unstable.rs:6:1
    |
 LL | extern crate rustc_query_system;
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -26,7 +26,7 @@ LL | extern crate rustc_query_system;
    = help: add `#![feature(rustc_private)]` to the crate attributes to enable
 
 error[E0658]: use of unstable library feature 'rustc_private': this crate is being loaded from the sysroot, an unstable location; did you mean to load this crate from crates.io via `Cargo.toml` instead?
-  --> $DIR/hash-stable-is-unstable.rs:10:5
+  --> $DIR/hash-stable-is-unstable.rs:9:5
    |
 LL | use rustc_macros::HashStable;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -35,7 +35,7 @@ LL | use rustc_macros::HashStable;
    = help: add `#![feature(rustc_private)]` to the crate attributes to enable
 
 error[E0658]: use of unstable library feature 'rustc_private': this crate is being loaded from the sysroot, an unstable location; did you mean to load this crate from crates.io via `Cargo.toml` instead?
-  --> $DIR/hash-stable-is-unstable.rs:13:10
+  --> $DIR/hash-stable-is-unstable.rs:12:10
    |
 LL | #[derive(HashStable)]
    |          ^^^^^^^^^^
diff --git a/tests/ui-fulldeps/pathless-extern-unstable.rs b/tests/ui-fulldeps/pathless-extern-unstable.rs
index 524b0c2f73a..7fba8343bc0 100644
--- a/tests/ui-fulldeps/pathless-extern-unstable.rs
+++ b/tests/ui-fulldeps/pathless-extern-unstable.rs
@@ -1,4 +1,3 @@
-// ignore-stage1
 // edition:2018
 // compile-flags:--extern rustc_middle
 
diff --git a/tests/ui-fulldeps/pathless-extern-unstable.stderr b/tests/ui-fulldeps/pathless-extern-unstable.stderr
index dcc3cddd32c..174cd3c2804 100644
--- a/tests/ui-fulldeps/pathless-extern-unstable.stderr
+++ b/tests/ui-fulldeps/pathless-extern-unstable.stderr
@@ -1,5 +1,5 @@
 error[E0658]: use of unstable library feature 'rustc_private': this crate is being loaded from the sysroot, an unstable location; did you mean to load this crate from crates.io via `Cargo.toml` instead?
-  --> $DIR/pathless-extern-unstable.rs:7:9
+  --> $DIR/pathless-extern-unstable.rs:6:9
    |
 LL | pub use rustc_middle;
    |         ^^^^^^^^^^^^
diff --git a/tests/ui-fulldeps/auxiliary/empty-plugin.rs b/tests/ui-fulldeps/plugin/auxiliary/empty-plugin.rs
index c24cdc97aa5..c24cdc97aa5 100644
--- a/tests/ui-fulldeps/auxiliary/empty-plugin.rs
+++ b/tests/ui-fulldeps/plugin/auxiliary/empty-plugin.rs
diff --git a/tests/ui-fulldeps/auxiliary/issue-40001-plugin.rs b/tests/ui-fulldeps/plugin/auxiliary/issue-40001-plugin.rs
index 3f6caecaa5a..3f6caecaa5a 100644
--- a/tests/ui-fulldeps/auxiliary/issue-40001-plugin.rs
+++ b/tests/ui-fulldeps/plugin/auxiliary/issue-40001-plugin.rs
diff --git a/tests/ui-fulldeps/auxiliary/lint-for-crate.rs b/tests/ui-fulldeps/plugin/auxiliary/lint-for-crate.rs
index 6304c07d2c7..6304c07d2c7 100644
--- a/tests/ui-fulldeps/auxiliary/lint-for-crate.rs
+++ b/tests/ui-fulldeps/plugin/auxiliary/lint-for-crate.rs
diff --git a/tests/ui-fulldeps/auxiliary/lint-group-plugin-test.rs b/tests/ui-fulldeps/plugin/auxiliary/lint-group-plugin-test.rs
index 4a41e7fbb72..4a41e7fbb72 100644
--- a/tests/ui-fulldeps/auxiliary/lint-group-plugin-test.rs
+++ b/tests/ui-fulldeps/plugin/auxiliary/lint-group-plugin-test.rs
diff --git a/tests/ui-fulldeps/auxiliary/lint-plugin-test.rs b/tests/ui-fulldeps/plugin/auxiliary/lint-plugin-test.rs
index 30956deb799..30956deb799 100644
--- a/tests/ui-fulldeps/auxiliary/lint-plugin-test.rs
+++ b/tests/ui-fulldeps/plugin/auxiliary/lint-plugin-test.rs
diff --git a/tests/ui-fulldeps/auxiliary/lint-tool-test.rs b/tests/ui-fulldeps/plugin/auxiliary/lint-tool-test.rs
index c2c024865e8..c2c024865e8 100644
--- a/tests/ui-fulldeps/auxiliary/lint-tool-test.rs
+++ b/tests/ui-fulldeps/plugin/auxiliary/lint-tool-test.rs
diff --git a/tests/ui-fulldeps/auxiliary/lto-syntax-extension-lib.rs b/tests/ui-fulldeps/plugin/auxiliary/lto-syntax-extension-lib.rs
index 954a1e554da..954a1e554da 100644
--- a/tests/ui-fulldeps/auxiliary/lto-syntax-extension-lib.rs
+++ b/tests/ui-fulldeps/plugin/auxiliary/lto-syntax-extension-lib.rs
diff --git a/tests/ui-fulldeps/auxiliary/lto-syntax-extension-plugin.rs b/tests/ui-fulldeps/plugin/auxiliary/lto-syntax-extension-plugin.rs
index 9b075c1a5b9..9b075c1a5b9 100644
--- a/tests/ui-fulldeps/auxiliary/lto-syntax-extension-plugin.rs
+++ b/tests/ui-fulldeps/plugin/auxiliary/lto-syntax-extension-plugin.rs
diff --git a/tests/ui-fulldeps/auxiliary/multiple-plugins-1.rs b/tests/ui-fulldeps/plugin/auxiliary/multiple-plugins-1.rs
index fd6e9e20f03..fd6e9e20f03 100644
--- a/tests/ui-fulldeps/auxiliary/multiple-plugins-1.rs
+++ b/tests/ui-fulldeps/plugin/auxiliary/multiple-plugins-1.rs
diff --git a/tests/ui-fulldeps/auxiliary/multiple-plugins-2.rs b/tests/ui-fulldeps/plugin/auxiliary/multiple-plugins-2.rs
index fd6e9e20f03..fd6e9e20f03 100644
--- a/tests/ui-fulldeps/auxiliary/multiple-plugins-2.rs
+++ b/tests/ui-fulldeps/plugin/auxiliary/multiple-plugins-2.rs
diff --git a/tests/ui-fulldeps/auxiliary/outlive-expansion-phase.rs b/tests/ui-fulldeps/plugin/auxiliary/outlive-expansion-phase.rs
index e83dfe80463..e83dfe80463 100644
--- a/tests/ui-fulldeps/auxiliary/outlive-expansion-phase.rs
+++ b/tests/ui-fulldeps/plugin/auxiliary/outlive-expansion-phase.rs
diff --git a/tests/ui-fulldeps/auxiliary/rlib-crate-test.rs b/tests/ui-fulldeps/plugin/auxiliary/rlib-crate-test.rs
index 3ba73538ecf..3ba73538ecf 100644
--- a/tests/ui-fulldeps/auxiliary/rlib-crate-test.rs
+++ b/tests/ui-fulldeps/plugin/auxiliary/rlib-crate-test.rs
diff --git a/tests/ui-fulldeps/feature-gate-plugin.rs b/tests/ui-fulldeps/plugin/feature-gate-plugin.rs
index 85eaf533643..85eaf533643 100644
--- a/tests/ui-fulldeps/feature-gate-plugin.rs
+++ b/tests/ui-fulldeps/plugin/feature-gate-plugin.rs
diff --git a/tests/ui-fulldeps/feature-gate-plugin.stderr b/tests/ui-fulldeps/plugin/feature-gate-plugin.stderr
index 5e40561c7f5..5e40561c7f5 100644
--- a/tests/ui-fulldeps/feature-gate-plugin.stderr
+++ b/tests/ui-fulldeps/plugin/feature-gate-plugin.stderr
diff --git a/tests/ui-fulldeps/gated-plugin.rs b/tests/ui-fulldeps/plugin/gated-plugin.rs
index 85eaf533643..85eaf533643 100644
--- a/tests/ui-fulldeps/gated-plugin.rs
+++ b/tests/ui-fulldeps/plugin/gated-plugin.rs
diff --git a/tests/ui-fulldeps/gated-plugin.stderr b/tests/ui-fulldeps/plugin/gated-plugin.stderr
index f48f1eab60b..f48f1eab60b 100644
--- a/tests/ui-fulldeps/gated-plugin.stderr
+++ b/tests/ui-fulldeps/plugin/gated-plugin.stderr
diff --git a/tests/ui-fulldeps/issue-15778-fail.rs b/tests/ui-fulldeps/plugin/issue-15778-fail.rs
index beecaadf955..beecaadf955 100644
--- a/tests/ui-fulldeps/issue-15778-fail.rs
+++ b/tests/ui-fulldeps/plugin/issue-15778-fail.rs
diff --git a/tests/ui-fulldeps/issue-15778-fail.stderr b/tests/ui-fulldeps/plugin/issue-15778-fail.stderr
index a37893e1203..a37893e1203 100644
--- a/tests/ui-fulldeps/issue-15778-fail.stderr
+++ b/tests/ui-fulldeps/plugin/issue-15778-fail.stderr
diff --git a/tests/ui-fulldeps/issue-40001.rs b/tests/ui-fulldeps/plugin/issue-40001.rs
index e14338fdbbf..e14338fdbbf 100644
--- a/tests/ui-fulldeps/issue-40001.rs
+++ b/tests/ui-fulldeps/plugin/issue-40001.rs
diff --git a/tests/ui-fulldeps/issue-40001.stderr b/tests/ui-fulldeps/plugin/issue-40001.stderr
index 73ec0692464..73ec0692464 100644
--- a/tests/ui-fulldeps/issue-40001.stderr
+++ b/tests/ui-fulldeps/plugin/issue-40001.stderr
diff --git a/tests/ui-fulldeps/lint-group-plugin-deny-cmdline.rs b/tests/ui-fulldeps/plugin/lint-group-plugin-deny-cmdline.rs
index 9f8a879608c..9f8a879608c 100644
--- a/tests/ui-fulldeps/lint-group-plugin-deny-cmdline.rs
+++ b/tests/ui-fulldeps/plugin/lint-group-plugin-deny-cmdline.rs
diff --git a/tests/ui-fulldeps/lint-group-plugin-deny-cmdline.stderr b/tests/ui-fulldeps/plugin/lint-group-plugin-deny-cmdline.stderr
index 20486d596d9..20486d596d9 100644
--- a/tests/ui-fulldeps/lint-group-plugin-deny-cmdline.stderr
+++ b/tests/ui-fulldeps/plugin/lint-group-plugin-deny-cmdline.stderr
diff --git a/tests/ui-fulldeps/lint-group-plugin.rs b/tests/ui-fulldeps/plugin/lint-group-plugin.rs
index 7b74be7a954..7b74be7a954 100644
--- a/tests/ui-fulldeps/lint-group-plugin.rs
+++ b/tests/ui-fulldeps/plugin/lint-group-plugin.rs
diff --git a/tests/ui-fulldeps/lint-group-plugin.stderr b/tests/ui-fulldeps/plugin/lint-group-plugin.stderr
index 6f429dad017..6f429dad017 100644
--- a/tests/ui-fulldeps/lint-group-plugin.stderr
+++ b/tests/ui-fulldeps/plugin/lint-group-plugin.stderr
diff --git a/tests/ui-fulldeps/lint-plugin-cmdline-allow.rs b/tests/ui-fulldeps/plugin/lint-plugin-cmdline-allow.rs
index 1cc16e2fd1c..1cc16e2fd1c 100644
--- a/tests/ui-fulldeps/lint-plugin-cmdline-allow.rs
+++ b/tests/ui-fulldeps/plugin/lint-plugin-cmdline-allow.rs
diff --git a/tests/ui-fulldeps/lint-plugin-cmdline-allow.stderr b/tests/ui-fulldeps/plugin/lint-plugin-cmdline-allow.stderr
index f06703a2784..f06703a2784 100644
--- a/tests/ui-fulldeps/lint-plugin-cmdline-allow.stderr
+++ b/tests/ui-fulldeps/plugin/lint-plugin-cmdline-allow.stderr
diff --git a/tests/ui-fulldeps/lint-plugin-cmdline-load.rs b/tests/ui-fulldeps/plugin/lint-plugin-cmdline-load.rs
index 0bd95dfbd14..0bd95dfbd14 100644
--- a/tests/ui-fulldeps/lint-plugin-cmdline-load.rs
+++ b/tests/ui-fulldeps/plugin/lint-plugin-cmdline-load.rs
diff --git a/tests/ui-fulldeps/lint-plugin-cmdline-load.stderr b/tests/ui-fulldeps/plugin/lint-plugin-cmdline-load.stderr
index 82679c9e10a..82679c9e10a 100644
--- a/tests/ui-fulldeps/lint-plugin-cmdline-load.stderr
+++ b/tests/ui-fulldeps/plugin/lint-plugin-cmdline-load.stderr
diff --git a/tests/ui-fulldeps/lint-plugin-deny-attr.rs b/tests/ui-fulldeps/plugin/lint-plugin-deny-attr.rs
index 04230a8e883..04230a8e883 100644
--- a/tests/ui-fulldeps/lint-plugin-deny-attr.rs
+++ b/tests/ui-fulldeps/plugin/lint-plugin-deny-attr.rs
diff --git a/tests/ui-fulldeps/lint-plugin-deny-attr.stderr b/tests/ui-fulldeps/plugin/lint-plugin-deny-attr.stderr
index 5e8891bf1f1..5e8891bf1f1 100644
--- a/tests/ui-fulldeps/lint-plugin-deny-attr.stderr
+++ b/tests/ui-fulldeps/plugin/lint-plugin-deny-attr.stderr
diff --git a/tests/ui-fulldeps/lint-plugin-deny-cmdline.rs b/tests/ui-fulldeps/plugin/lint-plugin-deny-cmdline.rs
index c460cfd5f94..c460cfd5f94 100644
--- a/tests/ui-fulldeps/lint-plugin-deny-cmdline.rs
+++ b/tests/ui-fulldeps/plugin/lint-plugin-deny-cmdline.rs
diff --git a/tests/ui-fulldeps/lint-plugin-deny-cmdline.stderr b/tests/ui-fulldeps/plugin/lint-plugin-deny-cmdline.stderr
index d5d6b535214..d5d6b535214 100644
--- a/tests/ui-fulldeps/lint-plugin-deny-cmdline.stderr
+++ b/tests/ui-fulldeps/plugin/lint-plugin-deny-cmdline.stderr
diff --git a/tests/ui-fulldeps/lint-plugin-forbid-attrs.rs b/tests/ui-fulldeps/plugin/lint-plugin-forbid-attrs.rs
index cf31b3ec158..cf31b3ec158 100644
--- a/tests/ui-fulldeps/lint-plugin-forbid-attrs.rs
+++ b/tests/ui-fulldeps/plugin/lint-plugin-forbid-attrs.rs
diff --git a/tests/ui-fulldeps/lint-plugin-forbid-attrs.stderr b/tests/ui-fulldeps/plugin/lint-plugin-forbid-attrs.stderr
index ae34b25cc2f..ae34b25cc2f 100644
--- a/tests/ui-fulldeps/lint-plugin-forbid-attrs.stderr
+++ b/tests/ui-fulldeps/plugin/lint-plugin-forbid-attrs.stderr
diff --git a/tests/ui-fulldeps/lint-plugin-forbid-cmdline.rs b/tests/ui-fulldeps/plugin/lint-plugin-forbid-cmdline.rs
index b9d1aa85a69..b9d1aa85a69 100644
--- a/tests/ui-fulldeps/lint-plugin-forbid-cmdline.rs
+++ b/tests/ui-fulldeps/plugin/lint-plugin-forbid-cmdline.rs
diff --git a/tests/ui-fulldeps/lint-plugin-forbid-cmdline.stderr b/tests/ui-fulldeps/plugin/lint-plugin-forbid-cmdline.stderr
index 491c4d20646..491c4d20646 100644
--- a/tests/ui-fulldeps/lint-plugin-forbid-cmdline.stderr
+++ b/tests/ui-fulldeps/plugin/lint-plugin-forbid-cmdline.stderr
diff --git a/tests/ui-fulldeps/lint-plugin.rs b/tests/ui-fulldeps/plugin/lint-plugin.rs
index 66057eea6bc..66057eea6bc 100644
--- a/tests/ui-fulldeps/lint-plugin.rs
+++ b/tests/ui-fulldeps/plugin/lint-plugin.rs
diff --git a/tests/ui-fulldeps/lint-plugin.stderr b/tests/ui-fulldeps/plugin/lint-plugin.stderr
index dd5d3d72ecf..dd5d3d72ecf 100644
--- a/tests/ui-fulldeps/lint-plugin.stderr
+++ b/tests/ui-fulldeps/plugin/lint-plugin.stderr
diff --git a/tests/ui-fulldeps/lint-tool-cmdline-allow.rs b/tests/ui-fulldeps/plugin/lint-tool-cmdline-allow.rs
index 83a8b3e1a7e..83a8b3e1a7e 100644
--- a/tests/ui-fulldeps/lint-tool-cmdline-allow.rs
+++ b/tests/ui-fulldeps/plugin/lint-tool-cmdline-allow.rs
diff --git a/tests/ui-fulldeps/lint-tool-cmdline-allow.stderr b/tests/ui-fulldeps/plugin/lint-tool-cmdline-allow.stderr
index b060e3a3e38..b060e3a3e38 100644
--- a/tests/ui-fulldeps/lint-tool-cmdline-allow.stderr
+++ b/tests/ui-fulldeps/plugin/lint-tool-cmdline-allow.stderr
diff --git a/tests/ui-fulldeps/lint-tool-test.rs b/tests/ui-fulldeps/plugin/lint-tool-test.rs
index f92bcd213b8..f92bcd213b8 100644
--- a/tests/ui-fulldeps/lint-tool-test.rs
+++ b/tests/ui-fulldeps/plugin/lint-tool-test.rs
diff --git a/tests/ui-fulldeps/lint-tool-test.stderr b/tests/ui-fulldeps/plugin/lint-tool-test.stderr
index 027cf8f80cf..027cf8f80cf 100644
--- a/tests/ui-fulldeps/lint-tool-test.stderr
+++ b/tests/ui-fulldeps/plugin/lint-tool-test.stderr
diff --git a/tests/ui-fulldeps/lto-syntax-extension.rs b/tests/ui-fulldeps/plugin/lto-syntax-extension.rs
index 5964e70f195..5964e70f195 100644
--- a/tests/ui-fulldeps/lto-syntax-extension.rs
+++ b/tests/ui-fulldeps/plugin/lto-syntax-extension.rs
diff --git a/tests/ui-fulldeps/lto-syntax-extension.stderr b/tests/ui-fulldeps/plugin/lto-syntax-extension.stderr
index 555493f3230..555493f3230 100644
--- a/tests/ui-fulldeps/lto-syntax-extension.stderr
+++ b/tests/ui-fulldeps/plugin/lto-syntax-extension.stderr
diff --git a/tests/ui-fulldeps/macro-crate-rlib.rs b/tests/ui-fulldeps/plugin/macro-crate-rlib.rs
index 1fd514c6173..38bd340539b 100644
--- a/tests/ui-fulldeps/macro-crate-rlib.rs
+++ b/tests/ui-fulldeps/plugin/macro-crate-rlib.rs
@@ -1,4 +1,5 @@
 // aux-build:rlib-crate-test.rs
+// ignore-stage1
 // ignore-cross-compile gives a different error message
 
 #![feature(plugin)]
diff --git a/tests/ui-fulldeps/macro-crate-rlib.stderr b/tests/ui-fulldeps/plugin/macro-crate-rlib.stderr
index 9c2b992b765..0651cee56f7 100644
--- a/tests/ui-fulldeps/macro-crate-rlib.stderr
+++ b/tests/ui-fulldeps/plugin/macro-crate-rlib.stderr
@@ -1,5 +1,5 @@
 error[E0457]: plugin `rlib_crate_test` only found in rlib format, but must be available in dylib format
-  --> $DIR/macro-crate-rlib.rs:5:11
+  --> $DIR/macro-crate-rlib.rs:6:11
    |
 LL | #![plugin(rlib_crate_test)]
    |           ^^^^^^^^^^^^^^^
diff --git a/tests/ui-fulldeps/multiple-plugins.rs b/tests/ui-fulldeps/plugin/multiple-plugins.rs
index 9af3ebd570c..9af3ebd570c 100644
--- a/tests/ui-fulldeps/multiple-plugins.rs
+++ b/tests/ui-fulldeps/plugin/multiple-plugins.rs
diff --git a/tests/ui-fulldeps/multiple-plugins.stderr b/tests/ui-fulldeps/plugin/multiple-plugins.stderr
index 878ffabfc7f..878ffabfc7f 100644
--- a/tests/ui-fulldeps/multiple-plugins.stderr
+++ b/tests/ui-fulldeps/plugin/multiple-plugins.stderr
diff --git a/tests/ui-fulldeps/outlive-expansion-phase.rs b/tests/ui-fulldeps/plugin/outlive-expansion-phase.rs
index fb22888d98a..fb22888d98a 100644
--- a/tests/ui-fulldeps/outlive-expansion-phase.rs
+++ b/tests/ui-fulldeps/plugin/outlive-expansion-phase.rs
diff --git a/tests/ui-fulldeps/outlive-expansion-phase.stderr b/tests/ui-fulldeps/plugin/outlive-expansion-phase.stderr
index e40a08ae73b..e40a08ae73b 100644
--- a/tests/ui-fulldeps/outlive-expansion-phase.stderr
+++ b/tests/ui-fulldeps/plugin/outlive-expansion-phase.stderr
diff --git a/tests/ui-fulldeps/plugin-args.rs b/tests/ui-fulldeps/plugin/plugin-args.rs
index 488f2b775bf..488f2b775bf 100644
--- a/tests/ui-fulldeps/plugin-args.rs
+++ b/tests/ui-fulldeps/plugin/plugin-args.rs
diff --git a/tests/ui-fulldeps/plugin-args.stderr b/tests/ui-fulldeps/plugin/plugin-args.stderr
index 177f33005c8..177f33005c8 100644
--- a/tests/ui-fulldeps/plugin-args.stderr
+++ b/tests/ui-fulldeps/plugin/plugin-args.stderr
diff --git a/tests/ui-fulldeps/plugin-as-extern-crate.rs b/tests/ui-fulldeps/plugin/plugin-as-extern-crate.rs
index 4d26e08d81e..4d26e08d81e 100644
--- a/tests/ui-fulldeps/plugin-as-extern-crate.rs
+++ b/tests/ui-fulldeps/plugin/plugin-as-extern-crate.rs
diff --git a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs
index 6cc7bab3726..ef85fada506 100644
--- a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs
+++ b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs
@@ -6,6 +6,7 @@
 // The proc_macro2 crate handles spans differently when on beta/stable release rather than nightly,
 // changing the output of this test. Since Diagnostic is strictly internal to the compiler
 // the test is just ignored on stable and beta:
+// ignore-stage1
 // ignore-beta
 // ignore-stable
 
diff --git a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr
index a2f3bb5277b..3f961449566 100644
--- a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr
+++ b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr
@@ -1,11 +1,11 @@
 error: unsupported type attribute for diagnostic derive enum
-  --> $DIR/diagnostic-derive.rs:41:1
+  --> $DIR/diagnostic-derive.rs:42:1
    |
 LL | #[diag(no_crate_example, code = "E0123")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: diagnostic slug not specified
-  --> $DIR/diagnostic-derive.rs:44:5
+  --> $DIR/diagnostic-derive.rs:45:5
    |
 LL |     Foo,
    |     ^^^
@@ -13,7 +13,7 @@ LL |     Foo,
    = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]`
 
 error: diagnostic slug not specified
-  --> $DIR/diagnostic-derive.rs:46:5
+  --> $DIR/diagnostic-derive.rs:47:5
    |
 LL |     Bar,
    |     ^^^
@@ -21,19 +21,19 @@ LL |     Bar,
    = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]`
 
 error: expected parentheses: #[diag(...)]
-  --> $DIR/diagnostic-derive.rs:52:8
+  --> $DIR/diagnostic-derive.rs:53:8
    |
 LL | #[diag = "E0123"]
    |        ^
 
 error: `#[nonsense(...)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:57:1
+  --> $DIR/diagnostic-derive.rs:58:1
    |
 LL | #[nonsense(no_crate_example, code = "E0123")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: diagnostic slug not specified
-  --> $DIR/diagnostic-derive.rs:57:1
+  --> $DIR/diagnostic-derive.rs:58:1
    |
 LL | / #[nonsense(no_crate_example, code = "E0123")]
 LL | |
@@ -45,7 +45,7 @@ LL | | struct InvalidStructAttr {}
    = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]`
 
 error: diagnostic slug not specified
-  --> $DIR/diagnostic-derive.rs:64:1
+  --> $DIR/diagnostic-derive.rs:65:1
    |
 LL | / #[diag("E0123")]
 LL | |
@@ -55,13 +55,13 @@ LL | | struct InvalidLitNestedAttr {}
    = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]`
 
 error: diagnostic slug must be the first argument
-  --> $DIR/diagnostic-derive.rs:74:16
+  --> $DIR/diagnostic-derive.rs:75:16
    |
 LL | #[diag(nonsense("foo"), code = "E0123", slug = "foo")]
    |                ^
 
 error: diagnostic slug not specified
-  --> $DIR/diagnostic-derive.rs:74:1
+  --> $DIR/diagnostic-derive.rs:75:1
    |
 LL | / #[diag(nonsense("foo"), code = "E0123", slug = "foo")]
 LL | |
@@ -72,7 +72,7 @@ LL | | struct InvalidNestedStructAttr1 {}
    = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]`
 
 error: unknown argument
-  --> $DIR/diagnostic-derive.rs:80:8
+  --> $DIR/diagnostic-derive.rs:81:8
    |
 LL | #[diag(nonsense = "...", code = "E0123", slug = "foo")]
    |        ^^^^^^^^
@@ -80,7 +80,7 @@ LL | #[diag(nonsense = "...", code = "E0123", slug = "foo")]
    = note: only the `code` parameter is valid after the slug
 
 error: diagnostic slug not specified
-  --> $DIR/diagnostic-derive.rs:80:1
+  --> $DIR/diagnostic-derive.rs:81:1
    |
 LL | / #[diag(nonsense = "...", code = "E0123", slug = "foo")]
 LL | |
@@ -91,7 +91,7 @@ LL | | struct InvalidNestedStructAttr2 {}
    = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]`
 
 error: unknown argument
-  --> $DIR/diagnostic-derive.rs:86:8
+  --> $DIR/diagnostic-derive.rs:87:8
    |
 LL | #[diag(nonsense = 4, code = "E0123", slug = "foo")]
    |        ^^^^^^^^
@@ -99,7 +99,7 @@ LL | #[diag(nonsense = 4, code = "E0123", slug = "foo")]
    = note: only the `code` parameter is valid after the slug
 
 error: diagnostic slug not specified
-  --> $DIR/diagnostic-derive.rs:86:1
+  --> $DIR/diagnostic-derive.rs:87:1
    |
 LL | / #[diag(nonsense = 4, code = "E0123", slug = "foo")]
 LL | |
@@ -110,7 +110,7 @@ LL | | struct InvalidNestedStructAttr3 {}
    = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]`
 
 error: unknown argument
-  --> $DIR/diagnostic-derive.rs:92:42
+  --> $DIR/diagnostic-derive.rs:93:42
    |
 LL | #[diag(no_crate_example, code = "E0123", slug = "foo")]
    |                                          ^^^^
@@ -118,55 +118,55 @@ LL | #[diag(no_crate_example, code = "E0123", slug = "foo")]
    = note: only the `code` parameter is valid after the slug
 
 error: `#[suggestion = ...]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:99:5
+  --> $DIR/diagnostic-derive.rs:100:5
    |
 LL |     #[suggestion = "bar"]
    |     ^^^^^^^^^^^^^^^^^^^^^
 
 error: specified multiple times
-  --> $DIR/diagnostic-derive.rs:106:8
+  --> $DIR/diagnostic-derive.rs:107:8
    |
 LL | #[diag(no_crate_example, code = "E0456")]
    |        ^^^^^^^^^^^^^^^^
    |
 note: previously specified here
-  --> $DIR/diagnostic-derive.rs:105:8
+  --> $DIR/diagnostic-derive.rs:106:8
    |
 LL | #[diag(no_crate_example, code = "E0123")]
    |        ^^^^^^^^^^^^^^^^
 
 error: specified multiple times
-  --> $DIR/diagnostic-derive.rs:106:26
+  --> $DIR/diagnostic-derive.rs:107:26
    |
 LL | #[diag(no_crate_example, code = "E0456")]
    |                          ^^^^
    |
 note: previously specified here
-  --> $DIR/diagnostic-derive.rs:105:26
+  --> $DIR/diagnostic-derive.rs:106:26
    |
 LL | #[diag(no_crate_example, code = "E0123")]
    |                          ^^^^
 
 error: specified multiple times
-  --> $DIR/diagnostic-derive.rs:112:42
+  --> $DIR/diagnostic-derive.rs:113:42
    |
 LL | #[diag(no_crate_example, code = "E0456", code = "E0457")]
    |                                          ^^^^
    |
 note: previously specified here
-  --> $DIR/diagnostic-derive.rs:112:26
+  --> $DIR/diagnostic-derive.rs:113:26
    |
 LL | #[diag(no_crate_example, code = "E0456", code = "E0457")]
    |                          ^^^^
 
 error: diagnostic slug must be the first argument
-  --> $DIR/diagnostic-derive.rs:117:43
+  --> $DIR/diagnostic-derive.rs:118:43
    |
 LL | #[diag(no_crate_example, no_crate::example, code = "E0456")]
    |                                           ^
 
 error: diagnostic slug not specified
-  --> $DIR/diagnostic-derive.rs:122:1
+  --> $DIR/diagnostic-derive.rs:123:1
    |
 LL | struct KindNotProvided {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -174,7 +174,7 @@ LL | struct KindNotProvided {}
    = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]`
 
 error: diagnostic slug not specified
-  --> $DIR/diagnostic-derive.rs:125:1
+  --> $DIR/diagnostic-derive.rs:126:1
    |
 LL | / #[diag(code = "E0456")]
 LL | |
@@ -184,31 +184,31 @@ LL | | struct SlugNotProvided {}
    = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]`
 
 error: the `#[primary_span]` attribute can only be applied to fields of type `Span` or `MultiSpan`
-  --> $DIR/diagnostic-derive.rs:136:5
+  --> $DIR/diagnostic-derive.rs:137:5
    |
 LL |     #[primary_span]
    |     ^^^^^^^^^^^^^^^
 
 error: `#[nonsense]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:144:5
+  --> $DIR/diagnostic-derive.rs:145:5
    |
 LL |     #[nonsense]
    |     ^^^^^^^^^^^
 
 error: the `#[label(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan`
-  --> $DIR/diagnostic-derive.rs:161:5
+  --> $DIR/diagnostic-derive.rs:162:5
    |
 LL |     #[label(no_crate_label)]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: `name` doesn't refer to a field on this type
-  --> $DIR/diagnostic-derive.rs:169:46
+  --> $DIR/diagnostic-derive.rs:170:46
    |
 LL |     #[suggestion(no_crate_suggestion, code = "{name}")]
    |                                              ^^^^^^^^
 
 error: invalid format string: expected `'}'` but string was terminated
-  --> $DIR/diagnostic-derive.rs:174:10
+  --> $DIR/diagnostic-derive.rs:175:10
    |
 LL | #[derive(Diagnostic)]
    |          ^^^^^^^^^^ expected `'}'` in format string
@@ -217,7 +217,7 @@ LL | #[derive(Diagnostic)]
    = note: this error originates in the derive macro `Diagnostic` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: invalid format string: unmatched `}` found
-  --> $DIR/diagnostic-derive.rs:184:10
+  --> $DIR/diagnostic-derive.rs:185:10
    |
 LL | #[derive(Diagnostic)]
    |          ^^^^^^^^^^ unmatched `}` in format string
@@ -226,19 +226,19 @@ LL | #[derive(Diagnostic)]
    = note: this error originates in the derive macro `Diagnostic` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: the `#[label(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan`
-  --> $DIR/diagnostic-derive.rs:204:5
+  --> $DIR/diagnostic-derive.rs:205:5
    |
 LL |     #[label(no_crate_label)]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: suggestion without `code = "..."`
-  --> $DIR/diagnostic-derive.rs:223:5
+  --> $DIR/diagnostic-derive.rs:224:5
    |
 LL |     #[suggestion(no_crate_suggestion)]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: invalid nested attribute
-  --> $DIR/diagnostic-derive.rs:231:18
+  --> $DIR/diagnostic-derive.rs:232:18
    |
 LL |     #[suggestion(nonsense = "bar")]
    |                  ^^^^^^^^
@@ -246,13 +246,13 @@ LL |     #[suggestion(nonsense = "bar")]
    = help: only `style`, `code` and `applicability` are valid nested attributes
 
 error: suggestion without `code = "..."`
-  --> $DIR/diagnostic-derive.rs:231:5
+  --> $DIR/diagnostic-derive.rs:232:5
    |
 LL |     #[suggestion(nonsense = "bar")]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: invalid nested attribute
-  --> $DIR/diagnostic-derive.rs:240:18
+  --> $DIR/diagnostic-derive.rs:241:18
    |
 LL |     #[suggestion(msg = "bar")]
    |                  ^^^
@@ -260,13 +260,13 @@ LL |     #[suggestion(msg = "bar")]
    = help: only `style`, `code` and `applicability` are valid nested attributes
 
 error: suggestion without `code = "..."`
-  --> $DIR/diagnostic-derive.rs:240:5
+  --> $DIR/diagnostic-derive.rs:241:5
    |
 LL |     #[suggestion(msg = "bar")]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: wrong field type for suggestion
-  --> $DIR/diagnostic-derive.rs:263:5
+  --> $DIR/diagnostic-derive.rs:264:5
    |
 LL | /     #[suggestion(no_crate_suggestion, code = "This is suggested code")]
 LL | |
@@ -276,79 +276,79 @@ LL | |     suggestion: Applicability,
    = help: `#[suggestion(...)]` should be applied to fields of type `Span` or `(Span, Applicability)`
 
 error: specified multiple times
-  --> $DIR/diagnostic-derive.rs:279:24
+  --> $DIR/diagnostic-derive.rs:280:24
    |
 LL |     suggestion: (Span, Span, Applicability),
    |                        ^^^^
    |
 note: previously specified here
-  --> $DIR/diagnostic-derive.rs:279:18
+  --> $DIR/diagnostic-derive.rs:280:18
    |
 LL |     suggestion: (Span, Span, Applicability),
    |                  ^^^^
 
 error: specified multiple times
-  --> $DIR/diagnostic-derive.rs:287:33
+  --> $DIR/diagnostic-derive.rs:288:33
    |
 LL |     suggestion: (Applicability, Applicability, Span),
    |                                 ^^^^^^^^^^^^^
    |
 note: previously specified here
-  --> $DIR/diagnostic-derive.rs:287:18
+  --> $DIR/diagnostic-derive.rs:288:18
    |
 LL |     suggestion: (Applicability, Applicability, Span),
    |                  ^^^^^^^^^^^^^
 
 error: `#[label = ...]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:294:5
+  --> $DIR/diagnostic-derive.rs:295:5
    |
 LL |     #[label = "bar"]
    |     ^^^^^^^^^^^^^^^^
 
 error: specified multiple times
-  --> $DIR/diagnostic-derive.rs:445:5
+  --> $DIR/diagnostic-derive.rs:446:5
    |
 LL |     #[suggestion(no_crate_suggestion, code = "...", applicability = "maybe-incorrect")]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: previously specified here
-  --> $DIR/diagnostic-derive.rs:447:24
+  --> $DIR/diagnostic-derive.rs:448:24
    |
 LL |     suggestion: (Span, Applicability),
    |                        ^^^^^^^^^^^^^
 
 error: invalid applicability
-  --> $DIR/diagnostic-derive.rs:453:69
+  --> $DIR/diagnostic-derive.rs:454:69
    |
 LL |     #[suggestion(no_crate_suggestion, code = "...", applicability = "batman")]
    |                                                                     ^^^^^^^^
 
 error: the `#[help(...)]` attribute can only be applied to fields of type `Span`, `MultiSpan`, `bool` or `()`
-  --> $DIR/diagnostic-derive.rs:520:5
+  --> $DIR/diagnostic-derive.rs:521:5
    |
 LL |     #[help(no_crate_help)]
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 error: a diagnostic slug must be the first argument to the attribute
-  --> $DIR/diagnostic-derive.rs:529:32
+  --> $DIR/diagnostic-derive.rs:530:32
    |
 LL |     #[label(no_crate_label, foo)]
    |                                ^
 
 error: invalid nested attribute
-  --> $DIR/diagnostic-derive.rs:537:29
+  --> $DIR/diagnostic-derive.rs:538:29
    |
 LL |     #[label(no_crate_label, foo = "...")]
    |                             ^^^
 
 error: invalid nested attribute
-  --> $DIR/diagnostic-derive.rs:545:29
+  --> $DIR/diagnostic-derive.rs:546:29
    |
 LL |     #[label(no_crate_label, foo("..."))]
    |                             ^^^
 
 error: `#[primary_span]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:557:5
+  --> $DIR/diagnostic-derive.rs:558:5
    |
 LL |     #[primary_span]
    |     ^^^^^^^^^^^^^^^
@@ -356,13 +356,13 @@ LL |     #[primary_span]
    = help: the `primary_span` field attribute is not valid for lint diagnostics
 
 error: `#[error(...)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:577:1
+  --> $DIR/diagnostic-derive.rs:578:1
    |
 LL | #[error(no_crate_example, code = "E0123")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: diagnostic slug not specified
-  --> $DIR/diagnostic-derive.rs:577:1
+  --> $DIR/diagnostic-derive.rs:578:1
    |
 LL | / #[error(no_crate_example, code = "E0123")]
 LL | |
@@ -374,13 +374,13 @@ LL | | struct ErrorAttribute {}
    = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]`
 
 error: `#[warn_(...)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:584:1
+  --> $DIR/diagnostic-derive.rs:585:1
    |
 LL | #[warn_(no_crate_example, code = "E0123")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: diagnostic slug not specified
-  --> $DIR/diagnostic-derive.rs:584:1
+  --> $DIR/diagnostic-derive.rs:585:1
    |
 LL | / #[warn_(no_crate_example, code = "E0123")]
 LL | |
@@ -392,13 +392,13 @@ LL | | struct WarnAttribute {}
    = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]`
 
 error: `#[lint(...)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:591:1
+  --> $DIR/diagnostic-derive.rs:592:1
    |
 LL | #[lint(no_crate_example, code = "E0123")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: diagnostic slug not specified
-  --> $DIR/diagnostic-derive.rs:591:1
+  --> $DIR/diagnostic-derive.rs:592:1
    |
 LL | / #[lint(no_crate_example, code = "E0123")]
 LL | |
@@ -410,19 +410,19 @@ LL | | struct LintAttributeOnSessionDiag {}
    = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]`
 
 error: `#[lint(...)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:598:1
+  --> $DIR/diagnostic-derive.rs:599:1
    |
 LL | #[lint(no_crate_example, code = "E0123")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: `#[lint(...)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:598:1
+  --> $DIR/diagnostic-derive.rs:599:1
    |
 LL | #[lint(no_crate_example, code = "E0123")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: diagnostic slug not specified
-  --> $DIR/diagnostic-derive.rs:598:1
+  --> $DIR/diagnostic-derive.rs:599:1
    |
 LL | / #[lint(no_crate_example, code = "E0123")]
 LL | |
@@ -435,19 +435,19 @@ LL | | struct LintAttributeOnLintDiag {}
    = help: specify the slug as the first argument to the attribute, such as `#[diag(compiletest_example)]`
 
 error: specified multiple times
-  --> $DIR/diagnostic-derive.rs:608:53
+  --> $DIR/diagnostic-derive.rs:609:53
    |
 LL |     #[suggestion(no_crate_suggestion, code = "...", code = ",,,")]
    |                                                     ^^^^
    |
 note: previously specified here
-  --> $DIR/diagnostic-derive.rs:608:39
+  --> $DIR/diagnostic-derive.rs:609:39
    |
 LL |     #[suggestion(no_crate_suggestion, code = "...", code = ",,,")]
    |                                       ^^^^
 
 error: wrong types for suggestion
-  --> $DIR/diagnostic-derive.rs:617:24
+  --> $DIR/diagnostic-derive.rs:618:24
    |
 LL |     suggestion: (Span, usize),
    |                        ^^^^^
@@ -455,7 +455,7 @@ LL |     suggestion: (Span, usize),
    = help: `#[suggestion(...)]` on a tuple field must be applied to fields of type `(Span, Applicability)`
 
 error: wrong types for suggestion
-  --> $DIR/diagnostic-derive.rs:625:17
+  --> $DIR/diagnostic-derive.rs:626:17
    |
 LL |     suggestion: (Span,),
    |                 ^^^^^^^
@@ -463,13 +463,13 @@ LL |     suggestion: (Span,),
    = help: `#[suggestion(...)]` on a tuple field must be applied to fields of type `(Span, Applicability)`
 
 error: suggestion without `code = "..."`
-  --> $DIR/diagnostic-derive.rs:632:5
+  --> $DIR/diagnostic-derive.rs:633:5
    |
 LL |     #[suggestion(no_crate_suggestion)]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: `#[multipart_suggestion(...)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:639:1
+  --> $DIR/diagnostic-derive.rs:640:1
    |
 LL | #[multipart_suggestion(no_crate_suggestion)]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -477,7 +477,7 @@ LL | #[multipart_suggestion(no_crate_suggestion)]
    = help: consider creating a `Subdiagnostic` instead
 
 error: `#[multipart_suggestion(...)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:646:5
+  --> $DIR/diagnostic-derive.rs:647:5
    |
 LL |     #[multipart_suggestion(no_crate_suggestion)]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -485,13 +485,13 @@ LL |     #[multipart_suggestion(no_crate_suggestion)]
    = help: consider creating a `Subdiagnostic` instead
 
 error: unexpected end of input, unexpected token in nested attribute, expected ident
-  --> $DIR/diagnostic-derive.rs:642:24
+  --> $DIR/diagnostic-derive.rs:643:24
    |
 LL | #[multipart_suggestion()]
    |                        ^
 
 error: `#[suggestion(...)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:654:1
+  --> $DIR/diagnostic-derive.rs:655:1
    |
 LL | #[suggestion(no_crate_suggestion, code = "...")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -499,7 +499,7 @@ LL | #[suggestion(no_crate_suggestion, code = "...")]
    = help: `#[label]` and `#[suggestion]` can only be applied to fields
 
 error: `#[label]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:663:1
+  --> $DIR/diagnostic-derive.rs:664:1
    |
 LL | #[label]
    | ^^^^^^^^
@@ -507,31 +507,31 @@ LL | #[label]
    = help: `#[label]` and `#[suggestion]` can only be applied to fields
 
 error: `eager` is the only supported nested attribute for `subdiagnostic`
-  --> $DIR/diagnostic-derive.rs:697:7
+  --> $DIR/diagnostic-derive.rs:698:7
    |
 LL |     #[subdiagnostic(bad)]
    |       ^^^^^^^^^^^^^^^^^^
 
 error: `#[subdiagnostic = ...]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:705:5
+  --> $DIR/diagnostic-derive.rs:706:5
    |
 LL |     #[subdiagnostic = "bad"]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: `eager` is the only supported nested attribute for `subdiagnostic`
-  --> $DIR/diagnostic-derive.rs:713:7
+  --> $DIR/diagnostic-derive.rs:714:7
    |
 LL |     #[subdiagnostic(bad, bad)]
    |       ^^^^^^^^^^^^^^^^^^^^^^^
 
 error: `eager` is the only supported nested attribute for `subdiagnostic`
-  --> $DIR/diagnostic-derive.rs:721:7
+  --> $DIR/diagnostic-derive.rs:722:7
    |
 LL |     #[subdiagnostic("bad")]
    |       ^^^^^^^^^^^^^^^^^^^^
 
 error: `#[subdiagnostic(...)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:729:5
+  --> $DIR/diagnostic-derive.rs:730:5
    |
 LL |     #[subdiagnostic(eager)]
    |     ^^^^^^^^^^^^^^^^^^^^^^^
@@ -539,31 +539,31 @@ LL |     #[subdiagnostic(eager)]
    = help: eager subdiagnostics are not supported on lints
 
 error: expected at least one string literal for `code(...)`
-  --> $DIR/diagnostic-derive.rs:787:23
+  --> $DIR/diagnostic-derive.rs:788:23
    |
 LL |     #[suggestion(code())]
    |                       ^
 
 error: `code(...)` must contain only string literals
-  --> $DIR/diagnostic-derive.rs:795:23
+  --> $DIR/diagnostic-derive.rs:796:23
    |
 LL |     #[suggestion(code(foo))]
    |                       ^^^
 
 error: unexpected token
-  --> $DIR/diagnostic-derive.rs:795:23
+  --> $DIR/diagnostic-derive.rs:796:23
    |
 LL |     #[suggestion(code(foo))]
    |                       ^^^
 
 error: expected string literal
-  --> $DIR/diagnostic-derive.rs:804:25
+  --> $DIR/diagnostic-derive.rs:805:25
    |
 LL |     #[suggestion(code = 3)]
    |                         ^
 
 error: `#[suggestion(...)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:819:5
+  --> $DIR/diagnostic-derive.rs:820:5
    |
 LL |     #[suggestion(no_crate_suggestion, code = "")]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -573,67 +573,67 @@ LL |     #[suggestion(no_crate_suggestion, code = "")]
    = help: to show a variable set of suggestions, use a `Vec` of `Subdiagnostic`s annotated with `#[suggestion(...)]`
 
 error: cannot find attribute `nonsense` in this scope
-  --> $DIR/diagnostic-derive.rs:57:3
+  --> $DIR/diagnostic-derive.rs:58:3
    |
 LL | #[nonsense(no_crate_example, code = "E0123")]
    |   ^^^^^^^^
 
 error: cannot find attribute `nonsense` in this scope
-  --> $DIR/diagnostic-derive.rs:144:7
+  --> $DIR/diagnostic-derive.rs:145:7
    |
 LL |     #[nonsense]
    |       ^^^^^^^^
 
 error: cannot find attribute `error` in this scope
-  --> $DIR/diagnostic-derive.rs:577:3
+  --> $DIR/diagnostic-derive.rs:578:3
    |
 LL | #[error(no_crate_example, code = "E0123")]
    |   ^^^^^
 
 error: cannot find attribute `warn_` in this scope
-  --> $DIR/diagnostic-derive.rs:584:3
+  --> $DIR/diagnostic-derive.rs:585:3
    |
 LL | #[warn_(no_crate_example, code = "E0123")]
    |   ^^^^^ help: a built-in attribute with a similar name exists: `warn`
 
 error: cannot find attribute `lint` in this scope
-  --> $DIR/diagnostic-derive.rs:591:3
+  --> $DIR/diagnostic-derive.rs:592:3
    |
 LL | #[lint(no_crate_example, code = "E0123")]
    |   ^^^^ help: a built-in attribute with a similar name exists: `link`
 
 error: cannot find attribute `lint` in this scope
-  --> $DIR/diagnostic-derive.rs:598:3
+  --> $DIR/diagnostic-derive.rs:599:3
    |
 LL | #[lint(no_crate_example, code = "E0123")]
    |   ^^^^ help: a built-in attribute with a similar name exists: `link`
 
 error: cannot find attribute `multipart_suggestion` in this scope
-  --> $DIR/diagnostic-derive.rs:639:3
+  --> $DIR/diagnostic-derive.rs:640:3
    |
 LL | #[multipart_suggestion(no_crate_suggestion)]
    |   ^^^^^^^^^^^^^^^^^^^^
 
 error: cannot find attribute `multipart_suggestion` in this scope
-  --> $DIR/diagnostic-derive.rs:642:3
+  --> $DIR/diagnostic-derive.rs:643:3
    |
 LL | #[multipart_suggestion()]
    |   ^^^^^^^^^^^^^^^^^^^^
 
 error: cannot find attribute `multipart_suggestion` in this scope
-  --> $DIR/diagnostic-derive.rs:646:7
+  --> $DIR/diagnostic-derive.rs:647:7
    |
 LL |     #[multipart_suggestion(no_crate_suggestion)]
    |       ^^^^^^^^^^^^^^^^^^^^
 
 error[E0425]: cannot find value `nonsense` in module `crate::fluent_generated`
-  --> $DIR/diagnostic-derive.rs:69:8
+  --> $DIR/diagnostic-derive.rs:70:8
    |
 LL | #[diag(nonsense, code = "E0123")]
    |        ^^^^^^^^ not found in `crate::fluent_generated`
 
 error[E0425]: cannot find value `__code_34` in this scope
-  --> $DIR/diagnostic-derive.rs:801:10
+  --> $DIR/diagnostic-derive.rs:802:10
    |
 LL | #[derive(Diagnostic)]
    |          ^^^^^^^^^^ not found in this scope
@@ -641,7 +641,7 @@ LL | #[derive(Diagnostic)]
    = note: this error originates in the derive macro `Diagnostic` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0277]: the trait bound `Hello: IntoDiagnosticArg` is not satisfied
-  --> $DIR/diagnostic-derive.rs:338:10
+  --> $DIR/diagnostic-derive.rs:339:10
    |
 LL | #[derive(Diagnostic)]
    |          ^^^^^^^^^^ the trait `IntoDiagnosticArg` is not implemented for `Hello`
diff --git a/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs b/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs
index 1d928ca93f9..73cc1cfc03a 100644
--- a/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs
+++ b/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs
@@ -4,6 +4,7 @@
 // The proc_macro2 crate handles spans differently when on beta/stable release rather than nightly,
 // changing the output of this test. Since Subdiagnostic is strictly internal to the compiler
 // the test is just ignored on stable and beta:
+// ignore-stage1
 // ignore-beta
 // ignore-stable
 
diff --git a/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr b/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr
index 4211b91f04a..529003d90ab 100644
--- a/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr
+++ b/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr
@@ -1,5 +1,5 @@
 error: label without `#[primary_span]` field
-  --> $DIR/subdiagnostic-derive.rs:49:1
+  --> $DIR/subdiagnostic-derive.rs:50:1
    |
 LL | / #[label(no_crate_example)]
 LL | |
@@ -9,133 +9,133 @@ LL | | }
    | |_^
 
 error: diagnostic slug must be first argument of a `#[label(...)]` attribute
-  --> $DIR/subdiagnostic-derive.rs:56:1
+  --> $DIR/subdiagnostic-derive.rs:57:1
    |
 LL | #[label]
    | ^^^^^^^^
 
 error: `#[foo]` is not a valid attribute
-  --> $DIR/subdiagnostic-derive.rs:65:1
+  --> $DIR/subdiagnostic-derive.rs:66:1
    |
 LL | #[foo]
    | ^^^^^^
 
 error: `#[label = ...]` is not a valid attribute
-  --> $DIR/subdiagnostic-derive.rs:75:1
+  --> $DIR/subdiagnostic-derive.rs:76:1
    |
 LL | #[label = "..."]
    | ^^^^^^^^^^^^^^^^
 
 error: invalid nested attribute
-  --> $DIR/subdiagnostic-derive.rs:84:9
+  --> $DIR/subdiagnostic-derive.rs:85:9
    |
 LL | #[label(bug = "...")]
    |         ^^^
 
 error: diagnostic slug must be first argument of a `#[label(...)]` attribute
-  --> $DIR/subdiagnostic-derive.rs:84:1
+  --> $DIR/subdiagnostic-derive.rs:85:1
    |
 LL | #[label(bug = "...")]
    | ^^^^^^^^^^^^^^^^^^^^^
 
 error: unexpected literal in nested attribute, expected ident
-  --> $DIR/subdiagnostic-derive.rs:94:9
+  --> $DIR/subdiagnostic-derive.rs:95:9
    |
 LL | #[label("...")]
    |         ^^^^^
 
 error: invalid nested attribute
-  --> $DIR/subdiagnostic-derive.rs:103:9
+  --> $DIR/subdiagnostic-derive.rs:104:9
    |
 LL | #[label(slug = 4)]
    |         ^^^^
 
 error: diagnostic slug must be first argument of a `#[label(...)]` attribute
-  --> $DIR/subdiagnostic-derive.rs:103:1
+  --> $DIR/subdiagnostic-derive.rs:104:1
    |
 LL | #[label(slug = 4)]
    | ^^^^^^^^^^^^^^^^^^
 
 error: invalid nested attribute
-  --> $DIR/subdiagnostic-derive.rs:113:9
+  --> $DIR/subdiagnostic-derive.rs:114:9
    |
 LL | #[label(slug("..."))]
    |         ^^^^
 
 error: diagnostic slug must be first argument of a `#[label(...)]` attribute
-  --> $DIR/subdiagnostic-derive.rs:113:1
+  --> $DIR/subdiagnostic-derive.rs:114:1
    |
 LL | #[label(slug("..."))]
    | ^^^^^^^^^^^^^^^^^^^^^
 
 error: unexpected end of input, unexpected token in nested attribute, expected ident
-  --> $DIR/subdiagnostic-derive.rs:133:9
+  --> $DIR/subdiagnostic-derive.rs:134:9
    |
 LL | #[label()]
    |         ^
 
 error: invalid nested attribute
-  --> $DIR/subdiagnostic-derive.rs:142:27
+  --> $DIR/subdiagnostic-derive.rs:143:27
    |
 LL | #[label(no_crate_example, code = "...")]
    |                           ^^^^
 
 error: invalid nested attribute
-  --> $DIR/subdiagnostic-derive.rs:151:27
+  --> $DIR/subdiagnostic-derive.rs:152:27
    |
 LL | #[label(no_crate_example, applicability = "machine-applicable")]
    |                           ^^^^^^^^^^^^^
 
 error: unsupported type attribute for subdiagnostic enum
-  --> $DIR/subdiagnostic-derive.rs:160:1
+  --> $DIR/subdiagnostic-derive.rs:161:1
    |
 LL | #[foo]
    | ^^^^^^
 
 error: `#[bar]` is not a valid attribute
-  --> $DIR/subdiagnostic-derive.rs:174:5
+  --> $DIR/subdiagnostic-derive.rs:175:5
    |
 LL |     #[bar]
    |     ^^^^^^
 
 error: `#[bar = ...]` is not a valid attribute
-  --> $DIR/subdiagnostic-derive.rs:186:5
+  --> $DIR/subdiagnostic-derive.rs:187:5
    |
 LL |     #[bar = "..."]
    |     ^^^^^^^^^^^^^^
 
 error: `#[bar = ...]` is not a valid attribute
-  --> $DIR/subdiagnostic-derive.rs:198:5
+  --> $DIR/subdiagnostic-derive.rs:199:5
    |
 LL |     #[bar = 4]
    |     ^^^^^^^^^^
 
 error: `#[bar(...)]` is not a valid attribute
-  --> $DIR/subdiagnostic-derive.rs:210:5
+  --> $DIR/subdiagnostic-derive.rs:211:5
    |
 LL |     #[bar("...")]
    |     ^^^^^^^^^^^^^
 
 error: invalid nested attribute
-  --> $DIR/subdiagnostic-derive.rs:222:13
+  --> $DIR/subdiagnostic-derive.rs:223:13
    |
 LL |     #[label(code = "...")]
    |             ^^^^
 
 error: diagnostic slug must be first argument of a `#[label(...)]` attribute
-  --> $DIR/subdiagnostic-derive.rs:222:5
+  --> $DIR/subdiagnostic-derive.rs:223:5
    |
 LL |     #[label(code = "...")]
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 error: the `#[primary_span]` attribute can only be applied to fields of type `Span` or `MultiSpan`
-  --> $DIR/subdiagnostic-derive.rs:251:5
+  --> $DIR/subdiagnostic-derive.rs:252:5
    |
 LL |     #[primary_span]
    |     ^^^^^^^^^^^^^^^
 
 error: label without `#[primary_span]` field
-  --> $DIR/subdiagnostic-derive.rs:248:1
+  --> $DIR/subdiagnostic-derive.rs:249:1
    |
 LL | / #[label(no_crate_example)]
 LL | |
@@ -147,13 +147,13 @@ LL | | }
    | |_^
 
 error: `#[applicability]` is only valid on suggestions
-  --> $DIR/subdiagnostic-derive.rs:261:5
+  --> $DIR/subdiagnostic-derive.rs:262:5
    |
 LL |     #[applicability]
    |     ^^^^^^^^^^^^^^^^
 
 error: `#[bar]` is not a valid attribute
-  --> $DIR/subdiagnostic-derive.rs:271:5
+  --> $DIR/subdiagnostic-derive.rs:272:5
    |
 LL |     #[bar]
    |     ^^^^^^
@@ -161,13 +161,13 @@ LL |     #[bar]
    = help: only `primary_span`, `applicability` and `skip_arg` are valid field attributes
 
 error: `#[bar = ...]` is not a valid attribute
-  --> $DIR/subdiagnostic-derive.rs:282:5
+  --> $DIR/subdiagnostic-derive.rs:283:5
    |
 LL |     #[bar = "..."]
    |     ^^^^^^^^^^^^^^
 
 error: `#[bar(...)]` is not a valid attribute
-  --> $DIR/subdiagnostic-derive.rs:293:5
+  --> $DIR/subdiagnostic-derive.rs:294:5
    |
 LL |     #[bar("...")]
    |     ^^^^^^^^^^^^^
@@ -175,7 +175,7 @@ LL |     #[bar("...")]
    = help: only `primary_span`, `applicability` and `skip_arg` are valid field attributes
 
 error: unexpected unsupported untagged union
-  --> $DIR/subdiagnostic-derive.rs:309:1
+  --> $DIR/subdiagnostic-derive.rs:310:1
    |
 LL | / union AC {
 LL | |
@@ -185,73 +185,73 @@ LL | | }
    | |_^
 
 error: a diagnostic slug must be the first argument to the attribute
-  --> $DIR/subdiagnostic-derive.rs:324:44
+  --> $DIR/subdiagnostic-derive.rs:325:44
    |
 LL | #[label(no_crate_example, no_crate::example)]
    |                                            ^
 
 error: specified multiple times
-  --> $DIR/subdiagnostic-derive.rs:337:5
+  --> $DIR/subdiagnostic-derive.rs:338:5
    |
 LL |     #[primary_span]
    |     ^^^^^^^^^^^^^^^
    |
 note: previously specified here
-  --> $DIR/subdiagnostic-derive.rs:334:5
+  --> $DIR/subdiagnostic-derive.rs:335:5
    |
 LL |     #[primary_span]
    |     ^^^^^^^^^^^^^^^
 
 error: subdiagnostic kind not specified
-  --> $DIR/subdiagnostic-derive.rs:343:8
+  --> $DIR/subdiagnostic-derive.rs:344:8
    |
 LL | struct AG {
    |        ^^
 
 error: specified multiple times
-  --> $DIR/subdiagnostic-derive.rs:380:46
+  --> $DIR/subdiagnostic-derive.rs:381:46
    |
 LL | #[suggestion(no_crate_example, code = "...", code = "...")]
    |                                              ^^^^
    |
 note: previously specified here
-  --> $DIR/subdiagnostic-derive.rs:380:32
+  --> $DIR/subdiagnostic-derive.rs:381:32
    |
 LL | #[suggestion(no_crate_example, code = "...", code = "...")]
    |                                ^^^^
 
 error: specified multiple times
-  --> $DIR/subdiagnostic-derive.rs:398:5
+  --> $DIR/subdiagnostic-derive.rs:399:5
    |
 LL |     #[applicability]
    |     ^^^^^^^^^^^^^^^^
    |
 note: previously specified here
-  --> $DIR/subdiagnostic-derive.rs:395:5
+  --> $DIR/subdiagnostic-derive.rs:396:5
    |
 LL |     #[applicability]
    |     ^^^^^^^^^^^^^^^^
 
 error: the `#[applicability]` attribute can only be applied to fields of type `Applicability`
-  --> $DIR/subdiagnostic-derive.rs:408:5
+  --> $DIR/subdiagnostic-derive.rs:409:5
    |
 LL |     #[applicability]
    |     ^^^^^^^^^^^^^^^^
 
 error: suggestion without `code = "..."`
-  --> $DIR/subdiagnostic-derive.rs:421:1
+  --> $DIR/subdiagnostic-derive.rs:422:1
    |
 LL | #[suggestion(no_crate_example)]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: invalid applicability
-  --> $DIR/subdiagnostic-derive.rs:431:62
+  --> $DIR/subdiagnostic-derive.rs:432:62
    |
 LL | #[suggestion(no_crate_example, code = "...", applicability = "foo")]
    |                                                              ^^^^^
 
 error: suggestion without `#[primary_span]` field
-  --> $DIR/subdiagnostic-derive.rs:449:1
+  --> $DIR/subdiagnostic-derive.rs:450:1
    |
 LL | / #[suggestion(no_crate_example, code = "...")]
 LL | |
@@ -261,25 +261,25 @@ LL | | }
    | |_^
 
 error: unsupported type attribute for subdiagnostic enum
-  --> $DIR/subdiagnostic-derive.rs:463:1
+  --> $DIR/subdiagnostic-derive.rs:464:1
    |
 LL | #[label]
    | ^^^^^^^^
 
 error: `var` doesn't refer to a field on this type
-  --> $DIR/subdiagnostic-derive.rs:483:39
+  --> $DIR/subdiagnostic-derive.rs:484:39
    |
 LL | #[suggestion(no_crate_example, code = "{var}", applicability = "machine-applicable")]
    |                                       ^^^^^^^
 
 error: `var` doesn't refer to a field on this type
-  --> $DIR/subdiagnostic-derive.rs:502:43
+  --> $DIR/subdiagnostic-derive.rs:503:43
    |
 LL |     #[suggestion(no_crate_example, code = "{var}", applicability = "machine-applicable")]
    |                                           ^^^^^^^
 
 error: `#[suggestion_part]` is not a valid attribute
-  --> $DIR/subdiagnostic-derive.rs:525:5
+  --> $DIR/subdiagnostic-derive.rs:526:5
    |
 LL |     #[suggestion_part]
    |     ^^^^^^^^^^^^^^^^^^
@@ -287,7 +287,7 @@ LL |     #[suggestion_part]
    = help: `#[suggestion_part(...)]` is only valid in multipart suggestions, use `#[primary_span]` instead
 
 error: `#[suggestion_part(...)]` is not a valid attribute
-  --> $DIR/subdiagnostic-derive.rs:528:5
+  --> $DIR/subdiagnostic-derive.rs:529:5
    |
 LL |     #[suggestion_part(code = "...")]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -295,7 +295,7 @@ LL |     #[suggestion_part(code = "...")]
    = help: `#[suggestion_part(...)]` is only valid in multipart suggestions
 
 error: suggestion without `#[primary_span]` field
-  --> $DIR/subdiagnostic-derive.rs:522:1
+  --> $DIR/subdiagnostic-derive.rs:523:1
    |
 LL | / #[suggestion(no_crate_example, code = "...")]
 LL | |
@@ -307,7 +307,7 @@ LL | | }
    | |_^
 
 error: invalid nested attribute
-  --> $DIR/subdiagnostic-derive.rs:537:42
+  --> $DIR/subdiagnostic-derive.rs:538:42
    |
 LL | #[multipart_suggestion(no_crate_example, code = "...", applicability = "machine-applicable")]
    |                                          ^^^^
@@ -315,7 +315,7 @@ LL | #[multipart_suggestion(no_crate_example, code = "...", applicability = "mac
    = help: only `style` and `applicability` are valid nested attributes
 
 error: multipart suggestion without any `#[suggestion_part(...)]` fields
-  --> $DIR/subdiagnostic-derive.rs:537:1
+  --> $DIR/subdiagnostic-derive.rs:538:1
    |
 LL | / #[multipart_suggestion(no_crate_example, code = "...", applicability = "machine-applicable")]
 LL | |
@@ -326,19 +326,19 @@ LL | | }
    | |_^
 
 error: `#[suggestion_part(...)]` attribute without `code = "..."`
-  --> $DIR/subdiagnostic-derive.rs:547:5
+  --> $DIR/subdiagnostic-derive.rs:548:5
    |
 LL |     #[suggestion_part]
    |     ^^^^^^^^^^^^^^^^^^
 
 error: unexpected end of input, unexpected token in nested attribute, expected ident
-  --> $DIR/subdiagnostic-derive.rs:555:23
+  --> $DIR/subdiagnostic-derive.rs:556:23
    |
 LL |     #[suggestion_part()]
    |                       ^
 
 error: `#[primary_span]` is not a valid attribute
-  --> $DIR/subdiagnostic-derive.rs:564:5
+  --> $DIR/subdiagnostic-derive.rs:565:5
    |
 LL |     #[primary_span]
    |     ^^^^^^^^^^^^^^^
@@ -346,7 +346,7 @@ LL |     #[primary_span]
    = help: multipart suggestions use one or more `#[suggestion_part]`s rather than one `#[primary_span]`
 
 error: multipart suggestion without any `#[suggestion_part(...)]` fields
-  --> $DIR/subdiagnostic-derive.rs:561:1
+  --> $DIR/subdiagnostic-derive.rs:562:1
    |
 LL | / #[multipart_suggestion(no_crate_example)]
 LL | |
@@ -358,121 +358,121 @@ LL | | }
    | |_^
 
 error: `#[suggestion_part(...)]` attribute without `code = "..."`
-  --> $DIR/subdiagnostic-derive.rs:572:5
+  --> $DIR/subdiagnostic-derive.rs:573:5
    |
 LL |     #[suggestion_part]
    |     ^^^^^^^^^^^^^^^^^^
 
 error: `code` is the only valid nested attribute
-  --> $DIR/subdiagnostic-derive.rs:578:23
+  --> $DIR/subdiagnostic-derive.rs:579:23
    |
 LL |     #[suggestion_part(foo = "bar")]
    |                       ^^^
 
 error: the `#[suggestion_part(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan`
-  --> $DIR/subdiagnostic-derive.rs:582:5
+  --> $DIR/subdiagnostic-derive.rs:583:5
    |
 LL |     #[suggestion_part(code = "...")]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: the `#[suggestion_part(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan`
-  --> $DIR/subdiagnostic-derive.rs:585:5
+  --> $DIR/subdiagnostic-derive.rs:586:5
    |
 LL |     #[suggestion_part()]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: unexpected end of input, unexpected token in nested attribute, expected ident
-  --> $DIR/subdiagnostic-derive.rs:575:23
+  --> $DIR/subdiagnostic-derive.rs:576:23
    |
 LL |     #[suggestion_part()]
    |                       ^
 
 error: expected `,`
-  --> $DIR/subdiagnostic-derive.rs:578:27
+  --> $DIR/subdiagnostic-derive.rs:579:27
    |
 LL |     #[suggestion_part(foo = "bar")]
    |                           ^
 
 error: specified multiple times
-  --> $DIR/subdiagnostic-derive.rs:593:37
+  --> $DIR/subdiagnostic-derive.rs:594:37
    |
 LL |     #[suggestion_part(code = "...", code = ",,,")]
    |                                     ^^^^
    |
 note: previously specified here
-  --> $DIR/subdiagnostic-derive.rs:593:23
+  --> $DIR/subdiagnostic-derive.rs:594:23
    |
 LL |     #[suggestion_part(code = "...", code = ",,,")]
    |                       ^^^^
 
 error: `#[applicability]` has no effect if all `#[suggestion]`/`#[multipart_suggestion]` attributes have a static `applicability = "..."`
-  --> $DIR/subdiagnostic-derive.rs:622:5
+  --> $DIR/subdiagnostic-derive.rs:623:5
    |
 LL |     #[applicability]
    |     ^^^^^^^^^^^^^^^^
 
 error: expected exactly one string literal for `code = ...`
-  --> $DIR/subdiagnostic-derive.rs:670:34
+  --> $DIR/subdiagnostic-derive.rs:671:34
    |
 LL |     #[suggestion_part(code("foo"))]
    |                                  ^
 
 error: unexpected token
-  --> $DIR/subdiagnostic-derive.rs:670:28
+  --> $DIR/subdiagnostic-derive.rs:671:28
    |
 LL |     #[suggestion_part(code("foo"))]
    |                            ^^^^^
 
 error: expected exactly one string literal for `code = ...`
-  --> $DIR/subdiagnostic-derive.rs:680:41
+  --> $DIR/subdiagnostic-derive.rs:681:41
    |
 LL |     #[suggestion_part(code("foo", "bar"))]
    |                                         ^
 
 error: unexpected token
-  --> $DIR/subdiagnostic-derive.rs:680:28
+  --> $DIR/subdiagnostic-derive.rs:681:28
    |
 LL |     #[suggestion_part(code("foo", "bar"))]
    |                            ^^^^^
 
 error: expected exactly one string literal for `code = ...`
-  --> $DIR/subdiagnostic-derive.rs:690:30
+  --> $DIR/subdiagnostic-derive.rs:691:30
    |
 LL |     #[suggestion_part(code(3))]
    |                              ^
 
 error: unexpected token
-  --> $DIR/subdiagnostic-derive.rs:690:28
+  --> $DIR/subdiagnostic-derive.rs:691:28
    |
 LL |     #[suggestion_part(code(3))]
    |                            ^
 
 error: expected exactly one string literal for `code = ...`
-  --> $DIR/subdiagnostic-derive.rs:700:29
+  --> $DIR/subdiagnostic-derive.rs:701:29
    |
 LL |     #[suggestion_part(code())]
    |                             ^
 
 error: expected string literal
-  --> $DIR/subdiagnostic-derive.rs:712:30
+  --> $DIR/subdiagnostic-derive.rs:713:30
    |
 LL |     #[suggestion_part(code = 3)]
    |                              ^
 
 error: specified multiple times
-  --> $DIR/subdiagnostic-derive.rs:754:1
+  --> $DIR/subdiagnostic-derive.rs:755:1
    |
 LL | #[suggestion(no_crate_example, code = "", style = "hidden", style = "normal")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: previously specified here
-  --> $DIR/subdiagnostic-derive.rs:754:1
+  --> $DIR/subdiagnostic-derive.rs:755:1
    |
 LL | #[suggestion(no_crate_example, code = "", style = "hidden", style = "normal")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: `#[suggestion_hidden(...)]` is not a valid attribute
-  --> $DIR/subdiagnostic-derive.rs:763:1
+  --> $DIR/subdiagnostic-derive.rs:764:1
    |
 LL | #[suggestion_hidden(no_crate_example, code = "")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -480,7 +480,7 @@ LL | #[suggestion_hidden(no_crate_example, code = "")]
    = help: Use `#[suggestion(..., style = "hidden")]` instead
 
 error: `#[suggestion_hidden(...)]` is not a valid attribute
-  --> $DIR/subdiagnostic-derive.rs:771:1
+  --> $DIR/subdiagnostic-derive.rs:772:1
    |
 LL | #[suggestion_hidden(no_crate_example, code = "", style = "normal")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -488,7 +488,7 @@ LL | #[suggestion_hidden(no_crate_example, code = "", style = "normal")]
    = help: Use `#[suggestion(..., style = "hidden")]` instead
 
 error: invalid suggestion style
-  --> $DIR/subdiagnostic-derive.rs:779:51
+  --> $DIR/subdiagnostic-derive.rs:780:51
    |
 LL | #[suggestion(no_crate_example, code = "", style = "foo")]
    |                                                   ^^^^^
@@ -496,31 +496,31 @@ LL | #[suggestion(no_crate_example, code = "", style = "foo")]
    = help: valid styles are `normal`, `short`, `hidden`, `verbose` and `tool-only`
 
 error: expected `= "xxx"`
-  --> $DIR/subdiagnostic-derive.rs:787:49
+  --> $DIR/subdiagnostic-derive.rs:788:49
    |
 LL | #[suggestion(no_crate_example, code = "", style = 42)]
    |                                                 ^
 
 error: a diagnostic slug must be the first argument to the attribute
-  --> $DIR/subdiagnostic-derive.rs:795:48
+  --> $DIR/subdiagnostic-derive.rs:796:48
    |
 LL | #[suggestion(no_crate_example, code = "", style)]
    |                                                ^
 
 error: expected `= "xxx"`
-  --> $DIR/subdiagnostic-derive.rs:803:48
+  --> $DIR/subdiagnostic-derive.rs:804:48
    |
 LL | #[suggestion(no_crate_example, code = "", style("foo"))]
    |                                                ^
 
 error: expected `,`
-  --> $DIR/subdiagnostic-derive.rs:803:48
+  --> $DIR/subdiagnostic-derive.rs:804:48
    |
 LL | #[suggestion(no_crate_example, code = "", style("foo"))]
    |                                                ^
 
 error: `#[primary_span]` is not a valid attribute
-  --> $DIR/subdiagnostic-derive.rs:815:5
+  --> $DIR/subdiagnostic-derive.rs:816:5
    |
 LL |     #[primary_span]
    |     ^^^^^^^^^^^^^^^
@@ -529,7 +529,7 @@ LL |     #[primary_span]
    = help: to create a suggestion with multiple spans, use `#[multipart_suggestion]` instead
 
 error: suggestion without `#[primary_span]` field
-  --> $DIR/subdiagnostic-derive.rs:812:1
+  --> $DIR/subdiagnostic-derive.rs:813:1
    |
 LL | / #[suggestion(no_crate_example, code = "")]
 LL | |
@@ -541,67 +541,67 @@ LL | | }
    | |_^
 
 error: cannot find attribute `foo` in this scope
-  --> $DIR/subdiagnostic-derive.rs:65:3
+  --> $DIR/subdiagnostic-derive.rs:66:3
    |
 LL | #[foo]
    |   ^^^
 
 error: cannot find attribute `foo` in this scope
-  --> $DIR/subdiagnostic-derive.rs:160:3
+  --> $DIR/subdiagnostic-derive.rs:161:3
    |
 LL | #[foo]
    |   ^^^
 
 error: cannot find attribute `bar` in this scope
-  --> $DIR/subdiagnostic-derive.rs:174:7
+  --> $DIR/subdiagnostic-derive.rs:175:7
    |
 LL |     #[bar]
    |       ^^^
 
 error: cannot find attribute `bar` in this scope
-  --> $DIR/subdiagnostic-derive.rs:186:7
+  --> $DIR/subdiagnostic-derive.rs:187:7
    |
 LL |     #[bar = "..."]
    |       ^^^
 
 error: cannot find attribute `bar` in this scope
-  --> $DIR/subdiagnostic-derive.rs:198:7
+  --> $DIR/subdiagnostic-derive.rs:199:7
    |
 LL |     #[bar = 4]
    |       ^^^
 
 error: cannot find attribute `bar` in this scope
-  --> $DIR/subdiagnostic-derive.rs:210:7
+  --> $DIR/subdiagnostic-derive.rs:211:7
    |
 LL |     #[bar("...")]
    |       ^^^
 
 error: cannot find attribute `bar` in this scope
-  --> $DIR/subdiagnostic-derive.rs:271:7
+  --> $DIR/subdiagnostic-derive.rs:272:7
    |
 LL |     #[bar]
    |       ^^^
 
 error: cannot find attribute `bar` in this scope
-  --> $DIR/subdiagnostic-derive.rs:282:7
+  --> $DIR/subdiagnostic-derive.rs:283:7
    |
 LL |     #[bar = "..."]
    |       ^^^
 
 error: cannot find attribute `bar` in this scope
-  --> $DIR/subdiagnostic-derive.rs:293:7
+  --> $DIR/subdiagnostic-derive.rs:294:7
    |
 LL |     #[bar("...")]
    |       ^^^
 
 error[E0425]: cannot find value `slug` in module `crate::fluent_generated`
-  --> $DIR/subdiagnostic-derive.rs:123:9
+  --> $DIR/subdiagnostic-derive.rs:124:9
    |
 LL | #[label(slug)]
    |         ^^^^ not found in `crate::fluent_generated`
 
 error[E0425]: cannot find value `__code_29` in this scope
-  --> $DIR/subdiagnostic-derive.rs:706:10
+  --> $DIR/subdiagnostic-derive.rs:707:10
    |
 LL | #[derive(Subdiagnostic)]
    |          ^^^^^^^^^^^^^ not found in this scope
diff --git a/tests/ui/attributes/invalid-repr.rs b/tests/ui/attributes/invalid-repr.rs
new file mode 100644
index 00000000000..10a487c127e
--- /dev/null
+++ b/tests/ui/attributes/invalid-repr.rs
@@ -0,0 +1,5 @@
+#[repr(align(16))]
+//~^ ERROR attribute should be applied to a struct, enum, function, associated function, or union
+pub type Foo = i32;
+
+fn main() {}
diff --git a/tests/ui/attributes/invalid-repr.stderr b/tests/ui/attributes/invalid-repr.stderr
new file mode 100644
index 00000000000..98a6a24b3c4
--- /dev/null
+++ b/tests/ui/attributes/invalid-repr.stderr
@@ -0,0 +1,12 @@
+error[E0517]: attribute should be applied to a struct, enum, function, associated function, or union
+  --> $DIR/invalid-repr.rs:1:8
+   |
+LL | #[repr(align(16))]
+   |        ^^^^^^^^^
+LL |
+LL | pub type Foo = i32;
+   | ------------------- not a struct, enum, function, associated function, or union
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0517`.
diff --git a/tests/ui/borrowck/borrowck-block-unint.rs b/tests/ui/borrowck/borrowck-block-uninit.rs
index 8d13b25a357..8d13b25a357 100644
--- a/tests/ui/borrowck/borrowck-block-unint.rs
+++ b/tests/ui/borrowck/borrowck-block-uninit.rs
diff --git a/tests/ui/borrowck/borrowck-block-unint.stderr b/tests/ui/borrowck/borrowck-block-uninit.stderr
index f47921a9752..1a5969586f2 100644
--- a/tests/ui/borrowck/borrowck-block-unint.stderr
+++ b/tests/ui/borrowck/borrowck-block-uninit.stderr
@@ -1,5 +1,5 @@
 error[E0381]: used binding `x` isn't initialized
-  --> $DIR/borrowck-block-unint.rs:4:11
+  --> $DIR/borrowck-block-uninit.rs:4:11
    |
 LL |     let x: isize;
    |         - binding declared here but left uninitialized
diff --git a/tests/ui/codegen/freeze-on-polymorphic-projection.rs b/tests/ui/codegen/freeze-on-polymorphic-projection.rs
new file mode 100644
index 00000000000..edc79f8fd94
--- /dev/null
+++ b/tests/ui/codegen/freeze-on-polymorphic-projection.rs
@@ -0,0 +1,19 @@
+// build-pass
+// compile-flags: -Copt-level=1 --crate-type=lib
+
+#![feature(specialization)]
+//~^ WARN the feature `specialization` is incomplete
+
+pub unsafe trait Storage {
+    type Handle;
+}
+
+pub unsafe trait MultipleStorage: Storage {}
+
+default unsafe impl<S> Storage for S where S: MultipleStorage {}
+
+// Make sure that we call is_freeze on `(S::Handle,)` in the param-env of `ice`,
+// instead of in an empty, reveal-all param-env.
+pub fn ice<S: Storage>(boxed: (S::Handle,)) -> (S::Handle,) {
+    boxed
+}
diff --git a/tests/ui/codegen/freeze-on-polymorphic-projection.stderr b/tests/ui/codegen/freeze-on-polymorphic-projection.stderr
new file mode 100644
index 00000000000..903cb2ff6aa
--- /dev/null
+++ b/tests/ui/codegen/freeze-on-polymorphic-projection.stderr
@@ -0,0 +1,12 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/freeze-on-polymorphic-projection.rs:4:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+   = help: consider using `min_specialization` instead, which is more stable and complete
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/consts/auxiliary/foreign-generic-mismatch-with-const-arg.rs b/tests/ui/consts/auxiliary/foreign-generic-mismatch-with-const-arg.rs
new file mode 100644
index 00000000000..85b0c6c9df8
--- /dev/null
+++ b/tests/ui/consts/auxiliary/foreign-generic-mismatch-with-const-arg.rs
@@ -0,0 +1 @@
+pub fn test<const N: usize, T>() {}
diff --git a/tests/ui/consts/foreign-generic-mismatch-with-const-arg.rs b/tests/ui/consts/foreign-generic-mismatch-with-const-arg.rs
new file mode 100644
index 00000000000..7590abbd827
--- /dev/null
+++ b/tests/ui/consts/foreign-generic-mismatch-with-const-arg.rs
@@ -0,0 +1,8 @@
+// aux-build: foreign-generic-mismatch-with-const-arg.rs
+
+extern crate foreign_generic_mismatch_with_const_arg;
+
+fn main() {
+    foreign_generic_mismatch_with_const_arg::test::<1>();
+    //~^ ERROR function takes 2 generic arguments but 1 generic argument was supplied
+}
diff --git a/tests/ui/consts/foreign-generic-mismatch-with-const-arg.stderr b/tests/ui/consts/foreign-generic-mismatch-with-const-arg.stderr
new file mode 100644
index 00000000000..4cc03a20514
--- /dev/null
+++ b/tests/ui/consts/foreign-generic-mismatch-with-const-arg.stderr
@@ -0,0 +1,21 @@
+error[E0107]: function takes 2 generic arguments but 1 generic argument was supplied
+  --> $DIR/foreign-generic-mismatch-with-const-arg.rs:6:46
+   |
+LL |     foreign_generic_mismatch_with_const_arg::test::<1>();
+   |                                              ^^^^   - supplied 1 generic argument
+   |                                              |
+   |                                              expected 2 generic arguments
+   |
+note: function defined here, with 2 generic parameters: `N`, `T`
+  --> $DIR/auxiliary/foreign-generic-mismatch-with-const-arg.rs:1:8
+   |
+LL | pub fn test<const N: usize, T>() {}
+   |        ^^^^ --------------  -
+help: add missing generic argument
+   |
+LL |     foreign_generic_mismatch_with_const_arg::test::<1, T>();
+   |                                                      +++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0107`.
diff --git a/tests/ui/error-codes/E0026-teach.stderr b/tests/ui/error-codes/E0026-teach.stderr
index 1a80edcbbe2..3d460490eb3 100644
--- a/tests/ui/error-codes/E0026-teach.stderr
+++ b/tests/ui/error-codes/E0026-teach.stderr
@@ -4,7 +4,7 @@ error[E0026]: struct `Thing` does not have a field named `z`
 LL |         Thing { x, y, z } => {}
    |                       ^ struct `Thing` does not have this field
    |
-   = note: This error indicates that a struct pattern attempted to extract a non-existent field from a struct. Struct fields are identified by the name used before the colon : so struct patterns should resemble the declaration of the struct type being matched.
+   = note: This error indicates that a struct pattern attempted to extract a nonexistent field from a struct. Struct fields are identified by the name used before the colon : so struct patterns should resemble the declaration of the struct type being matched.
            
            If you are using shorthand field patterns but want to refer to the struct field by a different name, you should rename it explicitly.
 
diff --git a/tests/ui-fulldeps/lint-group-denied-lint-allowed.rs b/tests/ui/lint-group-denied-lint-allowed.rs
index 7498745f206..8156b6ef617 100644
--- a/tests/ui-fulldeps/lint-group-denied-lint-allowed.rs
+++ b/tests/ui/lint-group-denied-lint-allowed.rs
@@ -1,4 +1,3 @@
-// aux-build:lint-group-plugin-test.rs
 // check-pass
 // compile-flags: -D unused -A unused-variables
 
diff --git a/tests/ui-fulldeps/lint-group-forbid-always-trumps-cli.rs b/tests/ui/lint-group-forbid-always-trumps-cli.rs
index fc19bc03906..77b792f98d5 100644
--- a/tests/ui-fulldeps/lint-group-forbid-always-trumps-cli.rs
+++ b/tests/ui/lint-group-forbid-always-trumps-cli.rs
@@ -1,4 +1,3 @@
-// aux-build:lint-group-plugin-test.rs
 // compile-flags: -F unused -A unused
 
 fn main() {
diff --git a/tests/ui-fulldeps/lint-group-forbid-always-trumps-cli.stderr b/tests/ui/lint-group-forbid-always-trumps-cli.stderr
index 6bab367b0d1..8910af87ca2 100644
--- a/tests/ui-fulldeps/lint-group-forbid-always-trumps-cli.stderr
+++ b/tests/ui/lint-group-forbid-always-trumps-cli.stderr
@@ -1,5 +1,5 @@
 error: unused variable: `x`
-  --> $DIR/lint-group-forbid-always-trumps-cli.rs:5:9
+  --> $DIR/lint-group-forbid-always-trumps-cli.rs:4:9
    |
 LL |     let x = 1;
    |         ^ help: if this is intentional, prefix it with an underscore: `_x`
diff --git a/tests/ui/lint/unused/issue-54538-unused-parens-lint.fixed b/tests/ui/lint/unused/issue-54538-unused-parens-lint.fixed
index 71ebaea8ed2..9c52ca5577e 100644
--- a/tests/ui/lint/unused/issue-54538-unused-parens-lint.fixed
+++ b/tests/ui/lint/unused/issue-54538-unused-parens-lint.fixed
@@ -21,17 +21,32 @@ fn lint_on_top_level() {
     let _ = |a: u8| 0; //~ ERROR unnecessary parentheses around pattern
 }
 
-fn _no_lint_attr() {
+fn no_lint_attr() {
     let _x = #[allow(dead_code)] (1 + 2);
 }
 
-fn _no_lint_yeet() -> Result<(), ()> {
+fn no_lint_yeet() -> Result<(), ()> {
     #[allow(unreachable_code)]
     if (do yeet) {}
 
     Ok(())
 }
 
+fn no_lint_ops() {
+    #![allow(unreachable_code, irrefutable_let_patterns)]
+    if ((..{}) == ..{}) {}
+    if (!return) {}
+    loop { match (() = () = () = break {}) {} }
+    while let () = (*&mut false |= true && return) {}
+}
+
+fn lint_break_if_not_followed_by_block() {
+    #![allow(unreachable_code)]
+    loop { if break {} } //~ ERROR unnecessary parentheses
+    loop { if break ({ println!("hello") }) {} } //~ ERROR unnecessary parentheses
+    loop { if (break { println!("hello") }) {} }
+}
+
 // Don't lint in these cases (#64106).
 fn or_patterns_no_lint() {
     match Box::new(0) {
diff --git a/tests/ui/lint/unused/issue-54538-unused-parens-lint.rs b/tests/ui/lint/unused/issue-54538-unused-parens-lint.rs
index 28b662dd024..196ecf0c1bb 100644
--- a/tests/ui/lint/unused/issue-54538-unused-parens-lint.rs
+++ b/tests/ui/lint/unused/issue-54538-unused-parens-lint.rs
@@ -21,17 +21,32 @@ fn lint_on_top_level() {
     let _ = |(a): u8| 0; //~ ERROR unnecessary parentheses around pattern
 }
 
-fn _no_lint_attr() {
+fn no_lint_attr() {
     let _x = #[allow(dead_code)] (1 + 2);
 }
 
-fn _no_lint_yeet() -> Result<(), ()> {
+fn no_lint_yeet() -> Result<(), ()> {
     #[allow(unreachable_code)]
     if (do yeet) {}
 
     Ok(())
 }
 
+fn no_lint_ops() {
+    #![allow(unreachable_code, irrefutable_let_patterns)]
+    if ((..{}) == ..{}) {}
+    if (!return) {}
+    loop { match (() = () = () = break {}) {} }
+    while let () = (*&mut false |= true && return) {}
+}
+
+fn lint_break_if_not_followed_by_block() {
+    #![allow(unreachable_code)]
+    loop { if (break) {} } //~ ERROR unnecessary parentheses
+    loop { if (break ({ println!("hello") })) {} } //~ ERROR unnecessary parentheses
+    loop { if (break { println!("hello") }) {} }
+}
+
 // Don't lint in these cases (#64106).
 fn or_patterns_no_lint() {
     match Box::new(0) {
diff --git a/tests/ui/lint/unused/issue-54538-unused-parens-lint.stderr b/tests/ui/lint/unused/issue-54538-unused-parens-lint.stderr
index a5e69e6d938..f916bba8194 100644
--- a/tests/ui/lint/unused/issue-54538-unused-parens-lint.stderr
+++ b/tests/ui/lint/unused/issue-54538-unused-parens-lint.stderr
@@ -75,8 +75,32 @@ LL -     let _ = |(a): u8| 0;
 LL +     let _ = |a: u8| 0;
    |
 
+error: unnecessary parentheses around `if` condition
+  --> $DIR/issue-54538-unused-parens-lint.rs:45:15
+   |
+LL |     loop { if (break) {} }
+   |               ^     ^
+   |
+help: remove these parentheses
+   |
+LL -     loop { if (break) {} }
+LL +     loop { if break {} }
+   |
+
+error: unnecessary parentheses around `if` condition
+  --> $DIR/issue-54538-unused-parens-lint.rs:46:15
+   |
+LL |     loop { if (break ({ println!("hello") })) {} }
+   |               ^                             ^
+   |
+help: remove these parentheses
+   |
+LL -     loop { if (break ({ println!("hello") })) {} }
+LL +     loop { if break ({ println!("hello") }) {} }
+   |
+
 error: unnecessary parentheses around pattern
-  --> $DIR/issue-54538-unused-parens-lint.rs:56:12
+  --> $DIR/issue-54538-unused-parens-lint.rs:71:12
    |
 LL |     if let (0 | 1) = 0 {}
    |            ^     ^
@@ -88,7 +112,7 @@ LL +     if let 0 | 1 = 0 {}
    |
 
 error: unnecessary parentheses around pattern
-  --> $DIR/issue-54538-unused-parens-lint.rs:57:13
+  --> $DIR/issue-54538-unused-parens-lint.rs:72:13
    |
 LL |     if let ((0 | 1),) = (0,) {}
    |             ^     ^
@@ -100,7 +124,7 @@ LL +     if let (0 | 1,) = (0,) {}
    |
 
 error: unnecessary parentheses around pattern
-  --> $DIR/issue-54538-unused-parens-lint.rs:58:13
+  --> $DIR/issue-54538-unused-parens-lint.rs:73:13
    |
 LL |     if let [(0 | 1)] = [0] {}
    |             ^     ^
@@ -112,7 +136,7 @@ LL +     if let [0 | 1] = [0] {}
    |
 
 error: unnecessary parentheses around pattern
-  --> $DIR/issue-54538-unused-parens-lint.rs:59:16
+  --> $DIR/issue-54538-unused-parens-lint.rs:74:16
    |
 LL |     if let 0 | (1 | 2) = 0 {}
    |                ^     ^
@@ -124,7 +148,7 @@ LL +     if let 0 | 1 | 2 = 0 {}
    |
 
 error: unnecessary parentheses around pattern
-  --> $DIR/issue-54538-unused-parens-lint.rs:61:15
+  --> $DIR/issue-54538-unused-parens-lint.rs:76:15
    |
 LL |     if let TS((0 | 1)) = TS(0) {}
    |               ^     ^
@@ -136,7 +160,7 @@ LL +     if let TS(0 | 1) = TS(0) {}
    |
 
 error: unnecessary parentheses around pattern
-  --> $DIR/issue-54538-unused-parens-lint.rs:63:20
+  --> $DIR/issue-54538-unused-parens-lint.rs:78:20
    |
 LL |     if let NS { f: (0 | 1) } = (NS { f: 0 }) {}
    |                    ^     ^
@@ -148,7 +172,7 @@ LL +     if let NS { f: 0 | 1 } = (NS { f: 0 }) {}
    |
 
 error: unnecessary parentheses around pattern
-  --> $DIR/issue-54538-unused-parens-lint.rs:73:9
+  --> $DIR/issue-54538-unused-parens-lint.rs:88:9
    |
 LL |         (_) => {}
    |         ^ ^
@@ -160,7 +184,7 @@ LL +         _ => {}
    |
 
 error: unnecessary parentheses around pattern
-  --> $DIR/issue-54538-unused-parens-lint.rs:74:9
+  --> $DIR/issue-54538-unused-parens-lint.rs:89:9
    |
 LL |         (y) => {}
    |         ^ ^
@@ -172,7 +196,7 @@ LL +         y => {}
    |
 
 error: unnecessary parentheses around pattern
-  --> $DIR/issue-54538-unused-parens-lint.rs:75:9
+  --> $DIR/issue-54538-unused-parens-lint.rs:90:9
    |
 LL |         (ref r) => {}
    |         ^     ^
@@ -184,7 +208,7 @@ LL +         ref r => {}
    |
 
 error: unnecessary parentheses around pattern
-  --> $DIR/issue-54538-unused-parens-lint.rs:76:9
+  --> $DIR/issue-54538-unused-parens-lint.rs:91:9
    |
 LL |         (e @ 1...2) => {}
    |         ^         ^
@@ -196,7 +220,7 @@ LL +         e @ 1...2 => {}
    |
 
 error: unnecessary parentheses around pattern
-  --> $DIR/issue-54538-unused-parens-lint.rs:82:9
+  --> $DIR/issue-54538-unused-parens-lint.rs:97:9
    |
 LL |         (e @ &(1...2)) => {}
    |         ^            ^
@@ -208,7 +232,7 @@ LL +         e @ &(1...2) => {}
    |
 
 error: unnecessary parentheses around pattern
-  --> $DIR/issue-54538-unused-parens-lint.rs:83:10
+  --> $DIR/issue-54538-unused-parens-lint.rs:98:10
    |
 LL |         &(_) => {}
    |          ^ ^
@@ -220,7 +244,7 @@ LL +         &_ => {}
    |
 
 error: unnecessary parentheses around pattern
-  --> $DIR/issue-54538-unused-parens-lint.rs:94:9
+  --> $DIR/issue-54538-unused-parens-lint.rs:109:9
    |
 LL |         (_) => {}
    |         ^ ^
@@ -232,7 +256,7 @@ LL +         _ => {}
    |
 
 error: unnecessary parentheses around pattern
-  --> $DIR/issue-54538-unused-parens-lint.rs:95:9
+  --> $DIR/issue-54538-unused-parens-lint.rs:110:9
    |
 LL |         (y) => {}
    |         ^ ^
@@ -244,7 +268,7 @@ LL +         y => {}
    |
 
 error: unnecessary parentheses around pattern
-  --> $DIR/issue-54538-unused-parens-lint.rs:96:9
+  --> $DIR/issue-54538-unused-parens-lint.rs:111:9
    |
 LL |         (ref r) => {}
    |         ^     ^
@@ -256,7 +280,7 @@ LL +         ref r => {}
    |
 
 error: unnecessary parentheses around pattern
-  --> $DIR/issue-54538-unused-parens-lint.rs:97:9
+  --> $DIR/issue-54538-unused-parens-lint.rs:112:9
    |
 LL |         (e @ 1..=2) => {}
    |         ^         ^
@@ -268,7 +292,7 @@ LL +         e @ 1..=2 => {}
    |
 
 error: unnecessary parentheses around pattern
-  --> $DIR/issue-54538-unused-parens-lint.rs:103:9
+  --> $DIR/issue-54538-unused-parens-lint.rs:118:9
    |
 LL |         (e @ &(1..=2)) => {}
    |         ^            ^
@@ -280,7 +304,7 @@ LL +         e @ &(1..=2) => {}
    |
 
 error: unnecessary parentheses around pattern
-  --> $DIR/issue-54538-unused-parens-lint.rs:104:10
+  --> $DIR/issue-54538-unused-parens-lint.rs:119:10
    |
 LL |         &(_) => {}
    |          ^ ^
@@ -291,5 +315,5 @@ LL -         &(_) => {}
 LL +         &_ => {}
    |
 
-error: aborting due to 24 previous errors
+error: aborting due to 26 previous errors
 
diff --git a/tests/ui/meta/no_std-extern-libc.rs b/tests/ui/meta/no_std-extern-libc.rs
new file mode 100644
index 00000000000..763ea740a27
--- /dev/null
+++ b/tests/ui/meta/no_std-extern-libc.rs
@@ -0,0 +1,7 @@
+// Test that `download-rustc` doesn't put duplicate copies of libc in the sysroot.
+// check-pass
+#![crate_type = "lib"]
+#![no_std]
+#![feature(rustc_private)]
+
+extern crate libc;
diff --git a/tests/ui/type-alias-enum-variants/enum-variant-generic-args.stderr b/tests/ui/type-alias-enum-variants/enum-variant-generic-args.stderr
index 758ff31ff70..e24cb11288e 100644
--- a/tests/ui/type-alias-enum-variants/enum-variant-generic-args.stderr
+++ b/tests/ui/type-alias-enum-variants/enum-variant-generic-args.stderr
@@ -115,7 +115,7 @@ LL |         Self::SVariant::<()> { v: () };
    |               not allowed on this type
    |
    = note: enum variants can't have type parameters
-help: you might have meant to specity type parameters on enum `Enum`
+help: you might have meant to specify type parameters on enum `Enum`
    |
 LL -         Self::SVariant::<()> { v: () };
 LL +         Enum::<()>::SVariant { v: () };
@@ -196,7 +196,7 @@ LL |         Self::<()>::SVariant::<()> { v: () };
    |                     not allowed on this type
    |
    = note: enum variants can't have type parameters
-help: you might have meant to specity type parameters on enum `Enum`
+help: you might have meant to specify type parameters on enum `Enum`
    |
 LL -         Self::<()>::SVariant::<()> { v: () };
 LL +         Enum::<()>::SVariant { v: () };
@@ -359,7 +359,7 @@ LL |     Alias::SVariant::<()> { v: () };
    |            not allowed on this type
    |
    = note: enum variants can't have type parameters
-help: you might have meant to specity type parameters on enum `Enum`
+help: you might have meant to specify type parameters on enum `Enum`
    |
 LL -     Alias::SVariant::<()> { v: () };
 LL +     Alias::<()>::SVariant { v: () };
@@ -374,7 +374,7 @@ LL |     Alias::<()>::SVariant::<()> { v: () };
    |                  not allowed on this type
    |
    = note: enum variants can't have type parameters
-help: you might have meant to specity type parameters on enum `Enum`
+help: you might have meant to specify type parameters on enum `Enum`
    |
 LL -     Alias::<()>::SVariant::<()> { v: () };
 LL +     Alias::<()>::SVariant { v: () };
@@ -389,7 +389,7 @@ LL |     AliasFixed::SVariant::<()> { v: () };
    |                 not allowed on this type
    |
    = note: enum variants can't have type parameters
-help: you might have meant to specity type parameters on enum `Enum`
+help: you might have meant to specify type parameters on enum `Enum`
    |
 LL -     AliasFixed::SVariant::<()> { v: () };
 LL +     AliasFixed::<()>::SVariant { v: () };
@@ -432,7 +432,7 @@ LL |     AliasFixed::<()>::SVariant::<()> { v: () };
    |                       not allowed on this type
    |
    = note: enum variants can't have type parameters
-help: you might have meant to specity type parameters on enum `Enum`
+help: you might have meant to specify type parameters on enum `Enum`
    |
 LL -     AliasFixed::<()>::SVariant::<()> { v: () };
 LL +     AliasFixed::<()>::SVariant { v: () };
diff --git a/tests/ui/typeck/bad-index-due-to-nested.rs b/tests/ui/typeck/bad-index-due-to-nested.rs
new file mode 100644
index 00000000000..2564b530004
--- /dev/null
+++ b/tests/ui/typeck/bad-index-due-to-nested.rs
@@ -0,0 +1,27 @@
+use std::hash::Hash;
+use std::marker::PhantomData;
+use std::ops::Index;
+
+struct HashMap<K, V>(PhantomData<(K, V)>);
+
+impl<K, V> Index<&K> for HashMap<K, V>
+where
+    K: Hash,
+    V: Copy,
+{
+    type Output = V;
+
+    fn index(&self, k: &K) -> &V {
+        todo!()
+    }
+}
+
+fn index<'a, K, V>(map: &'a HashMap<K, V>, k: K) -> &'a V {
+    map[k]
+    //~^ ERROR the trait bound `K: Hash` is not satisfied
+    //~| ERROR the trait bound `V: Copy` is not satisfied
+    //~| ERROR mismatched types
+    //~| ERROR mismatched types
+}
+
+fn main() {}
diff --git a/tests/ui/typeck/bad-index-due-to-nested.stderr b/tests/ui/typeck/bad-index-due-to-nested.stderr
new file mode 100644
index 00000000000..e03b06b336e
--- /dev/null
+++ b/tests/ui/typeck/bad-index-due-to-nested.stderr
@@ -0,0 +1,64 @@
+error[E0277]: the trait bound `K: Hash` is not satisfied
+  --> $DIR/bad-index-due-to-nested.rs:20:5
+   |
+LL |     map[k]
+   |     ^^^ the trait `Hash` is not implemented for `K`
+   |
+note: required by a bound in `<HashMap<K, V> as Index<&K>>`
+  --> $DIR/bad-index-due-to-nested.rs:9:8
+   |
+LL |     K: Hash,
+   |        ^^^^ required by this bound in `<HashMap<K, V> as Index<&K>>`
+help: consider restricting type parameter `K`
+   |
+LL | fn index<'a, K: std::hash::Hash, V>(map: &'a HashMap<K, V>, k: K) -> &'a V {
+   |               +++++++++++++++++
+
+error[E0277]: the trait bound `V: Copy` is not satisfied
+  --> $DIR/bad-index-due-to-nested.rs:20:5
+   |
+LL |     map[k]
+   |     ^^^ the trait `Copy` is not implemented for `V`
+   |
+note: required by a bound in `<HashMap<K, V> as Index<&K>>`
+  --> $DIR/bad-index-due-to-nested.rs:10:8
+   |
+LL |     V: Copy,
+   |        ^^^^ required by this bound in `<HashMap<K, V> as Index<&K>>`
+help: consider restricting type parameter `V`
+   |
+LL | fn index<'a, K, V: std::marker::Copy>(map: &'a HashMap<K, V>, k: K) -> &'a V {
+   |                  +++++++++++++++++++
+
+error[E0308]: mismatched types
+  --> $DIR/bad-index-due-to-nested.rs:20:9
+   |
+LL | fn index<'a, K, V>(map: &'a HashMap<K, V>, k: K) -> &'a V {
+   |              - this type parameter
+LL |     map[k]
+   |         ^
+   |         |
+   |         expected `&K`, found type parameter `K`
+   |         help: consider borrowing here: `&k`
+   |
+   = note:   expected reference `&K`
+           found type parameter `K`
+
+error[E0308]: mismatched types
+  --> $DIR/bad-index-due-to-nested.rs:20:5
+   |
+LL | fn index<'a, K, V>(map: &'a HashMap<K, V>, k: K) -> &'a V {
+   |                 - this type parameter               ----- expected `&'a V` because of return type
+LL |     map[k]
+   |     ^^^^^^
+   |     |
+   |     expected `&V`, found type parameter `V`
+   |     help: consider borrowing here: `&map[k]`
+   |
+   = note:   expected reference `&'a V`
+           found type parameter `V`
+
+error: aborting due to 4 previous errors
+
+Some errors have detailed explanations: E0277, E0308.
+For more information about an error, try `rustc --explain E0277`.