about summary refs log tree commit diff
diff options
context:
space:
mode:
authorRalf Jung <post@ralfj.de>2022-12-09 08:54:39 +0100
committerRalf Jung <post@ralfj.de>2022-12-09 08:54:39 +0100
commitaab3bcecb7da86b141d9a39079afedd0820115e6 (patch)
tree2f4932efa6ea145fbecbf32cb89dff3bc62e0d85
parent4e9f8393f87f8bdfad388fe112464d97661a8cb2 (diff)
parentb70a869d8f49e87d8432de6af6d209243a7053a4 (diff)
downloadrust-aab3bcecb7da86b141d9a39079afedd0820115e6.tar.gz
rust-aab3bcecb7da86b141d9a39079afedd0820115e6.zip
Merge from rustc
-rw-r--r--.gitmodules2
-rw-r--r--Cargo.lock82
-rw-r--r--Cargo.toml2
-rw-r--r--compiler/rustc_abi/src/lib.rs7
-rw-r--r--compiler/rustc_ast_lowering/src/expr.rs210
-rw-r--r--compiler/rustc_ast_lowering/src/item.rs44
-rw-r--r--compiler/rustc_ast_lowering/src/lib.rs34
-rw-r--r--compiler/rustc_ast_lowering/src/path.rs19
-rw-r--r--compiler/rustc_ast_pretty/src/pprust/state/item.rs15
-rw-r--r--compiler/rustc_attr/src/builtin.rs134
-rw-r--r--compiler/rustc_borrowck/src/borrow_set.rs8
-rw-r--r--compiler/rustc_borrowck/src/dataflow.rs10
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs12
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs16
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs23
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/mod.rs47
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs6
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/region_errors.rs2
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/region_name.rs2
-rw-r--r--compiler/rustc_borrowck/src/invalidation.rs65
-rw-r--r--compiler/rustc_borrowck/src/lib.rs69
-rw-r--r--compiler/rustc_borrowck/src/type_check/canonical.rs6
-rw-r--r--compiler/rustc_borrowck/src/type_check/mod.rs39
-rw-r--r--compiler/rustc_borrowck/src/universal_regions.rs6
-rw-r--r--compiler/rustc_builtin_macros/src/alloc_error_handler.rs37
-rw-r--r--compiler/rustc_builtin_macros/src/assert/context.rs38
-rw-r--r--compiler/rustc_builtin_macros/src/concat.rs2
-rw-r--r--compiler/rustc_builtin_macros/src/concat_bytes.rs10
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/clone.rs16
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/decodable.rs20
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/default.rs13
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/encodable.rs8
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/generic/mod.rs48
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/generic/ty.rs9
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/mod.rs6
-rw-r--r--compiler/rustc_builtin_macros/src/env.rs2
-rw-r--r--compiler/rustc_builtin_macros/src/format_foreign.rs34
-rw-r--r--compiler/rustc_builtin_macros/src/global_allocator.rs32
-rw-r--r--compiler/rustc_builtin_macros/src/test.rs92
-rw-r--r--compiler/rustc_builtin_macros/src/test_harness.rs5
-rw-r--r--compiler/rustc_codegen_gcc/src/consts.rs27
-rw-r--r--compiler/rustc_codegen_gcc/src/errors.rs7
-rw-r--r--compiler/rustc_codegen_llvm/src/consts.rs18
-rw-r--r--compiler/rustc_codegen_llvm/src/errors.rs7
-rw-r--r--compiler/rustc_codegen_ssa/src/back/link.rs11
-rw-r--r--compiler/rustc_const_eval/src/const_eval/machine.rs2
-rw-r--r--compiler/rustc_const_eval/src/interpret/eval_context.rs4
-rw-r--r--compiler/rustc_const_eval/src/interpret/machine.rs16
-rw-r--r--compiler/rustc_const_eval/src/interpret/step.rs39
-rw-r--r--compiler/rustc_data_structures/src/fingerprint.rs2
-rw-r--r--compiler/rustc_data_structures/src/intern.rs83
-rw-r--r--compiler/rustc_data_structures/src/sorted_map.rs4
-rw-r--r--compiler/rustc_data_structures/src/sorted_map/index_map.rs9
-rw-r--r--compiler/rustc_data_structures/src/stable_hasher.rs97
-rw-r--r--compiler/rustc_driver/src/lib.rs9
-rw-r--r--compiler/rustc_error_codes/src/error_codes.rs1
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0791.md41
-rw-r--r--compiler/rustc_error_messages/locales/en-US/codegen_gcc.ftl3
-rw-r--r--compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl3
-rw-r--r--compiler/rustc_error_messages/locales/en-US/hir_analysis.ftl5
-rw-r--r--compiler/rustc_error_messages/locales/en-US/parse.ftl3
-rw-r--r--compiler/rustc_expand/src/base.rs2
-rw-r--r--compiler/rustc_expand/src/expand.rs2
-rw-r--r--compiler/rustc_hir/src/hir.rs2
-rw-r--r--compiler/rustc_hir/src/hir_id.rs6
-rw-r--r--compiler/rustc_hir/src/lang_items.rs3
-rw-r--r--compiler/rustc_hir/src/tests.rs38
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/mod.rs1
-rw-r--r--compiler/rustc_hir_analysis/src/check/check.rs35
-rw-r--r--compiler/rustc_hir_analysis/src/check/compare_method.rs51
-rw-r--r--compiler/rustc_hir_analysis/src/collect.rs7
-rw-r--r--compiler/rustc_hir_analysis/src/collect/generics_of.rs16
-rw-r--r--compiler/rustc_hir_analysis/src/errors.rs11
-rw-r--r--compiler/rustc_hir_analysis/src/variance/mod.rs42
-rw-r--r--compiler/rustc_hir_pretty/src/lib.rs13
-rw-r--r--compiler/rustc_hir_typeck/src/check.rs3
-rw-r--r--compiler/rustc_hir_typeck/src/expr.rs3
-rw-r--r--compiler/rustc_hir_typeck/src/expr_use_visitor.rs11
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs13
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs5
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs4
-rw-r--r--compiler/rustc_hir_typeck/src/lib.rs32
-rw-r--r--compiler/rustc_hir_typeck/src/method/suggest.rs23
-rw-r--r--compiler/rustc_incremental/src/persist/fs.rs5
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/mod.rs191
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/note.rs2
-rw-r--r--compiler/rustc_interface/src/passes.rs63
-rw-r--r--compiler/rustc_interface/src/queries.rs35
-rw-r--r--compiler/rustc_interface/src/tests.rs1
-rw-r--r--compiler/rustc_lint/src/builtin.rs2
-rw-r--r--compiler/rustc_lint/src/early.rs107
-rw-r--r--compiler/rustc_lint/src/late.rs44
-rw-r--r--compiler/rustc_lint/src/pass_by_value.rs2
-rw-r--r--compiler/rustc_lint/src/unused.rs31
-rw-r--r--compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp11
-rw-r--r--compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp16
-rw-r--r--compiler/rustc_macros/src/query.rs4
-rw-r--r--compiler/rustc_metadata/src/creader.rs6
-rw-r--r--compiler/rustc_metadata/src/fs.rs9
-rw-r--r--compiler/rustc_middle/src/arena.rs7
-rw-r--r--compiler/rustc_middle/src/middle/codegen_fn_attrs.rs5
-rw-r--r--compiler/rustc_middle/src/mir/interpret/allocation.rs2
-rw-r--r--compiler/rustc_middle/src/mir/syntax.rs2
-rw-r--r--compiler/rustc_middle/src/query/mod.rs2
-rw-r--r--compiler/rustc_middle/src/ty/context.rs135
-rw-r--r--compiler/rustc_middle/src/ty/error.rs31
-rw-r--r--compiler/rustc_middle/src/ty/generics.rs14
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs153
-rw-r--r--compiler/rustc_middle/src/ty/query.rs24
-rw-r--r--compiler/rustc_middle/src/ty/sty.rs15
-rw-r--r--compiler/rustc_middle/src/ty/subst.rs23
-rw-r--r--compiler/rustc_mir_build/src/build/mod.rs20
-rw-r--r--compiler/rustc_mir_build/src/build/scope.rs56
-rw-r--r--compiler/rustc_mir_build/src/thir/cx/expr.rs4
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/mod.rs2
-rw-r--r--compiler/rustc_mir_dataflow/src/value_analysis.rs2
-rw-r--r--compiler/rustc_mir_transform/src/add_retag.rs53
-rw-r--r--compiler/rustc_mir_transform/src/dump_mir.rs6
-rw-r--r--compiler/rustc_mir_transform/src/generator.rs10
-rw-r--r--compiler/rustc_mir_transform/src/inline.rs28
-rw-r--r--compiler/rustc_mir_transform/src/remove_zsts.rs27
-rw-r--r--compiler/rustc_mir_transform/src/shim.rs10
-rw-r--r--compiler/rustc_parse/src/errors.rs8
-rw-r--r--compiler/rustc_parse/src/parser/expr.rs19
-rw-r--r--compiler/rustc_parse/src/parser/item.rs25
-rw-r--r--compiler/rustc_parse/src/parser/mod.rs4
-rw-r--r--compiler/rustc_passes/src/dead.rs6
-rw-r--r--compiler/rustc_passes/src/liveness.rs8
-rw-r--r--compiler/rustc_privacy/src/lib.rs10
-rw-r--r--compiler/rustc_query_system/src/dep_graph/graph.rs15
-rw-r--r--compiler/rustc_resolve/src/late.rs4
-rw-r--r--compiler/rustc_resolve/src/lib.rs2
-rw-r--r--compiler/rustc_save_analysis/src/dump_visitor.rs6
-rw-r--r--compiler/rustc_save_analysis/src/lib.rs8
-rw-r--r--compiler/rustc_session/Cargo.toml1
-rw-r--r--compiler/rustc_session/src/config.rs5
-rw-r--r--compiler/rustc_session/src/errors.rs8
-rw-r--r--compiler/rustc_session/src/options.rs3
-rw-r--r--compiler/rustc_session/src/output.rs29
-rw-r--r--compiler/rustc_session/src/session.rs11
-rw-r--r--compiler/rustc_span/src/def_id.rs10
-rw-r--r--compiler/rustc_span/src/symbol.rs3
-rw-r--r--compiler/rustc_target/src/spec/wasm32_unknown_unknown.rs7
-rw-r--r--compiler/rustc_trait_selection/src/traits/codegen.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/const_evaluatable.rs58
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs98
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/mod.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/project.rs42
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/normalize.rs14
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/mod.rs13
-rw-r--r--compiler/rustc_trait_selection/src/traits/wf.rs19
-rw-r--r--compiler/rustc_type_ir/src/lib.rs2
-rw-r--r--compiler/rustc_type_ir/src/sty.rs582
-rw-r--r--compiler/rustc_type_ir/src/ty_info.rs122
-rw-r--r--config.toml.example10
-rw-r--r--library/core/src/cmp.rs5
-rw-r--r--library/core/src/convert/num.rs2
-rw-r--r--library/core/src/future/mod.rs10
-rw-r--r--library/core/src/iter/sources/repeat_n.rs2
-rw-r--r--library/core/src/num/mod.rs4
-rw-r--r--library/core/src/str/pattern.rs2
-rw-r--r--library/core/src/task/wake.rs1
-rw-r--r--library/std/Cargo.toml2
-rw-r--r--library/std/src/sync/mpmc/array.rs2
-rw-r--r--library/std/src/sync/mpsc/mod.rs12
-rw-r--r--library/std/src/sys/itron/condvar.rs4
-rw-r--r--library/std/src/sys/itron/mutex.rs2
-rw-r--r--library/std/src/sys/itron/thread.rs48
-rw-r--r--library/std/src/sys/solid/io.rs4
-rw-r--r--library/std/src/sys/solid/os.rs3
-rw-r--r--library/std/src/sys/unix/weak.rs37
-rw-r--r--library/std/src/sys/windows/process.rs34
-rw-r--r--library/std/src/thread/scoped.rs2
-rw-r--r--src/bootstrap/builder.rs2
-rw-r--r--src/bootstrap/config.rs3
-rw-r--r--src/bootstrap/flags.rs9
-rw-r--r--src/bootstrap/lib.rs50
-rw-r--r--src/bootstrap/run.rs63
-rw-r--r--src/bootstrap/sanity.rs7
-rw-r--r--src/bootstrap/setup.rs91
-rw-r--r--src/bootstrap/tool.rs2
-rw-r--r--src/ci/docker/host-aarch64/aarch64-gnu/Dockerfile3
-rw-r--r--src/ci/docker/host-x86_64/dist-i686-linux/Dockerfile3
-rwxr-xr-xsrc/ci/docker/host-x86_64/dist-various-2/build-wasi-toolchain.sh8
-rw-r--r--src/ci/docker/host-x86_64/dist-x86_64-freebsd/Dockerfile3
-rw-r--r--src/ci/docker/host-x86_64/dist-x86_64-illumos/Dockerfile3
-rw-r--r--src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile3
-rw-r--r--src/ci/docker/host-x86_64/dist-x86_64-musl/Dockerfile3
-rw-r--r--src/ci/docker/host-x86_64/i686-gnu-nopt/Dockerfile3
-rw-r--r--src/ci/docker/host-x86_64/i686-gnu/Dockerfile3
-rw-r--r--src/ci/docker/host-x86_64/mingw-check/Dockerfile8
-rw-r--r--src/ci/docker/host-x86_64/test-various/Dockerfile3
-rw-r--r--src/ci/docker/host-x86_64/wasm32/Dockerfile3
-rw-r--r--src/ci/docker/host-x86_64/x86_64-gnu-aux/Dockerfile3
-rw-r--r--src/ci/docker/host-x86_64/x86_64-gnu-debug/Dockerfile3
-rw-r--r--src/ci/docker/host-x86_64/x86_64-gnu-distcheck/Dockerfile3
-rw-r--r--src/ci/docker/host-x86_64/x86_64-gnu-llvm-13-stage1/Dockerfile3
-rw-r--r--src/ci/docker/host-x86_64/x86_64-gnu-llvm-13/Dockerfile10
-rw-r--r--src/ci/docker/host-x86_64/x86_64-gnu-nopt/Dockerfile3
-rw-r--r--src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile8
-rw-r--r--src/ci/docker/host-x86_64/x86_64-gnu/Dockerfile3
-rwxr-xr-xsrc/ci/docker/scripts/freebsd-toolchain.sh2
m---------src/doc/book0
m---------src/doc/embedded-book0
m---------src/doc/nomicon0
m---------src/doc/reference0
m---------src/doc/rust-by-example0
m---------src/doc/rustc-dev-guide0
-rw-r--r--src/doc/unstable-book/src/language-features/abi-efiapi.md2
-rw-r--r--src/librustdoc/html/static/css/rustdoc.css24
-rw-r--r--src/librustdoc/html/static/js/scrape-examples.js2
-rw-r--r--src/librustdoc/html/static_files.rs2
m---------src/llvm-project0
-rw-r--r--src/test/mir-opt/inline/cycle.g.Inline.diff23
-rw-r--r--src/test/mir-opt/inline/cycle.main.Inline.diff40
-rw-r--r--src/test/mir-opt/inline/exponential_runtime.main.Inline.diff50
-rw-r--r--src/test/mir-opt/inline/exponential_runtime.rs87
-rw-r--r--src/test/mir-opt/inline/inline_cycle.one.Inline.diff11
-rw-r--r--src/test/mir-opt/inline/inline_cycle.two.Inline.diff23
-rw-r--r--src/test/mir-opt/inline/inline_cycle_generic.main.Inline.diff9
-rw-r--r--src/test/mir-opt/inline/inline_diverging.h.Inline.diff52
-rw-r--r--src/test/mir-opt/inline/inline_retag.bar.Inline.after.mir4
-rw-r--r--src/test/mir-opt/remove_zsts.get_union.PreCodegen.after.mir10
-rw-r--r--src/test/mir-opt/remove_zsts.get_union.RemoveZsts.diff19
-rw-r--r--src/test/mir-opt/remove_zsts.rs14
-rw-r--r--src/test/mir-opt/remove_zsts_dont_touch_unions.get_union.RemoveZsts.after.mir15
-rw-r--r--src/test/mir-opt/remove_zsts_dont_touch_unions.rs19
-rw-r--r--src/test/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.mir10
-rw-r--r--src/test/mir-opt/retag.core.ptr-drop_in_place.Test.SimplifyCfg-make_shim.after.mir1
-rw-r--r--src/test/mir-opt/retag.main-{closure#0}.SimplifyCfg-elaborate-drops.after.mir1
-rw-r--r--src/test/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.mir11
-rw-r--r--src/test/mir-opt/retag.{impl#0}-foo.SimplifyCfg-elaborate-drops.after.mir2
-rw-r--r--src/test/mir-opt/separate_const_switch.identity.SeparateConstSwitch.diff35
-rw-r--r--src/test/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs2
-rw-r--r--src/test/run-make/coverage-reports/Makefile2
-rw-r--r--src/test/rustdoc-gui/enum-variants.goml5
-rw-r--r--src/test/rustdoc-gui/method-margins.goml1
-rw-r--r--src/test/rustdoc-gui/scrape-examples-button-focus.goml13
-rw-r--r--src/test/rustdoc-gui/src/scrape_examples/examples/check.rs1
-rw-r--r--src/test/rustdoc-gui/src/test_docs/lib.rs1
-rw-r--r--src/test/rustdoc-gui/toggle-docs.goml4
-rw-r--r--src/test/rustdoc-ui/z-help.stdout1
-rw-r--r--src/test/ui/associated-inherent-types/issue-104260.rs14
-rw-r--r--src/test/ui/associated-inherent-types/normalize-projection-0.rs22
-rw-r--r--src/test/ui/associated-inherent-types/normalize-projection-1.rs22
-rw-r--r--src/test/ui/async-await/async-await-let-else.drop-tracking.stderr2
-rw-r--r--src/test/ui/async-await/drop-track-bad-field-in-fru.rs10
-rw-r--r--src/test/ui/async-await/drop-track-bad-field-in-fru.stderr23
-rw-r--r--src/test/ui/async-await/in-trait/nested-rpit.rs17
-rw-r--r--src/test/ui/async-await/in-trait/return-type-suggestion.rs14
-rw-r--r--src/test/ui/async-await/in-trait/return-type-suggestion.stderr23
-rw-r--r--src/test/ui/async-await/issue-68112.drop_tracking.stderr2
-rw-r--r--src/test/ui/async-await/issue-68112.no_drop_tracking.stderr2
-rw-r--r--src/test/ui/async-await/issue-69446-fnmut-capture.stderr3
-rw-r--r--src/test/ui/async-await/issue-70935-complex-spans.drop_tracking.stderr2
-rw-r--r--src/test/ui/async-await/partial-drop-partial-reinit.drop_tracking.stderr2
-rw-r--r--src/test/ui/async-await/partial-drop-partial-reinit.no_drop_tracking.stderr2
-rw-r--r--src/test/ui/async-await/track-caller/issue-105134.rs11
-rw-r--r--src/test/ui/async-await/track-caller/panic-track-caller.rs14
-rw-r--r--src/test/ui/auto-traits/bad-generics-on-dyn.rs11
-rw-r--r--src/test/ui/auto-traits/bad-generics-on-dyn.stderr11
-rw-r--r--src/test/ui/binop/binop-mul-i32-f32.stderr11
-rw-r--r--src/test/ui/const-generics/defaults/rp_impl_trait_fail.stderr8
-rw-r--r--src/test/ui/const-generics/defaults/self-referential.rs4
-rw-r--r--src/test/ui/const-generics/defaults/self-referential.stderr11
-rw-r--r--src/test/ui/const-generics/generic_const_exprs/const_kind_expr/wf_obligation.rs22
-rw-r--r--src/test/ui/const-generics/generic_const_exprs/const_kind_expr/wf_obligation.stderr20
-rw-r--r--src/test/ui/const-generics/generic_const_exprs/normed_to_param_is_evaluatable.rs12
-rw-r--r--src/test/ui/consts/const-eval/const-eval-overflow-3b.stderr11
-rw-r--r--src/test/ui/consts/const-eval/const-eval-overflow-4b.stderr11
-rw-r--r--src/test/ui/diagnostic-width/long-E0308.rs86
-rw-r--r--src/test/ui/diagnostic-width/long-E0308.stderr80
-rw-r--r--src/test/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr9
-rw-r--r--src/test/ui/duplicate/duplicate-type-parameter.stderr4
-rw-r--r--src/test/ui/error-codes/E0275.stderr2
-rw-r--r--src/test/ui/feature-gates/feature-gate-impl_trait_in_fn_trait_return.stderr6
-rw-r--r--src/test/ui/feature-gates/feature-gate-linkage.rs2
-rw-r--r--src/test/ui/feature-gates/feature-gate-linkage.stderr2
-rw-r--r--src/test/ui/generic-associated-types/own-bound-span.rs17
-rw-r--r--src/test/ui/generic-associated-types/own-bound-span.stderr15
-rw-r--r--src/test/ui/impl-trait/equality.stderr13
-rw-r--r--src/test/ui/impl-trait/nested-return-type4.rs8
-rw-r--r--src/test/ui/impl-trait/nested-return-type4.stderr20
-rw-r--r--src/test/ui/issues/issue-105330.rs21
-rw-r--r--src/test/ui/issues/issue-105330.stderr109
-rw-r--r--src/test/ui/issues/issue-20413.stderr10
-rw-r--r--src/test/ui/issues/issue-23122-2.stderr2
-rw-r--r--src/test/ui/issues/issue-24352.stderr11
-rw-r--r--src/test/ui/kindck/kindck-copy.stderr22
-rw-r--r--src/test/ui/lexer/lex-bad-char-literals-6.stderr18
-rw-r--r--src/test/ui/linkage-attr/auxiliary/def_external.rs (renamed from src/test/ui/linkage-attr/auxiliary/def_illtyped_external.rs)0
-rw-r--r--src/test/ui/linkage-attr/linkage-import.rs8
-rw-r--r--src/test/ui/linkage-attr/linkage-requires-raw-ptr.rs11
-rw-r--r--src/test/ui/linkage-attr/linkage-requires-raw-ptr.stderr8
-rw-r--r--src/test/ui/linkage-attr/linkage2.rs9
-rw-r--r--src/test/ui/linkage-attr/linkage2.stderr5
-rw-r--r--src/test/ui/lint/issue-104897.rs6
-rw-r--r--src/test/ui/lint/issue-104897.stderr43
-rw-r--r--src/test/ui/macros/syntax-error-recovery.stderr1
-rw-r--r--src/test/ui/maximal_mir_to_hir_coverage.rs10
-rw-r--r--src/test/ui/mismatched_types/binops.stderr13
-rw-r--r--src/test/ui/never_type/issue-13352.stderr13
-rw-r--r--src/test/ui/numbers-arithmetic/not-suggest-float-literal.stderr141
-rw-r--r--src/test/ui/numbers-arithmetic/suggest-float-literal.stderr88
-rw-r--r--src/test/ui/object-safety/object-safety-supertrait-mentions-GAT.stderr6
-rw-r--r--src/test/ui/parser/expr-as-stmt.fixed12
-rw-r--r--src/test/ui/parser/expr-as-stmt.rs12
-rw-r--r--src/test/ui/parser/expr-as-stmt.stderr43
-rw-r--r--src/test/ui/parser/issue-101477-enum.stderr2
-rw-r--r--src/test/ui/parser/issue-103869.rs9
-rw-r--r--src/test/ui/parser/issue-103869.stderr16
-rw-r--r--src/test/ui/parser/issue-105366.fixed12
-rw-r--r--src/test/ui/parser/issue-105366.rs12
-rw-r--r--src/test/ui/parser/issue-105366.stderr13
-rw-r--r--src/test/ui/parser/macro/issue-37113.stderr1
-rw-r--r--src/test/ui/recursion/issue-83150.stderr2
-rw-r--r--src/test/ui/regions/closure-in-projection-issue-97405.rs4
-rw-r--r--src/test/ui/regions/closure-in-projection-issue-97405.stderr20
-rw-r--r--src/test/ui/regions/issue-102374.rs1
-rw-r--r--src/test/ui/regions/issue-102374.stderr5
-rw-r--r--src/test/ui/rfc-1445-restrict-constants-in-patterns/match-requires-both-partialeq-and-eq.rs2
-rw-r--r--src/test/ui/span/multiline-span-simple.stderr13
-rw-r--r--src/test/ui/structs/struct-fn-in-definition.rs1
-rw-r--r--src/test/ui/structs/struct-fn-in-definition.stderr1
-rw-r--r--src/test/ui/structs/unresolved-struct-with-fru.rs12
-rw-r--r--src/test/ui/structs/unresolved-struct-with-fru.stderr9
-rw-r--r--src/test/ui/suggestions/assoc-const-as-fn.stderr6
-rw-r--r--src/test/ui/suggestions/try-removing-the-field.rs15
-rw-r--r--src/test/ui/suggestions/try-removing-the-field.stderr16
-rw-r--r--src/test/ui/trait-bounds/impl-missing-where-clause-lifetimes-from-trait.rs38
-rw-r--r--src/test/ui/trait-bounds/impl-missing-where-clause-lifetimes-from-trait.stderr36
-rw-r--r--src/test/ui/traits/issue-79458.stderr5
-rw-r--r--src/test/ui/traits/issue-91949-hangs-on-recursion.stderr2
-rw-r--r--src/test/ui/try-trait/bad-interconversion.stderr11
-rw-r--r--src/test/ui/type-alias-impl-trait/self-referential-2.stderr11
-rw-r--r--src/test/ui/type-alias-impl-trait/self-referential-4.stderr33
-rw-r--r--src/test/ui/type-alias-impl-trait/self-referential.stderr33
-rw-r--r--src/test/ui/type/type-check-defaults.stderr11
-rw-r--r--src/test/ui/typeck/issue-81293.stderr13
-rw-r--r--src/test/ui/typeck/path-to-method-sugg-unresolved-expr.rs4
-rw-r--r--src/test/ui/typeck/path-to-method-sugg-unresolved-expr.stderr9
-rw-r--r--src/test/ui/ufcs/ufcs-qpath-self-mismatch.stderr22
-rw-r--r--src/tools/collect-license-metadata/Cargo.toml10
-rw-r--r--src/tools/collect-license-metadata/src/licenses.rs65
-rw-r--r--src/tools/collect-license-metadata/src/main.rs30
-rw-r--r--src/tools/collect-license-metadata/src/path_tree.rs294
-rw-r--r--src/tools/collect-license-metadata/src/reuse.rs49
-rw-r--r--src/tools/compiletest/src/header.rs8
-rw-r--r--src/tools/generate-copyright/Cargo.toml11
-rw-r--r--src/tools/generate-copyright/src/main.rs94
-rw-r--r--src/tools/miri/src/borrow_tracker/mod.rs13
-rw-r--r--src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs4
-rw-r--r--src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs369
-rw-r--r--src/tools/miri/src/diagnostics.rs10
-rw-r--r--src/tools/miri/src/machine.rs22
-rw-r--r--triagebot.toml12
357 files changed, 4797 insertions, 3046 deletions
diff --git a/.gitmodules b/.gitmodules
index c8504937806..4011a6fa6b9 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -28,7 +28,7 @@
 [submodule "src/llvm-project"]
 	path = src/llvm-project
 	url = https://github.com/rust-lang/llvm-project.git
-	branch = rustc/15.0-2022-08-09
+	branch = rustc/15.0-2022-12-07
 [submodule "src/doc/embedded-book"]
 	path = src/doc/embedded-book
 	url = https://github.com/rust-embedded/book.git
diff --git a/Cargo.lock b/Cargo.lock
index dae79e5bc26..844cf99b468 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -581,6 +581,7 @@ dependencies = [
  "libc",
  "num-integer",
  "num-traits",
+ "serde",
  "time",
  "winapi",
 ]
@@ -731,6 +732,16 @@ dependencies = [
 ]
 
 [[package]]
+name = "collect-license-metadata"
+version = "0.1.0"
+dependencies = [
+ "anyhow",
+ "serde",
+ "serde_json",
+ "spdx-rs",
+]
+
+[[package]]
 name = "color-eyre"
 version = "0.6.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1553,6 +1564,15 @@ dependencies = [
 ]
 
 [[package]]
+name = "generate-copyright"
+version = "0.1.0"
+dependencies = [
+ "anyhow",
+ "serde",
+ "serde_json",
+]
+
+[[package]]
 name = "generic-array"
 version = "0.14.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2085,9 +2105,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
 
 [[package]]
 name = "libc"
-version = "0.2.135"
+version = "0.2.138"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "68783febc7782c6c5cb401fbda4de5a9898be1762314da0bb2c10ced61f18b0c"
+checksum = "db6d7e329c562c5dfab7a46a2afabc8b987ab9a4834c9d1ca04dc54c1546cef8"
 dependencies = [
  "rustc-std-workspace-core",
 ]
@@ -4328,6 +4348,7 @@ dependencies = [
  "rustc_span",
  "rustc_target",
  "smallvec",
+ "termize",
  "tracing",
  "winapi",
 ]
@@ -4865,6 +4886,35 @@ dependencies = [
 ]
 
 [[package]]
+name = "spdx-expression"
+version = "0.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "53d7ac03c67c572d85049d6db815e20a4a19b41b3d5cca732ac582342021ad77"
+dependencies = [
+ "nom",
+ "serde",
+ "thiserror",
+ "tracing",
+]
+
+[[package]]
+name = "spdx-rs"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b3c02f6eb7e7b4100c272f685a9ccaccaab302324e8c7ec3e2ee72340fb29ff3"
+dependencies = [
+ "chrono",
+ "log",
+ "nom",
+ "serde",
+ "spdx-expression",
+ "strum",
+ "strum_macros",
+ "thiserror",
+ "uuid",
+]
+
+[[package]]
 name = "stable_deref_trait"
 version = "1.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -4968,6 +5018,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
 
 [[package]]
+name = "strum"
+version = "0.24.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "063e6045c0e62079840579a7e47a355ae92f60eb74daaf156fb1e84ba164e63f"
+
+[[package]]
+name = "strum_macros"
+version = "0.24.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59"
+dependencies = [
+ "heck",
+ "proc-macro2",
+ "quote",
+ "rustversion",
+ "syn",
+]
+
+[[package]]
 name = "syn"
 version = "1.0.102"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -5597,6 +5666,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "8772a4ccbb4e89959023bc5b7cb8623a795caa7092d99f3aa9501b9484d4557d"
 
 [[package]]
+name = "uuid"
+version = "0.8.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7"
+dependencies = [
+ "getrandom 0.2.0",
+]
+
+[[package]]
 name = "valuable"
 version = "0.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/Cargo.toml b/Cargo.toml
index 13a98eedde8..000c10a1f90 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -39,6 +39,8 @@ members = [
   "src/tools/bump-stage0",
   "src/tools/replace-version-placeholder",
   "src/tools/lld-wrapper",
+  "src/tools/collect-license-metadata",
+  "src/tools/generate-copyright",
 ]
 
 exclude = [
diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs
index 85693259cd0..e14c9ea9a5d 100644
--- a/compiler/rustc_abi/src/lib.rs
+++ b/compiler/rustc_abi/src/lib.rs
@@ -9,6 +9,8 @@ use std::ops::{Add, AddAssign, Mul, RangeInclusive, Sub};
 use std::str::FromStr;
 
 use bitflags::bitflags;
+#[cfg(feature = "nightly")]
+use rustc_data_structures::stable_hasher::StableOrd;
 use rustc_index::vec::{Idx, IndexVec};
 #[cfg(feature = "nightly")]
 use rustc_macros::HashStable_Generic;
@@ -403,6 +405,11 @@ pub struct Size {
     raw: u64,
 }
 
+// Safety: Ord is implement as just comparing numerical values and numerical values
+// are not changed by (de-)serialization.
+#[cfg(feature = "nightly")]
+unsafe impl StableOrd for Size {}
+
 // This is debug-printed a lot in larger structs, don't waste too much space there
 impl fmt::Debug for Size {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs
index 4260805f1dd..24e2985cf56 100644
--- a/compiler/rustc_ast_lowering/src/expr.rs
+++ b/compiler/rustc_ast_lowering/src/expr.rs
@@ -16,7 +16,7 @@ use rustc_hir::def::Res;
 use rustc_hir::definitions::DefPathData;
 use rustc_session::errors::report_lit_error;
 use rustc_span::source_map::{respan, DesugaringKind, Span, Spanned};
-use rustc_span::symbol::{sym, Ident};
+use rustc_span::symbol::{kw, sym, Ident};
 use rustc_span::DUMMY_SP;
 use thin_vec::thin_vec;
 
@@ -147,6 +147,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 ),
                 ExprKind::Async(capture_clause, closure_node_id, block) => self.make_async_expr(
                     *capture_clause,
+                    None,
                     *closure_node_id,
                     None,
                     e.span,
@@ -435,18 +436,14 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 let lhs = self.lower_cond(lhs);
                 let rhs = self.lower_cond(rhs);
 
-                self.arena.alloc(self.expr(
-                    cond.span,
-                    hir::ExprKind::Binary(op, lhs, rhs),
-                    AttrVec::new(),
-                ))
+                self.arena.alloc(self.expr(cond.span, hir::ExprKind::Binary(op, lhs, rhs)))
             }
             ExprKind::Let(..) => self.lower_expr(cond),
             _ => {
                 let cond = self.lower_expr(cond);
                 let reason = DesugaringKind::CondTemporary;
                 let span_block = self.mark_span_with_reason(reason, cond.span, None);
-                self.expr_drop_temps(span_block, cond, AttrVec::new())
+                self.expr_drop_temps(span_block, cond)
             }
         }
     }
@@ -476,12 +473,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
     ) -> hir::ExprKind<'hir> {
         let lowered_cond = self.with_loop_condition_scope(|t| t.lower_cond(cond));
         let then = self.lower_block_expr(body);
-        let expr_break = self.expr_break(span, AttrVec::new());
+        let expr_break = self.expr_break(span);
         let stmt_break = self.stmt_expr(span, expr_break);
         let else_blk = self.block_all(span, arena_vec![self; stmt_break], None);
-        let else_expr = self.arena.alloc(self.expr_block(else_blk, AttrVec::new()));
+        let else_expr = self.arena.alloc(self.expr_block(else_blk));
         let if_kind = hir::ExprKind::If(lowered_cond, self.arena.alloc(then), Some(else_expr));
-        let if_expr = self.expr(span, if_kind, AttrVec::new());
+        let if_expr = self.expr(span, if_kind);
         let block = self.block_expr(self.arena.alloc(if_expr));
         let span = self.lower_span(span.with_hi(cond.span.hi()));
         let opt_label = self.lower_label(opt_label);
@@ -537,12 +534,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
         expr: &'hir hir::Expr<'hir>,
         overall_span: Span,
     ) -> &'hir hir::Expr<'hir> {
-        let constructor = self.arena.alloc(self.expr_lang_item_path(
-            method_span,
-            lang_item,
-            AttrVec::new(),
-            None,
-        ));
+        let constructor = self.arena.alloc(self.expr_lang_item_path(method_span, lang_item, None));
         self.expr_call(overall_span, constructor, std::slice::from_ref(expr))
     }
 
@@ -584,6 +576,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
     pub(super) fn make_async_expr(
         &mut self,
         capture_clause: CaptureBy,
+        outer_hir_id: Option<hir::HirId>,
         closure_node_id: NodeId,
         ret_ty: Option<hir::FnRetTy<'hir>>,
         span: Span,
@@ -592,14 +585,38 @@ impl<'hir> LoweringContext<'_, 'hir> {
     ) -> hir::ExprKind<'hir> {
         let output = ret_ty.unwrap_or_else(|| hir::FnRetTy::DefaultReturn(self.lower_span(span)));
 
-        // Resume argument type: `ResumeTy`
-        let unstable_span =
-            self.mark_span_with_reason(DesugaringKind::Async, span, self.allow_gen_future.clone());
-        let resume_ty = hir::QPath::LangItem(hir::LangItem::ResumeTy, unstable_span, None);
+        // Resume argument type, which should be `&mut Context<'_>`.
+        // NOTE: Using the `'static` lifetime here is technically cheating.
+        // The `Future::poll` argument really is `&'a mut Context<'b>`, but we cannot
+        // express the fact that we are not storing it across yield-points yet,
+        // and we would thus run into lifetime errors.
+        // See <https://github.com/rust-lang/rust/issues/68923>.
+        // Our lowering makes sure we are not mis-using the `_task_context` input type
+        // in the sense that we are indeed not using it across yield points. We
+        // get a fresh `&mut Context` for each resume / call of `Future::poll`.
+        // This "cheating" was previously done with a `ResumeTy` that contained a raw
+        // pointer, and a `get_context` accessor that pulled the `Context` lifetimes
+        // out of thin air.
+        let context_lifetime_ident = Ident::with_dummy_span(kw::StaticLifetime);
+        let context_lifetime = self.arena.alloc(hir::Lifetime {
+            hir_id: self.next_id(),
+            ident: context_lifetime_ident,
+            res: hir::LifetimeName::Static,
+        });
+        let context_path =
+            hir::QPath::LangItem(hir::LangItem::Context, self.lower_span(span), None);
+        let context_ty = hir::MutTy {
+            ty: self.arena.alloc(hir::Ty {
+                hir_id: self.next_id(),
+                kind: hir::TyKind::Path(context_path),
+                span: self.lower_span(span),
+            }),
+            mutbl: hir::Mutability::Mut,
+        };
         let input_ty = hir::Ty {
             hir_id: self.next_id(),
-            kind: hir::TyKind::Path(resume_ty),
-            span: unstable_span,
+            kind: hir::TyKind::Rptr(context_lifetime, context_ty),
+            span: self.lower_span(span),
         };
 
         // The closure/generator `FnDecl` takes a single (resume) argument of type `input_ty`.
@@ -651,18 +668,17 @@ impl<'hir> LoweringContext<'_, 'hir> {
 
             hir::ExprKind::Closure(c)
         };
-        let parent_has_track_caller = self
-            .attrs
-            .values()
-            .find(|attrs| attrs.into_iter().find(|attr| attr.has_name(sym::track_caller)).is_some())
-            .is_some();
+
+        let track_caller = outer_hir_id
+            .and_then(|id| self.attrs.get(&id.local_id))
+            .map_or(false, |attrs| attrs.into_iter().any(|attr| attr.has_name(sym::track_caller)));
+
+        let hir_id = self.lower_node_id(closure_node_id);
         let unstable_span =
             self.mark_span_with_reason(DesugaringKind::Async, span, self.allow_gen_future.clone());
-
-        let hir_id = if parent_has_track_caller {
-            let generator_hir_id = self.lower_node_id(closure_node_id);
+        if track_caller {
             self.lower_attrs(
-                generator_hir_id,
+                hir_id,
                 &[Attribute {
                     kind: AttrKind::Normal(ptr::P(NormalAttr {
                         item: AttrItem {
@@ -677,10 +693,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                     span: unstable_span,
                 }],
             );
-            generator_hir_id
-        } else {
-            self.lower_node_id(closure_node_id)
-        };
+        }
 
         let generator = hir::Expr { hir_id, kind: generator_kind, span: self.lower_span(span) };
 
@@ -693,12 +706,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
         // E0700 in src/test/ui/self/self_lifetime-async.rs
 
         // `future::identity_future`:
-        let identity_future = self.expr_lang_item_path(
-            unstable_span,
-            hir::LangItem::IdentityFuture,
-            AttrVec::new(),
-            None,
-        );
+        let identity_future =
+            self.expr_lang_item_path(unstable_span, hir::LangItem::IdentityFuture, None);
 
         // `future::identity_future(generator)`:
         hir::ExprKind::Call(self.arena.alloc(identity_future), arena_vec![self; generator])
@@ -710,7 +719,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
     ///     mut __awaitee => loop {
     ///         match unsafe { ::std::future::Future::poll(
     ///             <::std::pin::Pin>::new_unchecked(&mut __awaitee),
-    ///             ::std::future::get_context(task_context),
+    ///             task_context,
     ///         ) } {
     ///             ::std::task::Poll::Ready(result) => break result,
     ///             ::std::task::Poll::Pending => {}
@@ -751,7 +760,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
         // unsafe {
         //     ::std::future::Future::poll(
         //         ::std::pin::Pin::new_unchecked(&mut __awaitee),
-        //         ::std::future::get_context(task_context),
+        //         task_context,
         //     )
         // }
         let poll_expr = {
@@ -769,16 +778,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 arena_vec![self; ref_mut_awaitee],
                 Some(expr_hir_id),
             );
-            let get_context = self.expr_call_lang_item_fn_mut(
-                gen_future_span,
-                hir::LangItem::GetContext,
-                arena_vec![self; task_context],
-                Some(expr_hir_id),
-            );
             let call = self.expr_call_lang_item_fn(
                 span,
                 hir::LangItem::FuturePoll,
-                arena_vec![self; new_unchecked, get_context],
+                arena_vec![self; new_unchecked, task_context],
                 Some(expr_hir_id),
             );
             self.arena.alloc(self.expr_unsafe(call))
@@ -801,7 +804,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
             let break_x = self.with_loop_scope(loop_node_id, move |this| {
                 let expr_break =
                     hir::ExprKind::Break(this.lower_loop_destination(None), Some(x_expr));
-                this.arena.alloc(this.expr(gen_future_span, expr_break, AttrVec::new()))
+                this.arena.alloc(this.expr(gen_future_span, expr_break))
             });
             self.arm(ready_pat, break_x)
         };
@@ -834,17 +837,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
             let yield_expr = self.expr(
                 span,
                 hir::ExprKind::Yield(unit, hir::YieldSource::Await { expr: Some(expr_hir_id) }),
-                AttrVec::new(),
             );
             let yield_expr = self.arena.alloc(yield_expr);
 
             if let Some(task_context_hid) = self.task_context {
                 let lhs = self.expr_ident(span, task_context_ident, task_context_hid);
-                let assign = self.expr(
-                    span,
-                    hir::ExprKind::Assign(lhs, yield_expr, self.lower_span(span)),
-                    AttrVec::new(),
-                );
+                let assign =
+                    self.expr(span, hir::ExprKind::Assign(lhs, yield_expr, self.lower_span(span)));
                 self.stmt_expr(span, assign)
             } else {
                 // Use of `await` outside of an async context. Return `yield_expr` so that we can
@@ -1019,13 +1018,16 @@ impl<'hir> LoweringContext<'_, 'hir> {
 
                 let async_body = this.make_async_expr(
                     capture_clause,
+                    // FIXME(nbdd0121): This should also use a proper HIR id so `#[track_caller]`
+                    // can be applied on async closures as well.
+                    None,
                     inner_closure_id,
                     async_ret_ty,
                     body.span,
                     hir::AsyncGeneratorKind::Closure,
                     |this| this.with_new_scopes(|this| this.lower_expr_mut(body)),
                 );
-                this.expr(fn_decl_span, async_body, AttrVec::new())
+                this.expr(fn_decl_span, async_body)
             });
             body_id
         });
@@ -1285,7 +1287,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
         let ident = self.expr_ident(lhs.span, ident, binding);
         let assign =
             hir::ExprKind::Assign(self.lower_expr(lhs), ident, self.lower_span(eq_sign_span));
-        let expr = self.expr(lhs.span, assign, AttrVec::new());
+        let expr = self.expr(lhs.span, assign);
         assignments.push(self.stmt_expr(lhs.span, expr));
         pat
     }
@@ -1326,8 +1328,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
         let e2 = self.lower_expr_mut(e2);
         let fn_path =
             hir::QPath::LangItem(hir::LangItem::RangeInclusiveNew, self.lower_span(span), None);
-        let fn_expr =
-            self.arena.alloc(self.expr(span, hir::ExprKind::Path(fn_path), AttrVec::new()));
+        let fn_expr = self.arena.alloc(self.expr(span, hir::ExprKind::Path(fn_path)));
         hir::ExprKind::Call(fn_expr, arena_vec![self; e1, e2])
     }
 
@@ -1499,8 +1500,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
 
         // `None => break`
         let none_arm = {
-            let break_expr =
-                self.with_loop_scope(e.id, |this| this.expr_break_alloc(for_span, AttrVec::new()));
+            let break_expr = self.with_loop_scope(e.id, |this| this.expr_break_alloc(for_span));
             let pat = self.pat_none(for_span);
             self.arm(pat, break_expr)
         };
@@ -1509,7 +1509,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
         let some_arm = {
             let some_pat = self.pat_some(pat_span, pat);
             let body_block = self.with_loop_scope(e.id, |this| this.lower_block(body, false));
-            let body_expr = self.arena.alloc(self.expr_block(body_block, AttrVec::new()));
+            let body_expr = self.arena.alloc(self.expr_block(body_block));
             self.arm(some_pat, body_expr)
         };
 
@@ -1572,7 +1572,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
         // surrounding scope of the `match` since the `match` is not a terminating scope.
         //
         // Also, add the attributes to the outer returned expr node.
-        self.expr_drop_temps_mut(for_span, match_expr, e.attrs.clone())
+        let expr = self.expr_drop_temps_mut(for_span, match_expr);
+        self.lower_attrs(expr.hir_id, &e.attrs);
+        expr
     }
 
     /// Desugar `ExprKind::Try` from: `<expr>?` into:
@@ -1627,12 +1629,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
         let continue_arm = {
             let val_ident = Ident::with_dummy_span(sym::val);
             let (val_pat, val_pat_nid) = self.pat_ident(span, val_ident);
-            let val_expr = self.arena.alloc(self.expr_ident_with_attrs(
-                span,
-                val_ident,
-                val_pat_nid,
-                attrs.clone(),
-            ));
+            let val_expr = self.expr_ident(span, val_ident, val_pat_nid);
+            self.lower_attrs(val_expr.hir_id, &attrs);
             let continue_pat = self.pat_cf_continue(unstable_span, val_pat);
             self.arm(continue_pat, val_expr)
         };
@@ -1658,15 +1656,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
                         hir::Destination { label: None, target_id },
                         Some(from_residual_expr),
                     ),
-                    attrs,
                 ))
             } else {
-                self.arena.alloc(self.expr(
-                    try_span,
-                    hir::ExprKind::Ret(Some(from_residual_expr)),
-                    attrs,
-                ))
+                self.arena.alloc(self.expr(try_span, hir::ExprKind::Ret(Some(from_residual_expr))))
             };
+            self.lower_attrs(ret_expr.hir_id, &attrs);
 
             let break_pat = self.pat_cf_break(try_span, residual_local);
             self.arm(break_pat, ret_expr)
@@ -1731,18 +1725,16 @@ impl<'hir> LoweringContext<'_, 'hir> {
         &mut self,
         span: Span,
         expr: &'hir hir::Expr<'hir>,
-        attrs: AttrVec,
     ) -> &'hir hir::Expr<'hir> {
-        self.arena.alloc(self.expr_drop_temps_mut(span, expr, attrs))
+        self.arena.alloc(self.expr_drop_temps_mut(span, expr))
     }
 
     pub(super) fn expr_drop_temps_mut(
         &mut self,
         span: Span,
         expr: &'hir hir::Expr<'hir>,
-        attrs: AttrVec,
     ) -> hir::Expr<'hir> {
-        self.expr(span, hir::ExprKind::DropTemps(expr), attrs)
+        self.expr(span, hir::ExprKind::DropTemps(expr))
     }
 
     fn expr_match(
@@ -1752,29 +1744,25 @@ impl<'hir> LoweringContext<'_, 'hir> {
         arms: &'hir [hir::Arm<'hir>],
         source: hir::MatchSource,
     ) -> hir::Expr<'hir> {
-        self.expr(span, hir::ExprKind::Match(arg, arms, source), AttrVec::new())
+        self.expr(span, hir::ExprKind::Match(arg, arms, source))
     }
 
-    fn expr_break(&mut self, span: Span, attrs: AttrVec) -> hir::Expr<'hir> {
+    fn expr_break(&mut self, span: Span) -> hir::Expr<'hir> {
         let expr_break = hir::ExprKind::Break(self.lower_loop_destination(None), None);
-        self.expr(span, expr_break, attrs)
+        self.expr(span, expr_break)
     }
 
-    fn expr_break_alloc(&mut self, span: Span, attrs: AttrVec) -> &'hir hir::Expr<'hir> {
-        let expr_break = self.expr_break(span, attrs);
+    fn expr_break_alloc(&mut self, span: Span) -> &'hir hir::Expr<'hir> {
+        let expr_break = self.expr_break(span);
         self.arena.alloc(expr_break)
     }
 
     fn expr_mut_addr_of(&mut self, span: Span, e: &'hir hir::Expr<'hir>) -> hir::Expr<'hir> {
-        self.expr(
-            span,
-            hir::ExprKind::AddrOf(hir::BorrowKind::Ref, hir::Mutability::Mut, e),
-            AttrVec::new(),
-        )
+        self.expr(span, hir::ExprKind::AddrOf(hir::BorrowKind::Ref, hir::Mutability::Mut, e))
     }
 
     fn expr_unit(&mut self, sp: Span) -> &'hir hir::Expr<'hir> {
-        self.arena.alloc(self.expr(sp, hir::ExprKind::Tup(&[]), AttrVec::new()))
+        self.arena.alloc(self.expr(sp, hir::ExprKind::Tup(&[])))
     }
 
     fn expr_call_mut(
@@ -1783,7 +1771,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
         e: &'hir hir::Expr<'hir>,
         args: &'hir [hir::Expr<'hir>],
     ) -> hir::Expr<'hir> {
-        self.expr(span, hir::ExprKind::Call(e, args), AttrVec::new())
+        self.expr(span, hir::ExprKind::Call(e, args))
     }
 
     fn expr_call(
@@ -1802,8 +1790,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
         args: &'hir [hir::Expr<'hir>],
         hir_id: Option<hir::HirId>,
     ) -> hir::Expr<'hir> {
-        let path =
-            self.arena.alloc(self.expr_lang_item_path(span, lang_item, AttrVec::new(), hir_id));
+        let path = self.arena.alloc(self.expr_lang_item_path(span, lang_item, hir_id));
         self.expr_call_mut(span, path, args)
     }
 
@@ -1821,13 +1808,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
         &mut self,
         span: Span,
         lang_item: hir::LangItem,
-        attrs: AttrVec,
         hir_id: Option<hir::HirId>,
     ) -> hir::Expr<'hir> {
         self.expr(
             span,
             hir::ExprKind::Path(hir::QPath::LangItem(lang_item, self.lower_span(span), hir_id)),
-            attrs,
         )
     }
 
@@ -1842,19 +1827,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
 
     pub(super) fn expr_ident_mut(
         &mut self,
-        sp: Span,
-        ident: Ident,
-        binding: hir::HirId,
-    ) -> hir::Expr<'hir> {
-        self.expr_ident_with_attrs(sp, ident, binding, AttrVec::new())
-    }
-
-    fn expr_ident_with_attrs(
-        &mut self,
         span: Span,
         ident: Ident,
         binding: hir::HirId,
-        attrs: AttrVec,
     ) -> hir::Expr<'hir> {
         let hir_id = self.next_id();
         let res = Res::Local(binding);
@@ -1867,7 +1842,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
             }),
         ));
 
-        self.expr(span, expr_path, attrs)
+        self.expr(span, expr_path)
     }
 
     fn expr_unsafe(&mut self, expr: &'hir hir::Expr<'hir>) -> hir::Expr<'hir> {
@@ -1886,32 +1861,21 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 }),
                 None,
             ),
-            AttrVec::new(),
         )
     }
 
     fn expr_block_empty(&mut self, span: Span) -> &'hir hir::Expr<'hir> {
         let blk = self.block_all(span, &[], None);
-        let expr = self.expr_block(blk, AttrVec::new());
+        let expr = self.expr_block(blk);
         self.arena.alloc(expr)
     }
 
-    pub(super) fn expr_block(
-        &mut self,
-        b: &'hir hir::Block<'hir>,
-        attrs: AttrVec,
-    ) -> hir::Expr<'hir> {
-        self.expr(b.span, hir::ExprKind::Block(b, None), attrs)
+    pub(super) fn expr_block(&mut self, b: &'hir hir::Block<'hir>) -> hir::Expr<'hir> {
+        self.expr(b.span, hir::ExprKind::Block(b, None))
     }
 
-    pub(super) fn expr(
-        &mut self,
-        span: Span,
-        kind: hir::ExprKind<'hir>,
-        attrs: AttrVec,
-    ) -> hir::Expr<'hir> {
+    pub(super) fn expr(&mut self, span: Span, kind: hir::ExprKind<'hir>) -> hir::Expr<'hir> {
         let hir_id = self.next_id();
-        self.lower_attrs(hir_id, &attrs);
         hir::Expr { hir_id, kind, span: self.lower_span(span) }
     }
 
diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs
index f6275433fc5..d73d6d3918e 100644
--- a/compiler/rustc_ast_lowering/src/item.rs
+++ b/compiler/rustc_ast_lowering/src/item.rs
@@ -253,8 +253,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
                     // only cares about the input argument patterns in the function
                     // declaration (decl), not the return types.
                     let asyncness = header.asyncness;
-                    let body_id =
-                        this.lower_maybe_async_body(span, &decl, asyncness, body.as_deref());
+                    let body_id = this.lower_maybe_async_body(
+                        span,
+                        hir_id,
+                        &decl,
+                        asyncness,
+                        body.as_deref(),
+                    );
 
                     let mut itctx = ImplTraitContext::Universal;
                     let (generics, decl) = this.lower_generics(generics, id, &mut itctx, |this| {
@@ -701,6 +706,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
 
     fn lower_trait_item(&mut self, i: &AssocItem) -> &'hir hir::TraitItem<'hir> {
         let hir_id = self.lower_node_id(i.id);
+        self.lower_attrs(hir_id, &i.attrs);
         let trait_item_def_id = hir_id.expect_owner();
 
         let (generics, kind, has_default) = match &i.kind {
@@ -724,7 +730,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
             AssocItemKind::Fn(box Fn { sig, generics, body: Some(body), .. }) => {
                 let asyncness = sig.header.asyncness;
                 let body_id =
-                    self.lower_maybe_async_body(i.span, &sig.decl, asyncness, Some(&body));
+                    self.lower_maybe_async_body(i.span, hir_id, &sig.decl, asyncness, Some(&body));
                 let (generics, sig) = self.lower_method_sig(
                     generics,
                     sig,
@@ -759,7 +765,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
             AssocItemKind::MacCall(..) => panic!("macro item shouldn't exist at this point"),
         };
 
-        self.lower_attrs(hir_id, &i.attrs);
         let item = hir::TraitItem {
             owner_id: trait_item_def_id,
             ident: self.lower_ident(i.ident),
@@ -791,13 +796,15 @@ impl<'hir> LoweringContext<'_, 'hir> {
 
     /// Construct `ExprKind::Err` for the given `span`.
     pub(crate) fn expr_err(&mut self, span: Span) -> hir::Expr<'hir> {
-        self.expr(span, hir::ExprKind::Err, AttrVec::new())
+        self.expr(span, hir::ExprKind::Err)
     }
 
     fn lower_impl_item(&mut self, i: &AssocItem) -> &'hir hir::ImplItem<'hir> {
         // Since `default impl` is not yet implemented, this is always true in impls.
         let has_value = true;
         let (defaultness, _) = self.lower_defaultness(i.kind.defaultness(), has_value);
+        let hir_id = self.lower_node_id(i.id);
+        self.lower_attrs(hir_id, &i.attrs);
 
         let (generics, kind) = match &i.kind {
             AssocItemKind::Const(_, ty, expr) => {
@@ -810,8 +817,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
             AssocItemKind::Fn(box Fn { sig, generics, body, .. }) => {
                 self.current_item = Some(i.span);
                 let asyncness = sig.header.asyncness;
-                let body_id =
-                    self.lower_maybe_async_body(i.span, &sig.decl, asyncness, body.as_deref());
+                let body_id = self.lower_maybe_async_body(
+                    i.span,
+                    hir_id,
+                    &sig.decl,
+                    asyncness,
+                    body.as_deref(),
+                );
                 let (generics, sig) = self.lower_method_sig(
                     generics,
                     sig,
@@ -844,8 +856,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
             AssocItemKind::MacCall(..) => panic!("`TyMac` should have been expanded by now"),
         };
 
-        let hir_id = self.lower_node_id(i.id);
-        self.lower_attrs(hir_id, &i.attrs);
         let item = hir::ImplItem {
             owner_id: hir_id.expect_owner(),
             ident: self.lower_ident(i.ident),
@@ -978,6 +988,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
     fn lower_maybe_async_body(
         &mut self,
         span: Span,
+        fn_id: hir::HirId,
         decl: &FnDecl,
         asyncness: Async,
         body: Option<&Block>,
@@ -1128,6 +1139,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
 
             let async_expr = this.make_async_expr(
                 CaptureBy::Value,
+                Some(fn_id),
                 closure_id,
                 None,
                 body.span,
@@ -1139,11 +1151,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
                     // Transform into `drop-temps { <user-body> }`, an expression:
                     let desugared_span =
                         this.mark_span_with_reason(DesugaringKind::Async, user_body.span, None);
-                    let user_body = this.expr_drop_temps(
-                        desugared_span,
-                        this.arena.alloc(user_body),
-                        AttrVec::new(),
-                    );
+                    let user_body =
+                        this.expr_drop_temps(desugared_span, this.arena.alloc(user_body));
 
                     // As noted above, create the final block like
                     //
@@ -1160,14 +1169,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
                         Some(user_body),
                     );
 
-                    this.expr_block(body, AttrVec::new())
+                    this.expr_block(body)
                 },
             );
 
-            (
-                this.arena.alloc_from_iter(parameters),
-                this.expr(body.span, async_expr, AttrVec::new()),
-            )
+            (this.arena.alloc_from_iter(parameters), this.expr(body.span, async_expr))
         })
     }
 
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index 0258f8fd2d9..4fa18907fcd 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -259,6 +259,8 @@ enum ImplTraitContext {
     },
     /// Impl trait in type aliases.
     TypeAliasesOpaqueTy,
+    /// `impl Trait` is unstably accepted in this position.
+    FeatureGated(ImplTraitPosition, Symbol),
     /// `impl Trait` is not accepted in this position.
     Disallowed(ImplTraitPosition),
 }
@@ -1372,17 +1374,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                         }
                         path
                     }
-                    ImplTraitContext::Disallowed(
-                        position @ (ImplTraitPosition::TraitReturn | ImplTraitPosition::ImplReturn),
-                    ) => {
+                    ImplTraitContext::FeatureGated(position, feature) => {
                         self.tcx
                             .sess
                             .create_feature_err(
                                 MisplacedImplTrait {
                                     span: t.span,
-                                    position: DiagnosticArgFromDisplay(&position),
+                                    position: DiagnosticArgFromDisplay(position),
                                 },
-                                sym::return_position_impl_trait_in_trait,
+                                *feature,
                             )
                             .emit();
                         hir::TyKind::Err
@@ -1390,7 +1390,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                     ImplTraitContext::Disallowed(position) => {
                         self.tcx.sess.emit_err(MisplacedImplTrait {
                             span: t.span,
-                            position: DiagnosticArgFromDisplay(&position),
+                            position: DiagnosticArgFromDisplay(position),
                         });
                         hir::TyKind::Err
                     }
@@ -1739,14 +1739,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         } else {
             match &decl.output {
                 FnRetTy::Ty(ty) => {
-                    let mut context = if kind.return_impl_trait_allowed(self.tcx) {
+                    let context = if kind.return_impl_trait_allowed(self.tcx) {
                         let fn_def_id = self.local_def_id(fn_node_id);
                         ImplTraitContext::ReturnPositionOpaqueTy {
                             origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id),
                             in_trait: matches!(kind, FnDeclKind::Trait),
                         }
                     } else {
-                        ImplTraitContext::Disallowed(match kind {
+                        let position = match kind {
                             FnDeclKind::Fn | FnDeclKind::Inherent => {
                                 unreachable!("fn should allow in-band lifetimes")
                             }
@@ -1755,9 +1755,16 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                             FnDeclKind::Pointer => ImplTraitPosition::PointerReturn,
                             FnDeclKind::Trait => ImplTraitPosition::TraitReturn,
                             FnDeclKind::Impl => ImplTraitPosition::ImplReturn,
-                        })
+                        };
+                        match kind {
+                            FnDeclKind::Trait | FnDeclKind::Impl => ImplTraitContext::FeatureGated(
+                                position,
+                                sym::return_position_impl_trait_in_trait,
+                            ),
+                            _ => ImplTraitContext::Disallowed(position),
+                        }
                     };
-                    hir::FnRetTy::Return(self.lower_ty(ty, &mut context))
+                    hir::FnRetTy::Return(self.lower_ty(ty, &context))
                 }
                 FnRetTy::Default(span) => hir::FnRetTy::DefaultReturn(self.lower_span(*span)),
             }
@@ -1938,7 +1945,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                     output,
                     span,
                     if in_trait && !this.tcx.features().return_position_impl_trait_in_trait {
-                        ImplTraitContext::Disallowed(ImplTraitPosition::TraitReturn)
+                        ImplTraitContext::FeatureGated(
+                            ImplTraitPosition::TraitReturn,
+                            sym::return_position_impl_trait_in_trait,
+                        )
                     } else {
                         ImplTraitContext::ReturnPositionOpaqueTy {
                             origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id),
@@ -2291,7 +2301,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
     /// has no attributes and is not targeted by a `break`.
     fn lower_block_expr(&mut self, b: &Block) -> hir::Expr<'hir> {
         let block = self.lower_block(b, false);
-        self.expr_block(block, AttrVec::new())
+        self.expr_block(block)
     }
 
     fn lower_array_length(&mut self, c: &AnonConst) -> hir::ArrayLen {
diff --git a/compiler/rustc_ast_lowering/src/path.rs b/compiler/rustc_ast_lowering/src/path.rs
index 8d23c26e603..592fc5aa645 100644
--- a/compiler/rustc_ast_lowering/src/path.rs
+++ b/compiler/rustc_ast_lowering/src/path.rs
@@ -9,7 +9,7 @@ use rustc_ast::{self as ast, *};
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, PartialRes, Res};
 use rustc_hir::GenericArg;
-use rustc_span::symbol::{kw, Ident};
+use rustc_span::symbol::{kw, sym, Ident};
 use rustc_span::{BytePos, Span, DUMMY_SP};
 
 use smallvec::{smallvec, SmallVec};
@@ -352,11 +352,18 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             // fn f(_: impl Fn() -> impl Debug) -> impl Fn() -> impl Debug
             // //      disallowed --^^^^^^^^^^        allowed --^^^^^^^^^^
             // ```
-            FnRetTy::Ty(ty)
-                if matches!(itctx, ImplTraitContext::ReturnPositionOpaqueTy { .. })
-                    && self.tcx.features().impl_trait_in_fn_trait_return =>
-            {
-                self.lower_ty(&ty, itctx)
+            FnRetTy::Ty(ty) if matches!(itctx, ImplTraitContext::ReturnPositionOpaqueTy { .. }) => {
+                if self.tcx.features().impl_trait_in_fn_trait_return {
+                    self.lower_ty(&ty, itctx)
+                } else {
+                    self.lower_ty(
+                        &ty,
+                        &ImplTraitContext::FeatureGated(
+                            ImplTraitPosition::FnTraitReturn,
+                            sym::impl_trait_in_fn_trait_return,
+                        ),
+                    )
+                }
             }
             FnRetTy::Ty(ty) => {
                 self.lower_ty(&ty, &ImplTraitContext::Disallowed(ImplTraitPosition::FnTraitReturn))
diff --git a/compiler/rustc_ast_pretty/src/pprust/state/item.rs b/compiler/rustc_ast_pretty/src/pprust/state/item.rs
index e68a7b3f202..5b6a07721e2 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state/item.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state/item.rs
@@ -348,21 +348,10 @@ impl<'a> State<'a> {
                 self.head(visibility_qualified(&item.vis, "trait"));
                 self.print_ident(item.ident);
                 self.print_generic_params(&generics.params);
-                let mut real_bounds = Vec::with_capacity(bounds.len());
-                // FIXME(durka) this seems to be some quite outdated syntax
-                for b in bounds.iter() {
-                    if let GenericBound::Trait(ptr, ast::TraitBoundModifier::Maybe) = b {
-                        self.space();
-                        self.word_space("for ?");
-                        self.print_trait_ref(&ptr.trait_ref);
-                    } else {
-                        real_bounds.push(b.clone());
-                    }
-                }
                 self.nbsp();
-                if !real_bounds.is_empty() {
+                if !bounds.is_empty() {
                     self.word_nbsp("=");
-                    self.print_type_bounds(&real_bounds);
+                    self.print_type_bounds(&bounds);
                 }
                 self.print_where_clause(&generics.where_clause);
                 self.word(";");
diff --git a/compiler/rustc_attr/src/builtin.rs b/compiler/rustc_attr/src/builtin.rs
index 13b48d8f89a..ab5e19050ea 100644
--- a/compiler/rustc_attr/src/builtin.rs
+++ b/compiler/rustc_attr/src/builtin.rs
@@ -277,8 +277,7 @@ where
             allowed_through_unstable_modules = true;
         }
         // attributes with data
-        else if let Some(MetaItem { kind: MetaItemKind::List(ref metas), .. }) = meta {
-            let meta = meta.as_ref().unwrap();
+        else if let Some(meta @ MetaItem { kind: MetaItemKind::List(metas), .. }) = &meta {
             let get = |meta: &MetaItem, item: &mut Option<Symbol>| {
                 if item.is_some() {
                     handle_errors(
@@ -533,25 +532,24 @@ where
 
     // Merge the const-unstable info into the stability info
     if promotable {
-        if let Some((ref mut stab, _)) = const_stab {
-            stab.promotable = promotable;
-        } else {
-            sess.emit_err(session_diagnostics::RustcPromotablePairing { span: item_sp });
+        match &mut const_stab {
+            Some((stab, _)) => stab.promotable = promotable,
+            _ => _ = sess.emit_err(session_diagnostics::RustcPromotablePairing { span: item_sp }),
         }
     }
 
     if allowed_through_unstable_modules {
-        if let Some((
-            Stability {
-                level: StabilityLevel::Stable { ref mut allowed_through_unstable_modules, .. },
-                ..
-            },
-            _,
-        )) = stab
-        {
-            *allowed_through_unstable_modules = true;
-        } else {
-            sess.emit_err(session_diagnostics::RustcAllowedUnstablePairing { span: item_sp });
+        match &mut stab {
+            Some((
+                Stability {
+                    level: StabilityLevel::Stable { allowed_through_unstable_modules, .. },
+                    ..
+                },
+                _,
+            )) => *allowed_through_unstable_modules = true,
+            _ => {
+                sess.emit_err(session_diagnostics::RustcAllowedUnstablePairing { span: item_sp });
+            }
         }
     }
 
@@ -654,8 +652,8 @@ pub fn eval_condition(
     features: Option<&Features>,
     eval: &mut impl FnMut(Condition) -> bool,
 ) -> bool {
-    match cfg.kind {
-        ast::MetaItemKind::List(ref mis) if cfg.name_or_empty() == sym::version => {
+    match &cfg.kind {
+        ast::MetaItemKind::List(mis) if cfg.name_or_empty() == sym::version => {
             try_gate_cfg(sym::version, cfg.span, sess, features);
             let (min_version, span) = match &mis[..] {
                 [NestedMetaItem::Lit(MetaItemLit { kind: LitKind::Str(sym, ..), span, .. })] => {
@@ -688,7 +686,7 @@ pub fn eval_condition(
                 rustc_version >= min_version
             }
         }
-        ast::MetaItemKind::List(ref mis) => {
+        ast::MetaItemKind::List(mis) => {
             for mi in mis.iter() {
                 if !mi.is_meta_item() {
                     handle_errors(
@@ -759,7 +757,7 @@ pub fn eval_condition(
             sess.emit_err(session_diagnostics::CfgPredicateIdentifier { span: cfg.path.span });
             true
         }
-        MetaItemKind::NameValue(ref lit) if !lit.kind.is_str() => {
+        MetaItemKind::NameValue(lit) if !lit.kind.is_str() => {
             handle_errors(
                 sess,
                 lit.span,
@@ -1036,52 +1034,58 @@ pub fn parse_repr_attr(sess: &Session, attr: &Attribute) -> Vec<ReprAttr> {
                     });
                 }
             } else if let Some(meta_item) = item.meta_item() {
-                if let MetaItemKind::NameValue(ref value) = meta_item.kind {
-                    if meta_item.has_name(sym::align) || meta_item.has_name(sym::packed) {
-                        let name = meta_item.name_or_empty().to_ident_string();
-                        recognised = true;
-                        sess.emit_err(session_diagnostics::IncorrectReprFormatGeneric {
-                            span: item.span(),
-                            repr_arg: &name,
-                            cause: IncorrectReprFormatGenericCause::from_lit_kind(
-                                item.span(),
-                                &value.kind,
-                                &name,
-                            ),
-                        });
-                    } else if matches!(
-                        meta_item.name_or_empty(),
-                        sym::C | sym::simd | sym::transparent
-                    ) || int_type_of_word(meta_item.name_or_empty()).is_some()
-                    {
-                        recognised = true;
-                        sess.emit_err(session_diagnostics::InvalidReprHintNoValue {
-                            span: meta_item.span,
-                            name: meta_item.name_or_empty().to_ident_string(),
-                        });
+                match &meta_item.kind {
+                    MetaItemKind::NameValue(value) => {
+                        if meta_item.has_name(sym::align) || meta_item.has_name(sym::packed) {
+                            let name = meta_item.name_or_empty().to_ident_string();
+                            recognised = true;
+                            sess.emit_err(session_diagnostics::IncorrectReprFormatGeneric {
+                                span: item.span(),
+                                repr_arg: &name,
+                                cause: IncorrectReprFormatGenericCause::from_lit_kind(
+                                    item.span(),
+                                    &value.kind,
+                                    &name,
+                                ),
+                            });
+                        } else if matches!(
+                            meta_item.name_or_empty(),
+                            sym::C | sym::simd | sym::transparent
+                        ) || int_type_of_word(meta_item.name_or_empty()).is_some()
+                        {
+                            recognised = true;
+                            sess.emit_err(session_diagnostics::InvalidReprHintNoValue {
+                                span: meta_item.span,
+                                name: meta_item.name_or_empty().to_ident_string(),
+                            });
+                        }
                     }
-                } else if let MetaItemKind::List(_) = meta_item.kind {
-                    if meta_item.has_name(sym::align) {
-                        recognised = true;
-                        sess.emit_err(session_diagnostics::IncorrectReprFormatAlignOneArg {
-                            span: meta_item.span,
-                        });
-                    } else if meta_item.has_name(sym::packed) {
-                        recognised = true;
-                        sess.emit_err(session_diagnostics::IncorrectReprFormatPackedOneOrZeroArg {
-                            span: meta_item.span,
-                        });
-                    } else if matches!(
-                        meta_item.name_or_empty(),
-                        sym::C | sym::simd | sym::transparent
-                    ) || int_type_of_word(meta_item.name_or_empty()).is_some()
-                    {
-                        recognised = true;
-                        sess.emit_err(session_diagnostics::InvalidReprHintNoParen {
-                            span: meta_item.span,
-                            name: meta_item.name_or_empty().to_ident_string(),
-                        });
+                    MetaItemKind::List(_) => {
+                        if meta_item.has_name(sym::align) {
+                            recognised = true;
+                            sess.emit_err(session_diagnostics::IncorrectReprFormatAlignOneArg {
+                                span: meta_item.span,
+                            });
+                        } else if meta_item.has_name(sym::packed) {
+                            recognised = true;
+                            sess.emit_err(
+                                session_diagnostics::IncorrectReprFormatPackedOneOrZeroArg {
+                                    span: meta_item.span,
+                                },
+                            );
+                        } else if matches!(
+                            meta_item.name_or_empty(),
+                            sym::C | sym::simd | sym::transparent
+                        ) || int_type_of_word(meta_item.name_or_empty()).is_some()
+                        {
+                            recognised = true;
+                            sess.emit_err(session_diagnostics::InvalidReprHintNoParen {
+                                span: meta_item.span,
+                                name: meta_item.name_or_empty().to_ident_string(),
+                            });
+                        }
                     }
+                    _ => (),
                 }
             }
             if !recognised {
diff --git a/compiler/rustc_borrowck/src/borrow_set.rs b/compiler/rustc_borrowck/src/borrow_set.rs
index 563ff056ae4..5bb92a35826 100644
--- a/compiler/rustc_borrowck/src/borrow_set.rs
+++ b/compiler/rustc_borrowck/src/borrow_set.rs
@@ -198,7 +198,7 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherBorrows<'a, 'tcx> {
         rvalue: &mir::Rvalue<'tcx>,
         location: mir::Location,
     ) {
-        if let mir::Rvalue::Ref(region, kind, ref borrowed_place) = *rvalue {
+        if let &mir::Rvalue::Ref(region, kind, borrowed_place) = rvalue {
             if borrowed_place.ignore_borrow(self.tcx, self.body, &self.locals_state_at_exit) {
                 debug!("ignoring_borrow of {:?}", borrowed_place);
                 return;
@@ -211,7 +211,7 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherBorrows<'a, 'tcx> {
                 region,
                 reserve_location: location,
                 activation_location: TwoPhaseActivation::NotTwoPhase,
-                borrowed_place: *borrowed_place,
+                borrowed_place,
                 assigned_place: *assigned_place,
             };
             let (idx, _) = self.location_map.insert_full(location, borrow);
@@ -273,14 +273,14 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherBorrows<'a, 'tcx> {
     }
 
     fn visit_rvalue(&mut self, rvalue: &mir::Rvalue<'tcx>, location: mir::Location) {
-        if let mir::Rvalue::Ref(region, kind, ref place) = *rvalue {
+        if let &mir::Rvalue::Ref(region, kind, place) = rvalue {
             // double-check that we already registered a BorrowData for this
 
             let borrow_data = &self.location_map[&location];
             assert_eq!(borrow_data.reserve_location, location);
             assert_eq!(borrow_data.kind, kind);
             assert_eq!(borrow_data.region, region.to_region_vid());
-            assert_eq!(borrow_data.borrowed_place, *place);
+            assert_eq!(borrow_data.borrowed_place, place);
         }
 
         self.super_rvalue(rvalue, location)
diff --git a/compiler/rustc_borrowck/src/dataflow.rs b/compiler/rustc_borrowck/src/dataflow.rs
index 8070c0e6710..f825b1d8f70 100644
--- a/compiler/rustc_borrowck/src/dataflow.rs
+++ b/compiler/rustc_borrowck/src/dataflow.rs
@@ -358,9 +358,9 @@ impl<'tcx> rustc_mir_dataflow::GenKillAnalysis<'tcx> for Borrows<'_, 'tcx> {
         stmt: &mir::Statement<'tcx>,
         location: Location,
     ) {
-        match stmt.kind {
-            mir::StatementKind::Assign(box (lhs, ref rhs)) => {
-                if let mir::Rvalue::Ref(_, _, place) = *rhs {
+        match &stmt.kind {
+            mir::StatementKind::Assign(box (lhs, rhs)) => {
+                if let mir::Rvalue::Ref(_, _, place) = rhs {
                     if place.ignore_borrow(
                         self.tcx,
                         self.body,
@@ -377,13 +377,13 @@ impl<'tcx> rustc_mir_dataflow::GenKillAnalysis<'tcx> for Borrows<'_, 'tcx> {
 
                 // Make sure there are no remaining borrows for variables
                 // that are assigned over.
-                self.kill_borrows_on_place(trans, lhs);
+                self.kill_borrows_on_place(trans, *lhs);
             }
 
             mir::StatementKind::StorageDead(local) => {
                 // Make sure there are no remaining borrows for locals that
                 // are gone out of scope.
-                self.kill_borrows_on_place(trans, Place::from(local));
+                self.kill_borrows_on_place(trans, Place::from(*local));
             }
 
             mir::StatementKind::FakeRead(..)
diff --git a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs
index e05566dc2c7..1550958ab8e 100644
--- a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs
@@ -243,9 +243,9 @@ impl<'tcx> TypeOpInfo<'tcx> for PredicateQuery<'tcx> {
         placeholder_region: ty::Region<'tcx>,
         error_region: Option<ty::Region<'tcx>>,
     ) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> {
-        let (ref infcx, key, _) =
+        let (infcx, key, _) =
             mbcx.infcx.tcx.infer_ctxt().build_with_canonical(cause.span, &self.canonical_query);
-        let ocx = ObligationCtxt::new(infcx);
+        let ocx = ObligationCtxt::new(&infcx);
         type_op_prove_predicate_with_cause(&ocx, key, cause);
         try_extract_error_from_fulfill_cx(&ocx, placeholder_region, error_region)
     }
@@ -284,9 +284,9 @@ where
         placeholder_region: ty::Region<'tcx>,
         error_region: Option<ty::Region<'tcx>>,
     ) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> {
-        let (ref infcx, key, _) =
+        let (infcx, key, _) =
             mbcx.infcx.tcx.infer_ctxt().build_with_canonical(cause.span, &self.canonical_query);
-        let ocx = ObligationCtxt::new(infcx);
+        let ocx = ObligationCtxt::new(&infcx);
 
         // FIXME(lqd): Unify and de-duplicate the following with the actual
         // `rustc_traits::type_op::type_op_normalize` query to allow the span we need in the
@@ -328,9 +328,9 @@ impl<'tcx> TypeOpInfo<'tcx> for AscribeUserTypeQuery<'tcx> {
         placeholder_region: ty::Region<'tcx>,
         error_region: Option<ty::Region<'tcx>>,
     ) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> {
-        let (ref infcx, key, _) =
+        let (infcx, key, _) =
             mbcx.infcx.tcx.infer_ctxt().build_with_canonical(cause.span, &self.canonical_query);
-        let ocx = ObligationCtxt::new(infcx);
+        let ocx = ObligationCtxt::new(&infcx);
         type_op_ascribe_user_type_with_span(&ocx, key, Some(cause.span)).ok()?;
         try_extract_error_from_fulfill_cx(&ocx, placeholder_region, error_region)
     }
diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index d221da5c17e..5e3745f1735 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -265,7 +265,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                 DescribePlaceOpt { including_downcast: true, including_tuple_field: true },
             );
             let note_msg = match opt_name {
-                Some(ref name) => format!("`{}`", name),
+                Some(name) => format!("`{}`", name),
                 None => "value".to_owned(),
             };
             if self.suggest_borrow_fn_like(&mut err, ty, &move_site_vec, &note_msg) {
@@ -1417,7 +1417,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             // then just use the normal error. The closure isn't escaping
             // and `move` will not help here.
             (
-                Some(ref name),
+                Some(name),
                 BorrowExplanation::MustBeValidFor {
                     category:
                         category @ (ConstraintCategory::Return(_)
@@ -1438,7 +1438,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                     &format!("`{}`", name),
                 ),
             (
-                ref name,
+                name,
                 BorrowExplanation::MustBeValidFor {
                     category: ConstraintCategory::Assignment,
                     from_closure: false,
@@ -1450,7 +1450,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                     span,
                     ..
                 },
-            ) => self.report_escaping_data(borrow_span, name, upvar_span, upvar_name, span),
+            ) => self.report_escaping_data(borrow_span, &name, upvar_span, upvar_name, span),
             (Some(name), explanation) => self.report_local_value_does_not_live_long_enough(
                 location,
                 &name,
@@ -2452,7 +2452,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         // and it'll make sense.
         let location = borrow.reserve_location;
         debug!("annotate_argument_and_return_for_borrow: location={:?}", location);
-        if let Some(&Statement { kind: StatementKind::Assign(box (ref reservation, _)), .. }) =
+        if let Some(Statement { kind: StatementKind::Assign(box (reservation, _)), .. }) =
             &self.body[location.block].statements.get(location.statement_index)
         {
             debug!("annotate_argument_and_return_for_borrow: reservation={:?}", reservation);
@@ -2480,8 +2480,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                         // Check if our `target` was captured by a closure.
                         if let Rvalue::Aggregate(
                             box AggregateKind::Closure(def_id, substs),
-                            ref operands,
-                        ) = *rvalue
+                            operands,
+                        ) = rvalue
                         {
                             for operand in operands {
                                 let (Operand::Copy(assigned_from) | Operand::Move(assigned_from)) = operand else {
@@ -2505,7 +2505,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                                 // into a place then we should annotate the closure in
                                 // case it ends up being assigned into the return place.
                                 annotated_closure =
-                                    self.annotate_fn_sig(def_id, substs.as_closure().sig());
+                                    self.annotate_fn_sig(*def_id, substs.as_closure().sig());
                                 debug!(
                                     "annotate_argument_and_return_for_borrow: \
                                      annotated_closure={:?} assigned_from_local={:?} \
diff --git a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
index 582d683dd35..304683618d8 100644
--- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
@@ -469,8 +469,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                 } else if self.was_captured_by_trait_object(borrow) {
                     LaterUseKind::TraitCapture
                 } else if location.statement_index == block.statements.len() {
-                    if let TerminatorKind::Call { ref func, from_hir_call: true, .. } =
-                        block.terminator().kind
+                    if let TerminatorKind::Call { func, from_hir_call: true, .. } =
+                        &block.terminator().kind
                     {
                         // Just point to the function, to reduce the chance of overlapping spans.
                         let function_span = match func {
@@ -515,19 +515,16 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         // will only ever have one item at any given time, but by using a vector, we can pop from
         // it which simplifies the termination logic.
         let mut queue = vec![location];
-        let mut target = if let Some(&Statement {
-            kind: StatementKind::Assign(box (ref place, _)),
-            ..
-        }) = stmt
-        {
-            if let Some(local) = place.as_local() {
-                local
+        let mut target =
+            if let Some(Statement { kind: StatementKind::Assign(box (place, _)), .. }) = stmt {
+                if let Some(local) = place.as_local() {
+                    local
+                } else {
+                    return false;
+                }
             } else {
                 return false;
-            }
-        } else {
-            return false;
-        };
+            };
 
         debug!("was_captured_by_trait: target={:?} queue={:?}", target, queue);
         while let Some(current_location) = queue.pop() {
diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs
index 86c5d9cfa81..4e2271a3067 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mod.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs
@@ -78,7 +78,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             if let StatementKind::Assign(box (into, Rvalue::Use(from))) = &stmt.kind {
                 debug!("add_fnonce_closure_note: into={:?} from={:?}", into, from);
                 match from {
-                    Operand::Copy(ref place) | Operand::Move(ref place)
+                    Operand::Copy(place) | Operand::Move(place)
                         if target == place.local_or_deref_local() =>
                     {
                         target = into.local_or_deref_local()
@@ -101,7 +101,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                 debug!("add_moved_or_invoked_closure_note: id={:?}", id);
                 if Some(self.infcx.tcx.parent(id)) == self.infcx.tcx.lang_items().fn_once_trait() {
                     let closure = match args.first() {
-                        Some(Operand::Copy(ref place)) | Some(Operand::Move(ref place))
+                        Some(Operand::Copy(place) | Operand::Move(place))
                             if target == place.local_or_deref_local() =>
                         {
                             place.local_or_deref_local().unwrap()
@@ -439,9 +439,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                     if !is_terminator {
                         continue;
                     } else if let Some(Terminator {
-                        kind: TerminatorKind::Call { ref func, from_hir_call: false, .. },
+                        kind: TerminatorKind::Call { func, from_hir_call: false, .. },
                         ..
-                    }) = bbd.terminator
+                    }) = &bbd.terminator
                     {
                         if let Some(source) =
                             BorrowedContentSource::from_call(func.ty(self.body, tcx), tcx)
@@ -811,33 +811,30 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         };
 
         debug!("move_spans: moved_place={:?} location={:?} stmt={:?}", moved_place, location, stmt);
-        if let StatementKind::Assign(box (_, Rvalue::Aggregate(ref kind, ref places))) = stmt.kind {
-            match **kind {
-                AggregateKind::Closure(def_id, _) | AggregateKind::Generator(def_id, _, _) => {
-                    debug!("move_spans: def_id={:?} places={:?}", def_id, places);
-                    if let Some((args_span, generator_kind, capture_kind_span, path_span)) =
-                        self.closure_span(def_id, moved_place, places)
-                    {
-                        return ClosureUse {
-                            generator_kind,
-                            args_span,
-                            capture_kind_span,
-                            path_span,
-                        };
-                    }
-                }
-                _ => {}
+        if let StatementKind::Assign(box (_, Rvalue::Aggregate(kind, places))) = &stmt.kind
+            && let AggregateKind::Closure(def_id, _) | AggregateKind::Generator(def_id, _, _) = **kind
+        {
+            debug!("move_spans: def_id={:?} places={:?}", def_id, places);
+            if let Some((args_span, generator_kind, capture_kind_span, path_span)) =
+                self.closure_span(def_id, moved_place, places)
+            {
+                return ClosureUse {
+                    generator_kind,
+                    args_span,
+                    capture_kind_span,
+                    path_span,
+                };
             }
         }
 
         // StatementKind::FakeRead only contains a def_id if they are introduced as a result
         // of pattern matching within a closure.
-        if let StatementKind::FakeRead(box (cause, ref place)) = stmt.kind {
+        if let StatementKind::FakeRead(box (cause, place)) = stmt.kind {
             match cause {
                 FakeReadCause::ForMatchedPlace(Some(closure_def_id))
                 | FakeReadCause::ForLet(Some(closure_def_id)) => {
                     debug!("move_spans: def_id={:?} place={:?}", closure_def_id, place);
-                    let places = &[Operand::Move(*place)];
+                    let places = &[Operand::Move(place)];
                     if let Some((args_span, generator_kind, capture_kind_span, path_span)) =
                         self.closure_span(closure_def_id, moved_place, places)
                     {
@@ -924,7 +921,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         debug!("borrow_spans: use_span={:?} location={:?}", use_span, location);
 
         let target = match self.body[location.block].statements.get(location.statement_index) {
-            Some(&Statement { kind: StatementKind::Assign(box (ref place, _)), .. }) => {
+            Some(Statement { kind: StatementKind::Assign(box (place, _)), .. }) => {
                 if let Some(local) = place.as_local() {
                     local
                 } else {
@@ -940,9 +937,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         }
 
         for stmt in &self.body[location.block].statements[location.statement_index + 1..] {
-            if let StatementKind::Assign(box (_, Rvalue::Aggregate(ref kind, ref places))) =
-                stmt.kind
-            {
+            if let StatementKind::Assign(box (_, Rvalue::Aggregate(kind, places))) = &stmt.kind {
                 let (&def_id, is_generator) = match kind {
                     box AggregateKind::Closure(def_id, _) => (def_id, false),
                     box AggregateKind::Generator(def_id, _, _) => (def_id, true),
diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
index 0cf66e41001..3319a80681f 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
@@ -219,8 +219,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
             PlaceRef {
                 local,
                 projection:
-                    &[
-                        ref proj_base @ ..,
+                    [
+                        proj_base @ ..,
                         ProjectionElem::Deref,
                         ProjectionElem::Field(field, _),
                         ProjectionElem::Deref,
@@ -231,7 +231,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
                 if let Some(span) = get_mut_span_in_struct_field(
                     self.infcx.tcx,
                     Place::ty_from(local, proj_base, self.body, self.infcx.tcx).ty,
-                    field,
+                    *field,
                 ) {
                     err.span_suggestion_verbose(
                         span,
diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
index 7aa099433a7..9bc2e79e29b 100644
--- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
@@ -921,7 +921,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
                 }
             }
             hir::ExprKind::Block(blk, _) => {
-                if let Some(ref expr) = blk.expr {
+                if let Some(expr) = blk.expr {
                     // only when the block is a closure
                     if let hir::ExprKind::Closure(hir::Closure {
                         capture_clause: hir::CaptureBy::Ref,
diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs
index 39173e70acf..171e62d91e1 100644
--- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs
@@ -254,7 +254,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
             .or_else(|| self.give_name_if_anonymous_region_appears_in_impl_signature(fr))
             .or_else(|| self.give_name_if_anonymous_region_appears_in_arg_position_impl_trait(fr));
 
-        if let Some(ref value) = value {
+        if let Some(value) = &value {
             self.region_names.try_borrow_mut().unwrap().insert(fr, value.clone());
         }
 
diff --git a/compiler/rustc_borrowck/src/invalidation.rs b/compiler/rustc_borrowck/src/invalidation.rs
index f5317a143ae..f66a7ab3c03 100644
--- a/compiler/rustc_borrowck/src/invalidation.rs
+++ b/compiler/rustc_borrowck/src/invalidation.rs
@@ -69,9 +69,9 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> {
                 self.consume_operand(location, op);
             }
             StatementKind::Intrinsic(box NonDivergingIntrinsic::CopyNonOverlapping(mir::CopyNonOverlapping {
-                ref src,
-                ref dst,
-                ref count,
+                src,
+                dst,
+                count,
             })) => {
                 self.consume_operand(location, src);
                 self.consume_operand(location, dst);
@@ -106,7 +106,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> {
         self.check_activations(location);
 
         match &terminator.kind {
-            TerminatorKind::SwitchInt { ref discr, switch_ty: _, targets: _ } => {
+            TerminatorKind::SwitchInt { discr, switch_ty: _, targets: _ } => {
                 self.consume_operand(location, discr);
             }
             TerminatorKind::Drop { place: drop_place, target: _, unwind: _ } => {
@@ -119,7 +119,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> {
             }
             TerminatorKind::DropAndReplace {
                 place: drop_place,
-                value: ref new_value,
+                value: new_value,
                 target: _,
                 unwind: _,
             } => {
@@ -127,8 +127,8 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> {
                 self.consume_operand(location, new_value);
             }
             TerminatorKind::Call {
-                ref func,
-                ref args,
+                func,
+                args,
                 destination,
                 target: _,
                 cleanup: _,
@@ -141,15 +141,15 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> {
                 }
                 self.mutate_place(location, *destination, Deep);
             }
-            TerminatorKind::Assert { ref cond, expected: _, ref msg, target: _, cleanup: _ } => {
+            TerminatorKind::Assert { cond, expected: _, msg, target: _, cleanup: _ } => {
                 self.consume_operand(location, cond);
                 use rustc_middle::mir::AssertKind;
-                if let AssertKind::BoundsCheck { ref len, ref index } = *msg {
+                if let AssertKind::BoundsCheck { len, index } = msg {
                     self.consume_operand(location, len);
                     self.consume_operand(location, index);
                 }
             }
-            TerminatorKind::Yield { ref value, resume, resume_arg, drop: _ } => {
+            TerminatorKind::Yield { value, resume, resume_arg, drop: _ } => {
                 self.consume_operand(location, value);
 
                 // Invalidate all borrows of local places
@@ -175,25 +175,25 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> {
             }
             TerminatorKind::InlineAsm {
                 template: _,
-                ref operands,
+                operands,
                 options: _,
                 line_spans: _,
                 destination: _,
                 cleanup: _,
             } => {
                 for op in operands {
-                    match *op {
-                        InlineAsmOperand::In { reg: _, ref value } => {
+                    match op {
+                        InlineAsmOperand::In { reg: _, value } => {
                             self.consume_operand(location, value);
                         }
                         InlineAsmOperand::Out { reg: _, late: _, place, .. } => {
-                            if let Some(place) = place {
+                            if let &Some(place) = place {
                                 self.mutate_place(location, place, Shallow(None));
                             }
                         }
-                        InlineAsmOperand::InOut { reg: _, late: _, ref in_value, out_place } => {
+                        InlineAsmOperand::InOut { reg: _, late: _, in_value, out_place } => {
                             self.consume_operand(location, in_value);
-                            if let Some(out_place) = out_place {
+                            if let &Some(out_place) = out_place {
                                 self.mutate_place(location, out_place, Shallow(None));
                             }
                         }
@@ -252,8 +252,8 @@ impl<'cx, 'tcx> InvalidationGenerator<'cx, 'tcx> {
 
     // Simulates consumption of an rvalue
     fn consume_rvalue(&mut self, location: Location, rvalue: &Rvalue<'tcx>) {
-        match *rvalue {
-            Rvalue::Ref(_ /*rgn*/, bk, place) => {
+        match rvalue {
+            &Rvalue::Ref(_ /*rgn*/, bk, place) => {
                 let access_kind = match bk {
                     BorrowKind::Shallow => {
                         (Shallow(Some(ArtificialField::ShallowBorrow)), Read(ReadKind::Borrow(bk)))
@@ -272,7 +272,7 @@ impl<'cx, 'tcx> InvalidationGenerator<'cx, 'tcx> {
                 self.access_place(location, place, access_kind, LocalMutationIsAllowed::No);
             }
 
-            Rvalue::AddressOf(mutability, place) => {
+            &Rvalue::AddressOf(mutability, place) => {
                 let access_kind = match mutability {
                     Mutability::Mut => (
                         Deep,
@@ -288,20 +288,19 @@ impl<'cx, 'tcx> InvalidationGenerator<'cx, 'tcx> {
 
             Rvalue::ThreadLocalRef(_) => {}
 
-            Rvalue::Use(ref operand)
-            | Rvalue::Repeat(ref operand, _)
-            | Rvalue::UnaryOp(_ /*un_op*/, ref operand)
-            | Rvalue::Cast(_ /*cast_kind*/, ref operand, _ /*ty*/)
-            | Rvalue::ShallowInitBox(ref operand, _ /*ty*/) => {
-                self.consume_operand(location, operand)
-            }
-            Rvalue::CopyForDeref(ref place) => {
-                let op = &Operand::Copy(*place);
+            Rvalue::Use(operand)
+            | Rvalue::Repeat(operand, _)
+            | Rvalue::UnaryOp(_ /*un_op*/, operand)
+            | Rvalue::Cast(_ /*cast_kind*/, operand, _ /*ty*/)
+            | Rvalue::ShallowInitBox(operand, _ /*ty*/) => self.consume_operand(location, operand),
+
+            &Rvalue::CopyForDeref(place) => {
+                let op = &Operand::Copy(place);
                 self.consume_operand(location, op);
             }
 
-            Rvalue::Len(place) | Rvalue::Discriminant(place) => {
-                let af = match *rvalue {
+            &(Rvalue::Len(place) | Rvalue::Discriminant(place)) => {
+                let af = match rvalue {
                     Rvalue::Len(..) => Some(ArtificialField::ArrayLength),
                     Rvalue::Discriminant(..) => None,
                     _ => unreachable!(),
@@ -314,15 +313,15 @@ impl<'cx, 'tcx> InvalidationGenerator<'cx, 'tcx> {
                 );
             }
 
-            Rvalue::BinaryOp(_bin_op, box (ref operand1, ref operand2))
-            | Rvalue::CheckedBinaryOp(_bin_op, box (ref operand1, ref operand2)) => {
+            Rvalue::BinaryOp(_bin_op, box (operand1, operand2))
+            | Rvalue::CheckedBinaryOp(_bin_op, box (operand1, operand2)) => {
                 self.consume_operand(location, operand1);
                 self.consume_operand(location, operand2);
             }
 
             Rvalue::NullaryOp(_op, _ty) => {}
 
-            Rvalue::Aggregate(_, ref operands) => {
+            Rvalue::Aggregate(_, operands) => {
                 for operand in operands {
                     self.consume_operand(location, operand);
                 }
diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs
index 4d87ecf5e44..74b4e4a0cab 100644
--- a/compiler/rustc_borrowck/src/lib.rs
+++ b/compiler/rustc_borrowck/src/lib.rs
@@ -578,12 +578,12 @@ impl<'cx, 'tcx> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtx
         self.check_activations(location, span, flow_state);
 
         match &stmt.kind {
-            StatementKind::Assign(box (lhs, ref rhs)) => {
+            StatementKind::Assign(box (lhs, rhs)) => {
                 self.consume_rvalue(location, (rhs, span), flow_state);
 
                 self.mutate_place(location, (*lhs, span), Shallow(None), flow_state);
             }
-            StatementKind::FakeRead(box (_, ref place)) => {
+            StatementKind::FakeRead(box (_, place)) => {
                 // Read for match doesn't access any memory and is used to
                 // assert that a place is safe and live. So we don't have to
                 // do any checks here.
@@ -601,7 +601,7 @@ impl<'cx, 'tcx> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtx
                     flow_state,
                 );
             }
-            StatementKind::Intrinsic(box ref kind) => match kind {
+            StatementKind::Intrinsic(box kind) => match kind {
                 NonDivergingIntrinsic::Assume(op) => self.consume_operand(location, (op, span), flow_state),
                 NonDivergingIntrinsic::CopyNonOverlapping(..) => span_bug!(
                     span,
@@ -643,8 +643,8 @@ impl<'cx, 'tcx> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtx
 
         self.check_activations(loc, span, flow_state);
 
-        match term.kind {
-            TerminatorKind::SwitchInt { ref discr, switch_ty: _, targets: _ } => {
+        match &term.kind {
+            TerminatorKind::SwitchInt { discr, switch_ty: _, targets: _ } => {
                 self.consume_operand(loc, (discr, span), flow_state);
             }
             TerminatorKind::Drop { place, target: _, unwind: _ } => {
@@ -656,7 +656,7 @@ impl<'cx, 'tcx> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtx
 
                 self.access_place(
                     loc,
-                    (place, span),
+                    (*place, span),
                     (AccessDepth::Drop, Write(WriteKind::StorageDeadOrDrop)),
                     LocalMutationIsAllowed::Yes,
                     flow_state,
@@ -664,16 +664,16 @@ impl<'cx, 'tcx> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtx
             }
             TerminatorKind::DropAndReplace {
                 place: drop_place,
-                value: ref new_value,
+                value: new_value,
                 target: _,
                 unwind: _,
             } => {
-                self.mutate_place(loc, (drop_place, span), Deep, flow_state);
+                self.mutate_place(loc, (*drop_place, span), Deep, flow_state);
                 self.consume_operand(loc, (new_value, span), flow_state);
             }
             TerminatorKind::Call {
-                ref func,
-                ref args,
+                func,
+                args,
                 destination,
                 target: _,
                 cleanup: _,
@@ -684,43 +684,43 @@ impl<'cx, 'tcx> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtx
                 for arg in args {
                     self.consume_operand(loc, (arg, span), flow_state);
                 }
-                self.mutate_place(loc, (destination, span), Deep, flow_state);
+                self.mutate_place(loc, (*destination, span), Deep, flow_state);
             }
-            TerminatorKind::Assert { ref cond, expected: _, ref msg, target: _, cleanup: _ } => {
+            TerminatorKind::Assert { cond, expected: _, msg, target: _, cleanup: _ } => {
                 self.consume_operand(loc, (cond, span), flow_state);
                 use rustc_middle::mir::AssertKind;
-                if let AssertKind::BoundsCheck { ref len, ref index } = *msg {
+                if let AssertKind::BoundsCheck { len, index } = msg {
                     self.consume_operand(loc, (len, span), flow_state);
                     self.consume_operand(loc, (index, span), flow_state);
                 }
             }
 
-            TerminatorKind::Yield { ref value, resume: _, resume_arg, drop: _ } => {
+            TerminatorKind::Yield { value, resume: _, resume_arg, drop: _ } => {
                 self.consume_operand(loc, (value, span), flow_state);
-                self.mutate_place(loc, (resume_arg, span), Deep, flow_state);
+                self.mutate_place(loc, (*resume_arg, span), Deep, flow_state);
             }
 
             TerminatorKind::InlineAsm {
                 template: _,
-                ref operands,
+                operands,
                 options: _,
                 line_spans: _,
                 destination: _,
                 cleanup: _,
             } => {
                 for op in operands {
-                    match *op {
-                        InlineAsmOperand::In { reg: _, ref value } => {
+                    match op {
+                        InlineAsmOperand::In { reg: _, value } => {
                             self.consume_operand(loc, (value, span), flow_state);
                         }
                         InlineAsmOperand::Out { reg: _, late: _, place, .. } => {
                             if let Some(place) = place {
-                                self.mutate_place(loc, (place, span), Shallow(None), flow_state);
+                                self.mutate_place(loc, (*place, span), Shallow(None), flow_state);
                             }
                         }
-                        InlineAsmOperand::InOut { reg: _, late: _, ref in_value, out_place } => {
+                        InlineAsmOperand::InOut { reg: _, late: _, in_value, out_place } => {
                             self.consume_operand(loc, (in_value, span), flow_state);
-                            if let Some(out_place) = out_place {
+                            if let &Some(out_place) = out_place {
                                 self.mutate_place(
                                     loc,
                                     (out_place, span),
@@ -1164,8 +1164,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         (rvalue, span): (&'cx Rvalue<'tcx>, Span),
         flow_state: &Flows<'cx, 'tcx>,
     ) {
-        match *rvalue {
-            Rvalue::Ref(_ /*rgn*/, bk, place) => {
+        match rvalue {
+            &Rvalue::Ref(_ /*rgn*/, bk, place) => {
                 let access_kind = match bk {
                     BorrowKind::Shallow => {
                         (Shallow(Some(ArtificialField::ShallowBorrow)), Read(ReadKind::Borrow(bk)))
@@ -1203,7 +1203,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                 );
             }
 
-            Rvalue::AddressOf(mutability, place) => {
+            &Rvalue::AddressOf(mutability, place) => {
                 let access_kind = match mutability {
                     Mutability::Mut => (
                         Deep,
@@ -1232,14 +1232,15 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
 
             Rvalue::ThreadLocalRef(_) => {}
 
-            Rvalue::Use(ref operand)
-            | Rvalue::Repeat(ref operand, _)
-            | Rvalue::UnaryOp(_ /*un_op*/, ref operand)
-            | Rvalue::Cast(_ /*cast_kind*/, ref operand, _ /*ty*/)
-            | Rvalue::ShallowInitBox(ref operand, _ /*ty*/) => {
+            Rvalue::Use(operand)
+            | Rvalue::Repeat(operand, _)
+            | Rvalue::UnaryOp(_ /*un_op*/, operand)
+            | Rvalue::Cast(_ /*cast_kind*/, operand, _ /*ty*/)
+            | Rvalue::ShallowInitBox(operand, _ /*ty*/) => {
                 self.consume_operand(location, (operand, span), flow_state)
             }
-            Rvalue::CopyForDeref(place) => {
+
+            &Rvalue::CopyForDeref(place) => {
                 self.access_place(
                     location,
                     (place, span),
@@ -1257,7 +1258,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                 );
             }
 
-            Rvalue::Len(place) | Rvalue::Discriminant(place) => {
+            &(Rvalue::Len(place) | Rvalue::Discriminant(place)) => {
                 let af = match *rvalue {
                     Rvalue::Len(..) => Some(ArtificialField::ArrayLength),
                     Rvalue::Discriminant(..) => None,
@@ -1278,8 +1279,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                 );
             }
 
-            Rvalue::BinaryOp(_bin_op, box (ref operand1, ref operand2))
-            | Rvalue::CheckedBinaryOp(_bin_op, box (ref operand1, ref operand2)) => {
+            Rvalue::BinaryOp(_bin_op, box (operand1, operand2))
+            | Rvalue::CheckedBinaryOp(_bin_op, box (operand1, operand2)) => {
                 self.consume_operand(location, (operand1, span), flow_state);
                 self.consume_operand(location, (operand2, span), flow_state);
             }
@@ -1288,7 +1289,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                 // nullary ops take no dynamic input; no borrowck effect.
             }
 
-            Rvalue::Aggregate(ref aggregate_kind, ref operands) => {
+            Rvalue::Aggregate(aggregate_kind, operands) => {
                 // We need to report back the list of mutable upvars that were
                 // moved into the closure and subsequently used by the closure,
                 // in order to populate our used_mut set.
diff --git a/compiler/rustc_borrowck/src/type_check/canonical.rs b/compiler/rustc_borrowck/src/type_check/canonical.rs
index 1aad6738bba..3617bf58be9 100644
--- a/compiler/rustc_borrowck/src/type_check/canonical.rs
+++ b/compiler/rustc_borrowck/src/type_check/canonical.rs
@@ -121,9 +121,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
 
     pub(super) fn prove_predicates(
         &mut self,
-        predicates: impl IntoIterator<
-            Item = impl ToPredicate<'tcx, ty::Predicate<'tcx>> + std::fmt::Debug,
-        >,
+        predicates: impl IntoIterator<Item = impl ToPredicate<'tcx> + std::fmt::Debug>,
         locations: Locations,
         category: ConstraintCategory<'tcx>,
     ) {
@@ -135,7 +133,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
     #[instrument(skip(self), level = "debug")]
     pub(super) fn prove_predicate(
         &mut self,
-        predicate: impl ToPredicate<'tcx, ty::Predicate<'tcx>> + std::fmt::Debug,
+        predicate: impl ToPredicate<'tcx> + std::fmt::Debug,
         locations: Locations,
         category: ConstraintCategory<'tcx>,
     ) {
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index 18e3cbbb86a..6d4ec6b726e 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -1189,8 +1189,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
     fn check_stmt(&mut self, body: &Body<'tcx>, stmt: &Statement<'tcx>, location: Location) {
         let tcx = self.tcx();
         debug!("stmt kind: {:?}", stmt.kind);
-        match stmt.kind {
-            StatementKind::Assign(box (ref place, ref rv)) => {
+        match &stmt.kind {
+            StatementKind::Assign(box (place, rv)) => {
                 // Assignments to temporaries are not "interesting";
                 // they are not caused by the user, but rather artifacts
                 // of lowering. Assignments to other sorts of places *are* interesting
@@ -1279,11 +1279,11 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                     );
                 }
             }
-            StatementKind::AscribeUserType(box (ref place, ref projection), variance) => {
+            StatementKind::AscribeUserType(box (place, projection), variance) => {
                 let place_ty = place.ty(body, tcx).ty;
                 if let Err(terr) = self.relate_type_and_user_type(
                     place_ty,
-                    variance,
+                    *variance,
                     projection,
                     Locations::All(stmt.source_info.span),
                     ConstraintCategory::TypeAnnotation,
@@ -1300,7 +1300,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                     );
                 }
             }
-            StatementKind::Intrinsic(box ref kind) => match kind {
+            StatementKind::Intrinsic(box kind) => match kind {
                 NonDivergingIntrinsic::Assume(op) => self.check_operand(op, location),
                 NonDivergingIntrinsic::CopyNonOverlapping(..) => span_bug!(
                     stmt.source_info.span,
@@ -1328,7 +1328,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
     ) {
         let tcx = self.tcx();
         debug!("terminator kind: {:?}", term.kind);
-        match term.kind {
+        match &term.kind {
             TerminatorKind::Goto { .. }
             | TerminatorKind::Resume
             | TerminatorKind::Abort
@@ -1342,7 +1342,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                 // no checks needed for these
             }
 
-            TerminatorKind::DropAndReplace { ref place, ref value, target: _, unwind: _ } => {
+            TerminatorKind::DropAndReplace { place, value, target: _, unwind: _ } => {
                 let place_ty = place.ty(body, tcx).ty;
                 let rv_ty = value.ty(body, tcx);
 
@@ -1360,13 +1360,13 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                     );
                 }
             }
-            TerminatorKind::SwitchInt { ref discr, switch_ty, .. } => {
+            TerminatorKind::SwitchInt { discr, switch_ty, .. } => {
                 self.check_operand(discr, term_location);
 
                 let discr_ty = discr.ty(body, tcx);
                 if let Err(terr) = self.sub_types(
                     discr_ty,
-                    switch_ty,
+                    *switch_ty,
                     term_location.to_locations(),
                     ConstraintCategory::Assignment,
                 ) {
@@ -1384,14 +1384,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                 }
                 // FIXME: check the values
             }
-            TerminatorKind::Call {
-                ref func,
-                ref args,
-                ref destination,
-                from_hir_call,
-                target,
-                ..
-            } => {
+            TerminatorKind::Call { func, args, destination, from_hir_call, target, .. } => {
                 self.check_operand(func, term_location);
                 for arg in args {
                     self.check_operand(arg, term_location);
@@ -1431,7 +1424,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                     ConstraintCategory::Boring,
                 );
                 let sig = self.normalize(sig, term_location);
-                self.check_call_dest(body, term, &sig, *destination, target, term_location);
+                self.check_call_dest(body, term, &sig, *destination, *target, term_location);
 
                 // The ordinary liveness rules will ensure that all
                 // regions in the type of the callee are live here. We
@@ -1449,9 +1442,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                         .add_element(region_vid, term_location);
                 }
 
-                self.check_call_inputs(body, term, &sig, args, term_location, from_hir_call);
+                self.check_call_inputs(body, term, &sig, args, term_location, *from_hir_call);
             }
-            TerminatorKind::Assert { ref cond, ref msg, .. } => {
+            TerminatorKind::Assert { cond, msg, .. } => {
                 self.check_operand(cond, term_location);
 
                 let cond_ty = cond.ty(body, tcx);
@@ -1459,7 +1452,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                     span_mirbug!(self, term, "bad Assert ({:?}, not bool", cond_ty);
                 }
 
-                if let AssertKind::BoundsCheck { ref len, ref index } = *msg {
+                if let AssertKind::BoundsCheck { len, index } = msg {
                     if len.ty(body, tcx) != tcx.types.usize {
                         span_mirbug!(self, len, "bounds-check length non-usize {:?}", len)
                     }
@@ -1468,7 +1461,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                     }
                 }
             }
-            TerminatorKind::Yield { ref value, .. } => {
+            TerminatorKind::Yield { value, .. } => {
                 self.check_operand(value, term_location);
 
                 let value_ty = value.ty(body, tcx);
@@ -2630,7 +2623,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         substs: SubstsRef<'tcx>,
         location: Location,
     ) -> ty::InstantiatedPredicates<'tcx> {
-        if let Some(ref closure_requirements) = tcx.mir_borrowck(def_id).closure_requirements {
+        if let Some(closure_requirements) = &tcx.mir_borrowck(def_id).closure_requirements {
             constraint_conversion::ConstraintConversion::new(
                 self.infcx,
                 self.borrowck_context.universal_regions,
diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs
index 618da9e3253..a4a0c5b90fe 100644
--- a/compiler/rustc_borrowck/src/universal_regions.rs
+++ b/compiler/rustc_borrowck/src/universal_regions.rs
@@ -587,9 +587,9 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
         let typeck_root_def_id = tcx.typeck_root_def_id(self.mir_def.did.to_def_id());
         let identity_substs = InternalSubsts::identity_for_item(tcx, typeck_root_def_id);
         let fr_substs = match defining_ty {
-            DefiningTy::Closure(_, ref substs)
-            | DefiningTy::Generator(_, ref substs, _)
-            | DefiningTy::InlineConst(_, ref substs) => {
+            DefiningTy::Closure(_, substs)
+            | DefiningTy::Generator(_, substs, _)
+            | DefiningTy::InlineConst(_, substs) => {
                 // In the case of closures, we rely on the fact that
                 // the first N elements in the ClosureSubsts are
                 // inherited from the `typeck_root_def_id`.
diff --git a/compiler/rustc_builtin_macros/src/alloc_error_handler.rs b/compiler/rustc_builtin_macros/src/alloc_error_handler.rs
index 460175ed2ac..95e38e4b053 100644
--- a/compiler/rustc_builtin_macros/src/alloc_error_handler.rs
+++ b/compiler/rustc_builtin_macros/src/alloc_error_handler.rs
@@ -17,32 +17,23 @@ pub fn expand(
     check_builtin_macro_attribute(ecx, meta_item, sym::alloc_error_handler);
 
     let orig_item = item.clone();
-    let not_function = || {
-        ecx.sess
-            .parse_sess
-            .span_diagnostic
-            .span_err(item.span(), "alloc_error_handler must be a function");
-        vec![orig_item.clone()]
-    };
 
     // Allow using `#[alloc_error_handler]` on an item statement
     // FIXME - if we get deref patterns, use them to reduce duplication here
-    let (item, is_stmt, sig_span) = match &item {
-        Annotatable::Item(item) => match item.kind {
-            ItemKind::Fn(ref fn_kind) => (item, false, ecx.with_def_site_ctxt(fn_kind.sig.span)),
-            _ => return not_function(),
-        },
-        Annotatable::Stmt(stmt) => match &stmt.kind {
-            StmtKind::Item(item_) => match item_.kind {
-                ItemKind::Fn(ref fn_kind) => {
-                    (item_, true, ecx.with_def_site_ctxt(fn_kind.sig.span))
-                }
-                _ => return not_function(),
-            },
-            _ => return not_function(),
-        },
-        _ => return not_function(),
-    };
+    let (item, is_stmt, sig_span) =
+        if let Annotatable::Item(item) = &item
+            && let ItemKind::Fn(fn_kind) = &item.kind
+        {
+            (item, false, ecx.with_def_site_ctxt(fn_kind.sig.span))
+        } else if let Annotatable::Stmt(stmt) = &item
+            && let StmtKind::Item(item) = &stmt.kind
+            && let ItemKind::Fn(fn_kind) = &item.kind
+        {
+            (item, true, ecx.with_def_site_ctxt(fn_kind.sig.span))
+        } else {
+            ecx.sess.parse_sess.span_diagnostic.span_err(item.span(), "alloc_error_handler must be a function");
+            return vec![orig_item.clone()];
+        };
 
     // Generate a bunch of new items using the AllocFnFactory
     let span = ecx.with_def_site_ctxt(item.span);
diff --git a/compiler/rustc_builtin_macros/src/assert/context.rs b/compiler/rustc_builtin_macros/src/assert/context.rs
index d82bc0453f5..93b07801e03 100644
--- a/compiler/rustc_builtin_macros/src/assert/context.rs
+++ b/compiler/rustc_builtin_macros/src/assert/context.rs
@@ -191,19 +191,19 @@ impl<'cx, 'a> Context<'cx, 'a> {
     ///
     /// See [Self::manage_initial_capture] and [Self::manage_try_capture]
     fn manage_cond_expr(&mut self, expr: &mut P<Expr>) {
-        match (*expr).kind {
-            ExprKind::AddrOf(_, mutability, ref mut local_expr) => {
+        match &mut expr.kind {
+            ExprKind::AddrOf(_, mutability, local_expr) => {
                 self.with_is_consumed_management(
                     matches!(mutability, Mutability::Mut),
                     |this| this.manage_cond_expr(local_expr)
                 );
             }
-            ExprKind::Array(ref mut local_exprs) => {
+            ExprKind::Array(local_exprs) => {
                 for local_expr in local_exprs {
                     self.manage_cond_expr(local_expr);
                 }
             }
-            ExprKind::Binary(ref op, ref mut lhs, ref mut rhs) => {
+            ExprKind::Binary(op, lhs, rhs) => {
                 self.with_is_consumed_management(
                     matches!(
                         op.node,
@@ -226,56 +226,56 @@ impl<'cx, 'a> Context<'cx, 'a> {
                     }
                 );
             }
-            ExprKind::Call(_, ref mut local_exprs) => {
+            ExprKind::Call(_, local_exprs) => {
                 for local_expr in local_exprs {
                     self.manage_cond_expr(local_expr);
                 }
             }
-            ExprKind::Cast(ref mut local_expr, _) => {
+            ExprKind::Cast(local_expr, _) => {
                 self.manage_cond_expr(local_expr);
             }
-            ExprKind::Index(ref mut prefix, ref mut suffix) => {
+            ExprKind::Index(prefix, suffix) => {
                 self.manage_cond_expr(prefix);
                 self.manage_cond_expr(suffix);
             }
-            ExprKind::MethodCall(ref mut call) => {
-                for arg in call.args.iter_mut() {
+            ExprKind::MethodCall(call) => {
+                for arg in &mut call.args {
                     self.manage_cond_expr(arg);
                 }
             }
-            ExprKind::Path(_, Path { ref segments, .. }) if let &[ref path_segment] = &segments[..] => {
+            ExprKind::Path(_, Path { segments, .. }) if let [path_segment] = &segments[..] => {
                 let path_ident = path_segment.ident;
                 self.manage_initial_capture(expr, path_ident);
             }
-            ExprKind::Paren(ref mut local_expr) => {
+            ExprKind::Paren(local_expr) => {
                 self.manage_cond_expr(local_expr);
             }
-            ExprKind::Range(ref mut prefix, ref mut suffix, _) => {
-                if let Some(ref mut elem) = prefix {
+            ExprKind::Range(prefix, suffix, _) => {
+                if let Some(elem) = prefix {
                     self.manage_cond_expr(elem);
                 }
-                if let Some(ref mut elem) = suffix {
+                if let Some(elem) = suffix {
                     self.manage_cond_expr(elem);
                 }
             }
-            ExprKind::Repeat(ref mut local_expr, ref mut elem) => {
+            ExprKind::Repeat(local_expr, elem) => {
                 self.manage_cond_expr(local_expr);
                 self.manage_cond_expr(&mut elem.value);
             }
-            ExprKind::Struct(ref mut elem) => {
+            ExprKind::Struct(elem) => {
                 for field in &mut elem.fields {
                     self.manage_cond_expr(&mut field.expr);
                 }
-                if let StructRest::Base(ref mut local_expr) = elem.rest {
+                if let StructRest::Base(local_expr) = &mut elem.rest {
                     self.manage_cond_expr(local_expr);
                 }
             }
-            ExprKind::Tup(ref mut local_exprs) => {
+            ExprKind::Tup(local_exprs) => {
                 for local_expr in local_exprs {
                     self.manage_cond_expr(local_expr);
                 }
             }
-            ExprKind::Unary(un_op, ref mut local_expr) => {
+            ExprKind::Unary(un_op, local_expr) => {
                 self.with_is_consumed_management(
                     matches!(un_op, UnOp::Neg | UnOp::Not),
                     |this| this.manage_cond_expr(local_expr)
diff --git a/compiler/rustc_builtin_macros/src/concat.rs b/compiler/rustc_builtin_macros/src/concat.rs
index d579616ad1b..e2d71825d55 100644
--- a/compiler/rustc_builtin_macros/src/concat.rs
+++ b/compiler/rustc_builtin_macros/src/concat.rs
@@ -20,7 +20,7 @@ pub fn expand_concat(
     for e in es {
         match e.kind {
             ast::ExprKind::Lit(token_lit) => match ast::LitKind::from_token_lit(token_lit) {
-                Ok(ast::LitKind::Str(ref s, _) | ast::LitKind::Float(ref s, _)) => {
+                Ok(ast::LitKind::Str(s, _) | ast::LitKind::Float(s, _)) => {
                     accumulator.push_str(s.as_str());
                 }
                 Ok(ast::LitKind::Char(c)) => {
diff --git a/compiler/rustc_builtin_macros/src/concat_bytes.rs b/compiler/rustc_builtin_macros/src/concat_bytes.rs
index 161e3499584..d1124145dcb 100644
--- a/compiler/rustc_builtin_macros/src/concat_bytes.rs
+++ b/compiler/rustc_builtin_macros/src/concat_bytes.rs
@@ -144,8 +144,8 @@ pub fn expand_concat_bytes(
     let mut missing_literals = vec![];
     let mut has_errors = false;
     for e in es {
-        match e.kind {
-            ast::ExprKind::Array(ref exprs) => {
+        match &e.kind {
+            ast::ExprKind::Array(exprs) => {
                 for expr in exprs {
                     if let Some(elem) =
                         handle_array_element(cx, &mut has_errors, &mut missing_literals, expr)
@@ -154,7 +154,7 @@ pub fn expand_concat_bytes(
                     }
                 }
             }
-            ast::ExprKind::Repeat(ref expr, ref count) => {
+            ast::ExprKind::Repeat(expr, count) => {
                 if let ast::ExprKind::Lit(token_lit) = count.value.kind
                 && let Ok(ast::LitKind::Int(count_val, _)) =
                     ast::LitKind::from_token_lit(token_lit)
@@ -170,7 +170,7 @@ pub fn expand_concat_bytes(
                     cx.span_err(count.value.span, "repeat count is not a positive number");
                 }
             }
-            ast::ExprKind::Lit(token_lit) => match ast::LitKind::from_token_lit(token_lit) {
+            &ast::ExprKind::Lit(token_lit) => match ast::LitKind::from_token_lit(token_lit) {
                 Ok(ast::LitKind::Byte(val)) => {
                     accumulator.push(val);
                 }
@@ -184,7 +184,7 @@ pub fn expand_concat_bytes(
                     has_errors = true;
                 }
             },
-            ast::ExprKind::IncludedBytes(ref bytes) => {
+            ast::ExprKind::IncludedBytes(bytes) => {
                 accumulator.extend_from_slice(bytes);
             }
             ast::ExprKind::Err => {
diff --git a/compiler/rustc_builtin_macros/src/deriving/clone.rs b/compiler/rustc_builtin_macros/src/deriving/clone.rs
index 23b96d4176d..d59b3b8c86d 100644
--- a/compiler/rustc_builtin_macros/src/deriving/clone.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/clone.rs
@@ -32,10 +32,10 @@ pub fn expand_deriving_clone(
     let bounds;
     let substructure;
     let is_simple;
-    match *item {
-        Annotatable::Item(ref annitem) => match annitem.kind {
-            ItemKind::Struct(_, Generics { ref params, .. })
-            | ItemKind::Enum(_, Generics { ref params, .. }) => {
+    match item {
+        Annotatable::Item(annitem) => match &annitem.kind {
+            ItemKind::Struct(_, Generics { params, .. })
+            | ItemKind::Enum(_, Generics { params, .. }) => {
                 let container_id = cx.current_expansion.id.expn_data().parent.expect_local();
                 let has_derive_copy = cx.resolver.has_derive_copy(container_id);
                 if has_derive_copy
@@ -166,13 +166,13 @@ fn cs_clone(
     };
 
     let vdata;
-    match *substr.fields {
-        Struct(vdata_, ref af) => {
+    match substr.fields {
+        Struct(vdata_, af) => {
             ctor_path = cx.path(trait_span, vec![substr.type_ident]);
             all_fields = af;
-            vdata = vdata_;
+            vdata = *vdata_;
         }
-        EnumMatching(.., variant, ref af) => {
+        EnumMatching(.., variant, af) => {
             ctor_path = cx.path(trait_span, vec![substr.type_ident, variant.ident]);
             all_fields = af;
             vdata = &variant.data;
diff --git a/compiler/rustc_builtin_macros/src/deriving/decodable.rs b/compiler/rustc_builtin_macros/src/deriving/decodable.rs
index 6d14875a983..62af02c2bb4 100644
--- a/compiler/rustc_builtin_macros/src/deriving/decodable.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/decodable.rs
@@ -78,11 +78,11 @@ fn decodable_substructure(
     let blkarg = Ident::new(sym::_d, trait_span);
     let blkdecoder = cx.expr_ident(trait_span, blkarg);
 
-    let expr = match *substr.fields {
-        StaticStruct(_, ref summary) => {
-            let nfields = match *summary {
-                Unnamed(ref fields, _) => fields.len(),
-                Named(ref fields) => fields.len(),
+    let expr = match substr.fields {
+        StaticStruct(_, summary) => {
+            let nfields = match summary {
+                Unnamed(fields, _) => fields.len(),
+                Named(fields) => fields.len(),
             };
             let fn_read_struct_field_path: Vec<_> =
                 cx.def_site_path(&[sym::rustc_serialize, sym::Decoder, sym::read_struct_field]);
@@ -119,7 +119,7 @@ fn decodable_substructure(
                 ],
             )
         }
-        StaticEnum(_, ref fields) => {
+        StaticEnum(_, fields) => {
             let variant = Ident::new(sym::i, trait_span);
 
             let mut arms = Vec::with_capacity(fields.len() + 1);
@@ -194,10 +194,10 @@ fn decode_static_fields<F>(
 where
     F: FnMut(&mut ExtCtxt<'_>, Span, Symbol, usize) -> P<Expr>,
 {
-    match *fields {
-        Unnamed(ref fields, is_tuple) => {
+    match fields {
+        Unnamed(fields, is_tuple) => {
             let path_expr = cx.expr_path(outer_pat_path);
-            if !is_tuple {
+            if !*is_tuple {
                 path_expr
             } else {
                 let fields = fields
@@ -209,7 +209,7 @@ where
                 cx.expr_call(trait_span, path_expr, fields)
             }
         }
-        Named(ref fields) => {
+        Named(fields) => {
             // use the field's span to get nicer error messages.
             let fields = fields
                 .iter()
diff --git a/compiler/rustc_builtin_macros/src/deriving/default.rs b/compiler/rustc_builtin_macros/src/deriving/default.rs
index e88d2e409c6..eb66c4a69a6 100644
--- a/compiler/rustc_builtin_macros/src/deriving/default.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/default.rs
@@ -62,15 +62,12 @@ fn default_struct_substructure(
     let default_call = |span| cx.expr_call_global(span, default_ident.clone(), Vec::new());
 
     let expr = match summary {
-        Unnamed(ref fields, is_tuple) => {
-            if !is_tuple {
-                cx.expr_ident(trait_span, substr.type_ident)
-            } else {
-                let exprs = fields.iter().map(|sp| default_call(*sp)).collect();
-                cx.expr_call_ident(trait_span, substr.type_ident, exprs)
-            }
+        Unnamed(_, false) => cx.expr_ident(trait_span, substr.type_ident),
+        Unnamed(fields, true) => {
+            let exprs = fields.iter().map(|sp| default_call(*sp)).collect();
+            cx.expr_call_ident(trait_span, substr.type_ident, exprs)
         }
-        Named(ref fields) => {
+        Named(fields) => {
             let default_fields = fields
                 .iter()
                 .map(|&(ident, span)| cx.field_imm(span, ident, default_call(span)))
diff --git a/compiler/rustc_builtin_macros/src/deriving/encodable.rs b/compiler/rustc_builtin_macros/src/deriving/encodable.rs
index 9a46ca81537..68bc0ff2ec0 100644
--- a/compiler/rustc_builtin_macros/src/deriving/encodable.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/encodable.rs
@@ -164,8 +164,8 @@ fn encodable_substructure(
         ],
     ));
 
-    match *substr.fields {
-        Struct(_, ref fields) => {
+    match substr.fields {
+        Struct(_, fields) => {
             let fn_emit_struct_field_path =
                 cx.def_site_path(&[sym::rustc_serialize, sym::Encoder, sym::emit_struct_field]);
             let mut stmts = Vec::new();
@@ -224,7 +224,7 @@ fn encodable_substructure(
             BlockOrExpr::new_expr(expr)
         }
 
-        EnumMatching(idx, _, variant, ref fields) => {
+        EnumMatching(idx, _, variant, fields) => {
             // We're not generating an AST that the borrow checker is expecting,
             // so we need to generate a unique local variable to take the
             // mutable loan out on, otherwise we get conflicts which don't
@@ -274,7 +274,7 @@ fn encodable_substructure(
                 vec![
                     blkencoder,
                     name,
-                    cx.expr_usize(trait_span, idx),
+                    cx.expr_usize(trait_span, *idx),
                     cx.expr_usize(trait_span, fields.len()),
                     blk,
                 ],
diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
index 7fcaf0b436b..beac591bfc8 100644
--- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
@@ -369,15 +369,14 @@ fn find_type_parameters(
 
     impl<'a, 'b> visit::Visitor<'a> for Visitor<'a, 'b> {
         fn visit_ty(&mut self, ty: &'a ast::Ty) {
-            if let ast::TyKind::Path(_, ref path) = ty.kind {
-                if let Some(segment) = path.segments.first() {
-                    if self.ty_param_names.contains(&segment.ident.name) {
-                        self.type_params.push(TypeParameter {
-                            bound_generic_params: self.bound_generic_params_stack.clone(),
-                            ty: P(ty.clone()),
-                        });
-                    }
-                }
+            if let ast::TyKind::Path(_, path) = &ty.kind
+                && let Some(segment) = path.segments.first()
+                && self.ty_param_names.contains(&segment.ident.name)
+            {
+                self.type_params.push(TypeParameter {
+                    bound_generic_params: self.bound_generic_params_stack.clone(),
+                    ty: P(ty.clone()),
+                });
             }
 
             visit::walk_ty(self, ty)
@@ -428,8 +427,8 @@ impl<'a> TraitDef<'a> {
         push: &mut dyn FnMut(Annotatable),
         from_scratch: bool,
     ) {
-        match *item {
-            Annotatable::Item(ref item) => {
+        match item {
+            Annotatable::Item(item) => {
                 let is_packed = item.attrs.iter().any(|attr| {
                     for r in attr::find_repr_attrs(&cx.sess, attr) {
                         if let attr::ReprPacked(_) = r {
@@ -438,10 +437,10 @@ impl<'a> TraitDef<'a> {
                     }
                     false
                 });
-                let has_no_type_params = match item.kind {
-                    ast::ItemKind::Struct(_, ref generics)
-                    | ast::ItemKind::Enum(_, ref generics)
-                    | ast::ItemKind::Union(_, ref generics) => !generics
+                let has_no_type_params = match &item.kind {
+                    ast::ItemKind::Struct(_, generics)
+                    | ast::ItemKind::Enum(_, generics)
+                    | ast::ItemKind::Union(_, generics) => !generics
                         .params
                         .iter()
                         .any(|param| matches!(param.kind, ast::GenericParamKind::Type { .. })),
@@ -451,8 +450,8 @@ impl<'a> TraitDef<'a> {
                 let copy_fields =
                     is_packed && has_no_type_params && cx.resolver.has_derive_copy(container_id);
 
-                let newitem = match item.kind {
-                    ast::ItemKind::Struct(ref struct_def, ref generics) => self.expand_struct_def(
+                let newitem = match &item.kind {
+                    ast::ItemKind::Struct(struct_def, generics) => self.expand_struct_def(
                         cx,
                         &struct_def,
                         item.ident,
@@ -460,7 +459,7 @@ impl<'a> TraitDef<'a> {
                         from_scratch,
                         copy_fields,
                     ),
-                    ast::ItemKind::Enum(ref enum_def, ref generics) => {
+                    ast::ItemKind::Enum(enum_def, generics) => {
                         // We ignore `is_packed` here, because `repr(packed)`
                         // enums cause an error later on.
                         //
@@ -468,7 +467,7 @@ impl<'a> TraitDef<'a> {
                         // downstream in blatantly illegal code, so it is fine.
                         self.expand_enum_def(cx, enum_def, item.ident, generics, from_scratch)
                     }
-                    ast::ItemKind::Union(ref struct_def, ref generics) => {
+                    ast::ItemKind::Union(struct_def, generics) => {
                         if self.supports_unions {
                             self.expand_struct_def(
                                 cx,
@@ -663,12 +662,11 @@ impl<'a> TraitDef<'a> {
 
                     for field_ty_param in field_ty_params {
                         // if we have already handled this type, skip it
-                        if let ast::TyKind::Path(_, ref p) = field_ty_param.ty.kind {
-                            if p.segments.len() == 1
-                                && ty_param_names.contains(&p.segments[0].ident.name)
-                            {
-                                continue;
-                            };
+                        if let ast::TyKind::Path(_, p) = &field_ty_param.ty.kind
+                            && let [sole_segment] = &*p.segments
+                            && ty_param_names.contains(&sole_segment.ident.name)
+                        {
+                            continue;
                         }
                         let mut bounds: Vec<_> = self
                             .additional_bounds
diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs b/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs
index 36e2e293086..eaa4881906a 100644
--- a/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs
@@ -115,7 +115,7 @@ impl Ty {
         self_ty: Ident,
         generics: &Generics,
     ) -> ast::Path {
-        match *self {
+        match self {
             Self_ => {
                 let params: Vec<_> = generics
                     .params
@@ -135,7 +135,7 @@ impl Ty {
 
                 cx.path_all(span, false, vec![self_ty], params)
             }
-            Path(ref p) => p.to_path(cx, span, self_ty, generics),
+            Path(p) => p.to_path(cx, span, self_ty, generics),
             Ref(..) => cx.span_bug(span, "ref in a path in generic `derive`"),
             Unit => cx.span_bug(span, "unit in a path in generic `derive`"),
         }
@@ -180,10 +180,7 @@ impl Bounds {
         let params = self
             .bounds
             .iter()
-            .map(|t| {
-                let (name, ref bounds) = *t;
-                mk_ty_param(cx, span, name, &bounds, self_ty, self_generics)
-            })
+            .map(|&(name, ref bounds)| mk_ty_param(cx, span, name, &bounds, self_ty, self_generics))
             .collect();
 
         Generics {
diff --git a/compiler/rustc_builtin_macros/src/deriving/mod.rs b/compiler/rustc_builtin_macros/src/deriving/mod.rs
index 13fdd4fa68c..de657e4e600 100644
--- a/compiler/rustc_builtin_macros/src/deriving/mod.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/mod.rs
@@ -125,12 +125,12 @@ fn inject_impl_of_structural_trait(
     structural_path: generic::ty::Path,
     push: &mut dyn FnMut(Annotatable),
 ) {
-    let Annotatable::Item(ref item) = *item else {
+    let Annotatable::Item(item) = item else {
         unreachable!();
     };
 
-    let generics = match item.kind {
-        ItemKind::Struct(_, ref generics) | ItemKind::Enum(_, ref generics) => generics,
+    let generics = match &item.kind {
+        ItemKind::Struct(_, generics) | ItemKind::Enum(_, generics) => generics,
         // Do not inject `impl Structural for Union`. (`PartialEq` does not
         // support unions, so we will see error downstream.)
         ItemKind::Union(..) => return,
diff --git a/compiler/rustc_builtin_macros/src/env.rs b/compiler/rustc_builtin_macros/src/env.rs
index b8828fa671a..0b4e545f7a3 100644
--- a/compiler/rustc_builtin_macros/src/env.rs
+++ b/compiler/rustc_builtin_macros/src/env.rs
@@ -53,7 +53,7 @@ pub fn expand_env<'cx>(
     tts: TokenStream,
 ) -> Box<dyn base::MacResult + 'cx> {
     let mut exprs = match get_exprs_from_tts(cx, sp, tts) {
-        Some(ref exprs) if exprs.is_empty() => {
+        Some(exprs) if exprs.is_empty() => {
             cx.span_err(sp, "env! takes 1 or 2 arguments");
             return DummyResult::any(sp);
         }
diff --git a/compiler/rustc_builtin_macros/src/format_foreign.rs b/compiler/rustc_builtin_macros/src/format_foreign.rs
index ecd16736e7c..6f7fc3a95ba 100644
--- a/compiler/rustc_builtin_macros/src/format_foreign.rs
+++ b/compiler/rustc_builtin_macros/src/format_foreign.rs
@@ -13,23 +13,23 @@ pub(crate) mod printf {
 
     impl<'a> Substitution<'a> {
         pub fn as_str(&self) -> &str {
-            match *self {
-                Substitution::Format(ref fmt) => fmt.span,
+            match self {
+                Substitution::Format(fmt) => fmt.span,
                 Substitution::Escape(_) => "%%",
             }
         }
 
         pub fn position(&self) -> Option<InnerSpan> {
-            match *self {
-                Substitution::Format(ref fmt) => Some(fmt.position),
-                Substitution::Escape((start, end)) => Some(InnerSpan::new(start, end)),
+            match self {
+                Substitution::Format(fmt) => Some(fmt.position),
+                &Substitution::Escape((start, end)) => Some(InnerSpan::new(start, end)),
             }
         }
 
         pub fn set_position(&mut self, start: usize, end: usize) {
             match self {
-                Substitution::Format(ref mut fmt) => fmt.position = InnerSpan::new(start, end),
-                Substitution::Escape(ref mut pos) => *pos = (start, end),
+                Substitution::Format(fmt) => fmt.position = InnerSpan::new(start, end),
+                Substitution::Escape(pos) => *pos = (start, end),
             }
         }
 
@@ -38,8 +38,8 @@ pub(crate) mod printf {
         /// This ignores cases where the substitution does not have an exact equivalent, or where
         /// the substitution would be unnecessary.
         pub fn translate(&self) -> Result<String, Option<String>> {
-            match *self {
-                Substitution::Format(ref fmt) => fmt.translate(),
+            match self {
+                Substitution::Format(fmt) => fmt.translate(),
                 Substitution::Escape(_) => Err(None),
             }
         }
@@ -635,23 +635,17 @@ pub mod shell {
         }
 
         pub fn position(&self) -> Option<InnerSpan> {
-            match self {
-                Substitution::Ordinal(_, pos)
-                | Substitution::Name(_, pos)
-                | Substitution::Escape(pos) => Some(InnerSpan::new(pos.0, pos.1)),
-            }
+            let (Self::Ordinal(_, pos) | Self::Name(_, pos) | Self::Escape(pos)) = self;
+            Some(InnerSpan::new(pos.0, pos.1))
         }
 
         pub fn set_position(&mut self, start: usize, end: usize) {
-            match self {
-                Substitution::Ordinal(_, ref mut pos)
-                | Substitution::Name(_, ref mut pos)
-                | Substitution::Escape(ref mut pos) => *pos = (start, end),
-            }
+            let (Self::Ordinal(_, pos) | Self::Name(_, pos) | Self::Escape(pos)) = self;
+            *pos = (start, end);
         }
 
         pub fn translate(&self) -> Result<String, Option<String>> {
-            match *self {
+            match self {
                 Substitution::Ordinal(n, _) => Ok(format!("{{{}}}", n)),
                 Substitution::Name(n, _) => Ok(format!("{{{}}}", n)),
                 Substitution::Escape(_) => Err(None),
diff --git a/compiler/rustc_builtin_macros/src/global_allocator.rs b/compiler/rustc_builtin_macros/src/global_allocator.rs
index 0817aed037e..41531580c19 100644
--- a/compiler/rustc_builtin_macros/src/global_allocator.rs
+++ b/compiler/rustc_builtin_macros/src/global_allocator.rs
@@ -20,27 +20,23 @@ pub fn expand(
     check_builtin_macro_attribute(ecx, meta_item, sym::global_allocator);
 
     let orig_item = item.clone();
-    let not_static = || {
-        ecx.sess.parse_sess.span_diagnostic.span_err(item.span(), "allocators must be statics");
-        vec![orig_item.clone()]
-    };
 
     // Allow using `#[global_allocator]` on an item statement
     // FIXME - if we get deref patterns, use them to reduce duplication here
-    let (item, is_stmt, ty_span) = match &item {
-        Annotatable::Item(item) => match item.kind {
-            ItemKind::Static(ref ty, ..) => (item, false, ecx.with_def_site_ctxt(ty.span)),
-            _ => return not_static(),
-        },
-        Annotatable::Stmt(stmt) => match &stmt.kind {
-            StmtKind::Item(item_) => match item_.kind {
-                ItemKind::Static(ref ty, ..) => (item_, true, ecx.with_def_site_ctxt(ty.span)),
-                _ => return not_static(),
-            },
-            _ => return not_static(),
-        },
-        _ => return not_static(),
-    };
+    let (item, is_stmt, ty_span) =
+        if let Annotatable::Item(item) = &item
+            && let ItemKind::Static(ty, ..) = &item.kind
+        {
+            (item, false, ecx.with_def_site_ctxt(ty.span))
+        } else if let Annotatable::Stmt(stmt) = &item
+            && let StmtKind::Item(item) = &stmt.kind
+            && let ItemKind::Static(ty, ..) = &item.kind
+        {
+            (item, true, ecx.with_def_site_ctxt(ty.span))
+        } else {
+            ecx.sess.parse_sess.span_diagnostic.span_err(item.span(), "allocators must be statics");
+            return vec![orig_item.clone()]
+        };
 
     // Generate a bunch of new items using the AllocFnFactory
     let span = ecx.with_def_site_ctxt(item.span);
diff --git a/compiler/rustc_builtin_macros/src/test.rs b/compiler/rustc_builtin_macros/src/test.rs
index 3bcb60478ef..f5f02fc772a 100644
--- a/compiler/rustc_builtin_macros/src/test.rs
+++ b/compiler/rustc_builtin_macros/src/test.rs
@@ -466,61 +466,67 @@ fn test_type(cx: &ExtCtxt<'_>) -> TestType {
 fn has_test_signature(cx: &ExtCtxt<'_>, i: &ast::Item) -> bool {
     let has_should_panic_attr = cx.sess.contains_name(&i.attrs, sym::should_panic);
     let sd = &cx.sess.parse_sess.span_diagnostic;
-    if let ast::ItemKind::Fn(box ast::Fn { ref sig, ref generics, .. }) = i.kind {
-        if let ast::Unsafe::Yes(span) = sig.header.unsafety {
-            sd.struct_span_err(i.span, "unsafe functions cannot be used for tests")
-                .span_label(span, "`unsafe` because of this")
-                .emit();
-            return false;
-        }
-        if let ast::Async::Yes { span, .. } = sig.header.asyncness {
-            sd.struct_span_err(i.span, "async functions cannot be used for tests")
-                .span_label(span, "`async` because of this")
-                .emit();
-            return false;
-        }
-
-        // If the termination trait is active, the compiler will check that the output
-        // type implements the `Termination` trait as `libtest` enforces that.
-        let has_output = match sig.decl.output {
-            ast::FnRetTy::Default(..) => false,
-            ast::FnRetTy::Ty(ref t) if t.kind.is_unit() => false,
-            _ => true,
-        };
-
-        if !sig.decl.inputs.is_empty() {
-            sd.span_err(i.span, "functions used as tests can not have any arguments");
-            return false;
-        }
+    match &i.kind {
+        ast::ItemKind::Fn(box ast::Fn { sig, generics, .. }) => {
+            if let ast::Unsafe::Yes(span) = sig.header.unsafety {
+                sd.struct_span_err(i.span, "unsafe functions cannot be used for tests")
+                    .span_label(span, "`unsafe` because of this")
+                    .emit();
+                return false;
+            }
+            if let ast::Async::Yes { span, .. } = sig.header.asyncness {
+                sd.struct_span_err(i.span, "async functions cannot be used for tests")
+                    .span_label(span, "`async` because of this")
+                    .emit();
+                return false;
+            }
 
-        match (has_output, has_should_panic_attr) {
-            (true, true) => {
-                sd.span_err(i.span, "functions using `#[should_panic]` must return `()`");
-                false
+            // If the termination trait is active, the compiler will check that the output
+            // type implements the `Termination` trait as `libtest` enforces that.
+            let has_output = match &sig.decl.output {
+                ast::FnRetTy::Default(..) => false,
+                ast::FnRetTy::Ty(t) if t.kind.is_unit() => false,
+                _ => true,
+            };
+
+            if !sig.decl.inputs.is_empty() {
+                sd.span_err(i.span, "functions used as tests can not have any arguments");
+                return false;
             }
-            (true, false) => {
-                if !generics.params.is_empty() {
-                    sd.span_err(i.span, "functions used as tests must have signature fn() -> ()");
+
+            match (has_output, has_should_panic_attr) {
+                (true, true) => {
+                    sd.span_err(i.span, "functions using `#[should_panic]` must return `()`");
                     false
-                } else {
-                    true
                 }
+                (true, false) => {
+                    if !generics.params.is_empty() {
+                        sd.span_err(
+                            i.span,
+                            "functions used as tests must have signature fn() -> ()",
+                        );
+                        false
+                    } else {
+                        true
+                    }
+                }
+                (false, _) => true,
             }
-            (false, _) => true,
         }
-    } else {
-        // should be unreachable because `is_test_fn_item` should catch all non-fn items
-        false
+        _ => {
+            // should be unreachable because `is_test_fn_item` should catch all non-fn items
+            debug_assert!(false);
+            false
+        }
     }
 }
 
 fn has_bench_signature(cx: &ExtCtxt<'_>, i: &ast::Item) -> bool {
-    let has_sig = if let ast::ItemKind::Fn(box ast::Fn { ref sig, .. }) = i.kind {
+    let has_sig = match &i.kind {
         // N.B., inadequate check, but we're running
         // well before resolve, can't get too deep.
-        sig.decl.inputs.len() == 1
-    } else {
-        false
+        ast::ItemKind::Fn(box ast::Fn { sig, .. }) => sig.decl.inputs.len() == 1,
+        _ => false,
     };
 
     if !has_sig {
diff --git a/compiler/rustc_builtin_macros/src/test_harness.rs b/compiler/rustc_builtin_macros/src/test_harness.rs
index b5bce9278a9..ad887108091 100644
--- a/compiler/rustc_builtin_macros/src/test_harness.rs
+++ b/compiler/rustc_builtin_macros/src/test_harness.rs
@@ -131,8 +131,9 @@ impl<'a> MutVisitor for TestHarnessGenerator<'a> {
 
         // We don't want to recurse into anything other than mods, since
         // mods or tests inside of functions will break things
-        if let ast::ItemKind::Mod(_, ModKind::Loaded(.., ref spans)) = item.kind {
-            let ast::ModSpans { inner_span: span, inject_use_span: _ } = *spans;
+        if let ast::ItemKind::Mod(_, ModKind::Loaded(.., ast::ModSpans { inner_span: span, .. })) =
+            item.kind
+        {
             let prev_tests = mem::take(&mut self.tests);
             noop_visit_item_kind(&mut item.kind, self);
             self.add_test_cases(item.id, span, prev_tests);
diff --git a/compiler/rustc_codegen_gcc/src/consts.rs b/compiler/rustc_codegen_gcc/src/consts.rs
index 111bfeb1322..ea8ab761146 100644
--- a/compiler/rustc_codegen_gcc/src/consts.rs
+++ b/compiler/rustc_codegen_gcc/src/consts.rs
@@ -8,13 +8,11 @@ use rustc_middle::mir::mono::MonoItem;
 use rustc_middle::ty::{self, Instance, Ty};
 use rustc_middle::ty::layout::LayoutOf;
 use rustc_middle::mir::interpret::{self, ConstAllocation, ErrorHandled, Scalar as InterpScalar, read_target_uint};
-use rustc_span::Span;
 use rustc_span::def_id::DefId;
 use rustc_target::abi::{self, Align, HasDataLayout, Primitive, Size, WrappingRange};
 
 use crate::base;
 use crate::context::CodegenCx;
-use crate::errors::LinkageConstOrMutType;
 use crate::type_of::LayoutGccExt;
 
 impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
@@ -239,12 +237,12 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
                     }
 
                     Node::ForeignItem(&hir::ForeignItem {
-                        span,
+                        span: _,
                         kind: hir::ForeignItemKind::Static(..),
                         ..
                     }) => {
                         let fn_attrs = self.tcx.codegen_fn_attrs(def_id);
-                        check_and_apply_linkage(&self, &fn_attrs, ty, sym, span)
+                        check_and_apply_linkage(&self, &fn_attrs, ty, sym)
                     }
 
                     item => bug!("get_static: expected static, found {:?}", item),
@@ -257,8 +255,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
                 //debug!("get_static: sym={} item_attr={:?}", sym, self.tcx.item_attrs(def_id));
 
                 let attrs = self.tcx.codegen_fn_attrs(def_id);
-                let span = self.tcx.def_span(def_id);
-                let global = check_and_apply_linkage(&self, &attrs, ty, sym, span);
+                let global = check_and_apply_linkage(&self, &attrs, ty, sym);
 
                 let needs_dll_storage_attr = false; // TODO(antoyo)
 
@@ -355,24 +352,12 @@ pub fn codegen_static_initializer<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, def_id
     Ok((const_alloc_to_gcc(cx, alloc), alloc))
 }
 
-fn check_and_apply_linkage<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, attrs: &CodegenFnAttrs, ty: Ty<'tcx>, sym: &str, span: Span) -> LValue<'gcc> {
+fn check_and_apply_linkage<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, attrs: &CodegenFnAttrs, ty: Ty<'tcx>, sym: &str) -> LValue<'gcc> {
     let is_tls = attrs.flags.contains(CodegenFnAttrFlags::THREAD_LOCAL);
     let llty = cx.layout_of(ty).gcc_type(cx, true);
-    if let Some(linkage) = attrs.linkage {
-        // If this is a static with a linkage specified, then we need to handle
-        // it a little specially. The typesystem prevents things like &T and
-        // extern "C" fn() from being non-null, so we can't just declare a
-        // static and call it a day. Some linkages (like weak) will make it such
-        // that the static actually has a null value.
-        let llty2 =
-            if let ty::RawPtr(ref mt) = ty.kind() {
-                cx.layout_of(mt.ty).gcc_type(cx, true)
-            }
-            else {
-                cx.sess().emit_fatal(LinkageConstOrMutType { span: span })
-            };
+    if let Some(linkage) = attrs.import_linkage {
         // Declare a symbol `foo` with the desired linkage.
-        let global1 = cx.declare_global_with_linkage(&sym, llty2, base::global_linkage_to_gcc(linkage));
+        let global1 = cx.declare_global_with_linkage(&sym, cx.type_i8(), base::global_linkage_to_gcc(linkage));
 
         // Declare an internal global `extern_with_linkage_foo` which
         // is initialized with the address of `foo`.  If `foo` is
diff --git a/compiler/rustc_codegen_gcc/src/errors.rs b/compiler/rustc_codegen_gcc/src/errors.rs
index 89fed7be131..d0ba7e24791 100644
--- a/compiler/rustc_codegen_gcc/src/errors.rs
+++ b/compiler/rustc_codegen_gcc/src/errors.rs
@@ -212,13 +212,6 @@ pub(crate) struct InvalidMonomorphizationUnsupportedOperation<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(codegen_gcc_linkage_const_or_mut_type)]
-pub(crate) struct LinkageConstOrMutType {
-    #[primary_span]
-    pub span: Span,
-}
-
-#[derive(Diagnostic)]
 #[diag(codegen_gcc_lto_not_supported)]
 pub(crate) struct LTONotSupported;
 
diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs
index 3c324359565..3626aa901c0 100644
--- a/compiler/rustc_codegen_llvm/src/consts.rs
+++ b/compiler/rustc_codegen_llvm/src/consts.rs
@@ -1,7 +1,7 @@
 use crate::base;
 use crate::common::{self, CodegenCx};
 use crate::debuginfo;
-use crate::errors::{InvalidMinimumAlignment, LinkageConstOrMutType, SymbolAlreadyDefined};
+use crate::errors::{InvalidMinimumAlignment, SymbolAlreadyDefined};
 use crate::llvm::{self, True};
 use crate::llvm_util;
 use crate::type_::Type;
@@ -162,22 +162,12 @@ fn check_and_apply_linkage<'ll, 'tcx>(
     def_id: DefId,
 ) -> &'ll Value {
     let llty = cx.layout_of(ty).llvm_type(cx);
-    if let Some(linkage) = attrs.linkage {
+    if let Some(linkage) = attrs.import_linkage {
         debug!("get_static: sym={} linkage={:?}", sym, linkage);
 
-        // If this is a static with a linkage specified, then we need to handle
-        // it a little specially. The typesystem prevents things like &T and
-        // extern "C" fn() from being non-null, so we can't just declare a
-        // static and call it a day. Some linkages (like weak) will make it such
-        // that the static actually has a null value.
-        let llty2 = if let ty::RawPtr(ref mt) = ty.kind() {
-            cx.layout_of(mt.ty).llvm_type(cx)
-        } else {
-            cx.sess().emit_fatal(LinkageConstOrMutType { span: cx.tcx.def_span(def_id) })
-        };
         unsafe {
             // Declare a symbol `foo` with the desired linkage.
-            let g1 = cx.declare_global(sym, llty2);
+            let g1 = cx.declare_global(sym, cx.type_i8());
             llvm::LLVMRustSetLinkage(g1, base::linkage_to_llvm(linkage));
 
             // Declare an internal global `extern_with_linkage_foo` which
@@ -195,7 +185,7 @@ fn check_and_apply_linkage<'ll, 'tcx>(
                 })
             });
             llvm::LLVMRustSetLinkage(g2, llvm::Linkage::InternalLinkage);
-            llvm::LLVMSetInitializer(g2, g1);
+            llvm::LLVMSetInitializer(g2, cx.const_ptrcast(g1, llty));
             g2
         }
     } else if cx.tcx.sess.target.arch == "x86" &&
diff --git a/compiler/rustc_codegen_llvm/src/errors.rs b/compiler/rustc_codegen_llvm/src/errors.rs
index fddfbb23c67..af9f31fc324 100644
--- a/compiler/rustc_codegen_llvm/src/errors.rs
+++ b/compiler/rustc_codegen_llvm/src/errors.rs
@@ -62,13 +62,6 @@ pub(crate) struct InvalidMinimumAlignment {
 }
 
 #[derive(Diagnostic)]
-#[diag(codegen_llvm_linkage_const_or_mut_type)]
-pub(crate) struct LinkageConstOrMutType {
-    #[primary_span]
-    pub span: Span,
-}
-
-#[derive(Diagnostic)]
 #[diag(codegen_llvm_sanitizer_memtag_requires_mte)]
 pub(crate) struct SanitizerMemtagRequiresMte;
 
diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs
index 7cb4f5503a1..882430694e1 100644
--- a/compiler/rustc_codegen_ssa/src/back/link.rs
+++ b/compiler/rustc_codegen_ssa/src/back/link.rs
@@ -102,7 +102,7 @@ pub fn link_binary<'a>(
                 sess,
                 crate_type,
                 outputs,
-                codegen_results.crate_info.local_crate_name.as_str(),
+                codegen_results.crate_info.local_crate_name,
             );
             match crate_type {
                 CrateType::Rlib => {
@@ -2352,15 +2352,6 @@ fn add_native_libs_from_crate(
                                 &search_paths.get_or_init(|| archive_search_paths(sess)),
                             );
                         } else {
-                            // HACK/FIXME: Fixup a circular dependency between libgcc and libc
-                            // with glibc. This logic should be moved to the libc crate.
-                            if cnum != LOCAL_CRATE
-                                && sess.target.os == "linux"
-                                && sess.target.env == "gnu"
-                                && name == "c"
-                            {
-                                cmd.link_staticlib("gcc", false);
-                            }
                             cmd.link_staticlib(name, verbatim)
                         }
                     }
diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs
index 04e68b96455..3dfded2d930 100644
--- a/compiler/rustc_const_eval/src/const_eval/machine.rs
+++ b/compiler/rustc_const_eval/src/const_eval/machine.rs
@@ -240,7 +240,7 @@ impl<'mir, 'tcx: 'mir> CompileTimeEvalContext<'mir, 'tcx> {
                     let align = ImmTy::from_uint(target_align, args[1].layout).into();
                     let fn_abi = self.fn_abi_of_instance(instance, ty::List::empty())?;
 
-                    // We replace the entire entire function call with a "tail call".
+                    // We replace the entire function call with a "tail call".
                     // Note that this happens before the frame of the original function
                     // is pushed on the stack.
                     self.eval_fn_call(
diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs
index 79450fccfc4..e17d3e516a6 100644
--- a/compiler/rustc_const_eval/src/interpret/eval_context.rs
+++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs
@@ -676,6 +676,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         return_to_block: StackPopCleanup,
     ) -> InterpResult<'tcx> {
         trace!("body: {:#?}", body);
+        // Clobber previous return place contents, nobody is supposed to be able to see them any more
+        // This also checks dereferenceable, but not align. We rely on all constructed places being
+        // sufficiently aligned (in particular we rely on `deref_operand` checking alignment).
+        self.write_uninit(return_place)?;
         // first push a stack frame so we have access to the local substs
         let pre_frame = Frame {
             body,
diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs
index 88d25be6bd8..0604d5ee6fa 100644
--- a/compiler/rustc_const_eval/src/interpret/machine.rs
+++ b/compiler/rustc_const_eval/src/interpret/machine.rs
@@ -373,9 +373,21 @@ pub trait Machine<'mir, 'tcx>: Sized {
         Ok(())
     }
 
-    /// Executes a retagging operation.
+    /// Executes a retagging operation for a single pointer.
+    /// Returns the possibly adjusted pointer.
     #[inline]
-    fn retag(
+    fn retag_ptr_value(
+        _ecx: &mut InterpCx<'mir, 'tcx, Self>,
+        _kind: mir::RetagKind,
+        val: &ImmTy<'tcx, Self::Provenance>,
+    ) -> InterpResult<'tcx, ImmTy<'tcx, Self::Provenance>> {
+        Ok(val.clone())
+    }
+
+    /// Executes a retagging operation on a compound value.
+    /// Replaces all pointers stored in the given place.
+    #[inline]
+    fn retag_place_contents(
         _ecx: &mut InterpCx<'mir, 'tcx, Self>,
         _kind: mir::RetagKind,
         _place: &PlaceTy<'tcx, Self::Provenance>,
diff --git a/compiler/rustc_const_eval/src/interpret/step.rs b/compiler/rustc_const_eval/src/interpret/step.rs
index 60578246eed..81b44a49484 100644
--- a/compiler/rustc_const_eval/src/interpret/step.rs
+++ b/compiler/rustc_const_eval/src/interpret/step.rs
@@ -8,7 +8,7 @@ use rustc_middle::mir;
 use rustc_middle::mir::interpret::{InterpResult, Scalar};
 use rustc_middle::ty::layout::LayoutOf;
 
-use super::{InterpCx, Machine};
+use super::{ImmTy, InterpCx, Machine};
 
 /// Classify whether an operator is "left-homogeneous", i.e., the LHS has the
 /// same type as the result.
@@ -108,7 +108,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             // Stacked Borrows.
             Retag(kind, place) => {
                 let dest = self.eval_place(**place)?;
-                M::retag(self, *kind, &dest)?;
+                M::retag_place_contents(self, *kind, &dest)?;
             }
 
             Intrinsic(box ref intrinsic) => self.emulate_nondiverging_intrinsic(intrinsic)?,
@@ -247,10 +247,41 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 self.write_scalar(Scalar::from_machine_usize(len, self), &dest)?;
             }
 
-            AddressOf(_, place) | Ref(_, _, place) => {
+            Ref(_, borrow_kind, place) => {
                 let src = self.eval_place(place)?;
                 let place = self.force_allocation(&src)?;
-                self.write_immediate(place.to_ref(self), &dest)?;
+                let val = ImmTy::from_immediate(place.to_ref(self), dest.layout);
+                // A fresh reference was created, make sure it gets retagged.
+                let val = M::retag_ptr_value(
+                    self,
+                    if borrow_kind.allows_two_phase_borrow() {
+                        mir::RetagKind::TwoPhase
+                    } else {
+                        mir::RetagKind::Default
+                    },
+                    &val,
+                )?;
+                self.write_immediate(*val, &dest)?;
+            }
+
+            AddressOf(_, place) => {
+                // Figure out whether this is an addr_of of an already raw place.
+                let place_base_raw = if place.has_deref() {
+                    let ty = self.frame().body.local_decls[place.local].ty;
+                    ty.is_unsafe_ptr()
+                } else {
+                    // Not a deref, and thus not raw.
+                    false
+                };
+
+                let src = self.eval_place(place)?;
+                let place = self.force_allocation(&src)?;
+                let mut val = ImmTy::from_immediate(place.to_ref(self), dest.layout);
+                if !place_base_raw {
+                    // If this was not already raw, it needs retagging.
+                    val = M::retag_ptr_value(self, mir::RetagKind::Raw, &val)?;
+                }
+                self.write_immediate(*val, &dest)?;
             }
 
             NullaryOp(null_op, ty) => {
diff --git a/compiler/rustc_data_structures/src/fingerprint.rs b/compiler/rustc_data_structures/src/fingerprint.rs
index a39178016ce..d98f4e43fe8 100644
--- a/compiler/rustc_data_structures/src/fingerprint.rs
+++ b/compiler/rustc_data_structures/src/fingerprint.rs
@@ -140,7 +140,7 @@ impl stable_hasher::StableHasherResult for Fingerprint {
     }
 }
 
-impl_stable_hash_via_hash!(Fingerprint);
+impl_stable_traits_for_trivial_type!(Fingerprint);
 
 impl<E: Encoder> Encodable<E> for Fingerprint {
     #[inline]
diff --git a/compiler/rustc_data_structures/src/intern.rs b/compiler/rustc_data_structures/src/intern.rs
index 76a1288e6d3..ba94f3776eb 100644
--- a/compiler/rustc_data_structures/src/intern.rs
+++ b/compiler/rustc_data_structures/src/intern.rs
@@ -4,8 +4,6 @@ use std::hash::{Hash, Hasher};
 use std::ops::Deref;
 use std::ptr;
 
-use crate::fingerprint::Fingerprint;
-
 mod private {
     #[derive(Clone, Copy, Debug)]
     pub struct PrivateZst;
@@ -110,86 +108,5 @@ where
     }
 }
 
-/// A helper type that you can wrap round your own type in order to automatically
-/// cache the stable hash on creation and not recompute it whenever the stable hash
-/// of the type is computed.
-/// This is only done in incremental mode. You can also opt out of caching by using
-/// StableHash::ZERO for the hash, in which case the hash gets computed each time.
-/// This is useful if you have values that you intern but never (can?) use for stable
-/// hashing.
-#[derive(Copy, Clone)]
-pub struct WithStableHash<T> {
-    pub internee: T,
-    pub stable_hash: Fingerprint,
-}
-
-impl<T: PartialEq> PartialEq for WithStableHash<T> {
-    #[inline]
-    fn eq(&self, other: &Self) -> bool {
-        self.internee.eq(&other.internee)
-    }
-}
-
-impl<T: Eq> Eq for WithStableHash<T> {}
-
-impl<T: Ord> PartialOrd for WithStableHash<T> {
-    fn partial_cmp(&self, other: &WithStableHash<T>) -> Option<Ordering> {
-        Some(self.internee.cmp(&other.internee))
-    }
-}
-
-impl<T: Ord> Ord for WithStableHash<T> {
-    fn cmp(&self, other: &WithStableHash<T>) -> Ordering {
-        self.internee.cmp(&other.internee)
-    }
-}
-
-impl<T> Deref for WithStableHash<T> {
-    type Target = T;
-
-    #[inline]
-    fn deref(&self) -> &T {
-        &self.internee
-    }
-}
-
-impl<T: Hash> Hash for WithStableHash<T> {
-    #[inline]
-    fn hash<H: Hasher>(&self, s: &mut H) {
-        if self.stable_hash != Fingerprint::ZERO {
-            self.stable_hash.hash(s)
-        } else {
-            self.internee.hash(s)
-        }
-    }
-}
-
-impl<T: HashStable<CTX>, CTX> HashStable<CTX> for WithStableHash<T> {
-    fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
-        if self.stable_hash == Fingerprint::ZERO || cfg!(debug_assertions) {
-            // No cached hash available. This can only mean that incremental is disabled.
-            // We don't cache stable hashes in non-incremental mode, because they are used
-            // so rarely that the performance actually suffers.
-
-            // We need to build the hash as if we cached it and then hash that hash, as
-            // otherwise the hashes will differ between cached and non-cached mode.
-            let stable_hash: Fingerprint = {
-                let mut hasher = StableHasher::new();
-                self.internee.hash_stable(hcx, &mut hasher);
-                hasher.finish()
-            };
-            if cfg!(debug_assertions) && self.stable_hash != Fingerprint::ZERO {
-                assert_eq!(
-                    stable_hash, self.stable_hash,
-                    "cached stable hash does not match freshly computed stable hash"
-                );
-            }
-            stable_hash.hash_stable(hcx, hasher);
-        } else {
-            self.stable_hash.hash_stable(hcx, hasher);
-        }
-    }
-}
-
 #[cfg(test)]
 mod tests;
diff --git a/compiler/rustc_data_structures/src/sorted_map.rs b/compiler/rustc_data_structures/src/sorted_map.rs
index d607a5c8314..d13313dfd0e 100644
--- a/compiler/rustc_data_structures/src/sorted_map.rs
+++ b/compiler/rustc_data_structures/src/sorted_map.rs
@@ -1,4 +1,4 @@
-use crate::stable_hasher::{HashStable, StableHasher};
+use crate::stable_hasher::{HashStable, StableHasher, StableOrd};
 use std::borrow::Borrow;
 use std::cmp::Ordering;
 use std::iter::FromIterator;
@@ -308,7 +308,7 @@ impl<K: Ord, V> FromIterator<(K, V)> for SortedMap<K, V> {
     }
 }
 
-impl<K: HashStable<CTX>, V: HashStable<CTX>, CTX> HashStable<CTX> for SortedMap<K, V> {
+impl<K: HashStable<CTX> + StableOrd, V: HashStable<CTX>, CTX> HashStable<CTX> for SortedMap<K, V> {
     #[inline]
     fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
         self.data.hash_stable(ctx, hasher);
diff --git a/compiler/rustc_data_structures/src/sorted_map/index_map.rs b/compiler/rustc_data_structures/src/sorted_map/index_map.rs
index 0ec32dc4307..c2f0ae32896 100644
--- a/compiler/rustc_data_structures/src/sorted_map/index_map.rs
+++ b/compiler/rustc_data_structures/src/sorted_map/index_map.rs
@@ -120,13 +120,20 @@ where
         self.items.hash(hasher)
     }
 }
+
 impl<I: Idx, K, V, C> HashStable<C> for SortedIndexMultiMap<I, K, V>
 where
     K: HashStable<C>,
     V: HashStable<C>,
 {
     fn hash_stable(&self, ctx: &mut C, hasher: &mut StableHasher) {
-        self.items.hash_stable(ctx, hasher)
+        let SortedIndexMultiMap {
+            items,
+            // We can ignore this field because it is not observable from the outside.
+            idx_sorted_by_item_key: _,
+        } = self;
+
+        items.hash_stable(ctx, hasher)
     }
 }
 
diff --git a/compiler/rustc_data_structures/src/stable_hasher.rs b/compiler/rustc_data_structures/src/stable_hasher.rs
index cd392a7b678..1a728f82f00 100644
--- a/compiler/rustc_data_structures/src/stable_hasher.rs
+++ b/compiler/rustc_data_structures/src/stable_hasher.rs
@@ -219,7 +219,35 @@ pub trait ToStableHashKey<HCX> {
     fn to_stable_hash_key(&self, hcx: &HCX) -> Self::KeyType;
 }
 
-/// Implement HashStable by just calling `Hash::hash()`.
+/// Trait for marking a type as having a sort order that is
+/// stable across compilation session boundaries. More formally:
+///
+/// ```txt
+/// Ord::cmp(a1, b1) == Ord:cmp(a2, b2)
+///    where a2 = decode(encode(a1, context1), context2)
+///          b2 = decode(encode(b1, context1), context2)
+/// ```
+///
+/// i.e. the result of `Ord::cmp` is not influenced by encoding
+/// the values in one session and then decoding them in another
+/// session.
+///
+/// This is trivially true for types where encoding and decoding
+/// don't change the bytes of the values that are used during
+/// comparison and comparison only depends on these bytes (as
+/// opposed to some non-local state). Examples are u32, String,
+/// Path, etc.
+///
+/// But it is not true for:
+///  - `*const T` and `*mut T` because the values of these pointers
+///    will change between sessions.
+///  - `DefIndex`, `CrateNum`, `LocalDefId`, because their concrete
+///    values depend on state that might be different between
+///    compilation sessions.
+pub unsafe trait StableOrd: Ord {}
+
+/// Implement HashStable by just calling `Hash::hash()`. Also implement `StableOrd` for the type since
+/// that has the same requirements.
 ///
 /// **WARNING** This is only valid for types that *really* don't need any context for fingerprinting.
 /// But it is easy to misuse this macro (see [#96013](https://github.com/rust-lang/rust/issues/96013)
@@ -227,7 +255,7 @@ pub trait ToStableHashKey<HCX> {
 /// here in this module.
 ///
 /// Use `#[derive(HashStable_Generic)]` instead.
-macro_rules! impl_stable_hash_via_hash {
+macro_rules! impl_stable_traits_for_trivial_type {
     ($t:ty) => {
         impl<CTX> $crate::stable_hasher::HashStable<CTX> for $t {
             #[inline]
@@ -235,26 +263,28 @@ macro_rules! impl_stable_hash_via_hash {
                 ::std::hash::Hash::hash(self, hasher);
             }
         }
+
+        unsafe impl $crate::stable_hasher::StableOrd for $t {}
     };
 }
 
-impl_stable_hash_via_hash!(i8);
-impl_stable_hash_via_hash!(i16);
-impl_stable_hash_via_hash!(i32);
-impl_stable_hash_via_hash!(i64);
-impl_stable_hash_via_hash!(isize);
+impl_stable_traits_for_trivial_type!(i8);
+impl_stable_traits_for_trivial_type!(i16);
+impl_stable_traits_for_trivial_type!(i32);
+impl_stable_traits_for_trivial_type!(i64);
+impl_stable_traits_for_trivial_type!(isize);
 
-impl_stable_hash_via_hash!(u8);
-impl_stable_hash_via_hash!(u16);
-impl_stable_hash_via_hash!(u32);
-impl_stable_hash_via_hash!(u64);
-impl_stable_hash_via_hash!(usize);
+impl_stable_traits_for_trivial_type!(u8);
+impl_stable_traits_for_trivial_type!(u16);
+impl_stable_traits_for_trivial_type!(u32);
+impl_stable_traits_for_trivial_type!(u64);
+impl_stable_traits_for_trivial_type!(usize);
 
-impl_stable_hash_via_hash!(u128);
-impl_stable_hash_via_hash!(i128);
+impl_stable_traits_for_trivial_type!(u128);
+impl_stable_traits_for_trivial_type!(i128);
 
-impl_stable_hash_via_hash!(char);
-impl_stable_hash_via_hash!(());
+impl_stable_traits_for_trivial_type!(char);
+impl_stable_traits_for_trivial_type!(());
 
 impl<CTX> HashStable<CTX> for ! {
     fn hash_stable(&self, _ctx: &mut CTX, _hasher: &mut StableHasher) {
@@ -444,6 +474,10 @@ impl<CTX> HashStable<CTX> for String {
     }
 }
 
+// Safety: String comparison only depends on their contents and the
+// contents are not changed by (de-)serialization.
+unsafe impl StableOrd for String {}
+
 impl<HCX> ToStableHashKey<HCX> for String {
     type KeyType = String;
     #[inline]
@@ -459,6 +493,9 @@ impl<CTX> HashStable<CTX> for bool {
     }
 }
 
+// Safety: sort order of bools is not changed by (de-)serialization.
+unsafe impl StableOrd for bool {}
+
 impl<T, CTX> HashStable<CTX> for Option<T>
 where
     T: HashStable<CTX>,
@@ -474,6 +511,9 @@ where
     }
 }
 
+// Safety: the Option wrapper does not add instability to comparison.
+unsafe impl<T: StableOrd> StableOrd for Option<T> {}
+
 impl<T1, T2, CTX> HashStable<CTX> for Result<T1, T2>
 where
     T1: HashStable<CTX>,
@@ -550,8 +590,8 @@ where
     }
 }
 
-impl_stable_hash_via_hash!(::std::path::Path);
-impl_stable_hash_via_hash!(::std::path::PathBuf);
+impl_stable_traits_for_trivial_type!(::std::path::Path);
+impl_stable_traits_for_trivial_type!(::std::path::PathBuf);
 
 impl<K, V, R, HCX> HashStable<HCX> for ::std::collections::HashMap<K, V, R>
 where
@@ -584,27 +624,26 @@ where
 
 impl<K, V, HCX> HashStable<HCX> for ::std::collections::BTreeMap<K, V>
 where
-    K: ToStableHashKey<HCX>,
+    K: HashStable<HCX> + StableOrd,
     V: HashStable<HCX>,
 {
     fn hash_stable(&self, hcx: &mut HCX, hasher: &mut StableHasher) {
-        stable_hash_reduce(hcx, hasher, self.iter(), self.len(), |hasher, hcx, (key, value)| {
-            let key = key.to_stable_hash_key(hcx);
-            key.hash_stable(hcx, hasher);
-            value.hash_stable(hcx, hasher);
-        });
+        self.len().hash_stable(hcx, hasher);
+        for entry in self.iter() {
+            entry.hash_stable(hcx, hasher);
+        }
     }
 }
 
 impl<K, HCX> HashStable<HCX> for ::std::collections::BTreeSet<K>
 where
-    K: ToStableHashKey<HCX>,
+    K: HashStable<HCX> + StableOrd,
 {
     fn hash_stable(&self, hcx: &mut HCX, hasher: &mut StableHasher) {
-        stable_hash_reduce(hcx, hasher, self.iter(), self.len(), |hasher, hcx, key| {
-            let key = key.to_stable_hash_key(hcx);
-            key.hash_stable(hcx, hasher);
-        });
+        self.len().hash_stable(hcx, hasher);
+        for entry in self.iter() {
+            entry.hash_stable(hcx, hasher);
+        }
     }
 }
 
diff --git a/compiler/rustc_driver/src/lib.rs b/compiler/rustc_driver/src/lib.rs
index 22f87514dd8..f06ca5a0733 100644
--- a/compiler/rustc_driver/src/lib.rs
+++ b/compiler/rustc_driver/src/lib.rs
@@ -25,6 +25,7 @@ use rustc_data_structures::sync::SeqCst;
 use rustc_errors::registry::{InvalidErrorCode, Registry};
 use rustc_errors::{ErrorGuaranteed, PResult};
 use rustc_feature::find_gated_cfg;
+use rustc_hir::def_id::LOCAL_CRATE;
 use rustc_interface::util::{self, collect_crate_types, get_codegen_backend};
 use rustc_interface::{interface, Queries};
 use rustc_lint::LintStore;
@@ -374,14 +375,14 @@ fn run_compiler(
             queries.global_ctxt()?.peek_mut().enter(|tcx| {
                 let result = tcx.analysis(());
                 if sess.opts.unstable_opts.save_analysis {
-                    let crate_name = queries.crate_name()?.peek().clone();
+                    let crate_name = tcx.crate_name(LOCAL_CRATE);
                     sess.time("save_analysis", || {
                         save::process_crate(
                             tcx,
-                            &crate_name,
+                            crate_name,
                             compiler.input(),
                             None,
-                            DumpHandler::new(compiler.output_dir().as_deref(), &crate_name),
+                            DumpHandler::new(compiler.output_dir().as_deref(), crate_name),
                         )
                     });
                 }
@@ -678,7 +679,7 @@ fn print_crate_info(
                 let crate_types = collect_crate_types(sess, attrs);
                 for &style in &crate_types {
                     let fname =
-                        rustc_session::output::filename_for_input(sess, style, &id, &t_outputs);
+                        rustc_session::output::filename_for_input(sess, style, id, &t_outputs);
                     println!("{}", fname.file_name().unwrap().to_string_lossy());
                 }
             }
diff --git a/compiler/rustc_error_codes/src/error_codes.rs b/compiler/rustc_error_codes/src/error_codes.rs
index 1e86d159668..31a709c36d4 100644
--- a/compiler/rustc_error_codes/src/error_codes.rs
+++ b/compiler/rustc_error_codes/src/error_codes.rs
@@ -494,6 +494,7 @@ E0786: include_str!("./error_codes/E0786.md"),
 E0787: include_str!("./error_codes/E0787.md"),
 E0788: include_str!("./error_codes/E0788.md"),
 E0790: include_str!("./error_codes/E0790.md"),
+E0791: include_str!("./error_codes/E0791.md"),
 ;
 //  E0006, // merged with E0005
 //  E0008, // cannot bind by-move into a pattern guard
diff --git a/compiler/rustc_error_codes/src/error_codes/E0791.md b/compiler/rustc_error_codes/src/error_codes/E0791.md
new file mode 100644
index 00000000000..61d2f511a34
--- /dev/null
+++ b/compiler/rustc_error_codes/src/error_codes/E0791.md
@@ -0,0 +1,41 @@
+Static variables with the `#[linkage]` attribute within external blocks
+must have one of the following types, which are equivalent to a nullable
+pointer in C:
+
+* `*mut T` or `*const T`, where `T` may be any type.
+
+* An enumerator type with no `#[repr]` attribute and with two variants, where
+  one of the variants has no fields, and the other has a single field of one of
+  the following non-nullable types:
+  * Reference type
+  * Function pointer type
+
+  The variants can appear in either order.
+
+For example, the following declaration is invalid:
+
+```compile_fail,E0791
+#![feature(linkage)]
+
+extern "C" {
+    #[linkage = "extern_weak"]
+    static foo: i8;
+}
+```
+
+The following declarations are valid:
+
+```
+#![feature(linkage)]
+
+extern "C" {
+    #[linkage = "extern_weak"]
+    static foo: Option<unsafe extern "C" fn()>;
+
+    #[linkage = "extern_weak"]
+    static bar: Option<&'static i8>;
+
+    #[linkage = "extern_weak"]
+    static baz: *mut i8;
+}
+```
diff --git a/compiler/rustc_error_messages/locales/en-US/codegen_gcc.ftl b/compiler/rustc_error_messages/locales/en-US/codegen_gcc.ftl
index a1b7afeb709..08ce5172574 100644
--- a/compiler/rustc_error_messages/locales/en-US/codegen_gcc.ftl
+++ b/compiler/rustc_error_messages/locales/en-US/codegen_gcc.ftl
@@ -1,6 +1,3 @@
-codegen_gcc_linkage_const_or_mut_type =
-    must have type `*const T` or `*mut T` due to `#[linkage]` attribute
-
 codegen_gcc_unwinding_inline_asm =
     GCC backend does not support unwinding from inline asm
 
diff --git a/compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl b/compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl
index e273476b60b..97198cb4be2 100644
--- a/compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl
+++ b/compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl
@@ -23,9 +23,6 @@ codegen_llvm_branch_protection_requires_aarch64 =
 codegen_llvm_invalid_minimum_alignment =
     invalid minimum global alignment: {$err}
 
-codegen_llvm_linkage_const_or_mut_type =
-    must have type `*const T` or `*mut T` due to `#[linkage]` attribute
-
 codegen_llvm_sanitizer_memtag_requires_mte =
     `-Zsanitizer=memtag` requires `-Ctarget-feature=+mte`
 
diff --git a/compiler/rustc_error_messages/locales/en-US/hir_analysis.ftl b/compiler/rustc_error_messages/locales/en-US/hir_analysis.ftl
index 0894bbcaad4..a9ea161b93e 100644
--- a/compiler/rustc_error_messages/locales/en-US/hir_analysis.ftl
+++ b/compiler/rustc_error_messages/locales/en-US/hir_analysis.ftl
@@ -17,6 +17,8 @@ hir_analysis_lifetimes_or_bounds_mismatch_on_trait =
     lifetime parameters or bounds on {$item_kind} `{$ident}` do not match the trait declaration
     .label = lifetimes do not match {$item_kind} in trait
     .generics_label = lifetimes in impl do not match this {$item_kind} in trait
+    .where_label = this `where` clause might not match the one in the trait
+    .bounds_label = this bound might be missing in the impl
 
 hir_analysis_drop_impl_on_wrong_item =
     the `Drop` trait may only be implemented for local structs, enums, and unions
@@ -113,3 +115,6 @@ hir_analysis_const_bound_for_non_const_trait =
 hir_analysis_self_in_impl_self =
     `Self` is not valid in the self type of an impl block
     .note = replace `Self` with a different type
+
+hir_analysis_linkage_type =
+    invalid type for variable with `#[linkage]` attribute
diff --git a/compiler/rustc_error_messages/locales/en-US/parse.ftl b/compiler/rustc_error_messages/locales/en-US/parse.ftl
index 114b7ec1628..b53550e5fd5 100644
--- a/compiler/rustc_error_messages/locales/en-US/parse.ftl
+++ b/compiler/rustc_error_messages/locales/en-US/parse.ftl
@@ -362,3 +362,6 @@ parse_fn_ptr_with_generics = function pointer types may not have generic paramet
 
 parse_invalid_identifier_with_leading_number = expected identifier, found number literal
     .label = identifiers cannot start with a number
+
+parse_maybe_fn_typo_with_impl = you might have meant to write `impl` instead of `fn`
+    .suggestion = replace `fn` with `impl` here
diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs
index 13e2d1ebbe7..9d6a4f9a1fd 100644
--- a/compiler/rustc_expand/src/base.rs
+++ b/compiler/rustc_expand/src/base.rs
@@ -960,7 +960,7 @@ pub trait LintStoreExpand {
         node_id: NodeId,
         attrs: &[Attribute],
         items: &[P<Item>],
-        name: &str,
+        name: Symbol,
     );
 }
 
diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs
index e799fa404f6..1014ec2209c 100644
--- a/compiler/rustc_expand/src/expand.rs
+++ b/compiler/rustc_expand/src/expand.rs
@@ -1122,7 +1122,7 @@ impl InvocationCollectorNode for P<ast::Item> {
                         ecx.current_expansion.lint_node_id,
                         &attrs,
                         &items,
-                        ident.name.as_str(),
+                        ident.name,
                     );
                 }
 
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index 636e6e1b48d..8bc022e1e17 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -827,7 +827,7 @@ impl<'tcx> AttributeMap<'tcx> {
 pub struct OwnerNodes<'tcx> {
     /// Pre-computed hash of the full HIR.
     pub hash_including_bodies: Fingerprint,
-    /// Pre-computed hash of the item signature, sithout recursing into the body.
+    /// Pre-computed hash of the item signature, without recursing into the body.
     pub hash_without_bodies: Fingerprint,
     /// Full HIR for the current owner.
     // The zeroth node's parent should never be accessed: the owner's parent is computed by the
diff --git a/compiler/rustc_hir/src/hir_id.rs b/compiler/rustc_hir/src/hir_id.rs
index 93613ef27d4..060f40919f5 100644
--- a/compiler/rustc_hir/src/hir_id.rs
+++ b/compiler/rustc_hir/src/hir_id.rs
@@ -1,5 +1,5 @@
 use crate::def_id::{DefId, DefIndex, LocalDefId, CRATE_DEF_ID};
-use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey};
+use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableOrd, ToStableHashKey};
 use rustc_span::{def_id::DefPathHash, HashStableContext};
 use std::fmt;
 
@@ -146,6 +146,10 @@ impl ItemLocalId {
     pub const INVALID: ItemLocalId = ItemLocalId::MAX;
 }
 
+// Safety: Ord is implement as just comparing the LocalItemId's numerical
+// values and these are not changed by (de-)serialization.
+unsafe impl StableOrd for ItemLocalId {}
+
 /// The `HirId` corresponding to `CRATE_NODE_ID` and `CRATE_DEF_ID`.
 pub const CRATE_HIR_ID: HirId =
     HirId { owner: OwnerId { def_id: CRATE_DEF_ID }, local_id: ItemLocalId::from_u32(0) };
diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs
index 038509031b1..b51257df713 100644
--- a/compiler/rustc_hir/src/lang_items.rs
+++ b/compiler/rustc_hir/src/lang_items.rs
@@ -286,10 +286,9 @@ language_item_table! {
 
     // FIXME(swatinem): the following lang items are used for async lowering and
     // should become obsolete eventually.
-    ResumeTy,                sym::ResumeTy,            resume_ty,                  Target::Struct,         GenericRequirement::None;
     IdentityFuture,          sym::identity_future,     identity_future_fn,         Target::Fn,             GenericRequirement::None;
-    GetContext,              sym::get_context,         get_context_fn,             Target::Fn,             GenericRequirement::None;
 
+    Context,                 sym::Context,             context,                    Target::Struct,         GenericRequirement::None;
     FuturePoll,              sym::poll,                future_poll_fn,             Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None;
 
     FromFrom,                sym::from,                from_fn,                    Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None;
diff --git a/compiler/rustc_hir/src/tests.rs b/compiler/rustc_hir/src/tests.rs
index 4636d515249..d4791150947 100644
--- a/compiler/rustc_hir/src/tests.rs
+++ b/compiler/rustc_hir/src/tests.rs
@@ -1,5 +1,7 @@
 use crate::definitions::{DefKey, DefPathData, DisambiguatedDefPathData};
 use rustc_span::def_id::{DefPathHash, StableCrateId};
+use rustc_span::edition::Edition;
+use rustc_span::{create_session_if_not_set_then, Symbol};
 
 #[test]
 fn def_path_hash_depends_on_crate_id() {
@@ -11,26 +13,28 @@ fn def_path_hash_depends_on_crate_id() {
     // the crate by changing the crate disambiguator (e.g. via bumping the
     // crate's version number).
 
-    let id0 = StableCrateId::new("foo", false, vec!["1".to_string()]);
-    let id1 = StableCrateId::new("foo", false, vec!["2".to_string()]);
+    create_session_if_not_set_then(Edition::Edition2024, |_| {
+        let id0 = StableCrateId::new(Symbol::intern("foo"), false, vec!["1".to_string()]);
+        let id1 = StableCrateId::new(Symbol::intern("foo"), false, vec!["2".to_string()]);
 
-    let h0 = mk_test_hash(id0);
-    let h1 = mk_test_hash(id1);
+        let h0 = mk_test_hash(id0);
+        let h1 = mk_test_hash(id1);
 
-    assert_ne!(h0.stable_crate_id(), h1.stable_crate_id());
-    assert_ne!(h0.local_hash(), h1.local_hash());
+        assert_ne!(h0.stable_crate_id(), h1.stable_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);
+        fn mk_test_hash(stable_crate_id: StableCrateId) -> DefPathHash {
+            let parent_hash = DefPathHash::new(stable_crate_id, 0);
 
-        let key = DefKey {
-            parent: None,
-            disambiguated_data: DisambiguatedDefPathData {
-                data: DefPathData::CrateRoot,
-                disambiguator: 0,
-            },
-        };
+            let key = DefKey {
+                parent: None,
+                disambiguated_data: DisambiguatedDefPathData {
+                    data: DefPathData::CrateRoot,
+                    disambiguator: 0,
+                },
+            };
 
-        key.compute_stable_hash(parent_hash)
-    }
+            key.compute_stable_hash(parent_hash)
+        }
+    })
 }
diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs
index f204d59d005..66906b331da 100644
--- a/compiler/rustc_hir_analysis/src/astconv/mod.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs
@@ -1930,6 +1930,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                     adt_substs,
                 );
                 let ty = tcx.bound_type_of(assoc_ty_did).subst(tcx, item_substs);
+                let ty = self.normalize_ty(span, ty);
                 return Ok((ty, DefKind::AssocTy, assoc_ty_did));
             }
         }
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index 069b405423c..fc0ca62090d 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -1,4 +1,5 @@
 use crate::check::intrinsicck::InlineAsmCtxt;
+use crate::errors::LinkageType;
 
 use super::compare_method::check_type_bounds;
 use super::compare_method::{compare_impl_method, compare_ty_impl};
@@ -20,7 +21,7 @@ use rustc_middle::middle::stability::EvalResult;
 use rustc_middle::ty::layout::{LayoutError, MAX_SIMD_LANES};
 use rustc_middle::ty::subst::GenericArgKind;
 use rustc_middle::ty::util::{Discr, IntTypeExt};
-use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable};
+use rustc_middle::ty::{self, AdtDef, ParamEnv, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable};
 use rustc_session::lint::builtin::{UNINHABITED_STATIC, UNSUPPORTED_CALLING_CONVENTIONS};
 use rustc_span::symbol::sym;
 use rustc_span::{self, Span};
@@ -478,6 +479,36 @@ fn check_opaque_meets_bounds<'tcx>(
     let _ = infcx.inner.borrow_mut().opaque_type_storage.take_opaque_types();
 }
 
+fn is_enum_of_nonnullable_ptr<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    adt_def: AdtDef<'tcx>,
+    substs: SubstsRef<'tcx>,
+) -> bool {
+    if adt_def.repr().inhibit_enum_layout_opt() {
+        return false;
+    }
+
+    let [var_one, var_two] = &adt_def.variants().raw[..] else {
+        return false;
+    };
+    let (([], [field]) | ([field], [])) = (&var_one.fields[..], &var_two.fields[..]) else {
+        return false;
+    };
+    matches!(field.ty(tcx, substs).kind(), ty::FnPtr(..) | ty::Ref(..))
+}
+
+fn check_static_linkage<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) {
+    if tcx.codegen_fn_attrs(def_id).import_linkage.is_some() {
+        if match tcx.type_of(def_id).kind() {
+            ty::RawPtr(_) => false,
+            ty::Adt(adt_def, substs) => !is_enum_of_nonnullable_ptr(tcx, *adt_def, *substs),
+            _ => true,
+        } {
+            tcx.sess.emit_err(LinkageType { span: tcx.def_span(def_id) });
+        }
+    }
+}
+
 fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, id: hir::ItemId) {
     debug!(
         "check_item_type(it.def_id={:?}, it.name={})",
@@ -490,6 +521,7 @@ fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, id: hir::ItemId) {
             tcx.ensure().typeck(id.owner_id.def_id);
             maybe_check_static_with_link_section(tcx, id.owner_id.def_id);
             check_static_inhabited(tcx, id.owner_id.def_id);
+            check_static_linkage(tcx, id.owner_id.def_id);
         }
         DefKind::Const => {
             tcx.ensure().typeck(id.owner_id.def_id);
@@ -627,6 +659,7 @@ fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, id: hir::ItemId) {
                         }
                         hir::ForeignItemKind::Static(..) => {
                             check_static_inhabited(tcx, def_id);
+                            check_static_linkage(tcx, def_id);
                         }
                         _ => {}
                     }
diff --git a/compiler/rustc_hir_analysis/src/check/compare_method.rs b/compiler/rustc_hir_analysis/src/check/compare_method.rs
index 82a77416a19..1d6f9b29176 100644
--- a/compiler/rustc_hir_analysis/src/check/compare_method.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_method.rs
@@ -751,17 +751,45 @@ fn check_region_bounds_on_impl_item<'tcx>(
             .get_generics(impl_m.def_id.expect_local())
             .expect("expected impl item to have generics or else we can't compare them")
             .span;
-        let generics_span = if let Some(local_def_id) = trait_m.def_id.as_local() {
-            Some(
-                tcx.hir()
-                    .get_generics(local_def_id)
-                    .expect("expected trait item to have generics or else we can't compare them")
-                    .span,
-            )
-        } else {
-            None
-        };
 
+        let mut generics_span = None;
+        let mut bounds_span = vec![];
+        let mut where_span = None;
+        if let Some(trait_node) = tcx.hir().get_if_local(trait_m.def_id)
+            && let Some(trait_generics) = trait_node.generics()
+        {
+            generics_span = Some(trait_generics.span);
+            // FIXME: we could potentially look at the impl's bounds to not point at bounds that
+            // *are* present in the impl.
+            for p in trait_generics.predicates {
+                if let hir::WherePredicate::BoundPredicate(pred) = p {
+                    for b in pred.bounds {
+                        if let hir::GenericBound::Outlives(lt) = b {
+                            bounds_span.push(lt.ident.span);
+                        }
+                    }
+                }
+            }
+            if let Some(impl_node) = tcx.hir().get_if_local(impl_m.def_id)
+                && let Some(impl_generics) = impl_node.generics()
+            {
+                let mut impl_bounds = 0;
+                for p in impl_generics.predicates {
+                    if let hir::WherePredicate::BoundPredicate(pred) = p {
+                        for b in pred.bounds {
+                            if let hir::GenericBound::Outlives(_) = b {
+                                impl_bounds += 1;
+                            }
+                        }
+                    }
+                }
+                if impl_bounds == bounds_span.len() {
+                    bounds_span = vec![];
+                } else if impl_generics.has_where_clause_predicates {
+                    where_span = Some(impl_generics.where_clause_span);
+                }
+            }
+        }
         let reported = tcx
             .sess
             .create_err(LifetimesOrBoundsMismatchOnTrait {
@@ -769,9 +797,10 @@ fn check_region_bounds_on_impl_item<'tcx>(
                 item_kind: assoc_item_kind_str(impl_m),
                 ident: impl_m.ident(tcx),
                 generics_span,
+                bounds_span,
+                where_span,
             })
             .emit_unless(delay);
-
         return Err(reported);
     }
 
diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs
index b7084303aaf..945361ef43a 100644
--- a/compiler/rustc_hir_analysis/src/collect.rs
+++ b/compiler/rustc_hir_analysis/src/collect.rs
@@ -1814,7 +1814,12 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: DefId) -> CodegenFnAttrs {
             );
         } else if attr.has_name(sym::linkage) {
             if let Some(val) = attr.value_str() {
-                codegen_fn_attrs.linkage = Some(linkage_by_name(tcx, did, val.as_str()));
+                let linkage = Some(linkage_by_name(tcx, did, val.as_str()));
+                if tcx.is_foreign_item(did) {
+                    codegen_fn_attrs.import_linkage = linkage;
+                } else {
+                    codegen_fn_attrs.linkage = linkage;
+                }
             }
         } else if attr.has_name(sym::link_section) {
             if let Some(val) = attr.value_str() {
diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs
index 639f81f20bf..0a7e25300cb 100644
--- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs
@@ -4,7 +4,6 @@ use hir::{
     GenericParamKind, HirId, Node,
 };
 use rustc_hir as hir;
-use rustc_hir::def::DefKind;
 use rustc_hir::def_id::DefId;
 use rustc_middle::ty::{self, TyCtxt};
 use rustc_session::lint;
@@ -143,20 +142,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
             Some(tcx.typeck_root_def_id(def_id))
         }
         Node::Item(item) => match item.kind {
-            ItemKind::OpaqueTy(hir::OpaqueTy {
-                origin:
-                    hir::OpaqueTyOrigin::FnReturn(fn_def_id) | hir::OpaqueTyOrigin::AsyncFn(fn_def_id),
-                in_trait,
-                ..
-            }) => {
-                if in_trait {
-                    assert!(matches!(tcx.def_kind(fn_def_id), DefKind::AssocFn))
-                } else {
-                    assert!(matches!(tcx.def_kind(fn_def_id), DefKind::AssocFn | DefKind::Fn))
-                }
-                Some(fn_def_id.to_def_id())
-            }
-            ItemKind::OpaqueTy(hir::OpaqueTy { origin: hir::OpaqueTyOrigin::TyAlias, .. }) => {
+            ItemKind::OpaqueTy(hir::OpaqueTy { .. }) => {
                 let parent_id = tcx.hir().get_parent_item(hir_id);
                 assert_ne!(parent_id, hir::CRATE_OWNER_ID);
                 debug!("generics_of: parent of opaque ty {:?} is {:?}", def_id, parent_id);
diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs
index afbb27155a2..c92ab749bc1 100644
--- a/compiler/rustc_hir_analysis/src/errors.rs
+++ b/compiler/rustc_hir_analysis/src/errors.rs
@@ -43,6 +43,10 @@ pub struct LifetimesOrBoundsMismatchOnTrait {
     pub span: Span,
     #[label(generics_label)]
     pub generics_span: Option<Span>,
+    #[label(where_label)]
+    pub where_span: Option<Span>,
+    #[label(bounds_label)]
+    pub bounds_span: Vec<Span>,
     pub item_kind: &'static str,
     pub ident: Ident,
 }
@@ -285,3 +289,10 @@ pub struct SelfInImplSelf {
     #[note]
     pub note: (),
 }
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_linkage_type, code = "E0791")]
+pub(crate) struct LinkageType {
+    #[primary_span]
+    pub span: Span,
+}
diff --git a/compiler/rustc_hir_analysis/src/variance/mod.rs b/compiler/rustc_hir_analysis/src/variance/mod.rs
index 9db05eedbde..8b2719c2f8a 100644
--- a/compiler/rustc_hir_analysis/src/variance/mod.rs
+++ b/compiler/rustc_hir_analysis/src/variance/mod.rs
@@ -7,7 +7,8 @@ use rustc_arena::DroplessArena;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_middle::ty::query::Providers;
-use rustc_middle::ty::{self, CrateVariancesMap, TyCtxt, TypeSuperVisitable, TypeVisitable};
+use rustc_middle::ty::{self, CrateVariancesMap, SubstsRef, Ty, TyCtxt};
+use rustc_middle::ty::{DefIdTree, TypeSuperVisitable, TypeVisitable};
 use std::ops::ControlFlow;
 
 /// Defines the `TermsContext` basically houses an arena where we can
@@ -75,11 +76,30 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc
     // type Foo<'a, 'b, 'c> = impl Trait<'a> + 'b;
     // ```
     // we may not use `'c` in the hidden type.
-    struct OpaqueTypeLifetimeCollector {
+    struct OpaqueTypeLifetimeCollector<'tcx> {
+        tcx: TyCtxt<'tcx>,
+        root_def_id: DefId,
         variances: Vec<ty::Variance>,
     }
 
-    impl<'tcx> ty::TypeVisitor<'tcx> for OpaqueTypeLifetimeCollector {
+    impl<'tcx> OpaqueTypeLifetimeCollector<'tcx> {
+        #[instrument(level = "trace", skip(self), ret)]
+        fn visit_opaque(&mut self, def_id: DefId, substs: SubstsRef<'tcx>) -> ControlFlow<!> {
+            if def_id != self.root_def_id && self.tcx.is_descendant_of(def_id, self.root_def_id) {
+                let child_variances = self.tcx.variances_of(def_id);
+                for (a, v) in substs.iter().zip(child_variances) {
+                    if *v != ty::Bivariant {
+                        a.visit_with(self)?;
+                    }
+                }
+                ControlFlow::CONTINUE
+            } else {
+                substs.visit_with(self)
+            }
+        }
+    }
+
+    impl<'tcx> ty::TypeVisitor<'tcx> for OpaqueTypeLifetimeCollector<'tcx> {
         #[instrument(level = "trace", skip(self), ret)]
         fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
             if let ty::RegionKind::ReEarlyBound(ebr) = r.kind() {
@@ -87,6 +107,19 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc
             }
             r.super_visit_with(self)
         }
+
+        #[instrument(level = "trace", skip(self), ret)]
+        fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
+            match t.kind() {
+                ty::Opaque(def_id, substs) => self.visit_opaque(*def_id, substs),
+                ty::Projection(proj)
+                    if self.tcx.def_kind(proj.item_def_id) == DefKind::ImplTraitPlaceholder =>
+                {
+                    self.visit_opaque(proj.item_def_id, proj.substs)
+                }
+                _ => t.super_visit_with(self),
+            }
+        }
     }
 
     // By default, RPIT are invariant wrt type and const generics, but they are bivariant wrt
@@ -111,7 +144,8 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc
         }
     }
 
-    let mut collector = OpaqueTypeLifetimeCollector { variances };
+    let mut collector =
+        OpaqueTypeLifetimeCollector { tcx, root_def_id: item_def_id.to_def_id(), variances };
     let id_substs = ty::InternalSubsts::identity_for_item(tcx, item_def_id.to_def_id());
     for pred in tcx.bound_explicit_item_bounds(item_def_id.to_def_id()).transpose_iter() {
         let pred = pred.map_bound(|(pred, _)| *pred).subst(tcx, id_substs);
diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs
index 3791b2c8661..94bab9f339d 100644
--- a/compiler/rustc_hir_pretty/src/lib.rs
+++ b/compiler/rustc_hir_pretty/src/lib.rs
@@ -695,19 +695,8 @@ impl<'a> State<'a> {
                 self.head("trait");
                 self.print_ident(item.ident);
                 self.print_generic_params(generics.params);
-                let mut real_bounds = Vec::with_capacity(bounds.len());
-                // FIXME(durka) this seems to be some quite outdated syntax
-                for b in bounds {
-                    if let GenericBound::Trait(ptr, hir::TraitBoundModifier::Maybe) = b {
-                        self.space();
-                        self.word_space("for ?");
-                        self.print_trait_ref(&ptr.trait_ref);
-                    } else {
-                        real_bounds.push(b);
-                    }
-                }
                 self.nbsp();
-                self.print_bounds("=", real_bounds);
+                self.print_bounds("=", bounds);
                 self.print_where_clause(generics);
                 self.word(";");
                 self.end(); // end inner head-block
diff --git a/compiler/rustc_hir_typeck/src/check.rs b/compiler/rustc_hir_typeck/src/check.rs
index 0c9a350c295..32f86b8042c 100644
--- a/compiler/rustc_hir_typeck/src/check.rs
+++ b/compiler/rustc_hir_typeck/src/check.rs
@@ -1,7 +1,7 @@
 use crate::coercion::CoerceMany;
 use crate::gather_locals::GatherLocalsVisitor;
 use crate::FnCtxt;
-use crate::{GeneratorTypes, UnsafetyState};
+use crate::GeneratorTypes;
 use rustc_hir as hir;
 use rustc_hir::def::DefKind;
 use rustc_hir::intravisit::Visitor;
@@ -30,7 +30,6 @@ pub(super) fn check_fn<'a, 'tcx>(
     can_be_generator: Option<hir::Movability>,
 ) -> Option<GeneratorTypes<'tcx>> {
     let fn_id = fcx.tcx.hir().local_def_id_to_hir_id(fn_def_id);
-    fcx.ps.set(UnsafetyState::function(fn_sig.unsafety, fn_id));
 
     let tcx = fcx.tcx;
     let hir = tcx.hir();
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index 4a112e80f1d..ed87b94a040 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -1647,6 +1647,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         // the fields with the base_expr. This could cause us to hit errors later
         // when certain fields are assumed to exist that in fact do not.
         if error_happened {
+            if let Some(base_expr) = base_expr {
+                self.check_expr(base_expr);
+            }
             return;
         }
 
diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
index e5e798f4b93..03b174c7795 100644
--- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
+++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
@@ -523,6 +523,11 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
         // Consume the expressions supplying values for each field.
         for field in fields {
             self.consume_expr(field.expr);
+
+            // The struct path probably didn't resolve
+            if self.mc.typeck_results.opt_field_index(field.hir_id).is_none() {
+                self.tcx().sess.delay_span_bug(field.span, "couldn't resolve index for field");
+            }
         }
 
         let with_expr = match *opt_with {
@@ -540,9 +545,9 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
             ty::Adt(adt, substs) if adt.is_struct() => {
                 // Consume those fields of the with expression that are needed.
                 for (f_index, with_field) in adt.non_enum_variant().fields.iter().enumerate() {
-                    let is_mentioned = fields.iter().any(|f| {
-                        self.tcx().field_index(f.hir_id, self.mc.typeck_results) == f_index
-                    });
+                    let is_mentioned = fields
+                        .iter()
+                        .any(|f| self.mc.typeck_results.opt_field_index(f.hir_id) == Some(f_index));
                     if !is_mentioned {
                         let field_place = self.mc.cat_projection(
                             &*with_expr,
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
index 3078e0cbeda..60fec05d36d 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
@@ -1393,8 +1393,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         blk: &'tcx hir::Block<'tcx>,
         expected: Expectation<'tcx>,
     ) -> Ty<'tcx> {
-        let prev = self.ps.replace(self.ps.get().recurse(blk));
-
         // In some cases, blocks have just one exit, but other blocks
         // can be targeted by multiple breaks. This can happen both
         // with labeled blocks as well as when we desugar
@@ -1558,7 +1556,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         self.write_ty(blk.hir_id, ty);
 
-        self.ps.set(prev);
         ty
     }
 
@@ -1918,15 +1915,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         receiver: Option<&'tcx hir::Expr<'tcx>>,
         args: &'tcx [hir::Expr<'tcx>],
     ) -> bool {
-        // Do not call `fn_sig` on non-functions.
-        if !matches!(
-            self.tcx.def_kind(def_id),
-            DefKind::Fn | DefKind::AssocFn | DefKind::Variant | DefKind::Ctor(..)
-        ) {
+        let ty = self.tcx.type_of(def_id);
+        if !ty.is_fn() {
             return false;
         }
-
-        let sig = self.tcx.fn_sig(def_id).skip_binder();
+        let sig = ty.fn_sig(self.tcx).skip_binder();
         let args_referencing_param: Vec<_> = sig
             .inputs()
             .iter()
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
index 1e9b5752130..30b59da7852 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
@@ -8,7 +8,7 @@ use rustc_errors::ErrorGuaranteed;
 pub use suggestions::*;
 
 use crate::coercion::DynamicCoerceMany;
-use crate::{Diverges, EnclosingBreakables, Inherited, UnsafetyState};
+use crate::{Diverges, EnclosingBreakables, Inherited};
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_hir_analysis::astconv::AstConv;
@@ -74,8 +74,6 @@ pub struct FnCtxt<'a, 'tcx> {
 
     pub(super) resume_yield_tys: Option<(Ty<'tcx>, Ty<'tcx>)>,
 
-    pub(super) ps: Cell<UnsafetyState>,
-
     /// Whether the last checked node generates a divergence (e.g.,
     /// `return` will set this to `Always`). In general, when entering
     /// an expression or other node in the tree, the initial value
@@ -129,7 +127,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             ret_coercion: None,
             ret_coercion_span: Cell::new(None),
             resume_yield_tys: None,
-            ps: Cell::new(UnsafetyState::function(hir::Unsafety::Normal, hir::CRATE_HIR_ID)),
             diverges: Cell::new(Diverges::Maybe),
             enclosing_breakables: RefCell::new(EnclosingBreakables {
                 stack: Vec::new(),
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
index 1daca464b47..4f92477b5d8 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
@@ -32,11 +32,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     }
 
     pub(in super::super) fn suggest_semicolon_at_end(&self, span: Span, err: &mut Diagnostic) {
+        // This suggestion is incorrect for
+        // fn foo() -> bool { match () { () => true } || match () { () => true } }
         err.span_suggestion_short(
             span.shrink_to_hi(),
             "consider using a semicolon here",
             ";",
-            Applicability::MachineApplicable,
+            Applicability::MaybeIncorrect,
         );
     }
 
diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs
index 09bd123350d..5b2352cda34 100644
--- a/compiler/rustc_hir_typeck/src/lib.rs
+++ b/compiler/rustc_hir_typeck/src/lib.rs
@@ -89,38 +89,6 @@ pub struct LocalTy<'tcx> {
     revealed_ty: Ty<'tcx>,
 }
 
-#[derive(Copy, Clone)]
-pub struct UnsafetyState {
-    pub def: hir::HirId,
-    pub unsafety: hir::Unsafety,
-    from_fn: bool,
-}
-
-impl UnsafetyState {
-    pub fn function(unsafety: hir::Unsafety, def: hir::HirId) -> UnsafetyState {
-        UnsafetyState { def, unsafety, from_fn: true }
-    }
-
-    pub fn recurse(self, blk: &hir::Block<'_>) -> UnsafetyState {
-        use hir::BlockCheckMode;
-        match self.unsafety {
-            // If this unsafe, then if the outer function was already marked as
-            // unsafe we shouldn't attribute the unsafe'ness to the block. This
-            // way the block can be warned about instead of ignoring this
-            // extraneous block (functions are never warned about).
-            hir::Unsafety::Unsafe if self.from_fn => self,
-
-            unsafety => {
-                let (unsafety, def) = match blk.rules {
-                    BlockCheckMode::UnsafeBlock(..) => (hir::Unsafety::Unsafe, blk.hir_id),
-                    BlockCheckMode::DefaultBlock => (unsafety, self.def),
-                };
-                UnsafetyState { def, unsafety, from_fn: false }
-            }
-        }
-    }
-}
-
 /// If this `DefId` is a "primary tables entry", returns
 /// `Some((body_id, body_ty, fn_sig))`. Otherwise, returns `None`.
 ///
diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs
index 9ba4ddfd5cf..db93cfab2c0 100644
--- a/compiler/rustc_hir_typeck/src/method/suggest.rs
+++ b/compiler/rustc_hir_typeck/src/method/suggest.rs
@@ -1482,15 +1482,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             ident_name: Symbol,
         }
 
+        // FIXME: This really should be taking scoping, etc into account.
         impl<'v> Visitor<'v> for LetVisitor<'v> {
             fn visit_stmt(&mut self, ex: &'v hir::Stmt<'v>) {
-                if let hir::StmtKind::Local(hir::Local { pat, init, .. }) = &ex.kind {
-                    if let Binding(_, _, ident, ..) = pat.kind &&
-                        ident.name == self.ident_name {
-                        self.result = *init;
-                    }
+                if let hir::StmtKind::Local(hir::Local { pat, init, .. }) = &ex.kind
+                    && let Binding(_, _, ident, ..) = pat.kind
+                    && ident.name == self.ident_name
+                {
+                    self.result = *init;
+                } else {
+                    hir::intravisit::walk_stmt(self, ex);
                 }
-                hir::intravisit::walk_stmt(self, ex);
             }
         }
 
@@ -1498,9 +1500,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         visitor.visit_body(&body);
 
         let parent = self.tcx.hir().get_parent_node(seg1.hir_id);
-        if let Some(Node::Expr(call_expr)) = self.tcx.hir().find(parent) &&
-            let Some(expr) = visitor.result {
-            let self_ty = self.node_ty(expr.hir_id);
+        if let Some(Node::Expr(call_expr)) = self.tcx.hir().find(parent)
+            && let Some(expr) = visitor.result
+            && let Some(self_ty) = self.node_ty_opt(expr.hir_id)
+        {
             let probe = self.lookup_probe(
                 seg2.ident,
                 self_ty,
@@ -1513,7 +1516,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     sm.span_extend_while(seg1.ident.span.shrink_to_hi(), |c| c == ':').unwrap(),
                     "you may have meant to call an instance method",
                     ".".to_string(),
-                    Applicability::MaybeIncorrect
+                    Applicability::MaybeIncorrect,
                 );
             }
         }
diff --git a/compiler/rustc_incremental/src/persist/fs.rs b/compiler/rustc_incremental/src/persist/fs.rs
index 58d6e6d7efd..97ebed05855 100644
--- a/compiler/rustc_incremental/src/persist/fs.rs
+++ b/compiler/rustc_incremental/src/persist/fs.rs
@@ -109,6 +109,7 @@ use rustc_data_structures::{base_n, flock};
 use rustc_errors::ErrorGuaranteed;
 use rustc_fs_util::{link_or_copy, LinkOrCopy};
 use rustc_session::{Session, StableCrateId};
+use rustc_span::Symbol;
 
 use std::fs as std_fs;
 use std::io::{self, ErrorKind};
@@ -202,7 +203,7 @@ pub fn in_incr_comp_dir(incr_comp_session_dir: &Path, file_name: &str) -> PathBu
 /// [`rustc_interface::queries::dep_graph`]: ../../rustc_interface/struct.Queries.html#structfield.dep_graph
 pub fn prepare_session_directory(
     sess: &Session,
-    crate_name: &str,
+    crate_name: Symbol,
     stable_crate_id: StableCrateId,
 ) -> Result<(), ErrorGuaranteed> {
     if sess.opts.incremental.is_none() {
@@ -657,7 +658,7 @@ fn string_to_timestamp(s: &str) -> Result<SystemTime, ()> {
     Ok(UNIX_EPOCH + duration)
 }
 
-fn crate_path(sess: &Session, crate_name: &str, stable_crate_id: StableCrateId) -> PathBuf {
+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);
diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
index 662136ca18d..980a17e41e1 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
@@ -80,6 +80,7 @@ use rustc_middle::ty::{
 use rustc_span::{sym, symbol::kw, BytePos, DesugaringKind, Pos, Span};
 use rustc_target::spec::abi;
 use std::ops::{ControlFlow, Deref};
+use std::path::PathBuf;
 use std::{cmp, fmt, iter};
 
 mod note;
@@ -341,7 +342,15 @@ pub fn unexpected_hidden_region_diagnostic<'tcx>(
 
 impl<'tcx> InferCtxt<'tcx> {
     pub fn get_impl_future_output_ty(&self, ty: Ty<'tcx>) -> Option<Ty<'tcx>> {
-        let ty::Opaque(def_id, substs) = *ty.kind() else { return None; };
+        let (def_id, substs) = match *ty.kind() {
+            ty::Opaque(def_id, substs) => (def_id, substs),
+            ty::Projection(data)
+                if self.tcx.def_kind(data.item_def_id) == DefKind::ImplTraitPlaceholder =>
+            {
+                (data.item_def_id, data.substs)
+            }
+            _ => return None,
+        };
 
         let future_trait = self.tcx.require_lang_item(LangItem::Future, None);
         let item_def_id = self.tcx.associated_item_def_ids(future_trait)[0];
@@ -1344,10 +1353,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                             .map(|(mod_str, _)| mod_str.len() + separator_len)
                             .sum();
 
-                    debug!(
-                        "cmp: separator_len={}, split_idx={}, min_len={}",
-                        separator_len, split_idx, min_len
-                    );
+                    debug!(?separator_len, ?split_idx, ?min_len, "cmp");
 
                     if split_idx >= min_len {
                         // paths are identical, highlight everything
@@ -1358,7 +1364,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                     } else {
                         let (common, uniq1) = t1_str.split_at(split_idx);
                         let (_, uniq2) = t2_str.split_at(split_idx);
-                        debug!("cmp: common={}, uniq1={}, uniq2={}", common, uniq1, uniq2);
+                        debug!(?common, ?uniq1, ?uniq2, "cmp");
 
                         values.0.push_normal(common);
                         values.0.push_highlighted(uniq1);
@@ -1651,17 +1657,14 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                     }
                     ValuePairs::Regions(_) => (false, Mismatch::Fixed("lifetime")),
                 };
-                let vals = match self.values_str(values) {
-                    Some((expected, found)) => Some((expected, found)),
-                    None => {
-                        // Derived error. Cancel the emitter.
-                        // NOTE(eddyb) this was `.cancel()`, but `diag`
-                        // is borrowed, so we can't fully defuse it.
-                        diag.downgrade_to_delayed_bug();
-                        return;
-                    }
+                let Some(vals) = self.values_str(values) else {
+                    // Derived error. Cancel the emitter.
+                    // NOTE(eddyb) this was `.cancel()`, but `diag`
+                    // is borrowed, so we can't fully defuse it.
+                    diag.downgrade_to_delayed_bug();
+                    return;
                 };
-                (vals, exp_found, is_simple_error, Some(values))
+                (Some(vals), exp_found, is_simple_error, Some(values))
             }
         };
 
@@ -1693,7 +1696,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
             label_or_note(span, &terr.to_string());
         }
 
-        if let Some((expected, found)) = expected_found {
+        if let Some((expected, found, exp_p, found_p)) = expected_found {
             let (expected_label, found_label, exp_found) = match exp_found {
                 Mismatch::Variable(ef) => (
                     ef.expected.prefix_string(self.tcx),
@@ -1810,32 +1813,41 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                 }
                 TypeError::Sorts(values) => {
                     let extra = expected == found;
-                    let sort_string = |ty: Ty<'tcx>| match (extra, ty.kind()) {
-                        (true, ty::Opaque(def_id, _)) => {
-                            let sm = self.tcx.sess.source_map();
-                            let pos = sm.lookup_char_pos(self.tcx.def_span(*def_id).lo());
-                            format!(
-                                " (opaque type at <{}:{}:{}>)",
-                                sm.filename_for_diagnostics(&pos.file.name),
-                                pos.line,
-                                pos.col.to_usize() + 1,
-                            )
-                        }
-                        (true, ty::Projection(proj))
-                            if self.tcx.def_kind(proj.item_def_id)
-                                == DefKind::ImplTraitPlaceholder =>
-                        {
-                            let sm = self.tcx.sess.source_map();
-                            let pos = sm.lookup_char_pos(self.tcx.def_span(proj.item_def_id).lo());
-                            format!(
-                                " (trait associated opaque type at <{}:{}:{}>)",
-                                sm.filename_for_diagnostics(&pos.file.name),
-                                pos.line,
-                                pos.col.to_usize() + 1,
-                            )
+                    let sort_string = |ty: Ty<'tcx>, path: Option<PathBuf>| {
+                        let mut s = match (extra, ty.kind()) {
+                            (true, ty::Opaque(def_id, _)) => {
+                                let sm = self.tcx.sess.source_map();
+                                let pos = sm.lookup_char_pos(self.tcx.def_span(*def_id).lo());
+                                format!(
+                                    " (opaque type at <{}:{}:{}>)",
+                                    sm.filename_for_diagnostics(&pos.file.name),
+                                    pos.line,
+                                    pos.col.to_usize() + 1,
+                                )
+                            }
+                            (true, ty::Projection(proj))
+                                if self.tcx.def_kind(proj.item_def_id)
+                                    == DefKind::ImplTraitPlaceholder =>
+                            {
+                                let sm = self.tcx.sess.source_map();
+                                let pos = sm.lookup_char_pos(self.tcx.def_span(proj.item_def_id).lo());
+                                format!(
+                                    " (trait associated opaque type at <{}:{}:{}>)",
+                                    sm.filename_for_diagnostics(&pos.file.name),
+                                    pos.line,
+                                    pos.col.to_usize() + 1,
+                                )
+                            }
+                            (true, _) => format!(" ({})", ty.sort_string(self.tcx)),
+                            (false, _) => "".to_string(),
+                        };
+                        if let Some(path) = path {
+                            s.push_str(&format!(
+                                "\nthe full type name has been written to '{}'",
+                                path.display(),
+                            ));
                         }
-                        (true, _) => format!(" ({})", ty.sort_string(self.tcx)),
-                        (false, _) => "".to_string(),
+                        s
                     };
                     if !(values.expected.is_simple_text() && values.found.is_simple_text())
                         || (exp_found.map_or(false, |ef| {
@@ -1857,8 +1869,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                             expected,
                             &found_label,
                             found,
-                            &sort_string(values.expected),
-                            &sort_string(values.found),
+                            &sort_string(values.expected, exp_p),
+                            &sort_string(values.found, found_p),
                         );
                     }
                 }
@@ -2331,7 +2343,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                 let code = trace.cause.code();
                 if let &MatchExpressionArm(box MatchExpressionArmCause { source, .. }) = code
                     && let hir::MatchSource::TryDesugar = source
-                    && let Some((expected_ty, found_ty)) = self.values_str(trace.values)
+                    && let Some((expected_ty, found_ty, _, _)) = self.values_str(trace.values)
                 {
                     err.note(&format!(
                         "`?` operator cannot convert from `{}` to `{}`",
@@ -2447,7 +2459,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
     fn values_str(
         &self,
         values: ValuePairs<'tcx>,
-    ) -> Option<(DiagnosticStyledString, DiagnosticStyledString)> {
+    ) -> Option<(DiagnosticStyledString, DiagnosticStyledString, Option<PathBuf>, Option<PathBuf>)>
+    {
         match values {
             infer::Regions(exp_found) => self.expected_found_str(exp_found),
             infer::Terms(exp_found) => self.expected_found_str_term(exp_found),
@@ -2457,7 +2470,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                     found: exp_found.found.print_only_trait_path(),
                 };
                 match self.expected_found_str(pretty_exp_found) {
-                    Some((expected, found)) if expected == found => {
+                    Some((expected, found, _, _)) if expected == found => {
                         self.expected_found_str(exp_found)
                     }
                     ret => ret,
@@ -2469,7 +2482,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                     found: exp_found.found.print_only_trait_path(),
                 };
                 match self.expected_found_str(pretty_exp_found) {
-                    Some((expected, found)) if expected == found => {
+                    Some((expected, found, _, _)) if expected == found => {
                         self.expected_found_str(exp_found)
                     }
                     ret => ret,
@@ -2481,17 +2494,41 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
     fn expected_found_str_term(
         &self,
         exp_found: ty::error::ExpectedFound<ty::Term<'tcx>>,
-    ) -> Option<(DiagnosticStyledString, DiagnosticStyledString)> {
+    ) -> Option<(DiagnosticStyledString, DiagnosticStyledString, Option<PathBuf>, Option<PathBuf>)>
+    {
         let exp_found = self.resolve_vars_if_possible(exp_found);
         if exp_found.references_error() {
             return None;
         }
 
         Some(match (exp_found.expected.unpack(), exp_found.found.unpack()) {
-            (ty::TermKind::Ty(expected), ty::TermKind::Ty(found)) => self.cmp(expected, found),
+            (ty::TermKind::Ty(expected), ty::TermKind::Ty(found)) => {
+                let (mut exp, mut fnd) = self.cmp(expected, found);
+                // Use the terminal width as the basis to determine when to compress the printed
+                // out type, but give ourselves some leeway to avoid ending up creating a file for
+                // a type that is somewhat shorter than the path we'd write to.
+                let len = self.tcx.sess().diagnostic_width() + 40;
+                let exp_s = exp.content();
+                let fnd_s = fnd.content();
+                let mut exp_p = None;
+                let mut fnd_p = None;
+                if exp_s.len() > len {
+                    let (exp_s, exp_path) = self.tcx.short_ty_string(expected);
+                    exp = DiagnosticStyledString::highlighted(exp_s);
+                    exp_p = exp_path;
+                }
+                if fnd_s.len() > len {
+                    let (fnd_s, fnd_path) = self.tcx.short_ty_string(found);
+                    fnd = DiagnosticStyledString::highlighted(fnd_s);
+                    fnd_p = fnd_path;
+                }
+                (exp, fnd, exp_p, fnd_p)
+            }
             _ => (
                 DiagnosticStyledString::highlighted(exp_found.expected.to_string()),
                 DiagnosticStyledString::highlighted(exp_found.found.to_string()),
+                None,
+                None,
             ),
         })
     }
@@ -2500,7 +2537,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
     fn expected_found_str<T: fmt::Display + TypeFoldable<'tcx>>(
         &self,
         exp_found: ty::error::ExpectedFound<T>,
-    ) -> Option<(DiagnosticStyledString, DiagnosticStyledString)> {
+    ) -> Option<(DiagnosticStyledString, DiagnosticStyledString, Option<PathBuf>, Option<PathBuf>)>
+    {
         let exp_found = self.resolve_vars_if_possible(exp_found);
         if exp_found.references_error() {
             return None;
@@ -2509,6 +2547,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
         Some((
             DiagnosticStyledString::highlighted(exp_found.expected.to_string()),
             DiagnosticStyledString::highlighted(exp_found.found.to_string()),
+            None,
+            None,
         ))
     }
 
@@ -2842,36 +2882,29 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
         debug!("report_sub_sup_conflict: sup_region={:?}", sup_region);
         debug!("report_sub_sup_conflict: sup_origin={:?}", sup_origin);
 
-        if let (&infer::Subtype(ref sup_trace), &infer::Subtype(ref sub_trace)) =
-            (&sup_origin, &sub_origin)
+        if let infer::Subtype(ref sup_trace) = sup_origin
+            && let infer::Subtype(ref sub_trace) = sub_origin
+            && let Some((sup_expected, sup_found, _, _)) = self.values_str(sup_trace.values)
+            && let Some((sub_expected, sub_found, _, _)) = self.values_str(sub_trace.values)
+            && sub_expected == sup_expected
+            && sub_found == sup_found
         {
-            debug!("report_sub_sup_conflict: sup_trace={:?}", sup_trace);
-            debug!("report_sub_sup_conflict: sub_trace={:?}", sub_trace);
-            debug!("report_sub_sup_conflict: sup_trace.values={:?}", sup_trace.values);
-            debug!("report_sub_sup_conflict: sub_trace.values={:?}", sub_trace.values);
-
-            if let (Some((sup_expected, sup_found)), Some((sub_expected, sub_found))) =
-                (self.values_str(sup_trace.values), self.values_str(sub_trace.values))
-            {
-                if sub_expected == sup_expected && sub_found == sup_found {
-                    note_and_explain_region(
-                        self.tcx,
-                        &mut err,
-                        "...but the lifetime must also be valid for ",
-                        sub_region,
-                        "...",
-                        None,
-                    );
-                    err.span_note(
-                        sup_trace.cause.span,
-                        &format!("...so that the {}", sup_trace.cause.as_requirement_str()),
-                    );
+            note_and_explain_region(
+                self.tcx,
+                &mut err,
+                "...but the lifetime must also be valid for ",
+                sub_region,
+                "...",
+                None,
+            );
+            err.span_note(
+                sup_trace.cause.span,
+                &format!("...so that the {}", sup_trace.cause.as_requirement_str()),
+            );
 
-                    err.note_expected_found(&"", sup_expected, &"", sup_found);
-                    err.emit();
-                    return;
-                }
-            }
+            err.note_expected_found(&"", sup_expected, &"", sup_found);
+            err.emit();
+            return;
         }
 
         self.note_region_origin(&mut err, &sup_origin);
diff --git a/compiler/rustc_infer/src/infer/error_reporting/note.rs b/compiler/rustc_infer/src/infer/error_reporting/note.rs
index 41b115f3377..d2dffa4a0b7 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/note.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/note.rs
@@ -16,7 +16,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
             infer::Subtype(ref trace) => RegionOriginNote::WithRequirement {
                 span: trace.cause.span,
                 requirement: ObligationCauseAsDiagArg(trace.cause.clone()),
-                expected_found: self.values_str(trace.values),
+                expected_found: self.values_str(trace.values).map(|(e, f, _, _)| (e, f)),
             }
             .add_to_diagnostic(err),
             infer::Reborrow(span) => {
diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs
index 6b5b5df9e2a..f808c1438bf 100644
--- a/compiler/rustc_interface/src/passes.rs
+++ b/compiler/rustc_interface/src/passes.rs
@@ -12,6 +12,7 @@ use rustc_ast::{self as ast, visit};
 use rustc_borrowck as mir_borrowck;
 use rustc_codegen_ssa::traits::CodegenBackend;
 use rustc_data_structures::parallel;
+use rustc_data_structures::steal::Steal;
 use rustc_data_structures::sync::{Lrc, OnceCell, WorkerLocal};
 use rustc_errors::{ErrorGuaranteed, PResult};
 use rustc_expand::base::{ExtCtxt, LintStoreExpand, ResolverExpand};
@@ -157,7 +158,7 @@ pub fn create_resolver(
     sess: Lrc<Session>,
     metadata_loader: Box<MetadataLoaderDyn>,
     krate: &ast::Crate,
-    crate_name: &str,
+    crate_name: Symbol,
 ) -> BoxedResolver {
     trace!("create_resolver");
     BoxedResolver::new(sess, move |sess, resolver_arenas| {
@@ -170,7 +171,7 @@ pub fn register_plugins<'a>(
     metadata_loader: &'a dyn MetadataLoader,
     register_lints: impl Fn(&Session, &mut LintStore),
     mut krate: ast::Crate,
-    crate_name: &str,
+    crate_name: Symbol,
 ) -> Result<(ast::Crate, LintStore)> {
     krate = sess.time("attributes_injection", || {
         rustc_builtin_macros::cmdline_attrs::inject(
@@ -227,19 +228,21 @@ fn pre_expansion_lint<'a>(
     lint_store: &LintStore,
     registered_tools: &RegisteredTools,
     check_node: impl EarlyCheckNode<'a>,
-    node_name: &str,
+    node_name: Symbol,
 ) {
-    sess.prof.generic_activity_with_arg("pre_AST_expansion_lint_checks", node_name).run(|| {
-        rustc_lint::check_ast_node(
-            sess,
-            true,
-            lint_store,
-            registered_tools,
-            None,
-            rustc_lint::BuiltinCombinedPreExpansionLintPass::new(),
-            check_node,
-        );
-    });
+    sess.prof.generic_activity_with_arg("pre_AST_expansion_lint_checks", node_name.as_str()).run(
+        || {
+            rustc_lint::check_ast_node(
+                sess,
+                true,
+                lint_store,
+                registered_tools,
+                None,
+                rustc_lint::BuiltinCombinedPreExpansionLintPass::new(),
+                check_node,
+            );
+        },
+    );
 }
 
 // Cannot implement directly for `LintStore` due to trait coherence.
@@ -253,7 +256,7 @@ impl LintStoreExpand for LintStoreExpandImpl<'_> {
         node_id: ast::NodeId,
         attrs: &[ast::Attribute],
         items: &[rustc_ast::ptr::P<ast::Item>],
-        name: &str,
+        name: Symbol,
     ) {
         pre_expansion_lint(sess, self.0, registered_tools, (node_id, attrs, items), name);
     }
@@ -267,7 +270,7 @@ pub fn configure_and_expand(
     sess: &Session,
     lint_store: &LintStore,
     mut krate: ast::Crate,
-    crate_name: &str,
+    crate_name: Symbol,
     resolver: &mut Resolver<'_>,
 ) -> Result<ast::Crate> {
     trace!("configure_and_expand");
@@ -461,7 +464,7 @@ fn generated_output_paths(
     sess: &Session,
     outputs: &OutputFilenames,
     exact_name: bool,
-    crate_name: &str,
+    crate_name: Symbol,
 ) -> Vec<PathBuf> {
     let mut out_filenames = Vec::new();
     for output_type in sess.opts.output_types.keys() {
@@ -660,7 +663,7 @@ pub fn prepare_outputs(
     compiler: &Compiler,
     krate: &ast::Crate,
     boxed_resolver: &RefCell<BoxedResolver>,
-    crate_name: &str,
+    crate_name: Symbol,
 ) -> Result<OutputFilenames> {
     let _timer = sess.timer("prepare_outputs");
 
@@ -770,7 +773,7 @@ pub fn create_global_ctxt<'tcx>(
     dep_graph: DepGraph,
     resolver: Rc<RefCell<BoxedResolver>>,
     outputs: OutputFilenames,
-    crate_name: &str,
+    crate_name: Symbol,
     queries: &'tcx OnceCell<TcxQueries<'tcx>>,
     global_ctxt: &'tcx OnceCell<GlobalCtxt<'tcx>>,
     arena: &'tcx WorkerLocal<Arena<'tcx>>,
@@ -801,6 +804,12 @@ pub fn create_global_ctxt<'tcx>(
         TcxQueries::new(local_providers, extern_providers, query_result_on_disk_cache)
     });
 
+    let ty::ResolverOutputs {
+        definitions,
+        global_ctxt: untracked_resolutions,
+        ast_lowering: untracked_resolver_for_lowering,
+    } = resolver_outputs;
+
     let gcx = sess.time("setup_global_ctxt", || {
         global_ctxt.get_or_init(move || {
             TyCtxt::create_global_ctxt(
@@ -808,7 +817,8 @@ pub fn create_global_ctxt<'tcx>(
                 lint_store,
                 arena,
                 hir_arena,
-                resolver_outputs,
+                definitions,
+                untracked_resolutions,
                 krate,
                 dep_graph,
                 queries.on_disk_cache.as_ref().map(OnDiskCache::as_dyn),
@@ -820,7 +830,12 @@ pub fn create_global_ctxt<'tcx>(
         })
     });
 
-    QueryContext { gcx }
+    let mut qcx = QueryContext { gcx };
+    qcx.enter(|tcx| {
+        tcx.feed_unit_query()
+            .resolver_for_lowering(tcx.arena.alloc(Steal::new(untracked_resolver_for_lowering)))
+    });
+    qcx
 }
 
 /// Runs the resolution, type-checking, region checking and other
@@ -965,12 +980,10 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> {
 pub fn start_codegen<'tcx>(
     codegen_backend: &dyn CodegenBackend,
     tcx: TyCtxt<'tcx>,
-    outputs: &OutputFilenames,
 ) -> Box<dyn Any> {
     info!("Pre-codegen\n{:?}", tcx.debug_stats());
 
-    let (metadata, need_metadata_module) =
-        rustc_metadata::fs::encode_and_write_metadata(tcx, outputs);
+    let (metadata, need_metadata_module) = rustc_metadata::fs::encode_and_write_metadata(tcx);
 
     let codegen = tcx.sess.time("codegen_crate", move || {
         codegen_backend.codegen_crate(tcx, metadata, need_metadata_module)
@@ -986,7 +999,7 @@ pub fn start_codegen<'tcx>(
     info!("Post-codegen\n{:?}", tcx.debug_stats());
 
     if tcx.sess.opts.output_types.contains_key(&OutputType::Mir) {
-        if let Err(error) = rustc_mir_transform::dump_mir::emit_mir(tcx, outputs) {
+        if let Err(error) = rustc_mir_transform::dump_mir::emit_mir(tcx) {
             tcx.sess.emit_err(CantEmitMIR { error });
             tcx.sess.abort_if_errors();
         }
diff --git a/compiler/rustc_interface/src/queries.rs b/compiler/rustc_interface/src/queries.rs
index fc0b11183f7..39e1f2204b0 100644
--- a/compiler/rustc_interface/src/queries.rs
+++ b/compiler/rustc_interface/src/queries.rs
@@ -17,9 +17,11 @@ use rustc_query_impl::Queries as TcxQueries;
 use rustc_session::config::{self, OutputFilenames, OutputType};
 use rustc_session::{output::find_crate_name, Session};
 use rustc_span::symbol::sym;
+use rustc_span::Symbol;
 use std::any::Any;
 use std::cell::{Ref, RefCell, RefMut};
 use std::rc::Rc;
+use std::sync::Arc;
 
 /// Represent the result of a query.
 ///
@@ -73,7 +75,7 @@ pub struct Queries<'tcx> {
 
     dep_graph_future: Query<Option<DepGraphFuture>>,
     parse: Query<ast::Crate>,
-    crate_name: Query<String>,
+    crate_name: Query<Symbol>,
     register_plugins: Query<(ast::Crate, Lrc<LintStore>)>,
     expansion: Query<(Lrc<ast::Crate>, Rc<RefCell<BoxedResolver>>, Lrc<LintStore>)>,
     dep_graph: Query<DepGraph>,
@@ -134,7 +136,7 @@ impl<'tcx> Queries<'tcx> {
                 &*self.codegen_backend().metadata_loader(),
                 self.compiler.register_lints.as_deref().unwrap_or_else(|| empty),
                 krate,
-                &crate_name,
+                crate_name,
             )?;
 
             // Compute the dependency graph (in the background). We want to do
@@ -148,7 +150,7 @@ impl<'tcx> Queries<'tcx> {
         })
     }
 
-    pub fn crate_name(&self) -> Result<&Query<String>> {
+    pub fn crate_name(&self) -> Result<&Query<Symbol>> {
         self.crate_name.compute(|| {
             Ok({
                 let parse_result = self.parse()?;
@@ -164,7 +166,7 @@ impl<'tcx> Queries<'tcx> {
     ) -> Result<&Query<(Lrc<ast::Crate>, Rc<RefCell<BoxedResolver>>, Lrc<LintStore>)>> {
         trace!("expansion");
         self.expansion.compute(|| {
-            let crate_name = self.crate_name()?.peek().clone();
+            let crate_name = *self.crate_name()?.peek();
             let (krate, lint_store) = self.register_plugins()?.take();
             let _timer = self.session().timer("configure_and_expand");
             let sess = self.session();
@@ -172,10 +174,10 @@ impl<'tcx> Queries<'tcx> {
                 sess.clone(),
                 self.codegen_backend().metadata_loader(),
                 &krate,
-                &crate_name,
+                crate_name,
             );
             let krate = resolver.access(|resolver| {
-                passes::configure_and_expand(sess, &lint_store, krate, &crate_name, resolver)
+                passes::configure_and_expand(sess, &lint_store, krate, crate_name, resolver)
             })?;
             Ok((Lrc::new(krate), Rc::new(RefCell::new(resolver)), lint_store))
         })
@@ -200,21 +202,21 @@ impl<'tcx> Queries<'tcx> {
     pub fn prepare_outputs(&self) -> Result<&Query<OutputFilenames>> {
         self.prepare_outputs.compute(|| {
             let (krate, boxed_resolver, _) = &*self.expansion()?.peek();
-            let crate_name = self.crate_name()?.peek();
+            let crate_name = *self.crate_name()?.peek();
             passes::prepare_outputs(
                 self.session(),
                 self.compiler,
                 krate,
                 &*boxed_resolver,
-                &crate_name,
+                crate_name,
             )
         })
     }
 
     pub fn global_ctxt(&'tcx self) -> Result<&Query<QueryContext<'tcx>>> {
         self.global_ctxt.compute(|| {
-            let crate_name = self.crate_name()?.peek().clone();
-            let outputs = self.prepare_outputs()?.peek().clone();
+            let crate_name = *self.crate_name()?.peek();
+            let outputs = self.prepare_outputs()?.take();
             let dep_graph = self.dep_graph()?.peek().clone();
             let (krate, resolver, lint_store) = self.expansion()?.take();
             Ok(passes::create_global_ctxt(
@@ -224,7 +226,7 @@ impl<'tcx> Queries<'tcx> {
                 dep_graph,
                 resolver,
                 outputs,
-                &crate_name,
+                crate_name,
                 &self.queries,
                 &self.gcx,
                 &self.arena,
@@ -235,7 +237,6 @@ impl<'tcx> Queries<'tcx> {
 
     pub fn ongoing_codegen(&'tcx self) -> Result<&Query<Box<dyn Any>>> {
         self.ongoing_codegen.compute(|| {
-            let outputs = self.prepare_outputs()?;
             self.global_ctxt()?.peek_mut().enter(|tcx| {
                 tcx.analysis(()).ok();
 
@@ -249,7 +250,7 @@ impl<'tcx> Queries<'tcx> {
                 // Hook for UI tests.
                 Self::check_for_rustc_errors_attr(tcx);
 
-                Ok(passes::start_codegen(&***self.codegen_backend(), tcx, &*outputs.peek()))
+                Ok(passes::start_codegen(&***self.codegen_backend(), tcx))
             })
         })
     }
@@ -293,8 +294,10 @@ impl<'tcx> Queries<'tcx> {
         let codegen_backend = self.codegen_backend().clone();
 
         let dep_graph = self.dep_graph()?.peek().clone();
-        let prepare_outputs = self.prepare_outputs()?.take();
-        let crate_hash = self.global_ctxt()?.peek_mut().enter(|tcx| tcx.crate_hash(LOCAL_CRATE));
+        let (crate_hash, prepare_outputs) = self
+            .global_ctxt()?
+            .peek_mut()
+            .enter(|tcx| (tcx.crate_hash(LOCAL_CRATE), tcx.output_filenames(()).clone()));
         let ongoing_codegen = self.ongoing_codegen()?.take();
 
         Ok(Linker {
@@ -316,7 +319,7 @@ pub struct Linker {
 
     // compilation outputs
     dep_graph: DepGraph,
-    prepare_outputs: OutputFilenames,
+    prepare_outputs: Arc<OutputFilenames>,
     crate_hash: Svh,
     ongoing_codegen: Box<dyn Any>,
 }
diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs
index a6205f4d3a5..2b8f6557c82 100644
--- a/compiler/rustc_interface/src/tests.rs
+++ b/compiler/rustc_interface/src/tests.rs
@@ -747,6 +747,7 @@ fn test_unstable_options_tracking_hash() {
     tracked!(link_only, true);
     tracked!(llvm_plugins, vec![String::from("plugin_name")]);
     tracked!(location_detail, LocationDetail { file: true, line: false, column: false });
+    tracked!(maximal_hir_to_mir_coverage, true);
     tracked!(merge_functions, Some(MergeFunctions::Disabled));
     tracked!(mir_emit_retag, true);
     tracked!(mir_enable_passes, vec![("DestProp".to_string(), false)]);
diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index 825093384fb..d0d34d8d2b4 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -259,7 +259,7 @@ impl<'tcx> LateLintPass<'tcx> for NonShorthandFieldPatterns {
                 }
                 if let PatKind::Binding(binding_annot, _, ident, None) = fieldpat.pat.kind {
                     if cx.tcx.find_field_index(ident, &variant)
-                        == Some(cx.tcx.field_index(fieldpat.hir_id, cx.typeck_results()))
+                        == Some(cx.typeck_results().field_index(fieldpat.hir_id))
                     {
                         cx.struct_span_lint(
                             NON_SHORTHAND_FIELD_PATTERNS,
diff --git a/compiler/rustc_lint/src/early.rs b/compiler/rustc_lint/src/early.rs
index 215df567e0e..52363b0be2d 100644
--- a/compiler/rustc_lint/src/early.rs
+++ b/compiler/rustc_lint/src/early.rs
@@ -20,21 +20,23 @@ use rustc_ast::ptr::P;
 use rustc_ast::visit::{self as ast_visit, Visitor};
 use rustc_ast::{self as ast, walk_list, HasAttrs};
 use rustc_middle::ty::RegisteredTools;
-use rustc_session::lint::{BufferedEarlyLint, LintBuffer, LintPass};
+use rustc_session::lint::{BufferedEarlyLint, LintBuffer};
 use rustc_session::Session;
 use rustc_span::symbol::Ident;
 use rustc_span::Span;
 
-macro_rules! run_early_pass { ($cx:expr, $f:ident, $($args:expr),*) => ({
-    $cx.pass.$f(&$cx.context, $($args),*);
+macro_rules! run_early_passes { ($cx:expr, $f:ident, $($args:expr),*) => ({
+    for pass in $cx.passes.iter_mut() {
+        pass.$f(&$cx.context, $($args),*);
+    }
 }) }
 
-pub struct EarlyContextAndPass<'a, T: EarlyLintPass> {
+pub struct EarlyContextAndPasses<'a> {
     context: EarlyContext<'a>,
-    pass: T,
+    passes: Vec<EarlyLintPassObject>,
 }
 
-impl<'a, T: EarlyLintPass> EarlyContextAndPass<'a, T> {
+impl<'a> EarlyContextAndPasses<'a> {
     fn check_id(&mut self, id: ast::NodeId) {
         for early_lint in self.context.buffered.take(id) {
             let BufferedEarlyLint { span, msg, node_id: _, lint_id, diagnostic } = early_lint;
@@ -61,27 +63,27 @@ impl<'a, T: EarlyLintPass> EarlyContextAndPass<'a, T> {
 
         self.check_id(id);
         debug!("early context: enter_attrs({:?})", attrs);
-        run_early_pass!(self, enter_lint_attrs, attrs);
+        run_early_passes!(self, enter_lint_attrs, attrs);
         f(self);
         debug!("early context: exit_attrs({:?})", attrs);
-        run_early_pass!(self, exit_lint_attrs, attrs);
+        run_early_passes!(self, exit_lint_attrs, attrs);
         self.context.builder.pop(push);
     }
 }
 
-impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T> {
+impl<'a> ast_visit::Visitor<'a> for EarlyContextAndPasses<'a> {
     fn visit_param(&mut self, param: &'a ast::Param) {
         self.with_lint_attrs(param.id, &param.attrs, |cx| {
-            run_early_pass!(cx, check_param, param);
+            run_early_passes!(cx, check_param, param);
             ast_visit::walk_param(cx, param);
         });
     }
 
     fn visit_item(&mut self, it: &'a ast::Item) {
         self.with_lint_attrs(it.id, &it.attrs, |cx| {
-            run_early_pass!(cx, check_item, it);
+            run_early_passes!(cx, check_item, it);
             ast_visit::walk_item(cx, it);
-            run_early_pass!(cx, check_item_post, it);
+            run_early_passes!(cx, check_item_post, it);
         })
     }
 
@@ -92,10 +94,10 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T>
     }
 
     fn visit_pat(&mut self, p: &'a ast::Pat) {
-        run_early_pass!(self, check_pat, p);
+        run_early_passes!(self, check_pat, p);
         self.check_id(p.id);
         ast_visit::walk_pat(self, p);
-        run_early_pass!(self, check_pat_post, p);
+        run_early_passes!(self, check_pat_post, p);
     }
 
     fn visit_pat_field(&mut self, field: &'a ast::PatField) {
@@ -111,7 +113,7 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T>
 
     fn visit_expr(&mut self, e: &'a ast::Expr) {
         self.with_lint_attrs(e.id, &e.attrs, |cx| {
-            run_early_pass!(cx, check_expr, e);
+            run_early_passes!(cx, check_expr, e);
             ast_visit::walk_expr(cx, e);
         })
     }
@@ -132,7 +134,7 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T>
         // Note that statements get their attributes from
         // the AST struct that they wrap (e.g. an item)
         self.with_lint_attrs(s.id, s.attrs(), |cx| {
-            run_early_pass!(cx, check_stmt, s);
+            run_early_passes!(cx, check_stmt, s);
             cx.check_id(s.id);
         });
         // The visitor for the AST struct wrapped
@@ -143,7 +145,7 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T>
     }
 
     fn visit_fn(&mut self, fk: ast_visit::FnKind<'a>, span: Span, id: ast::NodeId) {
-        run_early_pass!(self, check_fn, fk, span, id);
+        run_early_passes!(self, check_fn, fk, span, id);
         self.check_id(id);
         ast_visit::walk_fn(self, fk);
 
@@ -171,37 +173,37 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T>
 
     fn visit_variant(&mut self, v: &'a ast::Variant) {
         self.with_lint_attrs(v.id, &v.attrs, |cx| {
-            run_early_pass!(cx, check_variant, v);
+            run_early_passes!(cx, check_variant, v);
             ast_visit::walk_variant(cx, v);
         })
     }
 
     fn visit_ty(&mut self, t: &'a ast::Ty) {
-        run_early_pass!(self, check_ty, t);
+        run_early_passes!(self, check_ty, t);
         self.check_id(t.id);
         ast_visit::walk_ty(self, t);
     }
 
     fn visit_ident(&mut self, ident: Ident) {
-        run_early_pass!(self, check_ident, ident);
+        run_early_passes!(self, check_ident, ident);
     }
 
     fn visit_local(&mut self, l: &'a ast::Local) {
         self.with_lint_attrs(l.id, &l.attrs, |cx| {
-            run_early_pass!(cx, check_local, l);
+            run_early_passes!(cx, check_local, l);
             ast_visit::walk_local(cx, l);
         })
     }
 
     fn visit_block(&mut self, b: &'a ast::Block) {
-        run_early_pass!(self, check_block, b);
+        run_early_passes!(self, check_block, b);
         self.check_id(b.id);
         ast_visit::walk_block(self, b);
     }
 
     fn visit_arm(&mut self, a: &'a ast::Arm) {
         self.with_lint_attrs(a.id, &a.attrs, |cx| {
-            run_early_pass!(cx, check_arm, a);
+            run_early_passes!(cx, check_arm, a);
             ast_visit::walk_arm(cx, a);
         })
     }
@@ -220,19 +222,19 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T>
     }
 
     fn visit_generic_arg(&mut self, arg: &'a ast::GenericArg) {
-        run_early_pass!(self, check_generic_arg, arg);
+        run_early_passes!(self, check_generic_arg, arg);
         ast_visit::walk_generic_arg(self, arg);
     }
 
     fn visit_generic_param(&mut self, param: &'a ast::GenericParam) {
         self.with_lint_attrs(param.id, &param.attrs, |cx| {
-            run_early_pass!(cx, check_generic_param, param);
+            run_early_passes!(cx, check_generic_param, param);
             ast_visit::walk_generic_param(cx, param);
         });
     }
 
     fn visit_generics(&mut self, g: &'a ast::Generics) {
-        run_early_pass!(self, check_generics, g);
+        run_early_passes!(self, check_generics, g);
         ast_visit::walk_generics(self, g);
     }
 
@@ -241,18 +243,18 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T>
     }
 
     fn visit_poly_trait_ref(&mut self, t: &'a ast::PolyTraitRef) {
-        run_early_pass!(self, check_poly_trait_ref, t);
+        run_early_passes!(self, check_poly_trait_ref, t);
         ast_visit::walk_poly_trait_ref(self, t);
     }
 
     fn visit_assoc_item(&mut self, item: &'a ast::AssocItem, ctxt: ast_visit::AssocCtxt) {
         self.with_lint_attrs(item.id, &item.attrs, |cx| match ctxt {
             ast_visit::AssocCtxt::Trait => {
-                run_early_pass!(cx, check_trait_item, item);
+                run_early_passes!(cx, check_trait_item, item);
                 ast_visit::walk_assoc_item(cx, item, ctxt);
             }
             ast_visit::AssocCtxt::Impl => {
-                run_early_pass!(cx, check_impl_item, item);
+                run_early_passes!(cx, check_impl_item, item);
                 ast_visit::walk_assoc_item(cx, item, ctxt);
             }
         });
@@ -273,45 +275,20 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T>
     }
 
     fn visit_attribute(&mut self, attr: &'a ast::Attribute) {
-        run_early_pass!(self, check_attribute, attr);
+        run_early_passes!(self, check_attribute, attr);
     }
 
     fn visit_mac_def(&mut self, mac: &'a ast::MacroDef, id: ast::NodeId) {
-        run_early_pass!(self, check_mac_def, mac);
+        run_early_passes!(self, check_mac_def, mac);
         self.check_id(id);
     }
 
     fn visit_mac_call(&mut self, mac: &'a ast::MacCall) {
-        run_early_pass!(self, check_mac, mac);
+        run_early_passes!(self, check_mac, mac);
         ast_visit::walk_mac(self, mac);
     }
 }
 
-struct EarlyLintPassObjects<'a> {
-    lints: &'a mut [EarlyLintPassObject],
-}
-
-#[allow(rustc::lint_pass_impl_without_macro)]
-impl LintPass for EarlyLintPassObjects<'_> {
-    fn name(&self) -> &'static str {
-        panic!()
-    }
-}
-
-macro_rules! early_lint_pass_impl {
-    ([], [$($(#[$attr:meta])* fn $name:ident($($param:ident: $arg:ty),*);)*]) => (
-        impl EarlyLintPass for EarlyLintPassObjects<'_> {
-            $(fn $name(&mut self, context: &EarlyContext<'_>, $($param: $arg),*) {
-                for obj in self.lints.iter_mut() {
-                    obj.$name(context, $($param),*);
-                }
-            })*
-        }
-    )
-}
-
-crate::early_lint_methods!(early_lint_pass_impl, []);
-
 /// Early lints work on different nodes - either on the crate root, or on freshly loaded modules.
 /// This trait generalizes over those nodes.
 pub trait EarlyCheckNode<'a>: Copy {
@@ -319,7 +296,7 @@ pub trait EarlyCheckNode<'a>: Copy {
     fn attrs<'b>(self) -> &'b [ast::Attribute]
     where
         'a: 'b;
-    fn check<'b>(self, cx: &mut EarlyContextAndPass<'b, impl EarlyLintPass>)
+    fn check<'b>(self, cx: &mut EarlyContextAndPasses<'b>)
     where
         'a: 'b;
 }
@@ -334,13 +311,13 @@ impl<'a> EarlyCheckNode<'a> for &'a ast::Crate {
     {
         &self.attrs
     }
-    fn check<'b>(self, cx: &mut EarlyContextAndPass<'b, impl EarlyLintPass>)
+    fn check<'b>(self, cx: &mut EarlyContextAndPasses<'b>)
     where
         'a: 'b,
     {
-        run_early_pass!(cx, check_crate, self);
+        run_early_passes!(cx, check_crate, self);
         ast_visit::walk_crate(cx, self);
-        run_early_pass!(cx, check_crate_post, self);
+        run_early_passes!(cx, check_crate_post, self);
     }
 }
 
@@ -354,7 +331,7 @@ impl<'a> EarlyCheckNode<'a> for (ast::NodeId, &'a [ast::Attribute], &'a [P<ast::
     {
         self.1
     }
-    fn check<'b>(self, cx: &mut EarlyContextAndPass<'b, impl EarlyLintPass>)
+    fn check<'b>(self, cx: &mut EarlyContextAndPasses<'b>)
     where
         'a: 'b,
     {
@@ -374,10 +351,10 @@ pub fn check_ast_node<'a>(
 ) {
     let passes =
         if pre_expansion { &lint_store.pre_expansion_passes } else { &lint_store.early_passes };
-    let mut passes: Vec<_> = passes.iter().map(|p| (p)()).collect();
+    let mut passes: Vec<EarlyLintPassObject> = passes.iter().map(|p| (p)()).collect();
     passes.push(Box::new(builtin_lints));
 
-    let mut cx = EarlyContextAndPass {
+    let mut cx = EarlyContextAndPasses {
         context: EarlyContext::new(
             sess,
             !pre_expansion,
@@ -385,7 +362,7 @@ pub fn check_ast_node<'a>(
             registered_tools,
             lint_buffer.unwrap_or_default(),
         ),
-        pass: EarlyLintPassObjects { lints: &mut passes[..] },
+        passes,
     };
     cx.with_lint_attrs(check_node.id(), check_node.attrs(), |cx| check_node.check(cx));
 
diff --git a/compiler/rustc_lint/src/late.rs b/compiler/rustc_lint/src/late.rs
index e1aedc26d1b..8a50cb1f19e 100644
--- a/compiler/rustc_lint/src/late.rs
+++ b/compiler/rustc_lint/src/late.rs
@@ -23,7 +23,6 @@ use rustc_hir::intravisit as hir_visit;
 use rustc_hir::intravisit::Visitor;
 use rustc_middle::hir::nested_filter;
 use rustc_middle::ty::{self, TyCtxt};
-use rustc_session::lint::LintPass;
 use rustc_span::Span;
 
 use std::any::Any;
@@ -37,15 +36,17 @@ pub fn unerased_lint_store(tcx: TyCtxt<'_>) -> &LintStore {
 }
 
 macro_rules! lint_callback { ($cx:expr, $f:ident, $($args:expr),*) => ({
-    $cx.pass.$f(&$cx.context, $($args),*);
+    for pass in $cx.passes.iter_mut() {
+        pass.$f(&$cx.context, $($args),*);
+    }
 }) }
 
-struct LateContextAndPass<'tcx, T: LateLintPass<'tcx>> {
+struct LateContextAndPasses<'tcx> {
     context: LateContext<'tcx>,
-    pass: T,
+    passes: Vec<LateLintPassObject<'tcx>>,
 }
 
-impl<'tcx, T: LateLintPass<'tcx>> LateContextAndPass<'tcx, T> {
+impl<'tcx> LateContextAndPasses<'tcx> {
     /// Merge the lints specified by any lint attributes into the
     /// current lint context, call the provided function, then reset the
     /// lints in effect to their previous state.
@@ -81,7 +82,7 @@ impl<'tcx, T: LateLintPass<'tcx>> LateContextAndPass<'tcx, T> {
     }
 }
 
-impl<'tcx, T: LateLintPass<'tcx>> hir_visit::Visitor<'tcx> for LateContextAndPass<'tcx, T> {
+impl<'tcx> hir_visit::Visitor<'tcx> for LateContextAndPasses<'tcx> {
     type NestedFilter = nested_filter::All;
 
     /// Because lints are scoped lexically, we want to walk nested
@@ -301,31 +302,6 @@ impl<'tcx, T: LateLintPass<'tcx>> hir_visit::Visitor<'tcx> for LateContextAndPas
     }
 }
 
-struct LateLintPassObjects<'a, 'tcx> {
-    lints: &'a mut [LateLintPassObject<'tcx>],
-}
-
-#[allow(rustc::lint_pass_impl_without_macro)]
-impl LintPass for LateLintPassObjects<'_, '_> {
-    fn name(&self) -> &'static str {
-        panic!()
-    }
-}
-
-macro_rules! late_lint_pass_impl {
-    ([], [$hir:tt], [$($(#[$attr:meta])* fn $name:ident($($param:ident: $arg:ty),*);)*]) => {
-        impl<$hir> LateLintPass<$hir> for LateLintPassObjects<'_, $hir> {
-            $(fn $name(&mut self, context: &LateContext<$hir>, $($param: $arg),*) {
-                for obj in self.lints.iter_mut() {
-                    obj.$name(context, $($param),*);
-                }
-            })*
-        }
-    };
-}
-
-crate::late_lint_methods!(late_lint_pass_impl, [], ['tcx]);
-
 pub(super) fn late_lint_mod<'tcx, T: LateLintPass<'tcx> + 'tcx>(
     tcx: TyCtxt<'tcx>,
     module_def_id: LocalDefId,
@@ -346,9 +322,8 @@ pub(super) fn late_lint_mod<'tcx, T: LateLintPass<'tcx> + 'tcx>(
     let mut passes: Vec<_> =
         unerased_lint_store(tcx).late_module_passes.iter().map(|pass| (pass)(tcx)).collect();
     passes.push(Box::new(builtin_lints));
-    let pass = LateLintPassObjects { lints: &mut passes[..] };
 
-    let mut cx = LateContextAndPass { context, pass };
+    let mut cx = LateContextAndPasses { context, passes };
 
     let (module, _span, hir_id) = tcx.hir().get_module(module_def_id);
     cx.process_mod(module, hir_id);
@@ -377,9 +352,8 @@ fn late_lint_crate<'tcx, T: LateLintPass<'tcx> + 'tcx>(tcx: TyCtxt<'tcx>, builti
     let mut passes =
         unerased_lint_store(tcx).late_passes.iter().map(|p| (p)(tcx)).collect::<Vec<_>>();
     passes.push(Box::new(builtin_lints));
-    let pass = LateLintPassObjects { lints: &mut passes[..] };
 
-    let mut cx = LateContextAndPass { context, pass };
+    let mut cx = LateContextAndPasses { context, passes };
 
     // Visit the whole crate.
     cx.with_lint_attrs(hir::CRATE_HIR_ID, |cx| {
diff --git a/compiler/rustc_lint/src/pass_by_value.rs b/compiler/rustc_lint/src/pass_by_value.rs
index cf1d82f4c06..0fa81b7e4e0 100644
--- a/compiler/rustc_lint/src/pass_by_value.rs
+++ b/compiler/rustc_lint/src/pass_by_value.rs
@@ -10,7 +10,7 @@ declare_tool_lint! {
     /// The `rustc_pass_by_value` lint marks a type with `#[rustc_pass_by_value]` requiring it to
     /// always be passed by value. This is usually used for types that are thin wrappers around
     /// references, so there is no benefit to an extra layer of indirection. (Example: `Ty` which
-    /// is a reference to an `Interned<TyS>`)
+    /// is a reference to an `Interned<TyKind>`)
     pub rustc::PASS_BY_VALUE,
     Warn,
     "pass by reference of a type flagged as `#[rustc_pass_by_value]`",
diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs
index a7836ea8e7a..b5db94f8c06 100644
--- a/compiler/rustc_lint/src/unused.rs
+++ b/compiler/rustc_lint/src/unused.rs
@@ -633,13 +633,34 @@ trait UnusedDelimLint {
         left_pos: Option<BytePos>,
         right_pos: Option<BytePos>,
     ) {
+        // If `value` has `ExprKind::Err`, unused delim lint can be broken.
+        // For example, the following code caused ICE.
+        // This is because the `ExprKind::Call` in `value` has `ExprKind::Err` as its argument
+        // and this leads to wrong spans. #104897
+        //
+        // ```
+        // fn f(){(print!(á
+        // ```
+        use rustc_ast::visit::{walk_expr, Visitor};
+        struct ErrExprVisitor {
+            has_error: bool,
+        }
+        impl<'ast> Visitor<'ast> for ErrExprVisitor {
+            fn visit_expr(&mut self, expr: &'ast ast::Expr) {
+                if let ExprKind::Err = expr.kind {
+                    self.has_error = true;
+                    return;
+                }
+                walk_expr(self, expr)
+            }
+        }
+        let mut visitor = ErrExprVisitor { has_error: false };
+        visitor.visit_expr(value);
+        if visitor.has_error {
+            return;
+        }
         let spans = match value.kind {
             ast::ExprKind::Block(ref block, None) if block.stmts.len() == 1 => {
-                if let StmtKind::Expr(expr) = &block.stmts[0].kind
-                    && let ExprKind::Err = expr.kind
-                {
-                    return
-                }
                 if let Some(span) = block.stmts[0].span.find_ancestor_inside(value.span) {
                     Some((value.span.with_hi(span.lo()), value.span.with_lo(span.hi())))
                 } else {
diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
index 7f4d63eed8b..1a3d458c300 100644
--- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
@@ -205,7 +205,12 @@ enum class LLVMRustCodeModel {
   None,
 };
 
-static Optional<CodeModel::Model> fromRust(LLVMRustCodeModel Model) {
+#if LLVM_VERSION_LT(16, 0)
+static Optional<CodeModel::Model>
+#else
+static std::optional<CodeModel::Model>
+#endif
+fromRust(LLVMRustCodeModel Model) {
   switch (Model) {
   case LLVMRustCodeModel::Tiny:
     return CodeModel::Tiny;
@@ -638,7 +643,11 @@ LLVMRustOptimize(
     LLVMSelfProfileInitializeCallbacks(PIC,LlvmSelfProfiler,BeforePassCallback,AfterPassCallback);
   }
 
+#if LLVM_VERSION_LT(16, 0)
   Optional<PGOOptions> PGOOpt;
+#else
+  std::optional<PGOOptions> PGOOpt;
+#endif
   if (PGOGenPath) {
     assert(!PGOUsePath && !PGOSampleUsePath);
     PGOOpt = PGOOptions(PGOGenPath, "", "", PGOOptions::IRInstr,
diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
index 792d921c6a4..3a748f38995 100644
--- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
@@ -17,7 +17,9 @@
 #include "llvm/Pass.h"
 #include "llvm/Bitcode/BitcodeWriter.h"
 #include "llvm/Support/Signals.h"
+#if LLVM_VERSION_LT(16, 0)
 #include "llvm/ADT/Optional.h"
+#endif
 
 #include <iostream>
 
@@ -708,7 +710,11 @@ enum class LLVMRustChecksumKind {
   SHA256,
 };
 
+#if LLVM_VERSION_LT(16, 0)
 static Optional<DIFile::ChecksumKind> fromRust(LLVMRustChecksumKind Kind) {
+#else
+static std::optional<DIFile::ChecksumKind> fromRust(LLVMRustChecksumKind Kind) {
+#endif
   switch (Kind) {
   case LLVMRustChecksumKind::None:
     return None;
@@ -787,8 +793,18 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateFile(
     const char *Filename, size_t FilenameLen,
     const char *Directory, size_t DirectoryLen, LLVMRustChecksumKind CSKind,
     const char *Checksum, size_t ChecksumLen) {
+
+#if LLVM_VERSION_LT(16, 0)
   Optional<DIFile::ChecksumKind> llvmCSKind = fromRust(CSKind);
+#else
+  std::optional<DIFile::ChecksumKind> llvmCSKind = fromRust(CSKind);
+#endif
+
+#if LLVM_VERSION_LT(16, 0)
   Optional<DIFile::ChecksumInfo<StringRef>> CSInfo{};
+#else
+  std::optional<DIFile::ChecksumInfo<StringRef>> CSInfo{};
+#endif
   if (llvmCSKind)
     CSInfo.emplace(*llvmCSKind, StringRef{Checksum, ChecksumLen});
   return wrap(Builder->createFile(StringRef(Filename, FilenameLen),
diff --git a/compiler/rustc_macros/src/query.rs b/compiler/rustc_macros/src/query.rs
index 4047969724a..789d83a0dd0 100644
--- a/compiler/rustc_macros/src/query.rs
+++ b/compiler/rustc_macros/src/query.rs
@@ -364,10 +364,6 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream {
                 modifiers.eval_always.is_none(),
                 "Query {name} cannot be both `feedable` and `eval_always`."
             );
-            assert!(
-                modifiers.no_hash.is_none(),
-                "Query {name} cannot be both `feedable` and `no_hash`."
-            );
             feedable_queries.extend(quote! {
                 #(#doc_comments)*
                 [#attribute_stream] fn #name(#arg) #result,
diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs
index 1a2389c7a84..efeaac8fe9a 100644
--- a/compiler/rustc_metadata/src/creader.rs
+++ b/compiler/rustc_metadata/src/creader.rs
@@ -245,7 +245,7 @@ impl<'a> CrateLoader<'a> {
     pub fn new(
         sess: &'a Session,
         metadata_loader: Box<MetadataLoaderDyn>,
-        local_crate_name: &str,
+        local_crate_name: Symbol,
     ) -> Self {
         let mut stable_crate_ids = FxHashMap::default();
         stable_crate_ids.insert(sess.local_stable_crate_id(), LOCAL_CRATE);
@@ -253,7 +253,7 @@ impl<'a> CrateLoader<'a> {
         CrateLoader {
             sess,
             metadata_loader,
-            local_crate_name: Symbol::intern(local_crate_name),
+            local_crate_name,
             cstore: CStore {
                 // We add an empty entry for LOCAL_CRATE (which maps to zero) in
                 // order to make array indices in `metas` match with the
@@ -1000,7 +1000,7 @@ impl<'a> CrateLoader<'a> {
                 );
                 let name = match orig_name {
                     Some(orig_name) => {
-                        validate_crate_name(self.sess, orig_name.as_str(), Some(item.span));
+                        validate_crate_name(self.sess, orig_name, Some(item.span));
                         orig_name
                     }
                     None => item.ident.name,
diff --git a/compiler/rustc_metadata/src/fs.rs b/compiler/rustc_metadata/src/fs.rs
index c41ae8d55cd..7601f6bd322 100644
--- a/compiler/rustc_metadata/src/fs.rs
+++ b/compiler/rustc_metadata/src/fs.rs
@@ -6,7 +6,7 @@ use crate::{encode_metadata, EncodedMetadata};
 use rustc_data_structures::temp_dir::MaybeTempDir;
 use rustc_hir::def_id::LOCAL_CRATE;
 use rustc_middle::ty::TyCtxt;
-use rustc_session::config::{CrateType, OutputFilenames, OutputType};
+use rustc_session::config::{CrateType, OutputType};
 use rustc_session::output::filename_for_metadata;
 use rustc_session::Session;
 use tempfile::Builder as TempFileBuilder;
@@ -38,10 +38,7 @@ pub fn emit_wrapper_file(
     out_filename
 }
 
-pub fn encode_and_write_metadata(
-    tcx: TyCtxt<'_>,
-    outputs: &OutputFilenames,
-) -> (EncodedMetadata, bool) {
+pub fn encode_and_write_metadata(tcx: TyCtxt<'_>) -> (EncodedMetadata, bool) {
     #[derive(PartialEq, Eq, PartialOrd, Ord)]
     enum MetadataKind {
         None,
@@ -64,7 +61,7 @@ pub fn encode_and_write_metadata(
         .unwrap_or(MetadataKind::None);
 
     let crate_name = tcx.crate_name(LOCAL_CRATE);
-    let out_filename = filename_for_metadata(tcx.sess, crate_name.as_str(), outputs);
+    let out_filename = filename_for_metadata(tcx.sess, crate_name, tcx.output_filenames(()));
     // To avoid races with another rustc process scanning the output directory,
     // we need to write the file somewhere else and atomically move it to its
     // final destination, with an `fs::rename` call. In order for the rename to
diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs
index e83106b1ee5..6de68841fe9 100644
--- a/compiler/rustc_middle/src/arena.rs
+++ b/compiler/rustc_middle/src/arena.rs
@@ -1,3 +1,5 @@
+#![allow(rustc::usage_of_ty_tykind)]
+
 /// This higher-order macro declares a list of types which can be allocated by `Arena`.
 ///
 /// Specifying the `decode` modifier will add decode impls for `&T` and `&[T]` where `T` is the type
@@ -28,6 +30,7 @@ macro_rules! arena_types {
             [decode] typeck_results: rustc_middle::ty::TypeckResults<'tcx>,
             [decode] borrowck_result:
                 rustc_middle::mir::BorrowCheckResult<'tcx>,
+            [] resolver: rustc_data_structures::steal::Steal<rustc_middle::ty::ResolverAstLowering>,
             [decode] unsafety_check_result: rustc_middle::mir::UnsafetyCheckResult,
             [decode] code_region: rustc_middle::mir::coverage::CodeRegion,
             [] const_allocs: rustc_middle::mir::interpret::Allocation,
@@ -88,8 +91,8 @@ macro_rules! arena_types {
             [] hir_id_set: rustc_hir::HirIdSet,
 
             // Interned types
-            [] tys: rustc_data_structures::intern::WithStableHash<rustc_middle::ty::TyS<'tcx>>,
-            [] predicates: rustc_data_structures::intern::WithStableHash<rustc_middle::ty::PredicateS<'tcx>>,
+            [] tys: rustc_type_ir::WithCachedTypeInfo<rustc_middle::ty::TyKind<'tcx>>,
+            [] predicates: rustc_type_ir::WithCachedTypeInfo<rustc_middle::ty::PredicateKind<'tcx>>,
             [] consts: rustc_middle::ty::ConstS<'tcx>,
 
             // Note that this deliberately duplicates items in the `rustc_hir::arena`,
diff --git a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs
index 45d33a1659f..bea884c856a 100644
--- a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs
+++ b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs
@@ -26,8 +26,10 @@ pub struct CodegenFnAttrs {
     /// The `#[target_feature(enable = "...")]` attribute and the enabled
     /// features (only enabled features are supported right now).
     pub target_features: Vec<Symbol>,
-    /// The `#[linkage = "..."]` attribute and the value we found.
+    /// The `#[linkage = "..."]` attribute on Rust-defined items and the value we found.
     pub linkage: Option<Linkage>,
+    /// The `#[linkage = "..."]` attribute on foreign items and the value we found.
+    pub import_linkage: Option<Linkage>,
     /// The `#[link_section = "..."]` attribute, or what executable section this
     /// should be placed in.
     pub link_section: Option<Symbol>,
@@ -113,6 +115,7 @@ impl CodegenFnAttrs {
             link_ordinal: None,
             target_features: vec![],
             linkage: None,
+            import_linkage: None,
             link_section: None,
             no_sanitize: SanitizerSet::empty(),
             instruction_set: None,
diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs
index 5f911d5884a..221105ac48f 100644
--- a/compiler/rustc_middle/src/mir/interpret/allocation.rs
+++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs
@@ -103,7 +103,7 @@ impl hash::Hash for Allocation {
 /// Interned types generally have an `Outer` type and an `Inner` type, where
 /// `Outer` is a newtype around `Interned<Inner>`, and all the operations are
 /// done on `Outer`, because all occurrences are interned. E.g. `Ty` is an
-/// outer type and `TyS` is its inner type.
+/// outer type and `TyKind` is its inner type.
 ///
 /// Here things are different because only const allocations are interned. This
 /// means that both the inner type (`Allocation`) and the outer type
diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs
index 7d2a6bda569..614e0d012b3 100644
--- a/compiler/rustc_middle/src/mir/syntax.rs
+++ b/compiler/rustc_middle/src/mir/syntax.rs
@@ -400,7 +400,7 @@ impl std::fmt::Display for NonDivergingIntrinsic<'_> {
 #[derive(Copy, Clone, TyEncodable, TyDecodable, Debug, PartialEq, Eq, Hash, HashStable)]
 #[rustc_pass_by_value]
 pub enum RetagKind {
-    /// The initial retag when entering a function.
+    /// The initial retag of arguments when entering a function.
     FnEntry,
     /// Retag preparing for a two-phase borrow.
     TwoPhase,
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index d6dea0e9f30..f2f2b22f52a 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -33,7 +33,7 @@ rustc_queries! {
     }
 
     query resolver_for_lowering(_: ()) -> &'tcx Steal<ty::ResolverAstLowering> {
-        eval_always
+        feedable
         no_hash
         desc { "getting the resolver for lowering" }
     }
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index c5683a9db94..b44bc14ec26 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -1,5 +1,7 @@
 //! Type context book-keeping.
 
+#![allow(rustc::usage_of_ty_tykind)]
+
 use crate::arena::Arena;
 use crate::dep_graph::{DepGraph, DepKindStruct};
 use crate::hir::place::Place as HirPlace;
@@ -19,15 +21,15 @@ use crate::ty::{
     self, AdtDef, AdtDefData, AdtKind, Binder, BindingMode, BoundVar, CanonicalPolyFnSig,
     ClosureSizeProfileData, Const, ConstS, DefIdTree, FloatTy, FloatVar, FloatVid,
     GenericParamDefKind, InferTy, IntTy, IntVar, IntVid, List, ParamConst, ParamTy,
-    PolyExistentialPredicate, PolyFnSig, Predicate, PredicateKind, PredicateS, ProjectionTy,
-    Region, RegionKind, ReprOptions, TraitObjectVisitor, Ty, TyKind, TyS, TyVar, TyVid, TypeAndMut,
-    UintTy, Visibility,
+    PolyExistentialPredicate, PolyFnSig, Predicate, PredicateKind, ProjectionTy, Region,
+    RegionKind, ReprOptions, TraitObjectVisitor, Ty, TyKind, TyVar, TyVid, TypeAndMut, UintTy,
+    Visibility,
 };
 use crate::ty::{GenericArg, GenericArgKind, InternalSubsts, SubstsRef, UserSubsts};
 use rustc_ast as ast;
 use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
-use rustc_data_structures::intern::{Interned, WithStableHash};
+use rustc_data_structures::intern::Interned;
 use rustc_data_structures::memmap::Mmap;
 use rustc_data_structures::profiling::SelfProfilerRef;
 use rustc_data_structures::sharded::{IntoPointer, ShardedHashMap};
@@ -68,6 +70,7 @@ use rustc_span::{Span, DUMMY_SP};
 use rustc_target::abi::{Layout, LayoutS, TargetDataLayout, VariantIdx};
 use rustc_target::spec::abi;
 use rustc_type_ir::sty::TyKind::*;
+use rustc_type_ir::WithCachedTypeInfo;
 use rustc_type_ir::{DynKind, InternAs, InternIteratorElement, Interner, TypeFlags};
 
 use std::any::Any;
@@ -81,7 +84,7 @@ use std::mem;
 use std::ops::{Bound, Deref};
 use std::sync::Arc;
 
-use super::{ImplPolarity, ResolverOutputs, RvalueScopes};
+use super::{ImplPolarity, RvalueScopes};
 
 pub trait OnDiskCache<'tcx>: rustc_data_structures::sync::Sync {
     /// Creates a new `OnDiskCache` instance from the serialized data in `data`.
@@ -137,13 +140,13 @@ pub struct CtxtInterners<'tcx> {
 
     // Specifically use a speedy hash algorithm for these hash sets, since
     // they're accessed quite often.
-    type_: InternedSet<'tcx, WithStableHash<TyS<'tcx>>>,
+    type_: InternedSet<'tcx, WithCachedTypeInfo<TyKind<'tcx>>>,
     const_lists: InternedSet<'tcx, List<ty::Const<'tcx>>>,
     substs: InternedSet<'tcx, InternalSubsts<'tcx>>,
     canonical_var_infos: InternedSet<'tcx, List<CanonicalVarInfo<'tcx>>>,
     region: InternedSet<'tcx, RegionKind<'tcx>>,
     poly_existential_predicates: InternedSet<'tcx, List<PolyExistentialPredicate<'tcx>>>,
-    predicate: InternedSet<'tcx, WithStableHash<PredicateS<'tcx>>>,
+    predicate: InternedSet<'tcx, WithCachedTypeInfo<ty::Binder<'tcx, PredicateKind<'tcx>>>>,
     predicates: InternedSet<'tcx, List<Predicate<'tcx>>>,
     projs: InternedSet<'tcx, List<ProjectionKind>>,
     place_elems: InternedSet<'tcx, List<PlaceElem<'tcx>>>,
@@ -194,15 +197,12 @@ impl<'tcx> CtxtInterners<'tcx> {
                     let stable_hash =
                         self.stable_hash(&flags, sess, definitions, cstore, source_span, &kind);
 
-                    let ty_struct = TyS {
-                        kind,
+                    InternedInSet(self.arena.alloc(WithCachedTypeInfo {
+                        internee: kind,
+                        stable_hash,
                         flags: flags.flags,
                         outer_exclusive_binder: flags.outer_exclusive_binder,
-                    };
-
-                    InternedInSet(
-                        self.arena.alloc(WithStableHash { internee: ty_struct, stable_hash }),
-                    )
+                    }))
                 })
                 .0,
         ))
@@ -246,16 +246,12 @@ impl<'tcx> CtxtInterners<'tcx> {
                     let stable_hash =
                         self.stable_hash(&flags, sess, definitions, cstore, source_span, &kind);
 
-                    let predicate_struct = PredicateS {
-                        kind,
+                    InternedInSet(self.arena.alloc(WithCachedTypeInfo {
+                        internee: kind,
+                        stable_hash,
                         flags: flags.flags,
                         outer_exclusive_binder: flags.outer_exclusive_binder,
-                    };
-
-                    InternedInSet(
-                        self.arena
-                            .alloc(WithStableHash { internee: predicate_struct, stable_hash }),
-                    )
+                    }))
                 })
                 .0,
         ))
@@ -671,6 +667,14 @@ impl<'tcx> TypeckResults<'tcx> {
         LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.field_indices }
     }
 
+    pub fn field_index(&self, id: hir::HirId) -> usize {
+        self.field_indices().get(id).cloned().expect("no index for a field")
+    }
+
+    pub fn opt_field_index(&self, id: hir::HirId) -> Option<usize> {
+        self.field_indices().get(id).cloned()
+    }
+
     pub fn user_provided_types(&self) -> LocalTableInContext<'_, CanonicalUserType<'tcx>> {
         LocalTableInContext { hir_owner: self.hir_owner, data: &self.user_provided_types }
     }
@@ -1034,16 +1038,29 @@ pub struct FreeRegionInfo {
 
 /// This struct should only be created by `create_def`.
 #[derive(Copy, Clone)]
-pub struct TyCtxtFeed<'tcx> {
+pub struct TyCtxtFeed<'tcx, KEY: Copy> {
     pub tcx: TyCtxt<'tcx>,
     // Do not allow direct access, as downstream code must not mutate this field.
-    def_id: LocalDefId,
+    key: KEY,
+}
+
+impl<'tcx> TyCtxt<'tcx> {
+    pub fn feed_unit_query(self) -> TyCtxtFeed<'tcx, ()> {
+        TyCtxtFeed { tcx: self, key: () }
+    }
+}
+
+impl<'tcx, KEY: Copy> TyCtxtFeed<'tcx, KEY> {
+    #[inline(always)]
+    pub fn key(&self) -> KEY {
+        self.key
+    }
 }
 
-impl<'tcx> TyCtxtFeed<'tcx> {
+impl<'tcx> TyCtxtFeed<'tcx, LocalDefId> {
     #[inline(always)]
     pub fn def_id(&self) -> LocalDefId {
-        self.def_id
+        self.key
     }
 }
 
@@ -1099,7 +1116,6 @@ pub struct GlobalCtxt<'tcx> {
 
     /// Output of the resolver.
     pub(crate) untracked_resolutions: ty::ResolverGlobalCtxt,
-    untracked_resolver_for_lowering: Steal<ty::ResolverAstLowering>,
     /// The entire crate as AST. This field serves as the input for the hir_crate query,
     /// which lowers it from AST to HIR. It must not be read or used by anything else.
     pub untracked_crate: Steal<Lrc<ast::Crate>>,
@@ -1262,20 +1278,16 @@ impl<'tcx> TyCtxt<'tcx> {
         lint_store: Lrc<dyn Any + sync::Send + sync::Sync>,
         arena: &'tcx WorkerLocal<Arena<'tcx>>,
         hir_arena: &'tcx WorkerLocal<hir::Arena<'tcx>>,
-        resolver_outputs: ResolverOutputs,
+        definitions: Definitions,
+        untracked_resolutions: ty::ResolverGlobalCtxt,
         krate: Lrc<ast::Crate>,
         dep_graph: DepGraph,
         on_disk_cache: Option<&'tcx dyn OnDiskCache<'tcx>>,
         queries: &'tcx dyn query::QueryEngine<'tcx>,
         query_kinds: &'tcx [DepKindStruct<'tcx>],
-        crate_name: &str,
+        crate_name: Symbol,
         output_filenames: OutputFilenames,
     ) -> GlobalCtxt<'tcx> {
-        let ResolverOutputs {
-            definitions,
-            global_ctxt: untracked_resolutions,
-            ast_lowering: untracked_resolver_for_lowering,
-        } = resolver_outputs;
         let data_layout = s.target.parse_data_layout().unwrap_or_else(|err| {
             s.emit_fatal(err);
         });
@@ -1304,7 +1316,6 @@ impl<'tcx> TyCtxt<'tcx> {
             lifetimes: common_lifetimes,
             consts: common_consts,
             untracked_resolutions,
-            untracked_resolver_for_lowering: Steal::new(untracked_resolver_for_lowering),
             untracked_crate: Steal::new(krate),
             on_disk_cache,
             queries,
@@ -1314,7 +1325,7 @@ impl<'tcx> TyCtxt<'tcx> {
             pred_rcache: Default::default(),
             selection_cache: Default::default(),
             evaluation_cache: Default::default(),
-            crate_name: Symbol::intern(crate_name),
+            crate_name,
             data_layout,
             alloc_map: Lock::new(interpret::AllocMap::new()),
             output_filenames: Arc::new(output_filenames),
@@ -1515,7 +1526,7 @@ impl<'tcx> TyCtxtAt<'tcx> {
         self,
         parent: LocalDefId,
         data: hir::definitions::DefPathData,
-    ) -> TyCtxtFeed<'tcx> {
+    ) -> TyCtxtFeed<'tcx, LocalDefId> {
         // This function modifies `self.definitions` using a side-effect.
         // We need to ensure that these side effects are re-run by the incr. comp. engine.
         // Depending on the forever-red node will tell the graph that the calling query
@@ -1536,9 +1547,9 @@ impl<'tcx> TyCtxtAt<'tcx> {
         // This is fine because:
         // - those queries are `eval_always` so we won't miss their result changing;
         // - this write will have happened before these queries are called.
-        let def_id = self.definitions.write().create_def(parent, data);
+        let key = self.definitions.write().create_def(parent, data);
 
-        let feed = TyCtxtFeed { tcx: self.tcx, def_id };
+        let feed = TyCtxtFeed { tcx: self.tcx, key };
         feed.def_span(self.span);
         feed
     }
@@ -2097,7 +2108,7 @@ macro_rules! sty_debug_print {
                 let shards = tcx.interners.type_.lock_shards();
                 let types = shards.iter().flat_map(|shard| shard.keys());
                 for &InternedInSet(t) in types {
-                    let variant = match t.kind {
+                    let variant = match t.internee {
                         ty::Bool | ty::Char | ty::Int(..) | ty::Uint(..) |
                             ty::Float(..) | ty::Str | ty::Never => continue,
                         ty::Error(_) => /* unimportant */ continue,
@@ -2207,51 +2218,26 @@ impl<'tcx, T: 'tcx + ?Sized> IntoPointer for InternedInSet<'tcx, T> {
 }
 
 #[allow(rustc::usage_of_ty_tykind)]
-impl<'tcx> Borrow<TyKind<'tcx>> for InternedInSet<'tcx, WithStableHash<TyS<'tcx>>> {
-    fn borrow<'a>(&'a self) -> &'a TyKind<'tcx> {
-        &self.0.kind
-    }
-}
-
-impl<'tcx> PartialEq for InternedInSet<'tcx, WithStableHash<TyS<'tcx>>> {
-    fn eq(&self, other: &InternedInSet<'tcx, WithStableHash<TyS<'tcx>>>) -> bool {
-        // The `Borrow` trait requires that `x.borrow() == y.borrow()` equals
-        // `x == y`.
-        self.0.kind == other.0.kind
-    }
-}
-
-impl<'tcx> Eq for InternedInSet<'tcx, WithStableHash<TyS<'tcx>>> {}
-
-impl<'tcx> Hash for InternedInSet<'tcx, WithStableHash<TyS<'tcx>>> {
-    fn hash<H: Hasher>(&self, s: &mut H) {
-        // The `Borrow` trait requires that `x.borrow().hash(s) == x.hash(s)`.
-        self.0.kind.hash(s)
-    }
-}
-
-impl<'tcx> Borrow<Binder<'tcx, PredicateKind<'tcx>>>
-    for InternedInSet<'tcx, WithStableHash<PredicateS<'tcx>>>
-{
-    fn borrow<'a>(&'a self) -> &'a Binder<'tcx, PredicateKind<'tcx>> {
-        &self.0.kind
+impl<'tcx, T> Borrow<T> for InternedInSet<'tcx, WithCachedTypeInfo<T>> {
+    fn borrow<'a>(&'a self) -> &'a T {
+        &self.0.internee
     }
 }
 
-impl<'tcx> PartialEq for InternedInSet<'tcx, WithStableHash<PredicateS<'tcx>>> {
-    fn eq(&self, other: &InternedInSet<'tcx, WithStableHash<PredicateS<'tcx>>>) -> bool {
+impl<'tcx, T: PartialEq> PartialEq for InternedInSet<'tcx, WithCachedTypeInfo<T>> {
+    fn eq(&self, other: &InternedInSet<'tcx, WithCachedTypeInfo<T>>) -> bool {
         // The `Borrow` trait requires that `x.borrow() == y.borrow()` equals
         // `x == y`.
-        self.0.kind == other.0.kind
+        self.0.internee == other.0.internee
     }
 }
 
-impl<'tcx> Eq for InternedInSet<'tcx, WithStableHash<PredicateS<'tcx>>> {}
+impl<'tcx, T: Eq> Eq for InternedInSet<'tcx, WithCachedTypeInfo<T>> {}
 
-impl<'tcx> Hash for InternedInSet<'tcx, WithStableHash<PredicateS<'tcx>>> {
+impl<'tcx, T: Hash> Hash for InternedInSet<'tcx, WithCachedTypeInfo<T>> {
     fn hash<H: Hasher>(&self, s: &mut H) {
         // The `Borrow` trait requires that `x.borrow().hash(s) == x.hash(s)`.
-        self.0.kind.hash(s)
+        self.0.internee.hash(s)
     }
 }
 
@@ -3107,7 +3093,6 @@ fn ptr_eq<T, U>(t: *const T, u: *const U) -> bool {
 
 pub fn provide(providers: &mut ty::query::Providers) {
     providers.resolutions = |tcx, ()| &tcx.untracked_resolutions;
-    providers.resolver_for_lowering = |tcx, ()| &tcx.untracked_resolver_for_lowering;
     providers.module_reexports =
         |tcx, id| tcx.resolutions(()).reexport_map.get(&id).map(|v| &v[..]);
     providers.crate_name = |tcx, id| {
diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs
index d83e17574a0..aa61c39b8d8 100644
--- a/compiler/rustc_middle/src/ty/error.rs
+++ b/compiler/rustc_middle/src/ty/error.rs
@@ -986,23 +986,32 @@ fn foo(&self) -> Self::T { String::new() }
     }
 
     pub fn short_ty_string(self, ty: Ty<'tcx>) -> (String, Option<PathBuf>) {
-        let length_limit = 50;
-        let type_limit = 4;
+        let width = self.sess.diagnostic_width();
+        let length_limit = width.saturating_sub(30);
+        let mut type_limit = 50;
         let regular = FmtPrinter::new(self, hir::def::Namespace::TypeNS)
             .pretty_print_type(ty)
             .expect("could not write to `String`")
             .into_buffer();
-        if regular.len() <= length_limit {
+        if regular.len() <= width {
             return (regular, None);
         }
-        let short = FmtPrinter::new_with_limit(
-            self,
-            hir::def::Namespace::TypeNS,
-            rustc_session::Limit(type_limit),
-        )
-        .pretty_print_type(ty)
-        .expect("could not write to `String`")
-        .into_buffer();
+        let mut short;
+        loop {
+            // Look for the longest properly trimmed path that still fits in lenght_limit.
+            short = FmtPrinter::new_with_limit(
+                self,
+                hir::def::Namespace::TypeNS,
+                rustc_session::Limit(type_limit),
+            )
+            .pretty_print_type(ty)
+            .expect("could not write to `String`")
+            .into_buffer();
+            if short.len() <= length_limit || type_limit == 0 {
+                break;
+            }
+            type_limit -= 1;
+        }
         if regular == short {
             return (regular, None);
         }
diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs
index a8da93e4c69..48329da3e63 100644
--- a/compiler/rustc_middle/src/ty/generics.rs
+++ b/compiler/rustc_middle/src/ty/generics.rs
@@ -101,6 +101,20 @@ impl GenericParamDef {
             _ => None,
         }
     }
+
+    pub fn to_error<'tcx>(
+        &self,
+        tcx: TyCtxt<'tcx>,
+        preceding_substs: &[ty::GenericArg<'tcx>],
+    ) -> ty::GenericArg<'tcx> {
+        match &self.kind {
+            ty::GenericParamDefKind::Lifetime => tcx.lifetimes.re_static.into(),
+            ty::GenericParamDefKind::Type { .. } => tcx.ty_error().into(),
+            ty::GenericParamDefKind::Const { .. } => {
+                tcx.const_error(tcx.bound_type_of(self.def_id).subst(tcx, preceding_substs)).into()
+            }
+        }
+    }
 }
 
 #[derive(Default)]
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index dd4ab3e8d30..c062e508ee3 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -9,6 +9,8 @@
 //!
 //! ["The `ty` module: representing types"]: https://rustc-dev-guide.rust-lang.org/ty.html
 
+#![allow(rustc::usage_of_ty_tykind)]
+
 pub use self::fold::{FallibleTypeFolder, TypeFoldable, TypeFolder, TypeSuperFoldable};
 pub use self::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor};
 pub use self::AssocItemContainer::*;
@@ -32,7 +34,7 @@ use rustc_ast::node_id::NodeMap;
 use rustc_attr as attr;
 use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet};
-use rustc_data_structures::intern::{Interned, WithStableHash};
+use rustc_data_structures::intern::Interned;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_data_structures::tagged_ptr::CopyTaggedPtr;
 use rustc_hir as hir;
@@ -50,6 +52,7 @@ use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::{ExpnId, Span};
 use rustc_target::abi::{Align, Integer, IntegerType, VariantIdx};
 pub use rustc_target::abi::{ReprFlags, ReprOptions};
+use rustc_type_ir::WithCachedTypeInfo;
 pub use subst::*;
 pub use vtable::*;
 
@@ -82,8 +85,8 @@ pub use self::consts::{
 pub use self::context::{
     tls, CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations,
     CtxtInterners, DeducedParamAttrs, FreeRegionInfo, GeneratorDiagnosticData,
-    GeneratorInteriorTypeCause, GlobalCtxt, Lift, OnDiskCache, TyCtxt, TypeckResults, UserType,
-    UserTypeAnnotationIndex,
+    GeneratorInteriorTypeCause, GlobalCtxt, Lift, OnDiskCache, TyCtxt, TyCtxtFeed, TypeckResults,
+    UserType, UserTypeAnnotationIndex,
 };
 pub use self::instance::{Instance, InstanceDef, ShortInstance};
 pub use self::list::List;
@@ -445,86 +448,22 @@ pub struct CReaderCacheKey {
     pub pos: usize,
 }
 
-/// Represents a type.
-///
-/// IMPORTANT:
-/// - This is a very "dumb" struct (with no derives and no `impls`).
-/// - Values of this type are always interned and thus unique, and are stored
-///   as an `Interned<TyS>`.
-/// - `Ty` (which contains a reference to a `Interned<TyS>`) or `Interned<TyS>`
-///   should be used everywhere instead of `TyS`. In particular, `Ty` has most
-///   of the relevant methods.
-#[derive(PartialEq, Eq, PartialOrd, Ord)]
-#[allow(rustc::usage_of_ty_tykind)]
-pub(crate) struct TyS<'tcx> {
-    /// This field shouldn't be used directly and may be removed in the future.
-    /// Use `Ty::kind()` instead.
-    kind: TyKind<'tcx>,
-
-    /// This field provides fast access to information that is also contained
-    /// in `kind`.
-    ///
-    /// This field shouldn't be used directly and may be removed in the future.
-    /// Use `Ty::flags()` instead.
-    flags: TypeFlags,
-
-    /// This field provides fast access to information that is also contained
-    /// in `kind`.
-    ///
-    /// This is a kind of confusing thing: it stores the smallest
-    /// binder such that
-    ///
-    /// (a) the binder itself captures nothing but
-    /// (b) all the late-bound things within the type are captured
-    ///     by some sub-binder.
-    ///
-    /// So, for a type without any late-bound things, like `u32`, this
-    /// will be *innermost*, because that is the innermost binder that
-    /// captures nothing. But for a type `&'D u32`, where `'D` is a
-    /// late-bound region with De Bruijn index `D`, this would be `D + 1`
-    /// -- the binder itself does not capture `D`, but `D` is captured
-    /// by an inner binder.
-    ///
-    /// We call this concept an "exclusive" binder `D` because all
-    /// De Bruijn indices within the type are contained within `0..D`
-    /// (exclusive).
-    outer_exclusive_binder: ty::DebruijnIndex,
-}
-
-/// Use this rather than `TyS`, whenever possible.
+/// Use this rather than `TyKind`, whenever possible.
 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, HashStable)]
 #[rustc_diagnostic_item = "Ty"]
 #[rustc_pass_by_value]
-pub struct Ty<'tcx>(Interned<'tcx, WithStableHash<TyS<'tcx>>>);
+pub struct Ty<'tcx>(Interned<'tcx, WithCachedTypeInfo<TyKind<'tcx>>>);
 
 impl<'tcx> TyCtxt<'tcx> {
     /// A "bool" type used in rustc_mir_transform unit tests when we
     /// have not spun up a TyCtxt.
-    pub const BOOL_TY_FOR_UNIT_TESTING: Ty<'tcx> = Ty(Interned::new_unchecked(&WithStableHash {
-        internee: TyS {
-            kind: ty::Bool,
+    pub const BOOL_TY_FOR_UNIT_TESTING: Ty<'tcx> =
+        Ty(Interned::new_unchecked(&WithCachedTypeInfo {
+            internee: ty::Bool,
+            stable_hash: Fingerprint::ZERO,
             flags: TypeFlags::empty(),
             outer_exclusive_binder: DebruijnIndex::from_usize(0),
-        },
-        stable_hash: Fingerprint::ZERO,
-    }));
-}
-
-impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for TyS<'tcx> {
-    #[inline]
-    fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
-        let TyS {
-            kind,
-
-            // The other fields just provide fast access to information that is
-            // also contained in `kind`, so no need to hash them.
-            flags: _,
-
-            outer_exclusive_binder: _,
-        } = self;
-
-        kind.hash_stable(hcx, hasher)
-    }
+        }));
 }
 
 impl ty::EarlyBoundRegion {
@@ -535,28 +474,18 @@ impl ty::EarlyBoundRegion {
     }
 }
 
-/// Represents a predicate.
-///
-/// See comments on `TyS`, which apply here too (albeit for
-/// `PredicateS`/`Predicate` rather than `TyS`/`Ty`).
-#[derive(Debug)]
-pub(crate) struct PredicateS<'tcx> {
-    kind: Binder<'tcx, PredicateKind<'tcx>>,
-    flags: TypeFlags,
-    /// See the comment for the corresponding field of [TyS].
-    outer_exclusive_binder: ty::DebruijnIndex,
-}
-
-/// Use this rather than `PredicateS`, whenever possible.
+/// Use this rather than `PredicateKind`, whenever possible.
 #[derive(Clone, Copy, PartialEq, Eq, Hash, HashStable)]
 #[rustc_pass_by_value]
-pub struct Predicate<'tcx>(Interned<'tcx, WithStableHash<PredicateS<'tcx>>>);
+pub struct Predicate<'tcx>(
+    Interned<'tcx, WithCachedTypeInfo<ty::Binder<'tcx, PredicateKind<'tcx>>>>,
+);
 
 impl<'tcx> Predicate<'tcx> {
     /// Gets the inner `Binder<'tcx, PredicateKind<'tcx>>`.
     #[inline]
     pub fn kind(self) -> Binder<'tcx, PredicateKind<'tcx>> {
-        self.0.kind
+        self.0.internee
     }
 
     #[inline(always)]
@@ -631,21 +560,6 @@ impl<'tcx> Predicate<'tcx> {
     }
 }
 
-impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for PredicateS<'tcx> {
-    fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
-        let PredicateS {
-            ref kind,
-
-            // The other fields just provide fast access to information that is
-            // also contained in `kind`, so no need to hash them.
-            flags: _,
-            outer_exclusive_binder: _,
-        } = self;
-
-        kind.hash_stable(hcx, hasher);
-    }
-}
-
 impl rustc_errors::IntoDiagnosticArg for Predicate<'_> {
     fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> {
         rustc_errors::DiagnosticArgValue::Str(std::borrow::Cow::Owned(self.to_string()))
@@ -1028,7 +942,7 @@ impl<'tcx> Term<'tcx> {
         unsafe {
             match ptr & TAG_MASK {
                 TYPE_TAG => TermKind::Ty(Ty(Interned::new_unchecked(
-                    &*((ptr & !TAG_MASK) as *const WithStableHash<ty::TyS<'tcx>>),
+                    &*((ptr & !TAG_MASK) as *const WithCachedTypeInfo<ty::TyKind<'tcx>>),
                 ))),
                 CONST_TAG => TermKind::Const(ty::Const(Interned::new_unchecked(
                     &*((ptr & !TAG_MASK) as *const ty::ConstS<'tcx>),
@@ -1072,7 +986,7 @@ impl<'tcx> TermKind<'tcx> {
             TermKind::Ty(ty) => {
                 // Ensure we can use the tag bits.
                 assert_eq!(mem::align_of_val(&*ty.0.0) & TAG_MASK, 0);
-                (TYPE_TAG, ty.0.0 as *const WithStableHash<ty::TyS<'tcx>> as usize)
+                (TYPE_TAG, ty.0.0 as *const WithCachedTypeInfo<ty::TyKind<'tcx>> as usize)
             }
             TermKind::Const(ct) => {
                 // Ensure we can use the tag bits.
@@ -1150,8 +1064,8 @@ impl<'tcx> ToPolyTraitRef<'tcx> for PolyTraitPredicate<'tcx> {
     }
 }
 
-pub trait ToPredicate<'tcx, Predicate> {
-    fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate;
+pub trait ToPredicate<'tcx, P = Predicate<'tcx>> {
+    fn to_predicate(self, tcx: TyCtxt<'tcx>) -> P;
 }
 
 impl<'tcx, T> ToPredicate<'tcx, T> for T {
@@ -1160,21 +1074,21 @@ impl<'tcx, T> ToPredicate<'tcx, T> for T {
     }
 }
 
-impl<'tcx> ToPredicate<'tcx, Predicate<'tcx>> for Binder<'tcx, PredicateKind<'tcx>> {
+impl<'tcx> ToPredicate<'tcx> for Binder<'tcx, PredicateKind<'tcx>> {
     #[inline(always)]
     fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
         tcx.mk_predicate(self)
     }
 }
 
-impl<'tcx> ToPredicate<'tcx, Predicate<'tcx>> for Clause<'tcx> {
+impl<'tcx> ToPredicate<'tcx> for Clause<'tcx> {
     #[inline(always)]
     fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
         tcx.mk_predicate(ty::Binder::dummy(ty::PredicateKind::Clause(self)))
     }
 }
 
-impl<'tcx> ToPredicate<'tcx, Predicate<'tcx>> for Binder<'tcx, TraitRef<'tcx>> {
+impl<'tcx> ToPredicate<'tcx> for Binder<'tcx, TraitRef<'tcx>> {
     #[inline(always)]
     fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
         let pred: PolyTraitPredicate<'tcx> = self.to_predicate(tcx);
@@ -1193,25 +1107,25 @@ impl<'tcx> ToPredicate<'tcx, PolyTraitPredicate<'tcx>> for Binder<'tcx, TraitRef
     }
 }
 
-impl<'tcx> ToPredicate<'tcx, Predicate<'tcx>> for PolyTraitPredicate<'tcx> {
+impl<'tcx> ToPredicate<'tcx> for PolyTraitPredicate<'tcx> {
     fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
         self.map_bound(|p| PredicateKind::Clause(Clause::Trait(p))).to_predicate(tcx)
     }
 }
 
-impl<'tcx> ToPredicate<'tcx, Predicate<'tcx>> for PolyRegionOutlivesPredicate<'tcx> {
+impl<'tcx> ToPredicate<'tcx> for PolyRegionOutlivesPredicate<'tcx> {
     fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
         self.map_bound(|p| PredicateKind::Clause(Clause::RegionOutlives(p))).to_predicate(tcx)
     }
 }
 
-impl<'tcx> ToPredicate<'tcx, Predicate<'tcx>> for PolyTypeOutlivesPredicate<'tcx> {
+impl<'tcx> ToPredicate<'tcx> for PolyTypeOutlivesPredicate<'tcx> {
     fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
         self.map_bound(|p| PredicateKind::Clause(Clause::TypeOutlives(p))).to_predicate(tcx)
     }
 }
 
-impl<'tcx> ToPredicate<'tcx, Predicate<'tcx>> for PolyProjectionPredicate<'tcx> {
+impl<'tcx> ToPredicate<'tcx> for PolyProjectionPredicate<'tcx> {
     fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
         self.map_bound(|p| PredicateKind::Clause(Clause::Projection(p))).to_predicate(tcx)
     }
@@ -2228,10 +2142,6 @@ impl<'tcx> TyCtxt<'tcx> {
         }
     }
 
-    pub fn field_index(self, hir_id: hir::HirId, typeck_results: &TypeckResults<'_>) -> usize {
-        typeck_results.field_indices().get(hir_id).cloned().expect("no index for a field")
-    }
-
     pub fn find_field_index(self, ident: Ident, variant: &VariantDef) -> Option<usize> {
         variant
             .fields
@@ -2692,8 +2602,7 @@ mod size_asserts {
     use super::*;
     use rustc_data_structures::static_assert_size;
     // tidy-alphabetical-start
-    static_assert_size!(PredicateS<'_>, 48);
-    static_assert_size!(TyS<'_>, 40);
-    static_assert_size!(WithStableHash<TyS<'_>>, 56);
+    static_assert_size!(PredicateKind<'_>, 32);
+    static_assert_size!(WithCachedTypeInfo<TyKind<'_>>, 56);
     // tidy-alphabetical-end
 }
diff --git a/compiler/rustc_middle/src/ty/query.rs b/compiler/rustc_middle/src/ty/query.rs
index a7fd1754960..642900d3ab4 100644
--- a/compiler/rustc_middle/src/ty/query.rs
+++ b/compiler/rustc_middle/src/ty/query.rs
@@ -328,13 +328,25 @@ macro_rules! define_callbacks {
     };
 }
 
+macro_rules! hash_result {
+    ([]) => {{
+        Some(dep_graph::hash_result)
+    }};
+    ([(no_hash) $($rest:tt)*]) => {{
+        None
+    }};
+    ([$other:tt $($modifiers:tt)*]) => {
+        hash_result!([$($modifiers)*])
+    };
+}
+
 macro_rules! define_feedable {
     ($($(#[$attr:meta])* [$($modifiers:tt)*] fn $name:ident($($K:tt)*) -> $V:ty,)*) => {
-        impl<'tcx> TyCtxtFeed<'tcx> {
-            $($(#[$attr])*
+        $(impl<'tcx, K: IntoQueryParam<$($K)*> + Copy> TyCtxtFeed<'tcx, K> {
+            $(#[$attr])*
             #[inline(always)]
             pub fn $name(self, value: $V) -> query_stored::$name<'tcx> {
-                let key = self.def_id().into_query_param();
+                let key = self.key().into_query_param();
                 opt_remap_env_constness!([$($modifiers)*][key]);
 
                 let tcx = self.tcx;
@@ -358,11 +370,11 @@ macro_rules! define_feedable {
                     tcx,
                     key,
                     &value,
-                    dep_graph::hash_result,
+                    hash_result!([$($modifiers)*]),
                 );
                 cache.complete(key, value, dep_node_index)
-            })*
-        }
+            }
+        })*
     }
 }
 
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index 5984686044b..9cbda95a4df 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -722,8 +722,17 @@ impl<'tcx> PolyExistentialPredicate<'tcx> {
                 self.rebind(p.with_self_ty(tcx, self_ty)).to_predicate(tcx)
             }
             ExistentialPredicate::AutoTrait(did) => {
-                let trait_ref = self.rebind(tcx.mk_trait_ref(did, [self_ty]));
-                trait_ref.without_const().to_predicate(tcx)
+                let generics = tcx.generics_of(did);
+                let trait_ref = if generics.params.len() == 1 {
+                    tcx.mk_trait_ref(did, [self_ty])
+                } else {
+                    // If this is an ill-formed auto trait, then synthesize
+                    // new error substs for the missing generics.
+                    let err_substs =
+                        ty::InternalSubsts::extend_with_error(tcx, did, &[self_ty.into()]);
+                    tcx.mk_trait_ref(did, err_substs)
+                };
+                self.rebind(trait_ref).without_const().to_predicate(tcx)
             }
         }
     }
@@ -1602,7 +1611,7 @@ impl<'tcx> Region<'tcx> {
 impl<'tcx> Ty<'tcx> {
     #[inline(always)]
     pub fn kind(self) -> &'tcx TyKind<'tcx> {
-        &self.0.0.kind
+        &self.0.0
     }
 
     #[inline(always)]
diff --git a/compiler/rustc_middle/src/ty/subst.rs b/compiler/rustc_middle/src/ty/subst.rs
index 141c8354c18..a1b084a5e89 100644
--- a/compiler/rustc_middle/src/ty/subst.rs
+++ b/compiler/rustc_middle/src/ty/subst.rs
@@ -6,10 +6,11 @@ use crate::ty::sty::{ClosureSubsts, GeneratorSubsts, InlineConstSubsts};
 use crate::ty::visit::{TypeVisitable, TypeVisitor};
 use crate::ty::{self, Lift, List, ParamConst, Ty, TyCtxt};
 
-use rustc_data_structures::intern::{Interned, WithStableHash};
+use rustc_data_structures::intern::Interned;
 use rustc_hir::def_id::DefId;
 use rustc_macros::HashStable;
 use rustc_serialize::{self, Decodable, Encodable};
+use rustc_type_ir::WithCachedTypeInfo;
 use smallvec::SmallVec;
 
 use core::intrinsics;
@@ -84,7 +85,7 @@ impl<'tcx> GenericArgKind<'tcx> {
             GenericArgKind::Type(ty) => {
                 // Ensure we can use the tag bits.
                 assert_eq!(mem::align_of_val(&*ty.0.0) & TAG_MASK, 0);
-                (TYPE_TAG, ty.0.0 as *const WithStableHash<ty::TyS<'tcx>> as usize)
+                (TYPE_TAG, ty.0.0 as *const WithCachedTypeInfo<ty::TyKind<'tcx>> as usize)
             }
             GenericArgKind::Const(ct) => {
                 // Ensure we can use the tag bits.
@@ -162,7 +163,7 @@ impl<'tcx> GenericArg<'tcx> {
                     &*((ptr & !TAG_MASK) as *const ty::RegionKind<'tcx>),
                 ))),
                 TYPE_TAG => GenericArgKind::Type(Ty(Interned::new_unchecked(
-                    &*((ptr & !TAG_MASK) as *const WithStableHash<ty::TyS<'tcx>>),
+                    &*((ptr & !TAG_MASK) as *const WithCachedTypeInfo<ty::TyKind<'tcx>>),
                 ))),
                 CONST_TAG => GenericArgKind::Const(ty::Const(Interned::new_unchecked(
                     &*((ptr & !TAG_MASK) as *const ty::ConstS<'tcx>),
@@ -352,6 +353,22 @@ impl<'tcx> InternalSubsts<'tcx> {
         }
     }
 
+    // Extend an `original_substs` list to the full number of substs expected by `def_id`,
+    // filling in the missing parameters with error ty/ct or 'static regions.
+    pub fn extend_with_error(
+        tcx: TyCtxt<'tcx>,
+        def_id: DefId,
+        original_substs: &[GenericArg<'tcx>],
+    ) -> SubstsRef<'tcx> {
+        ty::InternalSubsts::for_item(tcx, def_id, |def, substs| {
+            if let Some(subst) = original_substs.get(def.index as usize) {
+                *subst
+            } else {
+                def.to_error(tcx, substs)
+            }
+        })
+    }
+
     #[inline]
     pub fn types(&'tcx self) -> impl DoubleEndedIterator<Item = Ty<'tcx>> + 'tcx {
         self.iter()
diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs
index b456e2aa37a..007f3b55ec8 100644
--- a/compiler/rustc_mir_build/src/build/mod.rs
+++ b/compiler/rustc_mir_build/src/build/mod.rs
@@ -948,20 +948,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         original_source_scope: SourceScope,
         pattern_span: Span,
     ) {
-        let tcx = self.tcx;
-        let current_root = tcx.maybe_lint_level_root_bounded(arg_hir_id, self.hir_id);
-        let parent_root = tcx.maybe_lint_level_root_bounded(
-            self.source_scopes[original_source_scope]
-                .local_data
-                .as_ref()
-                .assert_crate_local()
-                .lint_root,
-            self.hir_id,
-        );
-        if current_root != parent_root {
-            self.source_scope =
-                self.new_source_scope(pattern_span, LintLevel::Explicit(current_root), None);
-        }
+        let parent_id = self.source_scopes[original_source_scope]
+            .local_data
+            .as_ref()
+            .assert_crate_local()
+            .lint_root;
+        self.maybe_new_source_scope(pattern_span, None, arg_hir_id, parent_id);
     }
 
     fn get_unit_temp(&mut self) -> Place<'tcx> {
diff --git a/compiler/rustc_mir_build/src/build/scope.rs b/compiler/rustc_mir_build/src/build/scope.rs
index 5ddae5f5300..33f49ffdaf6 100644
--- a/compiler/rustc_mir_build/src/build/scope.rs
+++ b/compiler/rustc_mir_build/src/build/scope.rs
@@ -85,6 +85,7 @@ use std::mem;
 
 use crate::build::{BlockAnd, BlockAndExtension, BlockFrame, Builder, CFG};
 use rustc_data_structures::fx::FxHashMap;
+use rustc_hir::HirId;
 use rustc_index::vec::IndexVec;
 use rustc_middle::middle::region;
 use rustc_middle::mir::*;
@@ -567,25 +568,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         F: FnOnce(&mut Builder<'a, 'tcx>) -> BlockAnd<R>,
     {
         let source_scope = self.source_scope;
-        let tcx = self.tcx;
         if let LintLevel::Explicit(current_hir_id) = lint_level {
-            // Use `maybe_lint_level_root_bounded` with `root_lint_level` as a bound
-            // to avoid adding Hir dependencies on our parents.
-            // We estimate the true lint roots here to avoid creating a lot of source scopes.
-
-            let parent_root = tcx.maybe_lint_level_root_bounded(
-                self.source_scopes[source_scope].local_data.as_ref().assert_crate_local().lint_root,
-                self.hir_id,
-            );
-            let current_root = tcx.maybe_lint_level_root_bounded(current_hir_id, self.hir_id);
-
-            if parent_root != current_root {
-                self.source_scope = self.new_source_scope(
-                    region_scope.1.span,
-                    LintLevel::Explicit(current_root),
-                    None,
-                );
-            }
+            let parent_id =
+                self.source_scopes[source_scope].local_data.as_ref().assert_crate_local().lint_root;
+            self.maybe_new_source_scope(region_scope.1.span, None, current_hir_id, parent_id);
         }
         self.push_scope(region_scope);
         let mut block;
@@ -758,6 +744,40 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         ))
     }
 
+    /// Possibly creates a new source scope if `current_root` and `parent_root`
+    /// are different, or if -Zmaximal-hir-to-mir-coverage is enabled.
+    pub(crate) fn maybe_new_source_scope(
+        &mut self,
+        span: Span,
+        safety: Option<Safety>,
+        current_id: HirId,
+        parent_id: HirId,
+    ) {
+        let (current_root, parent_root) =
+            if self.tcx.sess.opts.unstable_opts.maximal_hir_to_mir_coverage {
+                // Some consumers of rustc need to map MIR locations back to HIR nodes. Currently the
+                // the only part of rustc that tracks MIR -> HIR is the `SourceScopeLocalData::lint_root`
+                // field that tracks lint levels for MIR locations.  Normally the number of source scopes
+                // is limited to the set of nodes with lint annotations. The -Zmaximal-hir-to-mir-coverage
+                // flag changes this behavior to maximize the number of source scopes, increasing the
+                // granularity of the MIR->HIR mapping.
+                (current_id, parent_id)
+            } else {
+                // Use `maybe_lint_level_root_bounded` with `self.hir_id` as a bound
+                // to avoid adding Hir dependencies on our parents.
+                // We estimate the true lint roots here to avoid creating a lot of source scopes.
+                (
+                    self.tcx.maybe_lint_level_root_bounded(current_id, self.hir_id),
+                    self.tcx.maybe_lint_level_root_bounded(parent_id, self.hir_id),
+                )
+            };
+
+        if current_root != parent_root {
+            let lint_level = LintLevel::Explicit(current_root);
+            self.source_scope = self.new_source_scope(span, lint_level, safety);
+        }
+    }
+
     /// Creates a new source scope, nested in the current one.
     pub(crate) fn new_source_scope(
         &mut self,
diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs
index 5fa41ebeb6e..261b95ba95b 100644
--- a/compiler/rustc_mir_build/src/thir/cx/expr.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs
@@ -704,7 +704,7 @@ impl<'tcx> Cx<'tcx> {
             hir::ExprKind::Field(ref source, ..) => ExprKind::Field {
                 lhs: self.mirror_expr(source),
                 variant_index: VariantIdx::new(0),
-                name: Field::new(tcx.field_index(expr.hir_id, self.typeck_results)),
+                name: Field::new(self.typeck_results.field_index(expr.hir_id)),
             },
             hir::ExprKind::Cast(ref source, ref cast_ty) => {
                 // Check for a user-given type annotation on this `cast`
@@ -1079,7 +1079,7 @@ impl<'tcx> Cx<'tcx> {
         fields
             .iter()
             .map(|field| FieldExpr {
-                name: Field::new(self.tcx.field_index(field.hir_id, self.typeck_results)),
+                name: Field::new(self.typeck_results.field_index(field.hir_id)),
                 expr: self.mirror_expr(field.expr),
             })
             .collect()
diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
index 4c2a80e523f..48a231a6cd6 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
@@ -321,7 +321,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
                 let subpatterns = fields
                     .iter()
                     .map(|field| FieldPat {
-                        field: Field::new(self.tcx.field_index(field.hir_id, self.typeck_results)),
+                        field: Field::new(self.typeck_results.field_index(field.hir_id)),
                         pattern: self.lower_pattern(&field.pat),
                     })
                     .collect();
diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs
index cc69a1bb02d..7df01142264 100644
--- a/compiler/rustc_mir_dataflow/src/value_analysis.rs
+++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs
@@ -406,7 +406,7 @@ impl<V: Clone> Clone for StateData<V> {
 /// The dataflow state for an instance of [`ValueAnalysis`].
 ///
 /// Every instance specifies a lattice that represents the possible values of a single tracked
-/// place. If we call this lattice `V` and set set of tracked places `P`, then a [`State`] is an
+/// place. If we call this lattice `V` and set of tracked places `P`, then a [`State`] is an
 /// element of `{unreachable} ∪ (P -> V)`. This again forms a lattice, where the bottom element is
 /// `unreachable` and the top element is the mapping `p ↦ ⊤`. Note that the mapping `p ↦ ⊥` is not
 /// the bottom element (because joining an unreachable and any other reachable state yields a
diff --git a/compiler/rustc_mir_transform/src/add_retag.rs b/compiler/rustc_mir_transform/src/add_retag.rs
index 036b5589849..3d22035f078 100644
--- a/compiler/rustc_mir_transform/src/add_retag.rs
+++ b/compiler/rustc_mir_transform/src/add_retag.rs
@@ -10,16 +10,6 @@ use rustc_middle::ty::{self, Ty, TyCtxt};
 
 pub struct AddRetag;
 
-/// Determines whether this place is "stable": Whether, if we evaluate it again
-/// after the assignment, we can be sure to obtain the same place value.
-/// (Concurrent accesses by other threads are no problem as these are anyway non-atomic
-/// copies.  Data races are UB.)
-fn is_stable(place: PlaceRef<'_>) -> bool {
-    // Which place this evaluates to can change with any memory write,
-    // so cannot assume deref to be stable.
-    !place.has_deref()
-}
-
 /// Determine whether this type may contain a reference (or box), and thus needs retagging.
 /// We will only recurse `depth` times into Tuples/ADTs to bound the cost of this.
 fn may_contain_reference<'tcx>(ty: Ty<'tcx>, depth: u32, tcx: TyCtxt<'tcx>) -> bool {
@@ -69,22 +59,10 @@ 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>| {
-            // FIXME: Instead of giving up for unstable places, we should introduce
-            // a temporary and retag on that.
-            is_stable(place.as_ref())
+            !place.has_deref() // we're not eally 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()
         };
-        let place_base_raw = |place: &Place<'tcx>| {
-            // If this is a `Deref`, get the type of what we are deref'ing.
-            if place.has_deref() {
-                let ty = &local_decls[place.local].ty;
-                ty.is_unsafe_ptr()
-            } else {
-                // Not a deref, and thus not raw.
-                false
-            }
-        };
 
         // PART 1
         // Retag arguments at the beginning of the start block.
@@ -108,7 +86,7 @@ impl<'tcx> MirPass<'tcx> for AddRetag {
         }
 
         // PART 2
-        // Retag return values of functions.  Also escape-to-raw the argument of `drop`.
+        // Retag return values of functions.
         // We collect the return destinations because we cannot mutate while iterating.
         let returns = basic_blocks
             .iter_mut()
@@ -140,30 +118,25 @@ impl<'tcx> MirPass<'tcx> for AddRetag {
         }
 
         // PART 3
-        // Add retag after assignment.
+        // Add retag after assignments where data "enters" this function: the RHS is behind a deref and the LHS is not.
         for block_data in basic_blocks {
             // We want to insert statements as we iterate.  To this end, we
             // iterate backwards using indices.
             for i in (0..block_data.statements.len()).rev() {
                 let (retag_kind, place) = match block_data.statements[i].kind {
-                    // Retag-as-raw after escaping to a raw pointer, if the referent
-                    // is not already a raw pointer.
-                    StatementKind::Assign(box (lplace, Rvalue::AddressOf(_, ref rplace)))
-                        if !place_base_raw(rplace) =>
-                    {
-                        (RetagKind::Raw, lplace)
-                    }
                     // Retag after assignments of reference type.
                     StatementKind::Assign(box (ref place, ref rvalue)) if needs_retag(place) => {
-                        let kind = match rvalue {
-                            Rvalue::Ref(_, borrow_kind, _)
-                                if borrow_kind.allows_two_phase_borrow() =>
-                            {
-                                RetagKind::TwoPhase
-                            }
-                            _ => RetagKind::Default,
+                        let add_retag = match rvalue {
+                            // Ptr-creating operations already do their own internal retagging, no
+                            // need to also add a retag statement.
+                            Rvalue::Ref(..) | Rvalue::AddressOf(..) => false,
+                            _ => true,
                         };
-                        (kind, *place)
+                        if add_retag {
+                            (RetagKind::Default, *place)
+                        } else {
+                            continue;
+                        }
                     }
                     // Do nothing for the rest
                     _ => continue,
diff --git a/compiler/rustc_mir_transform/src/dump_mir.rs b/compiler/rustc_mir_transform/src/dump_mir.rs
index 778ae63c5a4..594cbd8977e 100644
--- a/compiler/rustc_mir_transform/src/dump_mir.rs
+++ b/compiler/rustc_mir_transform/src/dump_mir.rs
@@ -7,7 +7,7 @@ use crate::MirPass;
 use rustc_middle::mir::write_mir_pretty;
 use rustc_middle::mir::Body;
 use rustc_middle::ty::TyCtxt;
-use rustc_session::config::{OutputFilenames, OutputType};
+use rustc_session::config::OutputType;
 
 pub struct Marker(pub &'static str);
 
@@ -19,8 +19,8 @@ impl<'tcx> MirPass<'tcx> for Marker {
     fn run_pass(&self, _tcx: TyCtxt<'tcx>, _body: &mut Body<'tcx>) {}
 }
 
-pub fn emit_mir(tcx: TyCtxt<'_>, outputs: &OutputFilenames) -> io::Result<()> {
-    let path = outputs.path(OutputType::Mir);
+pub fn emit_mir(tcx: TyCtxt<'_>) -> io::Result<()> {
+    let path = tcx.output_filenames(()).path(OutputType::Mir);
     let mut f = io::BufWriter::new(File::create(&path)?);
     write_mir_pretty(tcx, None, &mut f)?;
     Ok(())
diff --git a/compiler/rustc_mir_transform/src/generator.rs b/compiler/rustc_mir_transform/src/generator.rs
index 8922298ecaf..69f96fe48ea 100644
--- a/compiler/rustc_mir_transform/src/generator.rs
+++ b/compiler/rustc_mir_transform/src/generator.rs
@@ -985,16 +985,6 @@ fn create_generator_drop_shim<'tcx>(
         tcx.mk_ptr(ty::TypeAndMut { ty: gen_ty, mutbl: hir::Mutability::Mut }),
         source_info,
     );
-    if tcx.sess.opts.unstable_opts.mir_emit_retag {
-        // Alias tracking must know we changed the type
-        body.basic_blocks_mut()[START_BLOCK].statements.insert(
-            0,
-            Statement {
-                source_info,
-                kind: StatementKind::Retag(RetagKind::Raw, Box::new(Place::from(SELF_ARG))),
-            },
-        )
-    }
 
     // Make sure we remove dead blocks to remove
     // unrelated code from the resume part of the function
diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs
index bf670c5c26a..220cf7df9c6 100644
--- a/compiler/rustc_mir_transform/src/inline.rs
+++ b/compiler/rustc_mir_transform/src/inline.rs
@@ -8,7 +8,6 @@ use rustc_middle::mir::visit::*;
 use rustc_middle::mir::*;
 use rustc_middle::ty::{self, Instance, InstanceDef, ParamEnv, Ty, TyCtxt};
 use rustc_session::config::OptLevel;
-use rustc_span::def_id::DefId;
 use rustc_span::{hygiene::ExpnKind, ExpnData, LocalExpnId, Span};
 use rustc_target::abi::VariantIdx;
 use rustc_target::spec::abi::Abi;
@@ -87,13 +86,8 @@ fn inline<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) -> bool {
 
     let param_env = tcx.param_env_reveal_all_normalized(def_id);
 
-    let mut this = Inliner {
-        tcx,
-        param_env,
-        codegen_fn_attrs: tcx.codegen_fn_attrs(def_id),
-        history: Vec::new(),
-        changed: false,
-    };
+    let mut this =
+        Inliner { tcx, param_env, codegen_fn_attrs: tcx.codegen_fn_attrs(def_id), changed: false };
     let blocks = BasicBlock::new(0)..body.basic_blocks.next_index();
     this.process_blocks(body, blocks);
     this.changed
@@ -104,12 +98,6 @@ struct Inliner<'tcx> {
     param_env: ParamEnv<'tcx>,
     /// Caller codegen attributes.
     codegen_fn_attrs: &'tcx CodegenFnAttrs,
-    /// Stack of inlined instances.
-    /// We only check the `DefId` and not the substs because we want to
-    /// avoid inlining cases of polymorphic recursion.
-    /// The number of `DefId`s is finite, so checking history is enough
-    /// to ensure that we do not loop endlessly while inlining.
-    history: Vec<DefId>,
     /// Indicates that the caller body has been modified.
     changed: bool,
 }
@@ -134,12 +122,12 @@ impl<'tcx> Inliner<'tcx> {
                     debug!("not-inlined {} [{}]", callsite.callee, reason);
                     continue;
                 }
-                Ok(new_blocks) => {
+                Ok(_) => {
                     debug!("inlined {}", callsite.callee);
                     self.changed = true;
-                    self.history.push(callsite.callee.def_id());
-                    self.process_blocks(caller_body, new_blocks);
-                    self.history.pop();
+                    // We could process the blocks returned by `try_inlining` here. However, that
+                    // leads to exponential compile times due to the top-down nature of this kind
+                    // of inlining.
                 }
             }
         }
@@ -313,10 +301,6 @@ impl<'tcx> Inliner<'tcx> {
                     return None;
                 }
 
-                if self.history.contains(&callee.def_id()) {
-                    return None;
-                }
-
                 let fn_sig = self.tcx.bound_fn_sig(def_id).subst(self.tcx, substs);
 
                 return Some(CallSite {
diff --git a/compiler/rustc_mir_transform/src/remove_zsts.rs b/compiler/rustc_mir_transform/src/remove_zsts.rs
index 40be4f146db..569e783fee8 100644
--- a/compiler/rustc_mir_transform/src/remove_zsts.rs
+++ b/compiler/rustc_mir_transform/src/remove_zsts.rs
@@ -1,8 +1,7 @@
 //! Removes assignments to ZST places.
 
 use crate::MirPass;
-use rustc_middle::mir::tcx::PlaceTy;
-use rustc_middle::mir::{Body, LocalDecls, Place, StatementKind};
+use rustc_middle::mir::{Body, StatementKind};
 use rustc_middle::ty::{self, Ty, TyCtxt};
 
 pub struct RemoveZsts;
@@ -35,9 +34,6 @@ impl<'tcx> MirPass<'tcx> for RemoveZsts {
                     if !layout.is_zst() {
                         continue;
                     }
-                    if involves_a_union(place, local_decls, tcx) {
-                        continue;
-                    }
                     if tcx.consider_optimizing(|| {
                         format!(
                             "RemoveZsts - Place: {:?} SourceInfo: {:?}",
@@ -63,24 +59,3 @@ fn maybe_zst(ty: Ty<'_>) -> bool {
         _ => false,
     }
 }
-
-/// Miri lazily allocates memory for locals on assignment,
-/// so we must preserve writes to unions and union fields,
-/// or it will ICE on reads of those fields.
-fn involves_a_union<'tcx>(
-    place: Place<'tcx>,
-    local_decls: &LocalDecls<'tcx>,
-    tcx: TyCtxt<'tcx>,
-) -> bool {
-    let mut place_ty = PlaceTy::from_ty(local_decls[place.local].ty);
-    if place_ty.ty.is_union() {
-        return true;
-    }
-    for elem in place.projection {
-        place_ty = place_ty.projection_ty(tcx, elem);
-        if place_ty.ty.is_union() {
-            return true;
-        }
-    }
-    return false;
-}
diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs
index a115bb2831a..16b7dcad17e 100644
--- a/compiler/rustc_mir_transform/src/shim.rs
+++ b/compiler/rustc_mir_transform/src/shim.rs
@@ -177,16 +177,6 @@ fn build_drop_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, ty: Option<Ty<'tcx>>)
     if ty.is_some() {
         // The first argument (index 0), but add 1 for the return value.
         let dropee_ptr = Place::from(Local::new(1 + 0));
-        if tcx.sess.opts.unstable_opts.mir_emit_retag {
-            // Function arguments should be retagged, and we make this one raw.
-            body.basic_blocks_mut()[START_BLOCK].statements.insert(
-                0,
-                Statement {
-                    source_info,
-                    kind: StatementKind::Retag(RetagKind::Raw, Box::new(dropee_ptr)),
-                },
-            );
-        }
         let patch = {
             let param_env = tcx.param_env_reveal_all_normalized(def_id);
             let mut elaborator =
diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs
index 9875cde4a05..18a0bee9c2e 100644
--- a/compiler/rustc_parse/src/errors.rs
+++ b/compiler/rustc_parse/src/errors.rs
@@ -1221,3 +1221,11 @@ pub(crate) struct UnexpectedIfWithIf(
     #[suggestion(applicability = "machine-applicable", code = " ", style = "verbose")]
     pub Span,
 );
+
+#[derive(Diagnostic)]
+#[diag(parse_maybe_fn_typo_with_impl)]
+pub(crate) struct FnTypoWithImpl {
+    #[primary_span]
+    #[suggestion(applicability = "maybe-incorrect", code = "impl", style = "verbose")]
+    pub fn_span: Span,
+}
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index fe3cfde2e63..f6a6ed379a2 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -390,20 +390,11 @@ impl<'a> Parser<'a> {
             // want to keep their span info to improve diagnostics in these cases in a later stage.
             (true, Some(AssocOp::Multiply)) | // `{ 42 } *foo = bar;` or `{ 42 } * 3`
             (true, Some(AssocOp::Subtract)) | // `{ 42 } -5`
-            (true, Some(AssocOp::Add)) // `{ 42 } + 42
-            // If the next token is a keyword, then the tokens above *are* unambiguously incorrect:
-            // `if x { a } else { b } && if y { c } else { d }`
-            if !self.look_ahead(1, |t| t.is_used_keyword()) => {
-                // These cases are ambiguous and can't be identified in the parser alone.
-                let sp = self.sess.source_map().start_point(self.token.span);
-                self.sess.ambiguous_block_expr_parse.borrow_mut().insert(sp, lhs.span);
-                false
-            }
-            (true, Some(AssocOp::LAnd)) |
-            (true, Some(AssocOp::LOr)) |
-            (true, Some(AssocOp::BitOr)) => {
-                // `{ 42 } &&x` (#61475) or `{ 42 } && if x { 1 } else { 0 }`. Separated from the
-                // above due to #74233.
+            (true, Some(AssocOp::Add)) | // `{ 42 } + 42` (unary plus)
+            (true, Some(AssocOp::LAnd)) | // `{ 42 } &&x` (#61475) or `{ 42 } && if x { 1 } else { 0 }`
+            (true, Some(AssocOp::LOr)) | // `{ 42 } || 42` ("logical or" or closure)
+            (true, Some(AssocOp::BitOr)) // `{ 42 } | 42` or `{ 42 } |x| 42`
+            => {
                 // These cases are ambiguous and can't be identified in the parser alone.
                 //
                 // Bitwise AND is left out because guessing intent is hard. We can make
diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs
index 84c63219920..ce4bc929c5c 100644
--- a/compiler/rustc_parse/src/parser/item.rs
+++ b/compiler/rustc_parse/src/parser/item.rs
@@ -3,6 +3,7 @@ use crate::errors::{DocCommentDoesNotDocumentAnything, UseEmptyBlockNotSemi};
 use super::diagnostics::{dummy_arg, ConsumeClosingDelim};
 use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign};
 use super::{AttrWrapper, FollowedByType, ForceCollect, Parser, PathStyle, TrailingToken};
+use crate::errors::FnTypoWithImpl;
 use rustc_ast::ast::*;
 use rustc_ast::ptr::P;
 use rustc_ast::token::{self, Delimiter, TokenKind};
@@ -1414,7 +1415,10 @@ impl<'a> Parser<'a> {
 
                 Ok((Some(vr), TrailingToken::MaybeComma))
             },
-        )
+        ).map_err(|mut err|{
+            err.help("enum variants can be `Variant`, `Variant = <integer>`, `Variant(Type, ..., TypeN)` or `Variant { fields: Types }`");
+            err
+        })
     }
 
     /// Parses `struct Foo { ... }`.
@@ -2123,11 +2127,26 @@ impl<'a> Parser<'a> {
         vis: &Visibility,
         case: Case,
     ) -> PResult<'a, (Ident, FnSig, Generics, Option<P<Block>>)> {
+        let fn_span = self.token.span;
         let header = self.parse_fn_front_matter(vis, case)?; // `const ... fn`
         let ident = self.parse_ident()?; // `foo`
         let mut generics = self.parse_generics()?; // `<'a, T, ...>`
-        let decl =
-            self.parse_fn_decl(fn_parse_mode.req_name, AllowPlus::Yes, RecoverReturnSign::Yes)?; // `(p: u8, ...)`
+        let decl = match self.parse_fn_decl(
+            fn_parse_mode.req_name,
+            AllowPlus::Yes,
+            RecoverReturnSign::Yes,
+        ) {
+            Ok(decl) => decl,
+            Err(old_err) => {
+                // If we see `for Ty ...` then user probably meant `impl` item.
+                if self.token.is_keyword(kw::For) {
+                    old_err.cancel();
+                    return Err(self.sess.create_err(FnTypoWithImpl { fn_span }));
+                } else {
+                    return Err(old_err);
+                }
+            }
+        };
         generics.where_clause = self.parse_where_clause()?; // `where T: Ord`
 
         let mut sig_hi = self.prev_token.span;
diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs
index 4d8bff28b05..bebb012660a 100644
--- a/compiler/rustc_parse/src/parser/mod.rs
+++ b/compiler/rustc_parse/src/parser/mod.rs
@@ -943,6 +943,10 @@ impl<'a> Parser<'a> {
                                 Err(e) => {
                                     // Parsing failed, therefore it must be something more serious
                                     // than just a missing separator.
+                                    for xx in &e.children {
+                                        // propagate the help message from sub error 'e' to main error 'expect_err;
+                                        expect_err.children.push(xx.clone());
+                                    }
                                     expect_err.emit();
 
                                     e.cancel();
diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs
index da023fcf4c3..a71ae717a50 100644
--- a/compiler/rustc_passes/src/dead.rs
+++ b/compiler/rustc_passes/src/dead.rs
@@ -124,7 +124,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
     fn handle_field_access(&mut self, lhs: &hir::Expr<'_>, hir_id: hir::HirId) {
         match self.typeck_results().expr_ty_adjusted(lhs).kind() {
             ty::Adt(def, _) => {
-                let index = self.tcx.field_index(hir_id, self.typeck_results());
+                let index = self.typeck_results().field_index(hir_id);
                 self.insert_def_id(def.non_enum_variant().fields[index].did);
             }
             ty::Tuple(..) => {}
@@ -208,7 +208,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
             if let PatKind::Wild = pat.pat.kind {
                 continue;
             }
-            let index = self.tcx.field_index(pat.hir_id, self.typeck_results());
+            let index = self.typeck_results().field_index(pat.hir_id);
             self.insert_def_id(variant.fields[index].did);
         }
     }
@@ -341,7 +341,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
     fn mark_as_used_if_union(&mut self, adt: ty::AdtDef<'tcx>, fields: &[hir::ExprField<'_>]) {
         if adt.is_union() && adt.non_enum_variant().fields.len() > 1 && adt.did().is_local() {
             for field in fields {
-                let index = self.tcx.field_index(field.hir_id, self.typeck_results());
+                let index = self.typeck_results().field_index(field.hir_id);
                 self.insert_def_id(adt.non_enum_variant().fields[index].did);
             }
         }
diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs
index 2234837050b..1f65cc8b609 100644
--- a/compiler/rustc_passes/src/liveness.rs
+++ b/compiler/rustc_passes/src/liveness.rs
@@ -1548,7 +1548,13 @@ impl<'tcx> Liveness<'_, 'tcx> {
                 .or_insert_with(|| (ln, var, vec![id_and_sp]));
         });
 
-        let can_remove = matches!(&pat.kind, hir::PatKind::Struct(_, _, true));
+        let can_remove = match pat.kind {
+            hir::PatKind::Struct(_, fields, true) => {
+                // if all fields are shorthand, remove the struct field, otherwise, mark with _ as prefix
+                fields.iter().all(|f| f.is_shorthand)
+            }
+            _ => false,
+        };
 
         for (_, (ln, var, hir_ids_and_spans)) in vars {
             if self.used_on_entry(ln, var) {
diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs
index f2177a7c283..a254c892478 100644
--- a/compiler/rustc_privacy/src/lib.rs
+++ b/compiler/rustc_privacy/src/lib.rs
@@ -1065,9 +1065,9 @@ impl<'tcx> Visitor<'tcx> for NamePrivacyVisitor<'tcx> {
                 // are checked for privacy (RFC 736). Rather than computing the set of
                 // unmentioned fields, just check them all.
                 for (vf_index, variant_field) in variant.fields.iter().enumerate() {
-                    let field = fields.iter().find(|f| {
-                        self.tcx.field_index(f.hir_id, self.typeck_results()) == vf_index
-                    });
+                    let field = fields
+                        .iter()
+                        .find(|f| self.typeck_results().field_index(f.hir_id) == vf_index);
                     let (use_ctxt, span) = match field {
                         Some(field) => (field.ident.span, field.span),
                         None => (base.span, base.span),
@@ -1077,7 +1077,7 @@ impl<'tcx> Visitor<'tcx> for NamePrivacyVisitor<'tcx> {
             } else {
                 for field in fields {
                     let use_ctxt = field.ident.span;
-                    let index = self.tcx.field_index(field.hir_id, self.typeck_results());
+                    let index = self.typeck_results().field_index(field.hir_id);
                     self.check_field(use_ctxt, field.span, adt, &variant.fields[index], false);
                 }
             }
@@ -1093,7 +1093,7 @@ impl<'tcx> Visitor<'tcx> for NamePrivacyVisitor<'tcx> {
             let variant = adt.variant_of_res(res);
             for field in fields {
                 let use_ctxt = field.ident.span;
-                let index = self.tcx.field_index(field.hir_id, self.typeck_results());
+                let index = self.typeck_results().field_index(field.hir_id);
                 self.check_field(use_ctxt, field.span, adt, &variant.fields[index], false);
             }
         }
diff --git a/compiler/rustc_query_system/src/dep_graph/graph.rs b/compiler/rustc_query_system/src/dep_graph/graph.rs
index 30d28ff3455..38c7c6cce67 100644
--- a/compiler/rustc_query_system/src/dep_graph/graph.rs
+++ b/compiler/rustc_query_system/src/dep_graph/graph.rs
@@ -510,7 +510,7 @@ impl<K: DepKind> DepGraph<K> {
         cx: Ctxt,
         key: A,
         result: &R,
-        hash_result: fn(&mut StableHashingContext<'_>, &R) -> Fingerprint,
+        hash_result: Option<fn(&mut StableHashingContext<'_>, &R) -> Fingerprint>,
     ) -> DepNodeIndex {
         if let Some(data) = self.data.as_ref() {
             // The caller query has more dependencies than the node we are creating.  We may
@@ -521,10 +521,12 @@ impl<K: DepKind> DepGraph<K> {
             // For sanity, we still check that the loaded stable hash and the new one match.
             if let Some(dep_node_index) = self.dep_node_index_of_opt(&node) {
                 let _current_fingerprint =
-                    crate::query::incremental_verify_ich(cx, result, &node, Some(hash_result));
+                    crate::query::incremental_verify_ich(cx, result, &node, hash_result);
 
                 #[cfg(debug_assertions)]
-                data.current.record_edge(dep_node_index, node, _current_fingerprint);
+                if hash_result.is_some() {
+                    data.current.record_edge(dep_node_index, node, _current_fingerprint);
+                }
 
                 return dep_node_index;
             }
@@ -539,8 +541,9 @@ impl<K: DepKind> DepGraph<K> {
             });
 
             let hashing_timer = cx.profiler().incr_result_hashing();
-            let current_fingerprint =
-                cx.with_stable_hashing_context(|mut hcx| hash_result(&mut hcx, result));
+            let current_fingerprint = hash_result.map(|hash_result| {
+                cx.with_stable_hashing_context(|mut hcx| hash_result(&mut hcx, result))
+            });
 
             let print_status = cfg!(debug_assertions) && cx.sess().opts.unstable_opts.dep_tasks;
 
@@ -550,7 +553,7 @@ impl<K: DepKind> DepGraph<K> {
                 &data.previous,
                 node,
                 edges,
-                Some(current_fingerprint),
+                current_fingerprint,
                 print_status,
             );
 
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index 51a53f7b37c..cf3e5946053 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -1927,7 +1927,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
                                 // We have a single lifetime => success.
                                 elision_lifetime = Elision::Param(res)
                             } else {
-                                // We have have multiple lifetimes => error.
+                                // We have multiple lifetimes => error.
                                 elision_lifetime = Elision::Err;
                             }
                         }
@@ -2360,8 +2360,8 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
                     if let GenericParamKind::Lifetime = param.kind {
                         // Record lifetime res, so lowering knows there is something fishy.
                         self.record_lifetime_param(param.id, LifetimeRes::Error);
-                        continue;
                     }
+                    continue;
                 }
                 Entry::Vacant(entry) => {
                     entry.insert(param.ident.span);
diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs
index 4ef89cfb255..82f5d0f534a 100644
--- a/compiler/rustc_resolve/src/lib.rs
+++ b/compiler/rustc_resolve/src/lib.rs
@@ -1196,7 +1196,7 @@ impl<'a> Resolver<'a> {
     pub fn new(
         session: &'a Session,
         krate: &Crate,
-        crate_name: &str,
+        crate_name: Symbol,
         metadata_loader: Box<MetadataLoaderDyn>,
         arenas: &'a ResolverArenas<'a>,
     ) -> Resolver<'a> {
diff --git a/compiler/rustc_save_analysis/src/dump_visitor.rs b/compiler/rustc_save_analysis/src/dump_visitor.rs
index b4528853825..9ae07cb005b 100644
--- a/compiler/rustc_save_analysis/src/dump_visitor.rs
+++ b/compiler/rustc_save_analysis/src/dump_visitor.rs
@@ -111,7 +111,7 @@ impl<'tcx> DumpVisitor<'tcx> {
         self.save_ctxt.lookup_def_id(ref_id)
     }
 
-    pub fn dump_crate_info(&mut self, name: &str) {
+    pub fn dump_crate_info(&mut self, name: Symbol) {
         let source_file = self.tcx.sess.local_crate_source_file.as_ref();
         let crate_root = source_file.map(|source_file| {
             let source_file = Path::new(source_file);
@@ -124,7 +124,7 @@ impl<'tcx> DumpVisitor<'tcx> {
 
         let data = CratePreludeData {
             crate_id: GlobalCrateId {
-                name: name.into(),
+                name: name.to_string(),
                 disambiguator: (self.tcx.sess.local_stable_crate_id().to_u64(), 0),
             },
             crate_root: crate_root.unwrap_or_else(|| "<no source>".to_owned()),
@@ -135,7 +135,7 @@ impl<'tcx> DumpVisitor<'tcx> {
         self.dumper.crate_prelude(data);
     }
 
-    pub fn dump_compilation_options(&mut self, input: &Input, crate_name: &str) {
+    pub fn dump_compilation_options(&mut self, input: &Input, crate_name: Symbol) {
         // Apply possible `remap-path-prefix` remapping to the input source file
         // (and don't include remapping args anymore)
         let (program, arguments) = {
diff --git a/compiler/rustc_save_analysis/src/lib.rs b/compiler/rustc_save_analysis/src/lib.rs
index f05eb2b7432..7735c571310 100644
--- a/compiler/rustc_save_analysis/src/lib.rs
+++ b/compiler/rustc_save_analysis/src/lib.rs
@@ -95,7 +95,7 @@ impl<'tcx> SaveContext<'tcx> {
     }
 
     /// Returns path to the compilation output (e.g., libfoo-12345678.rmeta)
-    pub fn compilation_output(&self, crate_name: &str) -> PathBuf {
+    pub fn compilation_output(&self, crate_name: Symbol) -> PathBuf {
         let sess = &self.tcx.sess;
         // Save-analysis is emitted per whole session, not per each crate type
         let crate_type = sess.crate_types()[0];
@@ -894,8 +894,8 @@ pub struct DumpHandler<'a> {
 }
 
 impl<'a> DumpHandler<'a> {
-    pub fn new(odir: Option<&'a Path>, cratename: &str) -> DumpHandler<'a> {
-        DumpHandler { odir, cratename: cratename.to_owned() }
+    pub fn new(odir: Option<&'a Path>, cratename: Symbol) -> DumpHandler<'a> {
+        DumpHandler { odir, cratename: cratename.to_string() }
     }
 
     fn output_file(&self, ctx: &SaveContext<'_>) -> (BufWriter<File>, PathBuf) {
@@ -960,7 +960,7 @@ impl SaveHandler for CallbackHandler<'_> {
 
 pub fn process_crate<'l, 'tcx, H: SaveHandler>(
     tcx: TyCtxt<'tcx>,
-    cratename: &str,
+    cratename: Symbol,
     input: &'l Input,
     config: Option<Config>,
     mut handler: H,
diff --git a/compiler/rustc_session/Cargo.toml b/compiler/rustc_session/Cargo.toml
index a052f293341..cbbba2252bf 100644
--- a/compiler/rustc_session/Cargo.toml
+++ b/compiler/rustc_session/Cargo.toml
@@ -18,6 +18,7 @@ rustc_fs_util = { path = "../rustc_fs_util" }
 rustc_ast = { path = "../rustc_ast" }
 rustc_lint_defs = { path = "../rustc_lint_defs" }
 smallvec = "1.8.1"
+termize = "0.1.1"
 
 [target.'cfg(unix)'.dependencies]
 libc = "0.2"
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index d8c4b0845d0..7a20100fd31 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -10,7 +10,7 @@ use crate::{lint, HashStableContext};
 
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 
-use rustc_data_structures::stable_hasher::ToStableHashKey;
+use rustc_data_structures::stable_hasher::{StableOrd, ToStableHashKey};
 use rustc_target::abi::Align;
 use rustc_target::spec::{PanicStrategy, SanitizerSet, SplitDebuginfo};
 use rustc_target::spec::{Target, TargetTriple, TargetWarnings, TARGETS};
@@ -288,6 +288,9 @@ pub enum OutputType {
     DepInfo,
 }
 
+// Safety: Trivial C-Style enums have a stable sort order across compilation sessions.
+unsafe impl StableOrd for OutputType {}
+
 impl<HCX: HashStableContext> ToStableHashKey<HCX> for OutputType {
     type KeyType = Self;
 
diff --git a/compiler/rustc_session/src/errors.rs b/compiler/rustc_session/src/errors.rs
index 8cb9e1a6f1a..ee492f802a7 100644
--- a/compiler/rustc_session/src/errors.rs
+++ b/compiler/rustc_session/src/errors.rs
@@ -129,10 +129,10 @@ pub struct FileIsNotWriteable<'a> {
 
 #[derive(Diagnostic)]
 #[diag(session_crate_name_does_not_match)]
-pub struct CrateNameDoesNotMatch<'a> {
+pub struct CrateNameDoesNotMatch {
     #[primary_span]
     pub span: Span,
-    pub s: &'a str,
+    pub s: Symbol,
     pub name: Symbol,
 }
 
@@ -151,11 +151,11 @@ pub struct CrateNameEmpty {
 
 #[derive(Diagnostic)]
 #[diag(session_invalid_character_in_create_name)]
-pub struct InvalidCharacterInCrateName<'a> {
+pub struct InvalidCharacterInCrateName {
     #[primary_span]
     pub span: Option<Span>,
     pub character: char,
-    pub crate_name: &'a str,
+    pub crate_name: Symbol,
 }
 
 #[derive(Subdiagnostic)]
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index 01a9361e786..8e9198b79df 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -1382,6 +1382,9 @@ options! {
         "list the symbols defined by a library crate (default: no)"),
     macro_backtrace: bool = (false, parse_bool, [UNTRACKED],
         "show macro backtraces (default: no)"),
+    maximal_hir_to_mir_coverage: bool = (false, parse_bool, [TRACKED],
+        "save as much information as possible about the correspondence between MIR and HIR \
+        as source scopes (default: no)"),
     merge_functions: Option<MergeFunctions> = (None, parse_merge_functions, [TRACKED],
         "control the operation of the MergeFunctions LLVM pass, taking \
         the same values as the target option of the same name"),
diff --git a/compiler/rustc_session/src/output.rs b/compiler/rustc_session/src/output.rs
index 2511bee46af..8ee3057de62 100644
--- a/compiler/rustc_session/src/output.rs
+++ b/compiler/rustc_session/src/output.rs
@@ -7,14 +7,14 @@ use crate::errors::{
 use crate::Session;
 use rustc_ast as ast;
 use rustc_span::symbol::sym;
-use rustc_span::Span;
+use rustc_span::{Span, Symbol};
 use std::path::{Path, PathBuf};
 
 pub fn out_filename(
     sess: &Session,
     crate_type: CrateType,
     outputs: &OutputFilenames,
-    crate_name: &str,
+    crate_name: Symbol,
 ) -> PathBuf {
     let default_filename = filename_for_input(sess, crate_type, crate_name, outputs);
     let out_filename = outputs
@@ -45,9 +45,9 @@ fn is_writeable(p: &Path) -> bool {
     }
 }
 
-pub fn find_crate_name(sess: &Session, attrs: &[ast::Attribute], input: &Input) -> String {
-    let validate = |s: String, span: Option<Span>| {
-        validate_crate_name(sess, &s, span);
+pub fn find_crate_name(sess: &Session, attrs: &[ast::Attribute], input: &Input) -> Symbol {
+    let validate = |s: Symbol, span: Option<Span>| {
+        validate_crate_name(sess, s, span);
         s
     };
 
@@ -59,38 +59,39 @@ pub fn find_crate_name(sess: &Session, attrs: &[ast::Attribute], input: &Input)
         sess.find_by_name(attrs, sym::crate_name).and_then(|at| at.value_str().map(|s| (at, s)));
 
     if let Some(ref s) = sess.opts.crate_name {
+        let s = Symbol::intern(s);
         if let Some((attr, name)) = attr_crate_name {
-            if name.as_str() != s {
+            if name != s {
                 sess.emit_err(CrateNameDoesNotMatch { span: attr.span, s, name });
             }
         }
-        return validate(s.clone(), None);
+        return validate(s, None);
     }
 
     if let Some((attr, s)) = attr_crate_name {
-        return validate(s.to_string(), Some(attr.span));
+        return validate(s, Some(attr.span));
     }
     if let Input::File(ref path) = *input {
         if let Some(s) = path.file_stem().and_then(|s| s.to_str()) {
             if s.starts_with('-') {
                 sess.emit_err(CrateNameInvalid { s });
             } else {
-                return validate(s.replace('-', "_"), None);
+                return validate(Symbol::intern(&s.replace('-', "_")), None);
             }
         }
     }
 
-    "rust_out".to_string()
+    Symbol::intern("rust_out")
 }
 
-pub fn validate_crate_name(sess: &Session, s: &str, sp: Option<Span>) {
+pub fn validate_crate_name(sess: &Session, s: Symbol, sp: Option<Span>) {
     let mut err_count = 0;
     {
         if s.is_empty() {
             err_count += 1;
             sess.emit_err(CrateNameEmpty { span: sp });
         }
-        for c in s.chars() {
+        for c in s.as_str().chars() {
             if c.is_alphanumeric() {
                 continue;
             }
@@ -109,7 +110,7 @@ pub fn validate_crate_name(sess: &Session, s: &str, sp: Option<Span>) {
 
 pub fn filename_for_metadata(
     sess: &Session,
-    crate_name: &str,
+    crate_name: Symbol,
     outputs: &OutputFilenames,
 ) -> PathBuf {
     // If the command-line specified the path, use that directly.
@@ -132,7 +133,7 @@ pub fn filename_for_metadata(
 pub fn filename_for_input(
     sess: &Session,
     crate_type: CrateType,
-    crate_name: &str,
+    crate_name: Symbol,
     outputs: &OutputFilenames,
 ) -> PathBuf {
     let libname = format!("{}{}", crate_name, sess.opts.cg.extra_filename);
diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs
index e99e460913e..4c049a8d628 100644
--- a/compiler/rustc_session/src/session.rs
+++ b/compiler/rustc_session/src/session.rs
@@ -952,6 +952,17 @@ impl Session {
     ) -> Option<Symbol> {
         attrs.iter().find(|at| at.has_name(name)).and_then(|at| at.value_str())
     }
+
+    pub fn diagnostic_width(&self) -> usize {
+        let default_column_width = 140;
+        if let Some(width) = self.opts.diagnostic_width {
+            width
+        } else if self.opts.unstable_opts.ui_testing {
+            default_column_width
+        } else {
+            termize::dimensions().map_or(default_column_width, |(w, _)| w)
+        }
+    }
 }
 
 // JUSTIFICATION: defn of the suggested wrapper fns
diff --git a/compiler/rustc_span/src/def_id.rs b/compiler/rustc_span/src/def_id.rs
index f5555846d20..e62ce2c266a 100644
--- a/compiler/rustc_span/src/def_id.rs
+++ b/compiler/rustc_span/src/def_id.rs
@@ -1,4 +1,4 @@
-use crate::HashStableContext;
+use crate::{HashStableContext, Symbol};
 use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey};
 use rustc_data_structures::AtomicRef;
@@ -149,9 +149,11 @@ impl StableCrateId {
 
     /// Computes the stable ID for a crate with the given name and
     /// `-Cmetadata` arguments.
-    pub fn new(crate_name: &str, is_exe: bool, mut metadata: Vec<String>) -> StableCrateId {
+    pub fn new(crate_name: Symbol, is_exe: bool, mut metadata: Vec<String>) -> StableCrateId {
         let mut hasher = StableHasher::new();
-        crate_name.hash(&mut hasher);
+        // We must hash the string text of the crate name, not the id, as the id is not stable
+        // across builds.
+        crate_name.as_str().hash(&mut hasher);
 
         // We don't want the stable crate ID to depend on the order of
         // -C metadata arguments, so sort them:
@@ -274,7 +276,7 @@ impl Ord for DefId {
 impl PartialOrd for DefId {
     #[inline]
     fn partial_cmp(&self, other: &DefId) -> Option<std::cmp::Ordering> {
-        Some(Ord::cmp(self, other))
+        Some(self.cmp(other))
     }
 }
 
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 9e446c96db3..61253845497 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -165,6 +165,7 @@ symbols! {
         Capture,
         Center,
         Clone,
+        Context,
         Continue,
         Copy,
         Count,
@@ -264,7 +265,6 @@ symbols! {
         Relaxed,
         Release,
         Result,
-        ResumeTy,
         Return,
         Right,
         Rust,
@@ -754,7 +754,6 @@ symbols! {
         generic_associated_types_extended,
         generic_const_exprs,
         generic_param_attrs,
-        get_context,
         global_allocator,
         global_asm,
         globs,
diff --git a/compiler/rustc_target/src/spec/wasm32_unknown_unknown.rs b/compiler/rustc_target/src/spec/wasm32_unknown_unknown.rs
index 8dad941b534..06529c2e403 100644
--- a/compiler/rustc_target/src/spec/wasm32_unknown_unknown.rs
+++ b/compiler/rustc_target/src/spec/wasm32_unknown_unknown.rs
@@ -33,12 +33,6 @@ pub fn target() -> Target {
             // For now this target just never has an entry symbol no matter the output
             // type, so unconditionally pass this.
             "--no-entry",
-            // Rust really needs a way for users to specify exports and imports in
-            // the source code. --export-dynamic isn't the right tool for this job,
-            // however it does have the side effect of automatically exporting a lot
-            // of symbols, which approximates what people want when compiling for
-            // wasm32-unknown-unknown expect, so use it for now.
-            "--export-dynamic",
         ],
     );
     options.add_pre_link_args(
@@ -48,7 +42,6 @@ pub fn target() -> Target {
             // otherwise
             "--target=wasm32-unknown-unknown",
             "-Wl,--no-entry",
-            "-Wl,--export-dynamic",
         ],
     );
 
diff --git a/compiler/rustc_trait_selection/src/traits/codegen.rs b/compiler/rustc_trait_selection/src/traits/codegen.rs
index 61743d78e9e..0102d268b42 100644
--- a/compiler/rustc_trait_selection/src/traits/codegen.rs
+++ b/compiler/rustc_trait_selection/src/traits/codegen.rs
@@ -70,7 +70,7 @@ pub fn codegen_select_candidate<'tcx>(
         // `rustc_ty_utils::resolve_associated_item` doesn't return `None` post-monomorphization.
         for err in errors {
             if let FulfillmentErrorCode::CodeCycle(cycle) = err.code {
-                infcx.err_ctxt().report_overflow_error_cycle(&cycle);
+                infcx.err_ctxt().report_overflow_obligation_cycle(&cycle);
             }
         }
         return Err(CodegenObligationError::FulfillmentError);
diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
index e9e65336299..7c9fde27420 100644
--- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
+++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
@@ -25,15 +25,13 @@ use crate::traits::ObligationCtxt;
 #[instrument(skip(infcx), level = "debug")]
 pub fn is_const_evaluatable<'tcx>(
     infcx: &InferCtxt<'tcx>,
-    ct: ty::Const<'tcx>,
+    unexpanded_ct: ty::Const<'tcx>,
     param_env: ty::ParamEnv<'tcx>,
     span: Span,
 ) -> Result<(), NotConstEvaluatable> {
     let tcx = infcx.tcx;
-    let uv = match ct.kind() {
-        ty::ConstKind::Unevaluated(uv) => uv,
-        // FIXME(generic_const_exprs): this seems wrong but I couldn't find a way to get this to trigger
-        ty::ConstKind::Expr(_) => bug!("unexpected expr in `is_const_evaluatable: {ct:?}"),
+    match tcx.expand_abstract_consts(unexpanded_ct).kind() {
+        ty::ConstKind::Unevaluated(_) | ty::ConstKind::Expr(_) => (),
         ty::ConstKind::Param(_)
         | ty::ConstKind::Bound(_, _)
         | ty::ConstKind::Placeholder(_)
@@ -43,7 +41,7 @@ pub fn is_const_evaluatable<'tcx>(
     };
 
     if tcx.features().generic_const_exprs {
-        let ct = tcx.expand_abstract_consts(ct);
+        let ct = tcx.expand_abstract_consts(unexpanded_ct);
 
         let is_anon_ct = if let ty::ConstKind::Unevaluated(uv) = ct.kind() {
             tcx.def_kind(uv.def.did) == DefKind::AnonConst
@@ -62,18 +60,40 @@ pub fn is_const_evaluatable<'tcx>(
             }
         }
 
-        let concrete = infcx.const_eval_resolve(param_env, uv, Some(span));
-        match concrete {
-            Err(ErrorHandled::TooGeneric) => Err(NotConstEvaluatable::Error(
-                infcx
-                    .tcx
-                    .sess
-                    .delay_span_bug(span, "Missing value for constant, but no error reported?"),
-            )),
-            Err(ErrorHandled::Reported(e)) => Err(NotConstEvaluatable::Error(e)),
-            Ok(_) => Ok(()),
+        match unexpanded_ct.kind() {
+            ty::ConstKind::Expr(_) => {
+                // FIXME(generic_const_exprs): we have a `ConstKind::Expr` which is fully concrete, but
+                // currently it is not possible to evaluate `ConstKind::Expr` so we are unable to tell if it
+                // is evaluatable or not. For now we just ICE until this is implemented.
+                Err(NotConstEvaluatable::Error(tcx.sess.delay_span_bug(
+                    span,
+                    "evaluating `ConstKind::Expr` is not currently supported",
+                )))
+            }
+            ty::ConstKind::Unevaluated(uv) => {
+                let concrete = infcx.const_eval_resolve(param_env, uv, Some(span));
+                match concrete {
+                    Err(ErrorHandled::TooGeneric) => {
+                        Err(NotConstEvaluatable::Error(infcx.tcx.sess.delay_span_bug(
+                            span,
+                            "Missing value for constant, but no error reported?",
+                        )))
+                    }
+                    Err(ErrorHandled::Reported(e)) => Err(NotConstEvaluatable::Error(e)),
+                    Ok(_) => Ok(()),
+                }
+            }
+            _ => bug!("unexpected constkind in `is_const_evalautable: {unexpanded_ct:?}`"),
         }
     } else {
+        let uv = match unexpanded_ct.kind() {
+            ty::ConstKind::Unevaluated(uv) => uv,
+            ty::ConstKind::Expr(_) => {
+                bug!("`ConstKind::Expr` without `feature(generic_const_exprs)` enabled")
+            }
+            _ => bug!("unexpected constkind in `is_const_evalautable: {unexpanded_ct:?}`"),
+        };
+
         // FIXME: We should only try to evaluate a given constant here if it is fully concrete
         // as we don't want to allow things like `[u8; std::mem::size_of::<*mut T>()]`.
         //
@@ -92,7 +112,7 @@ pub fn is_const_evaluatable<'tcx>(
                     && satisfied_from_param_env(
                         tcx,
                         infcx,
-                        tcx.expand_abstract_consts(ct),
+                        tcx.expand_abstract_consts(unexpanded_ct),
                         param_env,
                     ) =>
             {
@@ -152,6 +172,7 @@ fn satisfied_from_param_env<'tcx>(
     impl<'a, 'tcx> TypeVisitor<'tcx> for Visitor<'a, 'tcx> {
         type BreakTy = ();
         fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
+            debug!("is_const_evaluatable: candidate={:?}", c);
             if let Ok(()) = self.infcx.commit_if_ok(|_| {
                 let ocx = ObligationCtxt::new_in_snapshot(self.infcx);
                 if let Ok(()) = ocx.eq(&ObligationCause::dummy(), self.param_env, c.ty(), self.ct.ty())
@@ -187,7 +208,7 @@ fn satisfied_from_param_env<'tcx>(
                 let result = b_ct.visit_with(&mut v);
 
                 if let ControlFlow::Break(()) = result {
-                    debug!("is_const_evaluatable: abstract_const ~~> ok");
+                    debug!("is_const_evaluatable: yes");
                     return true;
                 }
             }
@@ -195,5 +216,6 @@ fn satisfied_from_param_env<'tcx>(
         }
     }
 
+    debug!("is_const_evaluatable: no");
     false
 }
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 3379279dd15..dda7b2b2fa5 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
@@ -99,26 +99,36 @@ pub trait InferCtxtExt<'tcx> {
 }
 
 pub trait TypeErrCtxtExt<'tcx> {
+    fn report_overflow_error<T>(
+        &self,
+        predicate: &T,
+        span: Span,
+        suggest_increasing_limit: bool,
+        mutate: impl FnOnce(&mut Diagnostic),
+    ) -> !
+    where
+        T: fmt::Display
+            + TypeFoldable<'tcx>
+            + Print<'tcx, FmtPrinter<'tcx, 'tcx>, Output = FmtPrinter<'tcx, 'tcx>>,
+        <T as Print<'tcx, FmtPrinter<'tcx, 'tcx>>>::Error: std::fmt::Debug;
+
     fn report_fulfillment_errors(
         &self,
         errors: &[FulfillmentError<'tcx>],
         body_id: Option<hir::BodyId>,
     ) -> ErrorGuaranteed;
 
-    fn report_overflow_error<T>(
+    fn report_overflow_obligation<T>(
         &self,
         obligation: &Obligation<'tcx, T>,
         suggest_increasing_limit: bool,
     ) -> !
     where
-        T: fmt::Display
-            + TypeFoldable<'tcx>
-            + Print<'tcx, FmtPrinter<'tcx, 'tcx>, Output = FmtPrinter<'tcx, 'tcx>>,
-        <T as Print<'tcx, FmtPrinter<'tcx, 'tcx>>>::Error: std::fmt::Debug;
+        T: ToPredicate<'tcx> + Clone;
 
     fn suggest_new_overflow_limit(&self, err: &mut Diagnostic);
 
-    fn report_overflow_error_cycle(&self, cycle: &[PredicateObligation<'tcx>]) -> !;
+    fn report_overflow_obligation_cycle(&self, cycle: &[PredicateObligation<'tcx>]) -> !;
 
     /// The `root_obligation` parameter should be the `root_obligation` field
     /// from a `FulfillmentError`. If no `FulfillmentError` is available,
@@ -458,8 +468,10 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
     /// occurrences in any case.
     fn report_overflow_error<T>(
         &self,
-        obligation: &Obligation<'tcx, T>,
+        predicate: &T,
+        span: Span,
         suggest_increasing_limit: bool,
+        mutate: impl FnOnce(&mut Diagnostic),
     ) -> !
     where
         T: fmt::Display
@@ -467,8 +479,9 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
             + Print<'tcx, FmtPrinter<'tcx, 'tcx>, Output = FmtPrinter<'tcx, 'tcx>>,
         <T as Print<'tcx, FmtPrinter<'tcx, 'tcx>>>::Error: std::fmt::Debug,
     {
-        let predicate = self.resolve_vars_if_possible(obligation.predicate.clone());
+        let predicate = self.resolve_vars_if_possible(predicate.clone());
         let mut pred_str = predicate.to_string();
+
         if pred_str.len() > 50 {
             // We don't need to save the type to a file, we will be talking about this type already
             // in a separate note when we explain the obligation, so it will be available that way.
@@ -483,7 +496,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
         }
         let mut err = struct_span_err!(
             self.tcx.sess,
-            obligation.cause.span,
+            span,
             E0275,
             "overflow evaluating the requirement `{}`",
             pred_str,
@@ -493,20 +506,46 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
             self.suggest_new_overflow_limit(&mut err);
         }
 
-        self.note_obligation_cause_code(
-            &mut err,
-            &obligation.predicate,
-            obligation.param_env,
-            obligation.cause.code(),
-            &mut vec![],
-            &mut Default::default(),
-        );
+        mutate(&mut err);
 
         err.emit();
         self.tcx.sess.abort_if_errors();
         bug!();
     }
 
+    /// Reports that an overflow has occurred and halts compilation. We
+    /// halt compilation unconditionally because it is important that
+    /// overflows never be masked -- they basically represent computations
+    /// whose result could not be truly determined and thus we can't say
+    /// if the program type checks or not -- and they are unusual
+    /// occurrences in any case.
+    fn report_overflow_obligation<T>(
+        &self,
+        obligation: &Obligation<'tcx, T>,
+        suggest_increasing_limit: bool,
+    ) -> !
+    where
+        T: ToPredicate<'tcx> + Clone,
+    {
+        let predicate = obligation.predicate.clone().to_predicate(self.tcx);
+        let predicate = self.resolve_vars_if_possible(predicate);
+        self.report_overflow_error(
+            &predicate,
+            obligation.cause.span,
+            suggest_increasing_limit,
+            |err| {
+                self.note_obligation_cause_code(
+                    err,
+                    &predicate,
+                    obligation.param_env,
+                    obligation.cause.code(),
+                    &mut vec![],
+                    &mut Default::default(),
+                );
+            },
+        );
+    }
+
     fn suggest_new_overflow_limit(&self, err: &mut Diagnostic) {
         let suggested_limit = match self.tcx.recursion_limit() {
             Limit(0) => Limit(2),
@@ -521,11 +560,11 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
     }
 
     /// Reports that a cycle was detected which led to overflow and halts
-    /// compilation. This is equivalent to `report_overflow_error` except
+    /// compilation. This is equivalent to `report_overflow_obligation` except
     /// that we can give a more helpful error message (and, in particular,
     /// we do not suggest increasing the overflow limit, which is not
     /// going to help).
-    fn report_overflow_error_cycle(&self, cycle: &[PredicateObligation<'tcx>]) -> ! {
+    fn report_overflow_obligation_cycle(&self, cycle: &[PredicateObligation<'tcx>]) -> ! {
         let cycle = self.resolve_vars_if_possible(cycle.to_owned());
         assert!(!cycle.is_empty());
 
@@ -533,7 +572,10 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
 
         // The 'deepest' obligation is most likely to have a useful
         // cause 'backtrace'
-        self.report_overflow_error(cycle.iter().max_by_key(|p| p.recursion_depth).unwrap(), false);
+        self.report_overflow_obligation(
+            cycle.iter().max_by_key(|p| p.recursion_depth).unwrap(),
+            false,
+        );
     }
 
     fn report_selection_error(
@@ -1554,7 +1596,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                 diag.emit();
             }
             FulfillmentErrorCode::CodeCycle(ref cycle) => {
-                self.report_overflow_error_cycle(cycle);
+                self.report_overflow_obligation_cycle(cycle);
             }
         }
     }
@@ -1607,7 +1649,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                         | ObligationCauseCode::ObjectCastObligation(..)
                         | ObligationCauseCode::OpaqueType
                 );
-                let expected_ty = data.term.ty().unwrap();
+                let expected_ty = data.term.ty().unwrap_or_else(|| self.tcx.ty_error());
 
                 // constrain inference variables a bit more to nested obligations from normalize so
                 // we can have more helpful errors.
@@ -1810,7 +1852,8 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
         &self,
         trait_pred: ty::PolyTraitPredicate<'tcx>,
     ) -> Vec<ImplCandidate<'tcx>> {
-        self.tcx
+        let mut candidates: Vec<_> = self
+            .tcx
             .all_impls(trait_pred.def_id())
             .filter_map(|def_id| {
                 if self.tcx.impl_polarity(def_id) == ty::ImplPolarity::Negative
@@ -1826,7 +1869,14 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                 self.fuzzy_match_tys(trait_pred.skip_binder().self_ty(), imp.self_ty(), false)
                     .map(|similarity| ImplCandidate { trait_ref: imp, similarity })
             })
-            .collect()
+            .collect();
+        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).
+            candidates.retain(|c| matches!(c.similarity, CandidateSimilarity::Exact { .. }));
+        }
+        candidates
     }
 
     fn report_similar_impl_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 1740128727a..6ea54b625bb 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -298,7 +298,7 @@ pub trait TypeErrCtxtExt<'tcx> {
         obligated_types: &mut Vec<Ty<'tcx>>,
         seen_requirements: &mut FxHashSet<DefId>,
     ) where
-        T: fmt::Display + ToPredicate<'tcx, T>;
+        T: fmt::Display + ToPredicate<'tcx>;
 
     /// Suggest to await before try: future? => future.await?
     fn suggest_await_before_try(
@@ -2353,7 +2353,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
         obligated_types: &mut Vec<Ty<'tcx>>,
         seen_requirements: &mut FxHashSet<DefId>,
     ) where
-        T: fmt::Display,
+        T: fmt::Display + ToPredicate<'tcx>,
     {
         let tcx = self.tcx;
         match *cause_code {
diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs
index c6818a4e57d..d3cfd61e195 100644
--- a/compiler/rustc_trait_selection/src/traits/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/mod.rs
@@ -150,7 +150,7 @@ pub fn type_known_to_meet_bound_modulo_regions<'tcx>(
 fn pred_known_to_hold_modulo_regions<'tcx>(
     infcx: &InferCtxt<'tcx>,
     param_env: ty::ParamEnv<'tcx>,
-    pred: impl ToPredicate<'tcx, ty::Predicate<'tcx>> + TypeVisitable<'tcx>,
+    pred: impl ToPredicate<'tcx> + TypeVisitable<'tcx>,
     span: Span,
 ) -> bool {
     let has_non_region_infer = pred.has_non_region_infer();
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index 051660be9c4..5789754e4fc 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -504,14 +504,12 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> {
                     Reveal::All => {
                         let recursion_limit = self.tcx().recursion_limit();
                         if !recursion_limit.value_within_limit(self.depth) {
-                            let obligation = Obligation::with_depth(
-                                self.tcx(),
-                                self.cause.clone(),
-                                recursion_limit.0,
-                                self.param_env,
-                                ty,
+                            self.selcx.infcx.err_ctxt().report_overflow_error(
+                                &ty,
+                                self.cause.span,
+                                true,
+                                |_| {},
                             );
-                            self.selcx.infcx.err_ctxt().report_overflow_error(&obligation, true);
                         }
 
                         let substs = substs.fold_with(self);
@@ -2321,11 +2319,10 @@ fn assoc_ty_own_obligations<'cx, 'tcx>(
     nested: &mut Vec<PredicateObligation<'tcx>>,
 ) {
     let tcx = selcx.tcx();
-    for predicate in tcx
+    let own = tcx
         .predicates_of(obligation.predicate.item_def_id)
-        .instantiate_own(tcx, obligation.predicate.substs)
-        .predicates
-    {
+        .instantiate_own(tcx, obligation.predicate.substs);
+    for (predicate, span) in std::iter::zip(own.predicates, own.spans) {
         let normalized = normalize_with_depth_to(
             selcx,
             obligation.param_env,
@@ -2334,9 +2331,30 @@ fn assoc_ty_own_obligations<'cx, 'tcx>(
             predicate,
             nested,
         );
+
+        let nested_cause = if matches!(
+            obligation.cause.code(),
+            super::CompareImplItemObligation { .. }
+                | super::CheckAssociatedTypeBounds { .. }
+                | super::AscribeUserTypeProvePredicate(..)
+        ) {
+            obligation.cause.clone()
+        } else if span.is_dummy() {
+            ObligationCause::new(
+                obligation.cause.span,
+                obligation.cause.body_id,
+                super::ItemObligation(obligation.predicate.item_def_id),
+            )
+        } else {
+            ObligationCause::new(
+                obligation.cause.span,
+                obligation.cause.body_id,
+                super::BindingObligation(obligation.predicate.item_def_id, span),
+            )
+        };
         nested.push(Obligation::with_depth(
             tcx,
-            obligation.cause.clone(),
+            nested_cause,
             obligation.recursion_depth + 1,
             obligation.param_env,
             normalized,
diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs
index f899321fc01..7ad532d8a34 100644
--- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs
@@ -7,7 +7,7 @@ use crate::infer::canonical::OriginalQueryValues;
 use crate::infer::{InferCtxt, InferOk};
 use crate::traits::error_reporting::TypeErrCtxtExt;
 use crate::traits::project::{needs_normalization, BoundVarReplacer, PlaceholderReplacer};
-use crate::traits::{Obligation, ObligationCause, PredicateObligation, Reveal};
+use crate::traits::{ObligationCause, PredicateObligation, Reveal};
 use rustc_data_structures::sso::SsoHashMap;
 use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_infer::traits::Normalized;
@@ -214,14 +214,12 @@ impl<'cx, 'tcx> FallibleTypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
                         let substs = substs.try_fold_with(self)?;
                         let recursion_limit = self.tcx().recursion_limit();
                         if !recursion_limit.value_within_limit(self.anon_depth) {
-                            let obligation = Obligation::with_depth(
-                                self.tcx(),
-                                self.cause.clone(),
-                                recursion_limit.0,
-                                self.param_env,
-                                ty,
+                            self.infcx.err_ctxt().report_overflow_error(
+                                &ty,
+                                self.cause.span,
+                                true,
+                                |_| {},
                             );
-                            self.infcx.err_ctxt().report_overflow_error(&obligation, true);
                         }
 
                         let generic_ty = self.tcx().bound_type_of(def_id);
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index 8835f2cc1b9..035deb61639 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -43,7 +43,6 @@ use rustc_middle::mir::interpret::ErrorHandled;
 use rustc_middle::ty::abstract_const::NotConstEvaluatable;
 use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams};
 use rustc_middle::ty::fold::BottomUpFolder;
-use rustc_middle::ty::print::{FmtPrinter, Print};
 use rustc_middle::ty::relate::TypeRelation;
 use rustc_middle::ty::SubstsRef;
 use rustc_middle::ty::{self, EarlyBinder, PolyProjectionPredicate, ToPolyTraitRef, ToPredicate};
@@ -1313,10 +1312,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         error_obligation: &Obligation<'tcx, T>,
     ) -> Result<(), OverflowError>
     where
-        T: fmt::Display
-            + TypeFoldable<'tcx>
-            + Print<'tcx, FmtPrinter<'tcx, 'tcx>, Output = FmtPrinter<'tcx, 'tcx>>,
-        <T as Print<'tcx, FmtPrinter<'tcx, 'tcx>>>::Error: std::fmt::Debug,
+        T: ToPredicate<'tcx> + Clone,
     {
         if !self.infcx.tcx.recursion_limit().value_within_limit(depth) {
             match self.query_mode {
@@ -1324,7 +1320,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                     if let Some(e) = self.infcx.tainted_by_errors() {
                         return Err(OverflowError::Error(e));
                     }
-                    self.infcx.err_ctxt().report_overflow_error(error_obligation, true);
+                    self.infcx.err_ctxt().report_overflow_obligation(error_obligation, true);
                 }
                 TraitQueryMode::Canonical => {
                     return Err(OverflowError::Canonical);
@@ -1345,10 +1341,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         error_obligation: &Obligation<'tcx, V>,
     ) -> Result<(), OverflowError>
     where
-        V: fmt::Display
-            + TypeFoldable<'tcx>
-            + Print<'tcx, FmtPrinter<'tcx, 'tcx>, Output = FmtPrinter<'tcx, 'tcx>>,
-        <V as Print<'tcx, FmtPrinter<'tcx, 'tcx>>>::Error: std::fmt::Debug,
+        V: ToPredicate<'tcx> + Clone,
     {
         self.check_recursion_depth(obligation.recursion_depth, error_obligation)
     }
diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs
index 0855d6d1973..e47ba64245f 100644
--- a/compiler/rustc_trait_selection/src/traits/wf.rs
+++ b/compiler/rustc_trait_selection/src/traits/wf.rs
@@ -476,9 +476,24 @@ impl<'tcx> WfPredicates<'tcx> {
                                 ty::Binder::dummy(ty::PredicateKind::WellFormed(ct.into())),
                             ));
                         }
-                        // FIXME(generic_const_exprs): This seems wrong but I could not find a way to get this to trigger
                         ty::ConstKind::Expr(_) => {
-                            bug!("checking wfness of `ConstKind::Expr` is unsupported")
+                            // FIXME(generic_const_exprs): this doesnt verify that given `Expr(N + 1)` the
+                            // trait bound `typeof(N): Add<typeof(1)>` holds. This is currently unnecessary
+                            // as `ConstKind::Expr` is only produced via normalization of `ConstKind::Unevaluated`
+                            // which means that the `DefId` would have been typeck'd elsewhere. However in
+                            // the future we may allow directly lowering to `ConstKind::Expr` in which case
+                            // we would not be proving bounds we should.
+
+                            let predicate =
+                                ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(ct));
+                            let cause = self.cause(traits::WellFormed(None));
+                            self.out.push(traits::Obligation::with_depth(
+                                self.tcx(),
+                                cause,
+                                self.recursion_depth,
+                                self.param_env,
+                                predicate,
+                            ));
                         }
 
                         ty::ConstKind::Error(_)
diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs
index 581993ba7d8..e3f7a1bd033 100644
--- a/compiler/rustc_type_ir/src/lib.rs
+++ b/compiler/rustc_type_ir/src/lib.rs
@@ -19,9 +19,11 @@ use std::mem::discriminant;
 
 pub mod codec;
 pub mod sty;
+pub mod ty_info;
 
 pub use codec::*;
 pub use sty::*;
+pub use ty_info::*;
 
 /// Needed so we can use #[derive(HashStable_Generic)]
 pub trait HashStableContext {}
diff --git a/compiler/rustc_type_ir/src/sty.rs b/compiler/rustc_type_ir/src/sty.rs
index 02cbb2e858f..3ed616d709b 100644
--- a/compiler/rustc_type_ir/src/sty.rs
+++ b/compiler/rustc_type_ir/src/sty.rs
@@ -301,61 +301,44 @@ impl<I: Interner> Clone for TyKind<I> {
 impl<I: Interner> PartialEq for TyKind<I> {
     #[inline]
     fn eq(&self, other: &TyKind<I>) -> bool {
-        let __self_vi = tykind_discriminant(self);
-        let __arg_1_vi = tykind_discriminant(other);
-        if __self_vi == __arg_1_vi {
-            match (&*self, &*other) {
-                (&Int(ref __self_0), &Int(ref __arg_1_0)) => __self_0 == __arg_1_0,
-                (&Uint(ref __self_0), &Uint(ref __arg_1_0)) => __self_0 == __arg_1_0,
-                (&Float(ref __self_0), &Float(ref __arg_1_0)) => __self_0 == __arg_1_0,
-                (&Adt(ref __self_0, ref __self_1), &Adt(ref __arg_1_0, ref __arg_1_1)) => {
-                    __self_0 == __arg_1_0 && __self_1 == __arg_1_1
+        tykind_discriminant(self) == tykind_discriminant(other)
+            && match (self, other) {
+                (Int(a_i), Int(b_i)) => a_i == b_i,
+                (Uint(a_u), Uint(b_u)) => a_u == b_u,
+                (Float(a_f), Float(b_f)) => a_f == b_f,
+                (Adt(a_d, a_s), Adt(b_d, b_s)) => a_d == b_d && a_s == b_s,
+                (Foreign(a_d), Foreign(b_d)) => a_d == b_d,
+                (Array(a_t, a_c), Array(b_t, b_c)) => a_t == b_t && a_c == b_c,
+                (Slice(a_t), Slice(b_t)) => a_t == b_t,
+                (RawPtr(a_t), RawPtr(b_t)) => a_t == b_t,
+                (Ref(a_r, a_t, a_m), Ref(b_r, b_t, b_m)) => a_r == b_r && a_t == b_t && a_m == b_m,
+                (FnDef(a_d, a_s), FnDef(b_d, b_s)) => a_d == b_d && a_s == b_s,
+                (FnPtr(a_s), FnPtr(b_s)) => a_s == b_s,
+                (Dynamic(a_p, a_r, a_repr), Dynamic(b_p, b_r, b_repr)) => {
+                    a_p == b_p && a_r == b_r && a_repr == b_repr
                 }
-                (&Foreign(ref __self_0), &Foreign(ref __arg_1_0)) => __self_0 == __arg_1_0,
-                (&Array(ref __self_0, ref __self_1), &Array(ref __arg_1_0, ref __arg_1_1)) => {
-                    __self_0 == __arg_1_0 && __self_1 == __arg_1_1
+                (Closure(a_d, a_s), Closure(b_d, b_s)) => a_d == b_d && a_s == b_s,
+                (Generator(a_d, a_s, a_m), Generator(b_d, b_s, b_m)) => {
+                    a_d == b_d && a_s == b_s && a_m == b_m
                 }
-                (&Slice(ref __self_0), &Slice(ref __arg_1_0)) => __self_0 == __arg_1_0,
-                (&RawPtr(ref __self_0), &RawPtr(ref __arg_1_0)) => __self_0 == __arg_1_0,
-                (
-                    &Ref(ref __self_0, ref __self_1, ref __self_2),
-                    &Ref(ref __arg_1_0, ref __arg_1_1, ref __arg_1_2),
-                ) => __self_0 == __arg_1_0 && __self_1 == __arg_1_1 && __self_2 == __arg_1_2,
-                (&FnDef(ref __self_0, ref __self_1), &FnDef(ref __arg_1_0, ref __arg_1_1)) => {
-                    __self_0 == __arg_1_0 && __self_1 == __arg_1_1
+                (GeneratorWitness(a_g), GeneratorWitness(b_g)) => a_g == b_g,
+                (Tuple(a_t), Tuple(b_t)) => a_t == b_t,
+                (Projection(a_p), Projection(b_p)) => a_p == b_p,
+                (Opaque(a_d, a_s), Opaque(b_d, b_s)) => a_d == b_d && a_s == b_s,
+                (Param(a_p), Param(b_p)) => a_p == b_p,
+                (Bound(a_d, a_b), Bound(b_d, b_b)) => a_d == b_d && a_b == b_b,
+                (Placeholder(a_p), Placeholder(b_p)) => a_p == b_p,
+                (Infer(a_t), Infer(b_t)) => a_t == b_t,
+                (Error(a_e), Error(b_e)) => a_e == b_e,
+                (Bool, Bool) | (Char, Char) | (Str, Str) | (Never, Never) => true,
+                _ => {
+                    debug_assert!(
+                        false,
+                        "This branch must be unreachable, maybe the match is missing an arm? self = self = {self:?}, other = {other:?}"
+                    );
+                    true
                 }
-                (&FnPtr(ref __self_0), &FnPtr(ref __arg_1_0)) => __self_0 == __arg_1_0,
-                (
-                    &Dynamic(ref __self_0, ref __self_1, ref self_repr),
-                    &Dynamic(ref __arg_1_0, ref __arg_1_1, ref arg_repr),
-                ) => __self_0 == __arg_1_0 && __self_1 == __arg_1_1 && self_repr == arg_repr,
-                (&Closure(ref __self_0, ref __self_1), &Closure(ref __arg_1_0, ref __arg_1_1)) => {
-                    __self_0 == __arg_1_0 && __self_1 == __arg_1_1
-                }
-                (
-                    &Generator(ref __self_0, ref __self_1, ref __self_2),
-                    &Generator(ref __arg_1_0, ref __arg_1_1, ref __arg_1_2),
-                ) => __self_0 == __arg_1_0 && __self_1 == __arg_1_1 && __self_2 == __arg_1_2,
-                (&GeneratorWitness(ref __self_0), &GeneratorWitness(ref __arg_1_0)) => {
-                    __self_0 == __arg_1_0
-                }
-                (&Tuple(ref __self_0), &Tuple(ref __arg_1_0)) => __self_0 == __arg_1_0,
-                (&Projection(ref __self_0), &Projection(ref __arg_1_0)) => __self_0 == __arg_1_0,
-                (&Opaque(ref __self_0, ref __self_1), &Opaque(ref __arg_1_0, ref __arg_1_1)) => {
-                    __self_0 == __arg_1_0 && __self_1 == __arg_1_1
-                }
-                (&Param(ref __self_0), &Param(ref __arg_1_0)) => __self_0 == __arg_1_0,
-                (&Bound(ref __self_0, ref __self_1), &Bound(ref __arg_1_0, ref __arg_1_1)) => {
-                    __self_0 == __arg_1_0 && __self_1 == __arg_1_1
-                }
-                (&Placeholder(ref __self_0), &Placeholder(ref __arg_1_0)) => __self_0 == __arg_1_0,
-                (&Infer(ref __self_0), &Infer(ref __arg_1_0)) => __self_0 == __arg_1_0,
-                (&Error(ref __self_0), &Error(ref __arg_1_0)) => __self_0 == __arg_1_0,
-                _ => true,
             }
-        } else {
-            false
-        }
     }
 }
 
@@ -366,7 +349,7 @@ impl<I: Interner> Eq for TyKind<I> {}
 impl<I: Interner> PartialOrd for TyKind<I> {
     #[inline]
     fn partial_cmp(&self, other: &TyKind<I>) -> Option<Ordering> {
-        Some(Ord::cmp(self, other))
+        Some(self.cmp(other))
     }
 }
 
@@ -374,213 +357,106 @@ impl<I: Interner> PartialOrd for TyKind<I> {
 impl<I: Interner> Ord for TyKind<I> {
     #[inline]
     fn cmp(&self, other: &TyKind<I>) -> Ordering {
-        let __self_vi = tykind_discriminant(self);
-        let __arg_1_vi = tykind_discriminant(other);
-        if __self_vi == __arg_1_vi {
-            match (&*self, &*other) {
-                (&Int(ref __self_0), &Int(ref __arg_1_0)) => Ord::cmp(__self_0, __arg_1_0),
-                (&Uint(ref __self_0), &Uint(ref __arg_1_0)) => Ord::cmp(__self_0, __arg_1_0),
-                (&Float(ref __self_0), &Float(ref __arg_1_0)) => Ord::cmp(__self_0, __arg_1_0),
-                (&Adt(ref __self_0, ref __self_1), &Adt(ref __arg_1_0, ref __arg_1_1)) => {
-                    match Ord::cmp(__self_0, __arg_1_0) {
-                        Ordering::Equal => Ord::cmp(__self_1, __arg_1_1),
-                        cmp => cmp,
-                    }
-                }
-                (&Foreign(ref __self_0), &Foreign(ref __arg_1_0)) => Ord::cmp(__self_0, __arg_1_0),
-                (&Array(ref __self_0, ref __self_1), &Array(ref __arg_1_0, ref __arg_1_1)) => {
-                    match Ord::cmp(__self_0, __arg_1_0) {
-                        Ordering::Equal => Ord::cmp(__self_1, __arg_1_1),
-                        cmp => cmp,
-                    }
-                }
-                (&Slice(ref __self_0), &Slice(ref __arg_1_0)) => Ord::cmp(__self_0, __arg_1_0),
-                (&RawPtr(ref __self_0), &RawPtr(ref __arg_1_0)) => Ord::cmp(__self_0, __arg_1_0),
-                (
-                    &Ref(ref __self_0, ref __self_1, ref __self_2),
-                    &Ref(ref __arg_1_0, ref __arg_1_1, ref __arg_1_2),
-                ) => match Ord::cmp(__self_0, __arg_1_0) {
-                    Ordering::Equal => match Ord::cmp(__self_1, __arg_1_1) {
-                        Ordering::Equal => Ord::cmp(__self_2, __arg_1_2),
-                        cmp => cmp,
-                    },
-                    cmp => cmp,
-                },
-                (&FnDef(ref __self_0, ref __self_1), &FnDef(ref __arg_1_0, ref __arg_1_1)) => {
-                    match Ord::cmp(__self_0, __arg_1_0) {
-                        Ordering::Equal => Ord::cmp(__self_1, __arg_1_1),
-                        cmp => cmp,
-                    }
+        tykind_discriminant(self).cmp(&tykind_discriminant(other)).then_with(|| {
+            match (self, other) {
+                (Int(a_i), Int(b_i)) => a_i.cmp(b_i),
+                (Uint(a_u), Uint(b_u)) => a_u.cmp(b_u),
+                (Float(a_f), Float(b_f)) => a_f.cmp(b_f),
+                (Adt(a_d, a_s), Adt(b_d, b_s)) => a_d.cmp(b_d).then_with(|| a_s.cmp(b_s)),
+                (Foreign(a_d), Foreign(b_d)) => a_d.cmp(b_d),
+                (Array(a_t, a_c), Array(b_t, b_c)) => a_t.cmp(b_t).then_with(|| a_c.cmp(b_c)),
+                (Slice(a_t), Slice(b_t)) => a_t.cmp(b_t),
+                (RawPtr(a_t), RawPtr(b_t)) => a_t.cmp(b_t),
+                (Ref(a_r, a_t, a_m), Ref(b_r, b_t, b_m)) => {
+                    a_r.cmp(b_r).then_with(|| a_t.cmp(b_t).then_with(|| a_m.cmp(b_m)))
                 }
-                (&FnPtr(ref __self_0), &FnPtr(ref __arg_1_0)) => Ord::cmp(__self_0, __arg_1_0),
-                (
-                    &Dynamic(ref __self_0, ref __self_1, ref self_repr),
-                    &Dynamic(ref __arg_1_0, ref __arg_1_1, ref arg_repr),
-                ) => match Ord::cmp(__self_0, __arg_1_0) {
-                    Ordering::Equal => match Ord::cmp(__self_1, __arg_1_1) {
-                        Ordering::Equal => Ord::cmp(self_repr, arg_repr),
-                        cmp => cmp,
-                    },
-                    cmp => cmp,
-                },
-                (&Closure(ref __self_0, ref __self_1), &Closure(ref __arg_1_0, ref __arg_1_1)) => {
-                    match Ord::cmp(__self_0, __arg_1_0) {
-                        Ordering::Equal => Ord::cmp(__self_1, __arg_1_1),
-                        cmp => cmp,
-                    }
+                (FnDef(a_d, a_s), FnDef(b_d, b_s)) => a_d.cmp(b_d).then_with(|| a_s.cmp(b_s)),
+                (FnPtr(a_s), FnPtr(b_s)) => a_s.cmp(b_s),
+                (Dynamic(a_p, a_r, a_repr), Dynamic(b_p, b_r, b_repr)) => {
+                    a_p.cmp(b_p).then_with(|| a_r.cmp(b_r).then_with(|| a_repr.cmp(b_repr)))
                 }
-                (
-                    &Generator(ref __self_0, ref __self_1, ref __self_2),
-                    &Generator(ref __arg_1_0, ref __arg_1_1, ref __arg_1_2),
-                ) => match Ord::cmp(__self_0, __arg_1_0) {
-                    Ordering::Equal => match Ord::cmp(__self_1, __arg_1_1) {
-                        Ordering::Equal => Ord::cmp(__self_2, __arg_1_2),
-                        cmp => cmp,
-                    },
-                    cmp => cmp,
-                },
-                (&GeneratorWitness(ref __self_0), &GeneratorWitness(ref __arg_1_0)) => {
-                    Ord::cmp(__self_0, __arg_1_0)
+                (Closure(a_p, a_s), Closure(b_p, b_s)) => a_p.cmp(b_p).then_with(|| a_s.cmp(b_s)),
+                (Generator(a_d, a_s, a_m), Generator(b_d, b_s, b_m)) => {
+                    a_d.cmp(b_d).then_with(|| a_s.cmp(b_s).then_with(|| a_m.cmp(b_m)))
                 }
-                (&Tuple(ref __self_0), &Tuple(ref __arg_1_0)) => Ord::cmp(__self_0, __arg_1_0),
-                (&Projection(ref __self_0), &Projection(ref __arg_1_0)) => {
-                    Ord::cmp(__self_0, __arg_1_0)
+                (GeneratorWitness(a_g), GeneratorWitness(b_g)) => a_g.cmp(b_g),
+                (Tuple(a_t), Tuple(b_t)) => a_t.cmp(b_t),
+                (Projection(a_p), Projection(b_p)) => a_p.cmp(b_p),
+                (Opaque(a_d, a_s), Opaque(b_d, b_s)) => a_d.cmp(b_d).then_with(|| a_s.cmp(b_s)),
+                (Param(a_p), Param(b_p)) => a_p.cmp(b_p),
+                (Bound(a_d, a_b), Bound(b_d, b_b)) => a_d.cmp(b_d).then_with(|| a_b.cmp(b_b)),
+                (Placeholder(a_p), Placeholder(b_p)) => a_p.cmp(b_p),
+                (Infer(a_t), Infer(b_t)) => a_t.cmp(b_t),
+                (Error(a_e), Error(b_e)) => a_e.cmp(b_e),
+                (Bool, Bool) | (Char, Char) | (Str, Str) | (Never, Never) => Ordering::Equal,
+                _ => {
+                    debug_assert!(false, "This branch must be unreachable, maybe the match is missing an arm? self = self = {self:?}, other = {other:?}");
+                    Ordering::Equal
                 }
-                (&Opaque(ref __self_0, ref __self_1), &Opaque(ref __arg_1_0, ref __arg_1_1)) => {
-                    match Ord::cmp(__self_0, __arg_1_0) {
-                        Ordering::Equal => Ord::cmp(__self_1, __arg_1_1),
-                        cmp => cmp,
-                    }
-                }
-                (&Param(ref __self_0), &Param(ref __arg_1_0)) => Ord::cmp(__self_0, __arg_1_0),
-                (&Bound(ref __self_0, ref __self_1), &Bound(ref __arg_1_0, ref __arg_1_1)) => {
-                    match Ord::cmp(__self_0, __arg_1_0) {
-                        Ordering::Equal => Ord::cmp(__self_1, __arg_1_1),
-                        cmp => cmp,
-                    }
-                }
-                (&Placeholder(ref __self_0), &Placeholder(ref __arg_1_0)) => {
-                    Ord::cmp(__self_0, __arg_1_0)
-                }
-                (&Infer(ref __self_0), &Infer(ref __arg_1_0)) => Ord::cmp(__self_0, __arg_1_0),
-                (&Error(ref __self_0), &Error(ref __arg_1_0)) => Ord::cmp(__self_0, __arg_1_0),
-                _ => Ordering::Equal,
             }
-        } else {
-            Ord::cmp(&__self_vi, &__arg_1_vi)
-        }
+        })
     }
 }
 
 // This is manually implemented because a derive would require `I: Hash`
 impl<I: Interner> hash::Hash for TyKind<I> {
     fn hash<__H: hash::Hasher>(&self, state: &mut __H) -> () {
-        match (&*self,) {
-            (&Int(ref __self_0),) => {
-                hash::Hash::hash(&tykind_discriminant(self), state);
-                hash::Hash::hash(__self_0, state)
-            }
-            (&Uint(ref __self_0),) => {
-                hash::Hash::hash(&tykind_discriminant(self), state);
-                hash::Hash::hash(__self_0, state)
-            }
-            (&Float(ref __self_0),) => {
-                hash::Hash::hash(&tykind_discriminant(self), state);
-                hash::Hash::hash(__self_0, state)
-            }
-            (&Adt(ref __self_0, ref __self_1),) => {
-                hash::Hash::hash(&tykind_discriminant(self), state);
-                hash::Hash::hash(__self_0, state);
-                hash::Hash::hash(__self_1, state)
-            }
-            (&Foreign(ref __self_0),) => {
-                hash::Hash::hash(&tykind_discriminant(self), state);
-                hash::Hash::hash(__self_0, state)
-            }
-            (&Array(ref __self_0, ref __self_1),) => {
-                hash::Hash::hash(&tykind_discriminant(self), state);
-                hash::Hash::hash(__self_0, state);
-                hash::Hash::hash(__self_1, state)
-            }
-            (&Slice(ref __self_0),) => {
-                hash::Hash::hash(&tykind_discriminant(self), state);
-                hash::Hash::hash(__self_0, state)
-            }
-            (&RawPtr(ref __self_0),) => {
-                hash::Hash::hash(&tykind_discriminant(self), state);
-                hash::Hash::hash(__self_0, state)
-            }
-            (&Ref(ref __self_0, ref __self_1, ref __self_2),) => {
-                hash::Hash::hash(&tykind_discriminant(self), state);
-                hash::Hash::hash(__self_0, state);
-                hash::Hash::hash(__self_1, state);
-                hash::Hash::hash(__self_2, state)
-            }
-            (&FnDef(ref __self_0, ref __self_1),) => {
-                hash::Hash::hash(&tykind_discriminant(self), state);
-                hash::Hash::hash(__self_0, state);
-                hash::Hash::hash(__self_1, state)
-            }
-            (&FnPtr(ref __self_0),) => {
-                hash::Hash::hash(&tykind_discriminant(self), state);
-                hash::Hash::hash(__self_0, state)
-            }
-            (&Dynamic(ref __self_0, ref __self_1, ref repr),) => {
-                hash::Hash::hash(&tykind_discriminant(self), state);
-                hash::Hash::hash(__self_0, state);
-                hash::Hash::hash(__self_1, state);
-                hash::Hash::hash(repr, state)
-            }
-            (&Closure(ref __self_0, ref __self_1),) => {
-                hash::Hash::hash(&tykind_discriminant(self), state);
-                hash::Hash::hash(__self_0, state);
-                hash::Hash::hash(__self_1, state)
-            }
-            (&Generator(ref __self_0, ref __self_1, ref __self_2),) => {
-                hash::Hash::hash(&tykind_discriminant(self), state);
-                hash::Hash::hash(__self_0, state);
-                hash::Hash::hash(__self_1, state);
-                hash::Hash::hash(__self_2, state)
-            }
-            (&GeneratorWitness(ref __self_0),) => {
-                hash::Hash::hash(&tykind_discriminant(self), state);
-                hash::Hash::hash(__self_0, state)
-            }
-            (&Tuple(ref __self_0),) => {
-                hash::Hash::hash(&tykind_discriminant(self), state);
-                hash::Hash::hash(__self_0, state)
-            }
-            (&Projection(ref __self_0),) => {
-                hash::Hash::hash(&tykind_discriminant(self), state);
-                hash::Hash::hash(__self_0, state)
-            }
-            (&Opaque(ref __self_0, ref __self_1),) => {
-                hash::Hash::hash(&tykind_discriminant(self), state);
-                hash::Hash::hash(__self_0, state);
-                hash::Hash::hash(__self_1, state)
-            }
-            (&Param(ref __self_0),) => {
-                hash::Hash::hash(&tykind_discriminant(self), state);
-                hash::Hash::hash(__self_0, state)
-            }
-            (&Bound(ref __self_0, ref __self_1),) => {
-                hash::Hash::hash(&tykind_discriminant(self), state);
-                hash::Hash::hash(__self_0, state);
-                hash::Hash::hash(__self_1, state)
-            }
-            (&Placeholder(ref __self_0),) => {
-                hash::Hash::hash(&tykind_discriminant(self), state);
-                hash::Hash::hash(__self_0, state)
-            }
-            (&Infer(ref __self_0),) => {
-                hash::Hash::hash(&tykind_discriminant(self), state);
-                hash::Hash::hash(__self_0, state)
+        tykind_discriminant(self).hash(state);
+        match self {
+            Int(i) => i.hash(state),
+            Uint(u) => u.hash(state),
+            Float(f) => f.hash(state),
+            Adt(d, s) => {
+                d.hash(state);
+                s.hash(state)
+            }
+            Foreign(d) => d.hash(state),
+            Array(t, c) => {
+                t.hash(state);
+                c.hash(state)
             }
-            (&Error(ref __self_0),) => {
-                hash::Hash::hash(&tykind_discriminant(self), state);
-                hash::Hash::hash(__self_0, state)
+            Slice(t) => t.hash(state),
+            RawPtr(t) => t.hash(state),
+            Ref(r, t, m) => {
+                r.hash(state);
+                t.hash(state);
+                m.hash(state)
+            }
+            FnDef(d, s) => {
+                d.hash(state);
+                s.hash(state)
+            }
+            FnPtr(s) => s.hash(state),
+            Dynamic(p, r, repr) => {
+                p.hash(state);
+                r.hash(state);
+                repr.hash(state)
+            }
+            Closure(d, s) => {
+                d.hash(state);
+                s.hash(state)
+            }
+            Generator(d, s, m) => {
+                d.hash(state);
+                s.hash(state);
+                m.hash(state)
+            }
+            GeneratorWitness(g) => g.hash(state),
+            Tuple(t) => t.hash(state),
+            Projection(p) => p.hash(state),
+            Opaque(d, s) => {
+                d.hash(state);
+                s.hash(state)
+            }
+            Param(p) => p.hash(state),
+            Bound(d, b) => {
+                d.hash(state);
+                b.hash(state)
             }
-            _ => hash::Hash::hash(&tykind_discriminant(self), state),
+            Placeholder(p) => p.hash(state),
+            Infer(t) => t.hash(state),
+            Error(e) => e.hash(state),
+            Bool | Char | Str | Never => (),
         }
     }
 }
@@ -588,37 +464,34 @@ impl<I: Interner> hash::Hash for TyKind<I> {
 // This is manually implemented because a derive would require `I: Debug`
 impl<I: Interner> fmt::Debug for TyKind<I> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        use std::fmt::*;
         match self {
-            Bool => Formatter::write_str(f, "Bool"),
-            Char => Formatter::write_str(f, "Char"),
-            Int(f0) => Formatter::debug_tuple_field1_finish(f, "Int", f0),
-            Uint(f0) => Formatter::debug_tuple_field1_finish(f, "Uint", f0),
-            Float(f0) => Formatter::debug_tuple_field1_finish(f, "Float", f0),
-            Adt(f0, f1) => Formatter::debug_tuple_field2_finish(f, "Adt", f0, f1),
-            Foreign(f0) => Formatter::debug_tuple_field1_finish(f, "Foreign", f0),
-            Str => Formatter::write_str(f, "Str"),
-            Array(f0, f1) => Formatter::debug_tuple_field2_finish(f, "Array", f0, f1),
-            Slice(f0) => Formatter::debug_tuple_field1_finish(f, "Slice", f0),
-            RawPtr(f0) => Formatter::debug_tuple_field1_finish(f, "RawPtr", f0),
-            Ref(f0, f1, f2) => Formatter::debug_tuple_field3_finish(f, "Ref", f0, f1, f2),
-            FnDef(f0, f1) => Formatter::debug_tuple_field2_finish(f, "FnDef", f0, f1),
-            FnPtr(f0) => Formatter::debug_tuple_field1_finish(f, "FnPtr", f0),
-            Dynamic(f0, f1, f2) => Formatter::debug_tuple_field3_finish(f, "Dynamic", f0, f1, f2),
-            Closure(f0, f1) => Formatter::debug_tuple_field2_finish(f, "Closure", f0, f1),
-            Generator(f0, f1, f2) => {
-                Formatter::debug_tuple_field3_finish(f, "Generator", f0, f1, f2)
-            }
-            GeneratorWitness(f0) => Formatter::debug_tuple_field1_finish(f, "GeneratorWitness", f0),
-            Never => Formatter::write_str(f, "Never"),
-            Tuple(f0) => Formatter::debug_tuple_field1_finish(f, "Tuple", f0),
-            Projection(f0) => Formatter::debug_tuple_field1_finish(f, "Projection", f0),
-            Opaque(f0, f1) => Formatter::debug_tuple_field2_finish(f, "Opaque", f0, f1),
-            Param(f0) => Formatter::debug_tuple_field1_finish(f, "Param", f0),
-            Bound(f0, f1) => Formatter::debug_tuple_field2_finish(f, "Bound", f0, f1),
-            Placeholder(f0) => Formatter::debug_tuple_field1_finish(f, "Placeholder", f0),
-            Infer(f0) => Formatter::debug_tuple_field1_finish(f, "Infer", f0),
-            TyKind::Error(f0) => Formatter::debug_tuple_field1_finish(f, "Error", f0),
+            Bool => f.write_str("Bool"),
+            Char => f.write_str("Char"),
+            Int(i) => f.debug_tuple_field1_finish("Int", i),
+            Uint(u) => f.debug_tuple_field1_finish("Uint", u),
+            Float(float) => f.debug_tuple_field1_finish("Float", float),
+            Adt(d, s) => f.debug_tuple_field2_finish("Adt", d, s),
+            Foreign(d) => f.debug_tuple_field1_finish("Foreign", d),
+            Str => f.write_str("Str"),
+            Array(t, c) => f.debug_tuple_field2_finish("Array", t, c),
+            Slice(t) => f.debug_tuple_field1_finish("Slice", t),
+            RawPtr(t) => f.debug_tuple_field1_finish("RawPtr", t),
+            Ref(r, t, m) => f.debug_tuple_field3_finish("Ref", r, t, m),
+            FnDef(d, s) => f.debug_tuple_field2_finish("FnDef", d, s),
+            FnPtr(s) => f.debug_tuple_field1_finish("FnPtr", s),
+            Dynamic(p, r, repr) => f.debug_tuple_field3_finish("Dynamic", p, r, repr),
+            Closure(d, s) => f.debug_tuple_field2_finish("Closure", d, s),
+            Generator(d, s, m) => f.debug_tuple_field3_finish("Generator", d, s, m),
+            GeneratorWitness(g) => f.debug_tuple_field1_finish("GeneratorWitness", g),
+            Never => f.write_str("Never"),
+            Tuple(t) => f.debug_tuple_field1_finish("Tuple", t),
+            Projection(p) => f.debug_tuple_field1_finish("Projection", p),
+            Opaque(d, s) => f.debug_tuple_field2_finish("Opaque", d, s),
+            Param(p) => f.debug_tuple_field1_finish("Param", p),
+            Bound(d, b) => f.debug_tuple_field2_finish("Bound", d, b),
+            Placeholder(p) => f.debug_tuple_field1_finish("Placeholder", p),
+            Infer(t) => f.debug_tuple_field1_finish("Infer", t),
+            TyKind::Error(e) => f.debug_tuple_field1_finish("Error", e),
         }
     }
 }
@@ -1091,12 +964,12 @@ where
 impl<I: Interner> Clone for RegionKind<I> {
     fn clone(&self) -> Self {
         match self {
-            ReEarlyBound(a) => ReEarlyBound(a.clone()),
-            ReLateBound(a, b) => ReLateBound(a.clone(), b.clone()),
-            ReFree(a) => ReFree(a.clone()),
+            ReEarlyBound(r) => ReEarlyBound(r.clone()),
+            ReLateBound(d, r) => ReLateBound(d.clone(), r.clone()),
+            ReFree(r) => ReFree(r.clone()),
             ReStatic => ReStatic,
-            ReVar(a) => ReVar(a.clone()),
-            RePlaceholder(a) => RePlaceholder(a.clone()),
+            ReVar(r) => ReVar(r.clone()),
+            RePlaceholder(r) => RePlaceholder(r.clone()),
             ReErased => ReErased,
         }
     }
@@ -1106,29 +979,23 @@ impl<I: Interner> Clone for RegionKind<I> {
 impl<I: Interner> PartialEq for RegionKind<I> {
     #[inline]
     fn eq(&self, other: &RegionKind<I>) -> bool {
-        let __self_vi = regionkind_discriminant(self);
-        let __arg_1_vi = regionkind_discriminant(other);
-        if __self_vi == __arg_1_vi {
-            match (&*self, &*other) {
-                (&ReEarlyBound(ref __self_0), &ReEarlyBound(ref __arg_1_0)) => {
-                    __self_0 == __arg_1_0
+        regionkind_discriminant(self) == regionkind_discriminant(other)
+            && match (self, other) {
+                (ReEarlyBound(a_r), ReEarlyBound(b_r)) => a_r == b_r,
+                (ReLateBound(a_d, a_r), ReLateBound(b_d, b_r)) => a_d == b_d && a_r == b_r,
+                (ReFree(a_r), ReFree(b_r)) => a_r == b_r,
+                (ReStatic, ReStatic) => true,
+                (ReVar(a_r), ReVar(b_r)) => a_r == b_r,
+                (RePlaceholder(a_r), RePlaceholder(b_r)) => a_r == b_r,
+                (ReErased, ReErased) => true,
+                _ => {
+                    debug_assert!(
+                        false,
+                        "This branch must be unreachable, maybe the match is missing an arm? self = self = {self:?}, other = {other:?}"
+                    );
+                    true
                 }
-                (
-                    &ReLateBound(ref __self_0, ref __self_1),
-                    &ReLateBound(ref __arg_1_0, ref __arg_1_1),
-                ) => __self_0 == __arg_1_0 && __self_1 == __arg_1_1,
-                (&ReFree(ref __self_0), &ReFree(ref __arg_1_0)) => __self_0 == __arg_1_0,
-                (&ReStatic, &ReStatic) => true,
-                (&ReVar(ref __self_0), &ReVar(ref __arg_1_0)) => __self_0 == __arg_1_0,
-                (&RePlaceholder(ref __self_0), &RePlaceholder(ref __arg_1_0)) => {
-                    __self_0 == __arg_1_0
-                }
-                (&ReErased, &ReErased) => true,
-                _ => true,
             }
-        } else {
-            false
-        }
     }
 }
 
@@ -1139,7 +1006,7 @@ impl<I: Interner> Eq for RegionKind<I> {}
 impl<I: Interner> PartialOrd for RegionKind<I> {
     #[inline]
     fn partial_cmp(&self, other: &RegionKind<I>) -> Option<Ordering> {
-        Some(Ord::cmp(self, other))
+        Some(self.cmp(other))
     }
 }
 
@@ -1147,66 +1014,41 @@ impl<I: Interner> PartialOrd for RegionKind<I> {
 impl<I: Interner> Ord for RegionKind<I> {
     #[inline]
     fn cmp(&self, other: &RegionKind<I>) -> Ordering {
-        let __self_vi = regionkind_discriminant(self);
-        let __arg_1_vi = regionkind_discriminant(other);
-        if __self_vi == __arg_1_vi {
-            match (&*self, &*other) {
-                (&ReEarlyBound(ref __self_0), &ReEarlyBound(ref __arg_1_0)) => {
-                    Ord::cmp(__self_0, __arg_1_0)
+        regionkind_discriminant(self).cmp(&regionkind_discriminant(other)).then_with(|| {
+            match (self, other) {
+                (ReEarlyBound(a_r), ReEarlyBound(b_r)) => a_r.cmp(b_r),
+                (ReLateBound(a_d, a_r), ReLateBound(b_d, b_r)) => {
+                    a_d.cmp(b_d).then_with(|| a_r.cmp(b_r))
                 }
-                (
-                    &ReLateBound(ref __self_0, ref __self_1),
-                    &ReLateBound(ref __arg_1_0, ref __arg_1_1),
-                ) => match Ord::cmp(__self_0, __arg_1_0) {
-                    Ordering::Equal => Ord::cmp(__self_1, __arg_1_1),
-                    cmp => cmp,
-                },
-                (&ReFree(ref __self_0), &ReFree(ref __arg_1_0)) => Ord::cmp(__self_0, __arg_1_0),
-                (&ReStatic, &ReStatic) => Ordering::Equal,
-                (&ReVar(ref __self_0), &ReVar(ref __arg_1_0)) => Ord::cmp(__self_0, __arg_1_0),
-                (&RePlaceholder(ref __self_0), &RePlaceholder(ref __arg_1_0)) => {
-                    Ord::cmp(__self_0, __arg_1_0)
+                (ReFree(a_r), ReFree(b_r)) => a_r.cmp(b_r),
+                (ReStatic, ReStatic) => Ordering::Equal,
+                (ReVar(a_r), ReVar(b_r)) => a_r.cmp(b_r),
+                (RePlaceholder(a_r), RePlaceholder(b_r)) => a_r.cmp(b_r),
+                (ReErased, ReErased) => Ordering::Equal,
+                _ => {
+                    debug_assert!(false, "This branch must be unreachable, maybe the match is missing an arm? self = self = {self:?}, other = {other:?}");
+                    Ordering::Equal
                 }
-                (&ReErased, &ReErased) => Ordering::Equal,
-                _ => Ordering::Equal,
             }
-        } else {
-            Ord::cmp(&__self_vi, &__arg_1_vi)
-        }
+        })
     }
 }
 
 // This is manually implemented because a derive would require `I: Hash`
 impl<I: Interner> hash::Hash for RegionKind<I> {
-    fn hash<__H: hash::Hasher>(&self, state: &mut __H) -> () {
-        match (&*self,) {
-            (&ReEarlyBound(ref __self_0),) => {
-                hash::Hash::hash(&regionkind_discriminant(self), state);
-                hash::Hash::hash(__self_0, state)
-            }
-            (&ReLateBound(ref __self_0, ref __self_1),) => {
-                hash::Hash::hash(&regionkind_discriminant(self), state);
-                hash::Hash::hash(__self_0, state);
-                hash::Hash::hash(__self_1, state)
-            }
-            (&ReFree(ref __self_0),) => {
-                hash::Hash::hash(&regionkind_discriminant(self), state);
-                hash::Hash::hash(__self_0, state)
-            }
-            (&ReStatic,) => {
-                hash::Hash::hash(&regionkind_discriminant(self), state);
-            }
-            (&ReVar(ref __self_0),) => {
-                hash::Hash::hash(&regionkind_discriminant(self), state);
-                hash::Hash::hash(__self_0, state)
-            }
-            (&RePlaceholder(ref __self_0),) => {
-                hash::Hash::hash(&regionkind_discriminant(self), state);
-                hash::Hash::hash(__self_0, state)
-            }
-            (&ReErased,) => {
-                hash::Hash::hash(&regionkind_discriminant(self), state);
-            }
+    fn hash<H: hash::Hasher>(&self, state: &mut H) -> () {
+        regionkind_discriminant(self).hash(state);
+        match self {
+            ReEarlyBound(r) => r.hash(state),
+            ReLateBound(d, r) => {
+                d.hash(state);
+                r.hash(state)
+            }
+            ReFree(r) => r.hash(state),
+            ReStatic => (),
+            ReVar(r) => r.hash(state),
+            RePlaceholder(r) => r.hash(state),
+            ReErased => (),
         }
     }
 }
@@ -1215,21 +1057,21 @@ impl<I: Interner> hash::Hash for RegionKind<I> {
 impl<I: Interner> fmt::Debug for RegionKind<I> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match self {
-            ReEarlyBound(ref data) => write!(f, "ReEarlyBound({:?})", data),
+            ReEarlyBound(data) => write!(f, "ReEarlyBound({:?})", data),
 
-            ReLateBound(binder_id, ref bound_region) => {
+            ReLateBound(binder_id, bound_region) => {
                 write!(f, "ReLateBound({:?}, {:?})", binder_id, bound_region)
             }
 
-            ReFree(ref fr) => fr.fmt(f),
+            ReFree(fr) => fr.fmt(f),
 
-            ReStatic => write!(f, "ReStatic"),
+            ReStatic => f.write_str("ReStatic"),
 
-            ReVar(ref vid) => vid.fmt(f),
+            ReVar(vid) => vid.fmt(f),
 
             RePlaceholder(placeholder) => write!(f, "RePlaceholder({:?})", placeholder),
 
-            ReErased => write!(f, "ReErased"),
+            ReErased => f.write_str("ReErased"),
         }
     }
 }
@@ -1317,18 +1159,18 @@ where
             ReErased | ReStatic => {
                 // No variant fields to hash for these ...
             }
-            ReLateBound(db, br) => {
-                db.hash_stable(hcx, hasher);
-                br.hash_stable(hcx, hasher);
+            ReLateBound(d, r) => {
+                d.hash_stable(hcx, hasher);
+                r.hash_stable(hcx, hasher);
             }
-            ReEarlyBound(eb) => {
-                eb.hash_stable(hcx, hasher);
+            ReEarlyBound(r) => {
+                r.hash_stable(hcx, hasher);
             }
-            ReFree(ref free_region) => {
-                free_region.hash_stable(hcx, hasher);
+            ReFree(r) => {
+                r.hash_stable(hcx, hasher);
             }
-            RePlaceholder(p) => {
-                p.hash_stable(hcx, hasher);
+            RePlaceholder(r) => {
+                r.hash_stable(hcx, hasher);
             }
             ReVar(_) => {
                 panic!("region variables should not be hashed: {self:?}")
diff --git a/compiler/rustc_type_ir/src/ty_info.rs b/compiler/rustc_type_ir/src/ty_info.rs
new file mode 100644
index 00000000000..4e5d424886a
--- /dev/null
+++ b/compiler/rustc_type_ir/src/ty_info.rs
@@ -0,0 +1,122 @@
+use std::{
+    cmp::Ordering,
+    hash::{Hash, Hasher},
+    ops::Deref,
+};
+
+use rustc_data_structures::{
+    fingerprint::Fingerprint,
+    stable_hasher::{HashStable, StableHasher},
+};
+
+use crate::{DebruijnIndex, TypeFlags};
+
+/// A helper type that you can wrap round your own type in order to automatically
+/// cache the stable hash, type flags and debruijn index on creation and
+/// not recompute it whenever the information is needed.
+/// This is only done in incremental mode. You can also opt out of caching by using
+/// StableHash::ZERO for the hash, in which case the hash gets computed each time.
+/// This is useful if you have values that you intern but never (can?) use for stable
+/// hashing.
+#[derive(Copy, Clone)]
+pub struct WithCachedTypeInfo<T> {
+    pub internee: T,
+    pub stable_hash: Fingerprint,
+
+    /// This field provides fast access to information that is also contained
+    /// in `kind`.
+    ///
+    /// This field shouldn't be used directly and may be removed in the future.
+    /// Use `Ty::flags()` instead.
+    pub flags: TypeFlags,
+
+    /// This field provides fast access to information that is also contained
+    /// in `kind`.
+    ///
+    /// This is a kind of confusing thing: it stores the smallest
+    /// binder such that
+    ///
+    /// (a) the binder itself captures nothing but
+    /// (b) all the late-bound things within the type are captured
+    ///     by some sub-binder.
+    ///
+    /// So, for a type without any late-bound things, like `u32`, this
+    /// will be *innermost*, because that is the innermost binder that
+    /// captures nothing. But for a type `&'D u32`, where `'D` is a
+    /// late-bound region with De Bruijn index `D`, this would be `D + 1`
+    /// -- the binder itself does not capture `D`, but `D` is captured
+    /// by an inner binder.
+    ///
+    /// We call this concept an "exclusive" binder `D` because all
+    /// De Bruijn indices within the type are contained within `0..D`
+    /// (exclusive).
+    pub outer_exclusive_binder: DebruijnIndex,
+}
+
+impl<T: PartialEq> PartialEq for WithCachedTypeInfo<T> {
+    #[inline]
+    fn eq(&self, other: &Self) -> bool {
+        self.internee.eq(&other.internee)
+    }
+}
+
+impl<T: Eq> Eq for WithCachedTypeInfo<T> {}
+
+impl<T: Ord> PartialOrd for WithCachedTypeInfo<T> {
+    fn partial_cmp(&self, other: &WithCachedTypeInfo<T>) -> Option<Ordering> {
+        Some(self.internee.cmp(&other.internee))
+    }
+}
+
+impl<T: Ord> Ord for WithCachedTypeInfo<T> {
+    fn cmp(&self, other: &WithCachedTypeInfo<T>) -> Ordering {
+        self.internee.cmp(&other.internee)
+    }
+}
+
+impl<T> Deref for WithCachedTypeInfo<T> {
+    type Target = T;
+
+    #[inline]
+    fn deref(&self) -> &T {
+        &self.internee
+    }
+}
+
+impl<T: Hash> Hash for WithCachedTypeInfo<T> {
+    #[inline]
+    fn hash<H: Hasher>(&self, s: &mut H) {
+        if self.stable_hash != Fingerprint::ZERO {
+            self.stable_hash.hash(s)
+        } else {
+            self.internee.hash(s)
+        }
+    }
+}
+
+impl<T: HashStable<CTX>, CTX> HashStable<CTX> for WithCachedTypeInfo<T> {
+    fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
+        if self.stable_hash == Fingerprint::ZERO || cfg!(debug_assertions) {
+            // No cached hash available. This can only mean that incremental is disabled.
+            // We don't cache stable hashes in non-incremental mode, because they are used
+            // so rarely that the performance actually suffers.
+
+            // We need to build the hash as if we cached it and then hash that hash, as
+            // otherwise the hashes will differ between cached and non-cached mode.
+            let stable_hash: Fingerprint = {
+                let mut hasher = StableHasher::new();
+                self.internee.hash_stable(hcx, &mut hasher);
+                hasher.finish()
+            };
+            if cfg!(debug_assertions) && self.stable_hash != Fingerprint::ZERO {
+                assert_eq!(
+                    stable_hash, self.stable_hash,
+                    "cached stable hash does not match freshly computed stable hash"
+                );
+            }
+            stable_hash.hash_stable(hcx, hasher);
+        } else {
+            self.stable_hash.hash_stable(hcx, hasher);
+        }
+    }
+}
diff --git a/config.toml.example b/config.toml.example
index c94a27b12a3..ca54cbd2d68 100644
--- a/config.toml.example
+++ b/config.toml.example
@@ -255,6 +255,16 @@ changelog-seen = 2
 # Defaults to the Python interpreter used to execute x.py
 #python = "python"
 
+# The path to the REUSE executable to use. Note that REUSE is not required in
+# most cases, as our tooling relies on a cached (and shrinked) copy of the
+# REUSE output present in the git repository and in our source tarballs.
+#
+# REUSE is only needed if your changes caused the overral licensing of the
+# repository to change, and the cached copy has to be regenerated.
+#
+# Defaults to the "reuse" command in the system path.
+#reuse = "reuse"
+
 # Force Cargo to check that Cargo.lock describes the precise dependency
 # set that all the Cargo.toml files create, instead of updating it.
 #locked-deps = false
diff --git a/library/core/src/cmp.rs b/library/core/src/cmp.rs
index 5db5cbfc3df..949896e5748 100644
--- a/library/core/src/cmp.rs
+++ b/library/core/src/cmp.rs
@@ -29,8 +29,7 @@ use crate::marker::StructuralPartialEq;
 
 use self::Ordering::*;
 
-/// Trait for equality comparisons which are [partial equivalence
-/// relations](https://en.wikipedia.org/wiki/Partial_equivalence_relation).
+/// Trait for equality comparisons.
 ///
 /// `x.eq(y)` can also be written `x == y`, and `x.ne(y)` can be written `x != y`.
 /// We use the easier-to-read infix notation in the remainder of this documentation.
@@ -38,6 +37,8 @@ use self::Ordering::*;
 /// This trait allows for partial equality, for types that do not have a full
 /// equivalence relation. For example, in floating point numbers `NaN != NaN`,
 /// so floating point types implement `PartialEq` but not [`trait@Eq`].
+/// Formally speaking, when `Rhs == Self`, this trait corresponds to a [partial equivalence
+/// relation](https://en.wikipedia.org/wiki/Partial_equivalence_relation).
 ///
 /// Implementations must ensure that `eq` and `ne` are consistent with each other:
 ///
diff --git a/library/core/src/convert/num.rs b/library/core/src/convert/num.rs
index 4fa5d129bc6..9c0d7e9a1e8 100644
--- a/library/core/src/convert/num.rs
+++ b/library/core/src/convert/num.rs
@@ -49,7 +49,7 @@ macro_rules! impl_from {
             // Rustdocs on the impl block show a "[+] show undocumented items" toggle.
             // Rustdocs on functions do not.
             #[doc = $doc]
-            #[inline]
+            #[inline(always)]
             fn from(small: $Small) -> Self {
                 small as Self
             }
diff --git a/library/core/src/future/mod.rs b/library/core/src/future/mod.rs
index f2b961d62e0..2a8e12fd4cf 100644
--- a/library/core/src/future/mod.rs
+++ b/library/core/src/future/mod.rs
@@ -44,7 +44,7 @@ pub use poll_fn::{poll_fn, PollFn};
 ///    non-Send/Sync as well, and we don't want that.
 ///
 /// It also simplifies the HIR lowering of `.await`.
-#[cfg_attr(not(bootstrap), lang = "ResumeTy")]
+// FIXME(swatinem): This type can be removed when bumping the bootstrap compiler
 #[doc(hidden)]
 #[unstable(feature = "gen_future", issue = "50547")]
 #[derive(Debug, Copy, Clone)]
@@ -61,6 +61,7 @@ unsafe impl Sync for ResumeTy {}
 /// This function returns a `GenFuture` underneath, but hides it in `impl Trait` to give
 /// better error messages (`impl Future` rather than `GenFuture<[closure.....]>`).
 // This is `const` to avoid extra errors after we recover from `const async fn`
+// FIXME(swatinem): This fn can be removed when bumping the bootstrap compiler
 #[cfg_attr(bootstrap, lang = "from_generator")]
 #[doc(hidden)]
 #[unstable(feature = "gen_future", issue = "50547")]
@@ -102,7 +103,8 @@ where
     GenFuture(gen)
 }
 
-#[lang = "get_context"]
+// FIXME(swatinem): This fn can be removed when bumping the bootstrap compiler
+#[cfg_attr(bootstrap, lang = "get_context")]
 #[doc(hidden)]
 #[unstable(feature = "gen_future", issue = "50547")]
 #[must_use]
@@ -113,6 +115,10 @@ pub unsafe fn get_context<'a, 'b>(cx: ResumeTy) -> &'a mut Context<'b> {
     unsafe { &mut *cx.0.as_ptr().cast() }
 }
 
+// FIXME(swatinem): This fn is currently needed to work around shortcomings
+// in type and lifetime inference.
+// See the comment at the bottom of `LoweringContext::make_async_expr` and
+// <https://github.com/rust-lang/rust/issues/104826>.
 #[cfg_attr(not(bootstrap), lang = "identity_future")]
 #[doc(hidden)]
 #[unstable(feature = "gen_future", issue = "50547")]
diff --git a/library/core/src/iter/sources/repeat_n.rs b/library/core/src/iter/sources/repeat_n.rs
index dc69bf4df59..fd8d25ce1a5 100644
--- a/library/core/src/iter/sources/repeat_n.rs
+++ b/library/core/src/iter/sources/repeat_n.rs
@@ -20,7 +20,7 @@ use crate::mem::ManuallyDrop;
 /// #![feature(iter_repeat_n)]
 /// use std::iter;
 ///
-/// // four of the the number four:
+/// // four of the number four:
 /// let mut four_fours = iter::repeat_n(4, 4);
 ///
 /// assert_eq!(Some(4), four_fours.next());
diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs
index b2328b001de..ac7f579ebb5 100644
--- a/library/core/src/num/mod.rs
+++ b/library/core/src/num/mod.rs
@@ -4,12 +4,14 @@
 
 use crate::ascii;
 use crate::convert::TryInto;
-use crate::error::Error;
 use crate::intrinsics;
 use crate::mem;
 use crate::ops::{Add, Mul, Sub};
 use crate::str::FromStr;
 
+#[cfg(not(no_fp_fmt_parse))]
+use crate::error::Error;
+
 // Used because the `?` operator is not allowed in a const context.
 macro_rules! try_opt {
     ($e:expr) => {
diff --git a/library/core/src/str/pattern.rs b/library/core/src/str/pattern.rs
index d76d6f8b2a2..19da6d2fbec 100644
--- a/library/core/src/str/pattern.rs
+++ b/library/core/src/str/pattern.rs
@@ -1894,7 +1894,7 @@ unsafe fn small_slice_eq(x: &[u8], y: &[u8]) -> bool {
     // Thus, derefencing both `px` and `py` in the loop below is safe.
     //
     // Moreover, we set `pxend` and `pyend` to be 4 bytes before the actual
-    // end of of `px` and `py`. Thus, the final dereference outside of the
+    // end of `px` and `py`. Thus, the final dereference outside of the
     // loop is guaranteed to be valid. (The final comparison will overlap with
     // the last comparison done in the loop for lengths that aren't multiples
     // of four.)
diff --git a/library/core/src/task/wake.rs b/library/core/src/task/wake.rs
index 0cff972df3a..9ab9b0ba1c7 100644
--- a/library/core/src/task/wake.rs
+++ b/library/core/src/task/wake.rs
@@ -174,6 +174,7 @@ impl RawWakerVTable {
 /// Currently, `Context` only serves to provide access to a [`&Waker`](Waker)
 /// which can be used to wake the current task.
 #[stable(feature = "futures_api", since = "1.36.0")]
+#[cfg_attr(not(bootstrap), lang = "Context")]
 pub struct Context<'a> {
     waker: &'a Waker,
     // Ensure we future-proof against variance changes by forcing
diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml
index c10bfde4ddf..a7aefc26b97 100644
--- a/library/std/Cargo.toml
+++ b/library/std/Cargo.toml
@@ -15,7 +15,7 @@ cfg-if = { version = "1.0", features = ['rustc-dep-of-std'] }
 panic_unwind = { path = "../panic_unwind", optional = true }
 panic_abort = { path = "../panic_abort" }
 core = { path = "../core" }
-libc = { version = "0.2.135", default-features = false, features = ['rustc-dep-of-std'] }
+libc = { version = "0.2.138", default-features = false, features = ['rustc-dep-of-std'] }
 compiler_builtins = { version = "0.1.82" }
 profiler_builtins = { path = "../profiler_builtins", optional = true }
 unwind = { path = "../unwind" }
diff --git a/library/std/src/sync/mpmc/array.rs b/library/std/src/sync/mpmc/array.rs
index 4db7b4990b9..f71edc6c525 100644
--- a/library/std/src/sync/mpmc/array.rs
+++ b/library/std/src/sync/mpmc/array.rs
@@ -225,7 +225,7 @@ impl<T> Channel<T> {
             let slot = unsafe { self.buffer.get_unchecked(index) };
             let stamp = slot.stamp.load(Ordering::Acquire);
 
-            // If the the stamp is ahead of the head by 1, we may attempt to pop.
+            // If the stamp is ahead of the head by 1, we may attempt to pop.
             if head + 1 == stamp {
                 let new = if index + 1 < self.cap {
                     // Same lap, incremented index.
diff --git a/library/std/src/sync/mpsc/mod.rs b/library/std/src/sync/mpsc/mod.rs
index 27fba761ada..adb488d4378 100644
--- a/library/std/src/sync/mpsc/mod.rs
+++ b/library/std/src/sync/mpsc/mod.rs
@@ -629,9 +629,7 @@ impl<T> Clone for Sender<T> {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T> Drop for Sender<T> {
-    fn drop(&mut self) {
-        let _ = self.inner;
-    }
+    fn drop(&mut self) {}
 }
 
 #[stable(feature = "mpsc_debug", since = "1.8.0")]
@@ -751,9 +749,7 @@ impl<T> Clone for SyncSender<T> {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T> Drop for SyncSender<T> {
-    fn drop(&mut self) {
-        let _ = self.inner;
-    }
+    fn drop(&mut self) {}
 }
 
 #[stable(feature = "mpsc_debug", since = "1.8.0")]
@@ -1094,9 +1090,7 @@ impl<T> IntoIterator for Receiver<T> {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T> Drop for Receiver<T> {
-    fn drop(&mut self) {
-        let _ = self.inner;
-    }
+    fn drop(&mut self) {}
 }
 
 #[stable(feature = "mpsc_debug", since = "1.8.0")]
diff --git a/library/std/src/sys/itron/condvar.rs b/library/std/src/sys/itron/condvar.rs
index f70aa434e48..7a47cc6696a 100644
--- a/library/std/src/sys/itron/condvar.rs
+++ b/library/std/src/sys/itron/condvar.rs
@@ -71,7 +71,7 @@ impl Condvar {
             }
         }
 
-        unsafe { mutex.lock() };
+        mutex.lock();
     }
 
     pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool {
@@ -109,7 +109,7 @@ impl Condvar {
         // we woke up because of `notify_*`.
         let success = self.waiters.with_locked(|waiters| unsafe { !waiters.remove(waiter) });
 
-        unsafe { mutex.lock() };
+        mutex.lock();
         success
     }
 }
diff --git a/library/std/src/sys/itron/mutex.rs b/library/std/src/sys/itron/mutex.rs
index f2eed8e771c..1f6cc419476 100644
--- a/library/std/src/sys/itron/mutex.rs
+++ b/library/std/src/sys/itron/mutex.rs
@@ -72,7 +72,7 @@ pub(super) struct MutexGuard<'a>(&'a Mutex);
 impl<'a> MutexGuard<'a> {
     #[inline]
     pub(super) fn lock(x: &'a Mutex) -> Self {
-        unsafe { x.lock() };
+        x.lock();
         Self(x)
     }
 }
diff --git a/library/std/src/sys/itron/thread.rs b/library/std/src/sys/itron/thread.rs
index d28f57f33be..c2b36680872 100644
--- a/library/std/src/sys/itron/thread.rs
+++ b/library/std/src/sys/itron/thread.rs
@@ -11,18 +11,25 @@ use crate::{
     ffi::CStr,
     hint, io,
     mem::ManuallyDrop,
+    ptr::NonNull,
     sync::atomic::{AtomicUsize, Ordering},
     sys::thread_local_dtor::run_dtors,
     time::Duration,
 };
 
 pub struct Thread {
-    inner: ManuallyDrop<Box<ThreadInner>>,
+    p_inner: NonNull<ThreadInner>,
 
     /// The ID of the underlying task.
     task: abi::ID,
 }
 
+// Safety: There's nothing in `Thread` that ties it to the original creator. It
+//         can be dropped by any threads.
+unsafe impl Send for Thread {}
+// Safety: `Thread` provides no methods that take `&self`.
+unsafe impl Sync for Thread {}
+
 /// State data shared between a parent thread and child thread. It's dropped on
 /// a transition to one of the final states.
 struct ThreadInner {
@@ -90,8 +97,9 @@ impl Thread {
         });
 
         unsafe extern "C" fn trampoline(exinf: isize) {
+            let p_inner: *mut ThreadInner = crate::ptr::from_exposed_addr_mut(exinf as usize);
             // Safety: `ThreadInner` is alive at this point
-            let inner = unsafe { &*(exinf as *const ThreadInner) };
+            let inner = unsafe { &*p_inner };
 
             // Safety: Since `trampoline` is called only once for each
             //         `ThreadInner` and only `trampoline` touches `start`,
@@ -119,13 +127,13 @@ impl Thread {
                     // No one will ever join, so we'll ask the collector task to
                     // delete the task.
 
-                    // In this case, `inner`'s ownership has been moved to us,
-                    // And we are responsible for dropping it. The acquire
+                    // In this case, `*p_inner`'s ownership has been moved to
+                    // us, and we are responsible for dropping it. The acquire
                     // ordering is not necessary because the parent thread made
                     // no memory access needing synchronization since the call
                     // to `acre_tsk`.
                     // Safety: See above.
-                    let _ = unsafe { Box::from_raw(inner as *const _ as *mut ThreadInner) };
+                    let _ = unsafe { Box::from_raw(p_inner) };
 
                     // Safety: There are no pinned references to the stack
                     unsafe { terminate_and_delete_current_task() };
@@ -162,13 +170,14 @@ impl Thread {
             }
         }
 
-        let inner_ptr = (&*inner) as *const ThreadInner;
+        // Safety: `Box::into_raw` returns a non-null pointer
+        let p_inner = unsafe { NonNull::new_unchecked(Box::into_raw(inner)) };
 
         let new_task = ItronError::err_if_negative(unsafe {
             abi::acre_tsk(&abi::T_CTSK {
                 // Activate this task immediately
                 tskatr: abi::TA_ACT,
-                exinf: inner_ptr as abi::EXINF,
+                exinf: p_inner.as_ptr().expose_addr() as abi::EXINF,
                 // The entry point
                 task: Some(trampoline),
                 // Inherit the calling task's base priority
@@ -180,7 +189,7 @@ impl Thread {
         })
         .map_err(|e| e.as_io_error())?;
 
-        Ok(Self { inner: ManuallyDrop::new(inner), task: new_task })
+        Ok(Self { p_inner, task: new_task })
     }
 
     pub fn yield_now() {
@@ -197,8 +206,9 @@ impl Thread {
         }
     }
 
-    pub fn join(mut self) {
-        let inner = &*self.inner;
+    pub fn join(self) {
+        // Safety: `ThreadInner` is alive at this point
+        let inner = unsafe { self.p_inner.as_ref() };
         // Get the current task ID. Panicking here would cause a resource leak,
         // so just abort on failure.
         let current_task = task::current_task_id_aborting();
@@ -243,8 +253,8 @@ impl Thread {
         unsafe { terminate_and_delete_task(self.task) };
 
         // In either case, we are responsible for dropping `inner`.
-        // Safety: The contents of `self.inner` will not be accessed hereafter
-        let _inner = unsafe { ManuallyDrop::take(&mut self.inner) };
+        // Safety: The contents of `*p_inner` will not be accessed hereafter
+        let _inner = unsafe { Box::from_raw(self.p_inner.as_ptr()) };
 
         // Skip the destructor (because it would attempt to detach the thread)
         crate::mem::forget(self);
@@ -253,13 +263,16 @@ impl Thread {
 
 impl Drop for Thread {
     fn drop(&mut self) {
+        // Safety: `ThreadInner` is alive at this point
+        let inner = unsafe { self.p_inner.as_ref() };
+
         // Detach the thread.
-        match self.inner.lifecycle.swap(LIFECYCLE_DETACHED_OR_JOINED, Ordering::Acquire) {
+        match inner.lifecycle.swap(LIFECYCLE_DETACHED_OR_JOINED, Ordering::Acquire) {
             LIFECYCLE_INIT => {
                 // [INIT → DETACHED]
                 // When the time comes, the child will figure out that no
                 // one will ever join it.
-                // The ownership of `self.inner` is moved to the child thread.
+                // The ownership of `*p_inner` is moved to the child thread.
                 // However, the release ordering is not necessary because we
                 // made no memory access needing synchronization since the call
                 // to `acre_tsk`.
@@ -278,10 +291,9 @@ impl Drop for Thread {
                 //         delete by entering the `FINISHED` state.
                 unsafe { terminate_and_delete_task(self.task) };
 
-                // Wwe are responsible for dropping `inner`.
-                // Safety: The contents of `self.inner` will not be accessed
-                //         hereafter
-                unsafe { ManuallyDrop::drop(&mut self.inner) };
+                // Wwe are responsible for dropping `*p_inner`.
+                // Safety: The contents of `*p_inner` will not be accessed hereafter
+                let _ = unsafe { Box::from_raw(self.p_inner.as_ptr()) };
             }
             _ => unsafe { hint::unreachable_unchecked() },
         }
diff --git a/library/std/src/sys/solid/io.rs b/library/std/src/sys/solid/io.rs
index 9eb17a10daa..a862bb78702 100644
--- a/library/std/src/sys/solid/io.rs
+++ b/library/std/src/sys/solid/io.rs
@@ -75,3 +75,7 @@ impl<'a> IoSliceMut<'a> {
         unsafe { slice::from_raw_parts_mut(self.vec.iov_base as *mut u8, self.vec.iov_len) }
     }
 }
+
+pub fn is_terminal<T>(_: &T) -> bool {
+    false
+}
diff --git a/library/std/src/sys/solid/os.rs b/library/std/src/sys/solid/os.rs
index 4906c62689d..6135921f0b5 100644
--- a/library/std/src/sys/solid/os.rs
+++ b/library/std/src/sys/solid/os.rs
@@ -1,7 +1,6 @@
 use super::unsupported;
-use crate::convert::TryFrom;
 use crate::error::Error as StdError;
-use crate::ffi::{CStr, CString, OsStr, OsString};
+use crate::ffi::{CStr, OsStr, OsString};
 use crate::fmt;
 use crate::io;
 use crate::os::{
diff --git a/library/std/src/sys/unix/weak.rs b/library/std/src/sys/unix/weak.rs
index e4ff21b25bd..f5a4ce929b2 100644
--- a/library/std/src/sys/unix/weak.rs
+++ b/library/std/src/sys/unix/weak.rs
@@ -29,7 +29,21 @@ use crate::ptr;
 use crate::sync::atomic::{self, AtomicPtr, Ordering};
 
 // We can use true weak linkage on ELF targets.
-#[cfg(not(any(target_os = "macos", target_os = "ios")))]
+#[cfg(all(not(any(target_os = "macos", target_os = "ios")), not(bootstrap)))]
+pub(crate) macro weak {
+    (fn $name:ident($($t:ty),*) -> $ret:ty) => (
+        let ref $name: ExternWeak<unsafe extern "C" fn($($t),*) -> $ret> = {
+            extern "C" {
+                #[linkage = "extern_weak"]
+                static $name: Option<unsafe extern "C" fn($($t),*) -> $ret>;
+            }
+            #[allow(unused_unsafe)]
+            ExternWeak::new(unsafe { $name })
+        };
+    )
+}
+
+#[cfg(all(not(any(target_os = "macos", target_os = "ios")), bootstrap))]
 pub(crate) macro weak {
     (fn $name:ident($($t:ty),*) -> $ret:ty) => (
         let ref $name: ExternWeak<unsafe extern "C" fn($($t),*) -> $ret> = {
@@ -47,11 +61,31 @@ pub(crate) macro weak {
 #[cfg(any(target_os = "macos", target_os = "ios"))]
 pub(crate) use self::dlsym as weak;
 
+#[cfg(not(bootstrap))]
+pub(crate) struct ExternWeak<F: Copy> {
+    weak_ptr: Option<F>,
+}
+
+#[cfg(not(bootstrap))]
+impl<F: Copy> ExternWeak<F> {
+    #[inline]
+    pub(crate) fn new(weak_ptr: Option<F>) -> Self {
+        ExternWeak { weak_ptr }
+    }
+
+    #[inline]
+    pub(crate) fn get(&self) -> Option<F> {
+        self.weak_ptr
+    }
+}
+
+#[cfg(bootstrap)]
 pub(crate) struct ExternWeak<F> {
     weak_ptr: *const libc::c_void,
     _marker: PhantomData<F>,
 }
 
+#[cfg(bootstrap)]
 impl<F> ExternWeak<F> {
     #[inline]
     pub(crate) fn new(weak_ptr: *const libc::c_void) -> Self {
@@ -59,6 +93,7 @@ impl<F> ExternWeak<F> {
     }
 }
 
+#[cfg(bootstrap)]
 impl<F> ExternWeak<F> {
     #[inline]
     pub(crate) fn get(&self) -> Option<F> {
diff --git a/library/std/src/sys/windows/process.rs b/library/std/src/sys/windows/process.rs
index 9cbb4ef19e9..31e9b34fb9e 100644
--- a/library/std/src/sys/windows/process.rs
+++ b/library/std/src/sys/windows/process.rs
@@ -252,10 +252,6 @@ impl Command {
     ) -> io::Result<(Process, StdioPipes)> {
         let maybe_env = self.env.capture_if_changed();
 
-        let mut si = zeroed_startupinfo();
-        si.cb = mem::size_of::<c::STARTUPINFO>() as c::DWORD;
-        si.dwFlags = c::STARTF_USESTDHANDLES;
-
         let child_paths = if let Some(env) = maybe_env.as_ref() {
             env.get(&EnvKey::new("PATH")).map(|s| s.as_os_str())
         } else {
@@ -314,9 +310,21 @@ impl Command {
         let stdin = stdin.to_handle(c::STD_INPUT_HANDLE, &mut pipes.stdin)?;
         let stdout = stdout.to_handle(c::STD_OUTPUT_HANDLE, &mut pipes.stdout)?;
         let stderr = stderr.to_handle(c::STD_ERROR_HANDLE, &mut pipes.stderr)?;
-        si.hStdInput = stdin.as_raw_handle();
-        si.hStdOutput = stdout.as_raw_handle();
-        si.hStdError = stderr.as_raw_handle();
+
+        let mut si = zeroed_startupinfo();
+        si.cb = mem::size_of::<c::STARTUPINFO>() as c::DWORD;
+
+        // If at least one of stdin, stdout or stderr are set (i.e. are non null)
+        // then set the `hStd` fields in `STARTUPINFO`.
+        // Otherwise skip this and allow the OS to apply its default behaviour.
+        // This provides more consistent behaviour between Win7 and Win8+.
+        let is_set = |stdio: &Handle| !stdio.as_raw_handle().is_null();
+        if is_set(&stderr) || is_set(&stdout) || is_set(&stdin) {
+            si.dwFlags |= c::STARTF_USESTDHANDLES;
+            si.hStdInput = stdin.as_raw_handle();
+            si.hStdOutput = stdout.as_raw_handle();
+            si.hStdError = stderr.as_raw_handle();
+        }
 
         unsafe {
             cvt(c::CreateProcessW(
@@ -513,9 +521,6 @@ fn program_exists(path: &Path) -> Option<Vec<u16>> {
 impl Stdio {
     fn to_handle(&self, stdio_id: c::DWORD, pipe: &mut Option<AnonPipe>) -> io::Result<Handle> {
         match *self {
-            // If no stdio handle is available, then inherit means that it
-            // should still be unavailable so propagate the
-            // INVALID_HANDLE_VALUE.
             Stdio::Inherit => match stdio::get_handle(stdio_id) {
                 Ok(io) => unsafe {
                     let io = Handle::from_raw_handle(io);
@@ -523,7 +528,8 @@ impl Stdio {
                     io.into_raw_handle();
                     ret
                 },
-                Err(..) => unsafe { Ok(Handle::from_raw_handle(c::INVALID_HANDLE_VALUE)) },
+                // If no stdio handle is available, then propagate the null value.
+                Err(..) => unsafe { Ok(Handle::from_raw_handle(ptr::null_mut())) },
             },
 
             Stdio::MakePipe => {
@@ -730,9 +736,9 @@ fn zeroed_startupinfo() -> c::STARTUPINFO {
         wShowWindow: 0,
         cbReserved2: 0,
         lpReserved2: ptr::null_mut(),
-        hStdInput: c::INVALID_HANDLE_VALUE,
-        hStdOutput: c::INVALID_HANDLE_VALUE,
-        hStdError: c::INVALID_HANDLE_VALUE,
+        hStdInput: ptr::null_mut(),
+        hStdOutput: ptr::null_mut(),
+        hStdError: ptr::null_mut(),
     }
 }
 
diff --git a/library/std/src/thread/scoped.rs b/library/std/src/thread/scoped.rs
index e6dbf35bd02..ada69aa8269 100644
--- a/library/std/src/thread/scoped.rs
+++ b/library/std/src/thread/scoped.rs
@@ -46,7 +46,7 @@ impl ScopeData {
         // We check for 'overflow' with usize::MAX / 2, to make sure there's no
         // chance it overflows to 0, which would result in unsoundness.
         if self.num_running_threads.fetch_add(1, Ordering::Relaxed) > usize::MAX / 2 {
-            // This can only reasonably happen by mem::forget()'ing many many ScopedJoinHandles.
+            // This can only reasonably happen by mem::forget()'ing a lot of ScopedJoinHandles.
             self.decrement_num_running_threads(false);
             panic!("too many running threads in thread scope");
         }
diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs
index cff5fd8c5b0..8ee6d49da8f 100644
--- a/src/bootstrap/builder.rs
+++ b/src/bootstrap/builder.rs
@@ -754,6 +754,8 @@ impl<'a> Builder<'a> {
                 run::BumpStage0,
                 run::ReplaceVersionPlaceholder,
                 run::Miri,
+                run::CollectLicenseMetadata,
+                run::GenerateCopyright,
             ),
             // These commands either don't use paths, or they're special-cased in Build::build()
             Kind::Clean | Kind::Format | Kind::Setup => vec![],
diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs
index babf09d2b93..d8c15c76e2d 100644
--- a/src/bootstrap/config.rs
+++ b/src/bootstrap/config.rs
@@ -213,6 +213,7 @@ pub struct Config {
     pub npm: Option<PathBuf>,
     pub gdb: Option<PathBuf>,
     pub python: Option<PathBuf>,
+    pub reuse: Option<PathBuf>,
     pub cargo_native_static: bool,
     pub configure_args: Vec<String>,
 
@@ -611,6 +612,7 @@ define_config! {
         nodejs: Option<String> = "nodejs",
         npm: Option<String> = "npm",
         python: Option<String> = "python",
+        reuse: Option<String> = "reuse",
         locked_deps: Option<bool> = "locked-deps",
         vendor: Option<bool> = "vendor",
         full_bootstrap: Option<bool> = "full-bootstrap",
@@ -1004,6 +1006,7 @@ impl Config {
         config.npm = build.npm.map(PathBuf::from);
         config.gdb = build.gdb.map(PathBuf::from);
         config.python = build.python.map(PathBuf::from);
+        config.reuse = build.reuse.map(PathBuf::from);
         config.submodules = build.submodules;
         set(&mut config.low_priority, build.low_priority);
         set(&mut config.compiler_docs, build.compiler_docs);
diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs
index 2001e29bd2e..37a8eb884ef 100644
--- a/src/bootstrap/flags.rs
+++ b/src/bootstrap/flags.rs
@@ -143,7 +143,7 @@ pub enum Subcommand {
         args: Vec<String>,
     },
     Setup {
-        profile: Profile,
+        profile: Option<Profile>,
     },
 }
 
@@ -628,14 +628,15 @@ Arguments:
                         |path| format!("{} is not a valid UTF8 string", path.to_string_lossy())
                     ));
 
-                    profile_string.parse().unwrap_or_else(|err| {
+                    let profile = profile_string.parse().unwrap_or_else(|err| {
                         eprintln!("error: {}", err);
                         eprintln!("help: the available profiles are:");
                         eprint!("{}", Profile::all_for_help("- "));
                         crate::detail_exit(1);
-                    })
+                    });
+                    Some(profile)
                 } else {
-                    t!(crate::setup::interactive_path())
+                    None
                 };
                 Subcommand::Setup { profile }
             }
diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs
index d69bced0b28..3ed53452309 100644
--- a/src/bootstrap/lib.rs
+++ b/src/bootstrap/lib.rs
@@ -542,16 +542,6 @@ impl Build {
             metrics: metrics::BuildMetrics::init(),
         };
 
-        build.verbose("finding compilers");
-        cc_detect::find(&mut build);
-        // When running `setup`, the profile is about to change, so any requirements we have now may
-        // be different on the next invocation. Don't check for them until the next time x.py is
-        // run. This is ok because `setup` never runs any build commands, so it won't fail if commands are missing.
-        if !matches!(build.config.cmd, Subcommand::Setup { .. }) {
-            build.verbose("running sanity check");
-            sanity::check(&mut build);
-        }
-
         // If local-rust is the same major.minor as the current version, then force a
         // local-rebuild
         let local_version_verbose =
@@ -567,16 +557,34 @@ impl Build {
             build.local_rebuild = true;
         }
 
-        // Make sure we update these before gathering metadata so we don't get an error about missing
-        // Cargo.toml files.
-        let rust_submodules =
-            ["src/tools/rust-installer", "src/tools/cargo", "library/backtrace", "library/stdarch"];
-        for s in rust_submodules {
-            build.update_submodule(Path::new(s));
-        }
+        build.verbose("finding compilers");
+        cc_detect::find(&mut build);
+        // When running `setup`, the profile is about to change, so any requirements we have now may
+        // be different on the next invocation. Don't check for them until the next time x.py is
+        // run. This is ok because `setup` never runs any build commands, so it won't fail if commands are missing.
+        //
+        // Similarly, for `setup` we don't actually need submodules or cargo metadata.
+        if !matches!(build.config.cmd, Subcommand::Setup { .. }) {
+            build.verbose("running sanity check");
+            sanity::check(&mut build);
+
+            // Make sure we update these before gathering metadata so we don't get an error about missing
+            // Cargo.toml files.
+            let rust_submodules = [
+                "src/tools/rust-installer",
+                "src/tools/cargo",
+                "library/backtrace",
+                "library/stdarch",
+            ];
+            for s in rust_submodules {
+                build.update_submodule(Path::new(s));
+            }
+            // Now, update all existing submodules.
+            build.update_existing_submodules();
 
-        build.verbose("learning about cargo");
-        metadata::build(&mut build);
+            build.verbose("learning about cargo");
+            metadata::build(&mut build);
+        }
 
         build
     }
@@ -668,7 +676,7 @@ impl Build {
 
     /// If any submodule has been initialized already, sync it unconditionally.
     /// This avoids contributors checking in a submodule change by accident.
-    pub fn maybe_update_submodules(&self) {
+    pub fn update_existing_submodules(&self) {
         // Avoid running git when there isn't a git checkout.
         if !self.config.submodules(&self.rust_info()) {
             return;
@@ -697,8 +705,6 @@ impl Build {
             job::setup(self);
         }
 
-        self.maybe_update_submodules();
-
         if let Subcommand::Format { check, paths } = &self.config.cmd {
             return format::format(&builder::Builder::new(&self), *check, &paths);
         }
diff --git a/src/bootstrap/run.rs b/src/bootstrap/run.rs
index d49b41c5132..05de51f8cc5 100644
--- a/src/bootstrap/run.rs
+++ b/src/bootstrap/run.rs
@@ -1,3 +1,4 @@
+use std::path::PathBuf;
 use std::process::Command;
 
 use crate::builder::{Builder, RunConfig, ShouldRun, Step};
@@ -189,3 +190,65 @@ impl Step for Miri {
         builder.run(&mut miri);
     }
 }
+
+#[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
+pub struct CollectLicenseMetadata;
+
+impl Step for CollectLicenseMetadata {
+    type Output = PathBuf;
+    const ONLY_HOSTS: bool = true;
+
+    fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
+        run.path("src/tools/collect-license-metadata")
+    }
+
+    fn make_run(run: RunConfig<'_>) {
+        run.builder.ensure(CollectLicenseMetadata);
+    }
+
+    fn run(self, builder: &Builder<'_>) -> Self::Output {
+        let Some(reuse) = &builder.config.reuse else {
+            panic!("REUSE is required to collect the license metadata");
+        };
+
+        // Temporary location, it will be moved to src/etc once it's accurate.
+        let dest = builder.out.join("license-metadata.json");
+
+        let mut cmd = builder.tool_cmd(Tool::CollectLicenseMetadata);
+        cmd.env("REUSE_EXE", reuse);
+        cmd.env("DEST", &dest);
+        builder.run(&mut cmd);
+
+        dest
+    }
+}
+
+#[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
+pub struct GenerateCopyright;
+
+impl Step for GenerateCopyright {
+    type Output = PathBuf;
+    const ONLY_HOSTS: bool = true;
+
+    fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
+        run.path("src/tools/generate-copyright")
+    }
+
+    fn make_run(run: RunConfig<'_>) {
+        run.builder.ensure(GenerateCopyright);
+    }
+
+    fn run(self, builder: &Builder<'_>) -> Self::Output {
+        let license_metadata = builder.ensure(CollectLicenseMetadata);
+
+        // Temporary location, it will be moved to the proper one once it's accurate.
+        let dest = builder.out.join("COPYRIGHT.md");
+
+        let mut cmd = builder.tool_cmd(Tool::GenerateCopyright);
+        cmd.env("LICENSE_METADATA", &license_metadata);
+        cmd.env("DEST", &dest);
+        builder.run(&mut cmd);
+
+        dest
+    }
+}
diff --git a/src/bootstrap/sanity.rs b/src/bootstrap/sanity.rs
index 631d42acb93..8a40b0f64f4 100644
--- a/src/bootstrap/sanity.rs
+++ b/src/bootstrap/sanity.rs
@@ -140,6 +140,13 @@ than building it.
         .map(|p| cmd_finder.must_have(p))
         .or_else(|| cmd_finder.maybe_have("gdb"));
 
+    build.config.reuse = build
+        .config
+        .reuse
+        .take()
+        .map(|p| cmd_finder.must_have(p))
+        .or_else(|| cmd_finder.maybe_have("reuse"));
+
     // We're gonna build some custom C code here and there, host triples
     // also build some C++ shims for LLVM so we need a C++ compiler.
     for target in &build.targets {
diff --git a/src/bootstrap/setup.rs b/src/bootstrap/setup.rs
index 04480277fe0..c7f98a7d0d1 100644
--- a/src/bootstrap/setup.rs
+++ b/src/bootstrap/setup.rs
@@ -1,15 +1,13 @@
+use crate::Config;
 use crate::{t, VERSION};
-use crate::{Config, TargetSelection};
 use std::env::consts::EXE_SUFFIX;
 use std::fmt::Write as _;
 use std::fs::File;
+use std::io::Write;
 use std::path::{Path, PathBuf, MAIN_SEPARATOR};
 use std::process::Command;
 use std::str::FromStr;
-use std::{
-    env, fmt, fs,
-    io::{self, Write},
-};
+use std::{fmt, fs, io};
 
 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
 pub enum Profile {
@@ -81,38 +79,10 @@ impl fmt::Display for Profile {
     }
 }
 
-pub fn setup(config: &Config, profile: Profile) {
-    let path = &config.config.clone().unwrap_or(PathBuf::from("config.toml"));
-
-    if path.exists() {
-        eprintln!(
-            "error: you asked `x.py` to setup a new config file, but one already exists at `{}`",
-            path.display()
-        );
-        eprintln!("help: try adding `profile = \"{}\"` at the top of {}", profile, path.display());
-        eprintln!(
-            "note: this will use the configuration in {}",
-            profile.include_path(&config.src).display()
-        );
-        crate::detail_exit(1);
-    }
-
-    let settings = format!(
-        "# Includes one of the default files in src/bootstrap/defaults\n\
-    profile = \"{}\"\n\
-    changelog-seen = {}\n",
-        profile, VERSION
-    );
-    t!(fs::write(path, settings));
-
-    let include_path = profile.include_path(&config.src);
-    println!("`x.py` will now use the configuration at {}", include_path.display());
-
-    let build = TargetSelection::from_user(&env!("BUILD_TRIPLE"));
+pub fn setup(config: &Config, profile: Option<Profile>) {
+    let profile = profile.unwrap_or_else(|| t!(interactive_path()));
     let stage_path =
-        ["build", build.rustc_target_arg(), "stage1"].join(&MAIN_SEPARATOR.to_string());
-
-    println!();
+        ["build", config.build.rustc_target_arg(), "stage1"].join(&MAIN_SEPARATOR.to_string());
 
     if !rustup_installed() && profile != Profile::User {
         eprintln!("`rustup` is not installed; cannot link `stage1` toolchain");
@@ -134,8 +104,6 @@ pub fn setup(config: &Config, profile: Profile) {
         Profile::User => &["dist", "build"],
     };
 
-    println!();
-
     t!(install_git_hook_maybe(&config));
 
     println!();
@@ -150,6 +118,36 @@ pub fn setup(config: &Config, profile: Profile) {
             "For more suggestions, see https://rustc-dev-guide.rust-lang.org/building/suggested.html"
         );
     }
+
+    let path = &config.config.clone().unwrap_or(PathBuf::from("config.toml"));
+    setup_config_toml(path, profile, config);
+}
+
+fn setup_config_toml(path: &PathBuf, profile: Profile, config: &Config) {
+    if path.exists() {
+        eprintln!();
+        eprintln!(
+            "error: you asked `x.py` to setup a new config file, but one already exists at `{}`",
+            path.display()
+        );
+        eprintln!("help: try adding `profile = \"{}\"` at the top of {}", profile, path.display());
+        eprintln!(
+            "note: this will use the configuration in {}",
+            profile.include_path(&config.src).display()
+        );
+        crate::detail_exit(1);
+    }
+
+    let settings = format!(
+        "# Includes one of the default files in src/bootstrap/defaults\n\
+    profile = \"{}\"\n\
+    changelog-seen = {}\n",
+        profile, VERSION
+    );
+    t!(fs::write(path, settings));
+
+    let include_path = profile.include_path(&config.src);
+    println!("`x.py` will now use the configuration at {}", include_path.display());
 }
 
 fn rustup_installed() -> bool {
@@ -303,7 +301,18 @@ pub fn interactive_path() -> io::Result<Profile> {
 
 // install a git hook to automatically run tidy --bless, if they want
 fn install_git_hook_maybe(config: &Config) -> io::Result<()> {
+    let git = t!(config.git().args(&["rev-parse", "--git-common-dir"]).output().map(|output| {
+        assert!(output.status.success(), "failed to run `git`");
+        PathBuf::from(t!(String::from_utf8(output.stdout)).trim())
+    }));
+    let dst = git.join("hooks").join("pre-push");
+    if dst.exists() {
+        // The git hook has already been set up, or the user already has a custom hook.
+        return Ok(());
+    }
+
     let mut input = String::new();
+    println!();
     println!(
         "Rust's CI will automatically fail if it doesn't pass `tidy`, the internal tool for ensuring code quality.
 If you'd like, x.py can install a git hook for you that will automatically run `tidy --bless` before
@@ -329,12 +338,6 @@ undesirable, simply delete the `pre-push` file from .git/hooks."
 
     if should_install {
         let src = config.src.join("src").join("etc").join("pre-push.sh");
-        let git =
-            t!(config.git().args(&["rev-parse", "--git-common-dir"]).output().map(|output| {
-                assert!(output.status.success(), "failed to run `git`");
-                PathBuf::from(t!(String::from_utf8(output.stdout)).trim())
-            }));
-        let dst = git.join("hooks").join("pre-push");
         match fs::hard_link(src, &dst) {
             Err(e) => eprintln!(
                 "error: could not create hook {}: do you already have the git hook installed?\n{}",
diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs
index ba329ea6c75..e0be4c432f1 100644
--- a/src/bootstrap/tool.rs
+++ b/src/bootstrap/tool.rs
@@ -380,6 +380,8 @@ bootstrap_tool!(
     HtmlChecker, "src/tools/html-checker", "html-checker";
     BumpStage0, "src/tools/bump-stage0", "bump-stage0";
     ReplaceVersionPlaceholder, "src/tools/replace-version-placeholder", "replace-version-placeholder";
+    CollectLicenseMetadata, "src/tools/collect-license-metadata", "collect-license-metadata";
+    GenerateCopyright, "src/tools/generate-copyright", "generate-copyright";
 );
 
 #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, Ord, PartialOrd)]
diff --git a/src/ci/docker/host-aarch64/aarch64-gnu/Dockerfile b/src/ci/docker/host-aarch64/aarch64-gnu/Dockerfile
index e54d0eafb40..699938c3718 100644
--- a/src/ci/docker/host-aarch64/aarch64-gnu/Dockerfile
+++ b/src/ci/docker/host-aarch64/aarch64-gnu/Dockerfile
@@ -14,7 +14,8 @@ RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-ins
   gdb \
   libssl-dev \
   pkg-config \
-  xz-utils
+  xz-utils \
+  && rm -rf /var/lib/apt/lists/*
 
 COPY scripts/sccache.sh /scripts/
 RUN sh /scripts/sccache.sh
diff --git a/src/ci/docker/host-x86_64/dist-i686-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-i686-linux/Dockerfile
index cd86d9fb584..ea4a2a2427d 100644
--- a/src/ci/docker/host-x86_64/dist-i686-linux/Dockerfile
+++ b/src/ci/docker/host-x86_64/dist-i686-linux/Dockerfile
@@ -32,7 +32,8 @@ RUN yum upgrade -y && \
       wget \
       xz \
       zlib-devel.i686 \
-      zlib-devel.x86_64
+      zlib-devel.x86_64 \
+      && yum clean all
 
 RUN mkdir -p /rustroot/bin && ln -s /usr/bin/cmake3 /rustroot/bin/cmake
 
diff --git a/src/ci/docker/host-x86_64/dist-various-2/build-wasi-toolchain.sh b/src/ci/docker/host-x86_64/dist-various-2/build-wasi-toolchain.sh
index 36c94458da7..67cee0148b2 100755
--- a/src/ci/docker/host-x86_64/dist-various-2/build-wasi-toolchain.sh
+++ b/src/ci/docker/host-x86_64/dist-various-2/build-wasi-toolchain.sh
@@ -2,15 +2,15 @@
 
 set -ex
 
-# Originally from https://github.com/llvm/llvm-project/releases/download/llvmorg-14.0.0/clang+llvm-14.0.0-x86_64-linux-gnu-ubuntu-18.04.tar.xz
-curl https://ci-mirrors.rust-lang.org/rustc/2022-05-10-clang%2Bllvm-14.0.0-x86_64-linux-gnu-ubuntu-18.04.tar.xz | \
+# Originally from https://github.com/llvm/llvm-project/releases/download/llvmorg-15.0.6/clang+llvm-15.0.6-x86_64-linux-gnu-ubuntu-18.04.tar.xz
+curl https://ci-mirrors.rust-lang.org/rustc/2022-12-06-clang%2Bllvm-15.0.6-x86_64-linux-gnu-ubuntu-18.04.tar.xz | \
   tar xJf -
-bin="$PWD/clang+llvm-14.0.0-x86_64-linux-gnu-ubuntu-18.04/bin"
+bin="$PWD/clang+llvm-15.0.6-x86_64-linux-gnu-ubuntu-18.04/bin"
 
 git clone https://github.com/WebAssembly/wasi-libc
 
 cd wasi-libc
-git reset --hard 9886d3d6200fcc3726329966860fc058707406cd
+git reset --hard 8b7148f69ae241a2749b3defe4606da8143b72e0
 make -j$(nproc) \
     CC="$bin/clang" \
     NM="$bin/llvm-nm" \
diff --git a/src/ci/docker/host-x86_64/dist-x86_64-freebsd/Dockerfile b/src/ci/docker/host-x86_64/dist-x86_64-freebsd/Dockerfile
index f9b1fa8951a..377d4a9ce5e 100644
--- a/src/ci/docker/host-x86_64/dist-x86_64-freebsd/Dockerfile
+++ b/src/ci/docker/host-x86_64/dist-x86_64-freebsd/Dockerfile
@@ -15,7 +15,8 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   xz-utils \
   wget \
   libssl-dev \
-  pkg-config
+  pkg-config \
+  && rm -rf /var/lib/apt/lists/*
 
 COPY scripts/freebsd-toolchain.sh /tmp/
 RUN /tmp/freebsd-toolchain.sh x86_64
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 c2e44ead51e..4e46bdee5ac 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
@@ -11,7 +11,8 @@ RUN apt-get update && \
     apt-get install -y --no-install-recommends \
       libgmp-dev \
       libmpfr-dev \
-      libmpc-dev
+      libmpc-dev \
+      && rm -rf /var/lib/apt/lists/*
 
 COPY scripts/illumos-toolchain.sh /tmp/
 
diff --git a/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile
index 423aba06cca..6bdc88e18f5 100644
--- a/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile
+++ b/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile
@@ -32,7 +32,8 @@ RUN yum upgrade -y && \
       wget \
       xz \
       zlib-devel.i686 \
-      zlib-devel.x86_64
+      zlib-devel.x86_64 \
+      && yum clean all
 
 RUN mkdir -p /rustroot/bin && ln -s /usr/bin/cmake3 /rustroot/bin/cmake
 
diff --git a/src/ci/docker/host-x86_64/dist-x86_64-musl/Dockerfile b/src/ci/docker/host-x86_64/dist-x86_64-musl/Dockerfile
index 51645a81853..13eaf7fce8c 100644
--- a/src/ci/docker/host-x86_64/dist-x86_64-musl/Dockerfile
+++ b/src/ci/docker/host-x86_64/dist-x86_64-musl/Dockerfile
@@ -16,7 +16,8 @@ RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-ins
   gdb \
   patch \
   libssl-dev \
-  pkg-config
+  pkg-config \
+  && rm -rf /var/lib/apt/lists/*
 
 WORKDIR /build/
 
diff --git a/src/ci/docker/host-x86_64/i686-gnu-nopt/Dockerfile b/src/ci/docker/host-x86_64/i686-gnu-nopt/Dockerfile
index dd74726f856..e2b66c2cff1 100644
--- a/src/ci/docker/host-x86_64/i686-gnu-nopt/Dockerfile
+++ b/src/ci/docker/host-x86_64/i686-gnu-nopt/Dockerfile
@@ -15,7 +15,8 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   gdb \
   zlib1g-dev \
   lib32z1-dev \
-  xz-utils
+  xz-utils \
+  && rm -rf /var/lib/apt/lists/*
 
 
 COPY scripts/sccache.sh /scripts/
diff --git a/src/ci/docker/host-x86_64/i686-gnu/Dockerfile b/src/ci/docker/host-x86_64/i686-gnu/Dockerfile
index 0c36cfd66bd..cb6559707d9 100644
--- a/src/ci/docker/host-x86_64/i686-gnu/Dockerfile
+++ b/src/ci/docker/host-x86_64/i686-gnu/Dockerfile
@@ -15,7 +15,8 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   gdb \
   zlib1g-dev \
   lib32z1-dev \
-  xz-utils
+  xz-utils \
+  && rm -rf /var/lib/apt/lists/*
 
 
 COPY scripts/sccache.sh /scripts/
diff --git a/src/ci/docker/host-x86_64/mingw-check/Dockerfile b/src/ci/docker/host-x86_64/mingw-check/Dockerfile
index 52a7776153d..40caa7c5013 100644
--- a/src/ci/docker/host-x86_64/mingw-check/Dockerfile
+++ b/src/ci/docker/host-x86_64/mingw-check/Dockerfile
@@ -20,20 +20,20 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   xz-utils \
   libssl-dev \
   pkg-config \
-  mingw-w64
+  mingw-w64 \
+  && rm -rf /var/lib/apt/lists/*
 
 RUN curl -sL https://nodejs.org/dist/v16.9.0/node-v16.9.0-linux-x64.tar.xz | tar -xJ
 ENV PATH="/node-v16.9.0-linux-x64/bin:${PATH}"
 # Install es-check
 # Pin its version to prevent unrelated CI failures due to future es-check versions.
-RUN npm install es-check@6.1.1 -g
-RUN npm install eslint@8.6.0 -g
+RUN npm install es-check@6.1.1 eslint@8.6.0 -g
 
 COPY scripts/sccache.sh /scripts/
 RUN sh /scripts/sccache.sh
 
 COPY host-x86_64/mingw-check/reuse-requirements.txt /tmp/
-RUN pip3 install --no-deps --require-hashes -r /tmp/reuse-requirements.txt
+RUN pip3 install --no-deps --no-cache-dir --require-hashes -r /tmp/reuse-requirements.txt
 
 COPY host-x86_64/mingw-check/validate-toolstate.sh /scripts/
 COPY host-x86_64/mingw-check/validate-error-codes.sh /scripts/
diff --git a/src/ci/docker/host-x86_64/test-various/Dockerfile b/src/ci/docker/host-x86_64/test-various/Dockerfile
index 7c09e3a582f..cf4451f8b33 100644
--- a/src/ci/docker/host-x86_64/test-various/Dockerfile
+++ b/src/ci/docker/host-x86_64/test-various/Dockerfile
@@ -21,7 +21,8 @@ RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-ins
   ovmf \
   qemu-efi-aarch64 \
   qemu-system-arm \
-  qemu-system-x86
+  qemu-system-x86 \
+  && rm -rf /var/lib/apt/lists/*
 
 RUN curl -sL https://nodejs.org/dist/v15.14.0/node-v15.14.0-linux-x64.tar.xz | \
   tar -xJ
diff --git a/src/ci/docker/host-x86_64/wasm32/Dockerfile b/src/ci/docker/host-x86_64/wasm32/Dockerfile
index 9e37c2822e8..ef1fde1c3b9 100644
--- a/src/ci/docker/host-x86_64/wasm32/Dockerfile
+++ b/src/ci/docker/host-x86_64/wasm32/Dockerfile
@@ -13,7 +13,8 @@ RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-ins
   sudo \
   gdb \
   xz-utils \
-  bzip2
+  bzip2 \
+  && rm -rf /var/lib/apt/lists/*
 
 COPY scripts/emscripten.sh /scripts/
 RUN bash /scripts/emscripten.sh
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-aux/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-aux/Dockerfile
index d55d5b56ad3..e08c4e1e8b7 100644
--- a/src/ci/docker/host-x86_64/x86_64-gnu-aux/Dockerfile
+++ b/src/ci/docker/host-x86_64/x86_64-gnu-aux/Dockerfile
@@ -19,7 +19,8 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   llvm-dev \
   libfreetype6-dev \
   libexpat1-dev \
-  tidy
+  tidy \
+  && rm -rf /var/lib/apt/lists/*
 
 COPY scripts/sccache.sh /scripts/
 RUN sh /scripts/sccache.sh
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-debug/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-debug/Dockerfile
index 739045248fe..c2b002055a8 100644
--- a/src/ci/docker/host-x86_64/x86_64-gnu-debug/Dockerfile
+++ b/src/ci/docker/host-x86_64/x86_64-gnu-debug/Dockerfile
@@ -23,7 +23,8 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   pkg-config \
   xz-utils \
   lld \
-  clang
+  clang \
+  && rm -rf /var/lib/apt/lists/*
 
 COPY scripts/sccache.sh /scripts/
 RUN sh /scripts/sccache.sh
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-distcheck/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-distcheck/Dockerfile
index 80a004501a8..7e640c49f01 100644
--- a/src/ci/docker/host-x86_64/x86_64-gnu-distcheck/Dockerfile
+++ b/src/ci/docker/host-x86_64/x86_64-gnu-distcheck/Dockerfile
@@ -15,7 +15,8 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   gdb \
   xz-utils \
   libssl-dev \
-  pkg-config
+  pkg-config \
+  && rm -rf /var/lib/apt/lists/*
 
 COPY scripts/sccache.sh /scripts/
 RUN sh /scripts/sccache.sh
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-13-stage1/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-13-stage1/Dockerfile
index 23f2215c2d9..16976a9428e 100644
--- a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-13-stage1/Dockerfile
+++ b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-13-stage1/Dockerfile
@@ -21,7 +21,8 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
     pkg-config \
     zlib1g-dev \
     xz-utils \
-    nodejs
+    nodejs \
+    && rm -rf /var/lib/apt/lists/*
 
 COPY scripts/sccache.sh /scripts/
 RUN sh /scripts/sccache.sh
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-13/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-13/Dockerfile
index 8f6831bc54e..06f15bd1211 100644
--- a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-13/Dockerfile
+++ b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-13/Dockerfile
@@ -24,15 +24,15 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   pkg-config \
   zlib1g-dev \
   xz-utils \
-  nodejs
-
+  nodejs \
+  \
 # Install powershell so we can test x.ps1 on Linux
-RUN apt-get update && \
-    apt-get install -y apt-transport-https software-properties-common && \
+    apt-transport-https software-properties-common && \
     curl -s "https://packages.microsoft.com/config/ubuntu/$(lsb_release -rs)/packages-microsoft-prod.deb" > packages-microsoft-prod.deb && \
     dpkg -i packages-microsoft-prod.deb && \
     apt-get update && \
-    apt-get install -y powershell
+    apt-get install -y powershell \
+    && rm -rf /var/lib/apt/lists/*
 
 COPY scripts/sccache.sh /scripts/
 RUN sh /scripts/sccache.sh
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-nopt/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-nopt/Dockerfile
index 77510d7ac62..9fdc78406fb 100644
--- a/src/ci/docker/host-x86_64/x86_64-gnu-nopt/Dockerfile
+++ b/src/ci/docker/host-x86_64/x86_64-gnu-nopt/Dockerfile
@@ -15,7 +15,8 @@ RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-ins
   gdb \
   libssl-dev \
   pkg-config \
-  xz-utils
+  xz-utils \
+  && rm -rf /var/lib/apt/lists/*
 
 COPY scripts/sccache.sh /scripts/
 RUN sh /scripts/sccache.sh
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile
index 4350ca20586..58c0c5db1a5 100644
--- a/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile
+++ b/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile
@@ -14,10 +14,9 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   libssl-dev \
   sudo \
   xz-utils \
-  tidy
-
+  tidy \
+  \
 # Install dependencies for chromium browser
-RUN apt-get install -y \
   gconf-service \
   libasound2 \
   libatk1.0-0 \
@@ -56,7 +55,8 @@ RUN apt-get install -y \
   libnss3 \
   lsb-release \
   xdg-utils \
-  wget
+  wget \
+  && rm -rf /var/lib/apt/lists/*
 
 COPY scripts/sccache.sh /scripts/
 RUN sh /scripts/sccache.sh
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu/Dockerfile
index 88c182a4d43..5b9581f72a6 100644
--- a/src/ci/docker/host-x86_64/x86_64-gnu/Dockerfile
+++ b/src/ci/docker/host-x86_64/x86_64-gnu/Dockerfile
@@ -15,7 +15,8 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   gdb \
   libssl-dev \
   pkg-config \
-  xz-utils
+  xz-utils \
+  && rm -rf /var/lib/apt/lists/*
 
 COPY scripts/sccache.sh /scripts/
 RUN sh /scripts/sccache.sh
diff --git a/src/ci/docker/scripts/freebsd-toolchain.sh b/src/ci/docker/scripts/freebsd-toolchain.sh
index 4a4cac1b723..17cd456b995 100755
--- a/src/ci/docker/scripts/freebsd-toolchain.sh
+++ b/src/ci/docker/scripts/freebsd-toolchain.sh
@@ -53,7 +53,7 @@ files_to_extract=(
 for lib in c cxxrt gcc_s m thr util; do
   files_to_extract=("${files_to_extract[@]}" "./lib/lib${lib}.*" "./usr/lib/lib${lib}.*")
 done
-for lib in c++ c_nonshared compiler_rt execinfo gcc pthread rt ssp_nonshared procstat devstat kvm; do
+for lib in c++ c_nonshared compiler_rt execinfo gcc pthread rt ssp_nonshared procstat devstat kvm memstat; do
   files_to_extract=("${files_to_extract[@]}" "./usr/lib/lib${lib}.*")
 done
 
diff --git a/src/doc/book b/src/doc/book
-Subproject 3f64052c048c6def93b94a2b514ee88bba91874
+Subproject a60f4316ec923a5ac2ed6a2eba6960edb832d85
diff --git a/src/doc/embedded-book b/src/doc/embedded-book
-Subproject c533348edd69f11a8f4225d633a05d7093fddbf
+Subproject 19f798d448835a4888e3b3eae7fe69f1d61d868
diff --git a/src/doc/nomicon b/src/doc/nomicon
-Subproject 05532356e7a4dbea2330aabb77611f5179493bb
+Subproject ae406aa5287a9e025abb72343aaceec98458c11
diff --git a/src/doc/reference b/src/doc/reference
-Subproject 9f0cc13ffcd27c1fbe1ab766a9491e15ddcf4d1
+Subproject 3ae62681ff236d5528ef7c8c28ba7c6b2ecc673
diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example
-Subproject 2b15c0abf2bada6e00553814336bc3e2d839909
+Subproject a9869b4a3c4cac3bc6099b41f088679e268400b
diff --git a/src/doc/rustc-dev-guide b/src/doc/rustc-dev-guide
-Subproject d0dc6c97a6486f68bac782fff135086eae6d77e
+Subproject e269950a57fa6fcda356426545fb5aa3691a7ce
diff --git a/src/doc/unstable-book/src/language-features/abi-efiapi.md b/src/doc/unstable-book/src/language-features/abi-efiapi.md
index 11ef0cfdb14..b492da88474 100644
--- a/src/doc/unstable-book/src/language-features/abi-efiapi.md
+++ b/src/doc/unstable-book/src/language-features/abi-efiapi.md
@@ -12,7 +12,7 @@ Specification].
 
 Example:
 
-```rust
+```rust,ignore (not-all-targets-support-uefi)
 #![feature(abi_efiapi)]
 
 extern "efiapi" { fn f1(); }
diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css
index f44797fe55f..11136179607 100644
--- a/src/librustdoc/html/static/css/rustdoc.css
+++ b/src/librustdoc/html/static/css/rustdoc.css
@@ -195,8 +195,7 @@ h1, h2, h3, h4, h5, h6,
 span.since,
 a.srclink,
 #help-button > a,
-details.rustdoc-toggle.top-doc > summary,
-details.rustdoc-toggle.non-exhaustive > summary,
+summary.hideme,
 .scraped-example-list,
 /* This selector is for the items listed in the "all items" page. */
 ul.all-items {
@@ -213,8 +212,7 @@ pre.rust a,
 .mobile-topbar h2 a,
 h1 a,
 .search-results a,
-.module-item .stab,
-.import-item .stab,
+.item-left .stab,
 .result-name .primitive > i, .result-name .keyword > i {
 	color: var(--main-color);
 }
@@ -1011,11 +1009,9 @@ so that we can apply CSS-filters to change the arrow color in themes */
 		0 -1px 0 black;
 }
 
-.module-item .stab,
-.import-item .stab {
+.item-left .stab {
 	border-radius: 3px;
 	display: inline-block;
-	font-size: 0.875rem;
 	line-height: 1.2;
 	margin-bottom: 0;
 	margin-left: 0.3125em;
@@ -1484,6 +1480,7 @@ details.rustdoc-toggle {
 	"Expand description" or "Show methods". */
 details.rustdoc-toggle > summary.hideme {
 	cursor: pointer;
+	font-size: 1rem;
 }
 
 details.rustdoc-toggle > summary {
@@ -1546,13 +1543,6 @@ details.rustdoc-toggle > summary:focus-visible::before {
 	outline-offset: 1px;
 }
 
-details.rustdoc-toggle.top-doc > summary,
-details.rustdoc-toggle.top-doc > summary::before,
-details.rustdoc-toggle.non-exhaustive > summary,
-details.rustdoc-toggle.non-exhaustive > summary::before {
-	font-size: 1rem;
-}
-
 details.non-exhaustive {
 	margin-bottom: 8px;
 }
@@ -1660,8 +1650,6 @@ in storage.js
 		/* Hide the sidebar offscreen while not in use. Doing this instead of display: none means
 		   the sidebar stays visible for screen readers, which is useful for navigation. */
 		left: -1000px;
-		margin: 0;
-		padding: 0;
 		z-index: 11;
 		/* Reduce height slightly to account for mobile topbar. */
 		height: calc(100vh - 45px);
@@ -1978,7 +1966,9 @@ in storage.js
 }
 
 .scraped-example .code-wrapper .example-wrap {
-	flex: 1;
+	display: grid;
+	grid-template-columns: max-content auto;
+	width: 100%;
 	overflow-x: auto;
 	overflow-y: hidden;
 	margin-bottom: 0;
diff --git a/src/librustdoc/html/static/js/scrape-examples.js b/src/librustdoc/html/static/js/scrape-examples.js
index d0fd115fd15..e328e656edd 100644
--- a/src/librustdoc/html/static/js/scrape-examples.js
+++ b/src/librustdoc/html/static/js/scrape-examples.js
@@ -57,7 +57,7 @@
                     });
                 });
 
-            example.querySelector("next")
+            example.querySelector(".next")
                 .addEventListener("click", () => {
                     onChangeLoc(() => {
                         locIndex = (locIndex + 1) % locs.length;
diff --git a/src/librustdoc/html/static_files.rs b/src/librustdoc/html/static_files.rs
index 1f87f95563a..b48b82307eb 100644
--- a/src/librustdoc/html/static_files.rs
+++ b/src/librustdoc/html/static_files.rs
@@ -130,4 +130,4 @@ static_files! {
     nanum_barun_gothic_license => "static/fonts/NanumBarunGothic-LICENSE.txt",
 }
 
-pub(crate) static SCRAPE_EXAMPLES_HELP_MD: &str = include_str!("static/js/scrape-examples.js");
+pub(crate) static SCRAPE_EXAMPLES_HELP_MD: &str = include_str!("static/scrape-examples-help.md");
diff --git a/src/llvm-project b/src/llvm-project
-Subproject a1232c451fc27173f8718e05d174b2503ca0b60
+Subproject 3dfd4d93fa013e1c0578d3ceac5c8f4ebba4b6e
diff --git a/src/test/mir-opt/inline/cycle.g.Inline.diff b/src/test/mir-opt/inline/cycle.g.Inline.diff
index 5f3ee467c88..afe157ccd7f 100644
--- a/src/test/mir-opt/inline/cycle.g.Inline.diff
+++ b/src/test/mir-opt/inline/cycle.g.Inline.diff
@@ -10,8 +10,6 @@
 +         let _3: ();                      // in scope 1 at $DIR/cycle.rs:6:5: 6:8
 +         let mut _4: &fn() {main};        // in scope 1 at $DIR/cycle.rs:6:5: 6:6
 +         let mut _5: ();                  // in scope 1 at $DIR/cycle.rs:6:5: 6:8
-+         scope 2 (inlined <fn() {main} as Fn<()>>::call - shim(fn() {main})) { // at $DIR/cycle.rs:6:5: 6:8
-+         }
 +     }
   
       bb0: {
@@ -29,7 +27,10 @@
 +         StorageLive(_4);                 // scope 1 at $DIR/cycle.rs:6:5: 6:6
 +         _4 = &_2;                        // scope 1 at $DIR/cycle.rs:6:5: 6:6
 +         StorageLive(_5);                 // scope 1 at $DIR/cycle.rs:6:5: 6:8
-+         _3 = move (*_4)() -> [return: bb4, unwind: bb2]; // scope 2 at $SRC_DIR/core/src/ops/function.rs:LL:COL
++         _3 = <fn() {main} as Fn<()>>::call(move _4, move _5) -> [return: bb2, unwind: bb3]; // scope 1 at $DIR/cycle.rs:6:5: 6:8
++                                          // mir::Constant
++                                          // + span: $DIR/cycle.rs:6:5: 6:6
++                                          // + literal: Const { ty: for<'a> extern "rust-call" fn(&'a fn() {main}, ()) -> <fn() {main} as FnOnce<()>>::Output {<fn() {main} as Fn<()>>::call}, val: Value(<ZST>) }
       }
   
       bb1: {
@@ -39,19 +40,19 @@
           return;                          // scope 0 at $DIR/cycle.rs:+2:2: +2:2
 +     }
 + 
-+     bb2 (cleanup): {
-+         drop(_2) -> bb3;                 // scope 1 at $DIR/cycle.rs:7:1: 7:2
++     bb2: {
++         StorageDead(_5);                 // scope 1 at $DIR/cycle.rs:6:7: 6:8
++         StorageDead(_4);                 // scope 1 at $DIR/cycle.rs:6:7: 6:8
++         StorageDead(_3);                 // scope 1 at $DIR/cycle.rs:6:8: 6:9
++         drop(_2) -> bb1;                 // scope 1 at $DIR/cycle.rs:7:1: 7:2
 +     }
 + 
 +     bb3 (cleanup): {
-+         resume;                          // scope 1 at $DIR/cycle.rs:5:1: 7:2
++         drop(_2) -> bb4;                 // scope 1 at $DIR/cycle.rs:7:1: 7:2
 +     }
 + 
-+     bb4: {
-+         StorageDead(_5);                 // scope 1 at $DIR/cycle.rs:6:7: 6:8
-+         StorageDead(_4);                 // scope 1 at $DIR/cycle.rs:6:7: 6:8
-+         StorageDead(_3);                 // scope 1 at $DIR/cycle.rs:6:8: 6:9
-+         drop(_2) -> bb1;                 // scope 1 at $DIR/cycle.rs:7:1: 7:2
++     bb4 (cleanup): {
++         resume;                          // scope 1 at $DIR/cycle.rs:5:1: 7:2
       }
   }
   
diff --git a/src/test/mir-opt/inline/cycle.main.Inline.diff b/src/test/mir-opt/inline/cycle.main.Inline.diff
index 8b4099b9d9f..bd89e09ecd1 100644
--- a/src/test/mir-opt/inline/cycle.main.Inline.diff
+++ b/src/test/mir-opt/inline/cycle.main.Inline.diff
@@ -10,18 +10,6 @@
 +         let _3: ();                      // in scope 1 at $DIR/cycle.rs:6:5: 6:8
 +         let mut _4: &fn() {g};           // in scope 1 at $DIR/cycle.rs:6:5: 6:6
 +         let mut _5: ();                  // in scope 1 at $DIR/cycle.rs:6:5: 6:8
-+         scope 2 (inlined <fn() {g} as Fn<()>>::call - shim(fn() {g})) { // at $DIR/cycle.rs:6:5: 6:8
-+             scope 3 (inlined g) {        // at $SRC_DIR/core/src/ops/function.rs:LL:COL
-+                 let mut _6: fn() {main}; // in scope 3 at $DIR/cycle.rs:12:5: 12:12
-+                 scope 4 (inlined f::<fn() {main}>) { // at $DIR/cycle.rs:12:5: 12:12
-+                     debug g => _6;       // in scope 4 at $DIR/cycle.rs:5:6: 5:7
-+                     let _7: ();          // in scope 4 at $DIR/cycle.rs:6:5: 6:8
-+                     let mut _8: &fn() {main}; // in scope 4 at $DIR/cycle.rs:6:5: 6:6
-+                     scope 5 (inlined <fn() {main} as Fn<()>>::call - shim(fn() {main})) { // at $DIR/cycle.rs:6:5: 6:8
-+                     }
-+                 }
-+             }
-+         }
 +     }
   
       bb0: {
@@ -39,11 +27,10 @@
 +         StorageLive(_4);                 // scope 1 at $DIR/cycle.rs:6:5: 6:6
 +         _4 = &_2;                        // scope 1 at $DIR/cycle.rs:6:5: 6:6
 +         StorageLive(_5);                 // scope 1 at $DIR/cycle.rs:6:5: 6:8
-+         StorageLive(_6);                 // scope 3 at $DIR/cycle.rs:12:5: 12:12
-+         StorageLive(_7);                 // scope 4 at $DIR/cycle.rs:6:5: 6:8
-+         StorageLive(_8);                 // scope 4 at $DIR/cycle.rs:6:5: 6:6
-+         _8 = &_6;                        // scope 4 at $DIR/cycle.rs:6:5: 6:6
-+         _7 = move (*_8)() -> [return: bb4, unwind: bb2]; // scope 5 at $SRC_DIR/core/src/ops/function.rs:LL:COL
++         _3 = <fn() {g} as Fn<()>>::call(move _4, move _5) -> [return: bb2, unwind: bb3]; // scope 1 at $DIR/cycle.rs:6:5: 6:8
++                                          // mir::Constant
++                                          // + span: $DIR/cycle.rs:6:5: 6:6
++                                          // + literal: Const { ty: for<'a> extern "rust-call" fn(&'a fn() {g}, ()) -> <fn() {g} as FnOnce<()>>::Output {<fn() {g} as Fn<()>>::call}, val: Value(<ZST>) }
       }
   
       bb1: {
@@ -53,22 +40,19 @@
           return;                          // scope 0 at $DIR/cycle.rs:+2:2: +2:2
 +     }
 + 
-+     bb2 (cleanup): {
-+         drop(_2) -> bb3;                 // scope 1 at $DIR/cycle.rs:7:1: 7:2
++     bb2: {
++         StorageDead(_5);                 // scope 1 at $DIR/cycle.rs:6:7: 6:8
++         StorageDead(_4);                 // scope 1 at $DIR/cycle.rs:6:7: 6:8
++         StorageDead(_3);                 // scope 1 at $DIR/cycle.rs:6:8: 6:9
++         drop(_2) -> bb1;                 // scope 1 at $DIR/cycle.rs:7:1: 7:2
 +     }
 + 
 +     bb3 (cleanup): {
-+         resume;                          // scope 1 at $DIR/cycle.rs:5:1: 7:2
++         drop(_2) -> bb4;                 // scope 1 at $DIR/cycle.rs:7:1: 7:2
 +     }
 + 
-+     bb4: {
-+         StorageDead(_8);                 // scope 4 at $DIR/cycle.rs:6:7: 6:8
-+         StorageDead(_7);                 // scope 4 at $DIR/cycle.rs:6:8: 6:9
-+         StorageDead(_6);                 // scope 3 at $DIR/cycle.rs:12:5: 12:12
-+         StorageDead(_5);                 // scope 1 at $DIR/cycle.rs:6:7: 6:8
-+         StorageDead(_4);                 // scope 1 at $DIR/cycle.rs:6:7: 6:8
-+         StorageDead(_3);                 // scope 1 at $DIR/cycle.rs:6:8: 6:9
-+         drop(_2) -> bb1;                 // scope 1 at $DIR/cycle.rs:7:1: 7:2
++     bb4 (cleanup): {
++         resume;                          // scope 1 at $DIR/cycle.rs:5:1: 7:2
       }
   }
   
diff --git a/src/test/mir-opt/inline/exponential_runtime.main.Inline.diff b/src/test/mir-opt/inline/exponential_runtime.main.Inline.diff
new file mode 100644
index 00000000000..d9fd7b324c7
--- /dev/null
+++ b/src/test/mir-opt/inline/exponential_runtime.main.Inline.diff
@@ -0,0 +1,50 @@
+- // MIR for `main` before Inline
++ // MIR for `main` after Inline
+  
+  fn main() -> () {
+      let mut _0: ();                      // return place in scope 0 at $DIR/exponential_runtime.rs:+0:11: +0:11
+      let _1: ();                          // in scope 0 at $DIR/exponential_runtime.rs:+1:5: +1:22
++     scope 1 (inlined <() as G>::call) {  // at $DIR/exponential_runtime.rs:86:5: 86:22
++         let _2: ();                      // in scope 1 at $DIR/exponential_runtime.rs:73:9: 73:25
++         let _3: ();                      // in scope 1 at $DIR/exponential_runtime.rs:74:9: 74:25
++         let _4: ();                      // in scope 1 at $DIR/exponential_runtime.rs:75:9: 75:25
++     }
+  
+      bb0: {
+          StorageLive(_1);                 // scope 0 at $DIR/exponential_runtime.rs:+1:5: +1:22
+-         _1 = <() as G>::call() -> bb1;   // scope 0 at $DIR/exponential_runtime.rs:+1:5: +1:22
++         StorageLive(_2);                 // scope 1 at $DIR/exponential_runtime.rs:73:9: 73:25
++         _2 = <() as F>::call() -> bb1;   // scope 1 at $DIR/exponential_runtime.rs:73:9: 73:25
+                                           // mir::Constant
+-                                          // + span: $DIR/exponential_runtime.rs:86:5: 86:20
+-                                          // + literal: Const { ty: fn() {<() as G>::call}, val: Value(<ZST>) }
++                                          // + span: $DIR/exponential_runtime.rs:73:9: 73:23
++                                          // + literal: Const { ty: fn() {<() as F>::call}, val: Value(<ZST>) }
+      }
+  
+      bb1: {
++         StorageDead(_2);                 // scope 1 at $DIR/exponential_runtime.rs:73:25: 73:26
++         StorageLive(_3);                 // scope 1 at $DIR/exponential_runtime.rs:74:9: 74:25
++         _3 = <() as F>::call() -> bb2;   // scope 1 at $DIR/exponential_runtime.rs:74:9: 74:25
++                                          // mir::Constant
++                                          // + span: $DIR/exponential_runtime.rs:74:9: 74:23
++                                          // + literal: Const { ty: fn() {<() as F>::call}, val: Value(<ZST>) }
++     }
++ 
++     bb2: {
++         StorageDead(_3);                 // scope 1 at $DIR/exponential_runtime.rs:74:25: 74:26
++         StorageLive(_4);                 // scope 1 at $DIR/exponential_runtime.rs:75:9: 75:25
++         _4 = <() as F>::call() -> bb3;   // scope 1 at $DIR/exponential_runtime.rs:75:9: 75:25
++                                          // mir::Constant
++                                          // + span: $DIR/exponential_runtime.rs:75:9: 75:23
++                                          // + literal: Const { ty: fn() {<() as F>::call}, val: Value(<ZST>) }
++     }
++ 
++     bb3: {
++         StorageDead(_4);                 // scope 1 at $DIR/exponential_runtime.rs:75:25: 75:26
+          StorageDead(_1);                 // scope 0 at $DIR/exponential_runtime.rs:+1:22: +1:23
+          _0 = const ();                   // scope 0 at $DIR/exponential_runtime.rs:+0:11: +2:2
+          return;                          // scope 0 at $DIR/exponential_runtime.rs:+2:2: +2:2
+      }
+  }
+  
diff --git a/src/test/mir-opt/inline/exponential_runtime.rs b/src/test/mir-opt/inline/exponential_runtime.rs
new file mode 100644
index 00000000000..d9219d76a98
--- /dev/null
+++ b/src/test/mir-opt/inline/exponential_runtime.rs
@@ -0,0 +1,87 @@
+// Checks that code with exponential runtime does not have exponential behavior in inlining.
+
+trait A {
+    fn call();
+}
+
+trait B {
+    fn call();
+}
+impl<T: A> B for T {
+    #[inline]
+    fn call() {
+        <T as A>::call();
+        <T as A>::call();
+        <T as A>::call();
+    }
+}
+
+trait C {
+    fn call();
+}
+impl<T: B> C for T {
+    #[inline]
+    fn call() {
+        <T as B>::call();
+        <T as B>::call();
+        <T as B>::call();
+    }
+}
+
+trait D {
+    fn call();
+}
+impl<T: C> D for T {
+    #[inline]
+    fn call() {
+        <T as C>::call();
+        <T as C>::call();
+        <T as C>::call();
+    }
+}
+
+trait E {
+    fn call();
+}
+impl<T: D> E for T {
+    #[inline]
+    fn call() {
+        <T as D>::call();
+        <T as D>::call();
+        <T as D>::call();
+    }
+}
+
+trait F {
+    fn call();
+}
+impl<T: E> F for T {
+    #[inline]
+    fn call() {
+        <T as E>::call();
+        <T as E>::call();
+        <T as E>::call();
+    }
+}
+
+trait G {
+    fn call();
+}
+impl<T: F> G for T {
+    #[inline]
+    fn call() {
+        <T as F>::call();
+        <T as F>::call();
+        <T as F>::call();
+    }
+}
+
+impl A for () {
+    #[inline(never)]
+    fn call() {}
+}
+
+// EMIT_MIR exponential_runtime.main.Inline.diff
+fn main() {
+    <() as G>::call();
+}
diff --git a/src/test/mir-opt/inline/inline_cycle.one.Inline.diff b/src/test/mir-opt/inline/inline_cycle.one.Inline.diff
index 5510cd7bc8c..f54a1a747d4 100644
--- a/src/test/mir-opt/inline/inline_cycle.one.Inline.diff
+++ b/src/test/mir-opt/inline/inline_cycle.one.Inline.diff
@@ -5,20 +5,17 @@
       let mut _0: ();                      // return place in scope 0 at $DIR/inline_cycle.rs:+0:10: +0:10
       let _1: ();                          // in scope 0 at $DIR/inline_cycle.rs:+1:5: +1:24
 +     scope 1 (inlined <C as Call>::call) { // at $DIR/inline_cycle.rs:14:5: 14:24
-+         scope 2 (inlined <A<C> as Call>::call) { // at $DIR/inline_cycle.rs:43:9: 43:23
-+             scope 3 (inlined <B<C> as Call>::call) { // at $DIR/inline_cycle.rs:28:9: 28:31
-+             }
-+         }
 +     }
   
       bb0: {
           StorageLive(_1);                 // scope 0 at $DIR/inline_cycle.rs:+1:5: +1:24
 -         _1 = <C as Call>::call() -> bb1; // scope 0 at $DIR/inline_cycle.rs:+1:5: +1:24
-+         _1 = <C as Call>::call() -> bb1; // scope 3 at $DIR/inline_cycle.rs:36:9: 36:28
++         _1 = <A<C> as Call>::call() -> bb1; // scope 1 at $DIR/inline_cycle.rs:43:9: 43:23
                                            // mir::Constant
 -                                          // + span: $DIR/inline_cycle.rs:14:5: 14:22
-+                                          // + span: $DIR/inline_cycle.rs:36:9: 36:26
-                                           // + literal: Const { ty: fn() {<C as Call>::call}, val: Value(<ZST>) }
+-                                          // + literal: Const { ty: fn() {<C as Call>::call}, val: Value(<ZST>) }
++                                          // + span: $DIR/inline_cycle.rs:43:9: 43:21
++                                          // + literal: Const { ty: fn() {<A<C> as Call>::call}, val: Value(<ZST>) }
       }
   
       bb1: {
diff --git a/src/test/mir-opt/inline/inline_cycle.two.Inline.diff b/src/test/mir-opt/inline/inline_cycle.two.Inline.diff
index ab1ea0e3b2c..a940848c269 100644
--- a/src/test/mir-opt/inline/inline_cycle.two.Inline.diff
+++ b/src/test/mir-opt/inline/inline_cycle.two.Inline.diff
@@ -9,11 +9,6 @@
 +         debug f => _2;                   // in scope 1 at $DIR/inline_cycle.rs:53:22: 53:23
 +         let _3: ();                      // in scope 1 at $DIR/inline_cycle.rs:54:5: 54:8
 +         let mut _4: ();                  // in scope 1 at $DIR/inline_cycle.rs:54:5: 54:8
-+         scope 2 (inlined <fn() {f} as FnOnce<()>>::call_once - shim(fn() {f})) { // at $DIR/inline_cycle.rs:54:5: 54:8
-+             scope 3 (inlined f) {        // at $SRC_DIR/core/src/ops/function.rs:LL:COL
-+                 let _5: ();              // in scope 3 at $DIR/inline_cycle.rs:59:5: 59:12
-+             }
-+         }
 +     }
   
       bb0: {
@@ -23,23 +18,19 @@
 +         _2 = f;                          // scope 0 at $DIR/inline_cycle.rs:+1:5: +1:12
                                            // mir::Constant
 -                                          // + span: $DIR/inline_cycle.rs:49:5: 49:9
-+                                          // + span: $DIR/inline_cycle.rs:49:10: 49:11
-+                                          // + literal: Const { ty: fn() {f}, val: Value(<ZST>) }
+-                                          // + literal: Const { ty: fn(fn() {f}) {call::<fn() {f}>}, val: Value(<ZST>) }
+-                                          // mir::Constant
+                                           // + span: $DIR/inline_cycle.rs:49:10: 49:11
+                                           // + literal: Const { ty: fn() {f}, val: Value(<ZST>) }
 +         StorageLive(_3);                 // scope 1 at $DIR/inline_cycle.rs:54:5: 54:8
 +         StorageLive(_4);                 // scope 1 at $DIR/inline_cycle.rs:54:5: 54:8
-+         StorageLive(_5);                 // scope 3 at $DIR/inline_cycle.rs:59:5: 59:12
-+         _5 = call::<fn() {f}>(f) -> bb1; // scope 3 at $DIR/inline_cycle.rs:59:5: 59:12
++         _3 = <fn() {f} as FnOnce<()>>::call_once(move _2, move _4) -> bb1; // scope 1 at $DIR/inline_cycle.rs:54:5: 54:8
 +                                          // mir::Constant
-+                                          // + span: $DIR/inline_cycle.rs:59:5: 59:9
-                                           // + literal: Const { ty: fn(fn() {f}) {call::<fn() {f}>}, val: Value(<ZST>) }
-                                           // mir::Constant
--                                          // + span: $DIR/inline_cycle.rs:49:10: 49:11
-+                                          // + span: $DIR/inline_cycle.rs:59:10: 59:11
-                                           // + literal: Const { ty: fn() {f}, val: Value(<ZST>) }
++                                          // + span: $DIR/inline_cycle.rs:54:5: 54:6
++                                          // + literal: Const { ty: extern "rust-call" fn(fn() {f}, ()) -> <fn() {f} as FnOnce<()>>::Output {<fn() {f} as FnOnce<()>>::call_once}, val: Value(<ZST>) }
       }
   
       bb1: {
-+         StorageDead(_5);                 // scope 3 at $DIR/inline_cycle.rs:59:12: 59:13
 +         StorageDead(_4);                 // scope 1 at $DIR/inline_cycle.rs:54:7: 54:8
 +         StorageDead(_3);                 // scope 1 at $DIR/inline_cycle.rs:54:8: 54:9
 +         StorageDead(_2);                 // scope 0 at $DIR/inline_cycle.rs:+1:5: +1:12
diff --git a/src/test/mir-opt/inline/inline_cycle_generic.main.Inline.diff b/src/test/mir-opt/inline/inline_cycle_generic.main.Inline.diff
index 52debab4dd1..04de3e61e5f 100644
--- a/src/test/mir-opt/inline/inline_cycle_generic.main.Inline.diff
+++ b/src/test/mir-opt/inline/inline_cycle_generic.main.Inline.diff
@@ -6,21 +6,18 @@
       let _1: ();                          // in scope 0 at $DIR/inline_cycle_generic.rs:+1:5: +1:24
 +     scope 1 (inlined <C as Call>::call) { // at $DIR/inline_cycle_generic.rs:9:5: 9:24
 +         scope 2 (inlined <B<A> as Call>::call) { // at $DIR/inline_cycle_generic.rs:38:9: 38:31
-+             scope 3 (inlined <A as Call>::call) { // at $DIR/inline_cycle_generic.rs:31:9: 31:28
-+                 scope 4 (inlined <B<C> as Call>::call) { // at $DIR/inline_cycle_generic.rs:23:9: 23:31
-+                 }
-+             }
 +         }
 +     }
   
       bb0: {
           StorageLive(_1);                 // scope 0 at $DIR/inline_cycle_generic.rs:+1:5: +1:24
 -         _1 = <C as Call>::call() -> bb1; // scope 0 at $DIR/inline_cycle_generic.rs:+1:5: +1:24
-+         _1 = <C as Call>::call() -> bb1; // scope 4 at $DIR/inline_cycle_generic.rs:31:9: 31:28
++         _1 = <A as Call>::call() -> bb1; // scope 2 at $DIR/inline_cycle_generic.rs:31:9: 31:28
                                            // mir::Constant
 -                                          // + span: $DIR/inline_cycle_generic.rs:9:5: 9:22
+-                                          // + literal: Const { ty: fn() {<C as Call>::call}, val: Value(<ZST>) }
 +                                          // + span: $DIR/inline_cycle_generic.rs:31:9: 31:26
-                                           // + literal: Const { ty: fn() {<C as Call>::call}, val: Value(<ZST>) }
++                                          // + literal: Const { ty: fn() {<A as Call>::call}, val: Value(<ZST>) }
       }
   
       bb1: {
diff --git a/src/test/mir-opt/inline/inline_diverging.h.Inline.diff b/src/test/mir-opt/inline/inline_diverging.h.Inline.diff
index 75a6ab37008..a01bcf1645b 100644
--- a/src/test/mir-opt/inline/inline_diverging.h.Inline.diff
+++ b/src/test/mir-opt/inline/inline_diverging.h.Inline.diff
@@ -19,14 +19,6 @@
 +             scope 3 {
 +                 debug b => _9;           // in scope 3 at $DIR/inline_diverging.rs:28:9: 28:10
 +             }
-+             scope 6 (inlined <fn() -> ! {sleep} as Fn<()>>::call - shim(fn() -> ! {sleep})) { // at $DIR/inline_diverging.rs:28:13: 28:16
-+                 scope 7 (inlined sleep) { // at $SRC_DIR/core/src/ops/function.rs:LL:COL
-+                 }
-+             }
-+         }
-+         scope 4 (inlined <fn() -> ! {sleep} as Fn<()>>::call - shim(fn() -> ! {sleep})) { // at $DIR/inline_diverging.rs:27:13: 27:16
-+             scope 5 (inlined sleep) {    // at $SRC_DIR/core/src/ops/function.rs:LL:COL
-+             }
 +         }
 +     }
   
@@ -46,11 +38,51 @@
 +         StorageLive(_4);                 // scope 1 at $DIR/inline_diverging.rs:27:13: 27:14
 +         _4 = &_2;                        // scope 1 at $DIR/inline_diverging.rs:27:13: 27:14
 +         StorageLive(_5);                 // scope 1 at $DIR/inline_diverging.rs:27:13: 27:16
-+         goto -> bb1;                     // scope 5 at $DIR/inline_diverging.rs:39:5: 39:12
++         _3 = <fn() -> ! {sleep} as Fn<()>>::call(move _4, move _5) -> [return: bb1, unwind: bb5]; // scope 1 at $DIR/inline_diverging.rs:27:13: 27:16
++                                          // mir::Constant
++                                          // + span: $DIR/inline_diverging.rs:27:13: 27:14
++                                          // + literal: Const { ty: for<'a> extern "rust-call" fn(&'a fn() -> ! {sleep}, ()) -> <fn() -> ! {sleep} as FnOnce<()>>::Output {<fn() -> ! {sleep} as Fn<()>>::call}, val: Value(<ZST>) }
 +     }
 + 
 +     bb1: {
-+         goto -> bb1;                     // scope 5 at $DIR/inline_diverging.rs:39:5: 39:12
++         StorageDead(_5);                 // scope 1 at $DIR/inline_diverging.rs:27:15: 27:16
++         StorageDead(_4);                 // scope 1 at $DIR/inline_diverging.rs:27:15: 27:16
++         StorageLive(_6);                 // scope 2 at $DIR/inline_diverging.rs:28:13: 28:14
++         _6 = &_2;                        // scope 2 at $DIR/inline_diverging.rs:28:13: 28:14
++         StorageLive(_7);                 // scope 2 at $DIR/inline_diverging.rs:28:13: 28:16
++         _9 = <fn() -> ! {sleep} as Fn<()>>::call(move _6, move _7) -> [return: bb2, unwind: bb4]; // scope 2 at $DIR/inline_diverging.rs:28:13: 28:16
++                                          // mir::Constant
++                                          // + span: $DIR/inline_diverging.rs:28:13: 28:14
++                                          // + literal: Const { ty: for<'a> extern "rust-call" fn(&'a fn() -> ! {sleep}, ()) -> <fn() -> ! {sleep} as FnOnce<()>>::Output {<fn() -> ! {sleep} as Fn<()>>::call}, val: Value(<ZST>) }
++     }
++ 
++     bb2: {
++         StorageDead(_7);                 // scope 2 at $DIR/inline_diverging.rs:28:15: 28:16
++         StorageDead(_6);                 // scope 2 at $DIR/inline_diverging.rs:28:15: 28:16
++         StorageLive(_8);                 // scope 3 at $DIR/inline_diverging.rs:29:6: 29:7
++         _8 = move _3;                    // scope 3 at $DIR/inline_diverging.rs:29:6: 29:7
++         Deinit(_1);                      // scope 3 at $DIR/inline_diverging.rs:29:5: 29:11
++         (_1.0: !) = move _8;             // scope 3 at $DIR/inline_diverging.rs:29:5: 29:11
++         (_1.1: !) = move _9;             // scope 3 at $DIR/inline_diverging.rs:29:5: 29:11
++         StorageDead(_8);                 // scope 3 at $DIR/inline_diverging.rs:29:10: 29:11
++         StorageDead(_3);                 // scope 1 at $DIR/inline_diverging.rs:30:1: 30:2
++         drop(_2) -> bb3;                 // scope 1 at $DIR/inline_diverging.rs:30:1: 30:2
++     }
++ 
++     bb3: {
++         unreachable;                     // scope 0 at $DIR/inline_diverging.rs:30:2: 30:2
++     }
++ 
++     bb4 (cleanup): {
++         drop(_3) -> bb5;                 // scope 1 at $DIR/inline_diverging.rs:30:1: 30:2
++     }
++ 
++     bb5 (cleanup): {
++         drop(_2) -> bb6;                 // scope 1 at $DIR/inline_diverging.rs:30:1: 30:2
++     }
++ 
++     bb6 (cleanup): {
++         resume;                          // scope 1 at $DIR/inline_diverging.rs:26:1: 30:2
       }
   }
   
diff --git a/src/test/mir-opt/inline/inline_retag.bar.Inline.after.mir b/src/test/mir-opt/inline/inline_retag.bar.Inline.after.mir
index 75af20d482d..60149ff3606 100644
--- a/src/test/mir-opt/inline/inline_retag.bar.Inline.after.mir
+++ b/src/test/mir-opt/inline/inline_retag.bar.Inline.after.mir
@@ -38,9 +38,7 @@ fn bar() -> bool {
                                          // + literal: Const { ty: &i32, val: Unevaluated(bar, [], Some(promoted[1])) }
         Retag(_10);                      // scope 1 at $DIR/inline_retag.rs:+2:7: +2:9
         _4 = &(*_10);                    // scope 1 at $DIR/inline_retag.rs:+2:7: +2:9
-        Retag(_4);                       // scope 1 at $DIR/inline_retag.rs:+2:7: +2:9
         _3 = &(*_4);                     // scope 1 at $DIR/inline_retag.rs:+2:7: +2:9
-        Retag(_3);                       // scope 1 at $DIR/inline_retag.rs:+2:7: +2:9
         StorageLive(_6);                 // scope 1 at $DIR/inline_retag.rs:+2:11: +2:14
         StorageLive(_7);                 // scope 1 at $DIR/inline_retag.rs:+2:11: +2:14
         _9 = const _;                    // scope 1 at $DIR/inline_retag.rs:+2:11: +2:14
@@ -49,9 +47,7 @@ fn bar() -> bool {
                                          // + literal: Const { ty: &i32, val: Unevaluated(bar, [], Some(promoted[0])) }
         Retag(_9);                       // scope 1 at $DIR/inline_retag.rs:+2:11: +2:14
         _7 = &(*_9);                     // scope 1 at $DIR/inline_retag.rs:+2:11: +2:14
-        Retag(_7);                       // scope 1 at $DIR/inline_retag.rs:+2:11: +2:14
         _6 = &(*_7);                     // scope 1 at $DIR/inline_retag.rs:+2:11: +2:14
-        Retag(_6);                       // scope 1 at $DIR/inline_retag.rs:+2:11: +2:14
         Retag(_3);                       // scope 2 at $DIR/inline_retag.rs:16:8: 16:9
         Retag(_6);                       // scope 2 at $DIR/inline_retag.rs:16:17: 16:18
         StorageLive(_11);                // scope 2 at $DIR/inline_retag.rs:17:5: 17:7
diff --git a/src/test/mir-opt/remove_zsts.get_union.PreCodegen.after.mir b/src/test/mir-opt/remove_zsts.get_union.PreCodegen.after.mir
new file mode 100644
index 00000000000..12e914e25e0
--- /dev/null
+++ b/src/test/mir-opt/remove_zsts.get_union.PreCodegen.after.mir
@@ -0,0 +1,10 @@
+// MIR for `get_union` after PreCodegen
+
+fn get_union() -> Foo {
+    let mut _0: Foo;                     // return place in scope 0 at $DIR/remove_zsts.rs:+0:19: +0:22
+
+    bb0: {
+        Deinit(_0);                      // scope 0 at $DIR/remove_zsts.rs:+1:5: +1:18
+        return;                          // scope 0 at $DIR/remove_zsts.rs:+2:2: +2:2
+    }
+}
diff --git a/src/test/mir-opt/remove_zsts.get_union.RemoveZsts.diff b/src/test/mir-opt/remove_zsts.get_union.RemoveZsts.diff
new file mode 100644
index 00000000000..169b7b1054b
--- /dev/null
+++ b/src/test/mir-opt/remove_zsts.get_union.RemoveZsts.diff
@@ -0,0 +1,19 @@
+- // MIR for `get_union` before RemoveZsts
++ // MIR for `get_union` after RemoveZsts
+  
+  fn get_union() -> Foo {
+      let mut _0: Foo;                     // return place in scope 0 at $DIR/remove_zsts.rs:+0:19: +0:22
+      let mut _1: ();                      // in scope 0 at $DIR/remove_zsts.rs:+1:14: +1:16
+  
+      bb0: {
+          StorageLive(_1);                 // scope 0 at $DIR/remove_zsts.rs:+1:14: +1:16
+-         Deinit(_1);                      // scope 0 at $DIR/remove_zsts.rs:+1:14: +1:16
++         nop;                             // scope 0 at $DIR/remove_zsts.rs:+1:14: +1:16
+          Deinit(_0);                      // scope 0 at $DIR/remove_zsts.rs:+1:5: +1:18
+-         (_0.0: ()) = move _1;            // scope 0 at $DIR/remove_zsts.rs:+1:5: +1:18
++         nop;                             // scope 0 at $DIR/remove_zsts.rs:+1:5: +1:18
+          StorageDead(_1);                 // scope 0 at $DIR/remove_zsts.rs:+1:17: +1:18
+          return;                          // scope 0 at $DIR/remove_zsts.rs:+2:2: +2:2
+      }
+  }
+  
diff --git a/src/test/mir-opt/remove_zsts.rs b/src/test/mir-opt/remove_zsts.rs
new file mode 100644
index 00000000000..1cf7ad6e366
--- /dev/null
+++ b/src/test/mir-opt/remove_zsts.rs
@@ -0,0 +1,14 @@
+union Foo {
+    x: (),
+    y: u64,
+}
+
+// EMIT_MIR remove_zsts.get_union.RemoveZsts.diff
+// EMIT_MIR remove_zsts.get_union.PreCodegen.after.mir
+fn get_union() -> Foo {
+    Foo { x: () }
+}
+
+fn main() {
+    get_union();
+}
diff --git a/src/test/mir-opt/remove_zsts_dont_touch_unions.get_union.RemoveZsts.after.mir b/src/test/mir-opt/remove_zsts_dont_touch_unions.get_union.RemoveZsts.after.mir
deleted file mode 100644
index 7d9e6046202..00000000000
--- a/src/test/mir-opt/remove_zsts_dont_touch_unions.get_union.RemoveZsts.after.mir
+++ /dev/null
@@ -1,15 +0,0 @@
-// MIR for `get_union` after RemoveZsts
-
-fn get_union() -> Foo {
-    let mut _0: Foo;                     // return place in scope 0 at $DIR/remove_zsts_dont_touch_unions.rs:+0:19: +0:22
-    let mut _1: ();                      // in scope 0 at $DIR/remove_zsts_dont_touch_unions.rs:+1:14: +1:16
-
-    bb0: {
-        StorageLive(_1);                 // scope 0 at $DIR/remove_zsts_dont_touch_unions.rs:+1:14: +1:16
-        nop;                             // scope 0 at $DIR/remove_zsts_dont_touch_unions.rs:+1:14: +1:16
-        Deinit(_0);                      // scope 0 at $DIR/remove_zsts_dont_touch_unions.rs:+1:5: +1:18
-        (_0.0: ()) = move _1;            // scope 0 at $DIR/remove_zsts_dont_touch_unions.rs:+1:5: +1:18
-        StorageDead(_1);                 // scope 0 at $DIR/remove_zsts_dont_touch_unions.rs:+1:17: +1:18
-        return;                          // scope 0 at $DIR/remove_zsts_dont_touch_unions.rs:+2:2: +2:2
-    }
-}
diff --git a/src/test/mir-opt/remove_zsts_dont_touch_unions.rs b/src/test/mir-opt/remove_zsts_dont_touch_unions.rs
deleted file mode 100644
index 8b9de9b4d65..00000000000
--- a/src/test/mir-opt/remove_zsts_dont_touch_unions.rs
+++ /dev/null
@@ -1,19 +0,0 @@
-// unit-test: RemoveZsts
-
-// Ensure RemoveZsts doesn't remove ZST assignments to union fields,
-// which causes problems in Miri.
-
-union Foo {
-    x: (),
-    y: u64,
-}
-
-// EMIT_MIR remove_zsts_dont_touch_unions.get_union.RemoveZsts.after.mir
-fn get_union() -> Foo {
-    Foo { x: () }
-}
-
-
-fn main() {
-    get_union();
-}
diff --git a/src/test/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.mir b/src/test/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.mir
index fe57e32a7ac..7b69b3e07d6 100644
--- a/src/test/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.mir
+++ b/src/test/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.mir
@@ -68,9 +68,7 @@ fn array_casts() -> () {
         StorageLive(_3);                 // scope 1 at $DIR/retag.rs:+2:13: +2:19
         StorageLive(_4);                 // scope 1 at $DIR/retag.rs:+2:13: +2:19
         _4 = &mut _1;                    // scope 1 at $DIR/retag.rs:+2:13: +2:19
-        Retag(_4);                       // scope 1 at $DIR/retag.rs:+2:13: +2:19
         _3 = &raw mut (*_4);             // scope 1 at $DIR/retag.rs:+2:13: +2:19
-        Retag([raw] _3);                 // scope 1 at $DIR/retag.rs:+2:13: +2:19
         _2 = move _3 as *mut usize (Pointer(ArrayToPointer)); // scope 1 at $DIR/retag.rs:+2:13: +2:33
         StorageDead(_3);                 // scope 1 at $DIR/retag.rs:+2:32: +2:33
         StorageDead(_4);                 // scope 1 at $DIR/retag.rs:+2:33: +2:34
@@ -96,9 +94,7 @@ fn array_casts() -> () {
         StorageLive(_10);                // scope 4 at $DIR/retag.rs:+6:13: +6:15
         StorageLive(_11);                // scope 4 at $DIR/retag.rs:+6:13: +6:15
         _11 = &_8;                       // scope 4 at $DIR/retag.rs:+6:13: +6:15
-        Retag(_11);                      // scope 4 at $DIR/retag.rs:+6:13: +6:15
         _10 = &raw const (*_11);         // scope 4 at $DIR/retag.rs:+6:13: +6:15
-        Retag([raw] _10);                // scope 4 at $DIR/retag.rs:+6:13: +6:15
         _9 = move _10 as *const usize (Pointer(ArrayToPointer)); // scope 4 at $DIR/retag.rs:+6:13: +6:31
         StorageDead(_10);                // scope 4 at $DIR/retag.rs:+6:30: +6:31
         StorageDead(_11);                // scope 4 at $DIR/retag.rs:+6:31: +6:32
@@ -119,7 +115,6 @@ fn array_casts() -> () {
         StorageDead(_17);                // scope 6 at $DIR/retag.rs:+7:33: +7:34
         _15 = (*_16);                    // scope 6 at $DIR/retag.rs:+7:25: +7:34
         _14 = &_15;                      // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-        Retag(_14);                      // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
         StorageLive(_18);                // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
         _35 = const _;                   // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                          // mir::Constant
@@ -127,7 +122,6 @@ fn array_casts() -> () {
                                          // + literal: Const { ty: &usize, val: Unevaluated(array_casts, [], Some(promoted[0])) }
         Retag(_35);                      // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
         _18 = &(*_35);                   // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-        Retag(_18);                      // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
         Deinit(_13);                     // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
         (_13.0: &usize) = move _14;      // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
         (_13.1: &usize) = move _18;      // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
@@ -164,15 +158,11 @@ fn array_casts() -> () {
         StorageLive(_30);                // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
         StorageLive(_31);                // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
         _31 = &(*_20);                   // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-        Retag(_31);                      // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
         _30 = &(*_31);                   // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-        Retag(_30);                      // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
         StorageLive(_32);                // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
         StorageLive(_33);                // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
         _33 = &(*_21);                   // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-        Retag(_33);                      // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
         _32 = &(*_33);                   // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-        Retag(_32);                      // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
         StorageLive(_34);                // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
         Deinit(_34);                     // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
         discriminant(_34) = 0;           // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
diff --git a/src/test/mir-opt/retag.core.ptr-drop_in_place.Test.SimplifyCfg-make_shim.after.mir b/src/test/mir-opt/retag.core.ptr-drop_in_place.Test.SimplifyCfg-make_shim.after.mir
index cdc413c568f..14f297e948b 100644
--- a/src/test/mir-opt/retag.core.ptr-drop_in_place.Test.SimplifyCfg-make_shim.after.mir
+++ b/src/test/mir-opt/retag.core.ptr-drop_in_place.Test.SimplifyCfg-make_shim.after.mir
@@ -6,7 +6,6 @@ fn std::ptr::drop_in_place(_1: *mut Test) -> () {
     let mut _3: ();                      // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
 
     bb0: {
-        Retag([raw] _1);                 // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
         _2 = &mut (*_1);                 // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
         _3 = <Test as Drop>::drop(move _2) -> bb1; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
                                          // mir::Constant
diff --git a/src/test/mir-opt/retag.main-{closure#0}.SimplifyCfg-elaborate-drops.after.mir b/src/test/mir-opt/retag.main-{closure#0}.SimplifyCfg-elaborate-drops.after.mir
index 96fc7e6493a..9e5c119a2b2 100644
--- a/src/test/mir-opt/retag.main-{closure#0}.SimplifyCfg-elaborate-drops.after.mir
+++ b/src/test/mir-opt/retag.main-{closure#0}.SimplifyCfg-elaborate-drops.after.mir
@@ -15,7 +15,6 @@ fn main::{closure#0}(_1: &[closure@main::{closure#0}], _2: &i32) -> &i32 {
         _3 = _2;                         // scope 0 at $DIR/retag.rs:+1:18: +1:19
         Retag(_3);                       // scope 0 at $DIR/retag.rs:+1:18: +1:19
         _0 = &(*_2);                     // scope 1 at $DIR/retag.rs:+2:9: +2:10
-        Retag(_0);                       // scope 1 at $DIR/retag.rs:+2:9: +2:10
         StorageDead(_3);                 // scope 0 at $DIR/retag.rs:+3:5: +3:6
         return;                          // scope 0 at $DIR/retag.rs:+3:6: +3:6
     }
diff --git a/src/test/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.mir b/src/test/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.mir
index 81225b44ebf..b853e450541 100644
--- a/src/test/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.mir
+++ b/src/test/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.mir
@@ -65,13 +65,10 @@ fn main() -> () {
         Deinit(_5);                      // scope 1 at $DIR/retag.rs:+3:17: +3:24
         (_5.0: i32) = const 0_i32;       // scope 1 at $DIR/retag.rs:+3:17: +3:24
         _4 = &_5;                        // scope 1 at $DIR/retag.rs:+3:17: +3:36
-        Retag(_4);                       // scope 1 at $DIR/retag.rs:+3:17: +3:36
         StorageLive(_6);                 // scope 1 at $DIR/retag.rs:+3:29: +3:35
         StorageLive(_7);                 // scope 1 at $DIR/retag.rs:+3:29: +3:35
         _7 = &mut _1;                    // scope 1 at $DIR/retag.rs:+3:29: +3:35
-        Retag(_7);                       // scope 1 at $DIR/retag.rs:+3:29: +3:35
         _6 = &mut (*_7);                 // scope 1 at $DIR/retag.rs:+3:29: +3:35
-        Retag([2phase] _6);              // scope 1 at $DIR/retag.rs:+3:29: +3:35
         _3 = Test::foo(move _4, move _6) -> [return: bb1, unwind: bb8]; // scope 1 at $DIR/retag.rs:+3:17: +3:36
                                          // mir::Constant
                                          // + span: $DIR/retag.rs:33:25: 33:28
@@ -93,7 +90,6 @@ fn main() -> () {
         _9 = move _3;                    // scope 2 at $DIR/retag.rs:+4:19: +4:20
         Retag(_9);                       // scope 2 at $DIR/retag.rs:+4:19: +4:20
         _8 = &mut (*_9);                 // scope 2 at $DIR/retag.rs:+4:19: +4:20
-        Retag(_8);                       // scope 2 at $DIR/retag.rs:+4:19: +4:20
         StorageDead(_9);                 // scope 2 at $DIR/retag.rs:+4:22: +4:23
         StorageLive(_10);                // scope 3 at $DIR/retag.rs:+5:13: +5:14
         _10 = move _8;                   // scope 3 at $DIR/retag.rs:+5:17: +5:18
@@ -101,7 +97,6 @@ fn main() -> () {
         StorageLive(_11);                // scope 4 at $DIR/retag.rs:+7:13: +7:15
         StorageLive(_12);                // scope 4 at $DIR/retag.rs:+7:18: +7:29
         _12 = &raw mut (*_10);           // scope 4 at $DIR/retag.rs:+7:18: +7:19
-        Retag([raw] _12);                // scope 4 at $DIR/retag.rs:+7:18: +7:19
         _11 = _12;                       // scope 4 at $DIR/retag.rs:+7:18: +7:29
         StorageDead(_12);                // scope 4 at $DIR/retag.rs:+7:29: +7:30
         _2 = const ();                   // scope 1 at $DIR/retag.rs:+2:5: +8:6
@@ -122,9 +117,7 @@ fn main() -> () {
         StorageLive(_17);                // scope 6 at $DIR/retag.rs:+15:16: +15:18
         StorageLive(_18);                // scope 6 at $DIR/retag.rs:+15:16: +15:18
         _18 = &_1;                       // scope 6 at $DIR/retag.rs:+15:16: +15:18
-        Retag(_18);                      // scope 6 at $DIR/retag.rs:+15:16: +15:18
         _17 = &(*_18);                   // scope 6 at $DIR/retag.rs:+15:16: +15:18
-        Retag(_17);                      // scope 6 at $DIR/retag.rs:+15:16: +15:18
         _15 = move _16(move _17) -> bb3; // scope 6 at $DIR/retag.rs:+15:14: +15:19
     }
 
@@ -139,7 +132,6 @@ fn main() -> () {
         Deinit(_21);                     // scope 7 at $DIR/retag.rs:+18:5: +18:12
         (_21.0: i32) = const 0_i32;      // scope 7 at $DIR/retag.rs:+18:5: +18:12
         _20 = &_21;                      // scope 7 at $DIR/retag.rs:+18:5: +18:24
-        Retag(_20);                      // scope 7 at $DIR/retag.rs:+18:5: +18:24
         StorageLive(_22);                // scope 7 at $DIR/retag.rs:+18:21: +18:23
         StorageLive(_23);                // scope 7 at $DIR/retag.rs:+18:21: +18:23
         _28 = const _;                   // scope 7 at $DIR/retag.rs:+18:21: +18:23
@@ -148,9 +140,7 @@ fn main() -> () {
                                          // + literal: Const { ty: &i32, val: Unevaluated(main, [], Some(promoted[0])) }
         Retag(_28);                      // scope 7 at $DIR/retag.rs:+18:21: +18:23
         _23 = &(*_28);                   // scope 7 at $DIR/retag.rs:+18:21: +18:23
-        Retag(_23);                      // scope 7 at $DIR/retag.rs:+18:21: +18:23
         _22 = &(*_23);                   // scope 7 at $DIR/retag.rs:+18:21: +18:23
-        Retag(_22);                      // scope 7 at $DIR/retag.rs:+18:21: +18:23
         _19 = Test::foo_shr(move _20, move _22) -> [return: bb4, unwind: bb7]; // scope 7 at $DIR/retag.rs:+18:5: +18:24
                                          // mir::Constant
                                          // + span: $DIR/retag.rs:48:13: 48:20
@@ -171,7 +161,6 @@ fn main() -> () {
         StorageLive(_25);                // scope 7 at $DIR/retag.rs:+21:9: +21:11
         StorageLive(_26);                // scope 7 at $DIR/retag.rs:+21:14: +21:28
         _26 = &raw const (*_15);         // scope 7 at $DIR/retag.rs:+21:14: +21:16
-        Retag([raw] _26);                // scope 7 at $DIR/retag.rs:+21:14: +21:16
         _25 = _26;                       // scope 7 at $DIR/retag.rs:+21:14: +21:28
         StorageDead(_26);                // scope 7 at $DIR/retag.rs:+21:28: +21:29
         StorageLive(_27);                // scope 8 at $DIR/retag.rs:+23:5: +23:18
diff --git a/src/test/mir-opt/retag.{impl#0}-foo.SimplifyCfg-elaborate-drops.after.mir b/src/test/mir-opt/retag.{impl#0}-foo.SimplifyCfg-elaborate-drops.after.mir
index 08fd655ae29..4b50205fa80 100644
--- a/src/test/mir-opt/retag.{impl#0}-foo.SimplifyCfg-elaborate-drops.after.mir
+++ b/src/test/mir-opt/retag.{impl#0}-foo.SimplifyCfg-elaborate-drops.after.mir
@@ -11,9 +11,7 @@ fn <impl at $DIR/retag.rs:12:1: 12:10>::foo(_1: &Test, _2: &mut i32) -> &mut i32
         Retag([fn entry] _2);            // scope 0 at $DIR/retag.rs:+0:23: +0:24
         StorageLive(_3);                 // scope 0 at $DIR/retag.rs:+1:9: +1:10
         _3 = &mut (*_2);                 // scope 0 at $DIR/retag.rs:+1:9: +1:10
-        Retag(_3);                       // scope 0 at $DIR/retag.rs:+1:9: +1:10
         _0 = &mut (*_3);                 // scope 0 at $DIR/retag.rs:+1:9: +1:10
-        Retag(_0);                       // scope 0 at $DIR/retag.rs:+1:9: +1:10
         StorageDead(_3);                 // scope 0 at $DIR/retag.rs:+2:5: +2:6
         return;                          // scope 0 at $DIR/retag.rs:+2:6: +2:6
     }
diff --git a/src/test/mir-opt/separate_const_switch.identity.SeparateConstSwitch.diff b/src/test/mir-opt/separate_const_switch.identity.SeparateConstSwitch.diff
index f25b3ce724b..b28c6f687f7 100644
--- a/src/test/mir-opt/separate_const_switch.identity.SeparateConstSwitch.diff
+++ b/src/test/mir-opt/separate_const_switch.identity.SeparateConstSwitch.diff
@@ -22,9 +22,6 @@
                   let mut _18: i32;        // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
                   scope 9 {
                       debug e => _16;      // in scope 9 at $SRC_DIR/core/src/result.rs:LL:COL
-                      scope 10 (inlined <i32 as From<i32>>::from) { // at $SRC_DIR/core/src/result.rs:LL:COL
-                          debug t => _18;  // in scope 10 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
-                      }
                   }
               }
           }
@@ -95,18 +92,11 @@
           StorageLive(_17);                // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL
           StorageLive(_18);                // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL
           _18 = move _16;                  // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL
-          _17 = move _18;                  // scope 10 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
-          StorageDead(_18);                // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL
-          Deinit(_0);                      // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL
-          ((_0 as Err).0: i32) = move _17; // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL
-          discriminant(_0) = 1;            // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL
-          StorageDead(_17);                // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL
-          StorageDead(_16);                // scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
-          StorageDead(_8);                 // scope 2 at $DIR/separate_const_switch.rs:+1:9: +1:10
-          StorageDead(_6);                 // scope 0 at $DIR/separate_const_switch.rs:+1:9: +1:10
-          StorageDead(_2);                 // scope 0 at $DIR/separate_const_switch.rs:+1:10: +1:11
-          StorageDead(_3);                 // scope 0 at $DIR/separate_const_switch.rs:+2:1: +2:2
-          return;                          // scope 0 at $DIR/separate_const_switch.rs:+2:2: +2:2
+-         _17 = <i32 as From<i32>>::from(move _18) -> bb8; // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL
++         _17 = <i32 as From<i32>>::from(move _18) -> bb7; // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL
+                                           // mir::Constant
+                                           // + span: $SRC_DIR/core/src/result.rs:LL:COL
+                                           // + literal: Const { ty: fn(i32) -> i32 {<i32 as From<i32>>::from}, val: Value(<ZST>) }
       }
   
 -     bb5: {
@@ -152,5 +142,20 @@
 +         _5 = discriminant(_3);           // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
 +         switchInt(move _5) -> [0_isize: bb1, 1_isize: bb3, otherwise: bb2]; // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
       }
+  
+-     bb8: {
++     bb7: {
+          StorageDead(_18);                // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL
+          Deinit(_0);                      // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL
+          ((_0 as Err).0: i32) = move _17; // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL
+          discriminant(_0) = 1;            // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL
+          StorageDead(_17);                // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL
+          StorageDead(_16);                // scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
+          StorageDead(_8);                 // scope 2 at $DIR/separate_const_switch.rs:+1:9: +1:10
+          StorageDead(_6);                 // scope 0 at $DIR/separate_const_switch.rs:+1:9: +1:10
+          StorageDead(_2);                 // scope 0 at $DIR/separate_const_switch.rs:+1:10: +1:11
+          StorageDead(_3);                 // scope 0 at $DIR/separate_const_switch.rs:+2:1: +2:2
+          return;                          // scope 0 at $DIR/separate_const_switch.rs:+2:2: +2:2
+      }
   }
   
diff --git a/src/test/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs b/src/test/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs
index 2c4309fbe66..3aa57d58908 100644
--- a/src/test/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs
+++ b/src/test/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs
@@ -67,7 +67,7 @@ impl CodegenBackend for TheBackend {
             if crate_type != CrateType::Rlib {
                 sess.fatal(&format!("Crate type is {:?}", crate_type));
             }
-            let output_name = out_filename(sess, crate_type, &outputs, &*crate_name.as_str());
+            let output_name = out_filename(sess, crate_type, &outputs, crate_name);
             let mut out_file = ::std::fs::File::create(output_name).unwrap();
             write!(out_file, "This has been \"compiled\" successfully.").unwrap();
         }
diff --git a/src/test/run-make/coverage-reports/Makefile b/src/test/run-make/coverage-reports/Makefile
index 436aebf1174..d06cd9c6a54 100644
--- a/src/test/run-make/coverage-reports/Makefile
+++ b/src/test/run-make/coverage-reports/Makefile
@@ -80,7 +80,7 @@ ifdef RUSTC_BLESS_TEST
 	rm -f expected_*
 endif
 
-include clear_expected_if_blessed
+-include clear_expected_if_blessed
 
 %: $(SOURCEDIR)/lib/%.rs
 	# Compile the test library with coverage instrumentation
diff --git a/src/test/rustdoc-gui/enum-variants.goml b/src/test/rustdoc-gui/enum-variants.goml
index 230abb236bd..8dfc49285f2 100644
--- a/src/test/rustdoc-gui/enum-variants.goml
+++ b/src/test/rustdoc-gui/enum-variants.goml
@@ -3,3 +3,8 @@ goto: "file://" + |DOC_PATH| + "/test_docs/enum.WhoLetTheDogOut.html"
 
 assert-css: (".variants > .variant", {"margin": "0px 0px 12px"})
 assert-css: (".variants > .docblock", {"margin": "0px 0px 32px 24px"})
+
+assert-css: (
+    "details.non-exhaustive > summary",
+    {"font-family": '"Fira Sans", Arial, NanumBarunGothic, sans-serif'},
+)
diff --git a/src/test/rustdoc-gui/method-margins.goml b/src/test/rustdoc-gui/method-margins.goml
index 397bcd40b36..ed36bcdec17 100644
--- a/src/test/rustdoc-gui/method-margins.goml
+++ b/src/test/rustdoc-gui/method-margins.goml
@@ -1,3 +1,4 @@
+// This test ensures that the margins on methods are coherent inside an impl block.
 goto: "file://" + |DOC_PATH| + "/test_docs/trait_members/struct.HasTrait.html#impl-TraitMembers-for-HasTrait"
 
 assert-count: ("#trait-implementations-list > .rustdoc-toggle", 1)
diff --git a/src/test/rustdoc-gui/scrape-examples-button-focus.goml b/src/test/rustdoc-gui/scrape-examples-button-focus.goml
index 2a263a87a47..a222139f1dc 100644
--- a/src/test/rustdoc-gui/scrape-examples-button-focus.goml
+++ b/src/test/rustdoc-gui/scrape-examples-button-focus.goml
@@ -1,4 +1,17 @@
 goto: "file://" + |DOC_PATH| + "/scrape_examples/fn.test.html"
+
+store-property: (initialScrollTop, ".scraped-example-list > .scraped-example pre", "scrollTop")
+focus: ".scraped-example-list > .scraped-example .next"
+press-key: "Enter"
+assert-property-false: (".scraped-example-list > .scraped-example pre", {
+	"scrollTop": |initialScrollTop|
+})
+focus: ".scraped-example-list > .scraped-example .prev"
+press-key: "Enter"
+assert-property: (".scraped-example-list > .scraped-example pre", {
+	"scrollTop": |initialScrollTop|
+})
+
 store-property: (smallOffsetHeight, ".scraped-example-list > .scraped-example pre", "offsetHeight")
 assert-property-false: (".scraped-example-list > .scraped-example pre", {
 	"scrollHeight": |smallOffsetHeight|
diff --git a/src/test/rustdoc-gui/src/scrape_examples/examples/check.rs b/src/test/rustdoc-gui/src/scrape_examples/examples/check.rs
index 3e69c6086ae..b3f682fe497 100644
--- a/src/test/rustdoc-gui/src/scrape_examples/examples/check.rs
+++ b/src/test/rustdoc-gui/src/scrape_examples/examples/check.rs
@@ -22,4 +22,5 @@ fn main() {
         println!("hello world!");
         println!("hello world!");
     }
+    scrape_examples::test();
 }
diff --git a/src/test/rustdoc-gui/src/test_docs/lib.rs b/src/test/rustdoc-gui/src/test_docs/lib.rs
index dea154c9319..1340511d472 100644
--- a/src/test/rustdoc-gui/src/test_docs/lib.rs
+++ b/src/test/rustdoc-gui/src/test_docs/lib.rs
@@ -76,6 +76,7 @@ impl AsRef<str> for Foo {
 ///
 /// # title!
 #[doc(alias = "ThisIsAnAlias")]
+#[non_exhaustive]
 pub enum WhoLetTheDogOut {
     /// Woof!
     Woof,
diff --git a/src/test/rustdoc-gui/toggle-docs.goml b/src/test/rustdoc-gui/toggle-docs.goml
index b7d10723767..45bb8daf1f2 100644
--- a/src/test/rustdoc-gui/toggle-docs.goml
+++ b/src/test/rustdoc-gui/toggle-docs.goml
@@ -7,6 +7,10 @@ wait-for: 50
 // This is now collapsed so there shouldn't be the "open" attribute on details.
 assert-attribute-false: ("#main-content > details.top-doc", {"open": ""})
 assert-text: ("#toggle-all-docs", "[+]")
+assert-css: (
+    "#main-content > details.top-doc > summary",
+    {"font-family": '"Fira Sans", Arial, NanumBarunGothic, sans-serif'},
+)
 click: "#toggle-all-docs"
 // Not collapsed anymore so the "open" attribute should be back.
 wait-for-attribute: ("#main-content > details.top-doc", {"open": ""})
diff --git a/src/test/rustdoc-ui/z-help.stdout b/src/test/rustdoc-ui/z-help.stdout
index 55154803098..94cf7b94241 100644
--- a/src/test/rustdoc-ui/z-help.stdout
+++ b/src/test/rustdoc-ui/z-help.stdout
@@ -77,6 +77,7 @@
     -Z                         location-detail=val -- what location details should be tracked when using caller_location, either `none`, or a comma separated list of location details, for which valid options are `file`, `line`, and `column` (default: `file,line,column`)
     -Z                                      ls=val -- list the symbols defined by a library crate (default: no)
     -Z                         macro-backtrace=val -- show macro backtraces (default: no)
+    -Z             maximal-hir-to-mir-coverage=val -- save as much information as possible about the correspondence between MIR and HIR as source scopes (default: no)
     -Z                         merge-functions=val -- control the operation of the MergeFunctions LLVM pass, taking the same values as the target option of the same name
     -Z                              meta-stats=val -- gather metadata statistics (default: no)
     -Z                          mir-emit-retag=val -- emit Retagging MIR statements, interpreted e.g., by miri; implies -Zmir-opt-level=0 (default: no)
diff --git a/src/test/ui/associated-inherent-types/issue-104260.rs b/src/test/ui/associated-inherent-types/issue-104260.rs
new file mode 100644
index 00000000000..a73cd1775b4
--- /dev/null
+++ b/src/test/ui/associated-inherent-types/issue-104260.rs
@@ -0,0 +1,14 @@
+// check-pass
+
+#![feature(inherent_associated_types)]
+#![allow(incomplete_features)]
+
+struct Foo;
+
+impl Foo {
+    type Bar<T> = u8;
+}
+
+fn main() {
+    let a: Foo::Bar<()>;
+}
diff --git a/src/test/ui/associated-inherent-types/normalize-projection-0.rs b/src/test/ui/associated-inherent-types/normalize-projection-0.rs
new file mode 100644
index 00000000000..50763ecddf9
--- /dev/null
+++ b/src/test/ui/associated-inherent-types/normalize-projection-0.rs
@@ -0,0 +1,22 @@
+// check-pass
+
+#![feature(inherent_associated_types)]
+#![allow(incomplete_features)]
+
+struct S<T>(T);
+
+impl<T: O> S<T> {
+    type P = <T as O>::P;
+}
+
+trait O {
+    type P;
+}
+
+impl O for i32 {
+    type P = String;
+}
+
+fn main() {
+    let _: S<i32>::P = String::new();
+}
diff --git a/src/test/ui/associated-inherent-types/normalize-projection-1.rs b/src/test/ui/associated-inherent-types/normalize-projection-1.rs
new file mode 100644
index 00000000000..2f7b2551a03
--- /dev/null
+++ b/src/test/ui/associated-inherent-types/normalize-projection-1.rs
@@ -0,0 +1,22 @@
+// check-pass
+
+#![feature(inherent_associated_types)]
+#![allow(incomplete_features)]
+
+struct S;
+
+impl S {
+    type P<T: O> = <T as O>::P;
+}
+
+trait O {
+    type P;
+}
+
+impl O for i32 {
+    type P = String;
+}
+
+fn main() {
+    let _: S::P<i32> = String::new();
+}
diff --git a/src/test/ui/async-await/async-await-let-else.drop-tracking.stderr b/src/test/ui/async-await/async-await-let-else.drop-tracking.stderr
index 3be7f370da3..616623ee077 100644
--- a/src/test/ui/async-await/async-await-let-else.drop-tracking.stderr
+++ b/src/test/ui/async-await/async-await-let-else.drop-tracking.stderr
@@ -40,7 +40,7 @@ LL |   async fn bar2<T>(_: T) -> ! {
 LL | |     panic!()
 LL | | }
    | |_^
-   = note: required because it captures the following types: `ResumeTy`, `Option<bool>`, `impl Future<Output = !>`, `()`
+   = note: required because it captures the following types: `&mut Context<'_>`, `Option<bool>`, `impl Future<Output = !>`, `()`
 note: required because it's used within this `async fn` body
   --> $DIR/async-await-let-else.rs:21:32
    |
diff --git a/src/test/ui/async-await/drop-track-bad-field-in-fru.rs b/src/test/ui/async-await/drop-track-bad-field-in-fru.rs
new file mode 100644
index 00000000000..28ad7767583
--- /dev/null
+++ b/src/test/ui/async-await/drop-track-bad-field-in-fru.rs
@@ -0,0 +1,10 @@
+// compile-flags: -Zdrop-tracking
+// edition: 2021
+
+fn main() {}
+
+async fn foo() {
+    None { value: (), ..Default::default() }.await;
+    //~^ ERROR `Option<_>` is not a future
+    //~| ERROR variant `Option<_>::None` has no field named `value`
+}
diff --git a/src/test/ui/async-await/drop-track-bad-field-in-fru.stderr b/src/test/ui/async-await/drop-track-bad-field-in-fru.stderr
new file mode 100644
index 00000000000..819b64ad77f
--- /dev/null
+++ b/src/test/ui/async-await/drop-track-bad-field-in-fru.stderr
@@ -0,0 +1,23 @@
+error[E0559]: variant `Option<_>::None` has no field named `value`
+  --> $DIR/drop-track-bad-field-in-fru.rs:7:12
+   |
+LL |     None { value: (), ..Default::default() }.await;
+   |            ^^^^^ `Option<_>::None` does not have this field
+
+error[E0277]: `Option<_>` is not a future
+  --> $DIR/drop-track-bad-field-in-fru.rs:7:45
+   |
+LL |     None { value: (), ..Default::default() }.await;
+   |                                             ^^^^^^
+   |                                             |
+   |                                             `Option<_>` is not a future
+   |                                             help: remove the `.await`
+   |
+   = help: the trait `Future` is not implemented for `Option<_>`
+   = note: Option<_> must be a future or must implement `IntoFuture` to be awaited
+   = note: required for `Option<_>` to implement `IntoFuture`
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0277, E0559.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/async-await/in-trait/nested-rpit.rs b/src/test/ui/async-await/in-trait/nested-rpit.rs
new file mode 100644
index 00000000000..ae8e0aed0cc
--- /dev/null
+++ b/src/test/ui/async-await/in-trait/nested-rpit.rs
@@ -0,0 +1,17 @@
+// check-pass
+// edition: 2021
+
+#![feature(async_fn_in_trait)]
+#![feature(return_position_impl_trait_in_trait)]
+#![allow(incomplete_features)]
+
+use std::future::Future;
+use std::marker::PhantomData;
+
+trait Lockable<K, V> {
+    async fn lock_all_entries(&self) -> impl Future<Output = Guard<'_>>;
+}
+
+struct Guard<'a>(PhantomData<&'a ()>);
+
+fn main() {}
diff --git a/src/test/ui/async-await/in-trait/return-type-suggestion.rs b/src/test/ui/async-await/in-trait/return-type-suggestion.rs
new file mode 100644
index 00000000000..3446761d119
--- /dev/null
+++ b/src/test/ui/async-await/in-trait/return-type-suggestion.rs
@@ -0,0 +1,14 @@
+// edition: 2021
+
+#![feature(async_fn_in_trait)]
+//~^ WARN the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
+
+trait A {
+    async fn e() {
+        Ok(())
+        //~^ ERROR mismatched types
+        //~| HELP consider using a semicolon here
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/async-await/in-trait/return-type-suggestion.stderr b/src/test/ui/async-await/in-trait/return-type-suggestion.stderr
new file mode 100644
index 00000000000..5a9b15e54a0
--- /dev/null
+++ b/src/test/ui/async-await/in-trait/return-type-suggestion.stderr
@@ -0,0 +1,23 @@
+warning: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/return-type-suggestion.rs:3:12
+   |
+LL | #![feature(async_fn_in_trait)]
+   |            ^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+error[E0308]: mismatched types
+  --> $DIR/return-type-suggestion.rs:8:9
+   |
+LL |         Ok(())
+   |         ^^^^^^- help: consider using a semicolon here: `;`
+   |         |
+   |         expected `()`, found enum `Result`
+   |
+   = note: expected unit type `()`
+                   found enum `Result<(), _>`
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/async-await/issue-68112.drop_tracking.stderr b/src/test/ui/async-await/issue-68112.drop_tracking.stderr
index f2802698fd5..1c90bedae79 100644
--- a/src/test/ui/async-await/issue-68112.drop_tracking.stderr
+++ b/src/test/ui/async-await/issue-68112.drop_tracking.stderr
@@ -57,7 +57,7 @@ note: required because it appears within the type `impl Future<Output = Arc<RefC
    |
 LL | fn make_non_send_future2() -> impl Future<Output = Arc<RefCell<i32>>> {
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = note: required because it captures the following types: `ResumeTy`, `impl Future<Output = Arc<RefCell<i32>>>`, `()`, `Ready<i32>`
+   = note: required because it captures the following types: `&mut Context<'_>`, `impl Future<Output = Arc<RefCell<i32>>>`, `()`, `Ready<i32>`
 note: required because it's used within this `async` block
   --> $DIR/issue-68112.rs:60:20
    |
diff --git a/src/test/ui/async-await/issue-68112.no_drop_tracking.stderr b/src/test/ui/async-await/issue-68112.no_drop_tracking.stderr
index 38eb85b302f..e09ae7fedd8 100644
--- a/src/test/ui/async-await/issue-68112.no_drop_tracking.stderr
+++ b/src/test/ui/async-await/issue-68112.no_drop_tracking.stderr
@@ -57,7 +57,7 @@ note: required because it appears within the type `impl Future<Output = Arc<RefC
    |
 LL | fn make_non_send_future2() -> impl Future<Output = Arc<RefCell<i32>>> {
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = note: required because it captures the following types: `ResumeTy`, `impl Future<Output = Arc<RefCell<i32>>>`, `()`, `i32`, `Ready<i32>`
+   = note: required because it captures the following types: `&mut Context<'_>`, `impl Future<Output = Arc<RefCell<i32>>>`, `()`, `i32`, `Ready<i32>`
 note: required because it's used within this `async` block
   --> $DIR/issue-68112.rs:60:20
    |
diff --git a/src/test/ui/async-await/issue-69446-fnmut-capture.stderr b/src/test/ui/async-await/issue-69446-fnmut-capture.stderr
index 3d2b0402bc5..e6ad2f0d444 100644
--- a/src/test/ui/async-await/issue-69446-fnmut-capture.stderr
+++ b/src/test/ui/async-await/issue-69446-fnmut-capture.stderr
@@ -14,6 +14,9 @@ LL | |     });
    |
    = note: `FnMut` closures only have access to their captured variables while they are executing...
    = note: ...therefore, they cannot allow references to captured variables to escape
+   = note: requirement occurs because of a mutable reference to `Context<'_>`
+   = note: mutable references are invariant over their type parameter
+   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/async-await/issue-70935-complex-spans.drop_tracking.stderr b/src/test/ui/async-await/issue-70935-complex-spans.drop_tracking.stderr
index 721234aa4a7..a8fd97cde8f 100644
--- a/src/test/ui/async-await/issue-70935-complex-spans.drop_tracking.stderr
+++ b/src/test/ui/async-await/issue-70935-complex-spans.drop_tracking.stderr
@@ -18,7 +18,7 @@ LL |   async fn baz<T>(_c: impl FnMut() -> T) where T: Future<Output=()> {
    |  ___________________________________________________________________^
 LL | | }
    | |_^
-   = note: required because it captures the following types: `ResumeTy`, `impl Future<Output = ()>`, `()`
+   = note: required because it captures the following types: `&mut Context<'_>`, `impl Future<Output = ()>`, `()`
 note: required because it's used within this `async` block
   --> $DIR/issue-70935-complex-spans.rs:16:5
    |
diff --git a/src/test/ui/async-await/partial-drop-partial-reinit.drop_tracking.stderr b/src/test/ui/async-await/partial-drop-partial-reinit.drop_tracking.stderr
index 17b4ef7bdc6..25876d50840 100644
--- a/src/test/ui/async-await/partial-drop-partial-reinit.drop_tracking.stderr
+++ b/src/test/ui/async-await/partial-drop-partial-reinit.drop_tracking.stderr
@@ -11,7 +11,7 @@ LL | async fn foo() {
    |
    = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `NotSend`
    = note: required because it appears within the type `(NotSend,)`
-   = note: required because it captures the following types: `ResumeTy`, `(NotSend,)`, `()`, `impl Future<Output = ()>`
+   = note: required because it captures the following types: `&mut Context<'_>`, `(NotSend,)`, `()`, `impl Future<Output = ()>`
 note: required because it's used within this `async fn` body
   --> $DIR/partial-drop-partial-reinit.rs:31:16
    |
diff --git a/src/test/ui/async-await/partial-drop-partial-reinit.no_drop_tracking.stderr b/src/test/ui/async-await/partial-drop-partial-reinit.no_drop_tracking.stderr
index 34d8a159f10..dba2a620779 100644
--- a/src/test/ui/async-await/partial-drop-partial-reinit.no_drop_tracking.stderr
+++ b/src/test/ui/async-await/partial-drop-partial-reinit.no_drop_tracking.stderr
@@ -11,7 +11,7 @@ LL | async fn foo() {
    |
    = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `NotSend`
    = note: required because it appears within the type `(NotSend,)`
-   = note: required because it captures the following types: `ResumeTy`, `(NotSend,)`, `impl Future<Output = ()>`, `()`
+   = note: required because it captures the following types: `&mut Context<'_>`, `(NotSend,)`, `impl Future<Output = ()>`, `()`
 note: required because it's used within this `async fn` body
   --> $DIR/partial-drop-partial-reinit.rs:31:16
    |
diff --git a/src/test/ui/async-await/track-caller/issue-105134.rs b/src/test/ui/async-await/track-caller/issue-105134.rs
new file mode 100644
index 00000000000..4e52b8e250b
--- /dev/null
+++ b/src/test/ui/async-await/track-caller/issue-105134.rs
@@ -0,0 +1,11 @@
+// check-pass
+// edition:2021
+
+#[track_caller]
+fn f() {
+    let _ = async {};
+}
+
+fn main() {
+    f();
+}
diff --git a/src/test/ui/async-await/track-caller/panic-track-caller.rs b/src/test/ui/async-await/track-caller/panic-track-caller.rs
index b113c56412f..5ebfeb3f36a 100644
--- a/src/test/ui/async-await/track-caller/panic-track-caller.rs
+++ b/src/test/ui/async-await/track-caller/panic-track-caller.rs
@@ -54,6 +54,19 @@ async fn foo_track_caller() {
     bar_track_caller().await
 }
 
+struct Foo;
+
+impl Foo {
+    #[track_caller]
+    async fn bar_assoc() {
+        panic!();
+    }
+}
+
+async fn foo_assoc() {
+    Foo::bar_assoc().await
+}
+
 fn panicked_at(f: impl FnOnce() + panic::UnwindSafe) -> u32 {
     let loc = Arc::new(Mutex::new(None));
 
@@ -73,4 +86,5 @@ fn panicked_at(f: impl FnOnce() + panic::UnwindSafe) -> u32 {
 fn main() {
     assert_eq!(panicked_at(|| block_on(foo())), 41);
     assert_eq!(panicked_at(|| block_on(foo_track_caller())), 54);
+    assert_eq!(panicked_at(|| block_on(foo_assoc())), 67);
 }
diff --git a/src/test/ui/auto-traits/bad-generics-on-dyn.rs b/src/test/ui/auto-traits/bad-generics-on-dyn.rs
new file mode 100644
index 00000000000..3f8ac14c72d
--- /dev/null
+++ b/src/test/ui/auto-traits/bad-generics-on-dyn.rs
@@ -0,0 +1,11 @@
+#![feature(auto_traits)]
+
+auto trait Trait1<'a> {}
+//~^ ERROR auto traits cannot have generic parameters
+
+fn f<'a>(x: &dyn Trait1<'a>)
+{}
+
+fn main() {
+    f(&1);
+}
diff --git a/src/test/ui/auto-traits/bad-generics-on-dyn.stderr b/src/test/ui/auto-traits/bad-generics-on-dyn.stderr
new file mode 100644
index 00000000000..ade69ced606
--- /dev/null
+++ b/src/test/ui/auto-traits/bad-generics-on-dyn.stderr
@@ -0,0 +1,11 @@
+error[E0567]: auto traits cannot have generic parameters
+  --> $DIR/bad-generics-on-dyn.rs:3:18
+   |
+LL | auto trait Trait1<'a> {}
+   |            ------^^^^ help: remove the parameters
+   |            |
+   |            auto trait cannot have generic parameters
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0567`.
diff --git a/src/test/ui/binop/binop-mul-i32-f32.stderr b/src/test/ui/binop/binop-mul-i32-f32.stderr
index 21c490965b1..c986bc3fd1e 100644
--- a/src/test/ui/binop/binop-mul-i32-f32.stderr
+++ b/src/test/ui/binop/binop-mul-i32-f32.stderr
@@ -6,15 +6,10 @@ LL |     x * y
    |
    = help: the trait `Mul<f32>` is not implemented for `i32`
    = help: the following other types implement trait `Mul<Rhs>`:
-             <&'a f32 as Mul<f32>>
-             <&'a f64 as Mul<f64>>
-             <&'a i128 as Mul<i128>>
-             <&'a i16 as Mul<i16>>
              <&'a i32 as Mul<i32>>
-             <&'a i64 as Mul<i64>>
-             <&'a i8 as Mul<i8>>
-             <&'a isize as Mul<isize>>
-           and 49 others
+             <&i32 as Mul<&i32>>
+             <i32 as Mul<&i32>>
+             <i32 as Mul>
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/const-generics/defaults/rp_impl_trait_fail.stderr b/src/test/ui/const-generics/defaults/rp_impl_trait_fail.stderr
index f2e7777ce68..a46bd53520b 100644
--- a/src/test/ui/const-generics/defaults/rp_impl_trait_fail.stderr
+++ b/src/test/ui/const-generics/defaults/rp_impl_trait_fail.stderr
@@ -18,9 +18,7 @@ LL |
 LL |     1_u32
    |     ----- return type was inferred to be `u32` here
    |
-   = help: the following other types implement trait `Traitor<N, M>`:
-             <u32 as Traitor<N, 2>>
-             <u64 as Traitor<1, 2>>
+   = help: the trait `Traitor<N, 2>` is implemented for `u32`
 
 error[E0277]: the trait bound `u64: Traitor` is not satisfied
   --> $DIR/rp_impl_trait_fail.rs:21:13
@@ -31,9 +29,7 @@ LL |
 LL |     1_u64
    |     ----- return type was inferred to be `u64` here
    |
-   = help: the following other types implement trait `Traitor<N, M>`:
-             <u32 as Traitor<N, 2>>
-             <u64 as Traitor<1, 2>>
+   = help: the trait `Traitor<1, 2>` is implemented for `u64`
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/const-generics/defaults/self-referential.rs b/src/test/ui/const-generics/defaults/self-referential.rs
new file mode 100644
index 00000000000..14a870dc39b
--- /dev/null
+++ b/src/test/ui/const-generics/defaults/self-referential.rs
@@ -0,0 +1,4 @@
+trait Foo<const M: u8, const M: u8 = M> {}
+//~^ ERROR the name `M` is already used for a generic parameter in this item's generic parameters
+impl Foo<2> for () {}
+fn main() {}
diff --git a/src/test/ui/const-generics/defaults/self-referential.stderr b/src/test/ui/const-generics/defaults/self-referential.stderr
new file mode 100644
index 00000000000..170c1f7f7b2
--- /dev/null
+++ b/src/test/ui/const-generics/defaults/self-referential.stderr
@@ -0,0 +1,11 @@
+error[E0403]: the name `M` is already used for a generic parameter in this item's generic parameters
+  --> $DIR/self-referential.rs:1:30
+   |
+LL | trait Foo<const M: u8, const M: u8 = M> {}
+   |                 -            ^ already used
+   |                 |
+   |                 first use of `M`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0403`.
diff --git a/src/test/ui/const-generics/generic_const_exprs/const_kind_expr/wf_obligation.rs b/src/test/ui/const-generics/generic_const_exprs/const_kind_expr/wf_obligation.rs
new file mode 100644
index 00000000000..6093fc70b16
--- /dev/null
+++ b/src/test/ui/const-generics/generic_const_exprs/const_kind_expr/wf_obligation.rs
@@ -0,0 +1,22 @@
+#![feature(generic_const_exprs, generic_arg_infer)]
+#![allow(incomplete_features)]
+
+// minimized repro for #105205
+//
+// the `foo::<_, L>` call results in a `WellFormed(_)` obligation and a
+// `ConstEvaluatable(Unevaluated(_ + 1 + L))` obligation. Attempting to fulfill the latter
+// unifies the `_` with `Expr(L - 1)` from the paramenv which turns the `WellFormed`
+// obligation into `WellFormed(Expr(L - 1))`
+
+fn foo<const N: usize, const M: usize>(_: [(); N + 1 + M]) {}
+
+fn ice<const L: usize>()
+where
+    [(); (L - 1) + 1 + L]:,
+{
+    foo::<_, L>([(); L + 1 + L]);
+    //~^ ERROR: mismatched types
+    //~^^ ERROR: unconstrained generic constant
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/generic_const_exprs/const_kind_expr/wf_obligation.stderr b/src/test/ui/const-generics/generic_const_exprs/const_kind_expr/wf_obligation.stderr
new file mode 100644
index 00000000000..da5194696e6
--- /dev/null
+++ b/src/test/ui/const-generics/generic_const_exprs/const_kind_expr/wf_obligation.stderr
@@ -0,0 +1,20 @@
+error[E0308]: mismatched types
+  --> $DIR/wf_obligation.rs:17:17
+   |
+LL |     foo::<_, L>([(); L + 1 + L]);
+   |                 ^^^^^^^^^^^^^^^ expected `N + 1 + M`, found `L + 1 + L`
+   |
+   = note: expected constant `N + 1 + M`
+              found constant `L + 1 + L`
+
+error: unconstrained generic constant
+  --> $DIR/wf_obligation.rs:17:22
+   |
+LL |     foo::<_, L>([(); L + 1 + L]);
+   |                      ^^^^^^^^^
+   |
+   = help: try adding a `where` bound using this expression: `where [(); L + 1 + L]:`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/const-generics/generic_const_exprs/normed_to_param_is_evaluatable.rs b/src/test/ui/const-generics/generic_const_exprs/normed_to_param_is_evaluatable.rs
new file mode 100644
index 00000000000..b37b354ae21
--- /dev/null
+++ b/src/test/ui/const-generics/generic_const_exprs/normed_to_param_is_evaluatable.rs
@@ -0,0 +1,12 @@
+// check-pass
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features, unused_braces)]
+
+#[rustfmt::skip]
+fn foo<const N: usize>() {
+    bar::<{{{{{{ N }}}}}}>();
+}
+
+fn bar<const N: usize>() {}
+
+fn main() {}
diff --git a/src/test/ui/consts/const-eval/const-eval-overflow-3b.stderr b/src/test/ui/consts/const-eval/const-eval-overflow-3b.stderr
index c685922c456..f199170018f 100644
--- a/src/test/ui/consts/const-eval/const-eval-overflow-3b.stderr
+++ b/src/test/ui/consts/const-eval/const-eval-overflow-3b.stderr
@@ -12,15 +12,10 @@ LL |     = [0; (i8::MAX + 1u8) as usize];
    |
    = help: the trait `~const Add<u8>` is not implemented for `i8`
    = help: the following other types implement trait `Add<Rhs>`:
-             <&'a f32 as Add<f32>>
-             <&'a f64 as Add<f64>>
-             <&'a i128 as Add<i128>>
-             <&'a i16 as Add<i16>>
-             <&'a i32 as Add<i32>>
-             <&'a i64 as Add<i64>>
              <&'a i8 as Add<i8>>
-             <&'a isize as Add<isize>>
-           and 48 others
+             <&i8 as Add<&i8>>
+             <i8 as Add<&i8>>
+             <i8 as Add>
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/consts/const-eval/const-eval-overflow-4b.stderr b/src/test/ui/consts/const-eval/const-eval-overflow-4b.stderr
index b396079240a..1f8e402317a 100644
--- a/src/test/ui/consts/const-eval/const-eval-overflow-4b.stderr
+++ b/src/test/ui/consts/const-eval/const-eval-overflow-4b.stderr
@@ -12,15 +12,10 @@ LL |     : [u32; (i8::MAX as i8 + 1u8) as usize]
    |
    = help: the trait `~const Add<u8>` is not implemented for `i8`
    = help: the following other types implement trait `Add<Rhs>`:
-             <&'a f32 as Add<f32>>
-             <&'a f64 as Add<f64>>
-             <&'a i128 as Add<i128>>
-             <&'a i16 as Add<i16>>
-             <&'a i32 as Add<i32>>
-             <&'a i64 as Add<i64>>
              <&'a i8 as Add<i8>>
-             <&'a isize as Add<isize>>
-           and 48 others
+             <&i8 as Add<&i8>>
+             <i8 as Add<&i8>>
+             <i8 as Add>
 
 error[E0604]: only `u8` can be cast as `char`, not `i8`
   --> $DIR/const-eval-overflow-4b.rs:22:13
diff --git a/src/test/ui/diagnostic-width/long-E0308.rs b/src/test/ui/diagnostic-width/long-E0308.rs
new file mode 100644
index 00000000000..3fd7a7110fd
--- /dev/null
+++ b/src/test/ui/diagnostic-width/long-E0308.rs
@@ -0,0 +1,86 @@
+// compile-flags: --diagnostic-width=60
+// normalize-stderr-test: "long-type-\d+" -> "long-type-hash"
+
+struct Atype<T, K>(T, K);
+struct Btype<T, K>(T, K);
+struct Ctype<T, K>(T, K);
+
+fn main() {
+    let x: Atype<
+      Btype<
+        Ctype<
+          Atype<
+            Btype<
+              Ctype<
+                Atype<
+                  Btype<
+                    Ctype<i32, i32>,
+                    i32
+                  >,
+                  i32
+                >,
+                i32
+              >,
+              i32
+            >,
+            i32
+          >,
+          i32
+        >,
+        i32
+      >,
+      i32
+    > = Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(
+        Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(
+            Ok("")
+        ))))))))))))))))))))))))))))))
+    ))))))))))))))))))))))))))))));
+    //~^^^^^ ERROR E0308
+
+    let _ = Some(Ok(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(
+        Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(
+            Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(
+                Some(Some(Some(Some(Some(Some(Some(Some(Some("")))))))))
+            )))))))))))))))))
+        ))))))))))))))))))
+    ))))))))))))))))) == Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(
+        Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(
+            Ok(Ok(Ok(Ok(Ok(Ok(Ok("")))))))
+        ))))))))))))))))))))))))))))))
+    ))))))))))))))))))))))));
+    //~^^^^^ ERROR E0308
+
+    let x: Atype<
+      Btype<
+        Ctype<
+          Atype<
+            Btype<
+              Ctype<
+                Atype<
+                  Btype<
+                    Ctype<i32, i32>,
+                    i32
+                  >,
+                  i32
+                >,
+                i32
+              >,
+              i32
+            >,
+            i32
+          >,
+          i32
+        >,
+        i32
+      >,
+      i32
+    > = ();
+    //~^ ERROR E0308
+
+    let _: () = Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(
+        Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(
+            Ok(Ok(Ok(Ok(Ok(Ok(Ok("")))))))
+        ))))))))))))))))))))))))))))))
+    ))))))))))))))))))))))));
+    //~^^^^^ ERROR E0308
+}
diff --git a/src/test/ui/diagnostic-width/long-E0308.stderr b/src/test/ui/diagnostic-width/long-E0308.stderr
new file mode 100644
index 00000000000..487ab23a1c1
--- /dev/null
+++ b/src/test/ui/diagnostic-width/long-E0308.stderr
@@ -0,0 +1,80 @@
+error[E0308]: mismatched types
+  --> $DIR/long-E0308.rs:33:9
+   |
+LL |        let x: Atype<
+   |  _____________-
+LL | |        Btype<
+LL | |          Ctype<
+LL | |            Atype<
+...  |
+LL | |        i32
+LL | |      > = Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok...
+   | | _____-___^
+   | ||_____|
+   |  |     expected due to this
+LL |  |         Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok...
+LL |  |             Ok("")
+LL |  |         ))))))))))))))))))))))))))))))
+LL |  |     ))))))))))))))))))))))))))))));
+   |  |__________________________________^ expected struct `Atype`, found enum `Result`
+   |
+   = note: expected struct `Atype<Btype<..., ...>, ...>`
+           the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/long-E0308/long-E0308.long-type-hash.txt'
+                found enum `Result<Result<..., ...>, ...>`
+           the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/long-E0308/long-E0308.long-type-hash.txt'
+
+error[E0308]: mismatched types
+  --> $DIR/long-E0308.rs:46:26
+   |
+LL |       ))))))))))))))))) == Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(O...
+   |  __________________________^
+LL | |         Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(...
+LL | |             Ok(Ok(Ok(Ok(Ok(Ok(Ok("")))))))
+LL | |         ))))))))))))))))))))))))))))))
+LL | |     ))))))))))))))))))))))));
+   | |____________________________^ expected enum `Option`, found enum `Result`
+   |
+   = note: expected enum `Option<Result<..., ...>>`
+           the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/long-E0308/long-E0308.long-type-hash.txt'
+              found enum `Result<Result<..., ...>, ...>`
+           the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/long-E0308/long-E0308.long-type-hash.txt'
+
+error[E0308]: mismatched types
+  --> $DIR/long-E0308.rs:77:9
+   |
+LL |       let x: Atype<
+   |  ____________-
+LL | |       Btype<
+LL | |         Ctype<
+LL | |           Atype<
+...  |
+LL | |       i32
+LL | |     > = ();
+   | |     -   ^^ expected struct `Atype`, found `()`
+   | |_____|
+   |       expected due to this
+   |
+   = note: expected struct `Atype<Btype<..., ...>, ...>`
+           the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/long-E0308/long-E0308.long-type-hash.txt'
+           found unit type `()`
+
+error[E0308]: mismatched types
+  --> $DIR/long-E0308.rs:80:17
+   |
+LL |       let _: () = Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(O...
+   |  ____________--___^
+   | |            |
+   | |            expected due to this
+LL | |         Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(...
+LL | |             Ok(Ok(Ok(Ok(Ok(Ok(Ok("")))))))
+LL | |         ))))))))))))))))))))))))))))))
+LL | |     ))))))))))))))))))))))));
+   | |____________________________^ expected `()`, found enum `Result`
+   |
+   = note: expected unit type `()`
+                   found enum `Result<Result<..., ...>, ...>`
+           the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/long-E0308/long-E0308.long-type-hash.txt'
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr b/src/test/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr
index d27b05fe7f7..7229b9ac986 100644
--- a/src/test/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr
+++ b/src/test/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr
@@ -12,10 +12,6 @@ LL |     Foo::<i32>::bar(&1i8);
              <i8 as Foo<u32>>
              <i8 as Foo<u64>>
              <i8 as Foo<u8>>
-             <u8 as Foo<bool>>
-             <u8 as Foo<u16>>
-             <u8 as Foo<u32>>
-             <u8 as Foo<u64>>
 
 error[E0277]: the trait bound `u8: Foo<i32>` is not satisfied
   --> $DIR/issue-39802-show-5-trait-impls.rs:25:21
@@ -26,11 +22,6 @@ LL |     Foo::<i32>::bar(&1u8);
    |     required by a bound introduced by this call
    |
    = help: the following other types implement trait `Foo<B>`:
-             <i8 as Foo<bool>>
-             <i8 as Foo<u16>>
-             <i8 as Foo<u32>>
-             <i8 as Foo<u64>>
-             <i8 as Foo<u8>>
              <u8 as Foo<bool>>
              <u8 as Foo<u16>>
              <u8 as Foo<u32>>
diff --git a/src/test/ui/duplicate/duplicate-type-parameter.stderr b/src/test/ui/duplicate/duplicate-type-parameter.stderr
index 6754574f0b9..628f898d5c8 100644
--- a/src/test/ui/duplicate/duplicate-type-parameter.stderr
+++ b/src/test/ui/duplicate/duplicate-type-parameter.stderr
@@ -55,10 +55,10 @@ LL | impl<T,T> Qux<T,T> for Option<T> {}
    |      first use of `T`
 
 error[E0207]: the type parameter `T` is not constrained by the impl trait, self type, or predicates
-  --> $DIR/duplicate-type-parameter.rs:24:6
+  --> $DIR/duplicate-type-parameter.rs:24:8
    |
 LL | impl<T,T> Qux<T,T> for Option<T> {}
-   |      ^ unconstrained type parameter
+   |        ^ unconstrained type parameter
 
 error: aborting due to 8 previous errors
 
diff --git a/src/test/ui/error-codes/E0275.stderr b/src/test/ui/error-codes/E0275.stderr
index 49a4d984af9..451a683ac8a 100644
--- a/src/test/ui/error-codes/E0275.stderr
+++ b/src/test/ui/error-codes/E0275.stderr
@@ -5,7 +5,7 @@ LL | impl<T> Foo for T where Bar<T>: Foo {}
    |                                 ^^^
    |
    = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`E0275`)
-note: required for `Bar<Bar<Bar<Bar<Bar<Bar<...>>>>>>` to implement `Foo`
+note: required for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<...>>>>>>>>>>>>>>>>>>>>>` to implement `Foo`
   --> $DIR/E0275.rs:6:9
    |
 LL | impl<T> Foo for T where Bar<T>: Foo {}
diff --git a/src/test/ui/feature-gates/feature-gate-impl_trait_in_fn_trait_return.stderr b/src/test/ui/feature-gates/feature-gate-impl_trait_in_fn_trait_return.stderr
index c485bc5c3ab..760dcb615c8 100644
--- a/src/test/ui/feature-gates/feature-gate-impl_trait_in_fn_trait_return.stderr
+++ b/src/test/ui/feature-gates/feature-gate-impl_trait_in_fn_trait_return.stderr
@@ -3,12 +3,18 @@ error[E0562]: `impl Trait` only allowed in function and inherent method return t
    |
 LL | fn f() -> impl Fn() -> impl Sized { || () }
    |                        ^^^^^^^^^^
+   |
+   = note: see issue #99697 <https://github.com/rust-lang/rust/issues/99697> for more information
+   = help: add `#![feature(impl_trait_in_fn_trait_return)]` to the crate attributes to enable
 
 error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait return
   --> $DIR/feature-gate-impl_trait_in_fn_trait_return.rs:3:32
    |
 LL | fn g() -> &'static dyn Fn() -> impl Sized { &|| () }
    |                                ^^^^^^^^^^
+   |
+   = note: see issue #99697 <https://github.com/rust-lang/rust/issues/99697> for more information
+   = help: add `#![feature(impl_trait_in_fn_trait_return)]` to the crate attributes to enable
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/feature-gates/feature-gate-linkage.rs b/src/test/ui/feature-gates/feature-gate-linkage.rs
index 15b8d442aeb..505f31ec638 100644
--- a/src/test/ui/feature-gates/feature-gate-linkage.rs
+++ b/src/test/ui/feature-gates/feature-gate-linkage.rs
@@ -1,5 +1,5 @@
 extern "C" {
-    #[linkage = "extern_weak"] static foo: isize;
+    #[linkage = "extern_weak"] static foo: *mut isize;
     //~^ ERROR: the `linkage` attribute is experimental and not portable
 }
 
diff --git a/src/test/ui/feature-gates/feature-gate-linkage.stderr b/src/test/ui/feature-gates/feature-gate-linkage.stderr
index 3e5b79bfd41..a1c73e555ef 100644
--- a/src/test/ui/feature-gates/feature-gate-linkage.stderr
+++ b/src/test/ui/feature-gates/feature-gate-linkage.stderr
@@ -1,7 +1,7 @@
 error[E0658]: the `linkage` attribute is experimental and not portable across platforms
   --> $DIR/feature-gate-linkage.rs:2:5
    |
-LL |     #[linkage = "extern_weak"] static foo: isize;
+LL |     #[linkage = "extern_weak"] static foo: *mut isize;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: see issue #29603 <https://github.com/rust-lang/rust/issues/29603> for more information
diff --git a/src/test/ui/generic-associated-types/own-bound-span.rs b/src/test/ui/generic-associated-types/own-bound-span.rs
new file mode 100644
index 00000000000..3699f7296f5
--- /dev/null
+++ b/src/test/ui/generic-associated-types/own-bound-span.rs
@@ -0,0 +1,17 @@
+struct S;
+
+trait D {
+    type P<T: Copy>;
+    //~^ NOTE required by this bound in `D::P`
+    //~| NOTE required by a bound in `D::P`
+}
+
+impl D for S {
+    type P<T: Copy> = ();
+}
+
+fn main() {
+    let _: <S as D>::P<String>;
+    //~^ ERROR the trait bound `String: Copy` is not satisfied
+    //~| NOTE the trait `Copy` is not implemented for `String`
+}
diff --git a/src/test/ui/generic-associated-types/own-bound-span.stderr b/src/test/ui/generic-associated-types/own-bound-span.stderr
new file mode 100644
index 00000000000..8ab8ea623b2
--- /dev/null
+++ b/src/test/ui/generic-associated-types/own-bound-span.stderr
@@ -0,0 +1,15 @@
+error[E0277]: the trait bound `String: Copy` is not satisfied
+  --> $DIR/own-bound-span.rs:14:12
+   |
+LL |     let _: <S as D>::P<String>;
+   |            ^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `String`
+   |
+note: required by a bound in `D::P`
+  --> $DIR/own-bound-span.rs:4:15
+   |
+LL |     type P<T: Copy>;
+   |               ^^^^ required by this bound in `D::P`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/impl-trait/equality.stderr b/src/test/ui/impl-trait/equality.stderr
index 1841b8e5dcd..69f4cbbbf42 100644
--- a/src/test/ui/impl-trait/equality.stderr
+++ b/src/test/ui/impl-trait/equality.stderr
@@ -30,15 +30,10 @@ LL |         n + sum_to(n - 1)
    |
    = help: the trait `Add<impl Foo>` is not implemented for `u32`
    = help: the following other types implement trait `Add<Rhs>`:
-             <&'a f32 as Add<f32>>
-             <&'a f64 as Add<f64>>
-             <&'a i128 as Add<i128>>
-             <&'a i16 as Add<i16>>
-             <&'a i32 as Add<i32>>
-             <&'a i64 as Add<i64>>
-             <&'a i8 as Add<i8>>
-             <&'a isize as Add<isize>>
-           and 48 others
+             <&'a u32 as Add<u32>>
+             <&u32 as Add<&u32>>
+             <u32 as Add<&u32>>
+             <u32 as Add>
 
 error: aborting due to 2 previous errors; 1 warning emitted
 
diff --git a/src/test/ui/impl-trait/nested-return-type4.rs b/src/test/ui/impl-trait/nested-return-type4.rs
new file mode 100644
index 00000000000..cec70bb1a0d
--- /dev/null
+++ b/src/test/ui/impl-trait/nested-return-type4.rs
@@ -0,0 +1,8 @@
+// edition: 2021
+
+fn test<'s: 's>(s: &'s str) -> impl std::future::Future<Output = impl Sized> {
+    async move { let _s = s; }
+    //~^ ERROR hidden type for `impl Future<Output = impl Sized>` captures lifetime that does not appear in bounds
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/nested-return-type4.stderr b/src/test/ui/impl-trait/nested-return-type4.stderr
new file mode 100644
index 00000000000..e761a60e79c
--- /dev/null
+++ b/src/test/ui/impl-trait/nested-return-type4.stderr
@@ -0,0 +1,20 @@
+error[E0700]: hidden type for `impl Future<Output = impl Sized>` captures lifetime that does not appear in bounds
+  --> $DIR/nested-return-type4.rs:4:5
+   |
+LL | fn test<'s: 's>(s: &'s str) -> impl std::future::Future<Output = impl Sized> {
+   |         -- hidden type `[async block@$DIR/nested-return-type4.rs:4:5: 4:31]` captures the lifetime `'s` as defined here
+LL |     async move { let _s = s; }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: to declare that `impl Future<Output = impl Sized>` captures `'s`, you can add an explicit `'s` lifetime bound
+   |
+LL | fn test<'s: 's>(s: &'s str) -> impl std::future::Future<Output = impl Sized> + 's {
+   |                                                                              ++++
+help: to declare that `impl Sized` captures `'s`, you can add an explicit `'s` lifetime bound
+   |
+LL | fn test<'s: 's>(s: &'s str) -> impl std::future::Future<Output = impl Sized + 's> {
+   |                                                                             ++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0700`.
diff --git a/src/test/ui/issues/issue-105330.rs b/src/test/ui/issues/issue-105330.rs
new file mode 100644
index 00000000000..86e45f10b0e
--- /dev/null
+++ b/src/test/ui/issues/issue-105330.rs
@@ -0,0 +1,21 @@
+pub trait TraitWAssocConst {
+    const A:   usize;
+}
+pub struct Demo {}
+
+impl TraitWAssocConst for impl Demo { //~ ERROR E0404
+    //~^ ERROR E0562
+    pubconst A: str = 32; //~ ERROR expected one of
+}
+
+fn foo<A: TraitWAssocConst<A=32>>() { //~ ERROR E0658
+    foo::<Demo>()(); //~ ERROR E0271
+    //~^ ERROR E0618
+    //~| ERROR E0277
+}
+
+fn main<A: TraitWAssocConst<A=32>>() { //~ ERROR E0131
+    //~^ ERROR E0658
+    foo::<Demo>(); //~ ERROR E0277
+    //~^ ERROR E0271
+}
diff --git a/src/test/ui/issues/issue-105330.stderr b/src/test/ui/issues/issue-105330.stderr
new file mode 100644
index 00000000000..92f2ccb6544
--- /dev/null
+++ b/src/test/ui/issues/issue-105330.stderr
@@ -0,0 +1,109 @@
+error: expected one of `!` or `::`, found `A`
+  --> $DIR/issue-105330.rs:8:14
+   |
+LL | impl TraitWAssocConst for impl Demo {
+   |                                     - while parsing this item list starting here
+LL |
+LL |     pubconst A: str = 32;
+   |              ^ expected one of `!` or `::`
+LL | }
+   | - the item list ends here
+
+error[E0404]: expected trait, found struct `Demo`
+  --> $DIR/issue-105330.rs:6:32
+   |
+LL | impl TraitWAssocConst for impl Demo {
+   |                                ^^^^ not a trait
+
+error[E0658]: associated const equality is incomplete
+  --> $DIR/issue-105330.rs:11:28
+   |
+LL | fn foo<A: TraitWAssocConst<A=32>>() {
+   |                            ^^^^
+   |
+   = note: see issue #92827 <https://github.com/rust-lang/rust/issues/92827> for more information
+   = help: add `#![feature(associated_const_equality)]` to the crate attributes to enable
+
+error[E0658]: associated const equality is incomplete
+  --> $DIR/issue-105330.rs:17:29
+   |
+LL | fn main<A: TraitWAssocConst<A=32>>() {
+   |                             ^^^^
+   |
+   = note: see issue #92827 <https://github.com/rust-lang/rust/issues/92827> for more information
+   = help: add `#![feature(associated_const_equality)]` to the crate attributes to enable
+
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type
+  --> $DIR/issue-105330.rs:6:27
+   |
+LL | impl TraitWAssocConst for impl Demo {
+   |                           ^^^^^^^^^
+
+error[E0277]: the trait bound `Demo: TraitWAssocConst` is not satisfied
+  --> $DIR/issue-105330.rs:12:11
+   |
+LL |     foo::<Demo>()();
+   |           ^^^^ the trait `TraitWAssocConst` is not implemented for `Demo`
+   |
+note: required by a bound in `foo`
+  --> $DIR/issue-105330.rs:11:11
+   |
+LL | fn foo<A: TraitWAssocConst<A=32>>() {
+   |           ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `foo`
+
+error[E0271]: type mismatch resolving `<Demo as TraitWAssocConst>::A == 32`
+  --> $DIR/issue-105330.rs:12:11
+   |
+LL |     foo::<Demo>()();
+   |           ^^^^ types differ
+   |
+note: required by a bound in `foo`
+  --> $DIR/issue-105330.rs:11:28
+   |
+LL | fn foo<A: TraitWAssocConst<A=32>>() {
+   |                            ^^^^ required by this bound in `foo`
+
+error[E0618]: expected function, found `()`
+  --> $DIR/issue-105330.rs:12:5
+   |
+LL | fn foo<A: TraitWAssocConst<A=32>>() {
+   | ----------------------------------- `foo::<Demo>` defined here returns `()`
+LL |     foo::<Demo>()();
+   |     ^^^^^^^^^^^^^--
+   |     |
+   |     call expression requires function
+
+error[E0277]: the trait bound `Demo: TraitWAssocConst` is not satisfied
+  --> $DIR/issue-105330.rs:19:11
+   |
+LL |     foo::<Demo>();
+   |           ^^^^ the trait `TraitWAssocConst` is not implemented for `Demo`
+   |
+note: required by a bound in `foo`
+  --> $DIR/issue-105330.rs:11:11
+   |
+LL | fn foo<A: TraitWAssocConst<A=32>>() {
+   |           ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `foo`
+
+error[E0271]: type mismatch resolving `<Demo as TraitWAssocConst>::A == 32`
+  --> $DIR/issue-105330.rs:19:11
+   |
+LL |     foo::<Demo>();
+   |           ^^^^ types differ
+   |
+note: required by a bound in `foo`
+  --> $DIR/issue-105330.rs:11:28
+   |
+LL | fn foo<A: TraitWAssocConst<A=32>>() {
+   |                            ^^^^ required by this bound in `foo`
+
+error[E0131]: `main` function is not allowed to have generic parameters
+  --> $DIR/issue-105330.rs:17:8
+   |
+LL | fn main<A: TraitWAssocConst<A=32>>() {
+   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `main` cannot have generic parameters
+
+error: aborting due to 11 previous errors
+
+Some errors have detailed explanations: E0131, E0271, E0277, E0404, E0562, E0618, E0658.
+For more information about an error, try `rustc --explain E0131`.
diff --git a/src/test/ui/issues/issue-20413.stderr b/src/test/ui/issues/issue-20413.stderr
index 91509ceace8..78df445972c 100644
--- a/src/test/ui/issues/issue-20413.stderr
+++ b/src/test/ui/issues/issue-20413.stderr
@@ -14,7 +14,7 @@ LL | impl<T> Foo for T where NoData<T>: Foo {
    |                                    ^^^
    |
    = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_20413`)
-note: required for `NoData<NoData<NoData<NoData<NoData<NoData<...>>>>>>` to implement `Foo`
+note: required for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<...>>>>>>>>>>>>>` to implement `Foo`
   --> $DIR/issue-20413.rs:9:9
    |
 LL | impl<T> Foo for T where NoData<T>: Foo {
@@ -30,13 +30,13 @@ LL | impl<T> Bar for T where EvenLessData<T>: Baz {
    |                                          ^^^
    |
    = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_20413`)
-note: required for `AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<...>>>>>>` to implement `Bar`
+note: required for `AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<...>>>>>>>` to implement `Bar`
   --> $DIR/issue-20413.rs:28:9
    |
 LL | impl<T> Bar for T where EvenLessData<T>: Baz {
    |         ^^^     ^
    = note: the full type name has been written to '$TEST_BUILD_DIR/issues/issue-20413/issue-20413.long-type-hash.txt'
-note: required for `EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<...>>>>>>` to implement `Baz`
+note: required for `EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<...>>>>>>>` to implement `Baz`
   --> $DIR/issue-20413.rs:35:9
    |
 LL | impl<T> Baz for T where AlmostNoData<T>: Bar {
@@ -52,13 +52,13 @@ LL | impl<T> Baz for T where AlmostNoData<T>: Bar {
    |                                          ^^^
    |
    = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_20413`)
-note: required for `EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<...>>>>>>` to implement `Baz`
+note: required for `EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<...>>>>>>>` to implement `Baz`
   --> $DIR/issue-20413.rs:35:9
    |
 LL | impl<T> Baz for T where AlmostNoData<T>: Bar {
    |         ^^^     ^
    = note: the full type name has been written to '$TEST_BUILD_DIR/issues/issue-20413/issue-20413.long-type-hash.txt'
-note: required for `AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<...>>>>>>` to implement `Bar`
+note: required for `AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<...>>>>>>>` to implement `Bar`
   --> $DIR/issue-20413.rs:28:9
    |
 LL | impl<T> Bar for T where EvenLessData<T>: Baz {
diff --git a/src/test/ui/issues/issue-23122-2.stderr b/src/test/ui/issues/issue-23122-2.stderr
index 5828e027b59..1f50b06a0e4 100644
--- a/src/test/ui/issues/issue-23122-2.stderr
+++ b/src/test/ui/issues/issue-23122-2.stderr
@@ -5,7 +5,7 @@ LL |     type Next = <GetNext<T::Next> as Next>::Next;
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_23122_2`)
-note: required for `GetNext<<<<<<... as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next>` to implement `Next`
+note: required for `GetNext<<<<<<<... as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next>` to implement `Next`
   --> $DIR/issue-23122-2.rs:10:15
    |
 LL | impl<T: Next> Next for GetNext<T> {
diff --git a/src/test/ui/issues/issue-24352.stderr b/src/test/ui/issues/issue-24352.stderr
index 118f37f6971..1f51b6e2905 100644
--- a/src/test/ui/issues/issue-24352.stderr
+++ b/src/test/ui/issues/issue-24352.stderr
@@ -6,15 +6,10 @@ LL |     1.0f64 - 1
    |
    = help: the trait `Sub<{integer}>` is not implemented for `f64`
    = help: the following other types implement trait `Sub<Rhs>`:
-             <&'a f32 as Sub<f32>>
              <&'a f64 as Sub<f64>>
-             <&'a i128 as Sub<i128>>
-             <&'a i16 as Sub<i16>>
-             <&'a i32 as Sub<i32>>
-             <&'a i64 as Sub<i64>>
-             <&'a i8 as Sub<i8>>
-             <&'a isize as Sub<isize>>
-           and 48 others
+             <&f64 as Sub<&f64>>
+             <f64 as Sub<&f64>>
+             <f64 as Sub>
 help: consider using a floating-point literal by writing it with `.0`
    |
 LL |     1.0f64 - 1.0
diff --git a/src/test/ui/kindck/kindck-copy.stderr b/src/test/ui/kindck/kindck-copy.stderr
index 025a5008d0f..9af89159a8c 100644
--- a/src/test/ui/kindck/kindck-copy.stderr
+++ b/src/test/ui/kindck/kindck-copy.stderr
@@ -4,16 +4,7 @@ error[E0277]: the trait bound `&'static mut isize: Copy` is not satisfied
 LL |     assert_copy::<&'static mut isize>();
    |                   ^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `&'static mut isize`
    |
-   = help: the following other types implement trait `Copy`:
-             f32
-             f64
-             i128
-             i16
-             i32
-             i64
-             i8
-             isize
-           and 6 others
+   = help: the trait `Copy` is implemented for `isize`
 note: required by a bound in `assert_copy`
   --> $DIR/kindck-copy.rs:5:18
    |
@@ -26,16 +17,7 @@ error[E0277]: the trait bound `&'a mut isize: Copy` is not satisfied
 LL |     assert_copy::<&'a mut isize>();
    |                   ^^^^^^^^^^^^^ the trait `Copy` is not implemented for `&'a mut isize`
    |
-   = help: the following other types implement trait `Copy`:
-             f32
-             f64
-             i128
-             i16
-             i32
-             i64
-             i8
-             isize
-           and 6 others
+   = help: the trait `Copy` is implemented for `isize`
 note: required by a bound in `assert_copy`
   --> $DIR/kindck-copy.rs:5:18
    |
diff --git a/src/test/ui/lexer/lex-bad-char-literals-6.stderr b/src/test/ui/lexer/lex-bad-char-literals-6.stderr
index afef0cb6034..ce41942467c 100644
--- a/src/test/ui/lexer/lex-bad-char-literals-6.stderr
+++ b/src/test/ui/lexer/lex-bad-char-literals-6.stderr
@@ -42,12 +42,11 @@ LL |     if x == y {}
              <&'a str as PartialEq<OsString>>
              <&'a str as PartialEq<String>>
              <&'b str as PartialEq<Cow<'a, str>>>
-             <String as PartialEq<&'a str>>
-             <String as PartialEq<Cow<'a, str>>>
-             <String as PartialEq<str>>
-             <String as PartialEq>
              <str as PartialEq<Cow<'a, str>>>
-           and 4 others
+             <str as PartialEq<OsStr>>
+             <str as PartialEq<OsString>>
+             <str as PartialEq<String>>
+             <str as PartialEq>
 
 error[E0308]: mismatched types
   --> $DIR/lex-bad-char-literals-6.rs:15:20
@@ -68,12 +67,11 @@ LL |     if x == z {}
              <&'a str as PartialEq<OsString>>
              <&'a str as PartialEq<String>>
              <&'b str as PartialEq<Cow<'a, str>>>
-             <String as PartialEq<&'a str>>
-             <String as PartialEq<Cow<'a, str>>>
-             <String as PartialEq<str>>
-             <String as PartialEq>
              <str as PartialEq<Cow<'a, str>>>
-           and 4 others
+             <str as PartialEq<OsStr>>
+             <str as PartialEq<OsString>>
+             <str as PartialEq<String>>
+             <str as PartialEq>
 
 error: aborting due to 6 previous errors
 
diff --git a/src/test/ui/linkage-attr/auxiliary/def_illtyped_external.rs b/src/test/ui/linkage-attr/auxiliary/def_external.rs
index 2300930e513..2300930e513 100644
--- a/src/test/ui/linkage-attr/auxiliary/def_illtyped_external.rs
+++ b/src/test/ui/linkage-attr/auxiliary/def_external.rs
diff --git a/src/test/ui/linkage-attr/linkage-import.rs b/src/test/ui/linkage-attr/linkage-import.rs
new file mode 100644
index 00000000000..f754ddc6e08
--- /dev/null
+++ b/src/test/ui/linkage-attr/linkage-import.rs
@@ -0,0 +1,8 @@
+// build-pass
+// aux-build:def_external.rs
+
+extern crate def_external as dep;
+
+fn main() {
+    println!("{:p}", &dep::EXTERN);
+}
diff --git a/src/test/ui/linkage-attr/linkage-requires-raw-ptr.rs b/src/test/ui/linkage-attr/linkage-requires-raw-ptr.rs
deleted file mode 100644
index 93afc537f7c..00000000000
--- a/src/test/ui/linkage-attr/linkage-requires-raw-ptr.rs
+++ /dev/null
@@ -1,11 +0,0 @@
-// rust-lang/rust#59548: We used to ICE when trying to use a static
-// with a type that violated its own `#[linkage]`.
-
-// build-fail
-// aux-build:def_illtyped_external.rs
-
-extern crate def_illtyped_external as dep;
-
-fn main() {
-    println!("{:p}", &dep::EXTERN);
-}
diff --git a/src/test/ui/linkage-attr/linkage-requires-raw-ptr.stderr b/src/test/ui/linkage-attr/linkage-requires-raw-ptr.stderr
deleted file mode 100644
index 5abbe745c6a..00000000000
--- a/src/test/ui/linkage-attr/linkage-requires-raw-ptr.stderr
+++ /dev/null
@@ -1,8 +0,0 @@
-error: must have type `*const T` or `*mut T` due to `#[linkage]` attribute
-  --> $DIR/auxiliary/def_illtyped_external.rs:5:1
-   |
-LL | pub static EXTERN: u32 = 0;
-   | ^^^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/linkage-attr/linkage2.rs b/src/test/ui/linkage-attr/linkage2.rs
index a7be1985286..aa42874f7ba 100644
--- a/src/test/ui/linkage-attr/linkage2.rs
+++ b/src/test/ui/linkage-attr/linkage2.rs
@@ -1,16 +1,11 @@
-// FIXME https://github.com/rust-lang/rust/issues/59774
-
-// build-fail
-// normalize-stderr-test "thread.*panicked.*Metadata module not compiled.*\n" -> ""
-// normalize-stderr-test "note:.*RUST_BACKTRACE=1.*\n" -> ""
-// ignore-sgx no weak linkages permitted
+// check-fail
 
 #![feature(linkage)]
 
 extern "C" {
     #[linkage = "extern_weak"]
     static foo: i32;
-//~^ ERROR: must have type `*const T` or `*mut T` due to `#[linkage]` attribute
+//~^ ERROR: invalid type for variable with `#[linkage]` attribute
 }
 
 fn main() {
diff --git a/src/test/ui/linkage-attr/linkage2.stderr b/src/test/ui/linkage-attr/linkage2.stderr
index a6ac0aad077..7265f711fd0 100644
--- a/src/test/ui/linkage-attr/linkage2.stderr
+++ b/src/test/ui/linkage-attr/linkage2.stderr
@@ -1,8 +1,9 @@
-error: must have type `*const T` or `*mut T` due to `#[linkage]` attribute
-  --> $DIR/linkage2.rs:12:5
+error[E0791]: invalid type for variable with `#[linkage]` attribute
+  --> $DIR/linkage2.rs:7:5
    |
 LL |     static foo: i32;
    |     ^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0791`.
diff --git a/src/test/ui/lint/issue-104897.rs b/src/test/ui/lint/issue-104897.rs
new file mode 100644
index 00000000000..5fbc658f155
--- /dev/null
+++ b/src/test/ui/lint/issue-104897.rs
@@ -0,0 +1,6 @@
+// error-pattern: this file contains an unclosed delimiter
+// error-pattern: this file contains an unclosed delimiter
+// error-pattern: this file contains an unclosed delimiter
+// error-pattern: format argument must be a string literal
+
+fn f(){(print!(á
diff --git a/src/test/ui/lint/issue-104897.stderr b/src/test/ui/lint/issue-104897.stderr
new file mode 100644
index 00000000000..817a93c2f3b
--- /dev/null
+++ b/src/test/ui/lint/issue-104897.stderr
@@ -0,0 +1,43 @@
+error: this file contains an unclosed delimiter
+  --> $DIR/issue-104897.rs:6:18
+   |
+LL | fn f(){(print!(á
+   |       --      -  ^
+   |       ||      |
+   |       ||      unclosed delimiter
+   |       |unclosed delimiter
+   |       unclosed delimiter
+
+error: this file contains an unclosed delimiter
+  --> $DIR/issue-104897.rs:6:18
+   |
+LL | fn f(){(print!(á
+   |       --      -  ^
+   |       ||      |
+   |       ||      unclosed delimiter
+   |       |unclosed delimiter
+   |       unclosed delimiter
+
+error: this file contains an unclosed delimiter
+  --> $DIR/issue-104897.rs:6:18
+   |
+LL | fn f(){(print!(á
+   |       --      -  ^
+   |       ||      |
+   |       ||      unclosed delimiter
+   |       |unclosed delimiter
+   |       unclosed delimiter
+
+error: format argument must be a string literal
+  --> $DIR/issue-104897.rs:6:16
+   |
+LL | fn f(){(print!(á
+   |                ^
+   |
+help: you might be missing a string literal to format with
+   |
+LL | fn f(){(print!("{}", á
+   |                +++++
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/macros/syntax-error-recovery.stderr b/src/test/ui/macros/syntax-error-recovery.stderr
index c153b3b910b..c42ee9b295e 100644
--- a/src/test/ui/macros/syntax-error-recovery.stderr
+++ b/src/test/ui/macros/syntax-error-recovery.stderr
@@ -7,6 +7,7 @@ LL |                 $token $($inner)? = $value,
 LL | values!(STRING(1) as (String) => cfg(test),);
    | -------------------------------------------- in this macro invocation
    |
+   = help: enum variants can be `Variant`, `Variant = <integer>`, `Variant(Type, ..., TypeN)` or `Variant { fields: Types }`
    = note: this error originates in the macro `values` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: macro expansion ignores token `(String)` and any following
diff --git a/src/test/ui/maximal_mir_to_hir_coverage.rs b/src/test/ui/maximal_mir_to_hir_coverage.rs
new file mode 100644
index 00000000000..5ca54633f21
--- /dev/null
+++ b/src/test/ui/maximal_mir_to_hir_coverage.rs
@@ -0,0 +1,10 @@
+// compile-flags: -Zmaximal-hir-to-mir-coverage
+// run-pass
+
+// Just making sure this flag is accepted and doesn't crash the compiler
+
+fn main() {
+  let x = 1;
+  let y = x + 1;
+  println!("{y}");
+}
diff --git a/src/test/ui/mismatched_types/binops.stderr b/src/test/ui/mismatched_types/binops.stderr
index 3de652d87ec..3585587ed4c 100644
--- a/src/test/ui/mismatched_types/binops.stderr
+++ b/src/test/ui/mismatched_types/binops.stderr
@@ -24,15 +24,10 @@ LL |     2 as usize - Some(1);
    |
    = help: the trait `Sub<Option<{integer}>>` is not implemented for `usize`
    = help: the following other types implement trait `Sub<Rhs>`:
-             <&'a f32 as Sub<f32>>
-             <&'a f64 as Sub<f64>>
-             <&'a i128 as Sub<i128>>
-             <&'a i16 as Sub<i16>>
-             <&'a i32 as Sub<i32>>
-             <&'a i64 as Sub<i64>>
-             <&'a i8 as Sub<i8>>
-             <&'a isize as Sub<isize>>
-           and 48 others
+             <&'a usize as Sub<usize>>
+             <&usize as Sub<&usize>>
+             <usize as Sub<&usize>>
+             <usize as Sub>
 
 error[E0277]: cannot multiply `{integer}` by `()`
   --> $DIR/binops.rs:4:7
diff --git a/src/test/ui/never_type/issue-13352.stderr b/src/test/ui/never_type/issue-13352.stderr
index fed780e6895..2d22da0b420 100644
--- a/src/test/ui/never_type/issue-13352.stderr
+++ b/src/test/ui/never_type/issue-13352.stderr
@@ -6,15 +6,10 @@ LL |     2_usize + (loop {});
    |
    = help: the trait `Add<()>` is not implemented for `usize`
    = help: the following other types implement trait `Add<Rhs>`:
-             <&'a f32 as Add<f32>>
-             <&'a f64 as Add<f64>>
-             <&'a i128 as Add<i128>>
-             <&'a i16 as Add<i16>>
-             <&'a i32 as Add<i32>>
-             <&'a i64 as Add<i64>>
-             <&'a i8 as Add<i8>>
-             <&'a isize as Add<isize>>
-           and 48 others
+             <&'a usize as Add<usize>>
+             <&usize as Add<&usize>>
+             <usize as Add<&usize>>
+             <usize as Add>
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/numbers-arithmetic/not-suggest-float-literal.stderr b/src/test/ui/numbers-arithmetic/not-suggest-float-literal.stderr
index 6aa1ad8dd89..8f0eef237cf 100644
--- a/src/test/ui/numbers-arithmetic/not-suggest-float-literal.stderr
+++ b/src/test/ui/numbers-arithmetic/not-suggest-float-literal.stderr
@@ -6,15 +6,10 @@ LL |     x + 100.0
    |
    = help: the trait `Add<{float}>` is not implemented for `u8`
    = help: the following other types implement trait `Add<Rhs>`:
-             <&'a f32 as Add<f32>>
-             <&'a f64 as Add<f64>>
-             <&'a i128 as Add<i128>>
-             <&'a i16 as Add<i16>>
-             <&'a i32 as Add<i32>>
-             <&'a i64 as Add<i64>>
-             <&'a i8 as Add<i8>>
-             <&'a isize as Add<isize>>
-           and 48 others
+             <&'a u8 as Add<u8>>
+             <&u8 as Add<&u8>>
+             <u8 as Add<&u8>>
+             <u8 as Add>
 
 error[E0277]: cannot add `&str` to `f64`
   --> $DIR/not-suggest-float-literal.rs:6:7
@@ -24,15 +19,10 @@ LL |     x + "foo"
    |
    = help: the trait `Add<&str>` is not implemented for `f64`
    = help: the following other types implement trait `Add<Rhs>`:
-             <&'a f32 as Add<f32>>
              <&'a f64 as Add<f64>>
-             <&'a i128 as Add<i128>>
-             <&'a i16 as Add<i16>>
-             <&'a i32 as Add<i32>>
-             <&'a i64 as Add<i64>>
-             <&'a i8 as Add<i8>>
-             <&'a isize as Add<isize>>
-           and 48 others
+             <&f64 as Add<&f64>>
+             <f64 as Add<&f64>>
+             <f64 as Add>
 
 error[E0277]: cannot add `{integer}` to `f64`
   --> $DIR/not-suggest-float-literal.rs:11:7
@@ -42,15 +32,10 @@ LL |     x + y
    |
    = help: the trait `Add<{integer}>` is not implemented for `f64`
    = help: the following other types implement trait `Add<Rhs>`:
-             <&'a f32 as Add<f32>>
              <&'a f64 as Add<f64>>
-             <&'a i128 as Add<i128>>
-             <&'a i16 as Add<i16>>
-             <&'a i32 as Add<i32>>
-             <&'a i64 as Add<i64>>
-             <&'a i8 as Add<i8>>
-             <&'a isize as Add<isize>>
-           and 48 others
+             <&f64 as Add<&f64>>
+             <f64 as Add<&f64>>
+             <f64 as Add>
 
 error[E0277]: cannot subtract `{float}` from `u8`
   --> $DIR/not-suggest-float-literal.rs:15:7
@@ -60,15 +45,10 @@ LL |     x - 100.0
    |
    = help: the trait `Sub<{float}>` is not implemented for `u8`
    = help: the following other types implement trait `Sub<Rhs>`:
-             <&'a f32 as Sub<f32>>
-             <&'a f64 as Sub<f64>>
-             <&'a i128 as Sub<i128>>
-             <&'a i16 as Sub<i16>>
-             <&'a i32 as Sub<i32>>
-             <&'a i64 as Sub<i64>>
-             <&'a i8 as Sub<i8>>
-             <&'a isize as Sub<isize>>
-           and 48 others
+             <&'a u8 as Sub<u8>>
+             <&u8 as Sub<&u8>>
+             <u8 as Sub<&u8>>
+             <u8 as Sub>
 
 error[E0277]: cannot subtract `&str` from `f64`
   --> $DIR/not-suggest-float-literal.rs:19:7
@@ -78,15 +58,10 @@ LL |     x - "foo"
    |
    = help: the trait `Sub<&str>` is not implemented for `f64`
    = help: the following other types implement trait `Sub<Rhs>`:
-             <&'a f32 as Sub<f32>>
              <&'a f64 as Sub<f64>>
-             <&'a i128 as Sub<i128>>
-             <&'a i16 as Sub<i16>>
-             <&'a i32 as Sub<i32>>
-             <&'a i64 as Sub<i64>>
-             <&'a i8 as Sub<i8>>
-             <&'a isize as Sub<isize>>
-           and 48 others
+             <&f64 as Sub<&f64>>
+             <f64 as Sub<&f64>>
+             <f64 as Sub>
 
 error[E0277]: cannot subtract `{integer}` from `f64`
   --> $DIR/not-suggest-float-literal.rs:24:7
@@ -96,15 +71,10 @@ LL |     x - y
    |
    = help: the trait `Sub<{integer}>` is not implemented for `f64`
    = help: the following other types implement trait `Sub<Rhs>`:
-             <&'a f32 as Sub<f32>>
              <&'a f64 as Sub<f64>>
-             <&'a i128 as Sub<i128>>
-             <&'a i16 as Sub<i16>>
-             <&'a i32 as Sub<i32>>
-             <&'a i64 as Sub<i64>>
-             <&'a i8 as Sub<i8>>
-             <&'a isize as Sub<isize>>
-           and 48 others
+             <&f64 as Sub<&f64>>
+             <f64 as Sub<&f64>>
+             <f64 as Sub>
 
 error[E0277]: cannot multiply `u8` by `{float}`
   --> $DIR/not-suggest-float-literal.rs:28:7
@@ -114,15 +84,10 @@ LL |     x * 100.0
    |
    = help: the trait `Mul<{float}>` is not implemented for `u8`
    = help: the following other types implement trait `Mul<Rhs>`:
-             <&'a f32 as Mul<f32>>
-             <&'a f64 as Mul<f64>>
-             <&'a i128 as Mul<i128>>
-             <&'a i16 as Mul<i16>>
-             <&'a i32 as Mul<i32>>
-             <&'a i64 as Mul<i64>>
-             <&'a i8 as Mul<i8>>
-             <&'a isize as Mul<isize>>
-           and 49 others
+             <&'a u8 as Mul<u8>>
+             <&u8 as Mul<&u8>>
+             <u8 as Mul<&u8>>
+             <u8 as Mul>
 
 error[E0277]: cannot multiply `f64` by `&str`
   --> $DIR/not-suggest-float-literal.rs:32:7
@@ -132,15 +97,10 @@ LL |     x * "foo"
    |
    = help: the trait `Mul<&str>` is not implemented for `f64`
    = help: the following other types implement trait `Mul<Rhs>`:
-             <&'a f32 as Mul<f32>>
              <&'a f64 as Mul<f64>>
-             <&'a i128 as Mul<i128>>
-             <&'a i16 as Mul<i16>>
-             <&'a i32 as Mul<i32>>
-             <&'a i64 as Mul<i64>>
-             <&'a i8 as Mul<i8>>
-             <&'a isize as Mul<isize>>
-           and 49 others
+             <&f64 as Mul<&f64>>
+             <f64 as Mul<&f64>>
+             <f64 as Mul>
 
 error[E0277]: cannot multiply `f64` by `{integer}`
   --> $DIR/not-suggest-float-literal.rs:37:7
@@ -150,15 +110,10 @@ LL |     x * y
    |
    = help: the trait `Mul<{integer}>` is not implemented for `f64`
    = help: the following other types implement trait `Mul<Rhs>`:
-             <&'a f32 as Mul<f32>>
              <&'a f64 as Mul<f64>>
-             <&'a i128 as Mul<i128>>
-             <&'a i16 as Mul<i16>>
-             <&'a i32 as Mul<i32>>
-             <&'a i64 as Mul<i64>>
-             <&'a i8 as Mul<i8>>
-             <&'a isize as Mul<isize>>
-           and 49 others
+             <&f64 as Mul<&f64>>
+             <f64 as Mul<&f64>>
+             <f64 as Mul>
 
 error[E0277]: cannot divide `u8` by `{float}`
   --> $DIR/not-suggest-float-literal.rs:41:7
@@ -168,15 +123,11 @@ LL |     x / 100.0
    |
    = help: the trait `Div<{float}>` is not implemented for `u8`
    = help: the following other types implement trait `Div<Rhs>`:
-             <&'a f32 as Div<f32>>
-             <&'a f64 as Div<f64>>
-             <&'a i128 as Div<i128>>
-             <&'a i16 as Div<i16>>
-             <&'a i32 as Div<i32>>
-             <&'a i64 as Div<i64>>
-             <&'a i8 as Div<i8>>
-             <&'a isize as Div<isize>>
-           and 54 others
+             <&'a u8 as Div<u8>>
+             <&u8 as Div<&u8>>
+             <u8 as Div<&u8>>
+             <u8 as Div<NonZeroU8>>
+             <u8 as Div>
 
 error[E0277]: cannot divide `f64` by `&str`
   --> $DIR/not-suggest-float-literal.rs:45:7
@@ -186,15 +137,10 @@ LL |     x / "foo"
    |
    = help: the trait `Div<&str>` is not implemented for `f64`
    = help: the following other types implement trait `Div<Rhs>`:
-             <&'a f32 as Div<f32>>
              <&'a f64 as Div<f64>>
-             <&'a i128 as Div<i128>>
-             <&'a i16 as Div<i16>>
-             <&'a i32 as Div<i32>>
-             <&'a i64 as Div<i64>>
-             <&'a i8 as Div<i8>>
-             <&'a isize as Div<isize>>
-           and 54 others
+             <&f64 as Div<&f64>>
+             <f64 as Div<&f64>>
+             <f64 as Div>
 
 error[E0277]: cannot divide `f64` by `{integer}`
   --> $DIR/not-suggest-float-literal.rs:50:7
@@ -204,15 +150,10 @@ LL |     x / y
    |
    = help: the trait `Div<{integer}>` is not implemented for `f64`
    = help: the following other types implement trait `Div<Rhs>`:
-             <&'a f32 as Div<f32>>
              <&'a f64 as Div<f64>>
-             <&'a i128 as Div<i128>>
-             <&'a i16 as Div<i16>>
-             <&'a i32 as Div<i32>>
-             <&'a i64 as Div<i64>>
-             <&'a i8 as Div<i8>>
-             <&'a isize as Div<isize>>
-           and 54 others
+             <&f64 as Div<&f64>>
+             <f64 as Div<&f64>>
+             <f64 as Div>
 
 error: aborting due to 12 previous errors
 
diff --git a/src/test/ui/numbers-arithmetic/suggest-float-literal.stderr b/src/test/ui/numbers-arithmetic/suggest-float-literal.stderr
index 988379e582a..03779d35637 100644
--- a/src/test/ui/numbers-arithmetic/suggest-float-literal.stderr
+++ b/src/test/ui/numbers-arithmetic/suggest-float-literal.stderr
@@ -7,14 +7,9 @@ LL |     x + 100
    = help: the trait `Add<{integer}>` is not implemented for `f32`
    = help: the following other types implement trait `Add<Rhs>`:
              <&'a f32 as Add<f32>>
-             <&'a f64 as Add<f64>>
-             <&'a i128 as Add<i128>>
-             <&'a i16 as Add<i16>>
-             <&'a i32 as Add<i32>>
-             <&'a i64 as Add<i64>>
-             <&'a i8 as Add<i8>>
-             <&'a isize as Add<isize>>
-           and 48 others
+             <&f32 as Add<&f32>>
+             <f32 as Add<&f32>>
+             <f32 as Add>
 help: consider using a floating-point literal by writing it with `.0`
    |
 LL |     x + 100.0
@@ -28,15 +23,10 @@ LL |     x + 100
    |
    = help: the trait `Add<{integer}>` is not implemented for `f64`
    = help: the following other types implement trait `Add<Rhs>`:
-             <&'a f32 as Add<f32>>
              <&'a f64 as Add<f64>>
-             <&'a i128 as Add<i128>>
-             <&'a i16 as Add<i16>>
-             <&'a i32 as Add<i32>>
-             <&'a i64 as Add<i64>>
-             <&'a i8 as Add<i8>>
-             <&'a isize as Add<isize>>
-           and 48 others
+             <&f64 as Add<&f64>>
+             <f64 as Add<&f64>>
+             <f64 as Add>
 help: consider using a floating-point literal by writing it with `.0`
    |
 LL |     x + 100.0
@@ -51,14 +41,9 @@ LL |     x - 100
    = help: the trait `Sub<{integer}>` is not implemented for `f32`
    = help: the following other types implement trait `Sub<Rhs>`:
              <&'a f32 as Sub<f32>>
-             <&'a f64 as Sub<f64>>
-             <&'a i128 as Sub<i128>>
-             <&'a i16 as Sub<i16>>
-             <&'a i32 as Sub<i32>>
-             <&'a i64 as Sub<i64>>
-             <&'a i8 as Sub<i8>>
-             <&'a isize as Sub<isize>>
-           and 48 others
+             <&f32 as Sub<&f32>>
+             <f32 as Sub<&f32>>
+             <f32 as Sub>
 help: consider using a floating-point literal by writing it with `.0`
    |
 LL |     x - 100.0
@@ -72,15 +57,10 @@ LL |     x - 100
    |
    = help: the trait `Sub<{integer}>` is not implemented for `f64`
    = help: the following other types implement trait `Sub<Rhs>`:
-             <&'a f32 as Sub<f32>>
              <&'a f64 as Sub<f64>>
-             <&'a i128 as Sub<i128>>
-             <&'a i16 as Sub<i16>>
-             <&'a i32 as Sub<i32>>
-             <&'a i64 as Sub<i64>>
-             <&'a i8 as Sub<i8>>
-             <&'a isize as Sub<isize>>
-           and 48 others
+             <&f64 as Sub<&f64>>
+             <f64 as Sub<&f64>>
+             <f64 as Sub>
 help: consider using a floating-point literal by writing it with `.0`
    |
 LL |     x - 100.0
@@ -95,14 +75,9 @@ LL |     x * 100
    = help: the trait `Mul<{integer}>` is not implemented for `f32`
    = help: the following other types implement trait `Mul<Rhs>`:
              <&'a f32 as Mul<f32>>
-             <&'a f64 as Mul<f64>>
-             <&'a i128 as Mul<i128>>
-             <&'a i16 as Mul<i16>>
-             <&'a i32 as Mul<i32>>
-             <&'a i64 as Mul<i64>>
-             <&'a i8 as Mul<i8>>
-             <&'a isize as Mul<isize>>
-           and 49 others
+             <&f32 as Mul<&f32>>
+             <f32 as Mul<&f32>>
+             <f32 as Mul>
 help: consider using a floating-point literal by writing it with `.0`
    |
 LL |     x * 100.0
@@ -116,15 +91,10 @@ LL |     x * 100
    |
    = help: the trait `Mul<{integer}>` is not implemented for `f64`
    = help: the following other types implement trait `Mul<Rhs>`:
-             <&'a f32 as Mul<f32>>
              <&'a f64 as Mul<f64>>
-             <&'a i128 as Mul<i128>>
-             <&'a i16 as Mul<i16>>
-             <&'a i32 as Mul<i32>>
-             <&'a i64 as Mul<i64>>
-             <&'a i8 as Mul<i8>>
-             <&'a isize as Mul<isize>>
-           and 49 others
+             <&f64 as Mul<&f64>>
+             <f64 as Mul<&f64>>
+             <f64 as Mul>
 help: consider using a floating-point literal by writing it with `.0`
    |
 LL |     x * 100.0
@@ -139,14 +109,9 @@ LL |     x / 100
    = help: the trait `Div<{integer}>` is not implemented for `f32`
    = help: the following other types implement trait `Div<Rhs>`:
              <&'a f32 as Div<f32>>
-             <&'a f64 as Div<f64>>
-             <&'a i128 as Div<i128>>
-             <&'a i16 as Div<i16>>
-             <&'a i32 as Div<i32>>
-             <&'a i64 as Div<i64>>
-             <&'a i8 as Div<i8>>
-             <&'a isize as Div<isize>>
-           and 54 others
+             <&f32 as Div<&f32>>
+             <f32 as Div<&f32>>
+             <f32 as Div>
 help: consider using a floating-point literal by writing it with `.0`
    |
 LL |     x / 100.0
@@ -160,15 +125,10 @@ LL |     x / 100
    |
    = help: the trait `Div<{integer}>` is not implemented for `f64`
    = help: the following other types implement trait `Div<Rhs>`:
-             <&'a f32 as Div<f32>>
              <&'a f64 as Div<f64>>
-             <&'a i128 as Div<i128>>
-             <&'a i16 as Div<i16>>
-             <&'a i32 as Div<i32>>
-             <&'a i64 as Div<i64>>
-             <&'a i8 as Div<i8>>
-             <&'a isize as Div<isize>>
-           and 54 others
+             <&f64 as Div<&f64>>
+             <f64 as Div<&f64>>
+             <f64 as Div>
 help: consider using a floating-point literal by writing it with `.0`
    |
 LL |     x / 100.0
diff --git a/src/test/ui/object-safety/object-safety-supertrait-mentions-GAT.stderr b/src/test/ui/object-safety/object-safety-supertrait-mentions-GAT.stderr
index c1aaad31e81..f05b0cd6538 100644
--- a/src/test/ui/object-safety/object-safety-supertrait-mentions-GAT.stderr
+++ b/src/test/ui/object-safety/object-safety-supertrait-mentions-GAT.stderr
@@ -3,10 +3,10 @@ error[E0311]: the parameter type `Self` may not live long enough
    = help: consider adding an explicit lifetime bound `Self: 'a`...
    = note: ...so that the type `Self` will meet its required lifetime bounds...
 note: ...that is required by this bound
-  --> $DIR/object-safety-supertrait-mentions-GAT.rs:9:39
+  --> $DIR/object-safety-supertrait-mentions-GAT.rs:6:15
    |
-LL | trait SuperTrait<T>: for<'a> GatTrait<Gat<'a> = T> {
-   |                                       ^^^^^^^^^^^
+LL |         Self: 'a;
+   |               ^^
 
 error: associated item referring to unboxed trait object for its own trait
   --> $DIR/object-safety-supertrait-mentions-GAT.rs:10:20
diff --git a/src/test/ui/parser/expr-as-stmt.fixed b/src/test/ui/parser/expr-as-stmt.fixed
index 36709eea17c..b06f62794c4 100644
--- a/src/test/ui/parser/expr-as-stmt.fixed
+++ b/src/test/ui/parser/expr-as-stmt.fixed
@@ -64,4 +64,16 @@ fn asteroids() -> impl FnOnce() -> bool {
     { foo(); } || { true } //~ ERROR E0308
 }
 
+// https://github.com/rust-lang/rust/issues/105179
+fn r#match() -> i32 {
+    (match () { () => 1 }) + match () { () => 1 } //~ ERROR expected expression, found `+`
+    //~^ ERROR mismatched types
+}
+
+// https://github.com/rust-lang/rust/issues/102171
+fn r#unsafe() -> i32 {
+    (unsafe { 1 }) + unsafe { 1 } //~ ERROR expected expression, found `+`
+    //~^ ERROR mismatched types
+}
+
 fn main() {}
diff --git a/src/test/ui/parser/expr-as-stmt.rs b/src/test/ui/parser/expr-as-stmt.rs
index 92bb972b240..b39d2b88647 100644
--- a/src/test/ui/parser/expr-as-stmt.rs
+++ b/src/test/ui/parser/expr-as-stmt.rs
@@ -64,4 +64,16 @@ fn asteroids() -> impl FnOnce() -> bool {
     { foo() } || { true } //~ ERROR E0308
 }
 
+// https://github.com/rust-lang/rust/issues/105179
+fn r#match() -> i32 {
+    match () { () => 1 } + match () { () => 1 } //~ ERROR expected expression, found `+`
+    //~^ ERROR mismatched types
+}
+
+// https://github.com/rust-lang/rust/issues/102171
+fn r#unsafe() -> i32 {
+    unsafe { 1 } + unsafe { 1 } //~ ERROR expected expression, found `+`
+    //~^ ERROR mismatched types
+}
+
 fn main() {}
diff --git a/src/test/ui/parser/expr-as-stmt.stderr b/src/test/ui/parser/expr-as-stmt.stderr
index 6da4ac34067..18c8b0b7c50 100644
--- a/src/test/ui/parser/expr-as-stmt.stderr
+++ b/src/test/ui/parser/expr-as-stmt.stderr
@@ -55,6 +55,28 @@ help: parentheses are required to parse this as an expression
 LL |     ({ true }) | { true }
    |     +        +
 
+error: expected expression, found `+`
+  --> $DIR/expr-as-stmt.rs:69:26
+   |
+LL |     match () { () => 1 } + match () { () => 1 }
+   |                          ^ expected expression
+   |
+help: parentheses are required to parse this as an expression
+   |
+LL |     (match () { () => 1 }) + match () { () => 1 }
+   |     +                    +
+
+error: expected expression, found `+`
+  --> $DIR/expr-as-stmt.rs:75:18
+   |
+LL |     unsafe { 1 } + unsafe { 1 }
+   |                  ^ expected expression
+   |
+help: parentheses are required to parse this as an expression
+   |
+LL |     (unsafe { 1 }) + unsafe { 1 }
+   |     +            +
+
 error[E0308]: mismatched types
   --> $DIR/expr-as-stmt.rs:64:7
    |
@@ -201,7 +223,26 @@ help: parentheses are required to parse this as an expression
 LL |     ({ true }) || { true }
    |     +        +
 
-error: aborting due to 18 previous errors
+error[E0308]: mismatched types
+  --> $DIR/expr-as-stmt.rs:69:5
+   |
+LL |     match () { () => 1 } + match () { () => 1 }
+   |     ^^^^^^^^^^^^^^^^^^^^- help: consider using a semicolon here
+   |     |
+   |     expected `()`, found integer
+
+error[E0308]: mismatched types
+  --> $DIR/expr-as-stmt.rs:75:14
+   |
+LL |     unsafe { 1 } + unsafe { 1 }
+   |              ^ expected `()`, found integer
+   |
+help: you might have meant to return this value
+   |
+LL |     unsafe { return 1; } + unsafe { 1 }
+   |              ++++++  +
+
+error: aborting due to 22 previous errors
 
 Some errors have detailed explanations: E0308, E0600, E0614.
 For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/parser/issue-101477-enum.stderr b/src/test/ui/parser/issue-101477-enum.stderr
index bffc881bdc8..1edca391e8f 100644
--- a/src/test/ui/parser/issue-101477-enum.stderr
+++ b/src/test/ui/parser/issue-101477-enum.stderr
@@ -3,6 +3,8 @@ error: unexpected `==`
    |
 LL |     B == 2
    |       ^^ help: try using `=` instead
+   |
+   = help: enum variants can be `Variant`, `Variant = <integer>`, `Variant(Type, ..., TypeN)` or `Variant { fields: Types }`
 
 error: expected item, found `==`
   --> $DIR/issue-101477-enum.rs:6:7
diff --git a/src/test/ui/parser/issue-103869.rs b/src/test/ui/parser/issue-103869.rs
new file mode 100644
index 00000000000..28c442bdd63
--- /dev/null
+++ b/src/test/ui/parser/issue-103869.rs
@@ -0,0 +1,9 @@
+enum VecOrMap{
+    vec: Vec<usize>,
+    //~^ ERROR expected one of `(`, `,`, `=`, `{`, or `}`, found `:`
+    //~| HELP: enum variants can be `Variant`, `Variant = <integer>`, `Variant(Type, ..., TypeN)` or `Variant { fields: Types }`
+    //~| ERROR expected item, found `:`
+    map: HashMap<String,usize>
+}
+
+fn main() {}
diff --git a/src/test/ui/parser/issue-103869.stderr b/src/test/ui/parser/issue-103869.stderr
new file mode 100644
index 00000000000..0b8cd919a9d
--- /dev/null
+++ b/src/test/ui/parser/issue-103869.stderr
@@ -0,0 +1,16 @@
+error: expected one of `(`, `,`, `=`, `{`, or `}`, found `:`
+  --> $DIR/issue-103869.rs:2:8
+   |
+LL |     vec: Vec<usize>,
+   |        ^ expected one of `(`, `,`, `=`, `{`, or `}`
+   |
+   = help: enum variants can be `Variant`, `Variant = <integer>`, `Variant(Type, ..., TypeN)` or `Variant { fields: Types }`
+
+error: expected item, found `:`
+  --> $DIR/issue-103869.rs:2:8
+   |
+LL |     vec: Vec<usize>,
+   |        ^ expected item
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/parser/issue-105366.fixed b/src/test/ui/parser/issue-105366.fixed
new file mode 100644
index 00000000000..ad26643c327
--- /dev/null
+++ b/src/test/ui/parser/issue-105366.fixed
@@ -0,0 +1,12 @@
+// run-rustfix
+
+struct Foo;
+
+impl From<i32> for Foo {
+    //~^ ERROR you might have meant to write `impl` instead of `fn`
+    fn from(_a: i32) -> Self {
+        Foo
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/parser/issue-105366.rs b/src/test/ui/parser/issue-105366.rs
new file mode 100644
index 00000000000..311b6a60f1a
--- /dev/null
+++ b/src/test/ui/parser/issue-105366.rs
@@ -0,0 +1,12 @@
+// run-rustfix
+
+struct Foo;
+
+fn From<i32> for Foo {
+    //~^ ERROR you might have meant to write `impl` instead of `fn`
+    fn from(_a: i32) -> Self {
+        Foo
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/parser/issue-105366.stderr b/src/test/ui/parser/issue-105366.stderr
new file mode 100644
index 00000000000..0a7408e2c17
--- /dev/null
+++ b/src/test/ui/parser/issue-105366.stderr
@@ -0,0 +1,13 @@
+error: you might have meant to write `impl` instead of `fn`
+  --> $DIR/issue-105366.rs:5:1
+   |
+LL | fn From<i32> for Foo {
+   | ^^
+   |
+help: replace `fn` with `impl` here
+   |
+LL | impl From<i32> for Foo {
+   | ~~~~
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/macro/issue-37113.stderr b/src/test/ui/parser/macro/issue-37113.stderr
index b1f8674fbdf..da9e743a0b4 100644
--- a/src/test/ui/parser/macro/issue-37113.stderr
+++ b/src/test/ui/parser/macro/issue-37113.stderr
@@ -9,6 +9,7 @@ LL |             $( $t, )*
 LL |     test_macro!(String,);
    |     -------------------- in this macro invocation
    |
+   = help: enum variants can be `Variant`, `Variant = <integer>`, `Variant(Type, ..., TypeN)` or `Variant { fields: Types }`
    = note: this error originates in the macro `test_macro` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to previous error
diff --git a/src/test/ui/recursion/issue-83150.stderr b/src/test/ui/recursion/issue-83150.stderr
index 4d00a708313..dde8ad1b6b3 100644
--- a/src/test/ui/recursion/issue-83150.stderr
+++ b/src/test/ui/recursion/issue-83150.stderr
@@ -12,7 +12,7 @@ LL |     func(&mut iter.map(|x| x + 1))
 error[E0275]: overflow evaluating the requirement `Map<&mut Map<&mut Map<&mut Map<..., ...>, ...>, ...>, ...>: Iterator`
    |
    = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_83150`)
-   = note: required for `&mut Map<&mut Map<&mut Map<..., ...>, ...>, ...>` to implement `Iterator`
+   = note: required for `&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<..., ...>, ...>, ...>, ...>, ...>, ...>, ...>` to implement `Iterator`
    = note: the full type name has been written to '$TEST_BUILD_DIR/recursion/issue-83150/issue-83150.long-type-hash.txt'
 
 error: aborting due to previous error; 1 warning emitted
diff --git a/src/test/ui/regions/closure-in-projection-issue-97405.rs b/src/test/ui/regions/closure-in-projection-issue-97405.rs
index e567d5c2723..88b1c139651 100644
--- a/src/test/ui/regions/closure-in-projection-issue-97405.rs
+++ b/src/test/ui/regions/closure-in-projection-issue-97405.rs
@@ -22,11 +22,11 @@ fn good_generic_fn<T>() {
 // This should fail because `T` ends up in the upvars of the closure.
 fn bad_generic_fn<T: Copy>(t: T) {
     assert_static(opaque(async move { t; }).next());
-    //~^ ERROR the associated type `<impl Iterator as Iterator>::Item` may not live long enough
+    //~^ ERROR the parameter type `T` may not live long enough
     assert_static(opaque(move || { t; }).next());
     //~^ ERROR the associated type `<impl Iterator as Iterator>::Item` may not live long enough
     assert_static(opaque(opaque(async move { t; }).next()).next());
-    //~^ ERROR the associated type `<impl Iterator as Iterator>::Item` may not live long enough
+    //~^ ERROR the parameter type `T` may not live long enough
 }
 
 fn main() {}
diff --git a/src/test/ui/regions/closure-in-projection-issue-97405.stderr b/src/test/ui/regions/closure-in-projection-issue-97405.stderr
index c08f1059ebf..907964aaf37 100644
--- a/src/test/ui/regions/closure-in-projection-issue-97405.stderr
+++ b/src/test/ui/regions/closure-in-projection-issue-97405.stderr
@@ -1,11 +1,13 @@
-error[E0310]: the associated type `<impl Iterator as Iterator>::Item` may not live long enough
+error[E0310]: the parameter type `T` may not live long enough
   --> $DIR/closure-in-projection-issue-97405.rs:24:5
    |
 LL |     assert_static(opaque(async move { t; }).next());
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
    |
-   = help: consider adding an explicit lifetime bound `<impl Iterator as Iterator>::Item: 'static`...
-   = note: ...so that the type `<impl Iterator as Iterator>::Item` will meet its required lifetime bounds
+help: consider adding an explicit lifetime bound...
+   |
+LL | fn bad_generic_fn<T: Copy + 'static>(t: T) {
+   |                           +++++++++
 
 error[E0310]: the associated type `<impl Iterator as Iterator>::Item` may not live long enough
   --> $DIR/closure-in-projection-issue-97405.rs:26:5
@@ -16,14 +18,16 @@ LL |     assert_static(opaque(move || { t; }).next());
    = help: consider adding an explicit lifetime bound `<impl Iterator as Iterator>::Item: 'static`...
    = note: ...so that the type `<impl Iterator as Iterator>::Item` will meet its required lifetime bounds
 
-error[E0310]: the associated type `<impl Iterator as Iterator>::Item` may not live long enough
+error[E0310]: the parameter type `T` may not live long enough
   --> $DIR/closure-in-projection-issue-97405.rs:28:5
    |
 LL |     assert_static(opaque(opaque(async move { t; }).next()).next());
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
    |
-   = help: consider adding an explicit lifetime bound `<impl Iterator as Iterator>::Item: 'static`...
-   = note: ...so that the type `<impl Iterator as Iterator>::Item` will meet its required lifetime bounds
+help: consider adding an explicit lifetime bound...
+   |
+LL | fn bad_generic_fn<T: Copy + 'static>(t: T) {
+   |                           +++++++++
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/regions/issue-102374.rs b/src/test/ui/regions/issue-102374.rs
index e0a1164211a..fd71248d9cb 100644
--- a/src/test/ui/regions/issue-102374.rs
+++ b/src/test/ui/regions/issue-102374.rs
@@ -1,3 +1,4 @@
+// normalize-stderr-test: "long-type-\d+" -> "long-type-hash"
 use std::cell::Cell;
 
 #[rustfmt::skip]
diff --git a/src/test/ui/regions/issue-102374.stderr b/src/test/ui/regions/issue-102374.stderr
index 31b855c36be..157850693ab 100644
--- a/src/test/ui/regions/issue-102374.stderr
+++ b/src/test/ui/regions/issue-102374.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/issue-102374.rs:16:5
+  --> $DIR/issue-102374.rs:17:5
    |
 LL | ) -> i32 {
    |      --- expected `i32` because of return type
@@ -7,7 +7,8 @@ LL |     f
    |     ^ expected `i32`, found fn pointer
    |
    = note:    expected type `i32`
-           found fn pointer `for<'z1, 'a, 'b, 'c, 'd, 'e, 'f, 'g, 'h, 'i, 'j, 'k, 'l, 'm, 'n, 'o, 'p, 'q, 'r, 's, 't, 'u, 'v, 'w, 'x, 'y, 'z, 'z0> fn(Cell<(&'z1 i32, &'a i32, &'b i32, &'c i32, &'d i32, &'e i32, &'f i32, &'g i32, &'h i32, &'i i32, &'j i32, &'k i32, &'l i32, &'m i32, &'n i32, &'o i32, &'p i32, &'q i32, &'r i32, &'s i32, &'t i32, &'u i32, &'v i32, &'w i32, &'x i32, &'y i32, &'z i32, &'z0 i32)>)`
+           found fn pointer `for<'z1, 'a, 'b, 'c, 'd, 'e, 'f, 'g, 'h, 'i, 'j, 'k, 'l, 'm, 'n, 'o, 'p, 'q, 'r, 's, 't, 'u, 'v, 'w, 'x, 'y, 'z, 'z0> fn(Cell<...>)`
+           the full type name has been written to '$TEST_BUILD_DIR/regions/issue-102374/issue-102374.long-type-hash.txt'
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/rfc-1445-restrict-constants-in-patterns/match-requires-both-partialeq-and-eq.rs b/src/test/ui/rfc-1445-restrict-constants-in-patterns/match-requires-both-partialeq-and-eq.rs
index 6b7d94603b5..a8deb8a7550 100644
--- a/src/test/ui/rfc-1445-restrict-constants-in-patterns/match-requires-both-partialeq-and-eq.rs
+++ b/src/test/ui/rfc-1445-restrict-constants-in-patterns/match-requires-both-partialeq-and-eq.rs
@@ -5,7 +5,7 @@ struct Foo {
 
 impl PartialEq for Foo {
     fn eq(&self, _: &Foo) -> bool {
-        false // ha ha sucker!
+        false // ha ha!
     }
 }
 
diff --git a/src/test/ui/span/multiline-span-simple.stderr b/src/test/ui/span/multiline-span-simple.stderr
index c0d9a8634e4..b44df962a9b 100644
--- a/src/test/ui/span/multiline-span-simple.stderr
+++ b/src/test/ui/span/multiline-span-simple.stderr
@@ -6,15 +6,10 @@ LL |     foo(1 as u32 +
    |
    = help: the trait `Add<()>` is not implemented for `u32`
    = help: the following other types implement trait `Add<Rhs>`:
-             <&'a f32 as Add<f32>>
-             <&'a f64 as Add<f64>>
-             <&'a i128 as Add<i128>>
-             <&'a i16 as Add<i16>>
-             <&'a i32 as Add<i32>>
-             <&'a i64 as Add<i64>>
-             <&'a i8 as Add<i8>>
-             <&'a isize as Add<isize>>
-           and 48 others
+             <&'a u32 as Add<u32>>
+             <&u32 as Add<&u32>>
+             <u32 as Add<&u32>>
+             <u32 as Add>
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/structs/struct-fn-in-definition.rs b/src/test/ui/structs/struct-fn-in-definition.rs
index 5ae1b727dc7..7f48f55fec9 100644
--- a/src/test/ui/structs/struct-fn-in-definition.rs
+++ b/src/test/ui/structs/struct-fn-in-definition.rs
@@ -28,6 +28,7 @@ enum E {
     //~^ ERROR functions are not allowed in enum definitions
     //~| HELP unlike in C++, Java, and C#, functions are declared in `impl` blocks
     //~| HELP see https://doc.rust-lang.org/book/ch05-03-method-syntax.html for more information
+    //~| HELP enum variants can be `Variant`, `Variant = <integer>`, `Variant(Type, ..., TypeN)` or `Variant { fields: Types }`
 }
 
 fn main() {}
diff --git a/src/test/ui/structs/struct-fn-in-definition.stderr b/src/test/ui/structs/struct-fn-in-definition.stderr
index 472365c6ed7..439c86ec22b 100644
--- a/src/test/ui/structs/struct-fn-in-definition.stderr
+++ b/src/test/ui/structs/struct-fn-in-definition.stderr
@@ -33,6 +33,7 @@ LL |     fn foo() {}
    |
    = help: unlike in C++, Java, and C#, functions are declared in `impl` blocks
    = help: see https://doc.rust-lang.org/book/ch05-03-method-syntax.html for more information
+   = help: enum variants can be `Variant`, `Variant = <integer>`, `Variant(Type, ..., TypeN)` or `Variant { fields: Types }`
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/structs/unresolved-struct-with-fru.rs b/src/test/ui/structs/unresolved-struct-with-fru.rs
new file mode 100644
index 00000000000..c9fdca45772
--- /dev/null
+++ b/src/test/ui/structs/unresolved-struct-with-fru.rs
@@ -0,0 +1,12 @@
+struct S {
+    a: u32,
+}
+
+fn main() {
+    let s1 = S { a: 1 };
+
+    let _ = || {
+        let s2 = Oops { a: 2, ..s1 };
+        //~^ ERROR cannot find struct, variant or union type `Oops` in this scope
+    };
+}
diff --git a/src/test/ui/structs/unresolved-struct-with-fru.stderr b/src/test/ui/structs/unresolved-struct-with-fru.stderr
new file mode 100644
index 00000000000..a5796a22225
--- /dev/null
+++ b/src/test/ui/structs/unresolved-struct-with-fru.stderr
@@ -0,0 +1,9 @@
+error[E0422]: cannot find struct, variant or union type `Oops` in this scope
+  --> $DIR/unresolved-struct-with-fru.rs:9:18
+   |
+LL |         let s2 = Oops { a: 2, ..s1 };
+   |                  ^^^^ not found in this scope
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0422`.
diff --git a/src/test/ui/suggestions/assoc-const-as-fn.stderr b/src/test/ui/suggestions/assoc-const-as-fn.stderr
index fa740687858..3b6e947c59f 100644
--- a/src/test/ui/suggestions/assoc-const-as-fn.stderr
+++ b/src/test/ui/suggestions/assoc-const-as-fn.stderr
@@ -1,8 +1,10 @@
 error[E0277]: the trait bound `T: GlUniformScalar` is not satisfied
-  --> $DIR/assoc-const-as-fn.rs:14:5
+  --> $DIR/assoc-const-as-fn.rs:14:40
    |
 LL |     <T as GlUniformScalar>::FACTORY(1, value);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `GlUniformScalar` is not implemented for `T`
+   |     -------------------------------    ^^^^^ the trait `GlUniformScalar` is not implemented for `T`
+   |     |
+   |     required by a bound introduced by this call
    |
 help: consider further restricting this bound
    |
diff --git a/src/test/ui/suggestions/try-removing-the-field.rs b/src/test/ui/suggestions/try-removing-the-field.rs
index 9d0573ca255..1b7289b229b 100644
--- a/src/test/ui/suggestions/try-removing-the-field.rs
+++ b/src/test/ui/suggestions/try-removing-the-field.rs
@@ -14,4 +14,19 @@ fn use_foo(x: Foo) -> i32 {
     return foo;
 }
 
+// issue #105028, suggest removing the field only for shorthand
+fn use_match(x: Foo) {
+    match x {
+        Foo { foo: unused, .. } => { //~ WARNING unused variable
+                                     //~| help: if this is intentional, prefix it with an underscore
+        }
+    }
+
+    match x {
+        Foo { foo, .. } => { //~ WARNING unused variable
+                             //~| help: try removing the field
+        }
+    }
+}
+
 fn main() {}
diff --git a/src/test/ui/suggestions/try-removing-the-field.stderr b/src/test/ui/suggestions/try-removing-the-field.stderr
index 448a2c3d2ec..7a6013d4a6e 100644
--- a/src/test/ui/suggestions/try-removing-the-field.stderr
+++ b/src/test/ui/suggestions/try-removing-the-field.stderr
@@ -8,5 +8,19 @@ LL |     let Foo { foo, bar, .. } = x;
    |
    = note: `#[warn(unused_variables)]` on by default
 
-warning: 1 warning emitted
+warning: unused variable: `unused`
+  --> $DIR/try-removing-the-field.rs:20:20
+   |
+LL |         Foo { foo: unused, .. } => {
+   |                    ^^^^^^ help: if this is intentional, prefix it with an underscore: `_unused`
+
+warning: unused variable: `foo`
+  --> $DIR/try-removing-the-field.rs:26:15
+   |
+LL |         Foo { foo, .. } => {
+   |               ^^^-
+   |               |
+   |               help: try removing the field
+
+warning: 3 warnings emitted
 
diff --git a/src/test/ui/trait-bounds/impl-missing-where-clause-lifetimes-from-trait.rs b/src/test/ui/trait-bounds/impl-missing-where-clause-lifetimes-from-trait.rs
new file mode 100644
index 00000000000..dcdbd022873
--- /dev/null
+++ b/src/test/ui/trait-bounds/impl-missing-where-clause-lifetimes-from-trait.rs
@@ -0,0 +1,38 @@
+trait Trait<T> {
+    fn foo<'a, K>(self, _: T, _: K) where T: 'a, K: 'a;
+}
+
+impl Trait<()> for () {
+    fn foo<'a, K>(self, _: (), _: K) where { //~ ERROR E0195
+        todo!();
+    }
+}
+
+struct State;
+
+trait Foo<T> {
+    fn foo<'a>(&self, state: &'a State) -> &'a T
+    where
+        T: 'a;
+}
+
+impl<F, T> Foo<T> for F
+where
+    F: Fn(&State) -> &T,
+{
+    fn foo<'a>(&self, state: &'a State) -> &'a T { //~ ERROR E0195
+        self(state)
+    }
+}
+
+trait Bar {
+    fn foo<'a>(&'a self) {}
+}
+
+impl Bar for () {
+    fn foo<'a: 'a>(&'a self) {} //~ ERROR E0195
+}
+
+fn main() {
+    ().foo((), ());
+}
diff --git a/src/test/ui/trait-bounds/impl-missing-where-clause-lifetimes-from-trait.stderr b/src/test/ui/trait-bounds/impl-missing-where-clause-lifetimes-from-trait.stderr
new file mode 100644
index 00000000000..e26cb22163f
--- /dev/null
+++ b/src/test/ui/trait-bounds/impl-missing-where-clause-lifetimes-from-trait.stderr
@@ -0,0 +1,36 @@
+error[E0195]: lifetime parameters or bounds on method `foo` do not match the trait declaration
+  --> $DIR/impl-missing-where-clause-lifetimes-from-trait.rs:6:11
+   |
+LL |     fn foo<'a, K>(self, _: T, _: K) where T: 'a, K: 'a;
+   |           -------                            --     -- this bound might be missing in the impl
+   |           |                                  |
+   |           |                                  this bound might be missing in the impl
+   |           lifetimes in impl do not match this method in trait
+...
+LL |     fn foo<'a, K>(self, _: (), _: K) where {
+   |           ^^^^^^^ lifetimes do not match method in trait
+
+error[E0195]: lifetime parameters or bounds on method `foo` do not match the trait declaration
+  --> $DIR/impl-missing-where-clause-lifetimes-from-trait.rs:23:11
+   |
+LL |     fn foo<'a>(&self, state: &'a State) -> &'a T
+   |           ---- lifetimes in impl do not match this method in trait
+LL |     where
+LL |         T: 'a;
+   |            -- this bound might be missing in the impl
+...
+LL |     fn foo<'a>(&self, state: &'a State) -> &'a T {
+   |           ^^^^ lifetimes do not match method in trait
+
+error[E0195]: lifetime parameters or bounds on method `foo` do not match the trait declaration
+  --> $DIR/impl-missing-where-clause-lifetimes-from-trait.rs:33:11
+   |
+LL |     fn foo<'a>(&'a self) {}
+   |           ---- lifetimes in impl do not match this method in trait
+...
+LL |     fn foo<'a: 'a>(&'a self) {}
+   |           ^^^^^^^^ lifetimes do not match method in trait
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0195`.
diff --git a/src/test/ui/traits/issue-79458.stderr b/src/test/ui/traits/issue-79458.stderr
index cf2e4edf9f0..08f7bbbf0ea 100644
--- a/src/test/ui/traits/issue-79458.stderr
+++ b/src/test/ui/traits/issue-79458.stderr
@@ -7,10 +7,7 @@ LL | struct Foo<'a, T> {
 LL |     bar: &'a mut T
    |     ^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `&mut T`
    |
-   = help: the following other types implement trait `Clone`:
-             &T
-             *const T
-             *mut T
+   = help: the trait `Clone` is implemented for `&T`
    = note: `Clone` is implemented for `&T`, but not for `&mut T`
    = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
 
diff --git a/src/test/ui/traits/issue-91949-hangs-on-recursion.stderr b/src/test/ui/traits/issue-91949-hangs-on-recursion.stderr
index a74d2524996..1f18c5daf66 100644
--- a/src/test/ui/traits/issue-91949-hangs-on-recursion.stderr
+++ b/src/test/ui/traits/issue-91949-hangs-on-recursion.stderr
@@ -17,7 +17,7 @@ error[E0275]: overflow evaluating the requirement `(): Sized`
    = help: consider increasing the recursion limit by adding a `#![recursion_limit = "512"]` attribute to your crate (`issue_91949_hangs_on_recursion`)
    = note: required for `std::iter::Empty<()>` to implement `Iterator`
    = note: 171 redundant requirements hidden
-   = note: required for `IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<..., ...>>, ...>>` to implement `Iterator`
+   = note: required for `IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<..., ...>>, ...>>, ...>>` to implement `Iterator`
    = note: the full type name has been written to '$TEST_BUILD_DIR/traits/issue-91949-hangs-on-recursion/issue-91949-hangs-on-recursion.long-type-hash.txt'
 
 error: aborting due to previous error; 1 warning emitted
diff --git a/src/test/ui/try-trait/bad-interconversion.stderr b/src/test/ui/try-trait/bad-interconversion.stderr
index 419a86bf33b..a49630adb95 100644
--- a/src/test/ui/try-trait/bad-interconversion.stderr
+++ b/src/test/ui/try-trait/bad-interconversion.stderr
@@ -8,15 +8,8 @@ LL |     Ok(Err(123_i32)?)
    |
    = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait
    = help: the following other types implement trait `From<T>`:
-             <f32 as From<i16>>
-             <f32 as From<i8>>
-             <f32 as From<u16>>
-             <f32 as From<u8>>
-             <f64 as From<f32>>
-             <f64 as From<i16>>
-             <f64 as From<i32>>
-             <f64 as From<i8>>
-           and 68 others
+             <u8 as From<NonZeroU8>>
+             <u8 as From<bool>>
    = note: required for `Result<u64, u8>` to implement `FromResidual<Result<Infallible, i32>>`
 
 error[E0277]: the `?` operator can only be used on `Result`s, not `Option`s, in a function that returns `Result`
diff --git a/src/test/ui/type-alias-impl-trait/self-referential-2.stderr b/src/test/ui/type-alias-impl-trait/self-referential-2.stderr
index 2b505d30730..c2cf70687fd 100644
--- a/src/test/ui/type-alias-impl-trait/self-referential-2.stderr
+++ b/src/test/ui/type-alias-impl-trait/self-referential-2.stderr
@@ -7,16 +7,7 @@ LL |     42_i32
    |     ------ return type was inferred to be `i32` here
    |
    = help: the trait `PartialEq<Foo>` is not implemented for `i32`
-   = help: the following other types implement trait `PartialEq<Rhs>`:
-             f32
-             f64
-             i128
-             i16
-             i32
-             i64
-             i8
-             isize
-           and 6 others
+   = help: the trait `PartialEq` is implemented for `i32`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/type-alias-impl-trait/self-referential-4.stderr b/src/test/ui/type-alias-impl-trait/self-referential-4.stderr
index 27880f792f4..98c762e3d38 100644
--- a/src/test/ui/type-alias-impl-trait/self-referential-4.stderr
+++ b/src/test/ui/type-alias-impl-trait/self-referential-4.stderr
@@ -7,16 +7,7 @@ LL |     i
    |     - return type was inferred to be `&i32` here
    |
    = help: the trait `PartialEq<Bar<'b, 'static>>` is not implemented for `&i32`
-   = help: the following other types implement trait `PartialEq<Rhs>`:
-             f32
-             f64
-             i128
-             i16
-             i32
-             i64
-             i8
-             isize
-           and 6 others
+   = help: the trait `PartialEq` is implemented for `i32`
 
 error[E0277]: can't compare `&i32` with `Foo<'static, 'b>`
   --> $DIR/self-referential-4.rs:11:31
@@ -27,16 +18,7 @@ LL |     i
    |     - return type was inferred to be `&i32` here
    |
    = help: the trait `PartialEq<Foo<'static, 'b>>` is not implemented for `&i32`
-   = help: the following other types implement trait `PartialEq<Rhs>`:
-             f32
-             f64
-             i128
-             i16
-             i32
-             i64
-             i8
-             isize
-           and 6 others
+   = help: the trait `PartialEq` is implemented for `i32`
 
 error[E0277]: can't compare `&i32` with `Moo<'static, 'a>`
   --> $DIR/self-referential-4.rs:17:31
@@ -47,16 +29,7 @@ LL |     i
    |     - return type was inferred to be `&i32` here
    |
    = help: the trait `PartialEq<Moo<'static, 'a>>` is not implemented for `&i32`
-   = help: the following other types implement trait `PartialEq<Rhs>`:
-             f32
-             f64
-             i128
-             i16
-             i32
-             i64
-             i8
-             isize
-           and 6 others
+   = help: the trait `PartialEq` is implemented for `i32`
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/type-alias-impl-trait/self-referential.stderr b/src/test/ui/type-alias-impl-trait/self-referential.stderr
index 97d510f6830..aff489d70e3 100644
--- a/src/test/ui/type-alias-impl-trait/self-referential.stderr
+++ b/src/test/ui/type-alias-impl-trait/self-referential.stderr
@@ -8,16 +8,7 @@ LL |     i
    |     - return type was inferred to be `&i32` here
    |
    = help: the trait `PartialEq<Bar<'b, 'a>>` is not implemented for `&i32`
-   = help: the following other types implement trait `PartialEq<Rhs>`:
-             f32
-             f64
-             i128
-             i16
-             i32
-             i64
-             i8
-             isize
-           and 6 others
+   = help: the trait `PartialEq` is implemented for `i32`
 
 error[E0277]: can't compare `&i32` with `(i32, &i32)`
   --> $DIR/self-referential.rs:12:31
@@ -29,16 +20,7 @@ LL |     (42, i)
    |     ------- return type was inferred to be `(i32, &i32)` here
    |
    = help: the trait `PartialEq<(i32, &i32)>` is not implemented for `&i32`
-   = help: the following other types implement trait `PartialEq<Rhs>`:
-             f32
-             f64
-             i128
-             i16
-             i32
-             i64
-             i8
-             isize
-           and 6 others
+   = help: the trait `PartialEq` is implemented for `i32`
 
 error[E0277]: can't compare `&i32` with `(i32, Moo<'b, 'a>::{opaque#0})`
   --> $DIR/self-referential.rs:19:31
@@ -50,16 +32,7 @@ LL |     (42, i)
    |     ------- return type was inferred to be `(i32, &i32)` here
    |
    = help: the trait `PartialEq<(i32, Moo<'b, 'a>::{opaque#0})>` is not implemented for `&i32`
-   = help: the following other types implement trait `PartialEq<Rhs>`:
-             f32
-             f64
-             i128
-             i16
-             i32
-             i64
-             i8
-             isize
-           and 6 others
+   = help: the trait `PartialEq` is implemented for `i32`
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/type/type-check-defaults.stderr b/src/test/ui/type/type-check-defaults.stderr
index cf77c057d46..9ba63ffe9c9 100644
--- a/src/test/ui/type/type-check-defaults.stderr
+++ b/src/test/ui/type/type-check-defaults.stderr
@@ -66,15 +66,10 @@ LL | trait ProjectionPred<T:Iterator = IntoIter<i32>> where T::Item : Add<u8> {}
    |
    = help: the trait `Add<u8>` is not implemented for `i32`
    = help: the following other types implement trait `Add<Rhs>`:
-             <&'a f32 as Add<f32>>
-             <&'a f64 as Add<f64>>
-             <&'a i128 as Add<i128>>
-             <&'a i16 as Add<i16>>
              <&'a i32 as Add<i32>>
-             <&'a i64 as Add<i64>>
-             <&'a i8 as Add<i8>>
-             <&'a isize as Add<isize>>
-           and 48 others
+             <&i32 as Add<&i32>>
+             <i32 as Add<&i32>>
+             <i32 as Add>
 
 error: aborting due to 7 previous errors
 
diff --git a/src/test/ui/typeck/issue-81293.stderr b/src/test/ui/typeck/issue-81293.stderr
index 9658288ac8b..6976be71135 100644
--- a/src/test/ui/typeck/issue-81293.stderr
+++ b/src/test/ui/typeck/issue-81293.stderr
@@ -21,15 +21,10 @@ LL |     a = c + b * 5;
    |
    = help: the trait `Add<u16>` is not implemented for `usize`
    = help: the following other types implement trait `Add<Rhs>`:
-             <&'a f32 as Add<f32>>
-             <&'a f64 as Add<f64>>
-             <&'a i128 as Add<i128>>
-             <&'a i16 as Add<i16>>
-             <&'a i32 as Add<i32>>
-             <&'a i64 as Add<i64>>
-             <&'a i8 as Add<i8>>
-             <&'a isize as Add<isize>>
-           and 48 others
+             <&'a usize as Add<usize>>
+             <&usize as Add<&usize>>
+             <usize as Add<&usize>>
+             <usize as Add>
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/typeck/path-to-method-sugg-unresolved-expr.rs b/src/test/ui/typeck/path-to-method-sugg-unresolved-expr.rs
new file mode 100644
index 00000000000..fb56b394493
--- /dev/null
+++ b/src/test/ui/typeck/path-to-method-sugg-unresolved-expr.rs
@@ -0,0 +1,4 @@
+fn main() {
+    let page_size = page_size::get();
+    //~^ ERROR failed to resolve: use of undeclared crate or module `page_size`
+}
diff --git a/src/test/ui/typeck/path-to-method-sugg-unresolved-expr.stderr b/src/test/ui/typeck/path-to-method-sugg-unresolved-expr.stderr
new file mode 100644
index 00000000000..b01e30be54d
--- /dev/null
+++ b/src/test/ui/typeck/path-to-method-sugg-unresolved-expr.stderr
@@ -0,0 +1,9 @@
+error[E0433]: failed to resolve: use of undeclared crate or module `page_size`
+  --> $DIR/path-to-method-sugg-unresolved-expr.rs:2:21
+   |
+LL |     let page_size = page_size::get();
+   |                     ^^^^^^^^^ use of undeclared crate or module `page_size`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0433`.
diff --git a/src/test/ui/ufcs/ufcs-qpath-self-mismatch.stderr b/src/test/ui/ufcs/ufcs-qpath-self-mismatch.stderr
index eaab6ff3d9a..ed56e1cf957 100644
--- a/src/test/ui/ufcs/ufcs-qpath-self-mismatch.stderr
+++ b/src/test/ui/ufcs/ufcs-qpath-self-mismatch.stderr
@@ -8,15 +8,10 @@ LL |     <i32 as Add<u32>>::add(1, 2);
    |
    = help: the trait `Add<u32>` is not implemented for `i32`
    = help: the following other types implement trait `Add<Rhs>`:
-             <&'a f32 as Add<f32>>
-             <&'a f64 as Add<f64>>
-             <&'a i128 as Add<i128>>
-             <&'a i16 as Add<i16>>
              <&'a i32 as Add<i32>>
-             <&'a i64 as Add<i64>>
-             <&'a i8 as Add<i8>>
-             <&'a isize as Add<isize>>
-           and 48 others
+             <&i32 as Add<&i32>>
+             <i32 as Add<&i32>>
+             <i32 as Add>
 
 error[E0308]: mismatched types
   --> $DIR/ufcs-qpath-self-mismatch.rs:7:28
@@ -62,15 +57,10 @@ LL |     <i32 as Add<u32>>::add(1, 2);
    |
    = help: the trait `Add<u32>` is not implemented for `i32`
    = help: the following other types implement trait `Add<Rhs>`:
-             <&'a f32 as Add<f32>>
-             <&'a f64 as Add<f64>>
-             <&'a i128 as Add<i128>>
-             <&'a i16 as Add<i16>>
              <&'a i32 as Add<i32>>
-             <&'a i64 as Add<i64>>
-             <&'a i8 as Add<i8>>
-             <&'a isize as Add<isize>>
-           and 48 others
+             <&i32 as Add<&i32>>
+             <i32 as Add<&i32>>
+             <i32 as Add>
 
 error: aborting due to 4 previous errors
 
diff --git a/src/tools/collect-license-metadata/Cargo.toml b/src/tools/collect-license-metadata/Cargo.toml
new file mode 100644
index 00000000000..d0820cfc2a0
--- /dev/null
+++ b/src/tools/collect-license-metadata/Cargo.toml
@@ -0,0 +1,10 @@
+[package]
+name = "collect-license-metadata"
+version = "0.1.0"
+edition = "2021"
+
+[dependencies]
+anyhow = "1.0.65"
+serde = { version = "1.0.147", features = ["derive"] }
+serde_json = "1.0.85"
+spdx-rs = "0.5.1"
diff --git a/src/tools/collect-license-metadata/src/licenses.rs b/src/tools/collect-license-metadata/src/licenses.rs
new file mode 100644
index 00000000000..1c95b1bc8e9
--- /dev/null
+++ b/src/tools/collect-license-metadata/src/licenses.rs
@@ -0,0 +1,65 @@
+use std::collections::HashMap;
+
+const COPYRIGHT_PREFIXES: &[&str] = &["SPDX-FileCopyrightText:", "Copyright", "(c)", "(C)", "©"];
+
+pub(crate) struct LicensesInterner {
+    by_id: Vec<License>,
+    by_struct: HashMap<License, usize>,
+}
+
+impl LicensesInterner {
+    pub(crate) fn new() -> Self {
+        LicensesInterner { by_id: Vec::new(), by_struct: HashMap::new() }
+    }
+
+    pub(crate) fn intern(&mut self, mut license: License) -> LicenseId {
+        license.simplify();
+        if let Some(id) = self.by_struct.get(&license) {
+            LicenseId(*id)
+        } else {
+            let id = self.by_id.len();
+            self.by_id.push(license.clone());
+            self.by_struct.insert(license, id);
+            LicenseId(id)
+        }
+    }
+
+    pub(crate) fn resolve(&self, id: LicenseId) -> &License {
+        &self.by_id[id.0]
+    }
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, serde::Serialize)]
+#[serde(transparent)]
+pub(crate) struct LicenseId(usize);
+
+#[derive(Clone, Hash, PartialEq, Eq, serde::Serialize)]
+pub(crate) struct License {
+    pub(crate) spdx: String,
+    pub(crate) copyright: Vec<String>,
+}
+
+impl License {
+    fn simplify(&mut self) {
+        self.remove_copyright_prefixes();
+        self.copyright.sort();
+        self.copyright.dedup();
+    }
+
+    fn remove_copyright_prefixes(&mut self) {
+        for copyright in &mut self.copyright {
+            let mut stripped = copyright.trim();
+            let mut previous_stripped;
+            loop {
+                previous_stripped = stripped;
+                for pattern in COPYRIGHT_PREFIXES {
+                    stripped = stripped.trim_start_matches(pattern).trim_start();
+                }
+                if stripped == previous_stripped {
+                    break;
+                }
+            }
+            *copyright = stripped.into();
+        }
+    }
+}
diff --git a/src/tools/collect-license-metadata/src/main.rs b/src/tools/collect-license-metadata/src/main.rs
new file mode 100644
index 00000000000..ca2a6f4b8c8
--- /dev/null
+++ b/src/tools/collect-license-metadata/src/main.rs
@@ -0,0 +1,30 @@
+mod licenses;
+mod path_tree;
+mod reuse;
+
+use crate::licenses::LicensesInterner;
+use anyhow::Error;
+use std::path::PathBuf;
+
+fn main() -> Result<(), Error> {
+    let reuse_exe: PathBuf = std::env::var_os("REUSE_EXE").expect("Missing REUSE_EXE").into();
+    let dest: PathBuf = std::env::var_os("DEST").expect("Missing DEST").into();
+
+    let mut interner = LicensesInterner::new();
+    let paths = crate::reuse::collect(&reuse_exe, &mut interner)?;
+
+    let mut tree = crate::path_tree::build(paths);
+    tree.simplify();
+
+    if let Some(parent) = dest.parent() {
+        std::fs::create_dir_all(parent)?;
+    }
+    std::fs::write(
+        &dest,
+        &serde_json::to_vec_pretty(&serde_json::json!({
+            "files": crate::path_tree::expand_interned_licenses(tree, &interner),
+        }))?,
+    )?;
+
+    Ok(())
+}
diff --git a/src/tools/collect-license-metadata/src/path_tree.rs b/src/tools/collect-license-metadata/src/path_tree.rs
new file mode 100644
index 00000000000..133ff683737
--- /dev/null
+++ b/src/tools/collect-license-metadata/src/path_tree.rs
@@ -0,0 +1,294 @@
+//! Tools like REUSE output per-file licensing information, but we need to condense it in the
+//! minimum amount of data that still represents the same licensing metadata. This module is
+//! responsible for that, by turning the list of paths into a tree and executing simplification
+//! passes over the tree to remove redundant information.
+
+use crate::licenses::{License, LicenseId, LicensesInterner};
+use std::collections::BTreeMap;
+use std::path::{Path, PathBuf};
+
+#[derive(serde::Serialize)]
+#[serde(rename_all = "kebab-case", tag = "type")]
+pub(crate) enum Node<L> {
+    Root { childs: Vec<Node<L>> },
+    Directory { name: PathBuf, childs: Vec<Node<L>>, license: Option<L> },
+    File { name: PathBuf, license: L },
+    FileGroup { names: Vec<PathBuf>, license: L },
+    Empty,
+}
+
+impl Node<LicenseId> {
+    pub(crate) fn simplify(&mut self) {
+        self.merge_directories();
+        self.collapse_in_licensed_directories();
+        self.merge_directory_licenses();
+        self.merge_file_groups();
+        self.remove_empty();
+    }
+
+    /// Initially, the build() function constructs a list of separate paths from the file
+    /// system root down to each file, like so:
+    ///
+    /// ```text
+    ///         ┌─► ./ ──► compiler/ ──► rustc/ ──► src/ ──► main.rs
+    ///         │
+    /// <root> ─┼─► ./ ──► compiler/ ──► rustc/ ──► Cargo.toml
+    ///         │
+    ///         └─► ./ ──► library/ ───► std/ ──► Cargo.toml
+    /// ```
+    ///
+    /// This pass is responsible for turning that into a proper directory tree:
+    ///
+    /// ```text
+    ///                 ┌─► compiler/ ──► rustc/ ──┬─► src/ ──► main.rs
+    ///                 │                          │
+    /// <root> ──► ./ ──┤                          └─► Cargo.toml
+    ///                 │
+    ///                 └─► library/ ───► std/ ──► Cargo.toml
+    /// ```
+    fn merge_directories(&mut self) {
+        match self {
+            Node::Root { childs } | Node::Directory { childs, license: None, .. } => {
+                let mut directories = BTreeMap::new();
+                let mut files = Vec::new();
+
+                for child in childs.drain(..) {
+                    match child {
+                        Node::Directory { name, mut childs, license: None } => {
+                            directories.entry(name).or_insert_with(Vec::new).append(&mut childs);
+                        }
+                        file @ Node::File { .. } => {
+                            files.push(file);
+                        }
+                        Node::Empty => {}
+                        Node::Root { .. } => {
+                            panic!("can't have a root inside another element");
+                        }
+                        Node::FileGroup { .. } => {
+                            panic!("FileGroup should not be present at this stage");
+                        }
+                        Node::Directory { license: Some(_), .. } => {
+                            panic!("license should not be set at this stage");
+                        }
+                    }
+                }
+
+                childs.extend(directories.into_iter().map(|(name, childs)| Node::Directory {
+                    name,
+                    childs,
+                    license: None,
+                }));
+                childs.append(&mut files);
+
+                for child in &mut *childs {
+                    child.merge_directories();
+                }
+            }
+            Node::Empty => {}
+            Node::File { .. } => {}
+            Node::FileGroup { .. } => {
+                panic!("FileGroup should not be present at this stage");
+            }
+            Node::Directory { license: Some(_), .. } => {
+                panic!("license should not be set at this stage");
+            }
+        }
+    }
+
+    /// In our codebase, most files in a directory have the same license as the other files in that
+    /// same directory, so it's redundant to store licensing metadata for all the files. Instead,
+    /// we can add a license for a whole directory, and only record the exceptions to a directory
+    /// licensing metadata.
+    ///
+    /// We cannot instead record only the difference to Rust's standard licensing, as the majority
+    /// of the files in our repository are *not* licensed under Rust's standard licensing due to
+    /// our inclusion of LLVM.
+    fn collapse_in_licensed_directories(&mut self) {
+        match self {
+            Node::Directory { childs, license, .. } => {
+                for child in &mut *childs {
+                    child.collapse_in_licensed_directories();
+                }
+
+                let mut licenses_count = BTreeMap::new();
+                for child in &*childs {
+                    let Some(license) = child.license() else { continue };
+                    *licenses_count.entry(license).or_insert(0) += 1;
+                }
+
+                let most_popular_license = licenses_count
+                    .into_iter()
+                    .max_by_key(|(_, count)| *count)
+                    .map(|(license, _)| license);
+
+                if let Some(most_popular_license) = most_popular_license {
+                    childs.retain(|child| child.license() != Some(most_popular_license));
+                    *license = Some(most_popular_license);
+                }
+            }
+            Node::Root { childs } => {
+                for child in &mut *childs {
+                    child.collapse_in_licensed_directories();
+                }
+            }
+            Node::File { .. } => {}
+            Node::FileGroup { .. } => {}
+            Node::Empty => {}
+        }
+    }
+
+    /// Reduce the depth of the tree by merging subdirectories with the same license as their
+    /// parent directory into their parent, and adjusting the paths of the childs accordingly.
+    fn merge_directory_licenses(&mut self) {
+        match self {
+            Node::Root { childs } => {
+                for child in &mut *childs {
+                    child.merge_directory_licenses();
+                }
+            }
+            Node::Directory { childs, license, .. } => {
+                let mut to_add = Vec::new();
+                for child in &mut *childs {
+                    child.merge_directory_licenses();
+
+                    let Node::Directory {
+                        name: child_name,
+                        childs: child_childs,
+                        license: child_license,
+                    } = child else { continue };
+
+                    if child_license != license {
+                        continue;
+                    }
+                    for mut child_child in child_childs.drain(..) {
+                        match &mut child_child {
+                            Node::Root { .. } => {
+                                panic!("can't have a root inside another element");
+                            }
+                            Node::FileGroup { .. } => {
+                                panic!("FileGroup should not be present at this stage");
+                            }
+                            Node::Directory { name: child_child_name, .. } => {
+                                *child_child_name = child_name.join(&child_child_name);
+                            }
+                            Node::File { name: child_child_name, .. } => {
+                                *child_child_name = child_name.join(&child_child_name);
+                            }
+                            Node::Empty => {}
+                        }
+                        to_add.push(child_child);
+                    }
+
+                    *child = Node::Empty;
+                }
+                childs.append(&mut to_add);
+            }
+            Node::Empty => {}
+            Node::File { .. } => {}
+            Node::FileGroup { .. } => {}
+        }
+    }
+
+    /// This pass groups multiple files in a directory with the same license into a single
+    /// "FileGroup", so that the license of all those files can be reported as a group.
+    ///
+    /// Crucially this pass runs after collapse_in_licensed_directories, so the most common license
+    /// will already be marked as the directory's license and won't be turned into a group.
+    fn merge_file_groups(&mut self) {
+        match self {
+            Node::Root { childs } | Node::Directory { childs, .. } => {
+                let mut grouped = BTreeMap::new();
+
+                for child in &mut *childs {
+                    child.merge_file_groups();
+                    if let Node::File { name, license } = child {
+                        grouped.entry(*license).or_insert_with(Vec::new).push(name.clone());
+                        *child = Node::Empty;
+                    }
+                }
+
+                for (license, mut names) in grouped.into_iter() {
+                    if names.len() == 1 {
+                        childs.push(Node::File { license, name: names.pop().unwrap() });
+                    } else {
+                        childs.push(Node::FileGroup { license, names });
+                    }
+                }
+            }
+            Node::File { .. } => {}
+            Node::FileGroup { .. } => panic!("FileGroup should not be present at this stage"),
+            Node::Empty => {}
+        }
+    }
+
+    /// Some nodes were replaced with Node::Empty to mark them for deletion. As the last step, make
+    /// sure to remove them from the tree.
+    fn remove_empty(&mut self) {
+        match self {
+            Node::Root { childs } | Node::Directory { childs, .. } => {
+                for child in &mut *childs {
+                    child.remove_empty();
+                }
+                childs.retain(|child| !matches!(child, Node::Empty));
+            }
+            Node::FileGroup { .. } => {}
+            Node::File { .. } => {}
+            Node::Empty => {}
+        }
+    }
+
+    fn license(&self) -> Option<LicenseId> {
+        match self {
+            Node::Directory { childs, license: Some(license), .. } if childs.is_empty() => {
+                Some(*license)
+            }
+            Node::File { license, .. } => Some(*license),
+            _ => None,
+        }
+    }
+}
+
+pub(crate) fn build(mut input: Vec<(PathBuf, LicenseId)>) -> Node<LicenseId> {
+    let mut childs = Vec::new();
+
+    // Ensure reproducibility of all future steps.
+    input.sort();
+
+    for (path, license) in input {
+        let mut node = Node::File { name: path.file_name().unwrap().into(), license };
+        for component in path.parent().unwrap_or_else(|| Path::new(".")).components().rev() {
+            node = Node::Directory {
+                name: component.as_os_str().into(),
+                childs: vec![node],
+                license: None,
+            };
+        }
+
+        childs.push(node);
+    }
+
+    Node::Root { childs }
+}
+
+/// Convert a `Node<LicenseId>` into a `Node<&License>`, expanding all interned license IDs with a
+/// reference to the actual license metadata.
+pub(crate) fn expand_interned_licenses(
+    node: Node<LicenseId>,
+    interner: &LicensesInterner,
+) -> Node<&License> {
+    match node {
+        Node::Root { childs } => Node::Root {
+            childs: childs.into_iter().map(|child| strip_interning(child, interner)).collect(),
+        },
+        Node::Directory { name, childs, license } => Node::Directory {
+            childs: childs.into_iter().map(|child| strip_interning(child, interner)).collect(),
+            license: license.map(|license| interner.resolve(license)),
+            name,
+        },
+        Node::File { name, license } => Node::File { name, license: interner.resolve(license) },
+        Node::FileGroup { names, license } => {
+            Node::FileGroup { names, license: interner.resolve(license) }
+        }
+        Node::Empty => Node::Empty,
+    }
+}
diff --git a/src/tools/collect-license-metadata/src/reuse.rs b/src/tools/collect-license-metadata/src/reuse.rs
new file mode 100644
index 00000000000..d6b3772ba51
--- /dev/null
+++ b/src/tools/collect-license-metadata/src/reuse.rs
@@ -0,0 +1,49 @@
+use crate::licenses::{License, LicenseId, LicensesInterner};
+use anyhow::Error;
+use std::path::{Path, PathBuf};
+use std::process::{Command, Stdio};
+use std::time::Instant;
+
+pub(crate) fn collect(
+    reuse_exe: &Path,
+    interner: &mut LicensesInterner,
+) -> Result<Vec<(PathBuf, LicenseId)>, Error> {
+    eprintln!("gathering license information from REUSE");
+    let start = Instant::now();
+    let raw = &obtain_spdx_document(reuse_exe)?;
+    eprintln!("finished gathering the license information from REUSE in {:.2?}", start.elapsed());
+
+    let document = spdx_rs::parsers::spdx_from_tag_value(&raw)?;
+
+    let mut result = Vec::new();
+    for file in document.file_information {
+        let license = interner.intern(License {
+            spdx: file.concluded_license.to_string(),
+            copyright: file.copyright_text.split('\n').map(|s| s.into()).collect(),
+        });
+
+        result.push((file.file_name.into(), license));
+    }
+
+    Ok(result)
+}
+
+fn obtain_spdx_document(reuse_exe: &Path) -> Result<String, Error> {
+    let output = Command::new(reuse_exe)
+        .args(&["spdx", "--add-license-concluded", "--creator-person=bors"])
+        .stdout(Stdio::piped())
+        .spawn()?
+        .wait_with_output()?;
+
+    if !output.status.success() {
+        eprintln!();
+        eprintln!("Note that Rust requires some REUSE features that might not be present in the");
+        eprintln!("release you're using. Make sure your REUSE release includes these PRs:");
+        eprintln!();
+        eprintln!(" - https://github.com/fsfe/reuse-tool/pull/623");
+        eprintln!();
+        anyhow::bail!("collecting licensing information with REUSE failed");
+    }
+
+    Ok(String::from_utf8(output.stdout)?)
+}
diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs
index 0d9a629e179..64d97e91442 100644
--- a/src/tools/compiletest/src/header.rs
+++ b/src/tools/compiletest/src/header.rs
@@ -260,9 +260,9 @@ impl TestProps {
         props.load_from(testfile, cfg, config);
 
         match (props.pass_mode, props.fail_mode) {
-            (None, None) => props.fail_mode = Some(FailMode::Check),
-            (Some(_), None) | (None, Some(_)) => {}
+            (None, None) if config.mode == Mode::Ui => props.fail_mode = Some(FailMode::Check),
             (Some(_), Some(_)) => panic!("cannot use a *-fail and *-pass mode together"),
+            _ => {}
         }
 
         props
@@ -522,8 +522,8 @@ impl TestProps {
     }
 
     pub fn pass_mode(&self, config: &Config) -> Option<PassMode> {
-        if !self.ignore_pass && self.fail_mode.is_none() && config.mode == Mode::Ui {
-            if let (mode @ Some(_), Some(_)) = (config.force_pass_mode, self.pass_mode) {
+        if !self.ignore_pass && self.fail_mode.is_none() {
+            if let mode @ Some(_) = config.force_pass_mode {
                 return mode;
             }
         }
diff --git a/src/tools/generate-copyright/Cargo.toml b/src/tools/generate-copyright/Cargo.toml
new file mode 100644
index 00000000000..899ef0f8a6c
--- /dev/null
+++ b/src/tools/generate-copyright/Cargo.toml
@@ -0,0 +1,11 @@
+[package]
+name = "generate-copyright"
+version = "0.1.0"
+edition = "2021"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
+anyhow = "1.0.65"
+serde = { version = "1.0.147", features = ["derive"] }
+serde_json = "1.0.85"
diff --git a/src/tools/generate-copyright/src/main.rs b/src/tools/generate-copyright/src/main.rs
new file mode 100644
index 00000000000..d172c9e157b
--- /dev/null
+++ b/src/tools/generate-copyright/src/main.rs
@@ -0,0 +1,94 @@
+use anyhow::Error;
+use std::io::Write;
+use std::path::PathBuf;
+
+fn main() -> Result<(), Error> {
+    let dest = env_path("DEST")?;
+    let license_metadata = env_path("LICENSE_METADATA")?;
+
+    let metadata: Metadata = serde_json::from_slice(&std::fs::read(&license_metadata)?)?;
+
+    let mut buffer = Vec::new();
+    render_recursive(&metadata.files, &mut buffer, 0)?;
+
+    std::fs::write(&dest, &buffer)?;
+
+    Ok(())
+}
+
+fn render_recursive(node: &Node, buffer: &mut Vec<u8>, depth: usize) -> Result<(), Error> {
+    let prefix = std::iter::repeat("> ").take(depth + 1).collect::<String>();
+
+    match node {
+        Node::Root { childs } => {
+            for child in childs {
+                render_recursive(child, buffer, depth)?;
+            }
+        }
+        Node::Directory { name, childs, license } => {
+            render_license(&prefix, std::iter::once(name), license, buffer)?;
+            if !childs.is_empty() {
+                writeln!(buffer, "{prefix}")?;
+                writeln!(buffer, "{prefix}*Exceptions:*")?;
+                for child in childs {
+                    writeln!(buffer, "{prefix}")?;
+                    render_recursive(child, buffer, depth + 1)?;
+                }
+            }
+        }
+        Node::FileGroup { names, license } => {
+            render_license(&prefix, names.iter(), license, buffer)?;
+        }
+        Node::File { name, license } => {
+            render_license(&prefix, std::iter::once(name), license, buffer)?;
+        }
+    }
+
+    Ok(())
+}
+
+fn render_license<'a>(
+    prefix: &str,
+    names: impl Iterator<Item = &'a String>,
+    license: &License,
+    buffer: &mut Vec<u8>,
+) -> Result<(), Error> {
+    for name in names {
+        writeln!(buffer, "{prefix}**`{name}`**  ")?;
+    }
+    writeln!(buffer, "{prefix}License: `{}`  ", license.spdx)?;
+    for (i, copyright) in license.copyright.iter().enumerate() {
+        let suffix = if i == license.copyright.len() - 1 { "" } else { "  " };
+        writeln!(buffer, "{prefix}Copyright: {copyright}{suffix}")?;
+    }
+
+    Ok(())
+}
+
+#[derive(serde::Deserialize)]
+struct Metadata {
+    files: Node,
+}
+
+#[derive(serde::Deserialize)]
+#[serde(rename_all = "kebab-case", tag = "type")]
+pub(crate) enum Node {
+    Root { childs: Vec<Node> },
+    Directory { name: String, childs: Vec<Node>, license: License },
+    File { name: String, license: License },
+    FileGroup { names: Vec<String>, license: License },
+}
+
+#[derive(serde::Deserialize)]
+struct License {
+    spdx: String,
+    copyright: Vec<String>,
+}
+
+fn env_path(var: &str) -> Result<PathBuf, Error> {
+    if let Some(var) = std::env::var_os(var) {
+        Ok(var.into())
+    } else {
+        anyhow::bail!("missing environment variable {var}")
+    }
+}
diff --git a/src/tools/miri/src/borrow_tracker/mod.rs b/src/tools/miri/src/borrow_tracker/mod.rs
index 10e6e252e94..f896a337f42 100644
--- a/src/tools/miri/src/borrow_tracker/mod.rs
+++ b/src/tools/miri/src/borrow_tracker/mod.rs
@@ -11,7 +11,6 @@ use rustc_target::abi::Size;
 
 use crate::*;
 pub mod stacked_borrows;
-use stacked_borrows::diagnostics::RetagCause;
 
 pub type CallId = NonZeroU64;
 
@@ -265,11 +264,19 @@ impl GlobalStateInner {
 
 impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
 pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
-    fn retag(&mut self, kind: RetagKind, place: &PlaceTy<'tcx, Provenance>) -> InterpResult<'tcx> {
+    fn retag_ptr_value(&mut self, kind: RetagKind, val: &ImmTy<'tcx, Provenance>) -> InterpResult<'tcx, ImmTy<'tcx, Provenance>> {
         let this = self.eval_context_mut();
         let method = this.machine.borrow_tracker.as_ref().unwrap().borrow().borrow_tracker_method;
         match method {
-            BorrowTrackerMethod::StackedBorrows => this.sb_retag(kind, place),
+            BorrowTrackerMethod::StackedBorrows => this.sb_retag_ptr_value(kind, val),
+        }
+    }
+
+    fn retag_place_contents(&mut self, kind: RetagKind, place: &PlaceTy<'tcx, Provenance>) -> InterpResult<'tcx> {
+        let this = self.eval_context_mut();
+        let method = this.machine.borrow_tracker.as_ref().unwrap().borrow().borrow_tracker_method;
+        match method {
+            BorrowTrackerMethod::StackedBorrows => this.sb_retag_place_contents(kind, place),
         }
     }
 
diff --git a/src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs b/src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs
index 9a7b38b13a3..24b3489e0d1 100644
--- a/src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs
+++ b/src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs
@@ -459,10 +459,10 @@ impl<'history, 'ecx, 'mir, 'tcx> DiagnosticCx<'history, 'ecx, 'mir, 'tcx> {
             Operation::Dealloc(_) => format!(" due to deallocation"),
             Operation::Access(AccessOp { kind, tag, .. }) =>
                 format!(" due to {kind:?} access for {tag:?}"),
-            Operation::Retag(RetagOp { orig_tag, permission, .. }) => {
+            Operation::Retag(RetagOp { orig_tag, permission, new_tag, .. }) => {
                 let permission = permission
                     .expect("start_grant should set the current permission before popping a tag");
-                format!(" due to {permission:?} retag from {orig_tag:?}")
+                format!(" due to {permission:?} retag from {orig_tag:?} (that retag created {new_tag:?})")
             }
         };
 
diff --git a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs
index bcac873251f..ffbc0086402 100644
--- a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs
+++ b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs
@@ -1,9 +1,13 @@
 //! Implements "Stacked Borrows".  See <https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md>
 //! for further information.
 
+pub mod diagnostics;
+mod item;
+mod stack;
+
 use log::trace;
 use std::cmp;
-use std::fmt::{self, Write};
+use std::fmt::Write;
 
 use rustc_data_structures::fx::FxHashSet;
 use rustc_middle::mir::{Mutability, RetagKind};
@@ -15,15 +19,13 @@ use rustc_target::abi::{Abi, Size};
 
 use crate::borrow_tracker::{
     stacked_borrows::diagnostics::{AllocHistory, DiagnosticCx, DiagnosticCxBuilder, TagHistory},
-    AccessKind, GlobalStateInner, ProtectorKind, RetagCause, RetagFields,
+    AccessKind, GlobalStateInner, ProtectorKind, RetagFields,
 };
 use crate::*;
 
-mod item;
+use diagnostics::RetagCause;
 pub use item::{Item, Permission};
-mod stack;
 pub use stack::Stack;
-pub mod diagnostics;
 
 pub type AllocState = Stacks;
 
@@ -40,30 +42,104 @@ pub struct Stacks {
     modified_since_last_gc: bool,
 }
 
-/// Indicates which kind of reference is being created.
-/// Used by high-level `reborrow` to compute which permissions to grant to the
-/// new pointer.
-#[derive(Copy, Clone, Hash, PartialEq, Eq)]
-enum RefKind {
-    /// `Box`.
-    Box,
-    /// `&mut`.
-    Unique { two_phase: bool },
-    /// `&` with or without interior mutability.
-    Shared,
-    /// `*mut`/`*const` (raw pointers).
-    Raw { mutable: bool },
+/// Indicates which permissions to grant to the retagged pointer.
+#[derive(Clone, Debug)]
+enum NewPermission {
+    Uniform {
+        perm: Permission,
+        access: Option<AccessKind>,
+        protector: Option<ProtectorKind>,
+    },
+    FreezeSensitive {
+        freeze_perm: Permission,
+        freeze_access: Option<AccessKind>,
+        freeze_protector: Option<ProtectorKind>,
+        nonfreeze_perm: Permission,
+        nonfreeze_access: Option<AccessKind>,
+        // nonfreeze_protector must always be None
+    },
 }
 
-impl fmt::Display for RefKind {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+impl NewPermission {
+    /// A key function: determine the permissions to grant at a retag for the given kind of
+    /// reference/pointer.
+    fn from_ref_ty<'tcx>(
+        ty: ty::Ty<'tcx>,
+        kind: RetagKind,
+        cx: &crate::MiriInterpCx<'_, 'tcx>,
+    ) -> Self {
+        let protector = (kind == RetagKind::FnEntry).then_some(ProtectorKind::StrongProtector);
+        match ty.kind() {
+            ty::Ref(_, pointee, Mutability::Mut) => {
+                if kind == RetagKind::TwoPhase {
+                    // We mostly just give up on 2phase-borrows, and treat these exactly like raw pointers.
+                    assert!(protector.is_none()); // RetagKind can't be both FnEntry and TwoPhase.
+                    NewPermission::Uniform {
+                        perm: Permission::SharedReadWrite,
+                        access: None,
+                        protector: None,
+                    }
+                } else if pointee.is_unpin(*cx.tcx, cx.param_env()) {
+                    // A regular full mutable reference.
+                    NewPermission::Uniform {
+                        perm: Permission::Unique,
+                        access: Some(AccessKind::Write),
+                        protector,
+                    }
+                } else {
+                    NewPermission::Uniform {
+                        perm: Permission::SharedReadWrite,
+                        // FIXME: We emit `dereferenceable` for `!Unpin` mutable references, so we
+                        // should do fake accesses here. But then we run into
+                        // <https://github.com/rust-lang/unsafe-code-guidelines/issues/381>, so for now
+                        // we don't do that.
+                        access: None,
+                        protector,
+                    }
+                }
+            }
+            ty::RawPtr(ty::TypeAndMut { mutbl: Mutability::Mut, .. }) => {
+                assert!(protector.is_none()); // RetagKind can't be both FnEntry and Raw.
+                // Mutable raw pointer. No access, not protected.
+                NewPermission::Uniform {
+                    perm: Permission::SharedReadWrite,
+                    access: None,
+                    protector: None,
+                }
+            }
+            ty::Ref(_, _pointee, Mutability::Not) => {
+                NewPermission::FreezeSensitive {
+                    freeze_perm: Permission::SharedReadOnly,
+                    freeze_access: Some(AccessKind::Read),
+                    freeze_protector: protector,
+                    nonfreeze_perm: Permission::SharedReadWrite,
+                    // Inside UnsafeCell, this does *not* count as an access, as there
+                    // might actually be mutable references further up the stack that
+                    // we have to keep alive.
+                    nonfreeze_access: None,
+                    // We do not protect inside UnsafeCell.
+                    // This fixes https://github.com/rust-lang/rust/issues/55005.
+                }
+            }
+            ty::RawPtr(ty::TypeAndMut { mutbl: Mutability::Not, .. }) => {
+                assert!(protector.is_none()); // RetagKind can't be both FnEntry and Raw.
+                // `*const T`, when freshly created, are read-only in the frozen part.
+                NewPermission::FreezeSensitive {
+                    freeze_perm: Permission::SharedReadOnly,
+                    freeze_access: Some(AccessKind::Read),
+                    freeze_protector: None,
+                    nonfreeze_perm: Permission::SharedReadWrite,
+                    nonfreeze_access: None,
+                }
+            }
+            _ => unreachable!(),
+        }
+    }
+
+    fn protector(&self) -> Option<ProtectorKind> {
         match self {
-            RefKind::Box => write!(f, "Box"),
-            RefKind::Unique { two_phase: false } => write!(f, "unique reference"),
-            RefKind::Unique { two_phase: true } => write!(f, "unique reference (two-phase)"),
-            RefKind::Shared => write!(f, "shared reference"),
-            RefKind::Raw { mutable: true } => write!(f, "raw (mutable) pointer"),
-            RefKind::Raw { mutable: false } => write!(f, "raw (constant) pointer"),
+            NewPermission::Uniform { protector, .. } => *protector,
+            NewPermission::FreezeSensitive { freeze_protector, .. } => *freeze_protector,
         }
     }
 }
@@ -518,10 +594,9 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<'
         &mut self,
         place: &MPlaceTy<'tcx, Provenance>,
         size: Size,
-        kind: RefKind,
-        retag_cause: RetagCause, // What caused this retag, for diagnostics only
+        new_perm: NewPermission,
         new_tag: BorTag,
-        protect: Option<ProtectorKind>,
+        retag_cause: RetagCause, // What caused this retag, for diagnostics only
     ) -> InterpResult<'tcx, Option<AllocId>> {
         let this = self.eval_context_mut();
 
@@ -532,20 +607,16 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<'
             let global = this.machine.borrow_tracker.as_ref().unwrap().borrow();
             let ty = place.layout.ty;
             if global.tracked_pointer_tags.contains(&new_tag) {
-                let mut kind_str = format!("{kind}");
-                match kind {
-                    RefKind::Unique { two_phase: false }
-                        if !ty.is_unpin(*this.tcx, this.param_env()) =>
-                    {
-                        write!(kind_str, " (!Unpin pointee type {ty})").unwrap()
-                    },
-                    RefKind::Shared
-                        if !ty.is_freeze(*this.tcx, this.param_env()) =>
-                    {
-                        write!(kind_str, " (!Freeze pointee type {ty})").unwrap()
-                    },
-                    _ => write!(kind_str, " (pointee type {ty})").unwrap(),
-                };
+                let mut kind_str = String::new();
+                match new_perm {
+                    NewPermission::Uniform { perm, .. } =>
+                        write!(kind_str, "{perm:?} permission").unwrap(),
+                    NewPermission::FreezeSensitive { freeze_perm, .. } if ty.is_freeze(*this.tcx, this.param_env()) =>
+                        write!(kind_str, "{freeze_perm:?} permission").unwrap(),
+                    NewPermission::FreezeSensitive { freeze_perm, nonfreeze_perm, .. }  =>
+                        write!(kind_str, "{freeze_perm:?}/{nonfreeze_perm:?} permission for frozen/non-frozen parts").unwrap(),
+                }
+                write!(kind_str, " (pointee type {ty})").unwrap();
                 this.emit_diagnostic(NonHaltingDiagnostic::CreatedPointerTag(
                     new_tag.inner(),
                     Some(kind_str),
@@ -579,7 +650,7 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<'
                     );
                     let mut dcx = dcx.build(&mut stacked_borrows.history, base_offset);
                     dcx.log_creation();
-                    if protect.is_some() {
+                    if new_perm.protector().is_some() {
                         dcx.log_protector();
                     }
                 },
@@ -592,8 +663,7 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<'
 
         if size == Size::ZERO {
             trace!(
-                "reborrow of size 0: {} reference {:?} derived from {:?} (pointee {})",
-                kind,
+                "reborrow of size 0: reference {:?} derived from {:?} (pointee {})",
                 new_tag,
                 place.ptr,
                 place.layout.ty,
@@ -630,8 +700,7 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<'
         }
 
         trace!(
-            "reborrow: {} reference {:?} derived from {:?} (pointee {}): {:?}, size {}",
-            kind,
+            "reborrow: reference {:?} derived from {:?} (pointee {}): {:?}, size {}",
             new_tag,
             orig_tag,
             place.layout.ty,
@@ -639,7 +708,7 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<'
             size.bytes()
         );
 
-        if let Some(protect) = protect {
+        if let Some(protect) = new_perm.protector() {
             // See comment in `Stack::item_invalidated` for why we store the tag twice.
             this.frame_mut().extra.borrow_tracker.as_mut().unwrap().protected_tags.push(new_tag);
             this.machine
@@ -651,30 +720,45 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<'
                 .insert(new_tag, protect);
         }
 
-        // Update the stacks.
-        // Make sure that raw pointers and mutable shared references are reborrowed "weak":
-        // There could be existing unique pointers reborrowed from them that should remain valid!
-        let (perm, access) = match kind {
-            RefKind::Unique { two_phase } => {
-                // Permission is Unique only if the type is `Unpin` and this is not twophase
-                if !two_phase && place.layout.ty.is_unpin(*this.tcx, this.param_env()) {
-                    (Permission::Unique, Some(AccessKind::Write))
-                } else {
-                    // FIXME: We emit `dereferenceable` for `!Unpin` mutable references, so we
-                    // should do fake accesses here. But then we run into
-                    // <https://github.com/rust-lang/unsafe-code-guidelines/issues/381>, so for now
-                    // we don't do that.
-                    (Permission::SharedReadWrite, None)
+        // Update the stacks, according to the new permission information we are given.
+        match new_perm {
+            NewPermission::Uniform { perm, access, protector } => {
+                assert!(perm != Permission::SharedReadOnly);
+                // Here we can avoid `borrow()` calls because we have mutable references.
+                // Note that this asserts that the allocation is mutable -- but since we are creating a
+                // mutable pointer, that seems reasonable.
+                let (alloc_extra, machine) = this.get_alloc_extra_mut(alloc_id)?;
+                let stacked_borrows = alloc_extra.borrow_tracker_sb_mut().get_mut();
+                let item = Item::new(new_tag, perm, protector.is_some());
+                let range = alloc_range(base_offset, size);
+                let global = machine.borrow_tracker.as_ref().unwrap().borrow();
+                let dcx = DiagnosticCxBuilder::retag(
+                    machine,
+                    retag_cause,
+                    new_tag,
+                    orig_tag,
+                    alloc_range(base_offset, size),
+                );
+                stacked_borrows.for_each(range, dcx, |stack, dcx, exposed_tags| {
+                    stack.grant(orig_tag, item, access, &global, dcx, exposed_tags)
+                })?;
+                drop(global);
+                if let Some(access) = access {
+                    assert_eq!(access, AccessKind::Write);
+                    // Make sure the data race model also knows about this.
+                    if let Some(data_race) = alloc_extra.data_race.as_mut() {
+                        data_race.write(alloc_id, range, machine)?;
+                    }
                 }
             }
-            RefKind::Box => (Permission::Unique, Some(AccessKind::Write)),
-            RefKind::Raw { mutable: true } => {
-                // Creating a raw ptr does not count as an access
-                (Permission::SharedReadWrite, None)
-            }
-            RefKind::Shared | RefKind::Raw { mutable: false } => {
-                // Shared references and *const are a whole different kind of game, the
-                // permission is not uniform across the entire range!
+            NewPermission::FreezeSensitive {
+                freeze_perm,
+                freeze_access,
+                freeze_protector,
+                nonfreeze_perm,
+                nonfreeze_access,
+            } => {
+                // The permission is not uniform across the entire range!
                 // We need a frozen-sensitive reborrow.
                 // We have to use shared references to alloc/memory_extra here since
                 // `visit_freeze_sensitive` needs to access the global state.
@@ -684,22 +768,12 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<'
                     // Adjust range.
                     range.start += base_offset;
                     // We are only ever `SharedReadOnly` inside the frozen bits.
-                    let (perm, access) = if frozen {
-                        (Permission::SharedReadOnly, Some(AccessKind::Read))
-                    } else {
-                        // Inside UnsafeCell, this does *not* count as an access, as there
-                        // might actually be mutable references further up the stack that
-                        // we have to keep alive.
-                        (Permission::SharedReadWrite, None)
-                    };
-                    let protected = if frozen {
-                        protect.is_some()
+                    let (perm, access, protector) = if frozen {
+                        (freeze_perm, freeze_access, freeze_protector)
                     } else {
-                        // We do not protect inside UnsafeCell.
-                        // This fixes https://github.com/rust-lang/rust/issues/55005.
-                        false
+                        (nonfreeze_perm, nonfreeze_access, None)
                     };
-                    let item = Item::new(new_tag, perm, protected);
+                    let item = Item::new(new_tag, perm, protector.is_some());
                     let global = this.machine.borrow_tracker.as_ref().unwrap().borrow();
                     let dcx = DiagnosticCxBuilder::retag(
                         &this.machine,
@@ -721,34 +795,6 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<'
                     }
                     Ok(())
                 })?;
-                return Ok(Some(alloc_id));
-            }
-        };
-
-        // Here we can avoid `borrow()` calls because we have mutable references.
-        // Note that this asserts that the allocation is mutable -- but since we are creating a
-        // mutable pointer, that seems reasonable.
-        let (alloc_extra, machine) = this.get_alloc_extra_mut(alloc_id)?;
-        let stacked_borrows = alloc_extra.borrow_tracker_sb_mut().get_mut();
-        let item = Item::new(new_tag, perm, protect.is_some());
-        let range = alloc_range(base_offset, size);
-        let global = machine.borrow_tracker.as_ref().unwrap().borrow();
-        let dcx = DiagnosticCxBuilder::retag(
-            machine,
-            retag_cause,
-            new_tag,
-            orig_tag,
-            alloc_range(base_offset, size),
-        );
-        stacked_borrows.for_each(range, dcx, |stack, dcx, exposed_tags| {
-            stack.grant(orig_tag, item, access, &global, dcx, exposed_tags)
-        })?;
-        drop(global);
-        if let Some(access) = access {
-            assert_eq!(access, AccessKind::Write);
-            // Make sure the data race model also knows about this.
-            if let Some(data_race) = alloc_extra.data_race.as_mut() {
-                data_race.write(alloc_id, range, machine)?;
             }
         }
 
@@ -760,9 +806,8 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<'
     fn sb_retag_reference(
         &mut self,
         val: &ImmTy<'tcx, Provenance>,
-        kind: RefKind,
-        retag_cause: RetagCause, // What caused this retag, for diagnostics only
-        protect: Option<ProtectorKind>,
+        new_perm: NewPermission,
+        cause: RetagCause, // What caused this retag, for diagnostics only
     ) -> InterpResult<'tcx, ImmTy<'tcx, Provenance>> {
         let this = self.eval_context_mut();
         // We want a place for where the ptr *points to*, so we get one.
@@ -780,7 +825,7 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<'
         let new_tag = this.machine.borrow_tracker.as_mut().unwrap().get_mut().new_ptr();
 
         // Reborrow.
-        let alloc_id = this.sb_reborrow(&place, size, kind, retag_cause, new_tag, protect)?;
+        let alloc_id = this.sb_reborrow(&place, size, new_perm, new_tag, cause)?;
 
         // Adjust pointer.
         let new_place = place.map_provenance(|p| {
@@ -807,7 +852,22 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<'
 
 impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
 pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
-    fn sb_retag(
+    fn sb_retag_ptr_value(
+        &mut self,
+        kind: RetagKind,
+        val: &ImmTy<'tcx, Provenance>,
+    ) -> InterpResult<'tcx, ImmTy<'tcx, Provenance>> {
+        let this = self.eval_context_mut();
+        let new_perm = NewPermission::from_ref_ty(val.layout.ty, kind, this);
+        let retag_cause = match kind {
+            RetagKind::TwoPhase { .. } => RetagCause::TwoPhase,
+            RetagKind::FnEntry => unreachable!(),
+            RetagKind::Raw | RetagKind::Default => RetagCause::Normal,
+        };
+        this.sb_retag_reference(&val, new_perm, retag_cause)
+    }
+
+    fn sb_retag_place_contents(
         &mut self,
         kind: RetagKind,
         place: &PlaceTy<'tcx, Provenance>,
@@ -815,9 +875,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         let this = self.eval_context_mut();
         let retag_fields = this.machine.borrow_tracker.as_mut().unwrap().get_mut().retag_fields;
         let retag_cause = match kind {
-            RetagKind::TwoPhase { .. } => RetagCause::TwoPhase,
+            RetagKind::Raw | RetagKind::TwoPhase { .. } => unreachable!(), // these can only happen in `retag_ptr_value`
             RetagKind::FnEntry => RetagCause::FnEntry,
-            RetagKind::Raw | RetagKind::Default => RetagCause::Normal,
+            RetagKind::Default => RetagCause::Normal,
         };
         let mut visitor = RetagVisitor { ecx: this, kind, retag_cause, retag_fields };
         return visitor.visit_value(place);
@@ -831,15 +891,14 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         }
         impl<'ecx, 'mir, 'tcx> RetagVisitor<'ecx, 'mir, 'tcx> {
             #[inline(always)] // yes this helps in our benchmarks
-            fn retag_place(
+            fn retag_ptr_inplace(
                 &mut self,
                 place: &PlaceTy<'tcx, Provenance>,
-                ref_kind: RefKind,
+                new_perm: NewPermission,
                 retag_cause: RetagCause,
-                protector: Option<ProtectorKind>,
             ) -> InterpResult<'tcx> {
                 let val = self.ecx.read_immediate(&self.ecx.place_to_op(place)?)?;
-                let val = self.ecx.sb_retag_reference(&val, ref_kind, retag_cause, protector)?;
+                let val = self.ecx.sb_retag_reference(&val, new_perm, retag_cause)?;
                 self.ecx.write_immediate(*val, place)?;
                 Ok(())
             }
@@ -856,13 +915,13 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
 
             fn visit_box(&mut self, place: &PlaceTy<'tcx, Provenance>) -> InterpResult<'tcx> {
                 // Boxes get a weak protectors, since they may be deallocated.
-                self.retag_place(
-                    place,
-                    RefKind::Box,
-                    self.retag_cause,
-                    /*protector*/
-                    (self.kind == RetagKind::FnEntry).then_some(ProtectorKind::WeakProtector),
-                )
+                let new_perm = NewPermission::Uniform {
+                    perm: Permission::Unique,
+                    access: Some(AccessKind::Write),
+                    protector: (self.kind == RetagKind::FnEntry)
+                        .then_some(ProtectorKind::WeakProtector),
+                };
+                self.retag_ptr_inplace(place, new_perm, self.retag_cause)
             }
 
             fn visit_value(&mut self, place: &PlaceTy<'tcx, Provenance>) -> InterpResult<'tcx> {
@@ -876,36 +935,16 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
 
                 // Check the type of this value to see what to do with it (retag, or recurse).
                 match place.layout.ty.kind() {
-                    ty::Ref(_, _, mutbl) => {
-                        let ref_kind = match mutbl {
-                            Mutability::Mut =>
-                                RefKind::Unique { two_phase: self.kind == RetagKind::TwoPhase },
-                            Mutability::Not => RefKind::Shared,
-                        };
-                        self.retag_place(
-                            place,
-                            ref_kind,
-                            self.retag_cause,
-                            /*protector*/
-                            (self.kind == RetagKind::FnEntry)
-                                .then_some(ProtectorKind::StrongProtector),
-                        )?;
+                    ty::Ref(..) => {
+                        let new_perm =
+                            NewPermission::from_ref_ty(place.layout.ty, self.kind, self.ecx);
+                        self.retag_ptr_inplace(place, new_perm, self.retag_cause)?;
                     }
-                    ty::RawPtr(tym) => {
-                        // We definitely do *not* want to recurse into raw pointers -- wide raw
-                        // pointers have fields, and for dyn Trait pointees those can have reference
-                        // type!
-                        if self.kind == RetagKind::Raw {
-                            // Raw pointers need to be enabled.
-                            self.retag_place(
-                                place,
-                                RefKind::Raw { mutable: tym.mutbl == Mutability::Mut },
-                                self.retag_cause,
-                                /*protector*/ None,
-                            )?;
-                        }
+                    ty::RawPtr(..) => {
+                        // We do *not* want to recurse into raw pointers -- wide raw pointers have
+                        // fields, and for dyn Trait pointees those can have reference type!
                     }
-                    _ if place.layout.ty.ty_adt_def().is_some_and(|adt| adt.is_box()) => {
+                    ty::Adt(adt, _) if adt.is_box() => {
                         // Recurse for boxes, they require some tricky handling and will end up in `visit_box` above.
                         // (Yes this means we technically also recursively retag the allocator itself
                         // even if field retagging is not enabled. *shrug*)
@@ -953,12 +992,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         let ptr_layout = this.layout_of(this.tcx.mk_mut_ptr(return_place.layout.ty))?;
         let val = ImmTy::from_immediate(return_place.to_ref(this), ptr_layout);
         // Reborrow it. With protection! That is part of the point.
-        let val = this.sb_retag_reference(
-            &val,
-            RefKind::Unique { two_phase: false },
-            RetagCause::FnReturn,
-            /*protector*/ Some(ProtectorKind::StrongProtector),
-        )?;
+        let new_perm = NewPermission::Uniform {
+            perm: Permission::Unique,
+            access: Some(AccessKind::Write),
+            protector: Some(ProtectorKind::StrongProtector),
+        };
+        let val = this.sb_retag_reference(&val, new_perm, RetagCause::FnReturn)?;
         // And use reborrowed pointer for return place.
         let return_place = this.ref_to_mplace(&val)?;
         this.frame_mut().return_place = return_place.into();
diff --git a/src/tools/miri/src/diagnostics.rs b/src/tools/miri/src/diagnostics.rs
index 074fa032dcc..d0fb9f9b0b5 100644
--- a/src/tools/miri/src/diagnostics.rs
+++ b/src/tools/miri/src/diagnostics.rs
@@ -63,9 +63,9 @@ impl MachineStopType for TerminationInfo {}
 
 /// Miri specific diagnostics
 pub enum NonHaltingDiagnostic {
-    /// (new_tag, new_kind, (alloc_id, base_offset, orig_tag))
+    /// (new_tag, new_perm, (alloc_id, base_offset, orig_tag))
     ///
-    /// new_kind is `None` for base tags.
+    /// new_perm is `None` for base tags.
     CreatedPointerTag(NonZeroU64, Option<String>, Option<(AllocId, AllocRange, ProvenanceExtra)>),
     /// This `Item` was popped from the borrow stack. The string explains the reason.
     PoppedPointerTag(Item, String),
@@ -393,10 +393,10 @@ impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> {
 
         let msg = match &e {
             CreatedPointerTag(tag, None, _) => format!("created base tag {tag:?}"),
-            CreatedPointerTag(tag, Some(kind), None) => format!("created {tag:?} for {kind}"),
-            CreatedPointerTag(tag, Some(kind), Some((alloc_id, range, orig_tag))) =>
+            CreatedPointerTag(tag, Some(perm), None) => format!("created {tag:?} with {perm} derived from unknown tag"),
+            CreatedPointerTag(tag, Some(perm), Some((alloc_id, range, orig_tag))) =>
                 format!(
-                    "created tag {tag:?} for {kind} at {alloc_id:?}{range:?} derived from {orig_tag:?}"
+                    "created tag {tag:?} with {perm} at {alloc_id:?}{range:?} derived from {orig_tag:?}"
                 ),
             PoppedPointerTag(item, cause) => format!("popped tracked tag for item {item:?}{cause}"),
             CreatedCallId(id) => format!("function call with id {id}"),
diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs
index c110229c985..e5b1eb2e487 100644
--- a/src/tools/miri/src/machine.rs
+++ b/src/tools/miri/src/machine.rs
@@ -967,8 +967,9 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
         ptr: Pointer<Self::Provenance>,
     ) -> InterpResult<'tcx> {
         match ptr.provenance {
-            Provenance::Concrete { alloc_id, tag } =>
-                intptrcast::GlobalStateInner::expose_ptr(ecx, alloc_id, tag),
+            Provenance::Concrete { alloc_id, tag } => {
+                intptrcast::GlobalStateInner::expose_ptr(ecx, alloc_id, tag)
+            }
             Provenance::Wildcard => {
                 // No need to do anything for wildcard pointers as
                 // their provenances have already been previously exposed.
@@ -1055,13 +1056,26 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
     }
 
     #[inline(always)]
-    fn retag(
+    fn retag_ptr_value(
+        ecx: &mut InterpCx<'mir, 'tcx, Self>,
+        kind: mir::RetagKind,
+        val: &ImmTy<'tcx, Provenance>,
+    ) -> InterpResult<'tcx, ImmTy<'tcx, Provenance>> {
+        if ecx.machine.borrow_tracker.is_some() {
+            ecx.retag_ptr_value(kind, val)
+        } else {
+            Ok(val.clone())
+        }
+    }
+
+    #[inline(always)]
+    fn retag_place_contents(
         ecx: &mut InterpCx<'mir, 'tcx, Self>,
         kind: mir::RetagKind,
         place: &PlaceTy<'tcx, Provenance>,
     ) -> InterpResult<'tcx> {
         if ecx.machine.borrow_tracker.is_some() {
-            ecx.retag(kind, place)?;
+            ecx.retag_place_contents(kind, place)?;
         }
         Ok(())
     }
diff --git a/triagebot.toml b/triagebot.toml
index bc0b88b2bab..49945e5c533 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -331,8 +331,16 @@ message = "Some changes occurred to MIR optimizations"
 cc = ["@rust-lang/wg-mir-opt"]
 
 [mentions."compiler/rustc_trait_selection/src/traits/const_evaluatable.rs"]
-message = "Some changes occurred in const_evaluatable.rs"
-cc = ["@lcnr"]
+message = "Some changes occurred in `const_evaluatable.rs`"
+cc = ["@BoxyUwU"]
+
+[mentions."compiler/rustc_middle/src/ty/abstract_const.rs"]
+message = "Some changes occured in `abstract_const.rs`"
+cc = ["@BoxyUwU"]
+
+[mentions."compiler/rustc_ty_utils/src/consts.rs"]
+message = "Some changes occured in `rustc_ty_utils::consts.rs`"
+cc = ["@BoxyUwU"]
 
 [mentions."compiler/rustc_trait_selection/src/traits/engine.rs"]
 message = """