about summary refs log tree commit diff
diff options
context:
space:
mode:
authorRalf Jung <post@ralfj.de>2022-11-10 09:59:18 +0100
committerRalf Jung <post@ralfj.de>2022-11-10 11:38:50 +0100
commitc02fa89007e47b4e99764e6f5bef7a7c3262139a (patch)
tree56e87adda0210ae585691eb2c6e3f1feb63affcf
parent71c3ecf31f1adf920d2cfd577392b8a45ac9c808 (diff)
parentdf2adc4760a1c03096ab4b39512ba90b983c2332 (diff)
downloadrust-c02fa89007e47b4e99764e6f5bef7a7c3262139a.tar.gz
rust-c02fa89007e47b4e99764e6f5bef7a7c3262139a.zip
Merge from rustc
-rw-r--r--Cargo.lock161
-rw-r--r--compiler/rustc_ast/src/util/literal.rs29
-rw-r--r--compiler/rustc_borrowck/src/constraints/graph.rs1
-rw-r--r--compiler/rustc_borrowck/src/constraints/mod.rs3
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs3
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs16
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/mod.rs20
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/region_errors.rs10
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/region_name.rs2
-rw-r--r--compiler/rustc_borrowck/src/lib.rs14
-rw-r--r--compiler/rustc_borrowck/src/nll.rs2
-rw-r--r--compiler/rustc_borrowck/src/region_infer/dump_mir.rs3
-rw-r--r--compiler/rustc_borrowck/src/region_infer/mod.rs162
-rw-r--r--compiler/rustc_borrowck/src/region_infer/opaque_types.rs4
-rw-r--r--compiler/rustc_borrowck/src/session_diagnostics.rs30
-rw-r--r--compiler/rustc_borrowck/src/type_check/constraint_conversion.rs82
-rw-r--r--compiler/rustc_borrowck/src/type_check/free_region_relations.rs5
-rw-r--r--compiler/rustc_borrowck/src/type_check/mod.rs109
-rw-r--r--compiler/rustc_borrowck/src/type_check/relate_tys.rs1
-rw-r--r--compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs2
-rw-r--r--compiler/rustc_codegen_gcc/src/type_.rs42
-rw-r--r--compiler/rustc_codegen_llvm/src/attributes.rs18
-rw-r--r--compiler/rustc_codegen_llvm/src/back/archive.rs35
-rw-r--r--compiler/rustc_codegen_llvm/src/back/lto.rs9
-rw-r--r--compiler/rustc_codegen_llvm/src/consts.rs20
-rw-r--r--compiler/rustc_codegen_llvm/src/context.rs12
-rw-r--r--compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs3
-rw-r--r--compiler/rustc_codegen_llvm/src/errors.rs139
-rw-r--r--compiler/rustc_codegen_llvm/src/lib.rs6
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm_util.rs38
-rw-r--r--compiler/rustc_codegen_llvm/src/mono_item.rs7
-rw-r--r--compiler/rustc_codegen_llvm/src/type_.rs8
-rw-r--r--compiler/rustc_codegen_ssa/src/back/write.rs24
-rw-r--r--compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs26
-rw-r--r--compiler/rustc_codegen_ssa/src/traits/type_.rs1
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/check.rs3
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs3
-rw-r--r--compiler/rustc_data_structures/Cargo.toml2
-rw-r--r--compiler/rustc_driver/src/lib.rs53
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0207.md75
-rw-r--r--compiler/rustc_error_messages/locales/en-US/borrowck.ftl12
-rw-r--r--compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl58
-rw-r--r--compiler/rustc_error_messages/locales/en-US/infer.ftl1
-rw-r--r--compiler/rustc_error_messages/locales/en-US/parser.ftl6
-rw-r--r--compiler/rustc_error_messages/locales/en-US/passes.ftl5
-rw-r--r--compiler/rustc_error_messages/src/lib.rs1
-rw-r--r--compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs1
-rw-r--r--compiler/rustc_errors/src/diagnostic.rs32
-rw-r--r--compiler/rustc_errors/src/diagnostic_builder.rs4
-rw-r--r--compiler/rustc_errors/src/diagnostic_impls.rs6
-rw-r--r--compiler/rustc_errors/src/emitter.rs60
-rw-r--r--compiler/rustc_feature/src/accepted.rs2
-rw-r--r--compiler/rustc_feature/src/active.rs4
-rw-r--r--compiler/rustc_feature/src/builtin_attrs.rs10
-rw-r--r--compiler/rustc_hir/src/hir.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/mod.rs50
-rw-r--r--compiler/rustc_hir_analysis/src/check/check.rs5
-rw-r--r--compiler/rustc_hir_analysis/src/check/compare_method.rs20
-rw-r--r--compiler/rustc_hir_analysis/src/check/intrinsic.rs17
-rw-r--r--compiler/rustc_hir_analysis/src/check/wfcheck.rs49
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/builtin.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/collect.rs3
-rw-r--r--compiler/rustc_hir_analysis/src/collect/lifetimes.rs104
-rw-r--r--compiler/rustc_hir_analysis/src/collect/type_of.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/lib.rs4
-rw-r--r--compiler/rustc_hir_typeck/src/_match.rs123
-rw-r--r--compiler/rustc_hir_typeck/src/autoderef.rs19
-rw-r--r--compiler/rustc_hir_typeck/src/callee.rs21
-rw-r--r--compiler/rustc_hir_typeck/src/check.rs39
-rw-r--r--compiler/rustc_hir_typeck/src/closure.rs10
-rw-r--r--compiler/rustc_hir_typeck/src/coercion.rs11
-rw-r--r--compiler/rustc_hir_typeck/src/expr.rs23
-rw-r--r--compiler/rustc_hir_typeck/src/fallback.rs26
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs18
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs5
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs14
-rw-r--r--compiler/rustc_hir_typeck/src/generator_interior/mod.rs104
-rw-r--r--compiler/rustc_hir_typeck/src/lib.rs7
-rw-r--r--compiler/rustc_hir_typeck/src/method/confirm.rs3
-rw-r--r--compiler/rustc_hir_typeck/src/method/probe.rs7
-rw-r--r--compiler/rustc_hir_typeck/src/method/suggest.rs138
-rw-r--r--compiler/rustc_hir_typeck/src/op.rs6
-rw-r--r--compiler/rustc_hir_typeck/src/pat.rs9
-rw-r--r--compiler/rustc_hir_typeck/src/place_op.rs7
-rw-r--r--compiler/rustc_infer/src/errors/mod.rs12
-rw-r--r--compiler/rustc_infer/src/errors/note_and_explain.rs7
-rw-r--r--compiler/rustc_infer/src/infer/canonical/canonicalizer.rs4
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/mod.rs90
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs4
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mod.rs5
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/named_anon_conflict.rs2
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_relation.rs79
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs12
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs2
-rw-r--r--compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs3
-rw-r--r--compiler/rustc_infer/src/infer/mod.rs7
-rw-r--r--compiler/rustc_infer/src/infer/region_constraints/leak_check.rs7
-rw-r--r--compiler/rustc_infer/src/infer/region_constraints/mod.rs4
-rw-r--r--compiler/rustc_infer/src/lib.rs1
-rw-r--r--compiler/rustc_infer/src/traits/error_reporting/mod.rs4
-rw-r--r--compiler/rustc_interface/src/lib.rs1
-rw-r--r--compiler/rustc_interface/src/proc_macro_decls.rs15
-rw-r--r--compiler/rustc_interface/src/util.rs22
-rw-r--r--compiler/rustc_lexer/src/lib.rs19
-rw-r--r--compiler/rustc_lexer/src/unescape.rs130
-rw-r--r--compiler/rustc_lexer/src/unescape/tests.rs29
-rw-r--r--compiler/rustc_lint/src/context.rs4
-rw-r--r--compiler/rustc_lint/src/levels.rs1
-rw-r--r--compiler/rustc_lint/src/lib.rs1
-rw-r--r--compiler/rustc_macros/src/diagnostics/error.rs4
-rw-r--r--compiler/rustc_middle/src/infer/canonical.rs6
-rw-r--r--compiler/rustc_middle/src/lint.rs2
-rw-r--r--compiler/rustc_middle/src/middle/privacy.rs124
-rw-r--r--compiler/rustc_middle/src/mir/mod.rs59
-rw-r--r--compiler/rustc_middle/src/query/mod.rs18
-rw-r--r--compiler/rustc_middle/src/traits/mod.rs5
-rw-r--r--compiler/rustc_middle/src/ty/context.rs22
-rw-r--r--compiler/rustc_middle/src/ty/error.rs4
-rw-r--r--compiler/rustc_middle/src/ty/fold.rs8
-rw-r--r--compiler/rustc_middle/src/ty/instance.rs4
-rw-r--r--compiler/rustc_middle/src/ty/layout.rs8
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs8
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs14
-rw-r--r--compiler/rustc_middle/src/ty/structural_impls.rs2
-rw-r--r--compiler/rustc_middle/src/ty/sty.rs2
-rw-r--r--compiler/rustc_middle/src/ty/visit.rs6
-rw-r--r--compiler/rustc_mir_build/src/build/custom/mod.rs155
-rw-r--r--compiler/rustc_mir_build/src/build/custom/parse.rs245
-rw-r--r--compiler/rustc_mir_build/src/build/custom/parse/instruction.rs72
-rw-r--r--compiler/rustc_mir_build/src/build/mod.rs17
-rw-r--r--compiler/rustc_mir_build/src/thir/cx/expr.rs16
-rw-r--r--compiler/rustc_mir_build/src/thir/cx/mod.rs11
-rw-r--r--compiler/rustc_mir_dataflow/src/elaborate_drops.rs5
-rw-r--r--compiler/rustc_mir_transform/src/check_unsafety.rs8
-rw-r--r--compiler/rustc_mir_transform/src/pass_manager.rs73
-rw-r--r--compiler/rustc_mir_transform/src/shim.rs8
-rw-r--r--compiler/rustc_parse/src/errors.rs18
-rw-r--r--compiler/rustc_parse/src/lexer/mod.rs119
-rw-r--r--compiler/rustc_parse/src/lexer/unescape_error_reporting.rs42
-rw-r--r--compiler/rustc_parse/src/parser/diagnostics.rs12
-rw-r--r--compiler/rustc_parse/src/parser/expr.rs45
-rw-r--r--compiler/rustc_parse_format/src/lib.rs47
-rw-r--r--compiler/rustc_passes/src/check_attr.rs55
-rw-r--r--compiler/rustc_passes/src/errors.rs3
-rw-r--r--compiler/rustc_passes/src/lib.rs2
-rw-r--r--compiler/rustc_privacy/src/lib.rs10
-rw-r--r--compiler/rustc_query_impl/src/lib.rs2
-rw-r--r--compiler/rustc_query_impl/src/on_disk_cache.rs2
-rw-r--r--compiler/rustc_query_impl/src/plumbing.rs29
-rw-r--r--compiler/rustc_query_impl/src/profiling_support.rs51
-rw-r--r--compiler/rustc_query_system/src/cache.rs4
-rw-r--r--compiler/rustc_query_system/src/dep_graph/dep_node.rs36
-rw-r--r--compiler/rustc_query_system/src/dep_graph/graph.rs101
-rw-r--r--compiler/rustc_query_system/src/dep_graph/mod.rs3
-rw-r--r--compiler/rustc_query_system/src/query/config.rs60
-rw-r--r--compiler/rustc_query_system/src/query/job.rs6
-rw-r--r--compiler/rustc_query_system/src/query/mod.rs2
-rw-r--r--compiler/rustc_query_system/src/query/plumbing.rs262
-rw-r--r--compiler/rustc_query_system/src/values.rs8
-rw-r--r--compiler/rustc_resolve/src/diagnostics.rs10
-rw-r--r--compiler/rustc_resolve/src/effective_visibilities.rs222
-rw-r--r--compiler/rustc_resolve/src/late/diagnostics.rs33
-rw-r--r--compiler/rustc_resolve/src/lib.rs19
-rw-r--r--compiler/rustc_session/src/config.rs2
-rw-r--r--compiler/rustc_span/src/source_map.rs8
-rw-r--r--compiler/rustc_span/src/source_map/tests.rs11
-rw-r--r--compiler/rustc_span/src/symbol.rs1
-rw-r--r--compiler/rustc_symbol_mangling/src/v0.rs4
-rw-r--r--compiler/rustc_target/src/spec/aarch64_apple_darwin.rs19
-rw-r--r--compiler/rustc_target/src/spec/aarch64_apple_ios.rs20
-rw-r--r--compiler/rustc_target/src/spec/aarch64_apple_ios_macabi.rs7
-rw-r--r--compiler/rustc_target/src/spec/aarch64_apple_ios_sim.rs22
-rw-r--r--compiler/rustc_target/src/spec/aarch64_apple_tvos.rs7
-rw-r--r--compiler/rustc_target/src/spec/aarch64_apple_watchos_sim.rs22
-rw-r--r--compiler/rustc_target/src/spec/apple_base.rs125
-rw-r--r--compiler/rustc_target/src/spec/apple_sdk_base.rs81
-rw-r--r--compiler/rustc_target/src/spec/arm64_32_apple_watchos.rs2
-rw-r--r--compiler/rustc_target/src/spec/armv7_apple_ios.rs15
-rw-r--r--compiler/rustc_target/src/spec/armv7k_apple_watchos.rs8
-rw-r--r--compiler/rustc_target/src/spec/armv7s_apple_ios.rs7
-rw-r--r--compiler/rustc_target/src/spec/i386_apple_ios.rs16
-rw-r--r--compiler/rustc_target/src/spec/i686_apple_darwin.rs24
-rw-r--r--compiler/rustc_target/src/spec/linux_kernel_base.rs18
-rw-r--r--compiler/rustc_target/src/spec/mod.rs10
-rw-r--r--compiler/rustc_target/src/spec/riscv64gc_unknown_freebsd.rs2
-rw-r--r--compiler/rustc_target/src/spec/riscv64gc_unknown_linux_gnu.rs2
-rw-r--r--compiler/rustc_target/src/spec/riscv64gc_unknown_linux_musl.rs2
-rw-r--r--compiler/rustc_target/src/spec/riscv64gc_unknown_none_elf.rs2
-rw-r--r--compiler/rustc_target/src/spec/riscv64gc_unknown_openbsd.rs2
-rw-r--r--compiler/rustc_target/src/spec/riscv64imac_unknown_none_elf.rs2
-rw-r--r--compiler/rustc_target/src/spec/tests/tests_impl.rs9
-rw-r--r--compiler/rustc_target/src/spec/windows_gnullvm_base.rs8
-rw-r--r--compiler/rustc_target/src/spec/x86_64_apple_darwin.rs22
-rw-r--r--compiler/rustc_target/src/spec/x86_64_apple_ios.rs12
-rw-r--r--compiler/rustc_target/src/spec/x86_64_apple_ios_macabi.rs7
-rw-r--r--compiler/rustc_target/src/spec/x86_64_apple_tvos.rs8
-rw-r--r--compiler/rustc_target/src/spec/x86_64_apple_watchos_sim.rs14
-rw-r--r--compiler/rustc_target/src/spec/x86_64_unknown_none_linuxkernel.rs28
-rw-r--r--compiler/rustc_trait_selection/src/autoderef.rs7
-rw-r--r--compiler/rustc_trait_selection/src/infer.rs12
-rw-r--r--compiler/rustc_trait_selection/src/lib.rs1
-rw-r--r--compiler/rustc_trait_selection/src/traits/auto_trait.rs12
-rw-r--r--compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs15
-rw-r--r--compiler/rustc_trait_selection/src/traits/engine.rs23
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs52
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs98
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs398
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs8
-rw-r--r--compiler/rustc_trait_selection/src/traits/misc.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/mod.rs62
-rw-r--r--compiler/rustc_trait_selection/src/traits/on_unimplemented.rs393
-rw-r--r--compiler/rustc_trait_selection/src/traits/outlives_bounds.rs6
-rw-r--r--compiler/rustc_trait_selection/src/traits/project.rs27
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/normalize.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs12
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/mod.rs18
-rw-r--r--compiler/rustc_trait_selection/src/traits/specialize/mod.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/wf.rs2
-rw-r--r--compiler/rustc_traits/src/chalk/db.rs2
-rw-r--r--compiler/rustc_traits/src/chalk/lowering.rs20
-rw-r--r--compiler/rustc_transmute/src/layout/tree.rs4
-rw-r--r--library/alloc/src/alloc/tests.rs1
-rw-r--r--library/alloc/src/boxed.rs31
-rw-r--r--library/alloc/src/collections/btree/node/tests.rs1
-rw-r--r--library/alloc/src/collections/mod.rs2
-rw-r--r--library/alloc/src/collections/vec_deque/tests.rs34
-rw-r--r--library/alloc/src/lib.rs1
-rw-r--r--library/alloc/src/vec/mod.rs6
-rw-r--r--library/core/benches/iter.rs23
-rw-r--r--library/core/benches/lib.rs2
-rw-r--r--library/core/src/array/mod.rs75
-rw-r--r--library/core/src/cell.rs2
-rw-r--r--library/core/src/const_closure.rs30
-rw-r--r--library/core/src/intrinsics.rs69
-rw-r--r--library/core/src/intrinsics/mir.rs123
-rw-r--r--library/core/src/iter/adapters/array_chunks.rs75
-rw-r--r--library/core/src/num/int_macros.rs29
-rw-r--r--library/core/src/num/nonzero.rs8
-rw-r--r--library/core/src/num/uint_macros.rs29
-rw-r--r--library/core/src/ops/function.rs329
-rw-r--r--library/core/src/pin.rs2
-rw-r--r--library/core/src/ptr/const_ptr.rs25
-rw-r--r--library/core/src/ptr/mut_ptr.rs28
-rw-r--r--library/core/src/slice/mod.rs7
-rw-r--r--library/core/src/tuple.rs11
-rw-r--r--library/core/tests/iter/adapters/array_chunks.rs3
-rw-r--r--library/core/tests/lib.rs1
-rw-r--r--library/std/Cargo.toml6
-rw-r--r--library/std/src/f32.rs2
-rw-r--r--library/std/src/f64.rs2
-rw-r--r--library/std/src/sync/mpsc/mpsc_queue.rs11
-rw-r--r--library/std/src/sync/mpsc/spsc_queue.rs8
-rw-r--r--library/unwind/src/lib.rs1
-rw-r--r--src/bootstrap/Cargo.lock75
-rw-r--r--src/bootstrap/Cargo.toml2
-rw-r--r--src/bootstrap/bin/main.rs2
-rw-r--r--src/bootstrap/builder.rs18
-rw-r--r--src/bootstrap/config.rs5
-rw-r--r--src/bootstrap/dist.rs7
-rw-r--r--src/bootstrap/doc.rs118
-rw-r--r--src/bootstrap/sanity.rs16
-rw-r--r--src/bootstrap/setup.rs2
-rw-r--r--src/bootstrap/test.rs7
-rw-r--r--src/ci/docker/host-x86_64/dist-various-2/Dockerfile3
-rwxr-xr-xsrc/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh11
m---------src/doc/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/rustc/src/linker-plugin-lto.md94
-rw-r--r--src/doc/rustc/src/platform-support.md7
-rw-r--r--src/doc/rustc/src/platform-support/unknown-uefi.md38
-rw-r--r--src/etc/natvis/intrinsic.natvis12
-rw-r--r--src/etc/natvis/liballoc.natvis8
-rw-r--r--src/librustdoc/clean/auto_trait.rs5
-rw-r--r--src/librustdoc/clean/inline.rs17
-rw-r--r--src/librustdoc/clean/mod.rs89
-rw-r--r--src/librustdoc/clean/simplify.rs10
-rw-r--r--src/librustdoc/clean/types.rs18
-rw-r--r--src/librustdoc/clean/utils.rs36
-rw-r--r--src/librustdoc/config.rs15
-rw-r--r--src/librustdoc/html/format.rs11
-rw-r--r--src/librustdoc/html/layout.rs25
-rw-r--r--src/librustdoc/html/render/context.rs26
-rw-r--r--src/librustdoc/html/render/print_item.rs8
-rw-r--r--src/librustdoc/html/render/write_shared.rs290
-rw-r--r--src/librustdoc/html/static/css/rustdoc.css61
-rw-r--r--src/librustdoc/html/static/css/themes/ayu.css28
-rw-r--r--src/librustdoc/html/static/css/themes/dark.css25
-rw-r--r--src/librustdoc/html/static/css/themes/light.css21
-rw-r--r--src/librustdoc/html/static/fonts/README.txt12
-rw-r--r--src/librustdoc/html/static/js/main.js10
-rw-r--r--src/librustdoc/html/static/js/settings.js10
-rw-r--r--src/librustdoc/html/static/js/storage.js24
-rw-r--r--src/librustdoc/html/static_files.rs259
-rw-r--r--src/librustdoc/html/templates/page.html56
-rw-r--r--src/librustdoc/html/templates/print_item.html2
-rw-r--r--src/librustdoc/json/conversions.rs2
-rw-r--r--src/librustdoc/lib.rs4
-rw-r--r--src/librustdoc/passes/collect_intra_doc_links.rs3
-rw-r--r--src/test/assembly/strict_provenance.rs37
-rw-r--r--src/test/codegen/auxiliary/static_dllimport_aux.rs13
-rw-r--r--src/test/codegen/avr/avr-func-addrspace.rs16
-rw-r--r--src/test/codegen/issue-81408-dllimport-thinlto-windows.rs15
-rw-r--r--src/test/debuginfo/basic-types.rs8
-rw-r--r--src/test/debuginfo/msvc-pretty-enums.rs6
-rw-r--r--src/test/debuginfo/msvc-scalarpair-params.rs4
-rw-r--r--src/test/debuginfo/pretty-std.rs4
-rw-r--r--src/test/debuginfo/rc_arc.rs8
-rw-r--r--src/test/debuginfo/result-types.rs6
-rw-r--r--src/test/debuginfo/type-names.rs10
-rw-r--r--src/test/debuginfo/unsized.rs12
-rw-r--r--src/test/incremental/hashes/extern_mods.rs4
-rw-r--r--src/test/mir-opt/building/custom/references.immut_ref.built.after.mir14
-rw-r--r--src/test/mir-opt/building/custom/references.mut_ref.built.after.mir14
-rw-r--r--src/test/mir-opt/building/custom/references.rs43
-rw-r--r--src/test/mir-opt/building/custom/simple_assign.rs37
-rw-r--r--src/test/mir-opt/building/custom/simple_assign.simple.built.after.mir18
-rw-r--r--src/test/mir-opt/building/custom/simple_assign.simple_ref.built.after.mir10
-rw-r--r--src/test/run-make/emit-shared-files/Makefile12
-rw-r--r--src/test/run-make/issue-88756-default-output/output-default.stdout4
-rw-r--r--src/test/run-make/valid-print-requests/valid-print-requests.stderr2
-rw-r--r--src/test/run-pass-valgrind/unsized-locals/by-value-trait-objects-rust-call.rs3
-rw-r--r--src/test/run-pass-valgrind/unsized-locals/by-value-trait-objects-rust-call2.rs3
-rw-r--r--src/test/rustdoc-gui/huge-logo.goml21
-rw-r--r--src/test/rustdoc-gui/run-on-hover.goml55
-rw-r--r--src/test/rustdoc-gui/rust-logo.goml9
-rw-r--r--src/test/rustdoc-gui/search-filter.goml2
-rw-r--r--src/test/rustdoc-gui/search-result-color.goml6
-rw-r--r--src/test/rustdoc-gui/sidebar-source-code.goml2
-rw-r--r--src/test/rustdoc-gui/source-code-page.goml2
-rw-r--r--src/test/rustdoc-gui/src/huge_logo/Cargo.lock7
-rw-r--r--src/test/rustdoc-gui/src/huge_logo/Cargo.toml8
-rw-r--r--src/test/rustdoc-gui/src/huge_logo/src/lib.rs17
-rw-r--r--src/test/rustdoc-ui/issue-103997.rs6
-rw-r--r--src/test/rustdoc-ui/issue-103997.stderr10
-rw-r--r--src/test/rustdoc/assoc-consts.rs1
-rw-r--r--src/test/rustdoc/inline_cross/assoc_item_trait_bounds.rs6
-rw-r--r--src/test/rustdoc/inline_cross/auxiliary/assoc_item_trait_bounds.rs2
-rw-r--r--src/test/rustdoc/inline_cross/auxiliary/dyn_trait.rs17
-rw-r--r--src/test/rustdoc/inline_cross/dyn_trait.rs31
-rw-r--r--src/test/rustdoc/inline_cross/impl_trait.rs2
-rw-r--r--src/test/rustdoc/issue-20727.rs2
-rw-r--r--src/test/rustdoc/static-root-path.rs12
-rw-r--r--src/test/ui/abi/homogenous-floats-target-feature-mixup.rs192
-rw-r--r--src/test/ui/abi/issues/issue-22565-rust-call.rs13
-rw-r--r--src/test/ui/abi/issues/issue-22565-rust-call.stderr33
-rw-r--r--src/test/ui/abi/rustcall-generic.rs4
-rw-r--r--src/test/ui/asm/issue-92378.rs2
-rw-r--r--src/test/ui/asm/naked-invalid-attr.stderr2
-rw-r--r--src/test/ui/attributes/key-value-non-ascii.rs2
-rw-r--r--src/test/ui/attributes/key-value-non-ascii.stderr4
-rw-r--r--src/test/ui/borrowck/borrow-immutable-upvar-mutation.rs6
-rw-r--r--src/test/ui/borrowck/borrow-immutable-upvar-mutation.stderr24
-rw-r--r--src/test/ui/borrowck/borrowck-borrowed-uniq-rvalue-2.stderr2
-rw-r--r--src/test/ui/borrowck/borrowck-borrowed-uniq-rvalue.stderr2
-rw-r--r--src/test/ui/borrowck/borrowck-move-by-capture.rs6
-rw-r--r--src/test/ui/borrowck/issue-11493.stderr2
-rw-r--r--src/test/ui/borrowck/issue-17545.stderr2
-rw-r--r--src/test/ui/borrowck/issue-36082.fixed2
-rw-r--r--src/test/ui/borrowck/issue-36082.rs2
-rw-r--r--src/test/ui/borrowck/issue-36082.stderr2
-rw-r--r--src/test/ui/c-variadic/issue-86053-1.stderr4
-rw-r--r--src/test/ui/cannot-mutate-captured-non-mut-var.rs4
-rw-r--r--src/test/ui/chalkify/closure.rs5
-rw-r--r--src/test/ui/chalkify/closure.stderr88
-rw-r--r--src/test/ui/chalkify/trait-objects.rs3
-rw-r--r--src/test/ui/chalkify/trait-objects.stderr28
-rw-r--r--src/test/ui/cleanup-rvalue-scopes-cf.stderr14
-rw-r--r--src/test/ui/closures/issue-78720.stderr4
-rw-r--r--src/test/ui/closures/supertrait-hint-references-assoc-ty.rs17
-rw-r--r--src/test/ui/conditional-compilation/cfg_accessible-not_sure.rs2
-rw-r--r--src/test/ui/consts/const-eval/const-eval-intrinsic-promotion.stderr2
-rw-r--r--src/test/ui/consts/const-eval/dont_promote_unstable_const_fn.stderr6
-rw-r--r--src/test/ui/consts/const-eval/dont_promote_unstable_const_fn_cross_crate.stderr4
-rw-r--r--src/test/ui/consts/const-eval/promoted_const_fn_fail.stderr2
-rw-r--r--src/test/ui/consts/const-eval/promoted_const_fn_fail_deny_const_err.stderr2
-rw-r--r--src/test/ui/consts/const-eval/promoted_raw_ptr_ops.stderr8
-rw-r--r--src/test/ui/consts/const-eval/transmute-const-promotion.stderr2
-rw-r--r--src/test/ui/consts/const-eval/union_promotion.stderr2
-rw-r--r--src/test/ui/consts/const-int-conversion.stderr14
-rw-r--r--src/test/ui/consts/const-int-overflowing.stderr6
-rw-r--r--src/test/ui/consts/const-int-rotate.stderr4
-rw-r--r--src/test/ui/consts/const-int-sign.stderr4
-rw-r--r--src/test/ui/consts/const-int-wrapping.stderr10
-rw-r--r--src/test/ui/consts/const-mut-refs/mut_ref_in_final.stderr10
-rw-r--r--src/test/ui/consts/const-ptr-nonnull.stderr4
-rw-r--r--src/test/ui/consts/const-ptr-unique.stderr2
-rw-r--r--src/test/ui/consts/control-flow/interior-mutability.stderr6
-rw-r--r--src/test/ui/consts/fn_trait_refs.rs77
-rw-r--r--src/test/ui/consts/issue-102117.rs4
-rw-r--r--src/test/ui/consts/issue-102117.stderr24
-rw-r--r--src/test/ui/consts/issue-104155.rs5
-rw-r--r--src/test/ui/consts/issue-54224.stderr4
-rw-r--r--src/test/ui/consts/issue-54954.rs (renamed from src/test/ui/issues/issue-54954.rs)0
-rw-r--r--src/test/ui/consts/issue-54954.stderr (renamed from src/test/ui/issues/issue-54954.stderr)0
-rw-r--r--src/test/ui/consts/min_const_fn/promotion.stderr12
-rw-r--r--src/test/ui/consts/promote-not.stderr40
-rw-r--r--src/test/ui/consts/promote_const_let.stderr2
-rw-r--r--src/test/ui/consts/promoted-const-drop.stderr4
-rw-r--r--src/test/ui/consts/qualif-union.stderr10
-rw-r--r--src/test/ui/did_you_mean/issue-103909.rs9
-rw-r--r--src/test/ui/did_you_mean/issue-103909.stderr26
-rw-r--r--src/test/ui/dropck/issue-54943-1.rs (renamed from src/test/ui/issues/issue-54943-1.rs)0
-rw-r--r--src/test/ui/dropck/issue-54943-2.rs (renamed from src/test/ui/issues/issue-54943-2.rs)0
-rw-r--r--src/test/ui/error-codes/E0059.stderr12
-rw-r--r--src/test/ui/error-codes/E0282.rs3
-rw-r--r--src/test/ui/error-codes/E0401.rs4
-rw-r--r--src/test/ui/error-codes/E0401.stderr27
-rw-r--r--src/test/ui/error-codes/E0778.rs8
-rw-r--r--src/test/ui/error-codes/E0778.stderr2
-rw-r--r--src/test/ui/error-codes/E0779.rs6
-rw-r--r--src/test/ui/error-codes/E0779.stderr2
-rw-r--r--src/test/ui/feature-gates/feature-gate-abi-efiapi.rs33
-rw-r--r--src/test/ui/feature-gates/feature-gate-abi-efiapi.stderr66
-rw-r--r--src/test/ui/feature-gates/feature-gate-abi.rs11
-rw-r--r--src/test/ui/feature-gates/feature-gate-abi.stderr117
-rw-r--r--src/test/ui/feature-gates/feature-gate-custom_mir.rs12
-rw-r--r--src/test/ui/feature-gates/feature-gate-custom_mir.stderr11
-rw-r--r--src/test/ui/feature-gates/feature-gate-isa_attribute.rs6
-rw-r--r--src/test/ui/feature-gates/feature-gate-isa_attribute.stderr25
-rw-r--r--src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr6
-rw-r--r--src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs2
-rw-r--r--src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr8
-rw-r--r--src/test/ui/fmt/unicode-escape-spans.rs19
-rw-r--r--src/test/ui/fmt/unicode-escape-spans.stderr63
-rw-r--r--src/test/ui/function-pointer/unsized-ret.rs3
-rw-r--r--src/test/ui/function-pointer/unsized-ret.stderr12
-rw-r--r--src/test/ui/generator/auto-trait-regions.stderr4
-rw-r--r--src/test/ui/generic-associated-types/bugs/hrtb-implied-1.stderr2
-rw-r--r--src/test/ui/generic-associated-types/bugs/issue-100013.rs39
-rw-r--r--src/test/ui/generic-associated-types/bugs/issue-100013.stderr82
-rw-r--r--src/test/ui/generic-associated-types/issue-91139.rs1
-rw-r--r--src/test/ui/generic-associated-types/issue-91139.stderr13
-rw-r--r--src/test/ui/impl-trait/cross-return-site-inference.rs9
-rw-r--r--src/test/ui/impl-trait/cross-return-site-inference.stderr4
-rw-r--r--src/test/ui/impl-trait/in-trait/generics-mismatch.rs17
-rw-r--r--src/test/ui/impl-trait/in-trait/generics-mismatch.stderr12
-rw-r--r--src/test/ui/impl-trait/in-trait/specialization-broken.rs26
-rw-r--r--src/test/ui/impl-trait/in-trait/specialization-broken.stderr23
-rw-r--r--src/test/ui/impl-trait/in-trait/specialization-substs-remap.rs24
-rw-r--r--src/test/ui/inference/cannot-infer-async.rs3
-rw-r--r--src/test/ui/inference/cannot-infer-closure.rs3
-rw-r--r--src/test/ui/inference/issue-103587.rs12
-rw-r--r--src/test/ui/inference/issue-103587.stderr40
-rw-r--r--src/test/ui/inference/issue-71732.rs3
-rw-r--r--src/test/ui/inference/issue-72616.rs5
-rw-r--r--src/test/ui/inference/issue-72616.stderr20
-rw-r--r--src/test/ui/inference/question-mark-type-infer.rs3
-rw-r--r--src/test/ui/issues/issue-12127.rs4
-rw-r--r--src/test/ui/issues/issue-23024.stderr2
-rw-r--r--src/test/ui/issues/issue-3707.stderr4
-rw-r--r--src/test/ui/issues/issue-47184.stderr2
-rw-r--r--src/test/ui/issues/issue-47511.stderr18
-rw-r--r--src/test/ui/issues/issue-52049.stderr2
-rw-r--r--src/test/ui/issues/issue-69396-const-no-type-in-macro.stderr5
-rw-r--r--src/test/ui/issues/issue-71584.rs3
-rw-r--r--src/test/ui/issues/issue-7607-1.stderr4
-rw-r--r--src/test/ui/iterators/collect-into-array.rs1
-rw-r--r--src/test/ui/iterators/collect-into-array.stderr2
-rw-r--r--src/test/ui/iterators/collect-into-slice.rs2
-rw-r--r--src/test/ui/iterators/collect-into-slice.stderr6
-rw-r--r--src/test/ui/lang-items/lang-item-missing-generator.rs6
-rw-r--r--src/test/ui/lang-items/lang-item-missing-generator.stderr11
-rw-r--r--src/test/ui/late-bound-lifetimes/auxiliary/upstream_alias.rs5
-rw-r--r--src/test/ui/late-bound-lifetimes/cross_crate_alias.rs10
-rw-r--r--src/test/ui/late-bound-lifetimes/downgraded_to_early_through_alias.rs24
-rw-r--r--src/test/ui/late-bound-lifetimes/issue-47511.rs (renamed from src/test/ui/issues/issue-47511.rs)7
-rw-r--r--src/test/ui/late-bound-lifetimes/late_bound_through_alias.rs16
-rw-r--r--src/test/ui/late-bound-lifetimes/mismatched_arg_count.rs12
-rw-r--r--src/test/ui/late-bound-lifetimes/mismatched_arg_count.stderr17
-rw-r--r--src/test/ui/lifetimes/borrowck-let-suggestion.stderr2
-rw-r--r--src/test/ui/match/issue-12552.rs (renamed from src/test/ui/issues/issue-12552.rs)0
-rw-r--r--src/test/ui/match/issue-12552.stderr (renamed from src/test/ui/issues/issue-12552.stderr)0
-rw-r--r--src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.rs4
-rw-r--r--src/test/ui/moves/moves-based-on-type-move-out-of-closure-env-issue-1965.rs4
-rw-r--r--src/test/ui/nll/borrowed-temporary-error.stderr2
-rw-r--r--src/test/ui/nll/closure-requirements/propagate-from-trait-match.rs3
-rw-r--r--src/test/ui/nll/closure-requirements/propagate-from-trait-match.stderr13
-rw-r--r--src/test/ui/nll/issue-54943.rs (renamed from src/test/ui/issues/issue-54943.rs)0
-rw-r--r--src/test/ui/nll/issue-54943.stderr (renamed from src/test/ui/issues/issue-54943.stderr)0
-rw-r--r--src/test/ui/nll/issue-57265-return-type-wf-check.stderr2
-rw-r--r--src/test/ui/nll/issue-98589-closures-relate-named-regions.stderr8
-rw-r--r--src/test/ui/nll/issue-98693.rs2
-rw-r--r--src/test/ui/nll/issue-98693.stderr9
-rw-r--r--src/test/ui/nll/ty-outlives/projection-implied-bounds.stderr4
-rw-r--r--src/test/ui/nll/ty-outlives/projection-no-regions-closure.stderr8
-rw-r--r--src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr8
-rw-r--r--src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr15
-rw-r--r--src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr4
-rw-r--r--src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.stderr4
-rw-r--r--src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.rs5
-rw-r--r--src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.stderr36
-rw-r--r--src/test/ui/nll/user-annotations/patterns.stderr6
-rw-r--r--src/test/ui/overloaded/overloaded-calls-nontuple.rs17
-rw-r--r--src/test/ui/overloaded/overloaded-calls-nontuple.stderr47
-rw-r--r--src/test/ui/parser/byte-literals.rs2
-rw-r--r--src/test/ui/parser/byte-literals.stderr4
-rw-r--r--src/test/ui/parser/byte-string-literals.rs4
-rw-r--r--src/test/ui/parser/byte-string-literals.stderr6
-rw-r--r--src/test/ui/parser/issue-102806.rs25
-rw-r--r--src/test/ui/parser/issue-102806.stderr45
-rw-r--r--src/test/ui/parser/issue-103451.rs5
-rw-r--r--src/test/ui/parser/issue-103451.stderr32
-rw-r--r--src/test/ui/parser/kw-in-trait-bounds.stderr16
-rw-r--r--src/test/ui/parser/label-after-block-like.rs43
-rw-r--r--src/test/ui/parser/label-after-block-like.stderr176
-rw-r--r--src/test/ui/parser/raw/raw-byte-string-literals.rs2
-rw-r--r--src/test/ui/parser/raw/raw-byte-string-literals.stderr2
-rw-r--r--src/test/ui/parser/underscore-suffix-for-string.rs17
-rw-r--r--src/test/ui/parser/underscore-suffix-for-string.stderr13
-rw-r--r--src/test/ui/parser/unicode-control-codepoints.rs16
-rw-r--r--src/test/ui/parser/unicode-control-codepoints.stderr24
-rw-r--r--src/test/ui/pin-macro/lifetime_errors_on_promotion_misusage.stderr4
-rw-r--r--src/test/ui/privacy/effective_visibilities.rs4
-rw-r--r--src/test/ui/privacy/effective_visibilities.stderr46
-rw-r--r--src/test/ui/privacy/effective_visibilities_glob.rs21
-rw-r--r--src/test/ui/privacy/effective_visibilities_glob.stderr26
-rw-r--r--src/test/ui/regions/regions-free-region-ordering-caller1.stderr2
-rw-r--r--src/test/ui/regions/regions-var-type-out-of-scope.stderr2
-rw-r--r--src/test/ui/span/borrowck-let-suggestion-suffixes.rs6
-rw-r--r--src/test/ui/span/borrowck-let-suggestion-suffixes.stderr6
-rw-r--r--src/test/ui/span/borrowck-ref-into-rvalue.stderr2
-rw-r--r--src/test/ui/span/issue-11925.rs4
-rw-r--r--src/test/ui/span/issue-15480.stderr2
-rw-r--r--src/test/ui/span/regions-close-over-borrowed-ref-in-obj.stderr2
-rw-r--r--src/test/ui/span/slice-borrow.stderr2
-rw-r--r--src/test/ui/static/static-drop-scope.stderr4
-rw-r--r--src/test/ui/static/static-reference-to-fn-2.stderr6
-rw-r--r--src/test/ui/static/static-region-bound.stderr2
-rw-r--r--src/test/ui/statics/issue-44373.stderr2
-rw-r--r--src/test/ui/suggestions/if-let-typo.stderr15
-rw-r--r--src/test/ui/suggestions/inner_type2.rs2
-rw-r--r--src/test/ui/suggestions/inner_type2.stderr2
-rw-r--r--src/test/ui/suggestions/issue-102354.stderr2
-rw-r--r--src/test/ui/suggestions/multibyte-escapes.rs12
-rw-r--r--src/test/ui/suggestions/multibyte-escapes.stderr12
-rw-r--r--src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish-placeholder.rs11
-rw-r--r--src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish-placeholder.stderr22
-rw-r--r--src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish-through-deref.stderr4
-rw-r--r--src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.fixed26
-rw-r--r--src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.rs19
-rw-r--r--src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.stderr88
-rw-r--r--src/test/ui/target-feature/tied-features-cli.one.stderr2
-rw-r--r--src/test/ui/target-feature/tied-features-cli.three.stderr2
-rw-r--r--src/test/ui/target-feature/tied-features-cli.two.stderr2
-rw-r--r--src/test/ui/traits/issue-77982.stderr7
-rw-r--r--src/test/ui/transmute/transmute-padding-ice.rs29
-rw-r--r--src/test/ui/transmute/transmute-padding-ice.stderr24
-rw-r--r--src/test/ui/typeck/issue-10969.rs (renamed from src/test/ui/issues/issue-10969.rs)0
-rw-r--r--src/test/ui/typeck/issue-10969.stderr (renamed from src/test/ui/issues/issue-10969.stderr)0
-rw-r--r--src/test/ui/typeck/issue-50687-ice-on-borrow.rs (renamed from src/test/ui/issues/issue-50687-ice-on-borrow.rs)0
-rw-r--r--src/test/ui/typeck/issue-50687-ice-on-borrow.stderr (renamed from src/test/ui/issues/issue-50687-ice-on-borrow.stderr)0
-rw-r--r--src/test/ui/typeck/issue-83693.stderr4
-rw-r--r--src/test/ui/unboxed-closures/non-tupled-arg-mismatch.rs2
-rw-r--r--src/test/ui/unboxed-closures/non-tupled-arg-mismatch.stderr20
-rw-r--r--src/test/ui/unboxed-closures/unboxed-closure-illegal-move.rs8
-rw-r--r--src/test/ui/unboxed-closures/unboxed-closures-mutate-upvar.rs6
-rw-r--r--src/test/ui/unboxed-closures/unboxed-closures-mutate-upvar.stderr4
-rw-r--r--src/test/ui/unboxed-closures/unboxed-closures-static-call-wrong-trait.rs4
-rw-r--r--src/test/ui/weird-exprs.rs11
-rw-r--r--src/tools/build-manifest/README.md32
-rw-r--r--src/tools/build-manifest/src/main.rs215
-rw-r--r--src/tools/build-manifest/src/manifest.rs5
-rw-r--r--src/tools/build-manifest/src/versions.rs140
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-6250.stderr5
-rw-r--r--src/tools/linkchecker/main.rs57
-rw-r--r--src/tools/miri/src/lib.rs1
-rw-r--r--src/tools/miri/tests/pass/integer-ops.rs1
-rw-r--r--src/tools/rust-analyzer/crates/syntax/src/validation.rs6
-rw-r--r--src/tools/rustdoc-js/tester.js7
-rw-r--r--src/tools/tidy/src/ui_tests.rs4
-rw-r--r--triagebot.toml1
575 files changed, 8434 insertions, 4434 deletions
diff --git a/Cargo.lock b/Cargo.lock
index f230f50212a..ddacf9cf024 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -4,42 +4,27 @@ version = 3
 
 [[package]]
 name = "addr2line"
-version = "0.16.0"
+version = "0.17.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3e61f2b7f93d2c7d2b08263acaa4a363b3e276806c68af6134c44f523bf1aacd"
+checksum = "b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b"
 dependencies = [
  "compiler_builtins",
- "gimli 0.25.0",
+ "gimli",
  "rustc-std-workspace-alloc",
  "rustc-std-workspace-core",
 ]
 
 [[package]]
-name = "addr2line"
-version = "0.17.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b"
-dependencies = [
- "gimli 0.26.1",
-]
-
-[[package]]
 name = "adler"
-version = "0.2.3"
+version = "1.0.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ee2a4ec343196209d6594e19543ae87a39f96d5534d7174822a3ad825dd6ed7e"
+checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
 dependencies = [
  "compiler_builtins",
  "rustc-std-workspace-core",
 ]
 
 [[package]]
-name = "adler"
-version = "1.0.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
-
-[[package]]
 name = "ahash"
 version = "0.7.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -185,12 +170,12 @@ version = "0.3.66"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "cab84319d616cfb654d03394f38ab7e6f0919e181b1b57e1fd15e7fb4077d9a7"
 dependencies = [
- "addr2line 0.17.0",
+ "addr2line",
  "cc",
  "cfg-if 1.0.0",
  "libc",
- "miniz_oxide 0.5.3",
- "object 0.29.0",
+ "miniz_oxide",
+ "object",
  "rustc-demangle",
 ]
 
@@ -1295,15 +1280,15 @@ checksum = "37ab347416e802de484e4d03c7316c48f1ecb56574dfd4a46a80f173ce1de04d"
 
 [[package]]
 name = "flate2"
-version = "1.0.16"
+version = "1.0.23"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "68c90b0fc46cf89d227cc78b40e494ff81287a92dd07631e5af0d06fe3cf885e"
+checksum = "b39522e96686d38f4bc984b9198e3a0613264abaebaff2c5c918bfa6b6da09af"
 dependencies = [
- "cfg-if 0.1.10",
+ "cfg-if 1.0.0",
  "crc32fast",
  "libc",
  "libz-sys",
- "miniz_oxide 0.4.0",
+ "miniz_oxide",
 ]
 
 [[package]]
@@ -1547,23 +1532,15 @@ dependencies = [
 
 [[package]]
 name = "gimli"
-version = "0.25.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f0a01e0497841a3b2db4f8afa483cce65f7e96a3498bd6c541734792aeac8fe7"
-dependencies = [
- "compiler_builtins",
- "rustc-std-workspace-alloc",
- "rustc-std-workspace-core",
-]
-
-[[package]]
-name = "gimli"
 version = "0.26.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "78cc372d058dcf6d5ecd98510e7fbc9e5aec4d21de70f65fea8fecebcd881bd4"
 dependencies = [
+ "compiler_builtins",
  "fallible-iterator",
  "indexmap",
+ "rustc-std-workspace-alloc",
+ "rustc-std-workspace-core",
  "stable_deref_trait",
 ]
 
@@ -2228,26 +2205,17 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
 
 [[package]]
 name = "miniz_oxide"
-version = "0.4.0"
+version = "0.5.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "be0f75932c1f6cfae3c04000e40114adf955636e19040f9c0a2c380702aa1c7f"
+checksum = "6f5c75688da582b8ffc1f1799e9db273f32133c49e048f614d22ec3256773ccc"
 dependencies = [
- "adler 0.2.3",
+ "adler",
  "compiler_builtins",
  "rustc-std-workspace-alloc",
  "rustc-std-workspace-core",
 ]
 
 [[package]]
-name = "miniz_oxide"
-version = "0.5.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6f5c75688da582b8ffc1f1799e9db273f32133c49e048f614d22ec3256773ccc"
-dependencies = [
- "adler 1.0.2",
-]
-
-[[package]]
 name = "miow"
 version = "0.3.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2348,27 +2316,18 @@ dependencies = [
 
 [[package]]
 name = "object"
-version = "0.26.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "39f37e50073ccad23b6d09bcb5b263f4e76d3bb6038e4a3c08e52162ffa8abc2"
-dependencies = [
- "compiler_builtins",
- "memchr",
- "rustc-std-workspace-alloc",
- "rustc-std-workspace-core",
-]
-
-[[package]]
-name = "object"
 version = "0.29.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "21158b2c33aa6d4561f1c0a6ea283ca92bc54802a93b263e910746d679a7eb53"
 dependencies = [
+ "compiler_builtins",
  "crc32fast",
  "flate2",
  "hashbrown",
  "indexmap",
  "memchr",
+ "rustc-std-workspace-alloc",
+ "rustc-std-workspace-core",
 ]
 
 [[package]]
@@ -2522,7 +2481,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f"
 dependencies = [
  "lock_api",
- "parking_lot_core 0.9.3",
+ "parking_lot_core 0.9.4",
 ]
 
 [[package]]
@@ -2541,15 +2500,15 @@ dependencies = [
 
 [[package]]
 name = "parking_lot_core"
-version = "0.9.3"
+version = "0.9.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "09a279cbf25cb0757810394fbc1e359949b59e348145c643a939a525692e6929"
+checksum = "4dc9e0dc2adc1c69d09143aff38d3d30c5c3f0df0dad82e6d25547af174ebec0"
 dependencies = [
  "cfg-if 1.0.0",
  "libc",
  "redox_syscall",
  "smallvec",
- "windows-sys 0.36.1",
+ "windows-sys 0.42.0",
 ]
 
 [[package]]
@@ -2774,9 +2733,9 @@ dependencies = [
 
 [[package]]
 name = "psm"
-version = "0.1.16"
+version = "0.1.21"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cd136ff4382c4753fc061cb9e4712ab2af263376b95bbd5bd8cd50c020b78e69"
+checksum = "5787f7cda34e3033a72192c018bc5883100330f362ef279a8cbccfce8bb4e874"
 dependencies = [
  "cc",
 ]
@@ -3305,7 +3264,7 @@ dependencies = [
  "cstr",
  "libc",
  "measureme",
- "object 0.29.0",
+ "object",
  "rustc-demangle",
  "rustc_ast",
  "rustc_attr",
@@ -3339,7 +3298,7 @@ dependencies = [
  "itertools",
  "jobserver",
  "libc",
- "object 0.29.0",
+ "object",
  "pathdiff",
  "regex",
  "rustc_arena",
@@ -4677,9 +4636,9 @@ checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
 
 [[package]]
 name = "stacker"
-version = "0.1.14"
+version = "0.1.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "90939d5171a4420b3ff5fbc8954d641e7377335454c259dcb80786f3f21dc9b4"
+checksum = "c886bd4480155fd3ef527d45e9ac8dd7118a898a46530b7b94c3e21866259fce"
 dependencies = [
  "cc",
  "cfg-if 1.0.0",
@@ -4698,7 +4657,7 @@ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
 name = "std"
 version = "0.0.0"
 dependencies = [
- "addr2line 0.16.0",
+ "addr2line",
  "alloc",
  "cfg-if 1.0.0",
  "compiler_builtins",
@@ -4708,8 +4667,8 @@ dependencies = [
  "hashbrown",
  "hermit-abi 0.2.6",
  "libc",
- "miniz_oxide 0.4.0",
- "object 0.26.2",
+ "miniz_oxide",
+ "object",
  "panic_abort",
  "panic_unwind",
  "profiler_builtins",
@@ -4926,9 +4885,9 @@ version = "0.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "e6cb0c7868d7f90407531108ab03263d9452a8811b7cdd87675343a40d4aa254"
 dependencies = [
- "gimli 0.26.1",
+ "gimli",
  "hashbrown",
- "object 0.29.0",
+ "object",
  "tracing",
 ]
 
@@ -5499,18 +5458,26 @@ dependencies = [
 
 [[package]]
 name = "windows-sys"
-version = "0.36.1"
+version = "0.42.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2"
+checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7"
 dependencies = [
- "windows_aarch64_msvc 0.36.1",
- "windows_i686_gnu 0.36.1",
- "windows_i686_msvc 0.36.1",
- "windows_x86_64_gnu 0.36.1",
- "windows_x86_64_msvc 0.36.1",
+ "windows_aarch64_gnullvm",
+ "windows_aarch64_msvc 0.42.0",
+ "windows_i686_gnu 0.42.0",
+ "windows_i686_msvc 0.42.0",
+ "windows_x86_64_gnu 0.42.0",
+ "windows_x86_64_gnullvm",
+ "windows_x86_64_msvc 0.42.0",
 ]
 
 [[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.42.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e"
+
+[[package]]
 name = "windows_aarch64_msvc"
 version = "0.28.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -5518,9 +5485,9 @@ checksum = "52695a41e536859d5308cc613b4a022261a274390b25bd29dfff4bf08505f3c2"
 
 [[package]]
 name = "windows_aarch64_msvc"
-version = "0.36.1"
+version = "0.42.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47"
+checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4"
 
 [[package]]
 name = "windows_i686_gnu"
@@ -5530,9 +5497,9 @@ checksum = "f54725ac23affef038fecb177de6c9bf065787c2f432f79e3c373da92f3e1d8a"
 
 [[package]]
 name = "windows_i686_gnu"
-version = "0.36.1"
+version = "0.42.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6"
+checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7"
 
 [[package]]
 name = "windows_i686_msvc"
@@ -5542,9 +5509,9 @@ checksum = "51d5158a43cc43623c0729d1ad6647e62fa384a3d135fd15108d37c683461f64"
 
 [[package]]
 name = "windows_i686_msvc"
-version = "0.36.1"
+version = "0.42.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024"
+checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246"
 
 [[package]]
 name = "windows_x86_64_gnu"
@@ -5554,9 +5521,15 @@ checksum = "bc31f409f565611535130cfe7ee8e6655d3fa99c1c61013981e491921b5ce954"
 
 [[package]]
 name = "windows_x86_64_gnu"
-version = "0.36.1"
+version = "0.42.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.42.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1"
+checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028"
 
 [[package]]
 name = "windows_x86_64_msvc"
@@ -5566,9 +5539,9 @@ checksum = "3f2b8c7cbd3bfdddd9ab98769f9746a7fad1bca236554cd032b78d768bc0e89f"
 
 [[package]]
 name = "windows_x86_64_msvc"
-version = "0.36.1"
+version = "0.42.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680"
+checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5"
 
 [[package]]
 name = "xattr"
diff --git a/compiler/rustc_ast/src/util/literal.rs b/compiler/rustc_ast/src/util/literal.rs
index 536b385606c..8f342175f7d 100644
--- a/compiler/rustc_ast/src/util/literal.rs
+++ b/compiler/rustc_ast/src/util/literal.rs
@@ -2,12 +2,9 @@
 
 use crate::ast::{self, Lit, LitKind};
 use crate::token::{self, Token};
-
-use rustc_lexer::unescape::{unescape_byte, unescape_char};
-use rustc_lexer::unescape::{unescape_byte_literal, unescape_literal, Mode};
+use rustc_lexer::unescape::{byte_from_char, unescape_byte, unescape_char, unescape_literal, Mode};
 use rustc_span::symbol::{kw, sym, Symbol};
 use rustc_span::Span;
-
 use std::ascii;
 
 pub enum LitError {
@@ -109,13 +106,11 @@ impl LitKind {
                 let s = symbol.as_str();
                 let mut buf = Vec::with_capacity(s.len());
                 let mut error = Ok(());
-                unescape_byte_literal(&s, Mode::ByteStr, &mut |_, unescaped_byte| {
-                    match unescaped_byte {
-                        Ok(c) => buf.push(c),
-                        Err(err) => {
-                            if err.is_fatal() {
-                                error = Err(LitError::LexerError);
-                            }
+                unescape_literal(&s, Mode::ByteStr, &mut |_, c| match c {
+                    Ok(c) => buf.push(byte_from_char(c)),
+                    Err(err) => {
+                        if err.is_fatal() {
+                            error = Err(LitError::LexerError);
                         }
                     }
                 });
@@ -127,13 +122,11 @@ impl LitKind {
                 let bytes = if s.contains('\r') {
                     let mut buf = Vec::with_capacity(s.len());
                     let mut error = Ok(());
-                    unescape_byte_literal(&s, Mode::RawByteStr, &mut |_, unescaped_byte| {
-                        match unescaped_byte {
-                            Ok(c) => buf.push(c),
-                            Err(err) => {
-                                if err.is_fatal() {
-                                    error = Err(LitError::LexerError);
-                                }
+                    unescape_literal(&s, Mode::RawByteStr, &mut |_, c| match c {
+                        Ok(c) => buf.push(byte_from_char(c)),
+                        Err(err) => {
+                            if err.is_fatal() {
+                                error = Err(LitError::LexerError);
                             }
                         }
                     });
diff --git a/compiler/rustc_borrowck/src/constraints/graph.rs b/compiler/rustc_borrowck/src/constraints/graph.rs
index 609fbc2bc15..385f153174c 100644
--- a/compiler/rustc_borrowck/src/constraints/graph.rs
+++ b/compiler/rustc_borrowck/src/constraints/graph.rs
@@ -163,6 +163,7 @@ impl<'s, 'tcx, D: ConstraintGraphDirecton> Iterator for Edges<'s, 'tcx, D> {
                 span: DUMMY_SP,
                 category: ConstraintCategory::Internal,
                 variance_info: VarianceDiagInfo::default(),
+                from_closure: false,
             })
         } else {
             None
diff --git a/compiler/rustc_borrowck/src/constraints/mod.rs b/compiler/rustc_borrowck/src/constraints/mod.rs
index df04128135b..9d9c4abb0aa 100644
--- a/compiler/rustc_borrowck/src/constraints/mod.rs
+++ b/compiler/rustc_borrowck/src/constraints/mod.rs
@@ -96,6 +96,9 @@ pub struct OutlivesConstraint<'tcx> {
 
     /// Variance diagnostic information
     pub variance_info: VarianceDiagInfo<'tcx>,
+
+    /// If this constraint is promoted from closure requirements.
+    pub from_closure: bool,
 }
 
 impl<'tcx> fmt::Debug for OutlivesConstraint<'tcx> {
diff --git a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs
index dac6abe37f5..897a161f785 100644
--- a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs
@@ -158,6 +158,7 @@ trait TypeOpInfo<'tcx> {
         error_region: Option<ty::Region<'tcx>>,
     ) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>>;
 
+    #[instrument(level = "debug", skip(self, mbcx))]
     fn report_error(
         &self,
         mbcx: &mut MirBorrowckCtxt<'_, 'tcx>,
@@ -167,6 +168,7 @@ trait TypeOpInfo<'tcx> {
     ) {
         let tcx = mbcx.infcx.tcx;
         let base_universe = self.base_universe();
+        debug!(?base_universe);
 
         let Some(adjusted_universe) =
             placeholder.universe.as_u32().checked_sub(base_universe.as_u32())
@@ -389,6 +391,7 @@ fn try_extract_error_from_fulfill_cx<'tcx>(
     )
 }
 
+#[instrument(level = "debug", skip(infcx, region_var_origin, universe_of_region))]
 fn try_extract_error_from_region_constraints<'tcx>(
     infcx: &InferCtxt<'tcx>,
     placeholder_region: ty::Region<'tcx>,
diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index 8987a51757c..86cae5d09b5 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -724,13 +724,19 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             borrow_span,
             &self.describe_any_place(borrow.borrowed_place.as_ref()),
         );
-
-        borrow_spans.var_span_label(
+        borrow_spans.var_subdiag(
             &mut err,
-            {
+            |var_span| {
+                use crate::session_diagnostics::CaptureVarCause::*;
                 let place = &borrow.borrowed_place;
                 let desc_place = self.describe_any_place(place.as_ref());
-                format!("borrow occurs due to use of {}{}", desc_place, borrow_spans.describe())
+                match borrow_spans {
+                    UseSpans::ClosureUse { generator_kind, .. } => match generator_kind {
+                        Some(_) => BorrowUsePlaceGenerator { place: desc_place, var_span },
+                        None => BorrowUsePlaceClosure { place: desc_place, var_span },
+                    },
+                    _ => BorrowUsePlace { place: desc_place, var_span },
+                }
             },
             "mutable",
         );
@@ -1551,7 +1557,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         }
 
         let mut err = self.temporary_value_borrowed_for_too_long(proper_span);
-        err.span_label(proper_span, "creates a temporary which is freed while still in use");
+        err.span_label(proper_span, "creates a temporary value which is freed while still in use");
         err.span_label(drop_span, "temporary value is freed at the end of this statement");
 
         match explanation {
diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs
index 534d9ecae6e..61518378e3d 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mod.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs
@@ -623,6 +623,26 @@ impl UseSpans<'_> {
         }
     }
 
+    /// Add a subdiagnostic to the use of the captured variable, if it exists.
+    pub(super) fn var_subdiag(
+        self,
+        err: &mut Diagnostic,
+        f: impl Fn(Span) -> crate::session_diagnostics::CaptureVarCause,
+        kind_desc: impl Into<String>,
+    ) {
+        if let UseSpans::ClosureUse { capture_kind_span, path_span, .. } = self {
+            if capture_kind_span == path_span {
+                err.subdiagnostic(f(capture_kind_span));
+            } else {
+                err.subdiagnostic(crate::session_diagnostics::CaptureVarKind {
+                    kind_desc: kind_desc.into(),
+                    kind_span: capture_kind_span,
+                });
+                err.subdiagnostic(f(path_span));
+            }
+        }
+    }
+
     /// Returns `false` if this place is not used in a closure.
     pub(super) fn for_closure(&self) -> bool {
         match *self {
diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
index 15230718dc0..76f249dac51 100644
--- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
@@ -2,7 +2,7 @@
 #![deny(rustc::diagnostic_outside_of_impl)]
 //! Error reporting machinery for lifetime errors.
 
-use rustc_data_structures::fx::FxHashSet;
+use rustc_data_structures::fx::FxIndexSet;
 use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, MultiSpan};
 use rustc_hir::def_id::DefId;
 use rustc_hir::intravisit::Visitor;
@@ -181,7 +181,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
                     // Try to convert the lower-bound region into something named we can print for the user.
                     let lower_bound_region = self.to_error_region(type_test.lower_bound);
 
-                    let type_test_span = type_test.locations.span(&self.body);
+                    let type_test_span = type_test.span;
 
                     if let Some(lower_bound_region) = lower_bound_region {
                         let generic_ty = type_test.generic_kind.to_ty(self.infcx.tcx);
@@ -276,7 +276,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
     fn get_impl_ident_and_self_ty_from_trait(
         &self,
         def_id: DefId,
-        trait_objects: &FxHashSet<DefId>,
+        trait_objects: &FxIndexSet<DefId>,
     ) -> Option<(Ident, &'tcx hir::Ty<'tcx>)> {
         let tcx = self.infcx.tcx;
         match tcx.hir().get_if_local(def_id) {
@@ -830,7 +830,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
         };
         debug!(?param);
 
-        let mut visitor = TraitObjectVisitor(FxHashSet::default());
+        let mut visitor = TraitObjectVisitor(FxIndexSet::default());
         visitor.visit_ty(param.param_ty);
 
         let Some((ident, self_ty)) =
@@ -843,7 +843,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
     fn suggest_constrain_dyn_trait_in_impl(
         &self,
         err: &mut Diagnostic,
-        found_dids: &FxHashSet<DefId>,
+        found_dids: &FxIndexSet<DefId>,
         ident: Ident,
         self_ty: &hir::Ty<'_>,
     ) -> bool {
diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs
index c044dbaba47..f9741bacd17 100644
--- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs
@@ -355,7 +355,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
                     })
                 }
 
-                ty::BoundRegionKind::BrAnon(_) => None,
+                ty::BoundRegionKind::BrAnon(..) => None,
             },
 
             ty::ReLateBound(..) | ty::ReVar(..) | ty::RePlaceholder(..) | ty::ReErased => None,
diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs
index abfe253d43d..4a4887f1970 100644
--- a/compiler/rustc_borrowck/src/lib.rs
+++ b/compiler/rustc_borrowck/src/lib.rs
@@ -18,6 +18,7 @@ extern crate tracing;
 
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::graph::dominators::Dominators;
+use rustc_data_structures::vec_map::VecMap;
 use rustc_errors::{Diagnostic, DiagnosticBuilder, ErrorGuaranteed};
 use rustc_hir as hir;
 use rustc_hir::def_id::LocalDefId;
@@ -129,6 +130,19 @@ fn mir_borrowck<'tcx>(
 ) -> &'tcx BorrowCheckResult<'tcx> {
     let (input_body, promoted) = tcx.mir_promoted(def);
     debug!("run query mir_borrowck: {}", tcx.def_path_str(def.did.to_def_id()));
+
+    if input_body.borrow().should_skip() {
+        debug!("Skipping borrowck because of injected body");
+        // Let's make up a borrowck result! Fun times!
+        let result = BorrowCheckResult {
+            concrete_opaque_types: VecMap::new(),
+            closure_requirements: None,
+            used_mut_upvars: SmallVec::new(),
+            tainted_by_errors: None,
+        };
+        return tcx.arena.alloc(result);
+    }
+
     let hir_owner = tcx.hir().local_def_id_to_hir_id(def.did).owner;
 
     let infcx =
diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs
index 08fdd28eb01..4e0205f8d43 100644
--- a/compiler/rustc_borrowck/src/nll.rs
+++ b/compiler/rustc_borrowck/src/nll.rs
@@ -242,7 +242,6 @@ pub(crate) fn compute_regions<'cx, 'tcx>(
         mut liveness_constraints,
         outlives_constraints,
         member_constraints,
-        closure_bounds_mapping,
         universe_causes,
         type_tests,
     } = constraints;
@@ -264,7 +263,6 @@ pub(crate) fn compute_regions<'cx, 'tcx>(
         universal_region_relations,
         outlives_constraints,
         member_constraints,
-        closure_bounds_mapping,
         universe_causes,
         type_tests,
         liveness_constraints,
diff --git a/compiler/rustc_borrowck/src/region_infer/dump_mir.rs b/compiler/rustc_borrowck/src/region_infer/dump_mir.rs
index fe5193102f9..cc945099952 100644
--- a/compiler/rustc_borrowck/src/region_infer/dump_mir.rs
+++ b/compiler/rustc_borrowck/src/region_infer/dump_mir.rs
@@ -74,8 +74,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         let mut constraints: Vec<_> = self.constraints.outlives().iter().collect();
         constraints.sort_by_key(|c| (c.sup, c.sub));
         for constraint in &constraints {
-            let OutlivesConstraint { sup, sub, locations, category, span, variance_info: _ } =
-                constraint;
+            let OutlivesConstraint { sup, sub, locations, category, span, .. } = constraint;
             let (name, arg) = match locations {
                 Locations::All(span) => {
                     ("All", tcx.sess.source_map().span_to_embeddable_string(*span))
diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs
index 0e7f243bcf3..94e9e05e5d6 100644
--- a/compiler/rustc_borrowck/src/region_infer/mod.rs
+++ b/compiler/rustc_borrowck/src/region_infer/mod.rs
@@ -6,10 +6,9 @@ use rustc_data_structures::frozen::Frozen;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::graph::scc::Sccs;
 use rustc_errors::Diagnostic;
-use rustc_hir::def_id::{DefId, CRATE_DEF_ID};
+use rustc_hir::def_id::CRATE_DEF_ID;
 use rustc_hir::CRATE_HIR_ID;
 use rustc_index::vec::IndexVec;
-use rustc_infer::infer::canonical::QueryOutlivesConstraint;
 use rustc_infer::infer::outlives::test_type_match;
 use rustc_infer::infer::region_constraints::{GenericKind, VarInfos, VerifyBound, VerifyIfEq};
 use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin, RegionVariableOrigin};
@@ -19,9 +18,7 @@ use rustc_middle::mir::{
 };
 use rustc_middle::traits::ObligationCause;
 use rustc_middle::traits::ObligationCauseCode;
-use rustc_middle::ty::{
-    self, subst::SubstsRef, RegionVid, Ty, TyCtxt, TypeFoldable, TypeVisitable,
-};
+use rustc_middle::ty::{self, RegionVid, Ty, TyCtxt, TypeFoldable, TypeVisitable};
 use rustc_span::Span;
 
 use crate::{
@@ -89,10 +86,6 @@ pub struct RegionInferenceContext<'tcx> {
     /// `member_region_scc`.
     member_constraints_applied: Vec<AppliedMemberConstraint>,
 
-    /// Map closure bounds to a `Span` that should be used for error reporting.
-    closure_bounds_mapping:
-        FxHashMap<Location, FxHashMap<(RegionVid, RegionVid), (ConstraintCategory<'tcx>, Span)>>,
-
     /// Map universe indexes to information on why we created it.
     universe_causes: FxHashMap<ty::UniverseIndex, UniverseInfo<'tcx>>,
 
@@ -221,8 +214,8 @@ pub struct TypeTest<'tcx> {
     /// The region `'x` that the type must outlive.
     pub lower_bound: RegionVid,
 
-    /// Where did this constraint arise and why?
-    pub locations: Locations,
+    /// The span to blame.
+    pub span: Span,
 
     /// A test which, if met by the region `'x`, proves that this type
     /// constraint is satisfied.
@@ -265,10 +258,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         universal_region_relations: Frozen<UniversalRegionRelations<'tcx>>,
         outlives_constraints: OutlivesConstraintSet<'tcx>,
         member_constraints_in: MemberConstraintSet<'tcx, RegionVid>,
-        closure_bounds_mapping: FxHashMap<
-            Location,
-            FxHashMap<(RegionVid, RegionVid), (ConstraintCategory<'tcx>, Span)>,
-        >,
         universe_causes: FxHashMap<ty::UniverseIndex, UniverseInfo<'tcx>>,
         type_tests: Vec<TypeTest<'tcx>>,
         liveness_constraints: LivenessValues<RegionVid>,
@@ -310,7 +299,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
             rev_scc_graph: None,
             member_constraints,
             member_constraints_applied: Vec::new(),
-            closure_bounds_mapping,
             universe_causes,
             scc_universes,
             scc_representatives,
@@ -882,13 +870,13 @@ impl<'tcx> RegionInferenceContext<'tcx> {
             if deduplicate_errors.insert((
                 erased_generic_kind,
                 type_test.lower_bound,
-                type_test.locations,
+                type_test.span,
             )) {
                 debug!(
                     "check_type_test: reporting error for erased_generic_kind={:?}, \
                      lower_bound_region={:?}, \
-                     type_test.locations={:?}",
-                    erased_generic_kind, type_test.lower_bound, type_test.locations,
+                     type_test.span={:?}",
+                    erased_generic_kind, type_test.lower_bound, type_test.span,
                 );
 
                 errors_buffer.push(RegionErrorKind::TypeTestError { type_test: type_test.clone() });
@@ -931,7 +919,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     ) -> bool {
         let tcx = infcx.tcx;
 
-        let TypeTest { generic_kind, lower_bound, locations, verify_bound: _ } = type_test;
+        let TypeTest { generic_kind, lower_bound, span: _, verify_bound: _ } = type_test;
 
         let generic_ty = generic_kind.to_ty(tcx);
         let Some(subject) = self.try_promote_type_test_subject(infcx, generic_ty) else {
@@ -959,7 +947,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
             propagated_outlives_requirements.push(ClosureOutlivesRequirement {
                 subject,
                 outlived_free_region: static_r,
-                blame_span: locations.span(body),
+                blame_span: type_test.span,
                 category: ConstraintCategory::Boring,
             });
 
@@ -1011,7 +999,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
                 let requirement = ClosureOutlivesRequirement {
                     subject,
                     outlived_free_region: upper_bound,
-                    blame_span: locations.span(body),
+                    blame_span: type_test.span,
                     category: ConstraintCategory::Boring,
                 };
                 debug!("try_promote_type_test: pushing {:#?}", requirement);
@@ -1804,18 +1792,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         }
     }
 
-    pub(crate) fn retrieve_closure_constraint_info(
-        &self,
-        constraint: OutlivesConstraint<'tcx>,
-    ) -> Option<(ConstraintCategory<'tcx>, Span)> {
-        match constraint.locations {
-            Locations::All(_) => None,
-            Locations::Single(loc) => {
-                self.closure_bounds_mapping[&loc].get(&(constraint.sup, constraint.sub)).copied()
-            }
-        }
-    }
-
     /// Finds a good `ObligationCause` to blame for the fact that `fr1` outlives `fr2`.
     pub(crate) fn find_outlives_blame_span(
         &self,
@@ -1921,6 +1897,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
                     span: p_c.definition_span,
                     category: ConstraintCategory::OpaqueType,
                     variance_info: ty::VarianceDiagInfo::default(),
+                    from_closure: false,
                 };
                 handle_constraint(constraint);
             }
@@ -2066,31 +2043,12 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         // Classify each of the constraints along the path.
         let mut categorized_path: Vec<BlameConstraint<'tcx>> = path
             .iter()
-            .map(|constraint| {
-                let (category, span, from_closure, cause_code) =
-                    if constraint.category == ConstraintCategory::ClosureBounds {
-                        if let Some((category, span)) =
-                            self.retrieve_closure_constraint_info(*constraint)
-                        {
-                            (category, span, true, ObligationCauseCode::MiscObligation)
-                        } else {
-                            (
-                                constraint.category,
-                                constraint.span,
-                                false,
-                                ObligationCauseCode::MiscObligation,
-                            )
-                        }
-                    } else {
-                        (constraint.category, constraint.span, false, cause_code.clone())
-                    };
-                BlameConstraint {
-                    category,
-                    from_closure,
-                    cause: ObligationCause::new(span, CRATE_HIR_ID, cause_code),
-                    variance_info: constraint.variance_info,
-                    outlives_constraint: *constraint,
-                }
+            .map(|constraint| BlameConstraint {
+                category: constraint.category,
+                from_closure: constraint.from_closure,
+                cause: ObligationCause::new(constraint.span, CRATE_HIR_ID, cause_code.clone()),
+                variance_info: constraint.variance_info,
+                outlives_constraint: *constraint,
             })
             .collect();
         debug!("categorized_path={:#?}", categorized_path);
@@ -2274,92 +2232,6 @@ impl<'tcx> RegionDefinition<'tcx> {
     }
 }
 
-pub trait ClosureRegionRequirementsExt<'tcx> {
-    fn apply_requirements(
-        &self,
-        tcx: TyCtxt<'tcx>,
-        closure_def_id: DefId,
-        closure_substs: SubstsRef<'tcx>,
-    ) -> Vec<QueryOutlivesConstraint<'tcx>>;
-}
-
-impl<'tcx> ClosureRegionRequirementsExt<'tcx> for ClosureRegionRequirements<'tcx> {
-    /// Given an instance T of the closure type, this method
-    /// instantiates the "extra" requirements that we computed for the
-    /// closure into the inference context. This has the effect of
-    /// adding new outlives obligations to existing variables.
-    ///
-    /// As described on `ClosureRegionRequirements`, the extra
-    /// requirements are expressed in terms of regionvids that index
-    /// into the free regions that appear on the closure type. So, to
-    /// do this, we first copy those regions out from the type T into
-    /// a vector. Then we can just index into that vector to extract
-    /// out the corresponding region from T and apply the
-    /// requirements.
-    fn apply_requirements(
-        &self,
-        tcx: TyCtxt<'tcx>,
-        closure_def_id: DefId,
-        closure_substs: SubstsRef<'tcx>,
-    ) -> Vec<QueryOutlivesConstraint<'tcx>> {
-        debug!(
-            "apply_requirements(closure_def_id={:?}, closure_substs={:?})",
-            closure_def_id, closure_substs
-        );
-
-        // Extract the values of the free regions in `closure_substs`
-        // into a vector.  These are the regions that we will be
-        // relating to one another.
-        let closure_mapping = &UniversalRegions::closure_mapping(
-            tcx,
-            closure_substs,
-            self.num_external_vids,
-            closure_def_id.expect_local(),
-        );
-        debug!("apply_requirements: closure_mapping={:?}", closure_mapping);
-
-        // Create the predicates.
-        self.outlives_requirements
-            .iter()
-            .map(|outlives_requirement| {
-                let outlived_region = closure_mapping[outlives_requirement.outlived_free_region];
-
-                match outlives_requirement.subject {
-                    ClosureOutlivesSubject::Region(region) => {
-                        let region = closure_mapping[region];
-                        debug!(
-                            "apply_requirements: region={:?} \
-                             outlived_region={:?} \
-                             outlives_requirement={:?}",
-                            region, outlived_region, outlives_requirement,
-                        );
-                        (
-                            ty::Binder::dummy(ty::OutlivesPredicate(
-                                region.into(),
-                                outlived_region,
-                            )),
-                            ConstraintCategory::BoringNoLocation,
-                        )
-                    }
-
-                    ClosureOutlivesSubject::Ty(ty) => {
-                        debug!(
-                            "apply_requirements: ty={:?} \
-                             outlived_region={:?} \
-                             outlives_requirement={:?}",
-                            ty, outlived_region, outlives_requirement,
-                        );
-                        (
-                            ty::Binder::dummy(ty::OutlivesPredicate(ty.into(), outlived_region)),
-                            ConstraintCategory::BoringNoLocation,
-                        )
-                    }
-                }
-            })
-            .collect()
-    }
-}
-
 #[derive(Clone, Debug)]
 pub struct BlameConstraint<'tcx> {
     pub category: ConstraintCategory<'tcx>,
diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
index 95ea42b584a..dd222485daf 100644
--- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
+++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
@@ -299,8 +299,8 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
         if errors.is_empty() {
             definition_ty
         } else {
-            infcx.err_ctxt().report_fulfillment_errors(&errors, None, false);
-            self.tcx.ty_error()
+            let reported = infcx.err_ctxt().report_fulfillment_errors(&errors, None);
+            self.tcx.ty_error_with_guaranteed(reported)
         }
     }
 }
diff --git a/compiler/rustc_borrowck/src/session_diagnostics.rs b/compiler/rustc_borrowck/src/session_diagnostics.rs
index fe24f85fae1..824f20a31bb 100644
--- a/compiler/rustc_borrowck/src/session_diagnostics.rs
+++ b/compiler/rustc_borrowck/src/session_diagnostics.rs
@@ -148,3 +148,33 @@ pub(crate) enum RequireStaticErr {
         multi_span: MultiSpan,
     },
 }
+
+#[derive(Subdiagnostic)]
+#[label(borrowck_capture_kind_label)]
+pub(crate) struct CaptureVarKind {
+    pub kind_desc: String,
+    #[primary_span]
+    pub kind_span: Span,
+}
+
+#[derive(Subdiagnostic)]
+pub(crate) enum CaptureVarCause {
+    #[label(borrowck_var_borrow_by_use_place)]
+    BorrowUsePlace {
+        place: String,
+        #[primary_span]
+        var_span: Span,
+    },
+    #[label(borrowck_var_borrow_by_use_place_in_generator)]
+    BorrowUsePlaceGenerator {
+        place: String,
+        #[primary_span]
+        var_span: Span,
+    },
+    #[label(borrowck_var_borrow_by_use_place_in_closure)]
+    BorrowUsePlaceClosure {
+        place: String,
+        #[primary_span]
+        var_span: Span,
+    },
+}
diff --git a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs
index d5bfc2f5208..ce7f857e273 100644
--- a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs
+++ b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs
@@ -1,10 +1,10 @@
-use rustc_infer::infer::canonical::QueryOutlivesConstraint;
+use rustc_hir::def_id::DefId;
 use rustc_infer::infer::canonical::QueryRegionConstraints;
 use rustc_infer::infer::outlives::env::RegionBoundPairs;
 use rustc_infer::infer::outlives::obligations::{TypeOutlives, TypeOutlivesDelegate};
 use rustc_infer::infer::region_constraints::{GenericKind, VerifyBound};
 use rustc_infer::infer::{self, InferCtxt, SubregionOrigin};
-use rustc_middle::mir::ConstraintCategory;
+use rustc_middle::mir::{ClosureOutlivesSubject, ClosureRegionRequirements, ConstraintCategory};
 use rustc_middle::ty::subst::GenericArgKind;
 use rustc_middle::ty::TypeFoldable;
 use rustc_middle::ty::{self, TyCtxt};
@@ -38,6 +38,7 @@ pub(crate) struct ConstraintConversion<'a, 'tcx> {
     locations: Locations,
     span: Span,
     category: ConstraintCategory<'tcx>,
+    from_closure: bool,
     constraints: &'a mut MirTypeckRegionConstraints<'tcx>,
 }
 
@@ -64,6 +65,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
             span,
             category,
             constraints,
+            from_closure: false,
         }
     }
 
@@ -81,12 +83,62 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
         }
         self.constraints.member_constraints = tmp;
 
-        for query_constraint in outlives {
-            self.convert(query_constraint);
+        for (predicate, constraint_category) in outlives {
+            // At the moment, we never generate any "higher-ranked"
+            // region constraints like `for<'a> 'a: 'b`. At some point
+            // when we move to universes, we will, and this assertion
+            // will start to fail.
+            let predicate = predicate.no_bound_vars().unwrap_or_else(|| {
+                bug!("query_constraint {:?} contained bound vars", predicate,);
+            });
+
+            self.convert(predicate, *constraint_category);
         }
     }
 
-    fn convert(&mut self, query_constraint: &QueryOutlivesConstraint<'tcx>) {
+    /// Given an instance of the closure type, this method instantiates the "extra" requirements
+    /// that we computed for the closure. This has the effect of adding new outlives obligations
+    /// to existing region variables in `closure_substs`.
+    #[instrument(skip(self), level = "debug")]
+    pub fn apply_closure_requirements(
+        &mut self,
+        closure_requirements: &ClosureRegionRequirements<'tcx>,
+        closure_def_id: DefId,
+        closure_substs: ty::SubstsRef<'tcx>,
+    ) {
+        // Extract the values of the free regions in `closure_substs`
+        // into a vector.  These are the regions that we will be
+        // relating to one another.
+        let closure_mapping = &UniversalRegions::closure_mapping(
+            self.tcx,
+            closure_substs,
+            closure_requirements.num_external_vids,
+            closure_def_id.expect_local(),
+        );
+        debug!(?closure_mapping);
+
+        // Create the predicates.
+        let backup = (self.category, self.span, self.from_closure);
+        self.from_closure = true;
+        for outlives_requirement in &closure_requirements.outlives_requirements {
+            let outlived_region = closure_mapping[outlives_requirement.outlived_free_region];
+            let subject = match outlives_requirement.subject {
+                ClosureOutlivesSubject::Region(re) => closure_mapping[re].into(),
+                ClosureOutlivesSubject::Ty(ty) => ty.into(),
+            };
+
+            self.category = outlives_requirement.category;
+            self.span = outlives_requirement.blame_span;
+            self.convert(ty::OutlivesPredicate(subject, outlived_region), self.category);
+        }
+        (self.category, self.span, self.from_closure) = backup;
+    }
+
+    fn convert(
+        &mut self,
+        predicate: ty::OutlivesPredicate<ty::GenericArg<'tcx>, ty::Region<'tcx>>,
+        constraint_category: ConstraintCategory<'tcx>,
+    ) {
         debug!("generate: constraints at: {:#?}", self.locations);
 
         // Extract out various useful fields we'll need below.
@@ -94,17 +146,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
             tcx, region_bound_pairs, implicit_region_bound, param_env, ..
         } = *self;
 
-        // At the moment, we never generate any "higher-ranked"
-        // region constraints like `for<'a> 'a: 'b`. At some point
-        // when we move to universes, we will, and this assertion
-        // will start to fail.
-        let ty::OutlivesPredicate(k1, r2) =
-            query_constraint.0.no_bound_vars().unwrap_or_else(|| {
-                bug!("query_constraint {:?} contained bound vars", query_constraint,);
-            });
-
-        let constraint_category = query_constraint.1;
-
+        let ty::OutlivesPredicate(k1, r2) = predicate;
         match k1.unpack() {
             GenericArgKind::Lifetime(r1) => {
                 let r1_vid = self.to_region_vid(r1);
@@ -127,10 +169,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
                 .type_must_outlive(origin, t1, r2, constraint_category);
             }
 
-            GenericArgKind::Const(_) => {
-                // Consts cannot outlive one another, so we
-                // don't need to handle any relations here.
-            }
+            GenericArgKind::Const(_) => unreachable!(),
         }
     }
 
@@ -160,7 +199,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
         verify_bound: VerifyBound<'tcx>,
     ) -> TypeTest<'tcx> {
         let lower_bound = self.to_region_vid(region);
-        TypeTest { generic_kind, lower_bound, locations: self.locations, verify_bound }
+        TypeTest { generic_kind, lower_bound, span: self.span, verify_bound }
     }
 
     fn to_region_vid(&mut self, r: ty::Region<'tcx>) -> ty::RegionVid {
@@ -188,6 +227,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
             sub,
             sup,
             variance_info: ty::VarianceDiagInfo::default(),
+            from_closure: self.from_closure,
         });
     }
 
diff --git a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs
index 02909592637..14cfc3613bf 100644
--- a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs
+++ b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs
@@ -247,12 +247,13 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
                     .and(type_op::normalize::Normalize::new(ty))
                     .fully_perform(self.infcx)
                     .unwrap_or_else(|_| {
-                        self.infcx
+                        let reported = self
+                            .infcx
                             .tcx
                             .sess
                             .delay_span_bug(span, &format!("failed to normalize {:?}", ty));
                         TypeOpOutput {
-                            output: self.infcx.tcx.ty_error(),
+                            output: self.infcx.tcx.ty_error_with_guaranteed(reported),
                             constraints: None,
                             error_info: None,
                         }
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index 3c1c3ab45ce..9c1d0bb8b23 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -27,7 +27,7 @@ use rustc_middle::mir::AssertKind;
 use rustc_middle::mir::*;
 use rustc_middle::ty::adjustment::PointerCast;
 use rustc_middle::ty::cast::CastTy;
-use rustc_middle::ty::subst::{GenericArgKind, SubstsRef, UserSubsts};
+use rustc_middle::ty::subst::{SubstsRef, UserSubsts};
 use rustc_middle::ty::visit::TypeVisitable;
 use rustc_middle::ty::{
     self, Binder, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, Dynamic,
@@ -61,7 +61,7 @@ use crate::{
     region_infer::values::{
         LivenessValues, PlaceholderIndex, PlaceholderIndices, RegionValueElements,
     },
-    region_infer::{ClosureRegionRequirementsExt, TypeTest},
+    region_infer::TypeTest,
     type_check::free_region_relations::{CreateResult, UniversalRegionRelations},
     universal_regions::{DefiningTy, UniversalRegions},
     Upvar,
@@ -144,7 +144,6 @@ pub(crate) fn type_check<'mir, 'tcx>(
         liveness_constraints: LivenessValues::new(elements.clone()),
         outlives_constraints: OutlivesConstraintSet::default(),
         member_constraints: MemberConstraintSet::default(),
-        closure_bounds_mapping: Default::default(),
         type_tests: Vec::default(),
         universe_causes: FxHashMap::default(),
     };
@@ -234,11 +233,11 @@ pub(crate) fn type_check<'mir, 'tcx>(
             let mut hidden_type = infcx.resolve_vars_if_possible(decl.hidden_type);
             trace!("finalized opaque type {:?} to {:#?}", opaque_type_key, hidden_type.ty.kind());
             if hidden_type.has_non_region_infer() {
-                infcx.tcx.sess.delay_span_bug(
+                let reported = infcx.tcx.sess.delay_span_bug(
                     decl.hidden_type.span,
                     &format!("could not resolve {:#?}", hidden_type.ty.kind()),
                 );
-                hidden_type.ty = infcx.tcx.ty_error();
+                hidden_type.ty = infcx.tcx.ty_error_with_guaranteed(reported);
             }
 
             (opaque_type_key, (hidden_type, decl.origin))
@@ -584,8 +583,6 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
         // modify their locations.
         let all_facts = &mut None;
         let mut constraints = Default::default();
-        let mut type_tests = Default::default();
-        let mut closure_bounds = Default::default();
         let mut liveness_constraints =
             LivenessValues::new(Rc::new(RegionValueElements::new(&promoted_body)));
         // Don't try to add borrow_region facts for the promoted MIR
@@ -596,11 +593,6 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
                 &mut this.cx.borrowck_context.constraints.outlives_constraints,
                 &mut constraints,
             );
-            mem::swap(&mut this.cx.borrowck_context.constraints.type_tests, &mut type_tests);
-            mem::swap(
-                &mut this.cx.borrowck_context.constraints.closure_bounds_mapping,
-                &mut closure_bounds,
-            );
             mem::swap(
                 &mut this.cx.borrowck_context.constraints.liveness_constraints,
                 &mut liveness_constraints,
@@ -621,13 +613,6 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
         swap_constraints(self);
 
         let locations = location.to_locations();
-
-        // Use location of promoted const in collected constraints
-        for type_test in type_tests.iter() {
-            let mut type_test = type_test.clone();
-            type_test.locations = locations;
-            self.cx.borrowck_context.constraints.type_tests.push(type_test)
-        }
         for constraint in constraints.outlives().iter() {
             let mut constraint = constraint.clone();
             constraint.locations = locations;
@@ -653,18 +638,6 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
                     .add_element(region, location);
             }
         }
-
-        if !closure_bounds.is_empty() {
-            let combined_bounds_mapping =
-                closure_bounds.into_iter().flat_map(|(_, value)| value).collect();
-            let existing = self
-                .cx
-                .borrowck_context
-                .constraints
-                .closure_bounds_mapping
-                .insert(location, combined_bounds_mapping);
-            assert!(existing.is_none(), "Multiple promoteds/closures at the same location.");
-        }
     }
 
     fn sanitize_projection(
@@ -941,9 +914,6 @@ pub(crate) struct MirTypeckRegionConstraints<'tcx> {
 
     pub(crate) member_constraints: MemberConstraintSet<'tcx, RegionVid>,
 
-    pub(crate) closure_bounds_mapping:
-        FxHashMap<Location, FxHashMap<(RegionVid, RegionVid), (ConstraintCategory<'tcx>, Span)>>,
-
     pub(crate) universe_causes: FxHashMap<ty::UniverseIndex, UniverseInfo<'tcx>>,
 
     pub(crate) type_tests: Vec<TypeTest<'tcx>>,
@@ -2562,6 +2532,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                                 span: location.to_locations().span(body),
                                 category,
                                 variance_info: ty::VarianceDiagInfo::default(),
+                                from_closure: false,
                             });
 
                             match mutbl {
@@ -2679,62 +2650,22 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         substs: SubstsRef<'tcx>,
         location: Location,
     ) -> ty::InstantiatedPredicates<'tcx> {
-        if let Some(ref closure_region_requirements) = tcx.mir_borrowck(def_id).closure_requirements
-        {
-            let closure_constraints = QueryRegionConstraints {
-                outlives: closure_region_requirements.apply_requirements(
-                    tcx,
-                    def_id.to_def_id(),
-                    substs,
-                ),
-
-                // Presently, closures never propagate member
-                // constraints to their parents -- they are enforced
-                // locally.  This is largely a non-issue as member
-                // constraints only come from `-> impl Trait` and
-                // friends which don't appear (thus far...) in
-                // closures.
-                member_constraints: vec![],
-            };
-
-            let bounds_mapping = closure_constraints
-                .outlives
-                .iter()
-                .enumerate()
-                .filter_map(|(idx, constraint)| {
-                    let ty::OutlivesPredicate(k1, r2) =
-                        constraint.0.no_bound_vars().unwrap_or_else(|| {
-                            bug!("query_constraint {:?} contained bound vars", constraint,);
-                        });
-
-                    match k1.unpack() {
-                        GenericArgKind::Lifetime(r1) => {
-                            // constraint is r1: r2
-                            let r1_vid = self.borrowck_context.universal_regions.to_region_vid(r1);
-                            let r2_vid = self.borrowck_context.universal_regions.to_region_vid(r2);
-                            let outlives_requirements =
-                                &closure_region_requirements.outlives_requirements[idx];
-                            Some((
-                                (r1_vid, r2_vid),
-                                (outlives_requirements.category, outlives_requirements.blame_span),
-                            ))
-                        }
-                        GenericArgKind::Type(_) | GenericArgKind::Const(_) => None,
-                    }
-                })
-                .collect();
-
-            let existing = self
-                .borrowck_context
-                .constraints
-                .closure_bounds_mapping
-                .insert(location, bounds_mapping);
-            assert!(existing.is_none(), "Multiple closures at the same location.");
-
-            self.push_region_constraints(
+        if let Some(ref closure_requirements) = tcx.mir_borrowck(def_id).closure_requirements {
+            constraint_conversion::ConstraintConversion::new(
+                self.infcx,
+                self.borrowck_context.universal_regions,
+                self.region_bound_pairs,
+                self.implicit_region_bound,
+                self.param_env,
                 location.to_locations(),
-                ConstraintCategory::ClosureBounds,
-                &closure_constraints,
+                DUMMY_SP,                   // irrelevant; will be overrided.
+                ConstraintCategory::Boring, // same as above.
+                &mut self.borrowck_context.constraints,
+            )
+            .apply_closure_requirements(
+                &closure_requirements,
+                def_id.to_def_id(),
+                substs,
             );
         }
 
diff --git a/compiler/rustc_borrowck/src/type_check/relate_tys.rs b/compiler/rustc_borrowck/src/type_check/relate_tys.rs
index 4f2dc263bf5..94d51032866 100644
--- a/compiler/rustc_borrowck/src/type_check/relate_tys.rs
+++ b/compiler/rustc_borrowck/src/type_check/relate_tys.rs
@@ -136,6 +136,7 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx>
                 span: self.locations.span(self.type_checker.body),
                 category: self.category,
                 variance_info: info,
+                from_closure: false,
             },
         );
     }
diff --git a/compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs b/compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs
index c55db2017ee..2ba012a77b0 100644
--- a/compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs
+++ b/compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs
@@ -59,7 +59,7 @@ impl DebugContext {
 
         let producer = format!(
             "cg_clif (rustc {}, cranelift {})",
-            rustc_interface::util::version_str().unwrap_or("unknown version"),
+            rustc_interface::util::rustc_version_str().unwrap_or("unknown version"),
             cranelift_codegen::VERSION,
         );
         let comp_dir = tcx
diff --git a/compiler/rustc_codegen_gcc/src/type_.rs b/compiler/rustc_codegen_gcc/src/type_.rs
index 68bdb8d4e55..862ed62c68b 100644
--- a/compiler/rustc_codegen_gcc/src/type_.rs
+++ b/compiler/rustc_codegen_gcc/src/type_.rs
@@ -201,6 +201,27 @@ impl<'gcc, 'tcx> BaseTypeMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
     fn val_ty(&self, value: RValue<'gcc>) -> Type<'gcc> {
         value.get_type()
     }
+
+    fn type_array(&self, ty: Type<'gcc>, mut len: u64) -> Type<'gcc> {
+        if let Some(struct_type) = ty.is_struct() {
+            if struct_type.get_field_count() == 0 {
+                // NOTE: since gccjit only supports i32 for the array size and libcore's tests uses a
+                // size of usize::MAX in test_binary_search, we workaround this by setting the size to
+                // zero for ZSTs.
+                // FIXME(antoyo): fix gccjit API.
+                len = 0;
+            }
+        }
+
+        // NOTE: see note above. Some other test uses usize::MAX.
+        if len == u64::MAX {
+            len = 0;
+        }
+
+        let len: i32 = len.try_into().expect("array len");
+
+        self.context.new_array_type(None, ty, len)
+    }
 }
 
 impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
@@ -227,27 +248,6 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
         self.context.new_opaque_struct_type(None, name)
     }
 
-    pub fn type_array(&self, ty: Type<'gcc>, mut len: u64) -> Type<'gcc> {
-        if let Some(struct_type) = ty.is_struct() {
-            if struct_type.get_field_count() == 0 {
-                // NOTE: since gccjit only supports i32 for the array size and libcore's tests uses a
-                // size of usize::MAX in test_binary_search, we workaround this by setting the size to
-                // zero for ZSTs.
-                // FIXME(antoyo): fix gccjit API.
-                len = 0;
-            }
-        }
-
-        // NOTE: see note above. Some other test uses usize::MAX.
-        if len == u64::MAX {
-            len = 0;
-        }
-
-        let len: i32 = len.try_into().expect("array len");
-
-        self.context.new_array_type(None, ty, len)
-    }
-
     pub fn type_bool(&self) -> Type<'gcc> {
         self.context.new_type::<bool>()
     }
diff --git a/compiler/rustc_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs
index d96da5cc11d..a8b47633519 100644
--- a/compiler/rustc_codegen_llvm/src/attributes.rs
+++ b/compiler/rustc_codegen_llvm/src/attributes.rs
@@ -12,6 +12,7 @@ use rustc_target::spec::{FramePointer, SanitizerSet, StackProbeType, StackProtec
 use smallvec::SmallVec;
 
 use crate::attributes;
+use crate::errors::{MissingFeatures, SanitizerMemtagRequiresMte, TargetFeatureDisableOrEnable};
 use crate::llvm::AttributePlace::Function;
 use crate::llvm::{self, AllocKindFlags, Attribute, AttributeKind, AttributePlace, MemoryEffects};
 use crate::llvm_util;
@@ -82,7 +83,7 @@ pub fn sanitize_attrs<'ll>(
         let mte_feature =
             features.iter().map(|s| &s[..]).rfind(|n| ["+mte", "-mte"].contains(&&n[..]));
         if let None | Some("-mte") = mte_feature {
-            cx.tcx.sess.err("`-Zsanitizer=memtag` requires `-Ctarget-feature=+mte`");
+            cx.tcx.sess.emit_err(SanitizerMemtagRequiresMte);
         }
 
         attrs.push(llvm::AttributeKind::SanitizeMemTag.create_attr(cx.llcx));
@@ -393,13 +394,14 @@ pub fn from_fn_attrs<'ll, 'tcx>(
             .get_attrs(instance.def_id(), sym::target_feature)
             .next()
             .map_or_else(|| cx.tcx.def_span(instance.def_id()), |a| a.span);
-        let msg = format!(
-            "the target features {} must all be either enabled or disabled together",
-            f.join(", ")
-        );
-        let mut err = cx.tcx.sess.struct_span_err(span, &msg);
-        err.help("add the missing features in a `target_feature` attribute");
-        err.emit();
+        cx.tcx
+            .sess
+            .create_err(TargetFeatureDisableOrEnable {
+                features: f,
+                span: Some(span),
+                missing_features: Some(MissingFeatures),
+            })
+            .emit();
         return;
     }
 
diff --git a/compiler/rustc_codegen_llvm/src/back/archive.rs b/compiler/rustc_codegen_llvm/src/back/archive.rs
index 082665bba38..5c68abeb08b 100644
--- a/compiler/rustc_codegen_llvm/src/back/archive.rs
+++ b/compiler/rustc_codegen_llvm/src/back/archive.rs
@@ -12,6 +12,10 @@ use std::str;
 use object::read::macho::FatArch;
 
 use crate::common;
+use crate::errors::{
+    ArchiveBuildFailure, DlltoolFailImportLibrary, ErrorCallingDllTool, ErrorCreatingImportLibrary,
+    ErrorWritingDEFFile, UnknownArchiveKind,
+};
 use crate::llvm::archive_ro::{ArchiveRO, Child};
 use crate::llvm::{self, ArchiveKind, LLVMMachineType, LLVMRustCOFFShortExport};
 use rustc_codegen_ssa::back::archive::{ArchiveBuilder, ArchiveBuilderBuilder};
@@ -147,7 +151,7 @@ impl<'a> ArchiveBuilder<'a> for LlvmArchiveBuilder<'a> {
     fn build(mut self: Box<Self>, output: &Path) -> bool {
         match self.build_with_llvm(output) {
             Ok(any_members) => any_members,
-            Err(e) => self.sess.fatal(&format!("failed to build archive: {}", e)),
+            Err(e) => self.sess.emit_fatal(ArchiveBuildFailure { error: e }),
         }
     }
 }
@@ -217,7 +221,7 @@ impl ArchiveBuilderBuilder for LlvmArchiveBuilderBuilder {
             match std::fs::write(&def_file_path, def_file_content) {
                 Ok(_) => {}
                 Err(e) => {
-                    sess.fatal(&format!("Error writing .DEF file: {}", e));
+                    sess.emit_fatal(ErrorWritingDEFFile { error: e });
                 }
             };
 
@@ -239,13 +243,14 @@ impl ArchiveBuilderBuilder for LlvmArchiveBuilderBuilder {
 
             match result {
                 Err(e) => {
-                    sess.fatal(&format!("Error calling dlltool: {}", e));
+                    sess.emit_fatal(ErrorCallingDllTool { error: e });
+                }
+                Ok(output) if !output.status.success() => {
+                    sess.emit_fatal(DlltoolFailImportLibrary {
+                        stdout: String::from_utf8_lossy(&output.stdout),
+                        stderr: String::from_utf8_lossy(&output.stderr),
+                    })
                 }
-                Ok(output) if !output.status.success() => sess.fatal(&format!(
-                    "Dlltool could not create import library: {}\n{}",
-                    String::from_utf8_lossy(&output.stdout),
-                    String::from_utf8_lossy(&output.stderr)
-                )),
                 _ => {}
             }
         } else {
@@ -293,11 +298,10 @@ impl ArchiveBuilderBuilder for LlvmArchiveBuilderBuilder {
             };
 
             if result == crate::llvm::LLVMRustResult::Failure {
-                sess.fatal(&format!(
-                    "Error creating import library for {}: {}",
+                sess.emit_fatal(ErrorCreatingImportLibrary {
                     lib_name,
-                    llvm::last_error().unwrap_or("unknown LLVM error".to_string())
-                ));
+                    error: llvm::last_error().unwrap_or("unknown LLVM error".to_string()),
+                });
             }
         };
 
@@ -308,9 +312,10 @@ impl ArchiveBuilderBuilder for LlvmArchiveBuilderBuilder {
 impl<'a> LlvmArchiveBuilder<'a> {
     fn build_with_llvm(&mut self, output: &Path) -> io::Result<bool> {
         let kind = &*self.sess.target.archive_format;
-        let kind = kind.parse::<ArchiveKind>().map_err(|_| kind).unwrap_or_else(|kind| {
-            self.sess.fatal(&format!("Don't know how to build archive of type: {}", kind))
-        });
+        let kind = kind
+            .parse::<ArchiveKind>()
+            .map_err(|_| kind)
+            .unwrap_or_else(|kind| self.sess.emit_fatal(UnknownArchiveKind { kind }));
 
         let mut additions = mem::take(&mut self.additions);
         let mut strings = Vec::new();
diff --git a/compiler/rustc_codegen_llvm/src/back/lto.rs b/compiler/rustc_codegen_llvm/src/back/lto.rs
index a49cc7f8d66..3fa21355b7f 100644
--- a/compiler/rustc_codegen_llvm/src/back/lto.rs
+++ b/compiler/rustc_codegen_llvm/src/back/lto.rs
@@ -1,4 +1,5 @@
 use crate::back::write::{self, save_temp_bitcode, DiagnosticHandlers};
+use crate::errors::DynamicLinkingWithLTO;
 use crate::llvm::{self, build_string};
 use crate::{LlvmCodegenBackend, ModuleLlvm};
 use object::read::archive::ArchiveFile;
@@ -90,13 +91,7 @@ fn prepare_lto(
         }
 
         if cgcx.opts.cg.prefer_dynamic && !cgcx.opts.unstable_opts.dylib_lto {
-            diag_handler
-                .struct_err("cannot prefer dynamic linking when performing LTO")
-                .note(
-                    "only 'staticlib', 'bin', and 'cdylib' outputs are \
-                               supported with LTO",
-                )
-                .emit();
+            diag_handler.emit_err(DynamicLinkingWithLTO);
             return Err(FatalError);
         }
 
diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs
index dd3c43ba5ca..3b504d3a7df 100644
--- a/compiler/rustc_codegen_llvm/src/consts.rs
+++ b/compiler/rustc_codegen_llvm/src/consts.rs
@@ -1,6 +1,7 @@
 use crate::base;
 use crate::common::{self, CodegenCx};
 use crate::debuginfo;
+use crate::errors::{InvalidMinimumAlignment, LinkageConstOrMutType, SymbolAlreadyDefined};
 use crate::llvm::{self, True};
 use crate::llvm_util;
 use crate::type_::Type;
@@ -19,6 +20,7 @@ use rustc_middle::mir::mono::MonoItem;
 use rustc_middle::ty::layout::LayoutOf;
 use rustc_middle::ty::{self, Instance, Ty};
 use rustc_middle::{bug, span_bug};
+use rustc_session::config::Lto;
 use rustc_target::abi::{
     AddressSpace, Align, HasDataLayout, Primitive, Scalar, Size, WrappingRange,
 };
@@ -145,7 +147,7 @@ fn set_global_alignment<'ll>(cx: &CodegenCx<'ll, '_>, gv: &'ll Value, mut align:
         match Align::from_bits(min) {
             Ok(min) => align = align.max(min),
             Err(err) => {
-                cx.sess().err(&format!("invalid minimum global alignment: {}", err));
+                cx.sess().emit_err(InvalidMinimumAlignment { err });
             }
         }
     }
@@ -173,10 +175,7 @@ fn check_and_apply_linkage<'ll, 'tcx>(
         let llty2 = if let ty::RawPtr(ref mt) = ty.kind() {
             cx.layout_of(mt.ty).llvm_type(cx)
         } else {
-            cx.sess().span_fatal(
-                cx.tcx.def_span(def_id),
-                "must have type `*const T` or `*mut T` due to `#[linkage]` attribute",
-            )
+            cx.sess().emit_fatal(LinkageConstOrMutType { span: cx.tcx.def_span(def_id) })
         };
         unsafe {
             // Declare a symbol `foo` with the desired linkage.
@@ -192,10 +191,10 @@ fn check_and_apply_linkage<'ll, 'tcx>(
             let mut real_name = "_rust_extern_with_linkage_".to_string();
             real_name.push_str(sym);
             let g2 = cx.define_global(&real_name, llty).unwrap_or_else(|| {
-                cx.sess().span_fatal(
-                    cx.tcx.def_span(def_id),
-                    &format!("symbol `{}` is already defined", &sym),
-                )
+                cx.sess().emit_fatal(SymbolAlreadyDefined {
+                    span: cx.tcx.def_span(def_id),
+                    symbol_name: sym,
+                })
             });
             llvm::LLVMRustSetLinkage(g2, llvm::Linkage::InternalLinkage);
             llvm::LLVMSetInitializer(g2, g1);
@@ -303,7 +302,8 @@ impl<'ll> CodegenCx<'ll, '_> {
                 // ThinLTO can't handle this workaround in all cases, so we don't
                 // emit the attrs. Instead we make them unnecessary by disallowing
                 // dynamic linking when linker plugin based LTO is enabled.
-                !self.tcx.sess.opts.cg.linker_plugin_lto.enabled();
+                !self.tcx.sess.opts.cg.linker_plugin_lto.enabled() &&
+                self.tcx.sess.lto() != Lto::Thin;
 
             // If this assertion triggers, there's something wrong with commandline
             // argument validation.
diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs
index 79ddfd884df..eaa2ccfc835 100644
--- a/compiler/rustc_codegen_llvm/src/context.rs
+++ b/compiler/rustc_codegen_llvm/src/context.rs
@@ -3,6 +3,7 @@ use crate::back::write::to_llvm_code_model;
 use crate::callee::get_fn;
 use crate::coverageinfo;
 use crate::debuginfo;
+use crate::errors::BranchProtectionRequiresAArch64;
 use crate::llvm;
 use crate::llvm_util;
 use crate::type_::Type;
@@ -26,6 +27,7 @@ use rustc_session::config::{BranchProtection, CFGuard, CFProtection};
 use rustc_session::config::{CrateType, DebugInfo, PAuthKey, PacRet};
 use rustc_session::Session;
 use rustc_span::source_map::Span;
+use rustc_span::source_map::Spanned;
 use rustc_target::abi::{
     call::FnAbi, HasDataLayout, PointeeInfo, Size, TargetDataLayout, VariantIdx,
 };
@@ -158,6 +160,10 @@ pub unsafe fn create_module<'ll>(
         if sess.target.arch == "s390x" {
             target_data_layout = target_data_layout.replace("-v128:64", "");
         }
+
+        if sess.target.arch == "riscv64" {
+            target_data_layout = target_data_layout.replace("-n32:64-", "-n64-");
+        }
     }
 
     // Ensure the data-layout values hardcoded remain the defaults.
@@ -271,7 +277,7 @@ pub unsafe fn create_module<'ll>(
 
     if let Some(BranchProtection { bti, pac_ret }) = sess.opts.unstable_opts.branch_protection {
         if sess.target.arch != "aarch64" {
-            sess.err("-Zbranch-protection is only supported on aarch64");
+            sess.emit_err(BranchProtectionRequiresAArch64);
         } else {
             llvm::LLVMRustAddModuleFlag(
                 llmod,
@@ -947,7 +953,7 @@ impl<'tcx> LayoutOfHelpers<'tcx> for CodegenCx<'_, 'tcx> {
     #[inline]
     fn handle_layout_err(&self, err: LayoutError<'tcx>, span: Span, ty: Ty<'tcx>) -> ! {
         if let LayoutError::SizeOverflow(_) = err {
-            self.sess().span_fatal(span, &err.to_string())
+            self.sess().emit_fatal(Spanned { span, node: err })
         } else {
             span_bug!(span, "failed to get layout for `{}`: {}", ty, err)
         }
@@ -965,7 +971,7 @@ impl<'tcx> FnAbiOfHelpers<'tcx> for CodegenCx<'_, 'tcx> {
         fn_abi_request: FnAbiRequest<'tcx>,
     ) -> ! {
         if let FnAbiError::Layout(LayoutError::SizeOverflow(_)) = err {
-            self.sess().span_fatal(span, &err.to_string())
+            self.sess().emit_fatal(Spanned { span, node: err })
         } else {
             match fn_abi_request {
                 FnAbiRequest::OfFnPtr { sig, extra_args } => {
diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs
index 433f043209e..8a8d889a298 100644
--- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs
+++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs
@@ -1,5 +1,6 @@
 use crate::common::CodegenCx;
 use crate::coverageinfo;
+use crate::errors::InstrumentCoverageRequiresLLVM12;
 use crate::llvm;
 
 use llvm::coverageinfo::CounterMappingRegion;
@@ -37,7 +38,7 @@ pub fn finalize<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>) {
     // LLVM 12.
     let version = coverageinfo::mapping_version();
     if version < 4 {
-        tcx.sess.fatal("rustc option `-C instrument-coverage` requires LLVM 12 or higher.");
+        tcx.sess.emit_fatal(InstrumentCoverageRequiresLLVM12);
     }
 
     debug!("Generating coverage map for CodegenUnit: `{}`", cx.codegen_unit.name());
diff --git a/compiler/rustc_codegen_llvm/src/errors.rs b/compiler/rustc_codegen_llvm/src/errors.rs
new file mode 100644
index 00000000000..0fafc214f2f
--- /dev/null
+++ b/compiler/rustc_codegen_llvm/src/errors.rs
@@ -0,0 +1,139 @@
+use std::borrow::Cow;
+
+use rustc_errors::fluent;
+use rustc_errors::DiagnosticBuilder;
+use rustc_errors::ErrorGuaranteed;
+use rustc_errors::Handler;
+use rustc_errors::IntoDiagnostic;
+use rustc_macros::{Diagnostic, Subdiagnostic};
+use rustc_span::Span;
+
+#[derive(Diagnostic)]
+#[diag(codegen_llvm_unknown_ctarget_feature_prefix)]
+#[note]
+pub(crate) struct UnknownCTargetFeaturePrefix<'a> {
+    pub feature: &'a str,
+}
+
+#[derive(Diagnostic)]
+#[diag(codegen_llvm_unknown_ctarget_feature)]
+#[note]
+pub(crate) struct UnknownCTargetFeature<'a> {
+    pub feature: &'a str,
+    #[subdiagnostic]
+    pub rust_feature: PossibleFeature<'a>,
+}
+
+#[derive(Subdiagnostic)]
+pub(crate) enum PossibleFeature<'a> {
+    #[help(possible_feature)]
+    Some { rust_feature: &'a str },
+    #[help(consider_filing_feature_request)]
+    None,
+}
+
+#[derive(Diagnostic)]
+#[diag(codegen_llvm_error_creating_import_library)]
+pub(crate) struct ErrorCreatingImportLibrary<'a> {
+    pub lib_name: &'a str,
+    pub error: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(codegen_llvm_instrument_coverage_requires_llvm_12)]
+pub(crate) struct InstrumentCoverageRequiresLLVM12;
+
+#[derive(Diagnostic)]
+#[diag(codegen_llvm_symbol_already_defined)]
+pub(crate) struct SymbolAlreadyDefined<'a> {
+    #[primary_span]
+    pub span: Span,
+    pub symbol_name: &'a str,
+}
+
+#[derive(Diagnostic)]
+#[diag(codegen_llvm_branch_protection_requires_aarch64)]
+pub(crate) struct BranchProtectionRequiresAArch64;
+
+#[derive(Diagnostic)]
+#[diag(codegen_llvm_invalid_minimum_alignment)]
+pub(crate) struct InvalidMinimumAlignment {
+    pub err: String,
+}
+
+#[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;
+
+#[derive(Diagnostic)]
+#[diag(codegen_llvm_archive_build_failure)]
+pub(crate) struct ArchiveBuildFailure {
+    pub error: std::io::Error,
+}
+
+#[derive(Diagnostic)]
+#[diag(codegen_llvm_error_writing_def_file)]
+pub(crate) struct ErrorWritingDEFFile {
+    pub error: std::io::Error,
+}
+
+#[derive(Diagnostic)]
+#[diag(codegen_llvm_error_calling_dlltool)]
+pub(crate) struct ErrorCallingDllTool {
+    pub error: std::io::Error,
+}
+
+#[derive(Diagnostic)]
+#[diag(codegen_llvm_dlltool_fail_import_library)]
+pub(crate) struct DlltoolFailImportLibrary<'a> {
+    pub stdout: Cow<'a, str>,
+    pub stderr: Cow<'a, str>,
+}
+
+#[derive(Diagnostic)]
+#[diag(codegen_llvm_unknown_archive_kind)]
+pub(crate) struct UnknownArchiveKind<'a> {
+    pub kind: &'a str,
+}
+
+#[derive(Diagnostic)]
+#[diag(codegen_llvm_dynamic_linking_with_lto)]
+#[note]
+pub(crate) struct DynamicLinkingWithLTO;
+
+#[derive(Diagnostic)]
+#[diag(codegen_llvm_fail_parsing_target_machine_config_to_target_machine)]
+pub(crate) struct FailParsingTargetMachineConfigToTargetMachine {
+    pub error: String,
+}
+
+pub(crate) struct TargetFeatureDisableOrEnable<'a> {
+    pub features: &'a [&'a str],
+    pub span: Option<Span>,
+    pub missing_features: Option<MissingFeatures>,
+}
+
+#[derive(Subdiagnostic)]
+#[help(codegen_llvm_missing_features)]
+pub(crate) struct MissingFeatures;
+
+impl IntoDiagnostic<'_, ErrorGuaranteed> for TargetFeatureDisableOrEnable<'_> {
+    fn into_diagnostic(self, sess: &'_ Handler) -> DiagnosticBuilder<'_, ErrorGuaranteed> {
+        let mut diag = sess.struct_err(fluent::codegen_llvm_target_feature_disable_or_enable);
+        if let Some(span) = self.span {
+            diag.set_span(span);
+        };
+        if let Some(missing_features) = self.missing_features {
+            diag.subdiagnostic(missing_features);
+        }
+        diag.set_arg("features", self.features.join(", "));
+        diag
+    }
+}
diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs
index d51aced85df..246e82545c8 100644
--- a/compiler/rustc_codegen_llvm/src/lib.rs
+++ b/compiler/rustc_codegen_llvm/src/lib.rs
@@ -12,6 +12,8 @@
 #![feature(iter_intersperse)]
 #![recursion_limit = "256"]
 #![allow(rustc::potential_query_instability)]
+#![deny(rustc::untranslatable_diagnostic)]
+#![deny(rustc::diagnostic_outside_of_impl)]
 
 #[macro_use]
 extern crate rustc_macros;
@@ -20,6 +22,7 @@ extern crate tracing;
 
 use back::write::{create_informational_target_machine, create_target_machine};
 
+use errors::FailParsingTargetMachineConfigToTargetMachine;
 pub use llvm_util::target_features;
 use rustc_ast::expand::allocator::AllocatorKind;
 use rustc_codegen_ssa::back::lto::{LtoModuleCodegen, SerializedModule, ThinModule};
@@ -62,6 +65,7 @@ mod context;
 mod coverageinfo;
 mod debuginfo;
 mod declare;
+mod errors;
 mod intrinsic;
 
 // The following is a work around that replaces `pub mod llvm;` and that fixes issue 53912.
@@ -412,7 +416,7 @@ impl ModuleLlvm {
             let tm = match (cgcx.tm_factory)(tm_factory_config) {
                 Ok(m) => m,
                 Err(e) => {
-                    handler.struct_err(&e).emit();
+                    handler.emit_err(FailParsingTargetMachineConfigToTargetMachine { error: e });
                     return Err(FatalError);
                 }
             };
diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs
index 2fd58567c48..e1f54356228 100644
--- a/compiler/rustc_codegen_llvm/src/llvm_util.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs
@@ -1,4 +1,8 @@
 use crate::back::write::create_informational_target_machine;
+use crate::errors::{
+    PossibleFeature, TargetFeatureDisableOrEnable, UnknownCTargetFeature,
+    UnknownCTargetFeaturePrefix,
+};
 use crate::llvm;
 use libc::c_int;
 use rustc_codegen_ssa::target_features::{
@@ -434,12 +438,7 @@ pub(crate) fn global_llvm_features(sess: &Session, diagnostics: bool) -> Vec<Str
                 Some(c @ '+' | c @ '-') => c,
                 Some(_) => {
                     if diagnostics {
-                        let mut diag = sess.struct_warn(&format!(
-                            "unknown feature specified for `-Ctarget-feature`: `{}`",
-                            s
-                        ));
-                        diag.note("features must begin with a `+` to enable or `-` to disable it");
-                        diag.emit();
+                        sess.emit_warning(UnknownCTargetFeaturePrefix { feature: s });
                     }
                     return None;
                 }
@@ -456,17 +455,15 @@ pub(crate) fn global_llvm_features(sess: &Session, diagnostics: bool) -> Vec<Str
                         None
                     }
                 });
-                let mut diag = sess.struct_warn(&format!(
-                    "unknown feature specified for `-Ctarget-feature`: `{}`",
-                    feature
-                ));
-                diag.note("it is still passed through to the codegen backend");
-                if let Some(rust_feature) = rust_feature {
-                    diag.help(&format!("you might have meant: `{}`", rust_feature));
+                let unknown_feature = if let Some(rust_feature) = rust_feature {
+                    UnknownCTargetFeature {
+                        feature,
+                        rust_feature: PossibleFeature::Some { rust_feature },
+                    }
                 } else {
-                    diag.note("consider filing a feature request");
-                }
-                diag.emit();
+                    UnknownCTargetFeature { feature, rust_feature: PossibleFeature::None }
+                };
+                sess.emit_warning(unknown_feature);
             }
 
             if diagnostics {
@@ -492,10 +489,11 @@ pub(crate) fn global_llvm_features(sess: &Session, diagnostics: bool) -> Vec<Str
     features.extend(feats);
 
     if diagnostics && let Some(f) = check_tied_features(sess, &featsmap) {
-        sess.err(&format!(
-            "target features {} must all be enabled or disabled together",
-            f.join(", ")
-        ));
+        sess.emit_err(TargetFeatureDisableOrEnable {
+            features: f,
+            span: None,
+            missing_features: None,
+        });
     }
 
     features
diff --git a/compiler/rustc_codegen_llvm/src/mono_item.rs b/compiler/rustc_codegen_llvm/src/mono_item.rs
index 1eceb7f5c87..76f692b2016 100644
--- a/compiler/rustc_codegen_llvm/src/mono_item.rs
+++ b/compiler/rustc_codegen_llvm/src/mono_item.rs
@@ -1,6 +1,7 @@
 use crate::attributes;
 use crate::base;
 use crate::context::CodegenCx;
+use crate::errors::SymbolAlreadyDefined;
 use crate::llvm;
 use crate::type_of::LayoutLlvmExt;
 use rustc_codegen_ssa::traits::*;
@@ -25,10 +26,8 @@ impl<'tcx> PreDefineMethods<'tcx> for CodegenCx<'_, 'tcx> {
         let llty = self.layout_of(ty).llvm_type(self);
 
         let g = self.define_global(symbol_name, llty).unwrap_or_else(|| {
-            self.sess().span_fatal(
-                self.tcx.def_span(def_id),
-                &format!("symbol `{}` is already defined", symbol_name),
-            )
+            self.sess()
+                .emit_fatal(SymbolAlreadyDefined { span: self.tcx.def_span(def_id), symbol_name })
         });
 
         unsafe {
diff --git a/compiler/rustc_codegen_llvm/src/type_.rs b/compiler/rustc_codegen_llvm/src/type_.rs
index eeb38d4ecf5..5eec7dc6130 100644
--- a/compiler/rustc_codegen_llvm/src/type_.rs
+++ b/compiler/rustc_codegen_llvm/src/type_.rs
@@ -127,10 +127,6 @@ impl<'ll> CodegenCx<'ll, '_> {
     pub(crate) fn type_variadic_func(&self, args: &[&'ll Type], ret: &'ll Type) -> &'ll Type {
         unsafe { llvm::LLVMFunctionType(ret, args.as_ptr(), args.len() as c_uint, True) }
     }
-
-    pub(crate) fn type_array(&self, ty: &'ll Type, len: u64) -> &'ll Type {
-        unsafe { llvm::LLVMRustArrayType(ty, len) }
-    }
 }
 
 impl<'ll, 'tcx> BaseTypeMethods<'tcx> for CodegenCx<'ll, 'tcx> {
@@ -231,6 +227,10 @@ impl<'ll, 'tcx> BaseTypeMethods<'tcx> for CodegenCx<'ll, 'tcx> {
     fn val_ty(&self, v: &'ll Value) -> &'ll Type {
         common::val_ty(v)
     }
+
+    fn type_array(&self, ty: &'ll Type, len: u64) -> &'ll Type {
+        unsafe { llvm::LLVMRustArrayType(ty, len) }
+    }
 }
 
 impl Type {
diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs
index d0ac016b02e..e3d28a1aca2 100644
--- a/compiler/rustc_codegen_ssa/src/back/write.rs
+++ b/compiler/rustc_codegen_ssa/src/back/write.rs
@@ -15,10 +15,8 @@ use rustc_data_structures::profiling::TimingGuard;
 use rustc_data_structures::profiling::VerboseTimingGuard;
 use rustc_data_structures::sync::Lrc;
 use rustc_errors::emitter::Emitter;
-use rustc_errors::{
-    translation::{to_fluent_args, Translate},
-    DiagnosticId, FatalError, Handler, Level,
-};
+use rustc_errors::{translation::Translate, DiagnosticId, FatalError, Handler, Level};
+use rustc_errors::{DiagnosticMessage, Style};
 use rustc_fs_util::link_or_copy;
 use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
 use rustc_incremental::{
@@ -38,6 +36,7 @@ use rustc_span::{BytePos, FileName, InnerSpan, Pos, Span};
 use rustc_target::spec::{MergeFunctions, SanitizerSet};
 
 use std::any::Any;
+use std::borrow::Cow;
 use std::fs;
 use std::io;
 use std::marker::PhantomData;
@@ -969,8 +968,11 @@ pub enum Message<B: WriteBackendMethods> {
     CodegenAborted,
 }
 
+type DiagnosticArgName<'source> = Cow<'source, str>;
+
 struct Diagnostic {
-    msg: String,
+    msg: Vec<(DiagnosticMessage, Style)>,
+    args: FxHashMap<DiagnosticArgName<'static>, rustc_errors::DiagnosticArgValue<'static>>,
     code: Option<DiagnosticId>,
     lvl: Level,
 }
@@ -1743,15 +1745,18 @@ impl Translate for SharedEmitter {
 
 impl Emitter for SharedEmitter {
     fn emit_diagnostic(&mut self, diag: &rustc_errors::Diagnostic) {
-        let fluent_args = to_fluent_args(diag.args());
+        let args: FxHashMap<Cow<'_, str>, rustc_errors::DiagnosticArgValue<'_>> =
+            diag.args().map(|(name, arg)| (name.clone(), arg.clone())).collect();
         drop(self.sender.send(SharedEmitterMessage::Diagnostic(Diagnostic {
-            msg: self.translate_messages(&diag.message, &fluent_args).to_string(),
+            msg: diag.message.clone(),
+            args: args.clone(),
             code: diag.code.clone(),
             lvl: diag.level(),
         })));
         for child in &diag.children {
             drop(self.sender.send(SharedEmitterMessage::Diagnostic(Diagnostic {
-                msg: self.translate_messages(&child.message, &fluent_args).to_string(),
+                msg: child.message.clone(),
+                args: args.clone(),
                 code: None,
                 lvl: child.level,
             })));
@@ -1782,10 +1787,11 @@ impl SharedEmitterMain {
             match message {
                 Ok(SharedEmitterMessage::Diagnostic(diag)) => {
                     let handler = sess.diagnostic();
-                    let mut d = rustc_errors::Diagnostic::new(diag.lvl, &diag.msg);
+                    let mut d = rustc_errors::Diagnostic::new_with_messages(diag.lvl, diag.msg);
                     if let Some(code) = diag.code {
                         d.code(code);
                     }
+                    d.replace_args(diag.args);
                     handler.emit_diagnostic(&mut d);
                 }
                 Ok(SharedEmitterMessage::InlineAsmError(cookie, msg, level, source)) => {
diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
index e05646e1e86..8647fbace2a 100644
--- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
+++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
@@ -59,7 +59,13 @@ fn push_debuginfo_type_name<'tcx>(
     match *t.kind() {
         ty::Bool => output.push_str("bool"),
         ty::Char => output.push_str("char"),
-        ty::Str => output.push_str("str"),
+        ty::Str => {
+            if cpp_like_debuginfo {
+                output.push_str("str$")
+            } else {
+                output.push_str("str")
+            }
+        }
         ty::Never => {
             if cpp_like_debuginfo {
                 output.push_str("never$");
@@ -152,25 +158,19 @@ fn push_debuginfo_type_name<'tcx>(
             }
         }
         ty::Ref(_, inner_type, mutbl) => {
-            // Slices and `&str` are treated like C++ pointers when computing debug
-            // info for MSVC debugger. However, wrapping these types' names in a synthetic type
-            // causes the .natvis engine for WinDbg to fail to display their data, so we opt these
-            // types out to aid debugging in MSVC.
-            let is_slice_or_str = matches!(*inner_type.kind(), ty::Slice(_) | ty::Str);
-
-            if !cpp_like_debuginfo {
-                output.push('&');
-                output.push_str(mutbl.prefix_str());
-            } else if !is_slice_or_str {
+            if cpp_like_debuginfo {
                 match mutbl {
                     Mutability::Not => output.push_str("ref$<"),
                     Mutability::Mut => output.push_str("ref_mut$<"),
                 }
+            } else {
+                output.push('&');
+                output.push_str(mutbl.prefix_str());
             }
 
             push_debuginfo_type_name(tcx, inner_type, qualified, output, visited);
 
-            if cpp_like_debuginfo && !is_slice_or_str {
+            if cpp_like_debuginfo {
                 push_close_angle_bracket(cpp_like_debuginfo, output);
             }
         }
@@ -195,7 +195,7 @@ fn push_debuginfo_type_name<'tcx>(
         }
         ty::Slice(inner_type) => {
             if cpp_like_debuginfo {
-                output.push_str("slice$<");
+                output.push_str("slice2$<");
             } else {
                 output.push('[');
             }
diff --git a/compiler/rustc_codegen_ssa/src/traits/type_.rs b/compiler/rustc_codegen_ssa/src/traits/type_.rs
index bdc6a91cf6a..86481d5d758 100644
--- a/compiler/rustc_codegen_ssa/src/traits/type_.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/type_.rs
@@ -22,6 +22,7 @@ pub trait BaseTypeMethods<'tcx>: Backend<'tcx> {
     fn type_f32(&self) -> Self::Type;
     fn type_f64(&self) -> Self::Type;
 
+    fn type_array(&self, ty: Self::Type, len: u64) -> Self::Type;
     fn type_func(&self, args: &[Self::Type], ret: Self::Type) -> Self::Type;
     fn type_struct(&self, els: &[Self::Type], packed: bool) -> Self::Type;
     fn type_kind(&self, ty: Self::Type) -> TypeKind;
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs
index b1ad22b899e..5a8b3e30b9f 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs
@@ -765,7 +765,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
 
                         let errors = ocx.select_all_or_error();
                         if !errors.is_empty() {
-                            infcx.err_ctxt().report_fulfillment_errors(&errors, None, false);
+                            infcx.err_ctxt().report_fulfillment_errors(&errors, None);
                         }
                     }
 
@@ -831,7 +831,6 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
                                         obligation.clone(),
                                         &obligation,
                                         &e,
-                                        false,
                                     );
                                 }
 
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs
index 335992342a6..d995d533ca3 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs
@@ -146,6 +146,7 @@ impl Qualif for NeedsNonConstDrop {
         qualifs.needs_non_const_drop
     }
 
+    #[instrument(level = "trace", skip(cx), ret)]
     fn in_any_value_of_ty<'tcx>(cx: &ConstCx<'_, 'tcx>, ty: Ty<'tcx>) -> bool {
         // Avoid selecting for simple cases, such as builtin types.
         if ty::util::is_trivially_const_drop(ty) {
@@ -174,6 +175,8 @@ impl Qualif for NeedsNonConstDrop {
             return true;
         };
 
+        trace!(?impl_src);
+
         if !matches!(
             impl_src,
             ImplSource::ConstDestruct(_) | ImplSource::Param(_, ty::BoundConstness::ConstIfConst)
diff --git a/compiler/rustc_data_structures/Cargo.toml b/compiler/rustc_data_structures/Cargo.toml
index 5152d5ab046..5afce15e26b 100644
--- a/compiler/rustc_data_structures/Cargo.toml
+++ b/compiler/rustc_data_structures/Cargo.toml
@@ -23,7 +23,7 @@ rustc_macros = { path = "../rustc_macros" }
 rustc_serialize = { path = "../rustc_serialize" }
 smallvec = { version = "1.8.1", features = ["const_generics", "union", "may_dangle"] }
 stable_deref_trait = "1.0.0"
-stacker = "0.1.14"
+stacker = "0.1.15"
 tempfile = "3.2"
 thin-vec = "0.2.9"
 tracing = "0.1"
diff --git a/compiler/rustc_driver/src/lib.rs b/compiler/rustc_driver/src/lib.rs
index cf4bcc7c158..e043368fdfe 100644
--- a/compiler/rustc_driver/src/lib.rs
+++ b/compiler/rustc_driver/src/lib.rs
@@ -6,6 +6,7 @@
 
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
 #![feature(once_cell)]
+#![feature(decl_macro)]
 #![recursion_limit = "256"]
 #![allow(rustc::potential_query_instability)]
 #![deny(rustc::untranslatable_diagnostic)]
@@ -736,26 +737,58 @@ fn print_crate_info(
             // Any output here interferes with Cargo's parsing of other printed output
             NativeStaticLibs => {}
             LinkArgs => {}
+            SplitDebuginfo => {
+                use rustc_target::spec::SplitDebuginfo::{Off, Packed, Unpacked};
+
+                for split in &[Off, Packed, Unpacked] {
+                    let stable = sess.target.options.supported_split_debuginfo.contains(split);
+                    let unstable_ok = sess.unstable_options();
+                    if stable || unstable_ok {
+                        println!("{}", split);
+                    }
+                }
+            }
         }
     }
     Compilation::Stop
 }
 
 /// Prints version information
-pub fn version(binary: &str, matches: &getopts::Matches) {
+///
+/// NOTE: this is a macro to support drivers built at a different time than the main `rustc_driver` crate.
+pub macro version($binary: literal, $matches: expr) {
+    fn unw(x: Option<&str>) -> &str {
+        x.unwrap_or("unknown")
+    }
+    $crate::version_at_macro_invocation(
+        $binary,
+        $matches,
+        unw(option_env!("CFG_VERSION")),
+        unw(option_env!("CFG_VER_HASH")),
+        unw(option_env!("CFG_VER_DATE")),
+        unw(option_env!("CFG_RELEASE")),
+    )
+}
+
+#[doc(hidden)] // use the macro instead
+pub fn version_at_macro_invocation(
+    binary: &str,
+    matches: &getopts::Matches,
+    version: &str,
+    commit_hash: &str,
+    commit_date: &str,
+    release: &str,
+) {
     let verbose = matches.opt_present("verbose");
 
-    println!("{} {}", binary, util::version_str().unwrap_or("unknown version"));
+    println!("{} {}", binary, version);
 
     if verbose {
-        fn unw(x: Option<&str>) -> &str {
-            x.unwrap_or("unknown")
-        }
         println!("binary: {}", binary);
-        println!("commit-hash: {}", unw(util::commit_hash_str()));
-        println!("commit-date: {}", unw(util::commit_date_str()));
+        println!("commit-hash: {}", commit_hash);
+        println!("commit-date: {}", commit_date);
         println!("host: {}", config::host_triple());
-        println!("release: {}", unw(util::release_str()));
+        println!("release: {}", release);
 
         let debug_flags = matches.opt_strs("Z");
         let backend_name = debug_flags.iter().find_map(|x| x.strip_prefix("codegen-backend="));
@@ -1071,7 +1104,7 @@ pub fn handle_options(args: &[String]) -> Option<getopts::Matches> {
     }
 
     if matches.opt_present("version") {
-        version("rustc", &matches);
+        version!("rustc", &matches);
         return None;
     }
 
@@ -1216,7 +1249,7 @@ pub fn report_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str) {
         format!("we would appreciate a bug report: {}", bug_report_url).into(),
         format!(
             "rustc {} running on {}",
-            util::version_str().unwrap_or("unknown_version"),
+            util::version_str!().unwrap_or("unknown_version"),
             config::host_triple()
         )
         .into(),
diff --git a/compiler/rustc_error_codes/src/error_codes/E0207.md b/compiler/rustc_error_codes/src/error_codes/E0207.md
index 8a7923ac93f..95e7c9fc76c 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0207.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0207.md
@@ -1,4 +1,5 @@
-A type parameter that is specified for `impl` is not constrained.
+A type, const or lifetime parameter that is specified for `impl` is not
+constrained.
 
 Erroneous code example:
 
@@ -14,8 +15,8 @@ impl<T: Default> Foo {
 }
 ```
 
-Any type parameter of an `impl` must meet at least one of
-the following criteria:
+Any type or const parameter of an `impl` must meet at least one of the
+following criteria:
 
  - it appears in the _implementing type_ of the impl, e.g. `impl<T> Foo<T>`
  - for a trait impl, it appears in the _implemented trait_, e.g.
@@ -23,6 +24,9 @@ the following criteria:
  - it is bound as an associated type, e.g. `impl<T, U> SomeTrait for T
    where T: AnotherTrait<AssocType=U>`
 
+Any unconstrained lifetime parameter of an `impl` is not supported if the
+lifetime parameter is used by an associated type.
+
 ### Error example 1
 
 Suppose we have a struct `Foo` and we would like to define some methods for it.
@@ -32,7 +36,6 @@ The problem is that the parameter `T` does not appear in the implementing type
 (`Foo`) of the impl. In this case, we can fix the error by moving the type
 parameter from the `impl` to the method `get`:
 
-
 ```
 struct Foo;
 
@@ -128,6 +131,70 @@ impl<T: Default> Maker<Foo<T>> for FooMaker {
 }
 ```
 
+### Error example 3
+
+Suppose we have a struct `Foo` and we would like to define some methods for it.
+The following code example has a definition which leads to a compiler error:
+
+```compile_fail,E0207
+struct Foo;
+
+impl<const T: i32> Foo {
+    // error: the const parameter `T` is not constrained by the impl trait, self
+    // type, or predicates [E0207]
+    fn get(&self) -> i32 {
+        i32::default()
+    }
+}
+```
+
+The problem is that the const parameter `T` does not appear in the implementing
+type (`Foo`) of the impl. In this case, we can fix the error by moving the type
+parameter from the `impl` to the method `get`:
+
+
+```
+struct Foo;
+
+// Move the const parameter from the impl to the method
+impl Foo {
+    fn get<const T: i32>(&self) -> i32 {
+        i32::default()
+    }
+}
+```
+
+### Error example 4
+
+Suppose we have a struct `Foo` and a struct `Bar` that uses lifetime `'a`. We
+would like to implement trait `Contains` for `Foo`. The trait `Contains` have
+the associated type `B`. The following code example has a definition which
+leads to a compiler error:
+
+```compile_fail,E0207
+struct Foo;
+struct Bar<'a>;
+
+trait Contains {
+    type B;
+
+    fn get(&self) -> i32;
+}
+
+impl<'a> Contains for Foo {
+    type B = Bar<'a>;
+
+    // error: the lifetime parameter `'a` is not constrained by the impl trait,
+    // self type, or predicates [E0207]
+    fn get(&self) -> i32 {
+        i32::default()
+    }
+}
+```
+
+Please note that unconstrained lifetime parameters are not supported if they are
+being used by an associated type.
+
 ### Additional information
 
 For more information, please see [RFC 447].
diff --git a/compiler/rustc_error_messages/locales/en-US/borrowck.ftl b/compiler/rustc_error_messages/locales/en-US/borrowck.ftl
index 67f2156f32e..80fc4c6e4f5 100644
--- a/compiler/rustc_error_messages/locales/en-US/borrowck.ftl
+++ b/compiler/rustc_error_messages/locales/en-US/borrowck.ftl
@@ -58,3 +58,15 @@ borrowck_returned_lifetime_short =
 
 borrowck_used_impl_require_static =
     the used `impl` has a `'static` requirement
+
+borrowck_capture_kind_label =
+    capture is {$kind_desc} because of use here
+
+borrowck_var_borrow_by_use_place_in_generator =
+    borrow occurs due to use of {$place} in closure in generator
+
+borrowck_var_borrow_by_use_place_in_closure =
+    borrow occurs due to use of {$place} in closure
+
+borrowck_var_borrow_by_use_place =
+    borrow occurs due to use of {$place}
diff --git a/compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl b/compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl
new file mode 100644
index 00000000000..68a205df6c7
--- /dev/null
+++ b/compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl
@@ -0,0 +1,58 @@
+codegen_llvm_unknown_ctarget_feature =
+    unknown feature specified for `-Ctarget-feature`: `{$feature}`
+    .note = it is still passed through to the codegen backend
+    .possible_feature = you might have meant: `{$rust_feature}`
+    .consider_filing_feature_request = consider filing a feature request
+
+codegen_llvm_unknown_ctarget_feature_prefix =
+    unknown feature specified for `-Ctarget-feature`: `{$feature}`
+    .note = features must begin with a `+` to enable or `-` to disable it
+
+codegen_llvm_error_creating_import_library =
+    Error creating import library for {$lib_name}: {$error}
+
+codegen_llvm_instrument_coverage_requires_llvm_12 =
+    rustc option `-C instrument-coverage` requires LLVM 12 or higher.
+
+codegen_llvm_symbol_already_defined =
+    symbol `{$symbol_name}` is already defined
+
+codegen_llvm_branch_protection_requires_aarch64 =
+    -Zbranch-protection is only supported on 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`
+
+codegen_llvm_archive_build_failure =
+    failed to build archive: {$error}
+
+codegen_llvm_error_writing_def_file =
+    Error writing .DEF file: {$error}
+
+codegen_llvm_error_calling_dlltool =
+    Error calling dlltool: {$error}
+
+codegen_llvm_dlltool_fail_import_library =
+    Dlltool could not create import library: {$stdout}\n{$stderr}
+
+codegen_llvm_unknown_archive_kind =
+    Don't know how to build archive of type: {$kind}
+
+codegen_llvm_target_feature_disable_or_enable =
+    the target features {$features} must all be either enabled or disabled together
+
+codegen_llvm_missing_features =
+    add the missing features in a `target_feature` attribute
+
+codegen_llvm_dynamic_linking_with_lto =
+    cannot prefer dynamic linking when performing LTO
+    .note = only 'staticlib', 'bin', and 'cdylib' outputs are supported with LTO
+
+codegen_llvm_fail_parsing_target_machine_config_to_target_machine =
+    failed to parse target machine config to target machine: {$error}
diff --git a/compiler/rustc_error_messages/locales/en-US/infer.ftl b/compiler/rustc_error_messages/locales/en-US/infer.ftl
index 18b3408b06a..fa975ff2c20 100644
--- a/compiler/rustc_error_messages/locales/en-US/infer.ftl
+++ b/compiler/rustc_error_messages/locales/en-US/infer.ftl
@@ -171,3 +171,4 @@ infer_msl_introduces_static = introduces a `'static` lifetime requirement
 infer_msl_unmet_req = because this has an unmet lifetime requirement
 infer_msl_trait_note = this has an implicit `'static` lifetime requirement
 infer_msl_trait_sugg = consider relaxing the implicit `'static` requirement
+infer_suggest_add_let_for_letchains = consider adding `let`
diff --git a/compiler/rustc_error_messages/locales/en-US/parser.ftl b/compiler/rustc_error_messages/locales/en-US/parser.ftl
index 13c368d1c58..6d42b23fb3a 100644
--- a/compiler/rustc_error_messages/locales/en-US/parser.ftl
+++ b/compiler/rustc_error_messages/locales/en-US/parser.ftl
@@ -112,6 +112,9 @@ parser_missing_semicolon_before_array = expected `;`, found `[`
 parser_invalid_block_macro_segment = cannot use a `block` macro fragment here
     .label = the `block` fragment is within this context
 
+parser_expect_dotdot_not_dotdotdot = expected `..`, found `...`
+    .suggestion = use `..` to fill in the rest of the fields
+
 parser_if_expression_missing_then_block = this `if` expression is missing a block after the condition
     .add_then_block = add a block here
     .condition_possibly_unfinished = this binary operation is possibly unfinished
@@ -122,6 +125,9 @@ parser_if_expression_missing_condition = missing condition for `if` expression
 
 parser_expected_expression_found_let = expected expression, found `let` statement
 
+parser_expect_eq_instead_of_eqeq = expected `=`, found `==`
+    .suggestion = consider using `=` here
+
 parser_expected_else_block = expected `{"{"}`, found {$first_tok}
     .label = expected an `if` or a block after this `else`
     .suggestion = add an `if` if this is the condition of a chained `else if` statement
diff --git a/compiler/rustc_error_messages/locales/en-US/passes.ftl b/compiler/rustc_error_messages/locales/en-US/passes.ftl
index 5239ff9dc05..001e53d1d0e 100644
--- a/compiler/rustc_error_messages/locales/en-US/passes.ftl
+++ b/compiler/rustc_error_messages/locales/en-US/passes.ftl
@@ -47,7 +47,10 @@ passes_no_coverage_not_coverable =
 
 passes_should_be_applied_to_fn =
     attribute should be applied to a function definition
-    .label = not a function definition
+    .label = {$on_crate ->
+        [true] cannot be applied to crates
+        *[false] not a function definition
+    }
 
 passes_naked_tracked_caller =
     cannot use `#[track_caller]` with `#[naked]`
diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs
index 9465051dd10..e34acba1057 100644
--- a/compiler/rustc_error_messages/src/lib.rs
+++ b/compiler/rustc_error_messages/src/lib.rs
@@ -42,6 +42,7 @@ fluent_messages! {
     borrowck => "../locales/en-US/borrowck.ftl",
     builtin_macros => "../locales/en-US/builtin_macros.ftl",
     codegen_gcc => "../locales/en-US/codegen_gcc.ftl",
+    codegen_llvm => "../locales/en-US/codegen_llvm.ftl",
     codegen_ssa => "../locales/en-US/codegen_ssa.ftl",
     compiletest => "../locales/en-US/compiletest.ftl",
     const_eval => "../locales/en-US/const_eval.ftl",
diff --git a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs
index f14b8ee3254..c450c276366 100644
--- a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs
+++ b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs
@@ -52,7 +52,6 @@ impl Emitter for AnnotateSnippetEmitterWriter {
         let (mut primary_span, suggestions) = self.primary_span_formatted(&diag, &fluent_args);
 
         self.fix_multispans_in_extern_macros_and_render_macro_backtrace(
-            &self.source_map,
             &mut primary_span,
             &mut children,
             &diag.level,
diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs
index 45c017df918..43101bbb9d3 100644
--- a/compiler/rustc_errors/src/diagnostic.rs
+++ b/compiler/rustc_errors/src/diagnostic.rs
@@ -44,6 +44,15 @@ pub trait IntoDiagnosticArg {
     fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static>;
 }
 
+impl<'source> IntoDiagnosticArg for DiagnosticArgValue<'source> {
+    fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
+        match self {
+            DiagnosticArgValue::Str(s) => DiagnosticArgValue::Str(Cow::Owned(s.into_owned())),
+            DiagnosticArgValue::Number(n) => DiagnosticArgValue::Number(n),
+        }
+    }
+}
+
 impl<'source> Into<FluentValue<'source>> for DiagnosticArgValue<'source> {
     fn into(self) -> FluentValue<'source> {
         match self {
@@ -205,6 +214,22 @@ impl Diagnostic {
     }
 
     #[track_caller]
+    pub fn new_with_messages(level: Level, messages: Vec<(DiagnosticMessage, Style)>) -> Self {
+        Diagnostic {
+            level,
+            message: messages,
+            code: None,
+            span: MultiSpan::new(),
+            children: vec![],
+            suggestions: Ok(vec![]),
+            args: Default::default(),
+            sort_span: DUMMY_SP,
+            is_lint: false,
+            emitted_at: DiagnosticLocation::caller(),
+        }
+    }
+
+    #[track_caller]
     pub fn new_with_code<M: Into<DiagnosticMessage>>(
         level: Level,
         code: Option<DiagnosticId>,
@@ -931,6 +956,13 @@ impl Diagnostic {
         self
     }
 
+    pub fn replace_args(
+        &mut self,
+        args: FxHashMap<DiagnosticArgName<'static>, DiagnosticArgValue<'static>>,
+    ) {
+        self.args = args;
+    }
+
     pub fn styled_message(&self) -> &[(DiagnosticMessage, Style)] {
         &self.message
     }
diff --git a/compiler/rustc_errors/src/diagnostic_builder.rs b/compiler/rustc_errors/src/diagnostic_builder.rs
index ecf8570e81f..730061fca99 100644
--- a/compiler/rustc_errors/src/diagnostic_builder.rs
+++ b/compiler/rustc_errors/src/diagnostic_builder.rs
@@ -482,9 +482,9 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> {
     /// In the meantime, though, callsites are required to deal with the "bug"
     /// locally in whichever way makes the most sense.
     #[track_caller]
-    pub fn delay_as_bug(&mut self) {
+    pub fn delay_as_bug(&mut self) -> G {
         self.downgrade_to_delayed_bug();
-        self.emit();
+        self.emit()
     }
 
     forward!(
diff --git a/compiler/rustc_errors/src/diagnostic_impls.rs b/compiler/rustc_errors/src/diagnostic_impls.rs
index 22f6fc700fa..c6035705e39 100644
--- a/compiler/rustc_errors/src/diagnostic_impls.rs
+++ b/compiler/rustc_errors/src/diagnostic_impls.rs
@@ -107,6 +107,12 @@ impl IntoDiagnosticArg for String {
     }
 }
 
+impl<'a> IntoDiagnosticArg for Cow<'a, str> {
+    fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
+        DiagnosticArgValue::Str(Cow::Owned(self.into_owned()))
+    }
+}
+
 impl<'a> IntoDiagnosticArg for &'a Path {
     fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
         DiagnosticArgValue::Str(Cow::Owned(self.display().to_string()))
diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs
index b7b8fe3f25a..55c7997a513 100644
--- a/compiler/rustc_errors/src/emitter.rs
+++ b/compiler/rustc_errors/src/emitter.rs
@@ -314,7 +314,6 @@ pub trait Emitter: Translate {
 
     fn fix_multispans_in_extern_macros_and_render_macro_backtrace(
         &self,
-        source_map: &Option<Lrc<SourceMap>>,
         span: &mut MultiSpan,
         children: &mut Vec<SubDiagnostic>,
         level: &Level,
@@ -340,7 +339,7 @@ pub trait Emitter: Translate {
             .collect();
 
         if !backtrace {
-            self.fix_multispans_in_extern_macros(source_map, span, children);
+            self.fix_multispans_in_extern_macros(span, children);
         }
 
         self.render_multispans_macro_backtrace(span, children, backtrace);
@@ -480,15 +479,13 @@ pub trait Emitter: Translate {
     // this will change the span to point at the use site.
     fn fix_multispans_in_extern_macros(
         &self,
-        source_map: &Option<Lrc<SourceMap>>,
         span: &mut MultiSpan,
         children: &mut Vec<SubDiagnostic>,
     ) {
-        let Some(source_map) = source_map else { return };
         debug!("fix_multispans_in_extern_macros: before: span={:?} children={:?}", span, children);
-        self.fix_multispan_in_extern_macros(source_map, span);
+        self.fix_multispan_in_extern_macros(span);
         for child in children.iter_mut() {
-            self.fix_multispan_in_extern_macros(source_map, &mut child.span);
+            self.fix_multispan_in_extern_macros(&mut child.span);
         }
         debug!("fix_multispans_in_extern_macros: after: span={:?} children={:?}", span, children);
     }
@@ -496,7 +493,8 @@ pub trait Emitter: Translate {
     // This "fixes" MultiSpans that contain `Span`s pointing to locations inside of external macros.
     // Since these locations are often difficult to read,
     // we move these spans from the external macros to their corresponding use site.
-    fn fix_multispan_in_extern_macros(&self, source_map: &Lrc<SourceMap>, span: &mut MultiSpan) {
+    fn fix_multispan_in_extern_macros(&self, span: &mut MultiSpan) {
+        let Some(source_map) = self.source_map() else { return };
         // First, find all the spans in external macros and point instead at their use site.
         let replacements: Vec<(Span, Span)> = span
             .primary_spans()
@@ -544,7 +542,6 @@ impl Emitter for EmitterWriter {
         debug!("emit_diagnostic: suggestions={:?}", suggestions);
 
         self.fix_multispans_in_extern_macros_and_render_macro_backtrace(
-            &self.sm,
             &mut primary_span,
             &mut children,
             &diag.level,
@@ -2213,22 +2210,45 @@ impl FileWithAnnotatedLines {
 
         if let Some(ref sm) = emitter.source_map() {
             for span_label in msp.span_labels() {
+                let fixup_lo_hi = |span: Span| {
+                    let lo = sm.lookup_char_pos(span.lo());
+                    let mut hi = sm.lookup_char_pos(span.hi());
+
+                    // Watch out for "empty spans". If we get a span like 6..6, we
+                    // want to just display a `^` at 6, so convert that to
+                    // 6..7. This is degenerate input, but it's best to degrade
+                    // gracefully -- and the parser likes to supply a span like
+                    // that for EOF, in particular.
+
+                    if lo.col_display == hi.col_display && lo.line == hi.line {
+                        hi.col_display += 1;
+                    }
+                    (lo, hi)
+                };
+
                 if span_label.span.is_dummy() {
+                    if let Some(span) = msp.primary_span() {
+                        // if we don't know where to render the annotation, emit it as a note
+                        // on the primary span.
+
+                        let (lo, hi) = fixup_lo_hi(span);
+
+                        let ann = Annotation {
+                            start_col: lo.col_display,
+                            end_col: hi.col_display,
+                            is_primary: span_label.is_primary,
+                            label: span_label
+                                .label
+                                .as_ref()
+                                .map(|m| emitter.translate_message(m, args).to_string()),
+                            annotation_type: AnnotationType::Singleline,
+                        };
+                        add_annotation_to_file(&mut output, lo.file, lo.line, ann);
+                    }
                     continue;
                 }
 
-                let lo = sm.lookup_char_pos(span_label.span.lo());
-                let mut hi = sm.lookup_char_pos(span_label.span.hi());
-
-                // Watch out for "empty spans". If we get a span like 6..6, we
-                // want to just display a `^` at 6, so convert that to
-                // 6..7. This is degenerate input, but it's best to degrade
-                // gracefully -- and the parser likes to supply a span like
-                // that for EOF, in particular.
-
-                if lo.col_display == hi.col_display && lo.line == hi.line {
-                    hi.col_display += 1;
-                }
+                let (lo, hi) = fixup_lo_hi(span_label.span);
 
                 if lo.line != hi.line {
                     let ml = MultilineAnnotation {
diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs
index db289a64046..c2aa096a993 100644
--- a/compiler/rustc_feature/src/accepted.rs
+++ b/compiler/rustc_feature/src/accepted.rs
@@ -191,6 +191,8 @@ declare_features! (
     (accepted, infer_outlives_requirements, "1.30.0", Some(44493), None),
     /// Allows irrefutable patterns in `if let` and `while let` statements (RFC 2086).
     (accepted, irrefutable_let_patterns, "1.33.0", Some(44495), None),
+    /// Allows `#[instruction_set(_)]` attribute.
+    (accepted, isa_attribute, "CURRENT_RUSTC_VERSION", Some(74727), None),
     /// Allows some increased flexibility in the name resolution rules,
     /// especially around globs and shadowing (RFC 1560).
     (accepted, item_like_imports, "1.15.0", Some(35120), None),
diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs
index 7900f150048..e94e038f928 100644
--- a/compiler/rustc_feature/src/active.rs
+++ b/compiler/rustc_feature/src/active.rs
@@ -152,6 +152,8 @@ declare_features! (
     (active, anonymous_lifetime_in_impl_trait, "1.63.0", None, None),
     /// Allows identifying the `compiler_builtins` crate.
     (active, compiler_builtins, "1.13.0", None, None),
+    /// Allows writing custom MIR
+    (active, custom_mir, "1.65.0", None, None),
     /// Outputs useful `assert!` messages
     (active, generic_assert, "1.63.0", None, None),
     /// Allows using the `rust-intrinsic`'s "ABI".
@@ -427,8 +429,6 @@ declare_features! (
     (incomplete, inline_const_pat, "1.58.0", Some(76001), None),
     /// Allows using `pointer` and `reference` in intra-doc links
     (active, intra_doc_pointers, "1.51.0", Some(80896), None),
-    /// Allows `#[instruction_set(_)]` attribute
-    (active, isa_attribute, "1.48.0", Some(74727), None),
     // Allows setting the threshold for the `large_assignments` lint.
     (active, large_assignments, "1.52.0", Some(83518), None),
     /// Allows `if/while p && let q = r && ...` chains.
diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs
index 14c8e3c458c..dc3a7495684 100644
--- a/compiler/rustc_feature/src/builtin_attrs.rs
+++ b/compiler/rustc_feature/src/builtin_attrs.rs
@@ -391,6 +391,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
         DuplicatesOk, @only_local: true,
     ),
     ungated!(track_caller, Normal, template!(Word), WarnFollowing),
+    ungated!(instruction_set, Normal, template!(List: "set"), ErrorPreceding),
     gated!(
         no_sanitize, Normal,
         template!(List: "address, memory, thread"), DuplicatesOk,
@@ -452,11 +453,6 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
         optimize, Normal, template!(List: "size|speed"), ErrorPreceding, optimize_attribute,
         experimental!(optimize),
     ),
-    // RFC 2867
-    gated!(
-        instruction_set, Normal, template!(List: "set"), ErrorPreceding,
-        isa_attribute, experimental!(instruction_set)
-    ),
 
     gated!(
         ffi_returns_twice, Normal, template!(Word), WarnFollowing, experimental!(ffi_returns_twice)
@@ -814,6 +810,10 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
     rustc_attr!(TEST, rustc_polymorphize_error, Normal, template!(Word), WarnFollowing),
     rustc_attr!(TEST, rustc_def_path, Normal, template!(Word), WarnFollowing),
     rustc_attr!(TEST, rustc_mir, Normal, template!(List: "arg1, arg2, ..."), DuplicatesOk),
+    gated!(
+        custom_mir, Normal, template!(List: r#"dialect = "...", phase = "...""#),
+        ErrorFollowing, "the `#[custom_mir]` attribute is just used for the Rust test suite",
+    ),
     rustc_attr!(TEST, rustc_dump_program_clauses, Normal, template!(Word), WarnFollowing),
     rustc_attr!(TEST, rustc_dump_env_program_clauses, Normal, template!(Word), WarnFollowing),
     rustc_attr!(TEST, rustc_object_lifetime_default, Normal, template!(Word), WarnFollowing),
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index ef00c1ffc30..82e260d158b 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -388,6 +388,8 @@ impl<'hir> GenericArgs<'hir> {
     }
 
     #[inline]
+    /// This function returns the number of type and const generic params.
+    /// It should only be used for diagnostics.
     pub fn num_generic_params(&self) -> usize {
         self.args.iter().filter(|arg| !matches!(arg, GenericArg::Lifetime(_))).count()
     }
diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs
index 9ad1d2bc542..4518cf30acd 100644
--- a/compiler/rustc_hir_analysis/src/astconv/mod.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs
@@ -274,7 +274,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             item_segment.args(),
             item_segment.infer_args,
             None,
-            None,
+            ty::BoundConstness::NotConst,
         );
         if let Some(b) = item_segment.args().bindings.first() {
             Self::prohibit_assoc_ty_binding(self.tcx(), b.span);
@@ -324,7 +324,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         generic_args: &'a hir::GenericArgs<'_>,
         infer_args: bool,
         self_ty: Option<Ty<'tcx>>,
-        constness: Option<ty::BoundConstness>,
+        constness: ty::BoundConstness,
     ) -> (SubstsRef<'tcx>, GenericArgCountResult) {
         // If the type is parameterized by this region, then replace this
         // region with the current anon region binding (in other words,
@@ -538,7 +538,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             &mut substs_ctx,
         );
 
-        if let Some(ty::BoundConstness::ConstIfConst) = constness
+        if let ty::BoundConstness::ConstIfConst = constness
             && generics.has_self && !tcx.has_attr(def_id, sym::const_trait)
         {
             tcx.sess.emit_err(crate::errors::ConstBoundForNonConstTrait { span } );
@@ -611,7 +611,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             item_segment.args(),
             item_segment.infer_args,
             None,
-            None,
+            ty::BoundConstness::NotConst,
         );
 
         if let Some(b) = item_segment.args().bindings.first() {
@@ -641,7 +641,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             self_ty,
             trait_ref.path.segments.last().unwrap(),
             true,
-            Some(constness),
+            constness,
         )
     }
 
@@ -668,7 +668,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             args,
             infer_args,
             Some(self_ty),
-            Some(constness),
+            constness,
         );
 
         let tcx = self.tcx();
@@ -798,7 +798,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         self_ty: Ty<'tcx>,
         trait_segment: &hir::PathSegment<'_>,
         is_impl: bool,
-        constness: Option<ty::BoundConstness>,
+        constness: ty::BoundConstness,
     ) -> ty::TraitRef<'tcx> {
         let (substs, _) = self.create_substs_for_ast_trait_ref(
             span,
@@ -822,7 +822,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         self_ty: Ty<'tcx>,
         trait_segment: &'a hir::PathSegment<'a>,
         is_impl: bool,
-        constness: Option<ty::BoundConstness>,
+        constness: ty::BoundConstness,
     ) -> (SubstsRef<'tcx>, GenericArgCountResult) {
         self.complain_about_internal_fn_trait(span, trait_def_id, trait_segment, is_impl);
 
@@ -1201,7 +1201,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                     (_, _) => {
                         let got = if let Some(_) = term.ty() { "type" } else { "constant" };
                         let expected = def_kind.descr(assoc_item_def_id);
-                        tcx.sess
+                        let reported = tcx
+                            .sess
                             .struct_span_err(
                                 binding.span,
                                 &format!("expected {expected} bound, found {got}"),
@@ -1212,11 +1213,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                             )
                             .emit();
                         term = match def_kind {
-                            hir::def::DefKind::AssocTy => tcx.ty_error().into(),
+                            hir::def::DefKind::AssocTy => {
+                                tcx.ty_error_with_guaranteed(reported).into()
+                            }
                             hir::def::DefKind::AssocConst => tcx
-                                .const_error(
+                                .const_error_with_guaranteed(
                                     tcx.bound_type_of(assoc_item_def_id)
                                         .subst(tcx, projection_ty.skip_binder().substs),
+                                    reported,
                                 )
                                 .into(),
                             _ => unreachable!(),
@@ -1334,8 +1338,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 .map(|&(trait_ref, _, _)| trait_ref.def_id())
                 .find(|&trait_ref| tcx.is_trait_alias(trait_ref))
                 .map(|trait_ref| tcx.def_span(trait_ref));
-            tcx.sess.emit_err(TraitObjectDeclaredWithNoTraits { span, trait_alias_span });
-            return tcx.ty_error();
+            let reported =
+                tcx.sess.emit_err(TraitObjectDeclaredWithNoTraits { span, trait_alias_span });
+            return tcx.ty_error_with_guaranteed(reported);
         }
 
         // Check that there are no gross object safety violations;
@@ -1345,14 +1350,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             let object_safety_violations =
                 astconv_object_safety_violations(tcx, item.trait_ref().def_id());
             if !object_safety_violations.is_empty() {
-                report_object_safety_error(
+                let reported = report_object_safety_error(
                     tcx,
                     span,
                     item.trait_ref().def_id(),
                     &object_safety_violations,
                 )
                 .emit();
-                return tcx.ty_error();
+                return tcx.ty_error_with_guaranteed(reported);
             }
         }
 
@@ -2112,13 +2117,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 "Type"
             };
 
-            self.report_ambiguous_associated_type(
+            let reported = self.report_ambiguous_associated_type(
                 span,
                 type_name,
                 &path_str,
                 item_segment.ident.name,
             );
-            return tcx.ty_error();
+            return tcx.ty_error_with_guaranteed(reported)
         };
 
         debug!("qpath_to_ty: self_type={:?}", self_ty);
@@ -2129,7 +2134,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             self_ty,
             trait_segment,
             false,
-            Some(constness),
+            constness,
         );
 
         let item_substs = self.create_substs_for_associated_item(
@@ -2560,8 +2565,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                     {
                         err.span_note(impl_.self_ty.span, "not a concrete type");
                     }
-                    err.emit();
-                    tcx.ty_error()
+                    tcx.ty_error_with_guaranteed(err.emit())
                 } else {
                     self.normalize_ty(span, ty)
                 }
@@ -2700,7 +2704,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                     &GenericArgs::none(),
                     true,
                     None,
-                    None,
+                    ty::BoundConstness::NotConst,
                 );
                 EarlyBinder(self.normalize_ty(span, tcx.at(span).type_of(def_id)))
                     .subst(tcx, substs)
@@ -2976,7 +2980,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
     ) {
         for br in referenced_regions.difference(&constrained_regions) {
             let br_name = match *br {
-                ty::BrNamed(_, kw::UnderscoreLifetime) | ty::BrAnon(_) | ty::BrEnv => {
+                ty::BrNamed(_, kw::UnderscoreLifetime) | ty::BrAnon(..) | ty::BrEnv => {
                     "an anonymous lifetime".to_string()
                 }
                 ty::BrNamed(_, name) => format!("lifetime `{}`", name),
@@ -2984,7 +2988,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
 
             let mut err = generate_err(&br_name);
 
-            if let ty::BrNamed(_, kw::UnderscoreLifetime) | ty::BrAnon(_) = *br {
+            if let ty::BrNamed(_, kw::UnderscoreLifetime) | ty::BrAnon(..) = *br {
                 // The only way for an anonymous lifetime to wind up
                 // in the return type but **also** be unconstrained is
                 // if it only appears in "associated types" in the
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index 133bbd52b91..0ba5e615101 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -26,6 +26,7 @@ use rustc_session::lint::builtin::{UNINHABITED_STATIC, UNSUPPORTED_CALLING_CONVE
 use rustc_span::symbol::sym;
 use rustc_span::{self, Span};
 use rustc_target::spec::abi::Abi;
+use rustc_trait_selection::traits::error_reporting::on_unimplemented::OnUnimplementedDirective;
 use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _;
 use rustc_trait_selection::traits::{self, ObligationCtxt};
 
@@ -471,7 +472,7 @@ fn check_opaque_meets_bounds<'tcx>(
     // version.
     let errors = ocx.select_all_or_error();
     if !errors.is_empty() {
-        infcx.err_ctxt().report_fulfillment_errors(&errors, None, false);
+        infcx.err_ctxt().report_fulfillment_errors(&errors, None);
     }
     match origin {
         // Checked when type checking the function containing them.
@@ -655,7 +656,7 @@ fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, id: hir::ItemId) {
 
 pub(super) fn check_on_unimplemented(tcx: TyCtxt<'_>, item: &hir::Item<'_>) {
     // an error would be reported if this fails.
-    let _ = traits::OnUnimplementedDirective::of_item(tcx, item.owner_id.to_def_id());
+    let _ = OnUnimplementedDirective::of_item(tcx, item.owner_id.to_def_id());
 }
 
 pub(super) fn check_specialization_validity<'tcx>(
diff --git a/compiler/rustc_hir_analysis/src/check/compare_method.rs b/compiler/rustc_hir_analysis/src/check/compare_method.rs
index c6b497e9b9f..04bf7c83b32 100644
--- a/compiler/rustc_hir_analysis/src/check/compare_method.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_method.rs
@@ -1,7 +1,7 @@
 use super::potentially_plural_count;
 use crate::errors::LifetimesOrBoundsMismatchOnTrait;
 use hir::def_id::{DefId, LocalDefId};
-use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_data_structures::fx::{FxHashMap, FxIndexSet};
 use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticId, ErrorGuaranteed};
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
@@ -256,7 +256,7 @@ fn compare_predicate_entailment<'tcx>(
     // Compute placeholder form of impl and trait method tys.
     let tcx = infcx.tcx;
 
-    let mut wf_tys = FxHashSet::default();
+    let mut wf_tys = FxIndexSet::default();
 
     let impl_sig = infcx.replace_bound_vars_with_fresh_vars(
         impl_m_span,
@@ -405,7 +405,7 @@ fn compare_predicate_entailment<'tcx>(
     // version.
     let errors = ocx.select_all_or_error();
     if !errors.is_empty() {
-        let reported = infcx.err_ctxt().report_fulfillment_errors(&errors, None, false);
+        let reported = infcx.err_ctxt().report_fulfillment_errors(&errors, None);
         return Err(reported);
     }
 
@@ -479,7 +479,7 @@ pub fn collect_trait_impl_trait_tys<'tcx>(
     let trait_sig = ocx.normalize(norm_cause.clone(), param_env, unnormalized_trait_sig);
     let trait_return_ty = trait_sig.output();
 
-    let wf_tys = FxHashSet::from_iter(
+    let wf_tys = FxIndexSet::from_iter(
         unnormalized_trait_sig.inputs_and_output.iter().chain(trait_sig.inputs_and_output.iter()),
     );
 
@@ -538,7 +538,7 @@ pub fn collect_trait_impl_trait_tys<'tcx>(
     // RPITs.
     let errors = ocx.select_all_or_error();
     if !errors.is_empty() {
-        let reported = infcx.err_ctxt().report_fulfillment_errors(&errors, None, false);
+        let reported = infcx.err_ctxt().report_fulfillment_errors(&errors, None);
         return Err(reported);
     }
 
@@ -611,11 +611,11 @@ pub fn collect_trait_impl_trait_tys<'tcx>(
                 collected_tys.insert(def_id, ty);
             }
             Err(err) => {
-                tcx.sess.delay_span_bug(
+                let reported = tcx.sess.delay_span_bug(
                     return_span,
                     format!("could not fully resolve: {ty} => {err:?}"),
                 );
-                collected_tys.insert(def_id, tcx.ty_error());
+                collected_tys.insert(def_id, tcx.ty_error_with_guaranteed(reported));
             }
         }
     }
@@ -1431,7 +1431,7 @@ pub(crate) fn raw_compare_const_impl<'tcx>(
     // version.
     let errors = ocx.select_all_or_error();
     if !errors.is_empty() {
-        return Err(infcx.err_ctxt().report_fulfillment_errors(&errors, None, false));
+        return Err(infcx.err_ctxt().report_fulfillment_errors(&errors, None));
     }
 
     // FIXME return `ErrorReported` if region obligations error?
@@ -1549,7 +1549,7 @@ fn compare_type_predicate_entailment<'tcx>(
     // version.
     let errors = ocx.select_all_or_error();
     if !errors.is_empty() {
-        let reported = infcx.err_ctxt().report_fulfillment_errors(&errors, None, false);
+        let reported = infcx.err_ctxt().report_fulfillment_errors(&errors, None);
         return Err(reported);
     }
 
@@ -1769,7 +1769,7 @@ pub fn check_type_bounds<'tcx>(
     // version.
     let errors = ocx.select_all_or_error();
     if !errors.is_empty() {
-        let reported = infcx.err_ctxt().report_fulfillment_errors(&errors, None, false);
+        let reported = infcx.err_ctxt().report_fulfillment_errors(&errors, None);
         return Err(reported);
     }
 
diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
index 609095c9cea..69e54b41d4c 100644
--- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs
+++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
@@ -134,15 +134,18 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
     let name_str = intrinsic_name.as_str();
 
     let bound_vars = tcx.mk_bound_variable_kinds(
-        [ty::BoundVariableKind::Region(ty::BrAnon(0)), ty::BoundVariableKind::Region(ty::BrEnv)]
-            .iter()
-            .copied(),
+        [
+            ty::BoundVariableKind::Region(ty::BrAnon(0, None)),
+            ty::BoundVariableKind::Region(ty::BrEnv),
+        ]
+        .iter()
+        .copied(),
     );
     let mk_va_list_ty = |mutbl| {
         tcx.lang_items().va_list().map(|did| {
             let region = tcx.mk_region(ty::ReLateBound(
                 ty::INNERMOST,
-                ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon(0) },
+                ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon(0, None) },
             ));
             let env_region = tcx.mk_region(ty::ReLateBound(
                 ty::INNERMOST,
@@ -364,7 +367,8 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
                 );
                 let discriminant_def_id = assoc_items[0];
 
-                let br = ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon(0) };
+                let br =
+                    ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon(0, None) };
                 (
                     1,
                     vec![
@@ -418,7 +422,8 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
             sym::nontemporal_store => (1, vec![tcx.mk_mut_ptr(param(0)), param(0)], tcx.mk_unit()),
 
             sym::raw_eq => {
-                let br = ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon(0) };
+                let br =
+                    ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon(0, None) };
                 let param_ty =
                     tcx.mk_imm_ref(tcx.mk_region(ty::ReLateBound(ty::INNERMOST, br)), param(0));
                 (1, vec![param_ty; 2], tcx.types.bool)
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index 0117bdd0ba8..8a70f41c8a8 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -1,7 +1,7 @@
 use crate::constrained_generic_params::{identify_constrained_generic_params, Parameter};
 use hir::def::DefKind;
 use rustc_ast as ast;
-use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
 use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed};
 use rustc_hir as hir;
 use rustc_hir::def_id::{DefId, LocalDefId};
@@ -21,6 +21,7 @@ use rustc_middle::ty::{GenericArgKind, InternalSubsts};
 use rustc_session::parse::feature_err;
 use rustc_span::symbol::{sym, Ident, Symbol};
 use rustc_span::{Span, DUMMY_SP};
+use rustc_target::spec::abi::Abi;
 use rustc_trait_selection::autoderef::Autoderef;
 use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
 use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _;
@@ -104,7 +105,7 @@ pub(super) fn enter_wf_checking_ctxt<'tcx, F>(
     f(&mut wfcx);
     let errors = wfcx.select_all_or_error();
     if !errors.is_empty() {
-        infcx.err_ctxt().report_fulfillment_errors(&errors, None, false);
+        infcx.err_ctxt().report_fulfillment_errors(&errors, None);
         return;
     }
 
@@ -411,7 +412,7 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, associated_items: &[hir::TraitItemRe
                                 .iter()
                                 .copied()
                                 .collect::<Vec<_>>(),
-                            &FxHashSet::default(),
+                            &FxIndexSet::default(),
                             gat_def_id.def_id,
                             gat_generics,
                         )
@@ -461,10 +462,10 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, associated_items: &[hir::TraitItemRe
             .into_iter()
             .filter(|clause| match clause.kind().skip_binder() {
                 ty::PredicateKind::RegionOutlives(ty::OutlivesPredicate(a, b)) => {
-                    !region_known_to_outlive(tcx, gat_hir, param_env, &FxHashSet::default(), a, b)
+                    !region_known_to_outlive(tcx, gat_hir, param_env, &FxIndexSet::default(), a, b)
                 }
                 ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(a, b)) => {
-                    !ty_known_to_outlive(tcx, gat_hir, param_env, &FxHashSet::default(), a, b)
+                    !ty_known_to_outlive(tcx, gat_hir, param_env, &FxIndexSet::default(), a, b)
                 }
                 _ => bug!("Unexpected PredicateKind"),
             })
@@ -546,7 +547,7 @@ fn gather_gat_bounds<'tcx, T: TypeFoldable<'tcx>>(
     param_env: ty::ParamEnv<'tcx>,
     item_hir: hir::HirId,
     to_check: T,
-    wf_tys: &FxHashSet<Ty<'tcx>>,
+    wf_tys: &FxIndexSet<Ty<'tcx>>,
     gat_def_id: LocalDefId,
     gat_generics: &'tcx ty::Generics,
 ) -> Option<FxHashSet<ty::Predicate<'tcx>>> {
@@ -653,7 +654,7 @@ fn ty_known_to_outlive<'tcx>(
     tcx: TyCtxt<'tcx>,
     id: hir::HirId,
     param_env: ty::ParamEnv<'tcx>,
-    wf_tys: &FxHashSet<Ty<'tcx>>,
+    wf_tys: &FxIndexSet<Ty<'tcx>>,
     ty: Ty<'tcx>,
     region: ty::Region<'tcx>,
 ) -> bool {
@@ -670,7 +671,7 @@ fn region_known_to_outlive<'tcx>(
     tcx: TyCtxt<'tcx>,
     id: hir::HirId,
     param_env: ty::ParamEnv<'tcx>,
-    wf_tys: &FxHashSet<Ty<'tcx>>,
+    wf_tys: &FxIndexSet<Ty<'tcx>>,
     region_a: ty::Region<'tcx>,
     region_b: ty::Region<'tcx>,
 ) -> bool {
@@ -694,7 +695,7 @@ fn resolve_regions_with_wf_tys<'tcx>(
     tcx: TyCtxt<'tcx>,
     id: hir::HirId,
     param_env: ty::ParamEnv<'tcx>,
-    wf_tys: &FxHashSet<Ty<'tcx>>,
+    wf_tys: &FxIndexSet<Ty<'tcx>>,
     add_constraints: impl for<'a> FnOnce(&'a InferCtxt<'tcx>, &'a RegionBoundPairs<'tcx>),
 ) -> bool {
     // Unfortunately, we have to use a new `InferCtxt` each call, because
@@ -1542,6 +1543,33 @@ fn check_fn_or_method<'tcx>(
         sig.output(),
         hir_decl.output.span(),
     );
+
+    if sig.abi == Abi::RustCall {
+        let span = tcx.def_span(def_id);
+        let has_implicit_self = hir_decl.implicit_self != hir::ImplicitSelfKind::None;
+        let mut inputs = sig.inputs().iter().skip(if has_implicit_self { 1 } else { 0 });
+        // Check that the argument is a tuple
+        if let Some(ty) = inputs.next() {
+            wfcx.register_bound(
+                ObligationCause::new(span, wfcx.body_id, ObligationCauseCode::RustCall),
+                wfcx.param_env,
+                *ty,
+                tcx.require_lang_item(hir::LangItem::Tuple, Some(span)),
+            );
+        } else {
+            tcx.sess.span_err(
+                hir_decl.inputs.last().map_or(span, |input| input.span),
+                "functions with the \"rust-call\" ABI must take a single non-self tuple argument",
+            );
+        }
+        // No more inputs other than the `self` type and the tuple type
+        if inputs.next().is_some() {
+            tcx.sess.span_err(
+                hir_decl.inputs.last().map_or(span, |input| input.span),
+                "functions with the \"rust-call\" ABI must take a single non-self tuple argument",
+            );
+        }
+    }
 }
 
 /// Basically `check_associated_type_bounds`, but separated for now and should be
@@ -1680,8 +1708,7 @@ fn receiver_is_valid<'tcx>(
         return true;
     }
 
-    let mut autoderef =
-        Autoderef::new(infcx, wfcx.param_env, wfcx.body_id, span, receiver_ty, span);
+    let mut autoderef = Autoderef::new(infcx, wfcx.param_env, wfcx.body_id, span, receiver_ty);
 
     // The `arbitrary_self_types` feature allows raw pointer receivers like `self: *const Self`.
     if arbitrary_self_types_enabled {
diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs
index b6c91d425df..6f74ef3ccad 100644
--- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs
@@ -321,7 +321,7 @@ fn visit_implementation_of_dispatch_from_dyn<'tcx>(tcx: TyCtxt<'tcx>, impl_did:
                     }),
                 );
                 if !errors.is_empty() {
-                    infcx.err_ctxt().report_fulfillment_errors(&errors, None, false);
+                    infcx.err_ctxt().report_fulfillment_errors(&errors, None);
                 }
 
                 // Finally, resolve all regions.
@@ -561,7 +561,7 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUn
         predicate_for_trait_def(tcx, param_env, cause, trait_def_id, 0, source, &[target.into()]);
     let errors = traits::fully_solve_obligation(&infcx, predicate);
     if !errors.is_empty() {
-        infcx.err_ctxt().report_fulfillment_errors(&errors, None, false);
+        infcx.err_ctxt().report_fulfillment_errors(&errors, None);
     }
 
     // Finally, resolve all regions.
diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs
index 25faacadf3d..4bca16c3a1c 100644
--- a/compiler/rustc_hir_analysis/src/collect.rs
+++ b/compiler/rustc_hir_analysis/src/collect.rs
@@ -512,8 +512,7 @@ impl<'tcx> AstConv<'tcx> for ItemCtxt<'tcx> {
                 }
                 _ => {}
             }
-            err.emit();
-            self.tcx().ty_error()
+            self.tcx().ty_error_with_guaranteed(err.emit())
         }
     }
 
diff --git a/compiler/rustc_hir_analysis/src/collect/lifetimes.rs b/compiler/rustc_hir_analysis/src/collect/lifetimes.rs
index 3d07f3fbc67..c64177eea3f 100644
--- a/compiler/rustc_hir_analysis/src/collect/lifetimes.rs
+++ b/compiler/rustc_hir_analysis/src/collect/lifetimes.rs
@@ -18,7 +18,7 @@ use rustc_middle::bug;
 use rustc_middle::hir::map::Map;
 use rustc_middle::hir::nested_filter;
 use rustc_middle::middle::resolve_lifetime::*;
-use rustc_middle::ty::{self, DefIdTree, TyCtxt};
+use rustc_middle::ty::{self, DefIdTree, TyCtxt, TypeSuperVisitable, TypeVisitor};
 use rustc_span::def_id::DefId;
 use rustc_span::symbol::{sym, Ident};
 use rustc_span::Span;
@@ -1781,7 +1781,7 @@ fn is_late_bound_map(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<&FxIndexSet<
 
     let mut late_bound = FxIndexSet::default();
 
-    let mut constrained_by_input = ConstrainedCollector::default();
+    let mut constrained_by_input = ConstrainedCollector { regions: Default::default(), tcx };
     for arg_ty in decl.inputs {
         constrained_by_input.visit_ty(arg_ty);
     }
@@ -1834,12 +1834,65 @@ fn is_late_bound_map(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<&FxIndexSet<
     debug!(?late_bound);
     return Some(tcx.arena.alloc(late_bound));
 
-    #[derive(Default)]
-    struct ConstrainedCollector {
+    /// Visits a `ty::Ty` collecting information about what generic parameters are constrained.
+    ///
+    /// The visitor does not operate on `hir::Ty` so that it can be called on the rhs of a `type Alias<...> = ...;`
+    /// which may live in a separate crate so there would not be any hir available. Instead we use the `type_of`
+    /// query to obtain a `ty::Ty` which will be present even in cross crate scenarios. It also naturally
+    /// handles cycle detection as we go through the query system.
+    ///
+    /// This is necessary in the first place for the following case:
+    /// ```
+    /// type Alias<'a, T> = <T as Trait<'a>>::Assoc;
+    /// fn foo<'a>(_: Alias<'a, ()>) -> Alias<'a, ()> { ... }
+    /// ```
+    ///
+    /// If we conservatively considered `'a` unconstrained then we could break users who had written code before
+    /// we started correctly handling aliases. If we considered `'a` constrained then it would become late bound
+    /// causing an error during astconv as the `'a` is not constrained by the input type `<() as Trait<'a>>::Assoc`
+    /// but appears in the output type `<() as Trait<'a>>::Assoc`.
+    ///
+    /// We must therefore "look into" the `Alias` to see whether we should consider `'a` constrained or not.
+    ///
+    /// See #100508 #85533 #47511 for additional context
+    struct ConstrainedCollectorPostAstConv {
+        arg_is_constrained: Box<[bool]>,
+    }
+
+    use std::ops::ControlFlow;
+    use ty::Ty;
+    impl<'tcx> TypeVisitor<'tcx> for ConstrainedCollectorPostAstConv {
+        fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<!> {
+            match t.kind() {
+                ty::Param(param_ty) => {
+                    self.arg_is_constrained[param_ty.index as usize] = true;
+                }
+                ty::Projection(_) => return ControlFlow::Continue(()),
+                _ => (),
+            }
+            t.super_visit_with(self)
+        }
+
+        fn visit_const(&mut self, _: ty::Const<'tcx>) -> ControlFlow<!> {
+            ControlFlow::Continue(())
+        }
+
+        fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<!> {
+            debug!("r={:?}", r.kind());
+            if let ty::RegionKind::ReEarlyBound(region) = r.kind() {
+                self.arg_is_constrained[region.index as usize] = true;
+            }
+
+            ControlFlow::Continue(())
+        }
+    }
+
+    struct ConstrainedCollector<'tcx> {
+        tcx: TyCtxt<'tcx>,
         regions: FxHashSet<LocalDefId>,
     }
 
-    impl<'v> Visitor<'v> for ConstrainedCollector {
+    impl<'v> Visitor<'v> for ConstrainedCollector<'_> {
         fn visit_ty(&mut self, ty: &'v hir::Ty<'v>) {
             match ty.kind {
                 hir::TyKind::Path(
@@ -1850,6 +1903,47 @@ fn is_late_bound_map(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<&FxIndexSet<
                     // (defined above)
                 }
 
+                hir::TyKind::Path(hir::QPath::Resolved(
+                    None,
+                    hir::Path { res: Res::Def(DefKind::TyAlias, alias_def), segments, span },
+                )) => {
+                    // See comments on `ConstrainedCollectorPostAstConv` for why this arm does not just consider
+                    // substs to be unconstrained.
+                    let generics = self.tcx.generics_of(alias_def);
+                    let mut walker = ConstrainedCollectorPostAstConv {
+                        arg_is_constrained: vec![false; generics.params.len()].into_boxed_slice(),
+                    };
+                    walker.visit_ty(self.tcx.type_of(alias_def));
+
+                    match segments.last() {
+                        Some(hir::PathSegment { args: Some(args), .. }) => {
+                            let tcx = self.tcx;
+                            for constrained_arg in
+                                args.args.iter().enumerate().flat_map(|(n, arg)| {
+                                    match walker.arg_is_constrained.get(n) {
+                                        Some(true) => Some(arg),
+                                        Some(false) => None,
+                                        None => {
+                                            tcx.sess.delay_span_bug(
+                                                *span,
+                                                format!(
+                                                    "Incorrect generic arg count for alias {:?}",
+                                                    alias_def
+                                                ),
+                                            );
+                                            None
+                                        }
+                                    }
+                                })
+                            {
+                                self.visit_generic_arg(constrained_arg);
+                            }
+                        }
+                        Some(_) => (),
+                        None => bug!("Path with no segments or self type"),
+                    }
+                }
+
                 hir::TyKind::Path(hir::QPath::Resolved(None, ref path)) => {
                     // consider only the lifetimes on the final
                     // segment; I am not sure it's even currently
diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs
index c29a645eb4a..2402495c2e4 100644
--- a/compiler/rustc_hir_analysis/src/collect/type_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs
@@ -698,7 +698,7 @@ fn find_opaque_ty_constraints_for_tait(tcx: TyCtxt<'_>, def_id: LocalDefId) -> T
     }
 
     let Some(hidden) = locator.found else {
-        tcx.sess.emit_err(UnconstrainedOpaqueType {
+        let reported = tcx.sess.emit_err(UnconstrainedOpaqueType {
             span: tcx.def_span(def_id),
             name: tcx.item_name(tcx.local_parent(def_id).to_def_id()),
             what: match tcx.hir().get(scope) {
@@ -708,7 +708,7 @@ fn find_opaque_ty_constraints_for_tait(tcx: TyCtxt<'_>, def_id: LocalDefId) -> T
                 _ => "item",
             },
         });
-        return tcx.ty_error();
+        return tcx.ty_error_with_guaranteed(reported);
     };
 
     // Only check against typeck if we didn't already error
diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs
index e806e94879d..267077cdab4 100644
--- a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs
+++ b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs
@@ -155,7 +155,7 @@ fn get_impl_substs<'tcx>(
 
     let errors = ocx.select_all_or_error();
     if !errors.is_empty() {
-        ocx.infcx.err_ctxt().report_fulfillment_errors(&errors, None, false);
+        ocx.infcx.err_ctxt().report_fulfillment_errors(&errors, None);
         return None;
     }
 
diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs
index bd1a461b935..664d3a3a1db 100644
--- a/compiler/rustc_hir_analysis/src/lib.rs
+++ b/compiler/rustc_hir_analysis/src/lib.rs
@@ -173,7 +173,7 @@ fn require_same_types<'tcx>(
     match &errors[..] {
         [] => true,
         errors => {
-            infcx.err_ctxt().report_fulfillment_errors(errors, None, false);
+            infcx.err_ctxt().report_fulfillment_errors(errors, None);
             false
         }
     }
@@ -336,7 +336,7 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) {
         ocx.register_bound(cause, param_env, norm_return_ty, term_did);
         let errors = ocx.select_all_or_error();
         if !errors.is_empty() {
-            infcx.err_ctxt().report_fulfillment_errors(&errors, None, false);
+            infcx.err_ctxt().report_fulfillment_errors(&errors, None);
             error = true;
         }
         // now we can take the return type of the given main function
diff --git a/compiler/rustc_hir_typeck/src/_match.rs b/compiler/rustc_hir_typeck/src/_match.rs
index 8d39fa81165..6a4a6a5b0a5 100644
--- a/compiler/rustc_hir_typeck/src/_match.rs
+++ b/compiler/rustc_hir_typeck/src/_match.rs
@@ -1,6 +1,6 @@
 use crate::coercion::{AsCoercionSite, CoerceMany};
 use crate::{Diverges, Expectation, FnCtxt, Needs};
-use rustc_errors::{Applicability, MultiSpan};
+use rustc_errors::{Applicability, Diagnostic, MultiSpan};
 use rustc_hir::{self as hir, ExprKind};
 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use rustc_infer::traits::Obligation;
@@ -137,55 +137,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 Some(&arm.body),
                 arm_ty,
                 Some(&mut |err| {
-                    let Some(ret) = self
-                        .tcx
-                        .hir()
-                        .find_by_def_id(self.body_id.owner.def_id)
-                        .and_then(|owner| owner.fn_decl())
-                        .map(|decl| decl.output.span())
-                    else { return; };
-                    let Expectation::IsLast(stmt) = orig_expected else {
-                        return
-                    };
-                    let can_coerce_to_return_ty = match self.ret_coercion.as_ref() {
-                        Some(ret_coercion) if self.in_tail_expr => {
-                            let ret_ty = ret_coercion.borrow().expected_ty();
-                            let ret_ty = self.inh.infcx.shallow_resolve(ret_ty);
-                            self.can_coerce(arm_ty, ret_ty)
-                                && prior_arm.map_or(true, |(_, t, _)| self.can_coerce(t, ret_ty))
-                                // The match arms need to unify for the case of `impl Trait`.
-                                && !matches!(ret_ty.kind(), ty::Opaque(..))
-                        }
-                        _ => false,
-                    };
-                    if !can_coerce_to_return_ty {
-                        return;
-                    }
-
-                    let semi_span = expr.span.shrink_to_hi().with_hi(stmt.hi());
-                    let mut ret_span: MultiSpan = semi_span.into();
-                    ret_span.push_span_label(
-                        expr.span,
-                        "this could be implicitly returned but it is a statement, not a \
-                            tail expression",
-                    );
-                    ret_span
-                        .push_span_label(ret, "the `match` arms can conform to this return type");
-                    ret_span.push_span_label(
-                        semi_span,
-                        "the `match` is a statement because of this semicolon, consider \
-                            removing it",
-                    );
-                    err.span_note(
-                        ret_span,
-                        "you might have meant to return the `match` expression",
-                    );
-                    err.tool_only_span_suggestion(
-                        semi_span,
-                        "remove this semicolon",
-                        "",
-                        Applicability::MaybeIncorrect,
-                    );
+                    self.suggest_removing_semicolon_for_coerce(
+                        err,
+                        expr,
+                        orig_expected,
+                        arm_ty,
+                        prior_arm,
+                    )
                 }),
                 false,
             );
@@ -219,6 +177,71 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         coercion.complete(self)
     }
 
+    fn suggest_removing_semicolon_for_coerce(
+        &self,
+        diag: &mut Diagnostic,
+        expr: &hir::Expr<'tcx>,
+        expectation: Expectation<'tcx>,
+        arm_ty: Ty<'tcx>,
+        prior_arm: Option<(Option<hir::HirId>, Ty<'tcx>, Span)>,
+    ) {
+        let hir = self.tcx.hir();
+
+        // First, check that we're actually in the tail of a function.
+        let hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Block(block, _), .. }) =
+            hir.get(self.body_id) else { return; };
+        let Some(hir::Stmt { kind: hir::StmtKind::Semi(last_expr), .. })
+            = block.innermost_block().stmts.last() else {  return; };
+        if last_expr.hir_id != expr.hir_id {
+            return;
+        }
+
+        // Next, make sure that we have no type expectation.
+        let Some(ret) = hir
+            .find_by_def_id(self.body_id.owner.def_id)
+            .and_then(|owner| owner.fn_decl())
+            .map(|decl| decl.output.span()) else { return; };
+        let Expectation::IsLast(stmt) = expectation else {
+            return;
+        };
+
+        let can_coerce_to_return_ty = match self.ret_coercion.as_ref() {
+            Some(ret_coercion) => {
+                let ret_ty = ret_coercion.borrow().expected_ty();
+                let ret_ty = self.inh.infcx.shallow_resolve(ret_ty);
+                self.can_coerce(arm_ty, ret_ty)
+                    && prior_arm.map_or(true, |(_, ty, _)| self.can_coerce(ty, ret_ty))
+                    // The match arms need to unify for the case of `impl Trait`.
+                    && !matches!(ret_ty.kind(), ty::Opaque(..))
+            }
+            _ => false,
+        };
+        if !can_coerce_to_return_ty {
+            return;
+        }
+
+        let semi_span = expr.span.shrink_to_hi().with_hi(stmt.hi());
+        let mut ret_span: MultiSpan = semi_span.into();
+        ret_span.push_span_label(
+            expr.span,
+            "this could be implicitly returned but it is a statement, not a \
+                            tail expression",
+        );
+        ret_span.push_span_label(ret, "the `match` arms can conform to this return type");
+        ret_span.push_span_label(
+            semi_span,
+            "the `match` is a statement because of this semicolon, consider \
+                            removing it",
+        );
+        diag.span_note(ret_span, "you might have meant to return the `match` expression");
+        diag.tool_only_span_suggestion(
+            semi_span,
+            "remove this semicolon",
+            "",
+            Applicability::MaybeIncorrect,
+        );
+    }
+
     /// When the previously checked expression (the scrutinee) diverges,
     /// warn the user about the match arms being unreachable.
     fn warn_arms_when_scrutinee_diverges(&self, arms: &'tcx [hir::Arm<'tcx>]) {
diff --git a/compiler/rustc_hir_typeck/src/autoderef.rs b/compiler/rustc_hir_typeck/src/autoderef.rs
index 59c366ad7d7..41b52a4c4a9 100644
--- a/compiler/rustc_hir_typeck/src/autoderef.rs
+++ b/compiler/rustc_hir_typeck/src/autoderef.rs
@@ -12,18 +12,7 @@ use std::iter;
 
 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     pub fn autoderef(&'a self, span: Span, base_ty: Ty<'tcx>) -> Autoderef<'a, 'tcx> {
-        Autoderef::new(self, self.param_env, self.body_id, span, base_ty, span)
-    }
-
-    /// Like `autoderef`, but provides a custom `Span` to use for calls to
-    /// an overloaded `Deref` operator
-    pub fn autoderef_overloaded_span(
-        &'a self,
-        span: Span,
-        base_ty: Ty<'tcx>,
-        overloaded_span: Span,
-    ) -> Autoderef<'a, 'tcx> {
-        Autoderef::new(self, self.param_env, self.body_id, span, base_ty, overloaded_span)
+        Autoderef::new(self, self.param_env, self.body_id, span, base_ty)
     }
 
     pub fn try_overloaded_deref(
@@ -55,11 +44,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         |InferOk { value: method, obligations: o }| {
                             obligations.extend(o);
                             if let ty::Ref(region, _, mutbl) = *method.sig.output().kind() {
-                                Some(OverloadedDeref {
-                                    region,
-                                    mutbl,
-                                    span: autoderef.overloaded_span(),
-                                })
+                                Some(OverloadedDeref { region, mutbl, span: autoderef.span() })
                             } else {
                                 None
                             }
diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs
index 1b33f2f02b8..2b019c8c9b7 100644
--- a/compiler/rustc_hir_typeck/src/callee.rs
+++ b/compiler/rustc_hir_typeck/src/callee.rs
@@ -129,6 +129,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         output
     }
 
+    #[instrument(level = "debug", skip(self, call_expr, callee_expr, arg_exprs, autoderef), ret)]
     fn try_overloaded_call_step(
         &self,
         call_expr: &'tcx hir::Expr<'tcx>,
@@ -138,10 +139,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     ) -> Option<CallStep<'tcx>> {
         let adjusted_ty =
             self.structurally_resolved_type(autoderef.span(), autoderef.final_ty(false));
-        debug!(
-            "try_overloaded_call_step(call_expr={:?}, adjusted_ty={:?})",
-            call_expr, adjusted_ty
-        );
 
         // If the callee is a bare function or a closure, then we're all set.
         match *adjusted_ty.kind() {
@@ -471,6 +468,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             def_id,
         );
 
+        if fn_sig.abi == abi::Abi::RustCall {
+            let sp = arg_exprs.last().map_or(call_expr.span, |expr| expr.span);
+            if let Some(ty) = fn_sig.inputs().last().copied() {
+                self.register_bound(
+                    ty,
+                    self.tcx.require_lang_item(hir::LangItem::Tuple, Some(sp)),
+                    traits::ObligationCause::new(sp, self.body_id, traits::RustCall),
+                );
+            } else {
+                self.tcx.sess.span_err(
+                        sp,
+                        "functions with the \"rust-call\" ABI must take a single non-self tuple argument",
+                    );
+            }
+        }
+
         fn_sig.output()
     }
 
diff --git a/compiler/rustc_hir_typeck/src/check.rs b/compiler/rustc_hir_typeck/src/check.rs
index 80147d90091..3c57e33f6f7 100644
--- a/compiler/rustc_hir_typeck/src/check.rs
+++ b/compiler/rustc_hir_typeck/src/check.rs
@@ -6,13 +6,11 @@ use rustc_hir as hir;
 use rustc_hir::def::DefKind;
 use rustc_hir::intravisit::Visitor;
 use rustc_hir::lang_items::LangItem;
-use rustc_hir::{ImplicitSelfKind, ItemKind, Node};
 use rustc_hir_analysis::check::fn_maybe_err;
 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use rustc_infer::infer::RegionVariableOrigin;
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_span::def_id::LocalDefId;
-use rustc_target::spec::abi::Abi;
 use rustc_trait_selection::traits;
 use std::cell::RefCell;
 
@@ -56,41 +54,6 @@ pub(super) fn check_fn<'a, 'tcx>(
 
     fn_maybe_err(tcx, span, fn_sig.abi);
 
-    if fn_sig.abi == Abi::RustCall {
-        let expected_args = if let ImplicitSelfKind::None = decl.implicit_self { 1 } else { 2 };
-
-        let err = || {
-            let item = match tcx.hir().get(fn_id) {
-                Node::Item(hir::Item { kind: ItemKind::Fn(header, ..), .. }) => Some(header),
-                Node::ImplItem(hir::ImplItem {
-                    kind: hir::ImplItemKind::Fn(header, ..), ..
-                }) => Some(header),
-                Node::TraitItem(hir::TraitItem {
-                    kind: hir::TraitItemKind::Fn(header, ..),
-                    ..
-                }) => Some(header),
-                // Closures are RustCall, but they tuple their arguments, so shouldn't be checked
-                Node::Expr(hir::Expr { kind: hir::ExprKind::Closure { .. }, .. }) => None,
-                node => bug!("Item being checked wasn't a function/closure: {:?}", node),
-            };
-
-            if let Some(header) = item {
-                tcx.sess.span_err(header.span, "functions with the \"rust-call\" ABI must take a single non-self argument that is a tuple");
-            }
-        };
-
-        if fn_sig.inputs().len() != expected_args {
-            err()
-        } else {
-            // FIXME(CraftSpider) Add a check on parameter expansion, so we don't just make the ICE happen later on
-            //   This will probably require wide-scale changes to support a TupleKind obligation
-            //   We can't resolve this without knowing the type of the param
-            if !matches!(fn_sig.inputs()[expected_args - 1].kind(), ty::Tuple(_) | ty::Param(_)) {
-                err()
-            }
-        }
-    }
-
     if body.generator_kind.is_some() && can_be_generator.is_some() {
         let yield_ty = fcx
             .next_ty_var(TypeVariableOrigin { kind: TypeVariableOriginKind::TypeInference, span });
@@ -137,7 +100,6 @@ pub(super) fn check_fn<'a, 'tcx>(
 
     inherited.typeck_results.borrow_mut().liberated_fn_sigs_mut().insert(fn_id, fn_sig);
 
-    fcx.in_tail_expr = true;
     if let ty::Dynamic(..) = declared_ret_ty.kind() {
         // FIXME: We need to verify that the return type is `Sized` after the return expression has
         // been evaluated so that we have types available for all the nodes being returned, but that
@@ -156,7 +118,6 @@ pub(super) fn check_fn<'a, 'tcx>(
         fcx.require_type_is_sized(declared_ret_ty, decl.output.span(), traits::SizedReturnType);
         fcx.check_return_expr(&body.value, false);
     }
-    fcx.in_tail_expr = false;
 
     // We insert the deferred_generator_interiors entry after visiting the body.
     // This ensures that all nested generators appear before the entry of this generator.
diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs
index 09df50c76b7..3001e799476 100644
--- a/compiler/rustc_hir_typeck/src/closure.rs
+++ b/compiler/rustc_hir_typeck/src/closure.rs
@@ -10,6 +10,7 @@ use rustc_hir_analysis::astconv::AstConv;
 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use rustc_infer::infer::LateBoundRegionConversionTime;
 use rustc_infer::infer::{InferOk, InferResult};
+use rustc_macros::{TypeFoldable, TypeVisitable};
 use rustc_middle::ty::subst::InternalSubsts;
 use rustc_middle::ty::visit::TypeVisitable;
 use rustc_middle::ty::{self, Ty};
@@ -22,7 +23,7 @@ use std::cmp;
 use std::iter;
 
 /// What signature do we *expect* the closure to have from context?
-#[derive(Debug)]
+#[derive(Debug, Clone, TypeFoldable, TypeVisitable)]
 struct ExpectedSig<'tcx> {
     /// Span that gave us this expectation, if we know that.
     cause_span: Option<Span>,
@@ -241,9 +242,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             if expected_sig.is_none()
                 && let ty::PredicateKind::Projection(proj_predicate) = bound_predicate.skip_binder()
             {
-                expected_sig = self.deduce_sig_from_projection(
+                expected_sig = self.normalize_associated_types_in(
+                    obligation.cause.span,
+                    self.deduce_sig_from_projection(
                     Some(obligation.cause.span),
-                    bound_predicate.rebind(proj_predicate),
+                        bound_predicate.rebind(proj_predicate),
+                    ),
                 );
             }
 
diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs
index e8bf299b037..4d8ab2c1c7a 100644
--- a/compiler/rustc_hir_typeck/src/coercion.rs
+++ b/compiler/rustc_hir_typeck/src/coercion.rs
@@ -705,12 +705,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
 
                 // Object safety violations or miscellaneous.
                 Err(err) => {
-                    self.err_ctxt().report_selection_error(
-                        obligation.clone(),
-                        &obligation,
-                        &err,
-                        false,
-                    );
+                    self.err_ctxt().report_selection_error(obligation.clone(), &obligation, &err);
                     // Treat this like an obligation and follow through
                     // with the unsizing - the lack of a coercion should
                     // be silent, as it causes a type mismatch later.
@@ -1644,9 +1639,9 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
                 if visitor.ret_exprs.len() > 0 && let Some(expr) = expression {
                     self.note_unreachable_loop_return(&mut err, &expr, &visitor.ret_exprs);
                 }
-                err.emit_unless(unsized_return);
+                let reported = err.emit_unless(unsized_return);
 
-                self.final_ty = Some(fcx.tcx.ty_error());
+                self.final_ty = Some(fcx.tcx.ty_error_with_guaranteed(reported));
             }
         }
     }
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index 682dbab56bc..43669489e69 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -80,14 +80,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         // coercions from ! to `expected`.
         if ty.is_never() {
             if let Some(adjustments) = self.typeck_results.borrow().adjustments().get(expr.hir_id) {
-                self.tcx().sess.delay_span_bug(
+                let reported = self.tcx().sess.delay_span_bug(
                     expr.span,
                     "expression with never type wound up being adjusted",
                 );
                 return if let [Adjustment { kind: Adjust::NeverToAny, target }] = &adjustments[..] {
                     target.to_owned()
                 } else {
-                    self.tcx().ty_error()
+                    self.tcx().ty_error_with_guaranteed(reported)
                 };
             }
 
@@ -396,8 +396,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         {
                             err.subdiagnostic(ExprParenthesesNeeded::surrounding(*sp));
                         }
-                        err.emit();
-                        oprnd_t = tcx.ty_error();
+                        oprnd_t = tcx.ty_error_with_guaranteed(err.emit());
                     }
                 }
                 hir::UnOp::Not => {
@@ -843,7 +842,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         {
             // Point any obligations that were registered due to opaque type
             // inference at the return expression.
-            self.select_obligations_where_possible(false, |errors| {
+            self.select_obligations_where_possible(|errors| {
                 self.point_at_return_for_opaque_ty_error(errors, span, return_expr_ty);
             });
         }
@@ -1097,12 +1096,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
             // If the assignment expression itself is ill-formed, don't
             // bother emitting another error
-            if lhs_ty.references_error() || rhs_ty.references_error() {
-                err.delay_as_bug()
-            } else {
-                err.emit();
-            }
-            return self.tcx.ty_error();
+            let reported = err.emit_unless(lhs_ty.references_error() || rhs_ty.references_error());
+            return self.tcx.ty_error_with_guaranteed(reported);
         }
 
         let lhs_ty = self.check_expr_with_needs(&lhs, Needs::MutPlace);
@@ -2738,7 +2733,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 Some((index_ty, element_ty)) => {
                     // two-phase not needed because index_ty is never mutable
                     self.demand_coerce(idx, idx_t, index_ty, None, AllowTwoPhase::No);
-                    self.select_obligations_where_possible(false, |errors| {
+                    self.select_obligations_where_possible(|errors| {
                         self.point_at_index_if_possible(errors, idx.span)
                     });
                     element_ty
@@ -2777,8 +2772,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             );
                         }
                     }
-                    err.emit();
-                    self.tcx.ty_error()
+                    let reported = err.emit();
+                    self.tcx.ty_error_with_guaranteed(reported)
                 }
             }
         }
diff --git a/compiler/rustc_hir_typeck/src/fallback.rs b/compiler/rustc_hir_typeck/src/fallback.rs
index 747ecb036b2..5d44092a5f6 100644
--- a/compiler/rustc_hir_typeck/src/fallback.rs
+++ b/compiler/rustc_hir_typeck/src/fallback.rs
@@ -7,16 +7,16 @@ use rustc_data_structures::{
 use rustc_middle::ty::{self, Ty};
 
 impl<'tcx> FnCtxt<'_, 'tcx> {
-    /// Performs type inference fallback, returning true if any fallback
-    /// occurs.
-    pub(super) fn type_inference_fallback(&self) -> bool {
+    /// Performs type inference fallback, setting `FnCtxt::fallback_has_occurred`
+    /// if fallback has occurred.
+    pub(super) fn type_inference_fallback(&self) {
         debug!(
             "type-inference-fallback start obligations: {:#?}",
             self.fulfillment_cx.borrow_mut().pending_obligations()
         );
 
         // All type checking constraints were added, try to fallback unsolved variables.
-        self.select_obligations_where_possible(false, |_| {});
+        self.select_obligations_where_possible(|_| {});
 
         debug!(
             "type-inference-fallback post selection obligations: {:#?}",
@@ -26,18 +26,17 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
         // Check if we have any unsolved variables. If not, no need for fallback.
         let unsolved_variables = self.unsolved_variables();
         if unsolved_variables.is_empty() {
-            return false;
+            return;
         }
 
         let diverging_fallback = self.calculate_diverging_fallback(&unsolved_variables);
 
-        let mut fallback_has_occurred = false;
         // We do fallback in two passes, to try to generate
         // better error messages.
         // The first time, we do *not* replace opaque types.
         for ty in unsolved_variables {
             debug!("unsolved_variable = {:?}", ty);
-            fallback_has_occurred |= self.fallback_if_possible(ty, &diverging_fallback);
+            self.fallback_if_possible(ty, &diverging_fallback);
         }
 
         // We now see if we can make progress. This might cause us to
@@ -63,9 +62,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
         // If we had tried to fallback the opaque inference variable to `MyType`,
         // we will generate a confusing type-check error that does not explicitly
         // refer to opaque types.
-        self.select_obligations_where_possible(fallback_has_occurred, |_| {});
-
-        fallback_has_occurred
+        self.select_obligations_where_possible(|_| {});
     }
 
     // Tries to apply a fallback to `ty` if it is an unsolved variable.
@@ -81,12 +78,13 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
     // Fallback becomes very dubious if we have encountered
     // type-checking errors.  In that case, fallback to Error.
     //
-    // The return value indicates whether fallback has occurred.
+    // Sets `FnCtxt::fallback_has_occurred` if fallback is performed
+    // during this call.
     fn fallback_if_possible(
         &self,
         ty: Ty<'tcx>,
         diverging_fallback: &FxHashMap<Ty<'tcx>, Ty<'tcx>>,
-    ) -> bool {
+    ) {
         // Careful: we do NOT shallow-resolve `ty`. We know that `ty`
         // is an unsolved variable, and we determine its fallback
         // based solely on how it was created, not what other type
@@ -111,7 +109,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
             ty::Infer(ty::FloatVar(_)) => self.tcx.types.f64,
             _ => match diverging_fallback.get(&ty) {
                 Some(&fallback_ty) => fallback_ty,
-                None => return false,
+                None => return,
             },
         };
         debug!("fallback_if_possible(ty={:?}): defaulting to `{:?}`", ty, fallback);
@@ -122,7 +120,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
             .map(|origin| origin.span)
             .unwrap_or(rustc_span::DUMMY_SP);
         self.demand_eqtype(span, ty, fallback);
-        true
+        self.fallback_has_occurred.set(true);
     }
 
     /// The "diverging fallback" system is rather complicated. This is
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
index 7563c543d3f..6ed7a93d463 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
@@ -106,7 +106,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         // possible. This can help substantially when there are
         // indirect dependencies that don't seem worth tracking
         // precisely.
-        self.select_obligations_where_possible(false, mutate_fulfillment_errors);
+        self.select_obligations_where_possible(mutate_fulfillment_errors);
         self.resolve_vars_if_possible(ty)
     }
 
@@ -600,7 +600,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     pub(in super::super) fn resolve_generator_interiors(&self, def_id: DefId) {
         let mut generators = self.deferred_generator_interiors.borrow_mut();
         for (body_id, interior, kind) in generators.drain(..) {
-            self.select_obligations_where_possible(false, |_| {});
+            self.select_obligations_where_possible(|_| {});
             crate::generator_interior::resolve_interior(self, def_id, body_id, interior, kind);
         }
     }
@@ -611,25 +611,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         if !errors.is_empty() {
             self.adjust_fulfillment_errors_for_expr_obligation(&mut errors);
-            self.err_ctxt().report_fulfillment_errors(&errors, self.inh.body_id, false);
+            self.err_ctxt().report_fulfillment_errors(&errors, self.inh.body_id);
         }
     }
 
     /// Select as many obligations as we can at present.
     pub(in super::super) fn select_obligations_where_possible(
         &self,
-        fallback_has_occurred: bool,
         mutate_fulfillment_errors: impl Fn(&mut Vec<traits::FulfillmentError<'tcx>>),
     ) {
         let mut result = self.fulfillment_cx.borrow_mut().select_where_possible(self);
         if !result.is_empty() {
             mutate_fulfillment_errors(&mut result);
             self.adjust_fulfillment_errors_for_expr_obligation(&mut result);
-            self.err_ctxt().report_fulfillment_errors(
-                &result,
-                self.inh.body_id,
-                fallback_has_occurred,
-            );
+            self.err_ctxt().report_fulfillment_errors(&result, self.inh.body_id);
         }
     }
 
@@ -1217,9 +1212,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             }
                         }
                     }
-                    err.emit();
-
-                    return (tcx.ty_error(), res);
+                    let reported = err.emit();
+                    return (tcx.ty_error_with_guaranteed(reported), res);
                 }
             }
         } else {
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
index e1955d838f2..a7a60a19bd3 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
@@ -136,6 +136,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             tuple_arguments,
             Some(method.def_id),
         );
+
         method.sig.output()
     }
 
@@ -214,7 +215,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         "cannot use call notation; the first type parameter \
                          for the function trait is neither a tuple nor unit"
                     )
-                    .emit();
+                    .delay_as_bug();
                     (self.err_args(provided_args.len()), None)
                 }
             }
@@ -344,7 +345,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             // an "opportunistic" trait resolution of any trait bounds on
             // the call. This helps coercions.
             if check_closures {
-                self.select_obligations_where_possible(false, |_| {})
+                self.select_obligations_where_possible(|_| {})
             }
 
             // Check each argument, to satisfy the input it was provided for
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
index 72388baa261..d5e4b6de581 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
@@ -68,10 +68,6 @@ pub struct FnCtxt<'a, 'tcx> {
     /// any).
     pub(super) ret_coercion: Option<RefCell<DynamicCoerceMany<'tcx>>>,
 
-    /// Used exclusively to reduce cost of advanced evaluation used for
-    /// more helpful diagnostics.
-    pub(super) in_tail_expr: bool,
-
     /// First span of a return site that we find. Used in error messages.
     pub(super) ret_coercion_span: Cell<Option<Span>>,
 
@@ -115,6 +111,8 @@ pub struct FnCtxt<'a, 'tcx> {
     pub(super) enclosing_breakables: RefCell<EnclosingBreakables<'tcx>>,
 
     pub(super) inh: &'a Inherited<'tcx>,
+
+    pub(super) fallback_has_occurred: Cell<bool>,
 }
 
 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
@@ -128,7 +126,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             param_env,
             err_count_on_creation: inh.tcx.sess.err_count(),
             ret_coercion: None,
-            in_tail_expr: false,
             ret_coercion_span: Cell::new(None),
             resume_yield_tys: None,
             ps: Cell::new(UnsafetyState::function(hir::Unsafety::Normal, hir::CRATE_HIR_ID)),
@@ -138,6 +135,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 by_id: Default::default(),
             }),
             inh,
+            fallback_has_occurred: Cell::new(false),
         }
     }
 
@@ -159,7 +157,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     ///
     /// [`InferCtxt::err_ctxt`]: infer::InferCtxt::err_ctxt
     pub fn err_ctxt(&'a self) -> TypeErrCtxt<'a, 'tcx> {
-        TypeErrCtxt { infcx: &self.infcx, typeck_results: Some(self.typeck_results.borrow()) }
+        TypeErrCtxt {
+            infcx: &self.infcx,
+            typeck_results: Some(self.typeck_results.borrow()),
+            fallback_has_occurred: self.fallback_has_occurred.get(),
+        }
     }
 
     pub fn errors_reported_since_creation(&self) -> bool {
diff --git a/compiler/rustc_hir_typeck/src/generator_interior/mod.rs b/compiler/rustc_hir_typeck/src/generator_interior/mod.rs
index b7dd599cd43..7bbfb70f2c3 100644
--- a/compiler/rustc_hir_typeck/src/generator_interior/mod.rs
+++ b/compiler/rustc_hir_typeck/src/generator_interior/mod.rs
@@ -13,10 +13,13 @@ use rustc_hir::def_id::DefId;
 use rustc_hir::hir_id::HirIdSet;
 use rustc_hir::intravisit::{self, Visitor};
 use rustc_hir::{Arm, Expr, ExprKind, Guard, HirId, Pat, PatKind};
+use rustc_infer::infer::RegionVariableOrigin;
 use rustc_middle::middle::region::{self, Scope, ScopeData, YieldData};
-use rustc_middle::ty::{self, RvalueScopes, Ty, TyCtxt, TypeVisitable};
+use rustc_middle::ty::fold::FnMutDelegate;
+use rustc_middle::ty::{self, BoundVariableKind, RvalueScopes, Ty, TyCtxt, TypeVisitable};
 use rustc_span::symbol::sym;
 use rustc_span::Span;
+use smallvec::{smallvec, SmallVec};
 
 mod drop_ranges;
 
@@ -211,31 +214,57 @@ pub fn resolve_interior<'a, 'tcx>(
 
     debug!("types in generator {:?}, span = {:?}", types, body.value.span);
 
-    let mut counter = 0;
+    // We want to deduplicate if the lifetimes are the same modulo some non-informative counter.
+    // So, we need to actually do two passes: first by type to anonymize (preserving information
+    // required for diagnostics), then a second pass over all captured types to reassign disjoint
+    // region indices.
     let mut captured_tys = FxHashSet::default();
     let type_causes: Vec<_> = types
         .into_iter()
         .filter_map(|mut cause| {
-            // Erase regions and canonicalize late-bound regions to deduplicate as many types as we
-            // can.
+            // Replace all regions inside the generator interior with late bound regions.
+            // Note that each region slot in the types gets a new fresh late bound region,
+            // which means that none of the regions inside relate to any other, even if
+            // typeck had previously found constraints that would cause them to be related.
+
+            let mut counter = 0;
+            let mut mk_bound_region = |span| {
+                let kind = ty::BrAnon(counter, span);
+                let var = ty::BoundVar::from_u32(counter);
+                counter += 1;
+                ty::BoundRegion { var, kind }
+            };
             let ty = fcx.normalize_associated_types_in(cause.span, cause.ty);
-            let erased = fcx.tcx.erase_regions(ty);
-            if captured_tys.insert(erased) {
-                // Replace all regions inside the generator interior with late bound regions.
-                // Note that each region slot in the types gets a new fresh late bound region,
-                // which means that none of the regions inside relate to any other, even if
-                // typeck had previously found constraints that would cause them to be related.
-                let folded = fcx.tcx.fold_regions(erased, |_, current_depth| {
-                    let br = ty::BoundRegion {
-                        var: ty::BoundVar::from_u32(counter),
-                        kind: ty::BrAnon(counter),
-                    };
-                    let r = fcx.tcx.mk_region(ty::ReLateBound(current_depth, br));
-                    counter += 1;
-                    r
-                });
-
-                cause.ty = folded;
+            let ty = fcx.tcx.fold_regions(ty, |region, current_depth| {
+                let br = match region.kind() {
+                    ty::ReVar(vid) => {
+                        let origin = fcx.region_var_origin(vid);
+                        match origin {
+                            RegionVariableOrigin::EarlyBoundRegion(span, _) => {
+                                mk_bound_region(Some(span))
+                            }
+                            _ => mk_bound_region(None),
+                        }
+                    }
+                    // FIXME: these should use `BrNamed`
+                    ty::ReEarlyBound(region) => {
+                        mk_bound_region(Some(fcx.tcx.def_span(region.def_id)))
+                    }
+                    ty::ReLateBound(_, ty::BoundRegion { kind, .. })
+                    | ty::ReFree(ty::FreeRegion { bound_region: kind, .. }) => match kind {
+                        ty::BoundRegionKind::BrAnon(_, span) => mk_bound_region(span),
+                        ty::BoundRegionKind::BrNamed(def_id, _) => {
+                            mk_bound_region(Some(fcx.tcx.def_span(def_id)))
+                        }
+                        ty::BoundRegionKind::BrEnv => mk_bound_region(None),
+                    },
+                    _ => mk_bound_region(None),
+                };
+                let r = fcx.tcx.mk_region(ty::ReLateBound(current_depth, br));
+                r
+            });
+            if captured_tys.insert(ty) {
+                cause.ty = ty;
                 Some(cause)
             } else {
                 None
@@ -243,11 +272,38 @@ pub fn resolve_interior<'a, 'tcx>(
         })
         .collect();
 
+    let mut bound_vars: SmallVec<[BoundVariableKind; 4]> = smallvec![];
+    let mut counter = 0;
+    // Optimization: If there is only one captured type, then we don't actually
+    // need to fold and reindex (since the first type doesn't change).
+    let type_causes = if captured_tys.len() > 0 {
+        // Optimization: Use `replace_escaping_bound_vars_uncached` instead of
+        // `fold_regions`, since we only have late bound regions, and it skips
+        // types without bound regions.
+        fcx.tcx.replace_escaping_bound_vars_uncached(
+            type_causes,
+            FnMutDelegate {
+                regions: &mut |br| {
+                    let kind = match br.kind {
+                        ty::BrAnon(_, span) => ty::BrAnon(counter, span),
+                        _ => br.kind,
+                    };
+                    let var = ty::BoundVar::from_usize(bound_vars.len());
+                    bound_vars.push(ty::BoundVariableKind::Region(kind));
+                    counter += 1;
+                    fcx.tcx.mk_region(ty::ReLateBound(ty::INNERMOST, ty::BoundRegion { var, kind }))
+                },
+                types: &mut |b| bug!("unexpected bound ty in binder: {b:?}"),
+                consts: &mut |b, ty| bug!("unexpected bound ct in binder: {b:?} {ty}"),
+            },
+        )
+    } else {
+        type_causes
+    };
+
     // Extract type components to build the witness type.
     let type_list = fcx.tcx.mk_type_list(type_causes.iter().map(|cause| cause.ty));
-    let bound_vars = fcx.tcx.mk_bound_variable_kinds(
-        (0..counter).map(|i| ty::BoundVariableKind::Region(ty::BrAnon(i))),
-    );
+    let bound_vars = fcx.tcx.mk_bound_variable_kinds(bound_vars.iter());
     let witness =
         fcx.tcx.mk_generator_witness(ty::Binder::bind_with_vars(type_list, bound_vars.clone()));
 
diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs
index d1762598a52..183e80f2e08 100644
--- a/compiler/rustc_hir_typeck/src/lib.rs
+++ b/compiler/rustc_hir_typeck/src/lib.rs
@@ -209,6 +209,7 @@ fn diagnostic_only_typeck<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &ty::T
     typeck_with_fallback(tcx, def_id, fallback)
 }
 
+#[instrument(level = "debug", skip(tcx, fallback), ret)]
 fn typeck_with_fallback<'tcx>(
     tcx: TyCtxt<'tcx>,
     def_id: LocalDefId,
@@ -316,12 +317,12 @@ fn typeck_with_fallback<'tcx>(
             fcx
         };
 
-        let fallback_has_occurred = fcx.type_inference_fallback();
+        fcx.type_inference_fallback();
 
         // Even though coercion casts provide type hints, we check casts after fallback for
         // backwards compatibility. This makes fallback a stronger type hint than a cast coercion.
         fcx.check_casts();
-        fcx.select_obligations_where_possible(fallback_has_occurred, |_| {});
+        fcx.select_obligations_where_possible(|_| {});
 
         // Closure and generator analysis may run after fallback
         // because they don't constrain other type variables.
@@ -458,7 +459,7 @@ fn report_unexpected_variant_res(tcx: TyCtxt<'_>, res: Res, qpath: &hir::QPath<'
 /// # fn f(x: (isize, isize)) {}
 /// f((1, 2));
 /// ```
-#[derive(Clone, Eq, PartialEq)]
+#[derive(Copy, Clone, Eq, PartialEq)]
 enum TupleArgumentsFlag {
     DontTupleArguments,
     TupleArguments,
diff --git a/compiler/rustc_hir_typeck/src/method/confirm.rs b/compiler/rustc_hir_typeck/src/method/confirm.rs
index be4ea998622..d996d6ec610 100644
--- a/compiler/rustc_hir_typeck/src/method/confirm.rs
+++ b/compiler/rustc_hir_typeck/src/method/confirm.rs
@@ -151,8 +151,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
     ) -> Ty<'tcx> {
         // Commit the autoderefs by calling `autoderef` again, but this
         // time writing the results into the various typeck results.
-        let mut autoderef =
-            self.autoderef_overloaded_span(self.span, unadjusted_self_ty, self.call_expr.span);
+        let mut autoderef = self.autoderef(self.call_expr.span, unadjusted_self_ty);
         let Some((ty, n)) = autoderef.nth(pick.autoderefs) else {
             return self.tcx.ty_error_with_message(
                 rustc_span::DUMMY_SP,
diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs
index e88701685bc..3fcd073f597 100644
--- a/compiler/rustc_hir_typeck/src/method/probe.rs
+++ b/compiler/rustc_hir_typeck/src/method/probe.rs
@@ -475,10 +475,9 @@ fn method_autoderef_steps<'tcx>(
     let (ref infcx, goal, inference_vars) = tcx.infer_ctxt().build_with_canonical(DUMMY_SP, &goal);
     let ParamEnvAnd { param_env, value: self_ty } = goal;
 
-    let mut autoderef =
-        Autoderef::new(infcx, param_env, hir::CRATE_HIR_ID, DUMMY_SP, self_ty, DUMMY_SP)
-            .include_raw_pointers()
-            .silence_errors();
+    let mut autoderef = Autoderef::new(infcx, param_env, hir::CRATE_HIR_ID, DUMMY_SP, self_ty)
+        .include_raw_pointers()
+        .silence_errors();
     let mut reached_raw_pointer = false;
     let mut steps: Vec<_> = autoderef
         .by_ref()
diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs
index 04ecd2757b4..79904384220 100644
--- a/compiler/rustc_hir_typeck/src/method/suggest.rs
+++ b/compiler/rustc_hir_typeck/src/method/suggest.rs
@@ -14,19 +14,26 @@ use rustc_hir::def::DefKind;
 use rustc_hir::def_id::DefId;
 use rustc_hir::lang_items::LangItem;
 use rustc_hir::{ExprKind, Node, QPath};
-use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
+use rustc_infer::infer::{
+    type_variable::{TypeVariableOrigin, TypeVariableOriginKind},
+    RegionVariableOrigin,
+};
+use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
 use rustc_middle::traits::util::supertraits;
 use rustc_middle::ty::fast_reject::{simplify_type, TreatParams};
 use rustc_middle::ty::print::with_crate_prefix;
-use rustc_middle::ty::{self, DefIdTree, ToPredicate, Ty, TyCtxt, TypeVisitable};
+use rustc_middle::ty::{
+    self, DefIdTree, GenericArg, GenericArgKind, ToPredicate, Ty, TyCtxt, TypeVisitable,
+};
 use rustc_middle::ty::{IsSuggestable, ToPolyTraitRef};
 use rustc_span::symbol::{kw, sym, Ident};
 use rustc_span::Symbol;
 use rustc_span::{lev_distance, source_map, ExpnKind, FileName, MacroKind, Span};
+use rustc_trait_selection::traits::error_reporting::on_unimplemented::OnUnimplementedNote;
 use rustc_trait_selection::traits::error_reporting::on_unimplemented::TypeErrCtxtExt as _;
 use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
 use rustc_trait_selection::traits::{
-    FulfillmentError, Obligation, ObligationCause, ObligationCauseCode, OnUnimplementedNote,
+    FulfillmentError, Obligation, ObligationCause, ObligationCauseCode,
 };
 
 use std::cmp::Ordering;
@@ -279,7 +286,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 ) {
                     return None;
                 }
-
                 span = item_name.span;
 
                 // Don't show generic arguments when the method can't be found in any implementation (#81576).
@@ -392,28 +398,118 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     custom_span_label = true;
                 }
                 if static_candidates.len() == 1 {
-                    let ty_str =
-                        if let Some(CandidateSource::Impl(impl_did)) = static_candidates.get(0) {
-                            // When the "method" is resolved through dereferencing, we really want the
-                            // original type that has the associated function for accurate suggestions.
-                            // (#61411)
-                            let ty = tcx.at(span).type_of(*impl_did);
-                            match (&ty.peel_refs().kind(), &actual.peel_refs().kind()) {
-                                (ty::Adt(def, _), ty::Adt(def_actual, _)) if def == def_actual => {
-                                    // Use `actual` as it will have more `substs` filled in.
-                                    self.ty_to_value_string(actual.peel_refs())
+                    let mut has_unsuggestable_args = false;
+                    let ty_str = if let Some(CandidateSource::Impl(impl_did)) =
+                        static_candidates.get(0)
+                    {
+                        // When the "method" is resolved through dereferencing, we really want the
+                        // original type that has the associated function for accurate suggestions.
+                        // (#61411)
+                        let ty = tcx.at(span).type_of(*impl_did);
+                        match (&ty.peel_refs().kind(), &actual.peel_refs().kind()) {
+                            (ty::Adt(def, _), ty::Adt(def_actual, substs)) if def == def_actual => {
+                                // If there are any inferred arguments, (`{integer}`), we should replace
+                                // them with underscores to allow the compiler to infer them
+                                let infer_substs: Vec<GenericArg<'_>> = substs
+                                    .into_iter()
+                                    .map(|arg| {
+                                        if !arg.is_suggestable(tcx, true) {
+                                            has_unsuggestable_args = true;
+                                            match arg.unpack() {
+                                            GenericArgKind::Lifetime(_) => self
+                                                .next_region_var(RegionVariableOrigin::MiscVariable(
+                                                    rustc_span::DUMMY_SP,
+                                                ))
+                                                .into(),
+                                            GenericArgKind::Type(_) => self
+                                                .next_ty_var(TypeVariableOrigin {
+                                                    span: rustc_span::DUMMY_SP,
+                                                    kind: TypeVariableOriginKind::MiscVariable,
+                                                })
+                                                .into(),
+                                            GenericArgKind::Const(arg) => self
+                                                .next_const_var(
+                                                    arg.ty(),
+                                                    ConstVariableOrigin {
+                                                        span: rustc_span::DUMMY_SP,
+                                                        kind: ConstVariableOriginKind::MiscVariable,
+                                                    },
+                                                )
+                                                .into(),
+                                            }
+                                        } else {
+                                            arg
+                                        }
+                                    })
+                                    .collect::<Vec<_>>();
+
+                                tcx.value_path_str_with_substs(
+                                    def_actual.did(),
+                                    tcx.intern_substs(&infer_substs),
+                                )
+                            }
+                            _ => self.ty_to_value_string(ty.peel_refs()),
+                        }
+                    } else {
+                        self.ty_to_value_string(actual.peel_refs())
+                    };
+                    if let SelfSource::MethodCall(_) = source {
+                        let first_arg = if let Some(CandidateSource::Impl(impl_did)) = static_candidates.get(0) &&
+                            let Some(assoc) = self.associated_value(*impl_did, item_name) {
+                            let sig = self.tcx.fn_sig(assoc.def_id);
+                            if let Some(first) = sig.inputs().skip_binder().get(0) {
+                                if first.peel_refs() == rcvr_ty.peel_refs() {
+                                    None
+                                } else {
+                                    Some(if first.is_region_ptr() {
+                                        if first.is_mutable_ptr() { "&mut " } else { "&" }
+                                    } else {
+                                        ""
+                                    })
                                 }
-                                _ => self.ty_to_value_string(ty.peel_refs()),
+                            } else {
+                                None
                             }
                         } else {
-                            self.ty_to_value_string(actual.peel_refs())
+                            None
+                        };
+                        let mut applicability = Applicability::MachineApplicable;
+                        let args = if let Some((receiver, args)) = args {
+                            // The first arg is the same kind as the receiver
+                            let explicit_args = if first_arg.is_some() {
+                                std::iter::once(receiver).chain(args.iter()).collect::<Vec<_>>()
+                            } else {
+                                // There is no `Self` kind to infer the arguments from
+                                if has_unsuggestable_args {
+                                    applicability = Applicability::HasPlaceholders;
+                                }
+                                args.iter().collect()
+                            };
+                            format!(
+                                "({}{})",
+                                first_arg.unwrap_or(""),
+                                explicit_args
+                                    .iter()
+                                    .map(|arg| tcx
+                                        .sess
+                                        .source_map()
+                                        .span_to_snippet(arg.span)
+                                        .unwrap_or_else(|_| {
+                                            applicability = Applicability::HasPlaceholders;
+                                            "_".to_owned()
+                                        }))
+                                    .collect::<Vec<_>>()
+                                    .join(", "),
+                            )
+                        } else {
+                            applicability = Applicability::HasPlaceholders;
+                            "(...)".to_owned()
                         };
-                    if let SelfSource::MethodCall(expr) = source {
                         err.span_suggestion(
-                            expr.span.to(span),
+                            sugg_span,
                             "use associated function syntax instead",
-                            format!("{}::{}", ty_str, item_name),
-                            Applicability::MachineApplicable,
+                            format!("{}::{}{}", ty_str, item_name, args),
+                            applicability,
                         );
                     } else {
                         err.help(&format!("try with `{}::{}`", ty_str, item_name,));
@@ -1826,7 +1922,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     /// Print out the type for use in value namespace.
     fn ty_to_value_string(&self, ty: Ty<'tcx>) -> String {
         match ty.kind() {
-            ty::Adt(def, substs) => format!("{}", ty::Instance::new(def.did(), substs)),
+            ty::Adt(def, substs) => self.tcx.def_path_str_with_substs(def.did(), substs),
             _ => self.ty_to_string(ty),
         }
     }
diff --git a/compiler/rustc_hir_typeck/src/op.rs b/compiler/rustc_hir_typeck/src/op.rs
index 8598369e884..38b3dd218a9 100644
--- a/compiler/rustc_hir_typeck/src/op.rs
+++ b/compiler/rustc_hir_typeck/src/op.rs
@@ -529,8 +529,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         }
                     }
                 }
-                err.emit();
-                self.tcx.ty_error()
+                let reported = err.emit();
+                self.tcx.ty_error_with_guaranteed(reported)
             }
         };
 
@@ -772,7 +772,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         match (method, trait_did) {
             (Some(ok), _) => {
                 let method = self.register_infer_ok_obligations(ok);
-                self.select_obligations_where_possible(false, |_| {});
+                self.select_obligations_where_possible(|_| {});
                 Ok(method)
             }
             (None, None) => Err(vec![]),
diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs
index ea90da4a6dc..eb10f3e2c10 100644
--- a/compiler/rustc_hir_typeck/src/pat.rs
+++ b/compiler/rustc_hir_typeck/src/pat.rs
@@ -19,7 +19,6 @@ use rustc_span::lev_distance::find_best_match_for_name;
 use rustc_span::source_map::{Span, Spanned};
 use rustc_span::symbol::{kw, sym, Ident};
 use rustc_span::{BytePos, DUMMY_SP};
-use rustc_trait_selection::autoderef::Autoderef;
 use rustc_trait_selection::traits::{ObligationCause, Pattern};
 use ty::VariantDef;
 
@@ -1278,12 +1277,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let element_tys = tcx.mk_type_list(element_tys_iter);
         let pat_ty = tcx.mk_ty(ty::Tuple(element_tys));
         if let Some(mut err) = self.demand_eqtype_pat_diag(span, expected, pat_ty, ti) {
-            err.emit();
+            let reported = err.emit();
             // Walk subpatterns with an expected type of `err` in this case to silence
             // further errors being emitted when using the bindings. #50333
-            let element_tys_iter = (0..max_len).map(|_| tcx.ty_error());
+            let element_tys_iter = (0..max_len).map(|_| tcx.ty_error_with_guaranteed(reported));
             for (_, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) {
-                self.check_pat(elem, tcx.ty_error(), def_bm, ti);
+                self.check_pat(elem, tcx.ty_error_with_guaranteed(reported), def_bm, ti);
             }
             tcx.mk_tup(element_tys_iter)
         } else {
@@ -2132,7 +2131,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             && let ty::Array(..) | ty::Slice(..) = ty.kind()
         {
             err.help("the semantics of slice patterns changed recently; see issue #62254");
-        } else if Autoderef::new(&self.infcx, self.param_env, self.body_id, span, expected_ty, span)
+        } else if self.autoderef(span, expected_ty)
             .any(|(ty, _)| matches!(ty.kind(), ty::Slice(..) | ty::Array(..)))
             && let (Some(span), true) = (ti.span, ti.origin_expr)
             && let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span)
diff --git a/compiler/rustc_hir_typeck/src/place_op.rs b/compiler/rustc_hir_typeck/src/place_op.rs
index ba8cf6926f3..952ea14887f 100644
--- a/compiler/rustc_hir_typeck/src/place_op.rs
+++ b/compiler/rustc_hir_typeck/src/place_op.rs
@@ -90,8 +90,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 Applicability::MachineApplicable,
             );
         }
-        err.emit();
-        Some((self.tcx.ty_error(), self.tcx.ty_error()))
+        let reported = err.emit();
+        Some((
+            self.tcx.ty_error_with_guaranteed(reported),
+            self.tcx.ty_error_with_guaranteed(reported),
+        ))
     }
 
     /// To type-check `base_expr[index_expr]`, we progressively autoderef
diff --git a/compiler/rustc_infer/src/errors/mod.rs b/compiler/rustc_infer/src/errors/mod.rs
index bb04e1c49ba..ec4eeb8caa2 100644
--- a/compiler/rustc_infer/src/errors/mod.rs
+++ b/compiler/rustc_infer/src/errors/mod.rs
@@ -180,6 +180,18 @@ pub enum SourceKindMultiSuggestion<'a> {
     },
 }
 
+#[derive(Subdiagnostic)]
+#[suggestion(
+    infer_suggest_add_let_for_letchains,
+    style = "verbose",
+    applicability = "machine-applicable",
+    code = "let "
+)]
+pub(crate) struct SuggAddLetForLetChains {
+    #[primary_span]
+    pub span: Span,
+}
+
 impl<'a> SourceKindMultiSuggestion<'a> {
     pub fn new_fully_qualified(
         span: Span,
diff --git a/compiler/rustc_infer/src/errors/note_and_explain.rs b/compiler/rustc_infer/src/errors/note_and_explain.rs
index 6a29d85627a..7aaa5ce2f42 100644
--- a/compiler/rustc_infer/src/errors/note_and_explain.rs
+++ b/compiler/rustc_infer/src/errors/note_and_explain.rs
@@ -89,10 +89,13 @@ impl<'a> DescriptionCtx<'a> {
                             };
                             me.span = Some(sp);
                         }
-                        ty::BrAnon(idx) => {
+                        ty::BrAnon(idx, span) => {
                             me.kind = "anon_num_here";
                             me.num_arg = idx+1;
-                            me.span = Some(tcx.def_span(scope));
+                            me.span = match span {
+                                Some(_) => span,
+                                None => Some(tcx.def_span(scope)),
+                            }
                         },
                         _ => {
                             me.kind = "defined_here_reg";
diff --git a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
index 365b4b1fccd..3dc0d60b1eb 100644
--- a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
+++ b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
@@ -495,7 +495,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Canonicalizer<'cx, 'tcx> {
             }
             ty::ConstKind::Bound(debruijn, _) => {
                 if debruijn >= self.binder_index {
-                    bug!("escaping bound type during canonicalization")
+                    bug!("escaping bound const during canonicalization")
                 } else {
                     return ct;
                 }
@@ -738,7 +738,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
         r: ty::Region<'tcx>,
     ) -> ty::Region<'tcx> {
         let var = self.canonical_var(info, r.into());
-        let br = ty::BoundRegion { var, kind: ty::BrAnon(var.as_u32()) };
+        let br = ty::BoundRegion { var, kind: ty::BrAnon(var.as_u32(), None) };
         let region = ty::ReLateBound(self.binder_index, br);
         self.tcx().mk_region(region)
     }
diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
index 9ff703e521f..22f32251f6d 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
@@ -1,3 +1,4 @@
+// ignore-tidy-filelength
 //! Error Reporting Code for the inference engine
 //!
 //! Because of the way inference, and in particular region inference,
@@ -58,12 +59,15 @@ use crate::traits::{
     StatementAsExpression,
 };
 
-use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use crate::errors::SuggAddLetForLetChains;
+use hir::intravisit::{walk_expr, walk_stmt};
+use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
 use rustc_errors::{pluralize, struct_span_err, Diagnostic, ErrorGuaranteed, IntoDiagnosticArg};
 use rustc_errors::{Applicability, DiagnosticBuilder, DiagnosticStyledString, MultiSpan};
 use rustc_hir as hir;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{DefId, LocalDefId};
+use rustc_hir::intravisit::Visitor;
 use rustc_hir::lang_items::LangItem;
 use rustc_hir::Node;
 use rustc_middle::dep_graph::DepContext;
@@ -91,6 +95,7 @@ pub mod nice_region_error;
 pub struct TypeErrCtxt<'a, 'tcx> {
     pub infcx: &'a InferCtxt<'tcx>,
     pub typeck_results: Option<std::cell::Ref<'a, ty::TypeckResults<'tcx>>>,
+    pub fallback_has_occurred: bool,
 }
 
 impl TypeErrCtxt<'_, '_> {
@@ -206,9 +211,12 @@ fn msg_span_from_early_bound_and_free_regions<'tcx>(
                         };
                         (text, sp)
                     }
-                    ty::BrAnon(idx) => (
+                    ty::BrAnon(idx, span) => (
                         format!("the anonymous lifetime #{} defined here", idx + 1),
-                        tcx.def_span(scope)
+                        match span {
+                            Some(span) => span,
+                            None => tcx.def_span(scope)
+                        }
                     ),
                     _ => (
                         format!("the lifetime `{}` as defined here", region),
@@ -1498,9 +1506,9 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
             values = None;
         }
         struct OpaqueTypesVisitor<'tcx> {
-            types: FxHashMap<TyCategory, FxHashSet<Span>>,
-            expected: FxHashMap<TyCategory, FxHashSet<Span>>,
-            found: FxHashMap<TyCategory, FxHashSet<Span>>,
+            types: FxIndexMap<TyCategory, FxIndexSet<Span>>,
+            expected: FxIndexMap<TyCategory, FxIndexSet<Span>>,
+            found: FxIndexMap<TyCategory, FxIndexSet<Span>>,
             ignore_span: Span,
             tcx: TyCtxt<'tcx>,
         }
@@ -1538,7 +1546,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                 &self,
                 err: &mut Diagnostic,
                 target: &str,
-                types: &FxHashMap<TyCategory, FxHashSet<Span>>,
+                types: &FxIndexMap<TyCategory, FxIndexSet<Span>>,
             ) {
                 for (key, values) in types.iter() {
                     let count = values.len();
@@ -2332,6 +2340,11 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                                 }
                             }
                         }
+                        // For code `if Some(..) = expr `, the type mismatch may be expected `bool` but found `()`,
+                        // we try to suggest to add the missing `let` for `if let Some(..) = expr`
+                        (ty::Bool, ty::Tuple(list)) => if list.len() == 0 {
+                            self.suggest_let_for_letchains(&mut err, &trace.cause, span);
+                        }
                         _ => {}
                     }
                 }
@@ -2356,6 +2369,67 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
         diag
     }
 
+    /// Try to find code with pattern `if Some(..) = expr`
+    /// use a `visitor` to mark the `if` which its span contains given error span,
+    /// and then try to find a assignment in the `cond` part, which span is equal with error span
+    fn suggest_let_for_letchains(
+        &self,
+        err: &mut Diagnostic,
+        cause: &ObligationCause<'_>,
+        span: Span,
+    ) {
+        let hir = self.tcx.hir();
+        let fn_hir_id = hir.get_parent_node(cause.body_id);
+        if let Some(node) = self.tcx.hir().find(fn_hir_id) &&
+            let hir::Node::Item(hir::Item {
+                    kind: hir::ItemKind::Fn(_sig, _, body_id), ..
+                }) = node {
+        let body = hir.body(*body_id);
+
+        /// Find the if expression with given span
+        struct IfVisitor {
+            pub result: bool,
+            pub found_if: bool,
+            pub err_span: Span,
+        }
+
+        impl<'v> Visitor<'v> for IfVisitor {
+            fn visit_expr(&mut self, ex: &'v hir::Expr<'v>) {
+                if self.result { return; }
+                match ex.kind {
+                    hir::ExprKind::If(cond, _, _) => {
+                        self.found_if = true;
+                        walk_expr(self, cond);
+                        self.found_if = false;
+                    }
+                    _ => walk_expr(self, ex),
+                }
+            }
+
+            fn visit_stmt(&mut self, ex: &'v hir::Stmt<'v>) {
+                if let hir::StmtKind::Local(hir::Local {
+                        span, pat: hir::Pat{..}, ty: None, init: Some(_), ..
+                    }) = &ex.kind
+                    && self.found_if
+                    && span.eq(&self.err_span) {
+                        self.result = true;
+                }
+                walk_stmt(self, ex);
+            }
+
+            fn visit_body(&mut self, body: &'v hir::Body<'v>) {
+                hir::intravisit::walk_body(self, body);
+            }
+        }
+
+        let mut visitor = IfVisitor { err_span: span, found_if: false, result: false };
+        visitor.visit_body(&body);
+        if visitor.result {
+                err.subdiagnostic(SuggAddLetForLetChains{span: span.shrink_to_lo()});
+            }
+        }
+    }
+
     fn emit_tuple_wrap_err(
         &self,
         err: &mut Diagnostic,
@@ -3254,7 +3328,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
         if blk.expr.is_some() {
             return false;
         }
-        let mut shadowed = FxHashSet::default();
+        let mut shadowed = FxIndexSet::default();
         let mut candidate_idents = vec![];
         let mut find_compatible_candidates = |pat: &hir::Pat<'_>| {
             if let hir::PatKind::Binding(_, hir_id, ident, _) = &pat.kind
diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs
index c5f2a1a3f7d..1067ccda20c 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs
@@ -9,7 +9,7 @@ use crate::infer::error_reporting::nice_region_error::NiceRegionError;
 use crate::infer::lexical_region_resolve::RegionResolutionError;
 use crate::infer::{SubregionOrigin, TypeTrace};
 use crate::traits::ObligationCauseCode;
-use rustc_data_structures::fx::FxHashSet;
+use rustc_data_structures::fx::FxIndexSet;
 use rustc_errors::{ErrorGuaranteed, MultiSpan};
 use rustc_hir as hir;
 use rustc_hir::intravisit::Visitor;
@@ -73,7 +73,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
 
             // Next, let's figure out the set of trait objects with implicit static bounds
             let ty = self.tcx().type_of(*impl_def_id);
-            let mut v = super::static_impl_trait::TraitObjectVisitor(FxHashSet::default());
+            let mut v = super::static_impl_trait::TraitObjectVisitor(FxIndexSet::default());
             v.visit_ty(ty);
             let mut traits = vec![];
             for matching_def_id in v.0 {
diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mod.rs
index aaf5a7af00a..8a0e332f9c7 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mod.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mod.rs
@@ -10,6 +10,7 @@ pub mod find_anon_type;
 mod mismatched_static_lifetime;
 mod named_anon_conflict;
 mod placeholder_error;
+mod placeholder_relation;
 mod static_impl_trait;
 mod trait_impl_difference;
 mod util;
@@ -52,7 +53,9 @@ impl<'cx, 'tcx> NiceRegionError<'cx, 'tcx> {
     pub fn try_report_from_nll(&self) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> {
         // Due to the improved diagnostics returned by the MIR borrow checker, only a subset of
         // the nice region errors are required when running under the MIR borrow checker.
-        self.try_report_named_anon_conflict().or_else(|| self.try_report_placeholder_conflict())
+        self.try_report_named_anon_conflict()
+            .or_else(|| self.try_report_placeholder_conflict())
+            .or_else(|| self.try_report_placeholder_relation())
     }
 
     pub fn try_report(&self) -> Option<ErrorGuaranteed> {
diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/named_anon_conflict.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/named_anon_conflict.rs
index 76cb76d9ff4..3fe7c1598fc 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/named_anon_conflict.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/named_anon_conflict.rs
@@ -68,7 +68,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
         let is_impl_item = region_info.is_impl_item;
 
         match br {
-            ty::BrNamed(_, kw::UnderscoreLifetime) | ty::BrAnon(_) => {}
+            ty::BrNamed(_, kw::UnderscoreLifetime) | ty::BrAnon(..) => {}
             _ => {
                 /* not an anonymous region */
                 debug!("try_report_named_anon_conflict: not an anonymous region");
diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_relation.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_relation.rs
new file mode 100644
index 00000000000..c42240f2172
--- /dev/null
+++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_relation.rs
@@ -0,0 +1,79 @@
+use crate::infer::{
+    error_reporting::nice_region_error::NiceRegionError, RegionResolutionError, SubregionOrigin,
+};
+use rustc_data_structures::intern::Interned;
+use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed};
+use rustc_middle::ty::{self, RePlaceholder, Region};
+
+impl<'tcx> NiceRegionError<'_, 'tcx> {
+    /// Emitted wwhen given a `ConcreteFailure` when relating two placeholders.
+    pub(super) fn try_report_placeholder_relation(
+        &self,
+    ) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> {
+        match &self.error {
+            Some(RegionResolutionError::ConcreteFailure(
+                SubregionOrigin::RelateRegionParamBound(span),
+                Region(Interned(RePlaceholder(ty::Placeholder { name: sub_name, .. }), _)),
+                Region(Interned(RePlaceholder(ty::Placeholder { name: sup_name, .. }), _)),
+            )) => {
+                let msg = "lifetime bound not satisfied";
+                let mut err = self.tcx().sess.struct_span_err(*span, msg);
+                let (sub_span, sub_symbol) = match sub_name {
+                    ty::BrNamed(def_id, symbol) => {
+                        (Some(self.tcx().def_span(def_id)), Some(symbol))
+                    }
+                    ty::BrAnon(_, span) => (*span, None),
+                    ty::BrEnv => (None, None),
+                };
+                let (sup_span, sup_symbol) = match sup_name {
+                    ty::BrNamed(def_id, symbol) => {
+                        (Some(self.tcx().def_span(def_id)), Some(symbol))
+                    }
+                    ty::BrAnon(_, span) => (*span, None),
+                    ty::BrEnv => (None, None),
+                };
+                match (sub_span, sup_span, sub_symbol, sup_symbol) {
+                    (Some(sub_span), Some(sup_span), Some(sub_symbol), Some(sup_symbol)) => {
+                        err.span_note(
+                            sub_span,
+                            format!("the lifetime `{sub_symbol}` defined here..."),
+                        );
+                        err.span_note(
+                            sup_span,
+                            format!("...must outlive the lifetime `{sup_symbol}` defined here"),
+                        );
+                    }
+                    (Some(sub_span), Some(sup_span), _, Some(sup_symbol)) => {
+                        err.span_note(sub_span, format!("the lifetime defined here..."));
+                        err.span_note(
+                            sup_span,
+                            format!("...must outlive the lifetime `{sup_symbol}` defined here"),
+                        );
+                    }
+                    (Some(sub_span), Some(sup_span), Some(sub_symbol), _) => {
+                        err.span_note(
+                            sub_span,
+                            format!("the lifetime `{sub_symbol}` defined here..."),
+                        );
+                        err.span_note(
+                            sup_span,
+                            format!("...must outlive the lifetime defined here"),
+                        );
+                    }
+                    (Some(sub_span), Some(sup_span), _, _) => {
+                        err.span_note(sub_span, format!("the lifetime defined here..."));
+                        err.span_note(
+                            sup_span,
+                            format!("...must outlive the lifetime defined here"),
+                        );
+                    }
+                    _ => {}
+                }
+                err.note("this is a known limitation that will be removed in the future (see issue #100013 <https://github.com/rust-lang/rust/issues/100013> for more information)");
+                Some(err)
+            }
+
+            _ => None,
+        }
+    }
+}
diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs
index 9bf755d7fcd..b4efe8da125 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs
@@ -4,7 +4,7 @@ use crate::infer::error_reporting::nice_region_error::NiceRegionError;
 use crate::infer::lexical_region_resolve::RegionResolutionError;
 use crate::infer::{SubregionOrigin, TypeTrace};
 use crate::traits::{ObligationCauseCode, UnifyReceiverContext};
-use rustc_data_structures::fx::FxHashSet;
+use rustc_data_structures::fx::FxIndexSet;
 use rustc_errors::{struct_span_err, Applicability, Diagnostic, ErrorGuaranteed, MultiSpan};
 use rustc_hir::def_id::DefId;
 use rustc_hir::intravisit::{walk_ty, Visitor};
@@ -236,7 +236,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
             // Same case of `impl Foo for dyn Bar { fn qux(&self) {} }` introducing a `'static`
             // lifetime as above, but called using a fully-qualified path to the method:
             // `Foo::qux(bar)`.
-            let mut v = TraitObjectVisitor(FxHashSet::default());
+            let mut v = TraitObjectVisitor(FxIndexSet::default());
             v.visit_ty(param.param_ty);
             if let Some((ident, self_ty)) =
                 self.get_impl_ident_and_self_ty_from_trait(item_def_id, &v.0)
@@ -408,7 +408,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
     fn get_impl_ident_and_self_ty_from_trait(
         &self,
         def_id: DefId,
-        trait_objects: &FxHashSet<DefId>,
+        trait_objects: &FxIndexSet<DefId>,
     ) -> Option<(Ident, &'tcx hir::Ty<'tcx>)> {
         let tcx = self.tcx();
         match tcx.hir().get_if_local(def_id) {
@@ -490,7 +490,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
             return false;
         };
 
-        let mut v = TraitObjectVisitor(FxHashSet::default());
+        let mut v = TraitObjectVisitor(FxIndexSet::default());
         v.visit_ty(ty);
 
         // Get the `Ident` of the method being called and the corresponding `impl` (to point at
@@ -506,7 +506,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
     fn suggest_constrain_dyn_trait_in_impl(
         &self,
         err: &mut Diagnostic,
-        found_dids: &FxHashSet<DefId>,
+        found_dids: &FxIndexSet<DefId>,
         ident: Ident,
         self_ty: &hir::Ty<'_>,
     ) -> bool {
@@ -538,7 +538,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
 }
 
 /// Collect all the trait objects in a type that could have received an implicit `'static` lifetime.
-pub struct TraitObjectVisitor(pub FxHashSet<DefId>);
+pub struct TraitObjectVisitor(pub FxIndexSet<DefId>);
 
 impl<'tcx> TypeVisitor<'tcx> for TraitObjectVisitor {
     fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs
index f1461d7010d..fd26d7d29c5 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs
@@ -149,6 +149,8 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
         region: ty::BoundRegionKind,
     ) -> bool {
         let late_bound_regions = self.tcx().collect_referenced_late_bound_regions(&ty);
+        // We are only checking is any region meets the condition so order doesn't matter
+        #[allow(rustc::potential_query_instability)]
         late_bound_regions.iter().any(|r| *r == region)
     }
 
diff --git a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs
index 5f13b2b3deb..ba990acfe6f 100644
--- a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs
+++ b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs
@@ -842,6 +842,9 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
         // are placeholders as upper bounds, but the universe of the
         // variable `'a`, or some variable that `'a` has to outlive, doesn't
         // permit those placeholders.
+        //
+        // We only iterate to find the min, which means it doesn't cause reproducibility issues
+        #[allow(rustc::potential_query_instability)]
         let min_universe = lower_vid_bounds
             .into_iter()
             .map(|vid| self.var_infos[vid].universe)
diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs
index c2eecd9e87a..ccba197dc80 100644
--- a/compiler/rustc_infer/src/infer/mod.rs
+++ b/compiler/rustc_infer/src/infer/mod.rs
@@ -10,6 +10,7 @@ pub(crate) use self::undo_log::{InferCtxtUndoLogs, Snapshot, UndoLog};
 
 use crate::traits::{self, ObligationCause, PredicateObligations, TraitEngine, TraitEngineExt};
 
+use rustc_data_structures::fx::FxIndexMap;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::sync::Lrc;
 use rustc_data_structures::undo_log::Rollback;
@@ -294,7 +295,7 @@ pub struct InferCtxt<'tcx> {
 
     /// the set of predicates on which errors have been reported, to
     /// avoid reporting the same error twice.
-    pub reported_trait_errors: RefCell<FxHashMap<Span, Vec<ty::Predicate<'tcx>>>>,
+    pub reported_trait_errors: RefCell<FxIndexMap<Span, Vec<ty::Predicate<'tcx>>>>,
 
     pub reported_closure_mismatch: RefCell<FxHashSet<(Span, Option<Span>)>>,
 
@@ -677,9 +678,9 @@ pub struct CombinedSnapshot<'tcx> {
 
 impl<'tcx> InferCtxt<'tcx> {
     /// Creates a `TypeErrCtxt` for emitting various inference errors.
-    /// During typeck, use `FnCtxt::infer_err` instead.
+    /// During typeck, use `FnCtxt::err_ctxt` instead.
     pub fn err_ctxt(&self) -> TypeErrCtxt<'_, 'tcx> {
-        TypeErrCtxt { infcx: self, typeck_results: None }
+        TypeErrCtxt { infcx: self, typeck_results: None, fallback_has_occurred: false }
     }
 
     /// calls `tcx.try_unify_abstract_consts` after
diff --git a/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs b/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs
index 90858e3072a..22b4bbb17d4 100644
--- a/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs
+++ b/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs
@@ -1,6 +1,7 @@
 use super::*;
 use crate::infer::CombinedSnapshot;
 use rustc_data_structures::{
+    fx::FxIndexMap,
     graph::{scc::Sccs, vec_graph::VecGraph},
     undo_log::UndoLogs,
 };
@@ -371,7 +372,7 @@ rustc_index::newtype_index! {
 /// an edge `R1 -> R2` in the graph.
 struct MiniGraph<'tcx> {
     /// Map from a region to the index of the node in the graph.
-    nodes: FxHashMap<ty::Region<'tcx>, LeakCheckNode>,
+    nodes: FxIndexMap<ty::Region<'tcx>, LeakCheckNode>,
 
     /// Map from node index to SCC, and stores the successors of each SCC. All
     /// the regions in the same SCC are equal to one another, and if `S1 -> S2`,
@@ -388,7 +389,7 @@ impl<'tcx> MiniGraph<'tcx> {
     where
         'tcx: 'a,
     {
-        let mut nodes = FxHashMap::default();
+        let mut nodes = FxIndexMap::default();
         let mut edges = Vec::new();
 
         // Note that if `R2: R1`, we get a callback `r1, r2`, so `target` is first parameter.
@@ -438,7 +439,7 @@ impl<'tcx> MiniGraph<'tcx> {
     }
 
     fn add_node(
-        nodes: &mut FxHashMap<ty::Region<'tcx>, LeakCheckNode>,
+        nodes: &mut FxIndexMap<ty::Region<'tcx>, LeakCheckNode>,
         r: ty::Region<'tcx>,
     ) -> LeakCheckNode {
         let l = nodes.len();
diff --git a/compiler/rustc_infer/src/infer/region_constraints/mod.rs b/compiler/rustc_infer/src/infer/region_constraints/mod.rs
index 67b3da68720..985c5d360db 100644
--- a/compiler/rustc_infer/src/infer/region_constraints/mod.rs
+++ b/compiler/rustc_infer/src/infer/region_constraints/mod.rs
@@ -7,7 +7,7 @@ use super::{
     InferCtxtUndoLogs, MiscVariable, RegionVariableOrigin, Rollback, Snapshot, SubregionOrigin,
 };
 
-use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_data_structures::fx::{FxHashMap, FxIndexSet};
 use rustc_data_structures::intern::Interned;
 use rustc_data_structures::sync::Lrc;
 use rustc_data_structures::undo_log::UndoLogs;
@@ -125,7 +125,7 @@ pub struct RegionConstraintData<'tcx> {
     /// we record the fact that `'a <= 'b` is implied by the fn
     /// signature, and then ignore the constraint when solving
     /// equations. This is a bit of a hack but seems to work.
-    pub givens: FxHashSet<(Region<'tcx>, ty::RegionVid)>,
+    pub givens: FxIndexSet<(Region<'tcx>, ty::RegionVid)>,
 }
 
 /// Represents a constraint that influences the inference process.
diff --git a/compiler/rustc_infer/src/lib.rs b/compiler/rustc_infer/src/lib.rs
index e040634edb0..4c119a44355 100644
--- a/compiler/rustc_infer/src/lib.rs
+++ b/compiler/rustc_infer/src/lib.rs
@@ -12,7 +12,6 @@
 //!
 //! This API is completely unstable and subject to change.
 
-#![allow(rustc::potential_query_instability)]
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
 #![feature(box_patterns)]
 #![feature(control_flow_enum)]
diff --git a/compiler/rustc_infer/src/traits/error_reporting/mod.rs b/compiler/rustc_infer/src/traits/error_reporting/mod.rs
index f8b5009a58d..4d53519581b 100644
--- a/compiler/rustc_infer/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/traits/error_reporting/mod.rs
@@ -1,7 +1,7 @@
 use super::ObjectSafetyViolation;
 
 use crate::infer::InferCtxt;
-use rustc_data_structures::fx::FxHashSet;
+use rustc_data_structures::fx::FxIndexSet;
 use rustc_errors::{struct_span_err, DiagnosticBuilder, ErrorGuaranteed, MultiSpan};
 use rustc_hir as hir;
 use rustc_hir::def_id::{DefId, LocalDefId};
@@ -56,7 +56,7 @@ pub fn report_object_safety_error<'tcx>(
     );
     err.span_label(span, format!("`{}` cannot be made into an object", trait_str));
 
-    let mut reported_violations = FxHashSet::default();
+    let mut reported_violations = FxIndexSet::default();
     let mut multi_span = vec![];
     let mut messages = vec![];
     for violation in violations {
diff --git a/compiler/rustc_interface/src/lib.rs b/compiler/rustc_interface/src/lib.rs
index a41a749ee68..542b638bbd7 100644
--- a/compiler/rustc_interface/src/lib.rs
+++ b/compiler/rustc_interface/src/lib.rs
@@ -1,4 +1,5 @@
 #![feature(box_patterns)]
+#![feature(decl_macro)]
 #![feature(internal_output_capture)]
 #![feature(thread_spawn_unchecked)]
 #![feature(once_cell)]
diff --git a/compiler/rustc_interface/src/proc_macro_decls.rs b/compiler/rustc_interface/src/proc_macro_decls.rs
index 4c236c693d0..9bf7778bfb2 100644
--- a/compiler/rustc_interface/src/proc_macro_decls.rs
+++ b/compiler/rustc_interface/src/proc_macro_decls.rs
@@ -4,21 +4,16 @@ use rustc_middle::ty::TyCtxt;
 use rustc_span::symbol::sym;
 
 fn proc_macro_decls_static(tcx: TyCtxt<'_>, (): ()) -> Option<LocalDefId> {
-    let mut finder = Finder { tcx, decls: None };
+    let mut decls = None;
 
     for id in tcx.hir().items() {
-        let attrs = finder.tcx.hir().attrs(id.hir_id());
-        if finder.tcx.sess.contains_name(attrs, sym::rustc_proc_macro_decls) {
-            finder.decls = Some(id.owner_id.def_id);
+        let attrs = tcx.hir().attrs(id.hir_id());
+        if tcx.sess.contains_name(attrs, sym::rustc_proc_macro_decls) {
+            decls = Some(id.owner_id.def_id);
         }
     }
 
-    finder.decls
-}
-
-struct Finder<'tcx> {
-    tcx: TyCtxt<'tcx>,
-    decls: Option<LocalDefId>,
+    decls
 }
 
 pub(crate) fn provide(providers: &mut Providers) {
diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs
index 62ee72f9883..2fe3fb2fa56 100644
--- a/compiler/rustc_interface/src/util.rs
+++ b/compiler/rustc_interface/src/util.rs
@@ -327,7 +327,7 @@ fn get_codegen_sysroot(maybe_sysroot: &Option<PathBuf>, backend_name: &str) -> M
     let mut file: Option<PathBuf> = None;
 
     let expected_names = &[
-        format!("rustc_codegen_{}-{}", backend_name, release_str().expect("CFG_RELEASE")),
+        format!("rustc_codegen_{}-{}", backend_name, env!("CFG_RELEASE")),
         format!("rustc_codegen_{}", backend_name),
     ];
     for entry in d.filter_map(|e| e.ok()) {
@@ -554,22 +554,12 @@ pub fn build_output_filenames(
     }
 }
 
-/// Returns a version string such as "1.46.0 (04488afe3 2020-08-24)"
-pub fn version_str() -> Option<&'static str> {
+/// Returns a version string such as "1.46.0 (04488afe3 2020-08-24)" when invoked by an in-tree tool.
+pub macro version_str() {
     option_env!("CFG_VERSION")
 }
 
-/// Returns a version string such as "0.12.0-dev".
-pub fn release_str() -> Option<&'static str> {
-    option_env!("CFG_RELEASE")
-}
-
-/// Returns the full SHA1 hash of HEAD of the Git repo from which rustc was built.
-pub fn commit_hash_str() -> Option<&'static str> {
-    option_env!("CFG_VER_HASH")
-}
-
-/// Returns the "commit date" of HEAD of the Git repo from which rustc was built as a static string.
-pub fn commit_date_str() -> Option<&'static str> {
-    option_env!("CFG_VER_DATE")
+/// Returns the version string for `rustc` itself (which may be different from a tool version).
+pub fn rustc_version_str() -> Option<&'static str> {
+    version_str!()
 }
diff --git a/compiler/rustc_lexer/src/lib.rs b/compiler/rustc_lexer/src/lib.rs
index 51515976e4e..d4140cb295f 100644
--- a/compiler/rustc_lexer/src/lib.rs
+++ b/compiler/rustc_lexer/src/lib.rs
@@ -88,7 +88,9 @@ pub enum TokenKind {
     /// tokens.
     UnknownPrefix,
 
-    /// Examples: `"12_u8"`, `"1.0e-40"`, `b"123`.
+    /// Examples: `12u8`, `1.0e-40`, `b"123"`. Note that `_` is an invalid
+    /// suffix, but may be present here on string and float literals. Users of
+    /// this type will need to check for and reject that case.
     ///
     /// See [LiteralKind] for more details.
     Literal { kind: LiteralKind, suffix_start: u32 },
@@ -203,13 +205,13 @@ pub enum RawStrError {
 #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
 pub enum Base {
     /// Literal starts with "0b".
-    Binary,
+    Binary = 2,
     /// Literal starts with "0o".
-    Octal,
-    /// Literal starts with "0x".
-    Hexadecimal,
+    Octal = 8,
     /// Literal doesn't contain a prefix.
-    Decimal,
+    Decimal = 10,
+    /// Literal starts with "0x".
+    Hexadecimal = 16,
 }
 
 /// `rustc` allows files to have a shebang, e.g. "#!/usr/bin/rustrun",
@@ -840,12 +842,13 @@ impl Cursor<'_> {
         self.eat_decimal_digits()
     }
 
-    // Eats the suffix of the literal, e.g. "_u8".
+    // Eats the suffix of the literal, e.g. "u8".
     fn eat_literal_suffix(&mut self) {
         self.eat_identifier();
     }
 
-    // Eats the identifier.
+    // Eats the identifier. Note: succeeds on `_`, which isn't a valid
+    // identifer.
     fn eat_identifier(&mut self) {
         if !is_id_start(self.first()) {
             return;
diff --git a/compiler/rustc_lexer/src/unescape.rs b/compiler/rustc_lexer/src/unescape.rs
index 8f64b5f5158..e405013dcab 100644
--- a/compiler/rustc_lexer/src/unescape.rs
+++ b/compiler/rustc_lexer/src/unescape.rs
@@ -52,10 +52,8 @@ pub enum EscapeError {
 
     /// Unicode escape code in byte literal.
     UnicodeEscapeInByte,
-    /// Non-ascii character in byte literal.
+    /// Non-ascii character in byte literal, byte string literal, or raw byte string literal.
     NonAsciiCharInByte,
-    /// Non-ascii character in byte string literal.
-    NonAsciiCharInByteString,
 
     /// After a line ending with '\', the next line contains whitespace
     /// characters that are not skipped.
@@ -78,54 +76,33 @@ impl EscapeError {
 /// Takes a contents of a literal (without quotes) and produces a
 /// sequence of escaped characters or errors.
 /// Values are returned through invoking of the provided callback.
-pub fn unescape_literal<F>(literal_text: &str, mode: Mode, callback: &mut F)
+pub fn unescape_literal<F>(src: &str, mode: Mode, callback: &mut F)
 where
     F: FnMut(Range<usize>, Result<char, EscapeError>),
 {
     match mode {
         Mode::Char | Mode::Byte => {
-            let mut chars = literal_text.chars();
-            let result = unescape_char_or_byte(&mut chars, mode);
-            // The Chars iterator moved forward.
-            callback(0..(literal_text.len() - chars.as_str().len()), result);
+            let mut chars = src.chars();
+            let res = unescape_char_or_byte(&mut chars, mode == Mode::Byte);
+            callback(0..(src.len() - chars.as_str().len()), res);
         }
-        Mode::Str | Mode::ByteStr => unescape_str_or_byte_str(literal_text, mode, callback),
-        // NOTE: Raw strings do not perform any explicit character escaping, here we
-        // only translate CRLF to LF and produce errors on bare CR.
+        Mode::Str | Mode::ByteStr => unescape_str_or_byte_str(src, mode == Mode::ByteStr, callback),
         Mode::RawStr | Mode::RawByteStr => {
-            unescape_raw_str_or_raw_byte_str(literal_text, mode, callback)
+            unescape_raw_str_or_raw_byte_str(src, mode == Mode::RawByteStr, callback)
         }
     }
 }
 
-/// Takes a contents of a byte, byte string or raw byte string (without quotes)
-/// and produces a sequence of bytes or errors.
-/// Values are returned through invoking of the provided callback.
-pub fn unescape_byte_literal<F>(literal_text: &str, mode: Mode, callback: &mut F)
-where
-    F: FnMut(Range<usize>, Result<u8, EscapeError>),
-{
-    debug_assert!(mode.is_bytes());
-    unescape_literal(literal_text, mode, &mut |range, result| {
-        callback(range, result.map(byte_from_char));
-    })
-}
-
 /// Takes a contents of a char literal (without quotes), and returns an
-/// unescaped char or an error
-pub fn unescape_char(literal_text: &str) -> Result<char, (usize, EscapeError)> {
-    let mut chars = literal_text.chars();
-    unescape_char_or_byte(&mut chars, Mode::Char)
-        .map_err(|err| (literal_text.len() - chars.as_str().len(), err))
+/// unescaped char or an error.
+pub fn unescape_char(src: &str) -> Result<char, EscapeError> {
+    unescape_char_or_byte(&mut src.chars(), false)
 }
 
 /// Takes a contents of a byte literal (without quotes), and returns an
 /// unescaped byte or an error.
-pub fn unescape_byte(literal_text: &str) -> Result<u8, (usize, EscapeError)> {
-    let mut chars = literal_text.chars();
-    unescape_char_or_byte(&mut chars, Mode::Byte)
-        .map(byte_from_char)
-        .map_err(|err| (literal_text.len() - chars.as_str().len(), err))
+pub fn unescape_byte(src: &str) -> Result<u8, EscapeError> {
+    unescape_char_or_byte(&mut src.chars(), true).map(byte_from_char)
 }
 
 /// What kind of literal do we parse.
@@ -147,7 +124,7 @@ impl Mode {
         }
     }
 
-    pub fn is_bytes(self) -> bool {
+    pub fn is_byte(self) -> bool {
         match self {
             Mode::Byte | Mode::ByteStr | Mode::RawByteStr => true,
             Mode::Char | Mode::Str | Mode::RawStr => false,
@@ -155,12 +132,9 @@ impl Mode {
     }
 }
 
-fn scan_escape(chars: &mut Chars<'_>, mode: Mode) -> Result<char, EscapeError> {
+fn scan_escape(chars: &mut Chars<'_>, is_byte: bool) -> Result<char, EscapeError> {
     // Previous character was '\\', unescape what follows.
-
-    let second_char = chars.next().ok_or(EscapeError::LoneSlash)?;
-
-    let res = match second_char {
+    let res = match chars.next().ok_or(EscapeError::LoneSlash)? {
         '"' => '"',
         'n' => '\n',
         'r' => '\r',
@@ -181,7 +155,7 @@ fn scan_escape(chars: &mut Chars<'_>, mode: Mode) -> Result<char, EscapeError> {
             let value = hi * 16 + lo;
 
             // For a non-byte literal verify that it is within ASCII range.
-            if !mode.is_bytes() && !is_ascii(value) {
+            if !is_byte && !is_ascii(value) {
                 return Err(EscapeError::OutOfRangeHexEscape);
             }
             let value = value as u8;
@@ -217,7 +191,7 @@ fn scan_escape(chars: &mut Chars<'_>, mode: Mode) -> Result<char, EscapeError> {
 
                         // Incorrect syntax has higher priority for error reporting
                         // than unallowed value for a literal.
-                        if mode.is_bytes() {
+                        if is_byte {
                             return Err(EscapeError::UnicodeEscapeInByte);
                         }
 
@@ -249,23 +223,22 @@ fn scan_escape(chars: &mut Chars<'_>, mode: Mode) -> Result<char, EscapeError> {
 }
 
 #[inline]
-fn ascii_check(first_char: char, mode: Mode) -> Result<char, EscapeError> {
-    if mode.is_bytes() && !first_char.is_ascii() {
+fn ascii_check(c: char, is_byte: bool) -> Result<char, EscapeError> {
+    if is_byte && !c.is_ascii() {
         // Byte literal can't be a non-ascii character.
         Err(EscapeError::NonAsciiCharInByte)
     } else {
-        Ok(first_char)
+        Ok(c)
     }
 }
 
-fn unescape_char_or_byte(chars: &mut Chars<'_>, mode: Mode) -> Result<char, EscapeError> {
-    debug_assert!(mode == Mode::Char || mode == Mode::Byte);
-    let first_char = chars.next().ok_or(EscapeError::ZeroChars)?;
-    let res = match first_char {
-        '\\' => scan_escape(chars, mode),
+fn unescape_char_or_byte(chars: &mut Chars<'_>, is_byte: bool) -> Result<char, EscapeError> {
+    let c = chars.next().ok_or(EscapeError::ZeroChars)?;
+    let res = match c {
+        '\\' => scan_escape(chars, is_byte),
         '\n' | '\t' | '\'' => Err(EscapeError::EscapeOnlyChar),
         '\r' => Err(EscapeError::BareCarriageReturn),
-        _ => ascii_check(first_char, mode),
+        _ => ascii_check(c, is_byte),
     }?;
     if chars.next().is_some() {
         return Err(EscapeError::MoreThanOneChar);
@@ -275,20 +248,20 @@ fn unescape_char_or_byte(chars: &mut Chars<'_>, mode: Mode) -> Result<char, Esca
 
 /// Takes a contents of a string literal (without quotes) and produces a
 /// sequence of escaped characters or errors.
-fn unescape_str_or_byte_str<F>(src: &str, mode: Mode, callback: &mut F)
+fn unescape_str_or_byte_str<F>(src: &str, is_byte: bool, callback: &mut F)
 where
     F: FnMut(Range<usize>, Result<char, EscapeError>),
 {
-    debug_assert!(mode == Mode::Str || mode == Mode::ByteStr);
-    let initial_len = src.len();
     let mut chars = src.chars();
-    while let Some(first_char) = chars.next() {
-        let start = initial_len - chars.as_str().len() - first_char.len_utf8();
 
-        let unescaped_char = match first_char {
+    // The `start` and `end` computation here is complicated because
+    // `skip_ascii_whitespace` makes us to skip over chars without counting
+    // them in the range computation.
+    while let Some(c) = chars.next() {
+        let start = src.len() - chars.as_str().len() - c.len_utf8();
+        let res = match c {
             '\\' => {
-                let second_char = chars.clone().next();
-                match second_char {
+                match chars.clone().next() {
                     Some('\n') => {
                         // Rust language specification requires us to skip whitespaces
                         // if unescaped '\' character is followed by '\n'.
@@ -297,17 +270,17 @@ where
                         skip_ascii_whitespace(&mut chars, start, callback);
                         continue;
                     }
-                    _ => scan_escape(&mut chars, mode),
+                    _ => scan_escape(&mut chars, is_byte),
                 }
             }
             '\n' => Ok('\n'),
             '\t' => Ok('\t'),
             '"' => Err(EscapeError::EscapeOnlyChar),
             '\r' => Err(EscapeError::BareCarriageReturn),
-            _ => ascii_check(first_char, mode),
+            _ => ascii_check(c, is_byte),
         };
-        let end = initial_len - chars.as_str().len();
-        callback(start..end, unescaped_char);
+        let end = src.len() - chars.as_str().len();
+        callback(start..end, res);
     }
 
     fn skip_ascii_whitespace<F>(chars: &mut Chars<'_>, start: usize, callback: &mut F)
@@ -340,30 +313,29 @@ where
 /// Takes a contents of a string literal (without quotes) and produces a
 /// sequence of characters or errors.
 /// NOTE: Raw strings do not perform any explicit character escaping, here we
-/// only translate CRLF to LF and produce errors on bare CR.
-fn unescape_raw_str_or_raw_byte_str<F>(literal_text: &str, mode: Mode, callback: &mut F)
+/// only produce errors on bare CR.
+fn unescape_raw_str_or_raw_byte_str<F>(src: &str, is_byte: bool, callback: &mut F)
 where
     F: FnMut(Range<usize>, Result<char, EscapeError>),
 {
-    debug_assert!(mode == Mode::RawStr || mode == Mode::RawByteStr);
-    let initial_len = literal_text.len();
-
-    let mut chars = literal_text.chars();
-    while let Some(curr) = chars.next() {
-        let start = initial_len - chars.as_str().len() - curr.len_utf8();
+    let mut chars = src.chars();
 
-        let result = match curr {
+    // The `start` and `end` computation here matches the one in
+    // `unescape_str_or_byte_str` for consistency, even though this function
+    // doesn't have to worry about skipping any chars.
+    while let Some(c) = chars.next() {
+        let start = src.len() - chars.as_str().len() - c.len_utf8();
+        let res = match c {
             '\r' => Err(EscapeError::BareCarriageReturnInRawString),
-            c if mode.is_bytes() && !c.is_ascii() => Err(EscapeError::NonAsciiCharInByteString),
-            c => Ok(c),
+            _ => ascii_check(c, is_byte),
         };
-        let end = initial_len - chars.as_str().len();
-
-        callback(start..end, result);
+        let end = src.len() - chars.as_str().len();
+        callback(start..end, res);
     }
 }
 
-fn byte_from_char(c: char) -> u8 {
+#[inline]
+pub fn byte_from_char(c: char) -> u8 {
     let res = c as u32;
     debug_assert!(res <= u8::MAX as u32, "guaranteed because of Mode::ByteStr");
     res as u8
diff --git a/compiler/rustc_lexer/src/unescape/tests.rs b/compiler/rustc_lexer/src/unescape/tests.rs
index fa61554afde..c7ca8fd16ae 100644
--- a/compiler/rustc_lexer/src/unescape/tests.rs
+++ b/compiler/rustc_lexer/src/unescape/tests.rs
@@ -3,8 +3,7 @@ use super::*;
 #[test]
 fn test_unescape_char_bad() {
     fn check(literal_text: &str, expected_error: EscapeError) {
-        let actual_result = unescape_char(literal_text).map_err(|(_offset, err)| err);
-        assert_eq!(actual_result, Err(expected_error));
+        assert_eq!(unescape_char(literal_text), Err(expected_error));
     }
 
     check("", EscapeError::ZeroChars);
@@ -68,8 +67,7 @@ fn test_unescape_char_bad() {
 #[test]
 fn test_unescape_char_good() {
     fn check(literal_text: &str, expected_char: char) {
-        let actual_result = unescape_char(literal_text);
-        assert_eq!(actual_result, Ok(expected_char));
+        assert_eq!(unescape_char(literal_text), Ok(expected_char));
     }
 
     check("a", 'a');
@@ -149,8 +147,7 @@ fn test_unescape_str_good() {
 #[test]
 fn test_unescape_byte_bad() {
     fn check(literal_text: &str, expected_error: EscapeError) {
-        let actual_result = unescape_byte(literal_text).map_err(|(_offset, err)| err);
-        assert_eq!(actual_result, Err(expected_error));
+        assert_eq!(unescape_byte(literal_text), Err(expected_error));
     }
 
     check("", EscapeError::ZeroChars);
@@ -219,8 +216,7 @@ fn test_unescape_byte_bad() {
 #[test]
 fn test_unescape_byte_good() {
     fn check(literal_text: &str, expected_byte: u8) {
-        let actual_result = unescape_byte(literal_text);
-        assert_eq!(actual_result, Ok(expected_byte));
+        assert_eq!(unescape_byte(literal_text), Ok(expected_byte));
     }
 
     check("a", b'a');
@@ -246,10 +242,10 @@ fn test_unescape_byte_good() {
 fn test_unescape_byte_str_good() {
     fn check(literal_text: &str, expected: &[u8]) {
         let mut buf = Ok(Vec::with_capacity(literal_text.len()));
-        unescape_byte_literal(literal_text, Mode::ByteStr, &mut |range, c| {
+        unescape_literal(literal_text, Mode::ByteStr, &mut |range, c| {
             if let Ok(b) = &mut buf {
                 match c {
-                    Ok(c) => b.push(c),
+                    Ok(c) => b.push(byte_from_char(c)),
                     Err(e) => buf = Err((range, e)),
                 }
             }
@@ -280,18 +276,13 @@ fn test_unescape_raw_str() {
 
 #[test]
 fn test_unescape_raw_byte_str() {
-    fn check(literal: &str, expected: &[(Range<usize>, Result<u8, EscapeError>)]) {
+    fn check(literal: &str, expected: &[(Range<usize>, Result<char, EscapeError>)]) {
         let mut unescaped = Vec::with_capacity(literal.len());
-        unescape_byte_literal(literal, Mode::RawByteStr, &mut |range, res| {
-            unescaped.push((range, res))
-        });
+        unescape_literal(literal, Mode::RawByteStr, &mut |range, res| unescaped.push((range, res)));
         assert_eq!(unescaped, expected);
     }
 
     check("\r", &[(0..1, Err(EscapeError::BareCarriageReturnInRawString))]);
-    check("🦀", &[(0..4, Err(EscapeError::NonAsciiCharInByteString))]);
-    check(
-        "🦀a",
-        &[(0..4, Err(EscapeError::NonAsciiCharInByteString)), (4..5, Ok(byte_from_char('a')))],
-    );
+    check("🦀", &[(0..4, Err(EscapeError::NonAsciiCharInByte))]);
+    check("🦀a", &[(0..4, Err(EscapeError::NonAsciiCharInByte)), (4..5, Ok('a'))]);
 }
diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs
index cec0003ffea..28f6ac61c5b 100644
--- a/compiler/rustc_lint/src/context.rs
+++ b/compiler/rustc_lint/src/context.rs
@@ -579,6 +579,7 @@ pub trait LintContext: Sized {
     /// Return value of the `decorate` closure is ignored, see [`struct_lint_level`] for a detailed explanation.
     ///
     /// [`struct_lint_level`]: rustc_middle::lint::struct_lint_level#decorate-signature
+    #[rustc_lint_diagnostics]
     fn lookup_with_diagnostics(
         &self,
         lint: &'static Lint,
@@ -882,6 +883,7 @@ pub trait LintContext: Sized {
     /// Return value of the `decorate` closure is ignored, see [`struct_lint_level`] for a detailed explanation.
     ///
     /// [`struct_lint_level`]: rustc_middle::lint::struct_lint_level#decorate-signature
+    #[rustc_lint_diagnostics]
     fn lookup<S: Into<MultiSpan>>(
         &self,
         lint: &'static Lint,
@@ -908,6 +910,7 @@ pub trait LintContext: Sized {
     /// Return value of the `decorate` closure is ignored, see [`struct_lint_level`] for a detailed explanation.
     ///
     /// [`struct_lint_level`]: rustc_middle::lint::struct_lint_level#decorate-signature
+    #[rustc_lint_diagnostics]
     fn struct_span_lint<S: Into<MultiSpan>>(
         &self,
         lint: &'static Lint,
@@ -933,6 +936,7 @@ pub trait LintContext: Sized {
     /// Return value of the `decorate` closure is ignored, see [`struct_lint_level`] for a detailed explanation.
     ///
     /// [`struct_lint_level`]: rustc_middle::lint::struct_lint_level#decorate-signature
+    #[rustc_lint_diagnostics]
     fn lint(
         &self,
         lint: &'static Lint,
diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs
index db0a3419e6a..dfe52312ff0 100644
--- a/compiler/rustc_lint/src/levels.rs
+++ b/compiler/rustc_lint/src/levels.rs
@@ -1073,6 +1073,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> {
     /// Return value of the `decorate` closure is ignored, see [`struct_lint_level`] for a detailed explanation.
     ///
     /// [`struct_lint_level`]: rustc_middle::lint::struct_lint_level#decorate-signature
+    #[rustc_lint_diagnostics]
     pub(crate) fn struct_lint(
         &self,
         lint: &'static Lint,
diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs
index 5288fc542d7..ebb7de70e05 100644
--- a/compiler/rustc_lint/src/lib.rs
+++ b/compiler/rustc_lint/src/lib.rs
@@ -36,6 +36,7 @@
 #![feature(let_chains)]
 #![feature(min_specialization)]
 #![feature(never_type)]
+#![feature(rustc_attrs)]
 #![recursion_limit = "256"]
 
 #[macro_use]
diff --git a/compiler/rustc_macros/src/diagnostics/error.rs b/compiler/rustc_macros/src/diagnostics/error.rs
index 0b1ededa775..4612f54e4b1 100644
--- a/compiler/rustc_macros/src/diagnostics/error.rs
+++ b/compiler/rustc_macros/src/diagnostics/error.rs
@@ -84,7 +84,7 @@ pub(crate) fn invalid_attr(attr: &Attribute, meta: &Meta) -> Diagnostic {
     }
 }
 
-/// Emit a error diagnostic for an invalid attribute (optionally performing additional decoration
+/// Emit an error diagnostic for an invalid attribute (optionally performing additional decoration
 /// using the `FnOnce` passed in `diag`) and return `Err(ErrorHandled)`.
 ///
 /// For methods that return a `Result<_, DiagnosticDeriveError>`:
@@ -126,7 +126,7 @@ pub(crate) fn invalid_nested_attr(attr: &Attribute, nested: &NestedMeta) -> Diag
     }
 }
 
-/// Emit a error diagnostic for an invalid nested attribute (optionally performing additional
+/// Emit an error diagnostic for an invalid nested attribute (optionally performing additional
 /// decoration using the `FnOnce` passed in `diag`) and return `Err(ErrorHandled)`.
 ///
 /// For methods that return a `Result<_, DiagnosticDeriveError>`:
diff --git a/compiler/rustc_middle/src/infer/canonical.rs b/compiler/rustc_middle/src/infer/canonical.rs
index 8d1ed4b2a52..0331d764b38 100644
--- a/compiler/rustc_middle/src/infer/canonical.rs
+++ b/compiler/rustc_middle/src/infer/canonical.rs
@@ -336,8 +336,10 @@ impl<'tcx> CanonicalVarValues<'tcx> {
                         tcx.mk_ty(ty::Bound(ty::INNERMOST, ty::BoundVar::from_u32(i).into())).into()
                     }
                     GenericArgKind::Lifetime(..) => {
-                        let br =
-                            ty::BoundRegion { var: ty::BoundVar::from_u32(i), kind: ty::BrAnon(i) };
+                        let br = ty::BoundRegion {
+                            var: ty::BoundVar::from_u32(i),
+                            kind: ty::BrAnon(i, None),
+                        };
                         tcx.mk_region(ty::ReLateBound(ty::INNERMOST, br)).into()
                     }
                     GenericArgKind::Const(ct) => tcx
diff --git a/compiler/rustc_middle/src/lint.rs b/compiler/rustc_middle/src/lint.rs
index 79522bd0b2b..51df42f6d14 100644
--- a/compiler/rustc_middle/src/lint.rs
+++ b/compiler/rustc_middle/src/lint.rs
@@ -276,7 +276,7 @@ pub fn explain_lint_level_source(
 
 /// The innermost function for emitting lints.
 ///
-/// If you are loocking to implement a lint, look for higher level functions,
+/// If you are looking to implement a lint, look for higher level functions,
 /// for example:
 /// - [`TyCtxt::emit_spanned_lint`]
 /// - [`TyCtxt::struct_span_lint_hir`]
diff --git a/compiler/rustc_middle/src/middle/privacy.rs b/compiler/rustc_middle/src/middle/privacy.rs
index ffbd6d10da6..3a91522d362 100644
--- a/compiler/rustc_middle/src/middle/privacy.rs
+++ b/compiler/rustc_middle/src/middle/privacy.rs
@@ -1,12 +1,14 @@
 //! A pass that checks to make sure private fields and methods aren't used
 //! outside their scopes. This pass will also generate a set of exported items
 //! which are available for use externally when compiled as a library.
-use crate::ty::{DefIdTree, Visibility};
+use crate::ty::{DefIdTree, TyCtxt, Visibility};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
+use rustc_hir::def::DefKind;
 use rustc_macros::HashStable;
 use rustc_query_system::ich::StableHashingContext;
 use rustc_span::def_id::LocalDefId;
+use std::hash::Hash;
 
 /// Represents the levels of effective visibility an item can have.
 ///
@@ -74,9 +76,9 @@ impl EffectiveVisibility {
 }
 
 /// Holds a map of effective visibilities for reachable HIR nodes.
-#[derive(Default, Clone, Debug)]
-pub struct EffectiveVisibilities {
-    map: FxHashMap<LocalDefId, EffectiveVisibility>,
+#[derive(Clone, Debug)]
+pub struct EffectiveVisibilities<Id = LocalDefId> {
+    map: FxHashMap<Id, EffectiveVisibility>,
 }
 
 impl EffectiveVisibilities {
@@ -111,12 +113,30 @@ impl EffectiveVisibilities {
         })
     }
 
-    pub fn effective_vis(&self, id: LocalDefId) -> Option<&EffectiveVisibility> {
-        self.map.get(&id)
-    }
-
-    pub fn iter(&self) -> impl Iterator<Item = (&LocalDefId, &EffectiveVisibility)> {
-        self.map.iter()
+    // FIXME: Share code with `fn update`.
+    pub fn update_eff_vis(
+        &mut self,
+        def_id: LocalDefId,
+        eff_vis: &EffectiveVisibility,
+        tree: impl DefIdTree,
+    ) {
+        use std::collections::hash_map::Entry;
+        match self.map.entry(def_id) {
+            Entry::Occupied(mut occupied) => {
+                let old_eff_vis = occupied.get_mut();
+                for l in Level::all_levels() {
+                    let vis_at_level = eff_vis.at_level(l);
+                    let old_vis_at_level = old_eff_vis.at_level_mut(l);
+                    if vis_at_level != old_vis_at_level
+                        && vis_at_level.is_at_least(*old_vis_at_level, tree)
+                    {
+                        *old_vis_at_level = *vis_at_level
+                    }
+                }
+                old_eff_vis
+            }
+            Entry::Vacant(vacant) => vacant.insert(*eff_vis),
+        };
     }
 
     pub fn set_public_at_level(
@@ -137,26 +157,82 @@ impl EffectiveVisibilities {
         self.map.insert(id, effective_vis);
     }
 
+    pub fn check_invariants(&self, tcx: TyCtxt<'_>, early: bool) {
+        if !cfg!(debug_assertions) {
+            return;
+        }
+        for (&def_id, ev) in &self.map {
+            // More direct visibility levels can never go farther than less direct ones,
+            // neither of effective visibilities can go farther than nominal visibility,
+            // and all effective visibilities are larger or equal than private visibility.
+            let private_vis = Visibility::Restricted(tcx.parent_module_from_def_id(def_id));
+            let span = tcx.def_span(def_id.to_def_id());
+            if !ev.direct.is_at_least(private_vis, tcx) {
+                span_bug!(span, "private {:?} > direct {:?}", private_vis, ev.direct);
+            }
+            if !ev.reexported.is_at_least(ev.direct, tcx) {
+                span_bug!(span, "direct {:?} > reexported {:?}", ev.direct, ev.reexported);
+            }
+            if !ev.reachable.is_at_least(ev.reexported, tcx) {
+                span_bug!(span, "reexported {:?} > reachable {:?}", ev.reexported, ev.reachable);
+            }
+            if !ev.reachable_through_impl_trait.is_at_least(ev.reachable, tcx) {
+                span_bug!(
+                    span,
+                    "reachable {:?} > reachable_through_impl_trait {:?}",
+                    ev.reachable,
+                    ev.reachable_through_impl_trait
+                );
+            }
+            let nominal_vis = tcx.visibility(def_id);
+            let def_kind = tcx.opt_def_kind(def_id);
+            // FIXME: `rustc_privacy` is not yet updated for the new logic and can set
+            // effective visibilities that are larger than the nominal one.
+            if !nominal_vis.is_at_least(ev.reachable_through_impl_trait, tcx) && early {
+                span_bug!(
+                    span,
+                    "{:?}: reachable_through_impl_trait {:?} > nominal {:?}",
+                    def_id,
+                    ev.reachable_through_impl_trait,
+                    nominal_vis
+                );
+            }
+            // Fully private items are never put into the table, this is important for performance.
+            // FIXME: Fully private `mod` items are currently put into the table.
+            if ev.reachable_through_impl_trait == private_vis && def_kind != Some(DefKind::Mod) {
+                span_bug!(span, "fully private item in the table {:?}: {:?}", def_id, ev.direct);
+            }
+        }
+    }
+}
+
+impl<Id: Eq + Hash> EffectiveVisibilities<Id> {
+    pub fn iter(&self) -> impl Iterator<Item = (&Id, &EffectiveVisibility)> {
+        self.map.iter()
+    }
+
+    pub fn effective_vis(&self, id: Id) -> Option<&EffectiveVisibility> {
+        self.map.get(&id)
+    }
+
     // `parent_id` is not necessarily a parent in source code tree,
     // it is the node from which the maximum effective visibility is inherited.
     pub fn update(
         &mut self,
-        id: LocalDefId,
+        id: Id,
         nominal_vis: Visibility,
-        default_vis: impl FnOnce() -> Visibility,
-        parent_id: LocalDefId,
+        default_vis: Visibility,
+        inherited_eff_vis: Option<EffectiveVisibility>,
         level: Level,
         tree: impl DefIdTree,
     ) -> bool {
         let mut changed = false;
-        let mut current_effective_vis = self.effective_vis(id).copied().unwrap_or_else(|| {
-            if id.is_top_level_module() {
-                EffectiveVisibility::from_vis(Visibility::Public)
-            } else {
-                EffectiveVisibility::from_vis(default_vis())
-            }
-        });
-        if let Some(inherited_effective_vis) = self.effective_vis(parent_id) {
+        let mut current_effective_vis = self
+            .map
+            .get(&id)
+            .copied()
+            .unwrap_or_else(|| EffectiveVisibility::from_vis(default_vis));
+        if let Some(inherited_effective_vis) = inherited_eff_vis {
             let mut inherited_effective_vis_at_prev_level =
                 *inherited_effective_vis.at_level(level);
             let mut calculated_effective_vis = inherited_effective_vis_at_prev_level;
@@ -194,6 +270,12 @@ impl EffectiveVisibilities {
     }
 }
 
+impl<Id> Default for EffectiveVisibilities<Id> {
+    fn default() -> Self {
+        EffectiveVisibilities { map: Default::default() }
+    }
+}
+
 impl<'a> HashStable<StableHashingContext<'a>> for EffectiveVisibilities {
     fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
         let EffectiveVisibilities { ref map } = *self;
diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs
index 0a96d23e354..5290d5aae46 100644
--- a/compiler/rustc_middle/src/mir/mod.rs
+++ b/compiler/rustc_middle/src/mir/mod.rs
@@ -138,6 +138,48 @@ impl MirPhase {
             }
         }
     }
+
+    /// Parses an `MirPhase` from a pair of strings. Panics if this isn't possible for any reason.
+    pub fn parse(dialect: String, phase: Option<String>) -> Self {
+        match &*dialect.to_ascii_lowercase() {
+            "built" => {
+                assert!(phase.is_none(), "Cannot specify a phase for `Built` MIR");
+                MirPhase::Built
+            }
+            "analysis" => Self::Analysis(AnalysisPhase::parse(phase)),
+            "runtime" => Self::Runtime(RuntimePhase::parse(phase)),
+            _ => panic!("Unknown MIR dialect {}", dialect),
+        }
+    }
+}
+
+impl AnalysisPhase {
+    pub fn parse(phase: Option<String>) -> Self {
+        let Some(phase) = phase else {
+            return Self::Initial;
+        };
+
+        match &*phase.to_ascii_lowercase() {
+            "initial" => Self::Initial,
+            "post_cleanup" | "post-cleanup" | "postcleanup" => Self::PostCleanup,
+            _ => panic!("Unknown analysis phase {}", phase),
+        }
+    }
+}
+
+impl RuntimePhase {
+    pub fn parse(phase: Option<String>) -> Self {
+        let Some(phase) = phase else {
+            return Self::Initial;
+        };
+
+        match &*phase.to_ascii_lowercase() {
+            "initial" => Self::Initial,
+            "post_cleanup" | "post-cleanup" | "postcleanup" => Self::PostCleanup,
+            "optimized" => Self::Optimized,
+            _ => panic!("Unknown runtime phase {}", phase),
+        }
+    }
 }
 
 impl Display for MirPhase {
@@ -293,6 +335,13 @@ pub struct Body<'tcx> {
     /// potentially allow things like `[u8; std::mem::size_of::<T>() * 0]` due to this.
     pub is_polymorphic: bool,
 
+    /// The phase at which this MIR should be "injected" into the compilation process.
+    ///
+    /// Everything that comes before this `MirPhase` should be skipped.
+    ///
+    /// This is only `Some` if the function that this body comes from was annotated with `rustc_custom_mir`.
+    pub injection_phase: Option<MirPhase>,
+
     pub tainted_by_errors: Option<ErrorGuaranteed>,
 }
 
@@ -339,6 +388,7 @@ impl<'tcx> Body<'tcx> {
             span,
             required_consts: Vec::new(),
             is_polymorphic: false,
+            injection_phase: None,
             tainted_by_errors,
         };
         body.is_polymorphic = body.has_non_region_param();
@@ -366,6 +416,7 @@ impl<'tcx> Body<'tcx> {
             required_consts: Vec::new(),
             var_debug_info: Vec::new(),
             is_polymorphic: false,
+            injection_phase: None,
             tainted_by_errors: None,
         };
         body.is_polymorphic = body.has_non_region_param();
@@ -508,6 +559,14 @@ impl<'tcx> Body<'tcx> {
     pub fn generator_kind(&self) -> Option<GeneratorKind> {
         self.generator.as_ref().map(|generator| generator.generator_kind)
     }
+
+    #[inline]
+    pub fn should_skip(&self) -> bool {
+        let Some(injection_phase) = self.injection_phase else {
+            return false;
+        };
+        injection_phase > self.phase
+    }
 }
 
 #[derive(Copy, Clone, PartialEq, Eq, Debug, TyEncodable, TyDecodable, HashStable)]
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index 33acaed435b..00242e7eed7 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -271,6 +271,10 @@ rustc_queries! {
         desc { |tcx| "elaborating item bounds for `{}`", tcx.def_path_str(key) }
     }
 
+    /// Look up all native libraries this crate depends on.
+    /// These are assembled from the following places:
+    /// - `extern` blocks (depending on their `link` attributes)
+    /// - the `libs` (`-l`) option
     query native_libraries(_: CrateNum) -> Vec<NativeLib> {
         arena_cache
         desc { "looking up the native libraries of a linked crate" }
@@ -1539,6 +1543,7 @@ rustc_queries! {
         desc { "available upstream drop-glue for `{:?}`", substs }
     }
 
+    /// Returns a list of all `extern` blocks of a crate.
     query foreign_modules(_: CrateNum) -> FxHashMap<DefId, ForeignModule> {
         arena_cache
         desc { "looking up the foreign modules of a linked crate" }
@@ -1550,9 +1555,12 @@ rustc_queries! {
     query entry_fn(_: ()) -> Option<(DefId, EntryFnType)> {
         desc { "looking up the entry function of a crate" }
     }
+
+    /// Finds the `rustc_proc_macro_decls` item of a crate.
     query proc_macro_decls_static(_: ()) -> Option<LocalDefId> {
-        desc { "looking up the derive registrar for a crate" }
+        desc { "looking up the proc macro declarations for a crate" }
     }
+
     // The macro which defines `rustc_metadata::provide_extern` depends on this query's name.
     // Changing the name should cause a compiler error, but in case that changes, be aware.
     query crate_hash(_: CrateNum) -> Svh {
@@ -1560,17 +1568,24 @@ rustc_queries! {
         desc { "looking up the hash a crate" }
         separate_provide_extern
     }
+
+    /// Gets the hash for the host proc macro. Used to support -Z dual-proc-macro.
     query crate_host_hash(_: CrateNum) -> Option<Svh> {
         eval_always
         desc { "looking up the hash of a host version of a crate" }
         separate_provide_extern
     }
+
+    /// Gets the extra data to put in each output filename for a crate.
+    /// For example, compiling the `foo` crate with `extra-filename=-a` creates a `libfoo-b.rlib` file.
     query extra_filename(_: CrateNum) -> String {
         arena_cache
         eval_always
         desc { "looking up the extra filename for a crate" }
         separate_provide_extern
     }
+
+    /// Gets the paths where the crate came from in the file system.
     query crate_extern_paths(_: CrateNum) -> Vec<PathBuf> {
         arena_cache
         eval_always
@@ -1594,6 +1609,7 @@ rustc_queries! {
         separate_provide_extern
     }
 
+    /// Get the corresponding native library from the `native_libraries` query
     query native_library(def_id: DefId) -> Option<&'tcx NativeLib> {
         desc { |tcx| "getting the native library for `{}`", tcx.def_path_str(def_id) }
     }
diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs
index 07ee758b32c..05382bd887c 100644
--- a/compiler/rustc_middle/src/traits/mod.rs
+++ b/compiler/rustc_middle/src/traits/mod.rs
@@ -438,6 +438,8 @@ pub enum ObligationCauseCode<'tcx> {
     },
 
     AscribeUserTypeProvePredicate(Span),
+
+    RustCall,
 }
 
 /// The 'location' at which we try to perform HIR-based wf checking.
@@ -574,9 +576,6 @@ pub enum SelectionError<'tcx> {
     /// Signaling that an error has already been emitted, to avoid
     /// multiple errors being shown.
     ErrorReporting,
-    /// Multiple applicable `impl`s where found. The `DefId`s correspond to
-    /// all the `impl`s' Items.
-    Ambiguous(Vec<DefId>),
 }
 
 /// When performing resolution, it is typically the case that there
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index e039436fe0a..2a93df771e1 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -1283,6 +1283,12 @@ impl<'tcx> TyCtxt<'tcx> {
         }
     }
 
+    /// Constructs a `TyKind::Error` type with current `ErrorGuaranteed`
+    #[track_caller]
+    pub fn ty_error_with_guaranteed(self, reported: ErrorGuaranteed) -> Ty<'tcx> {
+        self.mk_ty(Error(reported))
+    }
+
     /// Constructs a `TyKind::Error` type and registers a `delay_span_bug` to ensure it gets used.
     #[track_caller]
     pub fn ty_error(self) -> Ty<'tcx> {
@@ -1297,6 +1303,16 @@ impl<'tcx> TyCtxt<'tcx> {
         self.mk_ty(Error(reported))
     }
 
+    /// Like [TyCtxt::ty_error] but for constants, with current `ErrorGuaranteed`
+    #[track_caller]
+    pub fn const_error_with_guaranteed(
+        self,
+        ty: Ty<'tcx>,
+        reported: ErrorGuaranteed,
+    ) -> Const<'tcx> {
+        self.mk_const(ty::ConstKind::Error(reported), ty)
+    }
+
     /// Like [TyCtxt::ty_error] but for constants.
     #[track_caller]
     pub fn const_error(self, ty: Ty<'tcx>) -> Const<'tcx> {
@@ -2813,7 +2829,9 @@ impl<'tcx> TyCtxt<'tcx> {
         span: impl Into<MultiSpan>,
         decorator: impl for<'a> DecorateLint<'a, ()>,
     ) {
-        self.struct_span_lint_hir(lint, hir_id, span, decorator.msg(), |diag| {
+        let msg = decorator.msg();
+        let (level, src) = self.lint_level_at_node(lint, hir_id);
+        struct_lint_level(self.sess, lint, level, src, Some(span.into()), msg, |diag| {
             decorator.decorate_lint(diag)
         })
     }
@@ -2823,6 +2841,7 @@ impl<'tcx> TyCtxt<'tcx> {
     /// Return value of the `decorate` closure is ignored, see [`struct_lint_level`] for a detailed explanation.
     ///
     /// [`struct_lint_level`]: rustc_middle::lint::struct_lint_level#decorate-signature
+    #[rustc_lint_diagnostics]
     pub fn struct_span_lint_hir(
         self,
         lint: &'static Lint,
@@ -2853,6 +2872,7 @@ impl<'tcx> TyCtxt<'tcx> {
     /// Return value of the `decorate` closure is ignored, see [`struct_lint_level`] for a detailed explanation.
     ///
     /// [`struct_lint_level`]: rustc_middle::lint::struct_lint_level#decorate-signature
+    #[rustc_lint_diagnostics]
     pub fn struct_lint_node(
         self,
         lint: &'static Lint,
diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs
index 4e6cdb78602..dc13374f992 100644
--- a/compiler/rustc_middle/src/ty/error.rs
+++ b/compiler/rustc_middle/src/ty/error.rs
@@ -430,7 +430,9 @@ impl<'tcx> TyCtxt<'tcx> {
                     (ty::Projection(_), ty::Projection(_)) => {
                         diag.note("an associated type was expected, but a different one was found");
                     }
-                    (ty::Param(p), ty::Projection(proj)) | (ty::Projection(proj), ty::Param(p)) => {
+                    (ty::Param(p), ty::Projection(proj)) | (ty::Projection(proj), ty::Param(p))
+                        if self.def_kind(proj.item_def_id) != DefKind::ImplTraitPlaceholder =>
+                    {
                         let generics = self.generics_of(body_owner_def_id);
                         let p_span = self.def_span(generics.type_param(p, self).def_id);
                         if !sp.contains(p_span) {
diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs
index a329753726e..2842b3c3102 100644
--- a/compiler/rustc_middle/src/ty/fold.rs
+++ b/compiler/rustc_middle/src/ty/fold.rs
@@ -598,7 +598,7 @@ impl<'tcx> TyCtxt<'tcx> {
             .replace_late_bound_regions(sig, |_| {
                 let br = ty::BoundRegion {
                     var: ty::BoundVar::from_u32(counter),
-                    kind: ty::BrAnon(counter),
+                    kind: ty::BrAnon(counter, None),
                 };
                 let r = self.mk_region(ty::ReLateBound(ty::INNERMOST, br));
                 counter += 1;
@@ -606,7 +606,7 @@ impl<'tcx> TyCtxt<'tcx> {
             })
             .0;
         let bound_vars = self.mk_bound_variable_kinds(
-            (0..counter).map(|i| ty::BoundVariableKind::Region(ty::BrAnon(i))),
+            (0..counter).map(|i| ty::BoundVariableKind::Region(ty::BrAnon(i, None))),
         );
         Binder::bind_with_vars(inner, bound_vars)
     }
@@ -626,7 +626,9 @@ impl<'tcx> TyCtxt<'tcx> {
                 let index = entry.index();
                 let var = ty::BoundVar::from_usize(index);
                 let kind = entry
-                    .or_insert_with(|| ty::BoundVariableKind::Region(ty::BrAnon(index as u32)))
+                    .or_insert_with(|| {
+                        ty::BoundVariableKind::Region(ty::BrAnon(index as u32, None))
+                    })
                     .expect_region();
                 let br = ty::BoundRegion { var, kind };
                 self.tcx.mk_region(ty::ReLateBound(ty::INNERMOST, br))
diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs
index 6c1414f7b8a..ae0f158ede9 100644
--- a/compiler/rustc_middle/src/ty/instance.rs
+++ b/compiler/rustc_middle/src/ty/instance.rs
@@ -511,12 +511,12 @@ impl<'tcx> Instance<'tcx> {
         Instance::resolve(tcx, ty::ParamEnv::reveal_all(), def_id, substs).unwrap().unwrap()
     }
 
+    #[instrument(level = "debug", skip(tcx), ret)]
     pub fn fn_once_adapter_instance(
         tcx: TyCtxt<'tcx>,
         closure_did: DefId,
         substs: ty::SubstsRef<'tcx>,
     ) -> Option<Instance<'tcx>> {
-        debug!("fn_once_adapter_shim({:?}, {:?})", closure_did, substs);
         let fn_once = tcx.require_lang_item(LangItem::FnOnce, None);
         let call_once = tcx
             .associated_items(fn_once)
@@ -536,7 +536,7 @@ impl<'tcx> Instance<'tcx> {
         assert_eq!(sig.inputs().len(), 1);
         let substs = tcx.mk_substs_trait(self_ty, &[sig.inputs()[0].into()]);
 
-        debug!("fn_once_adapter_shim: self_ty={:?} sig={:?}", self_ty, sig);
+        debug!(?self_ty, ?sig);
         Some(Instance { def, substs })
     }
 
diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs
index 3312f44c67b..c74d6bc3774 100644
--- a/compiler/rustc_middle/src/ty/layout.rs
+++ b/compiler/rustc_middle/src/ty/layout.rs
@@ -189,8 +189,8 @@ pub enum LayoutError<'tcx> {
     NormalizationFailure(Ty<'tcx>, NormalizationError<'tcx>),
 }
 
-impl<'a> IntoDiagnostic<'a, !> for LayoutError<'a> {
-    fn into_diagnostic(self, handler: &'a Handler) -> DiagnosticBuilder<'a, !> {
+impl IntoDiagnostic<'_, !> for LayoutError<'_> {
+    fn into_diagnostic(self, handler: &Handler) -> DiagnosticBuilder<'_, !> {
         let mut diag = handler.struct_fatal("");
 
         match self {
@@ -1126,8 +1126,8 @@ impl<'tcx> fmt::Display for FnAbiError<'tcx> {
     }
 }
 
-impl<'tcx> IntoDiagnostic<'tcx, !> for FnAbiError<'tcx> {
-    fn into_diagnostic(self, handler: &'tcx Handler) -> DiagnosticBuilder<'tcx, !> {
+impl IntoDiagnostic<'_, !> for FnAbiError<'_> {
+    fn into_diagnostic(self, handler: &Handler) -> DiagnosticBuilder<'_, !> {
         handler.struct_fatal(self.to_string())
     }
 }
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 27090c62d21..b509ae6dd3b 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -2550,11 +2550,11 @@ impl<'tcx> TyCtxt<'tcx> {
 
     /// Looks up the span of `impl_did` if the impl is local; otherwise returns `Err`
     /// with the name of the crate containing the impl.
-    pub fn span_of_impl(self, impl_did: DefId) -> Result<Span, Symbol> {
-        if let Some(impl_did) = impl_did.as_local() {
-            Ok(self.def_span(impl_did))
+    pub fn span_of_impl(self, impl_def_id: DefId) -> Result<Span, Symbol> {
+        if let Some(impl_def_id) = impl_def_id.as_local() {
+            Ok(self.def_span(impl_def_id))
         } else {
-            Err(self.crate_name(impl_did.krate))
+            Err(self.crate_name(impl_def_id.krate))
         }
     }
 
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index fab85c39d25..2432b517519 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -1659,6 +1659,12 @@ impl<'t> TyCtxt<'t> {
         debug!("def_path_str: def_id={:?}, ns={:?}", def_id, ns);
         FmtPrinter::new(self, ns).print_def_path(def_id, substs).unwrap().into_buffer()
     }
+
+    pub fn value_path_str_with_substs(self, def_id: DefId, substs: &'t [GenericArg<'t>]) -> String {
+        let ns = guess_def_namespace(self, def_id);
+        debug!("value_path_str: def_id={:?}, ns={:?}", def_id, ns);
+        FmtPrinter::new(self, ns).print_value_path(def_id, substs).unwrap().into_buffer()
+    }
 }
 
 impl fmt::Write for FmtPrinter<'_, '_> {
@@ -2115,7 +2121,7 @@ impl<'a, 'tcx> ty::TypeFolder<'tcx> for RegionFolder<'a, 'tcx> {
                 // If this is an anonymous placeholder, don't rename. Otherwise, in some
                 // async fns, we get a `for<'r> Send` bound
                 match kind {
-                    ty::BrAnon(_) | ty::BrEnv => r,
+                    ty::BrAnon(..) | ty::BrEnv => r,
                     _ => {
                         // Index doesn't matter, since this is just for naming and these never get bound
                         let br = ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind };
@@ -2226,10 +2232,10 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
                     let ty::BoundVariableKind::Region(var) = var else {
                     // This doesn't really matter because it doesn't get used,
                     // it's just an empty value
-                    return ty::BrAnon(0);
+                    return ty::BrAnon(0, None);
                 };
                     match var {
-                        ty::BrAnon(_) | ty::BrEnv => {
+                        ty::BrAnon(..) | ty::BrEnv => {
                             start_or_continue(&mut self, "for<", ", ");
                             let name = next_name(&self);
                             debug!(?name);
@@ -2271,7 +2277,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
                             binder_level_idx: ty::DebruijnIndex,
                             br: ty::BoundRegion| {
                 let (name, kind) = match br.kind {
-                    ty::BrAnon(_) | ty::BrEnv => {
+                    ty::BrAnon(..) | ty::BrEnv => {
                         let name = next_name(&self);
 
                         if let Some(lt_idx) = lifetime_idx {
diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs
index f2070869ce0..9f0598d0ba8 100644
--- a/compiler/rustc_middle/src/ty/structural_impls.rs
+++ b/compiler/rustc_middle/src/ty/structural_impls.rs
@@ -68,7 +68,7 @@ impl<'tcx> fmt::Debug for ty::adjustment::Adjustment<'tcx> {
 impl fmt::Debug for ty::BoundRegionKind {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match *self {
-            ty::BrAnon(n) => write!(f, "BrAnon({:?})", n),
+            ty::BrAnon(n, span) => write!(f, "BrAnon({n:?}, {span:?})"),
             ty::BrNamed(did, name) => {
                 if did.is_crate_root() {
                     write!(f, "BrNamed({})", name)
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index 5f108bf0ef3..49d82b503a4 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -59,7 +59,7 @@ pub struct FreeRegion {
 #[derive(HashStable)]
 pub enum BoundRegionKind {
     /// An anonymous region parameter for a given fn (&T)
-    BrAnon(u32),
+    BrAnon(u32, Option<Span>),
 
     /// Named region parameters for functions (a in &'a T)
     ///
diff --git a/compiler/rustc_middle/src/ty/visit.rs b/compiler/rustc_middle/src/ty/visit.rs
index f0e9f990a81..5e366ef703f 100644
--- a/compiler/rustc_middle/src/ty/visit.rs
+++ b/compiler/rustc_middle/src/ty/visit.rs
@@ -97,7 +97,11 @@ pub trait TypeVisitable<'tcx>: fmt::Debug + Clone {
     }
     fn error_reported(&self) -> Result<(), ErrorGuaranteed> {
         if self.references_error() {
-            Err(ErrorGuaranteed::unchecked_claim_error_was_emitted())
+            if let Some(reported) = ty::tls::with(|tcx| tcx.sess.has_errors()) {
+                Err(reported)
+            } else {
+                bug!("expect tcx.sess.has_errors return true");
+            }
         } else {
             Ok(())
         }
diff --git a/compiler/rustc_mir_build/src/build/custom/mod.rs b/compiler/rustc_mir_build/src/build/custom/mod.rs
new file mode 100644
index 00000000000..68d8766c907
--- /dev/null
+++ b/compiler/rustc_mir_build/src/build/custom/mod.rs
@@ -0,0 +1,155 @@
+//! Provides the implementation of the `custom_mir` attribute.
+//!
+//! Up until MIR building, this attribute has absolutely no effect. The `mir!` macro is a normal
+//! decl macro that expands like any other, and the code goes through parsing, name resolution and
+//! type checking like all other code. In MIR building we finally detect whether this attribute is
+//! present, and if so we branch off into this module, which implements the attribute by
+//! implementing a custom lowering from THIR to MIR.
+//!
+//! The result of this lowering is returned "normally" from the `mir_built` query, with the only
+//! notable difference being that the `injected` field in the body is set. Various components of the
+//! MIR pipeline, like borrowck and the pass manager will then consult this field (via
+//! `body.should_skip()`) to skip the parts of the MIR pipeline that precede the MIR phase the user
+//! specified.
+//!
+//! This file defines the general framework for the custom parsing. The parsing for all the
+//! "top-level" constructs can be found in the `parse` submodule, while the parsing for statements,
+//! terminators, and everything below can be found in the `parse::instruction` submodule.
+//!
+
+use rustc_ast::Attribute;
+use rustc_data_structures::fx::FxHashMap;
+use rustc_hir::def_id::DefId;
+use rustc_index::vec::IndexVec;
+use rustc_middle::{
+    mir::*,
+    thir::*,
+    ty::{Ty, TyCtxt},
+};
+use rustc_span::Span;
+
+mod parse;
+
+pub(super) fn build_custom_mir<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    did: DefId,
+    thir: &Thir<'tcx>,
+    expr: ExprId,
+    params: &IndexVec<ParamId, Param<'tcx>>,
+    return_ty: Ty<'tcx>,
+    return_ty_span: Span,
+    span: Span,
+    attr: &Attribute,
+) -> Body<'tcx> {
+    let mut body = Body {
+        basic_blocks: BasicBlocks::new(IndexVec::new()),
+        source: MirSource::item(did),
+        phase: MirPhase::Built,
+        source_scopes: IndexVec::new(),
+        generator: None,
+        local_decls: LocalDecls::new(),
+        user_type_annotations: IndexVec::new(),
+        arg_count: params.len(),
+        spread_arg: None,
+        var_debug_info: Vec::new(),
+        span,
+        required_consts: Vec::new(),
+        is_polymorphic: false,
+        tainted_by_errors: None,
+        injection_phase: None,
+        pass_count: 1,
+    };
+
+    body.local_decls.push(LocalDecl::new(return_ty, return_ty_span));
+    body.basic_blocks_mut().push(BasicBlockData::new(None));
+    body.source_scopes.push(SourceScopeData {
+        span,
+        parent_scope: None,
+        inlined: None,
+        inlined_parent_scope: None,
+        local_data: ClearCrossCrate::Clear,
+    });
+    body.injection_phase = Some(parse_attribute(attr));
+
+    let mut pctxt = ParseCtxt {
+        tcx,
+        thir,
+        source_info: SourceInfo { span, scope: OUTERMOST_SOURCE_SCOPE },
+        body: &mut body,
+        local_map: FxHashMap::default(),
+        block_map: FxHashMap::default(),
+    };
+
+    let res = (|| {
+        pctxt.parse_args(&params)?;
+        pctxt.parse_body(expr)
+    })();
+    if let Err(err) = res {
+        tcx.sess.diagnostic().span_fatal(
+            err.span,
+            format!("Could not parse {}, found: {:?}", err.expected, err.item_description),
+        )
+    }
+
+    body
+}
+
+fn parse_attribute(attr: &Attribute) -> MirPhase {
+    let meta_items = attr.meta_item_list().unwrap();
+    let mut dialect: Option<String> = None;
+    let mut phase: Option<String> = None;
+
+    for nested in meta_items {
+        let name = nested.name_or_empty();
+        let value = nested.value_str().unwrap().as_str().to_string();
+        match name.as_str() {
+            "dialect" => {
+                assert!(dialect.is_none());
+                dialect = Some(value);
+            }
+            "phase" => {
+                assert!(phase.is_none());
+                phase = Some(value);
+            }
+            other => {
+                panic!("Unexpected key {}", other);
+            }
+        }
+    }
+
+    let Some(dialect) = dialect else {
+        assert!(phase.is_none());
+        return MirPhase::Built;
+    };
+
+    MirPhase::parse(dialect, phase)
+}
+
+struct ParseCtxt<'tcx, 'body> {
+    tcx: TyCtxt<'tcx>,
+    thir: &'body Thir<'tcx>,
+    source_info: SourceInfo,
+
+    body: &'body mut Body<'tcx>,
+    local_map: FxHashMap<LocalVarId, Local>,
+    block_map: FxHashMap<LocalVarId, BasicBlock>,
+}
+
+struct ParseError {
+    span: Span,
+    item_description: String,
+    expected: String,
+}
+
+impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
+    fn expr_error(&self, expr: ExprId, expected: &'static str) -> ParseError {
+        let expr = &self.thir[expr];
+        ParseError {
+            span: expr.span,
+            item_description: format!("{:?}", expr.kind),
+            expected: expected.to_string(),
+        }
+    }
+}
+
+type PResult<T> = Result<T, ParseError>;
diff --git a/compiler/rustc_mir_build/src/build/custom/parse.rs b/compiler/rustc_mir_build/src/build/custom/parse.rs
new file mode 100644
index 00000000000..52cb0a4826d
--- /dev/null
+++ b/compiler/rustc_mir_build/src/build/custom/parse.rs
@@ -0,0 +1,245 @@
+use rustc_index::vec::IndexVec;
+use rustc_middle::{mir::*, thir::*, ty::Ty};
+use rustc_span::Span;
+
+use super::{PResult, ParseCtxt, ParseError};
+
+mod instruction;
+
+/// Helper macro for parsing custom MIR.
+///
+/// Example usage looks something like:
+/// ```rust,ignore (incomplete example)
+/// parse_by_kind!(
+///     self, // : &ParseCtxt
+///     expr_id, // what you're matching against
+///     "assignment", // the thing you're trying to parse
+///     @call("mir_assign", args) => { args[0] }, // match invocations of the `mir_assign` special function
+///     ExprKind::Assign { lhs, .. } => { lhs }, // match thir assignment expressions
+///     // no need for fallthrough case - reasonable error is automatically generated
+/// )
+/// ```
+macro_rules! parse_by_kind {
+    (
+        $self:ident,
+        $expr_id:expr,
+        $expected:literal,
+        $(
+            @call($name:literal, $args:ident) => $call_expr:expr,
+        )*
+        $(
+            $pat:pat => $expr:expr,
+        )*
+    ) => {{
+        let expr_id = $self.preparse($expr_id);
+        let expr = &$self.thir[expr_id];
+        match &expr.kind {
+            $(
+                ExprKind::Call { ty, fun: _, args: $args, .. } if {
+                    match ty.kind() {
+                        ty::FnDef(did, _) => {
+                            $self.tcx.is_diagnostic_item(rustc_span::Symbol::intern($name), *did)
+                        }
+                        _ => false,
+                    }
+                } => $call_expr,
+            )*
+            $(
+                $pat => $expr,
+            )*
+            #[allow(unreachable_patterns)]
+            _ => return Err($self.expr_error(expr_id, $expected))
+        }
+    }};
+}
+pub(crate) use parse_by_kind;
+
+impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
+    /// Expressions should only ever be matched on after preparsing them. This removes extra scopes
+    /// we don't care about.
+    fn preparse(&self, expr_id: ExprId) -> ExprId {
+        let expr = &self.thir[expr_id];
+        match expr.kind {
+            ExprKind::Scope { value, .. } => self.preparse(value),
+            _ => expr_id,
+        }
+    }
+
+    fn statement_as_expr(&self, stmt_id: StmtId) -> PResult<ExprId> {
+        match &self.thir[stmt_id].kind {
+            StmtKind::Expr { expr, .. } => Ok(*expr),
+            kind @ StmtKind::Let { pattern, .. } => {
+                return Err(ParseError {
+                    span: pattern.span,
+                    item_description: format!("{:?}", kind),
+                    expected: "expression".to_string(),
+                });
+            }
+        }
+    }
+
+    pub fn parse_args(&mut self, params: &IndexVec<ParamId, Param<'tcx>>) -> PResult<()> {
+        for param in params.iter() {
+            let (var, span) = {
+                let pat = param.pat.as_ref().unwrap();
+                match &pat.kind {
+                    PatKind::Binding { var, .. } => (*var, pat.span),
+                    _ => {
+                        return Err(ParseError {
+                            span: pat.span,
+                            item_description: format!("{:?}", pat.kind),
+                            expected: "local".to_string(),
+                        });
+                    }
+                }
+            };
+            let decl = LocalDecl::new(param.ty, span);
+            let local = self.body.local_decls.push(decl);
+            self.local_map.insert(var, local);
+        }
+
+        Ok(())
+    }
+
+    /// Bodies are of the form:
+    ///
+    /// ```text
+    /// {
+    ///     let bb1: BasicBlock;
+    ///     let bb2: BasicBlock;
+    ///     {
+    ///         let RET: _;
+    ///         let local1;
+    ///         let local2;
+    ///
+    ///         {
+    ///             { // entry block
+    ///                 statement1;
+    ///                 terminator1
+    ///             };
+    ///
+    ///             bb1 = {
+    ///                 statement2;
+    ///                 terminator2
+    ///             };
+    ///
+    ///             bb2 = {
+    ///                 statement3;
+    ///                 terminator3
+    ///             }
+    ///
+    ///             RET
+    ///         }
+    ///     }
+    /// }
+    /// ```
+    ///
+    /// This allows us to easily parse the basic blocks declarations, local declarations, and
+    /// basic block definitions in order.
+    pub fn parse_body(&mut self, expr_id: ExprId) -> PResult<()> {
+        let body = parse_by_kind!(self, expr_id, "whole body",
+            ExprKind::Block { block } => self.thir[*block].expr.unwrap(),
+        );
+        let (block_decls, rest) = parse_by_kind!(self, body, "body with block decls",
+            ExprKind::Block { block } => {
+                let block = &self.thir[*block];
+                (&block.stmts, block.expr.unwrap())
+            },
+        );
+        self.parse_block_decls(block_decls.iter().copied())?;
+
+        let (local_decls, rest) = parse_by_kind!(self, rest, "body with local decls",
+            ExprKind::Block { block } => {
+                let block = &self.thir[*block];
+                (&block.stmts, block.expr.unwrap())
+            },
+        );
+        self.parse_local_decls(local_decls.iter().copied())?;
+
+        let block_defs = parse_by_kind!(self, rest, "body with block defs",
+            ExprKind::Block { block } => &self.thir[*block].stmts,
+        );
+        for (i, block_def) in block_defs.iter().enumerate() {
+            let block = self.parse_block_def(self.statement_as_expr(*block_def)?)?;
+            self.body.basic_blocks_mut()[BasicBlock::from_usize(i)] = block;
+        }
+
+        Ok(())
+    }
+
+    fn parse_block_decls(&mut self, stmts: impl Iterator<Item = StmtId>) -> PResult<()> {
+        for stmt in stmts {
+            let (var, _, _) = self.parse_let_statement(stmt)?;
+            let data = BasicBlockData::new(None);
+            let block = self.body.basic_blocks_mut().push(data);
+            self.block_map.insert(var, block);
+        }
+
+        Ok(())
+    }
+
+    fn parse_local_decls(&mut self, mut stmts: impl Iterator<Item = StmtId>) -> PResult<()> {
+        let (ret_var, ..) = self.parse_let_statement(stmts.next().unwrap())?;
+        self.local_map.insert(ret_var, Local::from_u32(0));
+
+        for stmt in stmts {
+            let (var, ty, span) = self.parse_let_statement(stmt)?;
+            let decl = LocalDecl::new(ty, span);
+            let local = self.body.local_decls.push(decl);
+            self.local_map.insert(var, local);
+        }
+
+        Ok(())
+    }
+
+    fn parse_let_statement(&mut self, stmt_id: StmtId) -> PResult<(LocalVarId, Ty<'tcx>, Span)> {
+        let pattern = match &self.thir[stmt_id].kind {
+            StmtKind::Let { pattern, .. } => pattern,
+            StmtKind::Expr { expr, .. } => {
+                return Err(self.expr_error(*expr, "let statement"));
+            }
+        };
+
+        self.parse_var(pattern)
+    }
+
+    fn parse_var(&mut self, mut pat: &Pat<'tcx>) -> PResult<(LocalVarId, Ty<'tcx>, Span)> {
+        // Make sure we throw out any `AscribeUserType` we find
+        loop {
+            match &pat.kind {
+                PatKind::Binding { var, ty, .. } => break Ok((*var, *ty, pat.span)),
+                PatKind::AscribeUserType { subpattern, .. } => {
+                    pat = subpattern;
+                }
+                _ => {
+                    break Err(ParseError {
+                        span: pat.span,
+                        item_description: format!("{:?}", pat.kind),
+                        expected: "local".to_string(),
+                    });
+                }
+            }
+        }
+    }
+
+    fn parse_block_def(&self, expr_id: ExprId) -> PResult<BasicBlockData<'tcx>> {
+        let block = parse_by_kind!(self, expr_id, "basic block",
+            ExprKind::Block { block } => &self.thir[*block],
+        );
+
+        let mut data = BasicBlockData::new(None);
+        for stmt_id in &*block.stmts {
+            let stmt = self.statement_as_expr(*stmt_id)?;
+            let statement = self.parse_statement(stmt)?;
+            data.statements.push(Statement { source_info: self.source_info, kind: statement });
+        }
+
+        let Some(trailing) = block.expr else {
+            return Err(self.expr_error(expr_id, "terminator"))
+        };
+        let terminator = self.parse_terminator(trailing)?;
+        data.terminator = Some(Terminator { source_info: self.source_info, kind: terminator });
+
+        Ok(data)
+    }
+}
diff --git a/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs b/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs
new file mode 100644
index 00000000000..6d6176584f5
--- /dev/null
+++ b/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs
@@ -0,0 +1,72 @@
+use rustc_middle::{mir::*, thir::*, ty};
+
+use super::{parse_by_kind, PResult, ParseCtxt};
+
+impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
+    pub fn parse_statement(&self, expr_id: ExprId) -> PResult<StatementKind<'tcx>> {
+        parse_by_kind!(self, expr_id, "statement",
+            @call("mir_retag", args) => {
+                Ok(StatementKind::Retag(RetagKind::Default, Box::new(self.parse_place(args[0])?)))
+            },
+            @call("mir_retag_raw", args) => {
+                Ok(StatementKind::Retag(RetagKind::Raw, Box::new(self.parse_place(args[0])?)))
+            },
+            ExprKind::Assign { lhs, rhs } => {
+                let lhs = self.parse_place(*lhs)?;
+                let rhs = self.parse_rvalue(*rhs)?;
+                Ok(StatementKind::Assign(Box::new((lhs, rhs))))
+            },
+        )
+    }
+
+    pub fn parse_terminator(&self, expr_id: ExprId) -> PResult<TerminatorKind<'tcx>> {
+        parse_by_kind!(self, expr_id, "terminator",
+            @call("mir_return", _args) => {
+                Ok(TerminatorKind::Return)
+            },
+            @call("mir_goto", args) => {
+                Ok(TerminatorKind::Goto { target: self.parse_block(args[0])? } )
+            },
+        )
+    }
+
+    fn parse_rvalue(&self, expr_id: ExprId) -> PResult<Rvalue<'tcx>> {
+        parse_by_kind!(self, expr_id, "rvalue",
+            ExprKind::Borrow { borrow_kind, arg } => Ok(
+                Rvalue::Ref(self.tcx.lifetimes.re_erased, *borrow_kind, self.parse_place(*arg)?)
+            ),
+            ExprKind::AddressOf { mutability, arg } => Ok(
+                Rvalue::AddressOf(*mutability, self.parse_place(*arg)?)
+            ),
+            _ => self.parse_operand(expr_id).map(Rvalue::Use),
+        )
+    }
+
+    fn parse_operand(&self, expr_id: ExprId) -> PResult<Operand<'tcx>> {
+        parse_by_kind!(self, expr_id, "operand",
+            @call("mir_move", args) => self.parse_place(args[0]).map(Operand::Move),
+            _ => self.parse_place(expr_id).map(Operand::Copy),
+        )
+    }
+
+    fn parse_place(&self, expr_id: ExprId) -> PResult<Place<'tcx>> {
+        parse_by_kind!(self, expr_id, "place",
+            ExprKind::Deref { arg } => Ok(
+                self.parse_place(*arg)?.project_deeper(&[PlaceElem::Deref], self.tcx)
+            ),
+            _ => self.parse_local(expr_id).map(Place::from),
+        )
+    }
+
+    fn parse_local(&self, expr_id: ExprId) -> PResult<Local> {
+        parse_by_kind!(self, expr_id, "local",
+            ExprKind::VarRef { id } => Ok(self.local_map[id]),
+        )
+    }
+
+    fn parse_block(&self, expr_id: ExprId) -> PResult<BasicBlock> {
+        parse_by_kind!(self, expr_id, "basic block",
+            ExprKind::VarRef { id } => Ok(self.block_map[id]),
+        )
+    }
+}
diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs
index cbcf9cd129f..437ac8d82a1 100644
--- a/compiler/rustc_mir_build/src/build/mod.rs
+++ b/compiler/rustc_mir_build/src/build/mod.rs
@@ -481,6 +481,22 @@ fn construct_fn<'tcx>(
         (None, fn_sig.output())
     };
 
+    if let Some(custom_mir_attr) =
+        tcx.hir().attrs(fn_id).iter().find(|attr| attr.name_or_empty() == sym::custom_mir)
+    {
+        return custom::build_custom_mir(
+            tcx,
+            fn_def.did.to_def_id(),
+            thir,
+            expr,
+            arguments,
+            return_ty,
+            return_ty_span,
+            span,
+            custom_mir_attr,
+        );
+    }
+
     let infcx = tcx.infer_ctxt().build();
     let mut builder = Builder::new(
         thir,
@@ -1033,6 +1049,7 @@ pub(crate) fn parse_float_into_scalar(
 
 mod block;
 mod cfg;
+mod custom;
 mod expr;
 mod matches;
 mod misc;
diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs
index c7a7c3e3fa8..c4639d3a513 100644
--- a/compiler/rustc_mir_build/src/thir/cx/expr.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs
@@ -51,11 +51,17 @@ impl<'tcx> Cx<'tcx> {
         trace!(?expr.ty);
 
         // Now apply adjustments, if any.
-        for adjustment in self.typeck_results.expr_adjustments(hir_expr) {
-            trace!(?expr, ?adjustment);
-            let span = expr.span;
-            expr =
-                self.apply_adjustment(hir_expr, expr, adjustment, adjustment_span.unwrap_or(span));
+        if self.apply_adjustments {
+            for adjustment in self.typeck_results.expr_adjustments(hir_expr) {
+                trace!(?expr, ?adjustment);
+                let span = expr.span;
+                expr = self.apply_adjustment(
+                    hir_expr,
+                    expr,
+                    adjustment,
+                    adjustment_span.unwrap_or(span),
+                );
+            }
         }
 
         trace!(?expr.ty, "after adjustments");
diff --git a/compiler/rustc_mir_build/src/thir/cx/mod.rs b/compiler/rustc_mir_build/src/thir/cx/mod.rs
index 1d95d6b53fb..b5c4b7b137d 100644
--- a/compiler/rustc_mir_build/src/thir/cx/mod.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/mod.rs
@@ -80,6 +80,9 @@ struct Cx<'tcx> {
     /// for the receiver.
     adjustment_span: Option<(HirId, Span)>,
 
+    /// False to indicate that adjustments should not be applied. Only used for `custom_mir`
+    apply_adjustments: bool,
+
     /// The `DefId` of the owner of this body.
     body_owner: DefId,
 }
@@ -87,6 +90,8 @@ struct Cx<'tcx> {
 impl<'tcx> Cx<'tcx> {
     fn new(tcx: TyCtxt<'tcx>, def: ty::WithOptConstParam<LocalDefId>) -> Cx<'tcx> {
         let typeck_results = tcx.typeck_opt_const_arg(def);
+        let did = def.did;
+        let hir = tcx.hir();
         Cx {
             tcx,
             thir: Thir::new(),
@@ -94,8 +99,12 @@ impl<'tcx> Cx<'tcx> {
             region_scope_tree: tcx.region_scope_tree(def.did),
             typeck_results,
             rvalue_scopes: &typeck_results.rvalue_scopes,
-            body_owner: def.did.to_def_id(),
+            body_owner: did.to_def_id(),
             adjustment_span: None,
+            apply_adjustments: hir
+                .attrs(hir.local_def_id_to_hir_id(did))
+                .iter()
+                .all(|attr| attr.name_or_empty() != rustc_span::sym::custom_mir),
         }
     }
 
diff --git a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs
index 23403628c53..14d265a402e 100644
--- a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs
+++ b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs
@@ -407,9 +407,8 @@ where
         self.drop_ladder(fields, succ, unwind).0
     }
 
+    #[instrument(level = "debug", ret)]
     fn open_drop_for_box(&mut self, adt: ty::AdtDef<'tcx>, substs: SubstsRef<'tcx>) -> BasicBlock {
-        debug!("open_drop_for_box({:?}, {:?}, {:?})", self, adt, substs);
-
         // drop glue is sent straight to codegen
         // box cannot be directly dereferenced
         let unique_ty = adt.non_enum_variant().fields[0].ty(self.tcx(), substs);
@@ -431,8 +430,8 @@ where
         self.drop_subpath(interior, interior_path, succ, unwind_succ)
     }
 
+    #[instrument(level = "debug", ret)]
     fn open_drop_for_adt(&mut self, adt: ty::AdtDef<'tcx>, substs: SubstsRef<'tcx>) -> BasicBlock {
-        debug!("open_drop_for_adt({:?}, {:?}, {:?})", self, adt, substs);
         if adt.variants().is_empty() {
             return self.elaborator.patch().new_block(BasicBlockData {
                 statements: vec![],
diff --git a/compiler/rustc_mir_transform/src/check_unsafety.rs b/compiler/rustc_mir_transform/src/check_unsafety.rs
index 269d9f3b102..e783d189137 100644
--- a/compiler/rustc_mir_transform/src/check_unsafety.rs
+++ b/compiler/rustc_mir_transform/src/check_unsafety.rs
@@ -471,6 +471,14 @@ fn unsafety_check_result<'tcx>(
     // `mir_built` force this.
     let body = &tcx.mir_built(def).borrow();
 
+    if body.should_skip() {
+        return tcx.arena.alloc(UnsafetyCheckResult {
+            violations: Vec::new(),
+            used_unsafe_blocks: FxHashSet::default(),
+            unused_unsafes: Some(Vec::new()),
+        });
+    }
+
     let param_env = tcx.param_env(def.did);
 
     let mut checker = UnsafetyChecker::new(body, def.did, tcx, param_env);
diff --git a/compiler/rustc_mir_transform/src/pass_manager.rs b/compiler/rustc_mir_transform/src/pass_manager.rs
index 230c6a7cb4b..27dbc3e22c9 100644
--- a/compiler/rustc_mir_transform/src/pass_manager.rs
+++ b/compiler/rustc_mir_transform/src/pass_manager.rs
@@ -96,45 +96,48 @@ fn run_passes_inner<'tcx>(
     phase_change: Option<MirPhase>,
     validate_each: bool,
 ) {
-    let validate = validate_each & tcx.sess.opts.unstable_opts.validate_mir;
+    let validate = validate_each & tcx.sess.opts.unstable_opts.validate_mir & !body.should_skip();
     let overridden_passes = &tcx.sess.opts.unstable_opts.mir_enable_passes;
     trace!(?overridden_passes);
 
-    for pass in passes {
-        let name = pass.name();
-
-        let overridden =
-            overridden_passes.iter().rev().find(|(s, _)| s == &*name).map(|(_name, polarity)| {
-                trace!(
-                    pass = %name,
-                    "{} as requested by flag",
-                    if *polarity { "Running" } else { "Not running" },
-                );
-                *polarity
-            });
-        if !overridden.unwrap_or_else(|| pass.is_enabled(&tcx.sess)) {
-            continue;
+    if !body.should_skip() {
+        for pass in passes {
+            let name = pass.name();
+
+            let overridden = overridden_passes.iter().rev().find(|(s, _)| s == &*name).map(
+                |(_name, polarity)| {
+                    trace!(
+                        pass = %name,
+                        "{} as requested by flag",
+                        if *polarity { "Running" } else { "Not running" },
+                    );
+                    *polarity
+                },
+            );
+            if !overridden.unwrap_or_else(|| pass.is_enabled(&tcx.sess)) {
+                continue;
+            }
+
+            let dump_enabled = pass.is_mir_dump_enabled();
+
+            if dump_enabled {
+                dump_mir_for_pass(tcx, body, &name, false);
+            }
+            if validate {
+                validate_body(tcx, body, format!("before pass {}", name));
+            }
+
+            pass.run_pass(tcx, body);
+
+            if dump_enabled {
+                dump_mir_for_pass(tcx, body, &name, true);
+            }
+            if validate {
+                validate_body(tcx, body, format!("after pass {}", name));
+            }
+
+            body.pass_count += 1;
         }
-
-        let dump_enabled = pass.is_mir_dump_enabled();
-
-        if dump_enabled {
-            dump_mir_for_pass(tcx, body, &name, false);
-        }
-        if validate {
-            validate_body(tcx, body, format!("before pass {}", name));
-        }
-
-        pass.run_pass(tcx, body);
-
-        if dump_enabled {
-            dump_mir_for_pass(tcx, body, &name, true);
-        }
-        if validate {
-            validate_body(tcx, body, format!("after pass {}", name));
-        }
-
-        body.pass_count += 1;
     }
 
     if let Some(new_phase) = phase_change {
diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs
index bf590674144..a0ff7550fae 100644
--- a/compiler/rustc_mir_transform/src/shim.rs
+++ b/compiler/rustc_mir_transform/src/shim.rs
@@ -569,17 +569,13 @@ impl<'tcx> CloneShimBuilder<'tcx> {
 
 /// Builds a "call" shim for `instance`. The shim calls the function specified by `call_kind`,
 /// first adjusting its first argument according to `rcvr_adjustment`.
+#[instrument(level = "debug", skip(tcx), ret)]
 fn build_call_shim<'tcx>(
     tcx: TyCtxt<'tcx>,
     instance: ty::InstanceDef<'tcx>,
     rcvr_adjustment: Option<Adjustment>,
     call_kind: CallKind<'tcx>,
 ) -> Body<'tcx> {
-    debug!(
-        "build_call_shim(instance={:?}, rcvr_adjustment={:?}, call_kind={:?})",
-        instance, rcvr_adjustment, call_kind
-    );
-
     // `FnPtrShim` contains the fn pointer type that a call shim is being built for - this is used
     // to substitute into the signature of the shim. It is not necessary for users of this
     // MIR body to perform further substitutions (see `InstanceDef::has_polymorphic_mir_body`).
@@ -641,7 +637,7 @@ fn build_call_shim<'tcx>(
 
     let span = tcx.def_span(def_id);
 
-    debug!("build_call_shim: sig={:?}", sig);
+    debug!(?sig);
 
     let mut local_decls = local_decls_for_sig(&sig, span);
     let source_info = SourceInfo::outermost(span);
diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs
index dc204902842..e3acc11811f 100644
--- a/compiler/rustc_parse/src/errors.rs
+++ b/compiler/rustc_parse/src/errors.rs
@@ -369,6 +369,15 @@ pub(crate) struct MissingSemicolonBeforeArray {
 }
 
 #[derive(Diagnostic)]
+#[diag(parser_expect_dotdot_not_dotdotdot)]
+pub(crate) struct MissingDotDot {
+    #[primary_span]
+    pub token_span: Span,
+    #[suggestion(applicability = "maybe-incorrect", code = "..", style = "verbose")]
+    pub sugg_span: Span,
+}
+
+#[derive(Diagnostic)]
 #[diag(parser_invalid_block_macro_segment)]
 pub(crate) struct InvalidBlockMacroSegment {
     #[primary_span]
@@ -412,6 +421,15 @@ pub(crate) struct ExpectedExpressionFoundLet {
 }
 
 #[derive(Diagnostic)]
+#[diag(parser_expect_eq_instead_of_eqeq)]
+pub(crate) struct ExpectedEqForLetExpr {
+    #[primary_span]
+    pub span: Span,
+    #[suggestion(applicability = "maybe-incorrect", code = "=", style = "verbose")]
+    pub sugg_span: Span,
+}
+
+#[derive(Diagnostic)]
 #[diag(parser_expected_else_block)]
 pub(crate) struct ExpectedElseBlock {
     #[primary_span]
diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs
index 462bce16ad7..645262bd2f1 100644
--- a/compiler/rustc_parse/src/lexer/mod.rs
+++ b/compiler/rustc_parse/src/lexer/mod.rs
@@ -175,20 +175,10 @@ impl<'a> StringReader<'a> {
                         if string == "_" {
                             self.sess
                                 .span_diagnostic
-                                .struct_span_warn(
+                                .struct_span_err(
                                     self.mk_sp(suffix_start, self.pos),
                                     "underscore literal suffix is not allowed",
                                 )
-                                .warn(
-                                    "this was previously accepted by the compiler but is \
-                                       being phased out; it will become a hard error in \
-                                       a future release!",
-                                )
-                                .note(
-                                    "see issue #42326 \
-                                     <https://github.com/rust-lang/rust/issues/42326> \
-                                     for more information",
-                                )
                                 .emit();
                             None
                         } else {
@@ -363,55 +353,55 @@ impl<'a> StringReader<'a> {
     fn cook_lexer_literal(
         &self,
         start: BytePos,
-        suffix_start: BytePos,
+        end: BytePos,
         kind: rustc_lexer::LiteralKind,
     ) -> (token::LitKind, Symbol) {
-        // prefix means `"` or `br"` or `r###"`, ...
-        let (lit_kind, mode, prefix_len, postfix_len) = match kind {
+        match kind {
             rustc_lexer::LiteralKind::Char { terminated } => {
                 if !terminated {
                     self.sess.span_diagnostic.span_fatal_with_code(
-                        self.mk_sp(start, suffix_start),
+                        self.mk_sp(start, end),
                         "unterminated character literal",
                         error_code!(E0762),
                     )
                 }
-                (token::Char, Mode::Char, 1, 1) // ' '
+                self.cook_quoted(token::Char, Mode::Char, start, end, 1, 1) // ' '
             }
             rustc_lexer::LiteralKind::Byte { terminated } => {
                 if !terminated {
                     self.sess.span_diagnostic.span_fatal_with_code(
-                        self.mk_sp(start + BytePos(1), suffix_start),
+                        self.mk_sp(start + BytePos(1), end),
                         "unterminated byte constant",
                         error_code!(E0763),
                     )
                 }
-                (token::Byte, Mode::Byte, 2, 1) // b' '
+                self.cook_quoted(token::Byte, Mode::Byte, start, end, 2, 1) // b' '
             }
             rustc_lexer::LiteralKind::Str { terminated } => {
                 if !terminated {
                     self.sess.span_diagnostic.span_fatal_with_code(
-                        self.mk_sp(start, suffix_start),
+                        self.mk_sp(start, end),
                         "unterminated double quote string",
                         error_code!(E0765),
                     )
                 }
-                (token::Str, Mode::Str, 1, 1) // " "
+                self.cook_quoted(token::Str, Mode::Str, start, end, 1, 1) // " "
             }
             rustc_lexer::LiteralKind::ByteStr { terminated } => {
                 if !terminated {
                     self.sess.span_diagnostic.span_fatal_with_code(
-                        self.mk_sp(start + BytePos(1), suffix_start),
+                        self.mk_sp(start + BytePos(1), end),
                         "unterminated double quote byte string",
                         error_code!(E0766),
                     )
                 }
-                (token::ByteStr, Mode::ByteStr, 2, 1) // b" "
+                self.cook_quoted(token::ByteStr, Mode::ByteStr, start, end, 2, 1) // b" "
             }
             rustc_lexer::LiteralKind::RawStr { n_hashes } => {
                 if let Some(n_hashes) = n_hashes {
                     let n = u32::from(n_hashes);
-                    (token::StrRaw(n_hashes), Mode::RawStr, 2 + n, 1 + n) // r##" "##
+                    let kind = token::StrRaw(n_hashes);
+                    self.cook_quoted(kind, Mode::RawStr, start, end, 2 + n, 1 + n) // r##" "##
                 } else {
                     self.report_raw_str_error(start, 1);
                 }
@@ -419,56 +409,59 @@ impl<'a> StringReader<'a> {
             rustc_lexer::LiteralKind::RawByteStr { n_hashes } => {
                 if let Some(n_hashes) = n_hashes {
                     let n = u32::from(n_hashes);
-                    (token::ByteStrRaw(n_hashes), Mode::RawByteStr, 3 + n, 1 + n) // br##" "##
+                    let kind = token::ByteStrRaw(n_hashes);
+                    self.cook_quoted(kind, Mode::RawByteStr, start, end, 3 + n, 1 + n) // br##" "##
                 } else {
                     self.report_raw_str_error(start, 2);
                 }
             }
             rustc_lexer::LiteralKind::Int { base, empty_int } => {
-                return if empty_int {
+                if empty_int {
                     self.sess
                         .span_diagnostic
                         .struct_span_err_with_code(
-                            self.mk_sp(start, suffix_start),
+                            self.mk_sp(start, end),
                             "no valid digits found for number",
                             error_code!(E0768),
                         )
                         .emit();
                     (token::Integer, sym::integer(0))
                 } else {
-                    self.validate_int_literal(base, start, suffix_start);
-                    (token::Integer, self.symbol_from_to(start, suffix_start))
-                };
+                    if matches!(base, Base::Binary | Base::Octal) {
+                        let base = base as u32;
+                        let s = self.str_from_to(start + BytePos(2), end);
+                        for (idx, c) in s.char_indices() {
+                            if c != '_' && c.to_digit(base).is_none() {
+                                self.err_span_(
+                                    start + BytePos::from_usize(2 + idx),
+                                    start + BytePos::from_usize(2 + idx + c.len_utf8()),
+                                    &format!("invalid digit for a base {} literal", base),
+                                );
+                            }
+                        }
+                    }
+                    (token::Integer, self.symbol_from_to(start, end))
+                }
             }
             rustc_lexer::LiteralKind::Float { base, empty_exponent } => {
                 if empty_exponent {
                     self.err_span_(start, self.pos, "expected at least one digit in exponent");
                 }
-
                 match base {
-                    Base::Hexadecimal => self.err_span_(
-                        start,
-                        suffix_start,
-                        "hexadecimal float literal is not supported",
-                    ),
+                    Base::Hexadecimal => {
+                        self.err_span_(start, end, "hexadecimal float literal is not supported")
+                    }
                     Base::Octal => {
-                        self.err_span_(start, suffix_start, "octal float literal is not supported")
+                        self.err_span_(start, end, "octal float literal is not supported")
                     }
                     Base::Binary => {
-                        self.err_span_(start, suffix_start, "binary float literal is not supported")
+                        self.err_span_(start, end, "binary float literal is not supported")
                     }
-                    _ => (),
+                    _ => {}
                 }
-
-                let id = self.symbol_from_to(start, suffix_start);
-                return (token::Float, id);
+                (token::Float, self.symbol_from_to(start, end))
             }
-        };
-        let content_start = start + BytePos(prefix_len);
-        let content_end = suffix_start - BytePos(postfix_len);
-        let id = self.symbol_from_to(content_start, content_end);
-        self.validate_literal_escape(mode, content_start, content_end, prefix_len, postfix_len);
-        (lit_kind, id)
+        }
     }
 
     #[inline]
@@ -659,20 +652,22 @@ impl<'a> StringReader<'a> {
         )
     }
 
-    fn validate_literal_escape(
+    fn cook_quoted(
         &self,
+        kind: token::LitKind,
         mode: Mode,
-        content_start: BytePos,
-        content_end: BytePos,
+        start: BytePos,
+        end: BytePos,
         prefix_len: u32,
         postfix_len: u32,
-    ) {
+    ) -> (token::LitKind, Symbol) {
+        let content_start = start + BytePos(prefix_len);
+        let content_end = end - BytePos(postfix_len);
         let lit_content = self.str_from_to(content_start, content_end);
         unescape::unescape_literal(lit_content, mode, &mut |range, result| {
             // Here we only check for errors. The actual unescaping is done later.
             if let Err(err) = result {
-                let span_with_quotes = self
-                    .mk_sp(content_start - BytePos(prefix_len), content_end + BytePos(postfix_len));
+                let span_with_quotes = self.mk_sp(start, end);
                 let (start, end) = (range.start as u32, range.end as u32);
                 let lo = content_start + BytePos(start);
                 let hi = lo + BytePos(end - start);
@@ -688,23 +683,7 @@ impl<'a> StringReader<'a> {
                 );
             }
         });
-    }
-
-    fn validate_int_literal(&self, base: Base, content_start: BytePos, content_end: BytePos) {
-        let base = match base {
-            Base::Binary => 2,
-            Base::Octal => 8,
-            _ => return,
-        };
-        let s = self.str_from_to(content_start + BytePos(2), content_end);
-        for (idx, c) in s.char_indices() {
-            let idx = idx as u32;
-            if c != '_' && c.to_digit(base).is_none() {
-                let lo = content_start + BytePos(2 + idx);
-                let hi = content_start + BytePos(2 + idx + c.len_utf8() as u32);
-                self.err_span_(lo, hi, &format!("invalid digit for a base {} literal", base));
-            }
-        }
+        (kind, Symbol::intern(lit_content))
     }
 }
 
diff --git a/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs b/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs
index f075de71426..6373f5b4fd6 100644
--- a/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs
+++ b/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs
@@ -108,7 +108,7 @@ pub(crate) fn emit_unescape_error(
             }
 
             if !has_help {
-                let (prefix, msg) = if mode.is_bytes() {
+                let (prefix, msg) = if mode.is_byte() {
                     ("b", "if you meant to write a byte string literal, use double quotes")
                 } else {
                     ("", "if you meant to write a `str` literal, use double quotes")
@@ -142,7 +142,7 @@ pub(crate) fn emit_unescape_error(
         EscapeError::EscapeOnlyChar => {
             let (c, char_span) = last_char();
 
-            let msg = if mode.is_bytes() {
+            let msg = if mode.is_byte() {
                 "byte constant must be escaped"
             } else {
                 "character constant must be escaped"
@@ -182,11 +182,11 @@ pub(crate) fn emit_unescape_error(
             let (c, span) = last_char();
 
             let label =
-                if mode.is_bytes() { "unknown byte escape" } else { "unknown character escape" };
+                if mode.is_byte() { "unknown byte escape" } else { "unknown character escape" };
             let ec = escaped_char(c);
             let mut diag = handler.struct_span_err(span, &format!("{}: `{}`", label, ec));
             diag.span_label(span, label);
-            if c == '{' || c == '}' && !mode.is_bytes() {
+            if c == '{' || c == '}' && !mode.is_byte() {
                 diag.help(
                     "if used in a formatting string, curly braces are escaped with `{{` and `}}`",
                 );
@@ -196,7 +196,7 @@ pub(crate) fn emit_unescape_error(
                      version control settings",
                 );
             } else {
-                if !mode.is_bytes() {
+                if !mode.is_byte() {
                     diag.span_suggestion(
                         span_with_quotes,
                         "if you meant to write a literal backslash (perhaps escaping in a regular expression), consider a raw string literal",
@@ -231,16 +231,23 @@ pub(crate) fn emit_unescape_error(
                 .emit();
         }
         EscapeError::NonAsciiCharInByte => {
-            assert!(mode.is_bytes());
             let (c, span) = last_char();
-            let mut err = handler.struct_span_err(span, "non-ASCII character in byte constant");
+            let desc = match mode {
+                Mode::Byte => "byte literal",
+                Mode::ByteStr => "byte string literal",
+                Mode::RawByteStr => "raw byte string literal",
+                _ => panic!("non-is_byte literal paired with NonAsciiCharInByte"),
+            };
+            let mut err = handler.struct_span_err(span, format!("non-ASCII character in {}", desc));
             let postfix = if unicode_width::UnicodeWidthChar::width(c).unwrap_or(1) == 0 {
                 format!(" but is {:?}", c)
             } else {
                 String::new()
             };
-            err.span_label(span, &format!("byte constant must be ASCII{}", postfix));
-            if (c as u32) <= 0xFF {
+            err.span_label(span, &format!("must be ASCII{}", postfix));
+            // Note: the \\xHH suggestions are not given for raw byte string
+            // literals, because they are araw and so cannot use any escapes.
+            if (c as u32) <= 0xFF && mode != Mode::RawByteStr {
                 err.span_suggestion(
                     span,
                     &format!(
@@ -250,9 +257,9 @@ pub(crate) fn emit_unescape_error(
                     format!("\\x{:X}", c as u32),
                     Applicability::MaybeIncorrect,
                 );
-            } else if matches!(mode, Mode::Byte) {
+            } else if mode == Mode::Byte {
                 err.span_label(span, "this multibyte character does not fit into a single byte");
-            } else if matches!(mode, Mode::ByteStr) {
+            } else if mode != Mode::RawByteStr {
                 let mut utf8 = String::new();
                 utf8.push(c);
                 err.span_suggestion(
@@ -270,19 +277,6 @@ pub(crate) fn emit_unescape_error(
             }
             err.emit();
         }
-        EscapeError::NonAsciiCharInByteString => {
-            assert!(mode.is_bytes());
-            let (c, span) = last_char();
-            let postfix = if unicode_width::UnicodeWidthChar::width(c).unwrap_or(1) == 0 {
-                format!(" but is {:?}", c)
-            } else {
-                String::new()
-            };
-            handler
-                .struct_span_err(span, "raw byte string must be ASCII")
-                .span_label(span, &format!("must be ASCII{}", postfix))
-                .emit();
-        }
         EscapeError::OutOfRangeHexEscape => {
             handler
                 .struct_span_err(span, "out of range hex escape")
diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs
index 7dc4fd0044f..c609aa93da3 100644
--- a/compiler/rustc_parse/src/parser/diagnostics.rs
+++ b/compiler/rustc_parse/src/parser/diagnostics.rs
@@ -2468,11 +2468,15 @@ impl<'a> Parser<'a> {
     }
 
     pub(crate) fn maybe_recover_unexpected_block_label(&mut self) -> bool {
-        let Some(label) = self.eat_label().filter(|_| {
-            self.eat(&token::Colon) && self.token.kind == token::OpenDelim(Delimiter::Brace)
-        }) else {
+        // Check for `'a : {`
+        if !(self.check_lifetime()
+            && self.look_ahead(1, |tok| tok.kind == token::Colon)
+            && self.look_ahead(2, |tok| tok.kind == token::OpenDelim(Delimiter::Brace)))
+        {
             return false;
-        };
+        }
+        let label = self.eat_label().expect("just checked if a label exists");
+        self.bump(); // eat `:`
         let span = label.ident.span.to(self.prev_token.span);
         let mut err = self.struct_span_err(span, "block label not supported here");
         err.span_label(span, "not supported here");
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index 0eb633f6416..da2d20e47ee 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -9,9 +9,9 @@ use crate::errors::{
     ArrayBracketsInsteadOfSpaces, ArrayBracketsInsteadOfSpacesSugg, AsyncMoveOrderIncorrect,
     BinaryFloatLiteralNotSupported, BracesForStructLiteral, CatchAfterTry, CommaAfterBaseStruct,
     ComparisonInterpretedAsGeneric, ComparisonOrShiftInterpretedAsGenericSugg,
-    DoCatchSyntaxRemoved, DotDotDot, EqFieldInit, ExpectedElseBlock, ExpectedExpressionFoundLet,
-    FieldExpressionWithGeneric, FloatLiteralRequiresIntegerPart, FoundExprWouldBeStmt,
-    HexadecimalFloatLiteralNotSupported, IfExpressionMissingCondition,
+    DoCatchSyntaxRemoved, DotDotDot, EqFieldInit, ExpectedElseBlock, ExpectedEqForLetExpr,
+    ExpectedExpressionFoundLet, FieldExpressionWithGeneric, FloatLiteralRequiresIntegerPart,
+    FoundExprWouldBeStmt, HexadecimalFloatLiteralNotSupported, IfExpressionMissingCondition,
     IfExpressionMissingThenBlock, IfExpressionMissingThenBlockSub, IntLiteralTooLarge,
     InvalidBlockMacroSegment, InvalidComparisonOperator, InvalidComparisonOperatorSub,
     InvalidFloatLiteralSuffix, InvalidFloatLiteralWidth, InvalidIntLiteralWidth,
@@ -20,9 +20,9 @@ use crate::errors::{
     InvalidNumLiteralSuffix, LabeledLoopInBreak, LeadingPlusNotSupported, LeftArrowOperator,
     LifetimeInBorrowExpression, MacroInvocationWithQualifiedPath, MalformedLoopLabel,
     MatchArmBodyWithoutBraces, MatchArmBodyWithoutBracesSugg, MissingCommaAfterMatchArm,
-    MissingInInForLoop, MissingInInForLoopSub, MissingSemicolonBeforeArray, NoFieldsForFnCall,
-    NotAsNegationOperator, NotAsNegationOperatorSub, OctalFloatLiteralNotSupported,
-    OuterAttributeNotAllowedOnIfElse, ParenthesesWithStructFields,
+    MissingDotDot, MissingInInForLoop, MissingInInForLoopSub, MissingSemicolonBeforeArray,
+    NoFieldsForFnCall, NotAsNegationOperator, NotAsNegationOperatorSub,
+    OctalFloatLiteralNotSupported, OuterAttributeNotAllowedOnIfElse, ParenthesesWithStructFields,
     RequireColonAfterLabeledExpression, ShiftInterpretedAsGeneric, StructLiteralNotAllowedHere,
     StructLiteralNotAllowedHereSugg, TildeAsUnaryOperator, UnexpectedTokenAfterLabel,
     UnexpectedTokenAfterLabelSugg, WrapExpressionInParentheses,
@@ -833,16 +833,11 @@ impl<'a> Parser<'a> {
                 ("cast", None)
             };
 
-        // Save the memory location of expr before parsing any following postfix operators.
-        // This will be compared with the memory location of the output expression.
-        // If they different we can assume we parsed another expression because the existing expression is not reallocated.
-        let addr_before = &*cast_expr as *const _ as usize;
         let with_postfix = self.parse_dot_or_call_expr_with_(cast_expr, span)?;
-        let changed = addr_before != &*with_postfix as *const _ as usize;
 
         // Check if an illegal postfix operator has been added after the cast.
-        // If the resulting expression is not a cast, or has a different memory location, it is an illegal postfix operator.
-        if !matches!(with_postfix.kind, ExprKind::Cast(_, _) | ExprKind::Type(_, _)) || changed {
+        // If the resulting expression is not a cast, it is an illegal postfix operator.
+        if !matches!(with_postfix.kind, ExprKind::Cast(_, _) | ExprKind::Type(_, _)) {
             let msg = format!(
                 "{cast_kind} cannot be followed by {}",
                 match with_postfix.kind {
@@ -2334,7 +2329,15 @@ impl<'a> Parser<'a> {
             RecoverColon::Yes,
             CommaRecoveryMode::LikelyTuple,
         )?;
-        self.expect(&token::Eq)?;
+        if self.token == token::EqEq {
+            self.sess.emit_err(ExpectedEqForLetExpr {
+                span: self.token.span,
+                sugg_span: self.token.span,
+            });
+            self.bump();
+        } else {
+            self.expect(&token::Eq)?;
+        }
         let expr = self.with_res(self.restrictions | Restrictions::NO_STRUCT_LITERAL, |this| {
             this.parse_assoc_expr_with(1 + prec_let_scrutinee_needs_par(), None.into())
         })?;
@@ -2880,7 +2883,7 @@ impl<'a> Parser<'a> {
         };
 
         while self.token != token::CloseDelim(close_delim) {
-            if self.eat(&token::DotDot) {
+            if self.eat(&token::DotDot) || self.recover_struct_field_dots(close_delim) {
                 let exp_span = self.prev_token.span;
                 // We permit `.. }` on the left-hand side of a destructuring assignment.
                 if self.check(&token::CloseDelim(close_delim)) {
@@ -3027,6 +3030,18 @@ impl<'a> Parser<'a> {
         self.recover_stmt();
     }
 
+    fn recover_struct_field_dots(&mut self, close_delim: Delimiter) -> bool {
+        if !self.look_ahead(1, |t| *t == token::CloseDelim(close_delim))
+            && self.eat(&token::DotDotDot)
+        {
+            // recover from typo of `...`, suggest `..`
+            let span = self.prev_token.span;
+            self.sess.emit_err(MissingDotDot { token_span: span, sugg_span: span });
+            return true;
+        }
+        false
+    }
+
     /// Parses `ident (COLON expr)?`.
     fn parse_expr_field(&mut self) -> PResult<'a, ExprField> {
         let attrs = self.parse_outer_attributes()?;
diff --git a/compiler/rustc_parse_format/src/lib.rs b/compiler/rustc_parse_format/src/lib.rs
index 1394993abad..54bf4d1d6b7 100644
--- a/compiler/rustc_parse_format/src/lib.rs
+++ b/compiler/rustc_parse_format/src/lib.rs
@@ -819,19 +819,19 @@ fn find_skips_from_snippet(
     };
 
     fn find_skips(snippet: &str, is_raw: bool) -> Vec<usize> {
-        let mut s = snippet.char_indices().peekable();
+        let mut s = snippet.char_indices();
         let mut skips = vec![];
         while let Some((pos, c)) = s.next() {
-            match (c, s.peek()) {
+            match (c, s.clone().next()) {
                 // skip whitespace and empty lines ending in '\\'
                 ('\\', Some((next_pos, '\n'))) if !is_raw => {
                     skips.push(pos);
-                    skips.push(*next_pos);
+                    skips.push(next_pos);
                     let _ = s.next();
 
-                    while let Some((pos, c)) = s.peek() {
+                    while let Some((pos, c)) = s.clone().next() {
                         if matches!(c, ' ' | '\n' | '\t') {
-                            skips.push(*pos);
+                            skips.push(pos);
                             let _ = s.next();
                         } else {
                             break;
@@ -839,7 +839,7 @@ fn find_skips_from_snippet(
                     }
                 }
                 ('\\', Some((next_pos, 'n' | 't' | 'r' | '0' | '\\' | '\'' | '\"'))) => {
-                    skips.push(*next_pos);
+                    skips.push(next_pos);
                     let _ = s.next();
                 }
                 ('\\', Some((_, 'x'))) if !is_raw => {
@@ -858,19 +858,30 @@ fn find_skips_from_snippet(
                     }
                     if let Some((next_pos, next_c)) = s.next() {
                         if next_c == '{' {
-                            skips.push(next_pos);
-                            let mut i = 0; // consume up to 6 hexanumeric chars + closing `}`
-                            while let (Some((next_pos, c)), true) = (s.next(), i < 7) {
-                                if c.is_digit(16) {
-                                    skips.push(next_pos);
-                                } else if c == '}' {
-                                    skips.push(next_pos);
-                                    break;
-                                } else {
-                                    break;
-                                }
-                                i += 1;
+                            // consume up to 6 hexanumeric chars
+                            let digits_len =
+                                s.clone().take(6).take_while(|(_, c)| c.is_digit(16)).count();
+
+                            let len_utf8 = s
+                                .as_str()
+                                .get(..digits_len)
+                                .and_then(|digits| u32::from_str_radix(digits, 16).ok())
+                                .and_then(char::from_u32)
+                                .map_or(1, char::len_utf8);
+
+                            // Skip the digits, for chars that encode to more than 1 utf-8 byte
+                            // exclude as many digits as it is greater than 1 byte
+                            //
+                            // So for a 3 byte character, exclude 2 digits
+                            let required_skips =
+                                digits_len.saturating_sub(len_utf8.saturating_sub(1));
+
+                            // skip '{' and '}' also
+                            for pos in (next_pos..).take(required_skips + 2) {
+                                skips.push(pos)
                             }
+
+                            s.nth(digits_len);
                         } else if next_c.is_digit(16) {
                             skips.push(next_pos);
                             // We suggest adding `{` and `}` when appropriate, accept it here as if
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index 27a57adf964..0c34b0e1bf3 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -119,13 +119,13 @@ impl CheckAttrVisitor<'_> {
                 }
                 sym::naked => self.check_naked(hir_id, attr, span, target),
                 sym::rustc_legacy_const_generics => {
-                    self.check_rustc_legacy_const_generics(&attr, span, target, item)
+                    self.check_rustc_legacy_const_generics(hir_id, &attr, span, target, item)
                 }
                 sym::rustc_lint_query_instability => {
-                    self.check_rustc_lint_query_instability(&attr, span, target)
+                    self.check_rustc_lint_query_instability(hir_id, &attr, span, target)
                 }
                 sym::rustc_lint_diagnostics => {
-                    self.check_rustc_lint_diagnostics(&attr, span, target)
+                    self.check_rustc_lint_diagnostics(hir_id, &attr, span, target)
                 }
                 sym::rustc_lint_opt_ty => self.check_rustc_lint_opt_ty(&attr, span, target),
                 sym::rustc_lint_opt_deny_field_access => {
@@ -135,7 +135,9 @@ impl CheckAttrVisitor<'_> {
                 | sym::rustc_dirty
                 | sym::rustc_if_this_changed
                 | sym::rustc_then_this_would_need => self.check_rustc_dirty_clean(&attr),
-                sym::cmse_nonsecure_entry => self.check_cmse_nonsecure_entry(attr, span, target),
+                sym::cmse_nonsecure_entry => {
+                    self.check_cmse_nonsecure_entry(hir_id, attr, span, target)
+                }
                 sym::collapse_debuginfo => self.check_collapse_debuginfo(attr, span, target),
                 sym::const_trait => self.check_const_trait(attr, span, target),
                 sym::must_not_suspend => self.check_must_not_suspend(&attr, span, target),
@@ -386,6 +388,7 @@ impl CheckAttrVisitor<'_> {
                 self.tcx.sess.emit_err(errors::AttrShouldBeAppliedToFn {
                     attr_span: attr.span,
                     defn_span: span,
+                    on_crate: hir_id == CRATE_HIR_ID,
                 });
                 false
             }
@@ -393,7 +396,13 @@ impl CheckAttrVisitor<'_> {
     }
 
     /// Checks if `#[cmse_nonsecure_entry]` is applied to a function definition.
-    fn check_cmse_nonsecure_entry(&self, attr: &Attribute, span: Span, target: Target) -> bool {
+    fn check_cmse_nonsecure_entry(
+        &self,
+        hir_id: HirId,
+        attr: &Attribute,
+        span: Span,
+        target: Target,
+    ) -> bool {
         match target {
             Target::Fn
             | Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent) => true,
@@ -401,6 +410,7 @@ impl CheckAttrVisitor<'_> {
                 self.tcx.sess.emit_err(errors::AttrShouldBeAppliedToFn {
                     attr_span: attr.span,
                     defn_span: span,
+                    on_crate: hir_id == CRATE_HIR_ID,
                 });
                 false
             }
@@ -465,9 +475,11 @@ impl CheckAttrVisitor<'_> {
                 true
             }
             _ => {
-                self.tcx
-                    .sess
-                    .emit_err(errors::TrackedCallerWrongLocation { attr_span, defn_span: span });
+                self.tcx.sess.emit_err(errors::TrackedCallerWrongLocation {
+                    attr_span,
+                    defn_span: span,
+                    on_crate: hir_id == CRATE_HIR_ID,
+                });
                 false
             }
         }
@@ -576,6 +588,7 @@ impl CheckAttrVisitor<'_> {
                 self.tcx.sess.emit_err(errors::AttrShouldBeAppliedToFn {
                     attr_span: attr.span,
                     defn_span: span,
+                    on_crate: hir_id == CRATE_HIR_ID,
                 });
                 false
             }
@@ -1240,7 +1253,7 @@ impl CheckAttrVisitor<'_> {
                     UNUSED_ATTRIBUTES,
                     hir_id,
                     attr.span,
-                    errors::Cold { span },
+                    errors::Cold { span, on_crate: hir_id == CRATE_HIR_ID },
                 );
             }
         }
@@ -1376,6 +1389,7 @@ impl CheckAttrVisitor<'_> {
     /// Checks if `#[rustc_legacy_const_generics]` is applied to a function and has a valid argument.
     fn check_rustc_legacy_const_generics(
         &self,
+        hir_id: HirId,
         attr: &Attribute,
         span: Span,
         target: Target,
@@ -1386,6 +1400,7 @@ impl CheckAttrVisitor<'_> {
             self.tcx.sess.emit_err(errors::AttrShouldBeAppliedToFn {
                 attr_span: attr.span,
                 defn_span: span,
+                on_crate: hir_id == CRATE_HIR_ID,
             });
             return false;
         }
@@ -1450,12 +1465,19 @@ impl CheckAttrVisitor<'_> {
 
     /// Helper function for checking that the provided attribute is only applied to a function or
     /// method.
-    fn check_applied_to_fn_or_method(&self, attr: &Attribute, span: Span, target: Target) -> bool {
+    fn check_applied_to_fn_or_method(
+        &self,
+        hir_id: HirId,
+        attr: &Attribute,
+        span: Span,
+        target: Target,
+    ) -> bool {
         let is_function = matches!(target, Target::Fn | Target::Method(..));
         if !is_function {
             self.tcx.sess.emit_err(errors::AttrShouldBeAppliedToFn {
                 attr_span: attr.span,
                 defn_span: span,
+                on_crate: hir_id == CRATE_HIR_ID,
             });
             false
         } else {
@@ -1467,17 +1489,24 @@ impl CheckAttrVisitor<'_> {
     /// or method.
     fn check_rustc_lint_query_instability(
         &self,
+        hir_id: HirId,
         attr: &Attribute,
         span: Span,
         target: Target,
     ) -> bool {
-        self.check_applied_to_fn_or_method(attr, span, target)
+        self.check_applied_to_fn_or_method(hir_id, attr, span, target)
     }
 
     /// Checks that the `#[rustc_lint_diagnostics]` attribute is only applied to a function or
     /// method.
-    fn check_rustc_lint_diagnostics(&self, attr: &Attribute, span: Span, target: Target) -> bool {
-        self.check_applied_to_fn_or_method(attr, span, target)
+    fn check_rustc_lint_diagnostics(
+        &self,
+        hir_id: HirId,
+        attr: &Attribute,
+        span: Span,
+        target: Target,
+    ) -> bool {
+        self.check_applied_to_fn_or_method(hir_id, attr, span, target)
     }
 
     /// Checks that the `#[rustc_lint_opt_ty]` attribute is only applied to a struct.
diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs
index 1dbf0d642e2..c6cd69add28 100644
--- a/compiler/rustc_passes/src/errors.rs
+++ b/compiler/rustc_passes/src/errors.rs
@@ -81,6 +81,7 @@ pub struct AttrShouldBeAppliedToFn {
     pub attr_span: Span,
     #[label]
     pub defn_span: Span,
+    pub on_crate: bool,
 }
 
 #[derive(Diagnostic)]
@@ -97,6 +98,7 @@ pub struct TrackedCallerWrongLocation {
     pub attr_span: Span,
     #[label]
     pub defn_span: Span,
+    pub on_crate: bool,
 }
 
 #[derive(Diagnostic)]
@@ -367,6 +369,7 @@ pub struct MustNotSuspend {
 pub struct Cold {
     #[label]
     pub span: Span,
+    pub on_crate: bool,
 }
 
 #[derive(LintDiagnostic)]
diff --git a/compiler/rustc_passes/src/lib.rs b/compiler/rustc_passes/src/lib.rs
index 15f60f626c8..6e621b7eb5e 100644
--- a/compiler/rustc_passes/src/lib.rs
+++ b/compiler/rustc_passes/src/lib.rs
@@ -5,8 +5,6 @@
 //! This API is completely unstable and subject to change.
 
 #![allow(rustc::potential_query_instability)]
-#![deny(rustc::untranslatable_diagnostic)]
-#![deny(rustc::diagnostic_outside_of_impl)]
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
 #![feature(iter_intersperse)]
 #![feature(let_chains)]
diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs
index 865d6306bd3..e17f85c1aae 100644
--- a/compiler/rustc_privacy/src/lib.rs
+++ b/compiler/rustc_privacy/src/lib.rs
@@ -959,6 +959,10 @@ impl<'tcx, 'a> Visitor<'tcx> for TestReachabilityVisitor<'tcx, 'a> {
                 for variant in def.variants.iter() {
                     let variant_id = self.tcx.hir().local_def_id(variant.id);
                     self.effective_visibility_diagnostic(variant_id);
+                    if let Some(ctor_hir_id) = variant.data.ctor_hir_id() {
+                        let ctor_def_id = self.tcx.hir().local_def_id(ctor_hir_id);
+                        self.effective_visibility_diagnostic(ctor_def_id);
+                    }
                     for field in variant.data.fields() {
                         let def_id = self.tcx.hir().local_def_id(field.hir_id);
                         self.effective_visibility_diagnostic(def_id);
@@ -966,6 +970,10 @@ impl<'tcx, 'a> Visitor<'tcx> for TestReachabilityVisitor<'tcx, 'a> {
                 }
             }
             hir::ItemKind::Struct(ref def, _) | hir::ItemKind::Union(ref def, _) => {
+                if let Some(ctor_hir_id) = def.ctor_hir_id() {
+                    let ctor_def_id = self.tcx.hir().local_def_id(ctor_hir_id);
+                    self.effective_visibility_diagnostic(ctor_def_id);
+                }
                 for field in def.fields() {
                     let def_id = self.tcx.hir().local_def_id(field.hir_id);
                     self.effective_visibility_diagnostic(def_id);
@@ -2131,6 +2139,7 @@ fn effective_visibilities(tcx: TyCtxt<'_>, (): ()) -> &EffectiveVisibilities {
         changed: false,
     };
 
+    visitor.effective_visibilities.check_invariants(tcx, true);
     loop {
         tcx.hir().walk_toplevel_module(&mut visitor);
         if visitor.changed {
@@ -2139,6 +2148,7 @@ fn effective_visibilities(tcx: TyCtxt<'_>, (): ()) -> &EffectiveVisibilities {
             break;
         }
     }
+    visitor.effective_visibilities.check_invariants(tcx, false);
 
     let mut check_visitor =
         TestReachabilityVisitor { tcx, effective_visibilities: &visitor.effective_visibilities };
diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs
index 11d4c97e71c..18cb0e0ca0b 100644
--- a/compiler/rustc_query_impl/src/lib.rs
+++ b/compiler/rustc_query_impl/src/lib.rs
@@ -36,7 +36,7 @@ mod keys;
 use keys::Key;
 
 pub use rustc_query_system::query::QueryConfig;
-pub(crate) use rustc_query_system::query::{QueryDescription, QueryVTable};
+pub(crate) use rustc_query_system::query::QueryVTable;
 
 mod on_disk_cache;
 pub use on_disk_cache::OnDiskCache;
diff --git a/compiler/rustc_query_impl/src/on_disk_cache.rs b/compiler/rustc_query_impl/src/on_disk_cache.rs
index 8b14ce210a2..a6cb8f7bd55 100644
--- a/compiler/rustc_query_impl/src/on_disk_cache.rs
+++ b/compiler/rustc_query_impl/src/on_disk_cache.rs
@@ -1063,7 +1063,7 @@ pub fn encode_query_results<'a, 'tcx, CTX, Q>(
     query_result_index: &mut EncodedDepNodeIndex,
 ) where
     CTX: QueryContext + 'tcx,
-    Q: super::QueryDescription<CTX>,
+    Q: super::QueryConfig<CTX>,
     Q::Value: Encodable<CacheEncoder<'a, 'tcx>>,
 {
     let _timer = tcx
diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs
index 1d17f422196..992e777904e 100644
--- a/compiler/rustc_query_impl/src/plumbing.rs
+++ b/compiler/rustc_query_impl/src/plumbing.rs
@@ -17,8 +17,7 @@ use rustc_middle::ty::{self, TyCtxt};
 use rustc_query_system::dep_graph::{DepNodeParams, HasDepContext};
 use rustc_query_system::ich::StableHashingContext;
 use rustc_query_system::query::{
-    force_query, QueryConfig, QueryContext, QueryDescription, QueryJobId, QueryMap,
-    QuerySideEffects, QueryStackFrame,
+    force_query, QueryConfig, QueryContext, QueryJobId, QueryMap, QuerySideEffects, QueryStackFrame,
 };
 use rustc_query_system::{LayoutOfDepth, QueryOverflow, Value};
 use rustc_serialize::Decodable;
@@ -340,7 +339,7 @@ pub(crate) fn create_query_frame<
 
 fn try_load_from_on_disk_cache<'tcx, Q>(tcx: TyCtxt<'tcx>, dep_node: DepNode)
 where
-    Q: QueryDescription<QueryCtxt<'tcx>>,
+    Q: QueryConfig<QueryCtxt<'tcx>>,
     Q::Key: DepNodeParams<TyCtxt<'tcx>>,
 {
     debug_assert!(tcx.dep_graph.is_green(&dep_node));
@@ -365,7 +364,7 @@ where
 
 fn force_from_dep_node<'tcx, Q>(tcx: TyCtxt<'tcx>, dep_node: DepNode) -> bool
 where
-    Q: QueryDescription<QueryCtxt<'tcx>>,
+    Q: QueryConfig<QueryCtxt<'tcx>>,
     Q::Key: DepNodeParams<TyCtxt<'tcx>>,
     Q::Value: Value<TyCtxt<'tcx>>,
 {
@@ -398,12 +397,9 @@ where
     }
 }
 
-pub(crate) fn query_callback<'tcx, Q: QueryConfig>(
-    is_anon: bool,
-    is_eval_always: bool,
-) -> DepKindStruct<'tcx>
+pub(crate) fn query_callback<'tcx, Q>(is_anon: bool, is_eval_always: bool) -> DepKindStruct<'tcx>
 where
-    Q: QueryDescription<QueryCtxt<'tcx>>,
+    Q: QueryConfig<QueryCtxt<'tcx>>,
     Q::Key: DepNodeParams<TyCtxt<'tcx>>,
 {
     let fingerprint_style = Q::Key::fingerprint_style();
@@ -458,14 +454,12 @@ macro_rules! define_queries {
             })*
         }
 
-        $(impl<'tcx> QueryConfig for queries::$name<'tcx> {
+        $(impl<'tcx> QueryConfig<QueryCtxt<'tcx>> for queries::$name<'tcx> {
             type Key = query_keys::$name<'tcx>;
             type Value = query_values::$name<'tcx>;
             type Stored = query_stored::$name<'tcx>;
             const NAME: &'static str = stringify!($name);
-        }
 
-        impl<'tcx> QueryDescription<QueryCtxt<'tcx>> for queries::$name<'tcx> {
             #[inline]
             fn cache_on_disk(tcx: TyCtxt<'tcx>, key: &Self::Key) -> bool {
                 ::rustc_middle::query::cached::$name(tcx, key)
@@ -662,12 +656,15 @@ macro_rules! define_queries_struct {
             local_providers: Box<Providers>,
             extern_providers: Box<ExternProviders>,
             query_structs: Vec<$crate::plumbing::QueryStruct<'tcx>>,
-
             pub on_disk_cache: Option<OnDiskCache<'tcx>>,
-
             jobs: AtomicU64,
 
-            $($(#[$attr])*  $name: QueryState<<queries::$name<'tcx> as QueryConfig>::Key>,)*
+            $(
+                $(#[$attr])*
+                $name: QueryState<
+                    <queries::$name<'tcx> as QueryConfig<QueryCtxt<'tcx>>>::Key
+                >,
+            )*
         }
 
         impl<'tcx> Queries<'tcx> {
@@ -704,7 +701,7 @@ macro_rules! define_queries_struct {
                 &'tcx self,
                 tcx: TyCtxt<'tcx>,
                 span: Span,
-                key: <queries::$name<'tcx> as QueryConfig>::Key,
+                key: <queries::$name<'tcx> as QueryConfig<QueryCtxt<'tcx>>>::Key,
                 mode: QueryMode,
             ) -> Option<query_stored::$name<'tcx>> {
                 let qcx = QueryCtxt { tcx, queries: self };
diff --git a/compiler/rustc_query_impl/src/profiling_support.rs b/compiler/rustc_query_impl/src/profiling_support.rs
index 2cc311d48c8..81114f2cd82 100644
--- a/compiler/rustc_query_impl/src/profiling_support.rs
+++ b/compiler/rustc_query_impl/src/profiling_support.rs
@@ -19,18 +19,18 @@ impl QueryKeyStringCache {
     }
 }
 
-struct QueryKeyStringBuilder<'p, 'c, 'tcx> {
+struct QueryKeyStringBuilder<'p, 'tcx> {
     profiler: &'p SelfProfiler,
     tcx: TyCtxt<'tcx>,
-    string_cache: &'c mut QueryKeyStringCache,
+    string_cache: &'p mut QueryKeyStringCache,
 }
 
-impl<'p, 'c, 'tcx> QueryKeyStringBuilder<'p, 'c, 'tcx> {
+impl<'p, 'tcx> QueryKeyStringBuilder<'p, 'tcx> {
     fn new(
         profiler: &'p SelfProfiler,
         tcx: TyCtxt<'tcx>,
-        string_cache: &'c mut QueryKeyStringCache,
-    ) -> QueryKeyStringBuilder<'p, 'c, 'tcx> {
+        string_cache: &'p mut QueryKeyStringCache,
+    ) -> QueryKeyStringBuilder<'p, 'tcx> {
         QueryKeyStringBuilder { profiler, tcx, string_cache }
     }
 
@@ -99,7 +99,7 @@ impl<'p, 'c, 'tcx> QueryKeyStringBuilder<'p, 'c, 'tcx> {
 }
 
 trait IntoSelfProfilingString {
-    fn to_self_profile_string(&self, builder: &mut QueryKeyStringBuilder<'_, '_, '_>) -> StringId;
+    fn to_self_profile_string(&self, builder: &mut QueryKeyStringBuilder<'_, '_>) -> StringId;
 }
 
 // The default implementation of `IntoSelfProfilingString` just uses `Debug`
@@ -109,7 +109,7 @@ trait IntoSelfProfilingString {
 impl<T: Debug> IntoSelfProfilingString for T {
     default fn to_self_profile_string(
         &self,
-        builder: &mut QueryKeyStringBuilder<'_, '_, '_>,
+        builder: &mut QueryKeyStringBuilder<'_, '_>,
     ) -> StringId {
         let s = format!("{:?}", self);
         builder.profiler.alloc_string(&s[..])
@@ -117,60 +117,42 @@ impl<T: Debug> IntoSelfProfilingString for T {
 }
 
 impl<T: SpecIntoSelfProfilingString> IntoSelfProfilingString for T {
-    fn to_self_profile_string(&self, builder: &mut QueryKeyStringBuilder<'_, '_, '_>) -> StringId {
+    fn to_self_profile_string(&self, builder: &mut QueryKeyStringBuilder<'_, '_>) -> StringId {
         self.spec_to_self_profile_string(builder)
     }
 }
 
 #[rustc_specialization_trait]
 trait SpecIntoSelfProfilingString: Debug {
-    fn spec_to_self_profile_string(
-        &self,
-        builder: &mut QueryKeyStringBuilder<'_, '_, '_>,
-    ) -> StringId;
+    fn spec_to_self_profile_string(&self, builder: &mut QueryKeyStringBuilder<'_, '_>) -> StringId;
 }
 
 impl SpecIntoSelfProfilingString for DefId {
-    fn spec_to_self_profile_string(
-        &self,
-        builder: &mut QueryKeyStringBuilder<'_, '_, '_>,
-    ) -> StringId {
+    fn spec_to_self_profile_string(&self, builder: &mut QueryKeyStringBuilder<'_, '_>) -> StringId {
         builder.def_id_to_string_id(*self)
     }
 }
 
 impl SpecIntoSelfProfilingString for CrateNum {
-    fn spec_to_self_profile_string(
-        &self,
-        builder: &mut QueryKeyStringBuilder<'_, '_, '_>,
-    ) -> StringId {
+    fn spec_to_self_profile_string(&self, builder: &mut QueryKeyStringBuilder<'_, '_>) -> StringId {
         builder.def_id_to_string_id(self.as_def_id())
     }
 }
 
 impl SpecIntoSelfProfilingString for DefIndex {
-    fn spec_to_self_profile_string(
-        &self,
-        builder: &mut QueryKeyStringBuilder<'_, '_, '_>,
-    ) -> StringId {
+    fn spec_to_self_profile_string(&self, builder: &mut QueryKeyStringBuilder<'_, '_>) -> StringId {
         builder.def_id_to_string_id(DefId { krate: LOCAL_CRATE, index: *self })
     }
 }
 
 impl SpecIntoSelfProfilingString for LocalDefId {
-    fn spec_to_self_profile_string(
-        &self,
-        builder: &mut QueryKeyStringBuilder<'_, '_, '_>,
-    ) -> StringId {
+    fn spec_to_self_profile_string(&self, builder: &mut QueryKeyStringBuilder<'_, '_>) -> StringId {
         builder.def_id_to_string_id(DefId { krate: LOCAL_CRATE, index: self.local_def_index })
     }
 }
 
 impl<T: SpecIntoSelfProfilingString> SpecIntoSelfProfilingString for WithOptConstParam<T> {
-    fn spec_to_self_profile_string(
-        &self,
-        builder: &mut QueryKeyStringBuilder<'_, '_, '_>,
-    ) -> StringId {
+    fn spec_to_self_profile_string(&self, builder: &mut QueryKeyStringBuilder<'_, '_>) -> StringId {
         // We print `WithOptConstParam` values as tuples to make them shorter
         // and more readable, without losing information:
         //
@@ -205,10 +187,7 @@ where
     T0: SpecIntoSelfProfilingString,
     T1: SpecIntoSelfProfilingString,
 {
-    fn spec_to_self_profile_string(
-        &self,
-        builder: &mut QueryKeyStringBuilder<'_, '_, '_>,
-    ) -> StringId {
+    fn spec_to_self_profile_string(&self, builder: &mut QueryKeyStringBuilder<'_, '_>) -> StringId {
         let val0 = self.0.to_self_profile_string(builder);
         let val1 = self.1.to_self_profile_string(builder);
 
diff --git a/compiler/rustc_query_system/src/cache.rs b/compiler/rustc_query_system/src/cache.rs
index d592812f79b..7cc885be2ba 100644
--- a/compiler/rustc_query_system/src/cache.rs
+++ b/compiler/rustc_query_system/src/cache.rs
@@ -26,7 +26,7 @@ impl<Key, Value> Cache<Key, Value> {
 }
 
 impl<Key: Eq + Hash, Value: Clone> Cache<Key, Value> {
-    pub fn get<CTX: DepContext>(&self, key: &Key, tcx: CTX) -> Option<Value> {
+    pub fn get<Tcx: DepContext>(&self, key: &Key, tcx: Tcx) -> Option<Value> {
         Some(self.hashmap.borrow().get(key)?.get(tcx))
     }
 
@@ -46,7 +46,7 @@ impl<T: Clone> WithDepNode<T> {
         WithDepNode { dep_node, cached_value }
     }
 
-    pub fn get<CTX: DepContext>(&self, tcx: CTX) -> T {
+    pub fn get<Tcx: DepContext>(&self, tcx: Tcx) -> T {
         tcx.dep_graph().read_index(self.dep_node);
         self.cached_value.clone()
     }
diff --git a/compiler/rustc_query_system/src/dep_graph/dep_node.rs b/compiler/rustc_query_system/src/dep_graph/dep_node.rs
index 5c6ce0556eb..d79c5816a9c 100644
--- a/compiler/rustc_query_system/src/dep_graph/dep_node.rs
+++ b/compiler/rustc_query_system/src/dep_graph/dep_node.rs
@@ -61,18 +61,18 @@ impl<K: DepKind> DepNode<K> {
     /// Creates a new, parameterless DepNode. This method will assert
     /// that the DepNode corresponding to the given DepKind actually
     /// does not require any parameters.
-    pub fn new_no_params<Ctxt>(tcx: Ctxt, kind: K) -> DepNode<K>
+    pub fn new_no_params<Tcx>(tcx: Tcx, kind: K) -> DepNode<K>
     where
-        Ctxt: super::DepContext<DepKind = K>,
+        Tcx: super::DepContext<DepKind = K>,
     {
         debug_assert_eq!(tcx.fingerprint_style(kind), FingerprintStyle::Unit);
         DepNode { kind, hash: Fingerprint::ZERO.into() }
     }
 
-    pub fn construct<Ctxt, Key>(tcx: Ctxt, kind: K, arg: &Key) -> DepNode<K>
+    pub fn construct<Tcx, Key>(tcx: Tcx, kind: K, arg: &Key) -> DepNode<K>
     where
-        Ctxt: super::DepContext<DepKind = K>,
-        Key: DepNodeParams<Ctxt>,
+        Tcx: super::DepContext<DepKind = K>,
+        Key: DepNodeParams<Tcx>,
     {
         let hash = arg.to_fingerprint(tcx);
         let dep_node = DepNode { kind, hash: hash.into() };
@@ -93,9 +93,9 @@ impl<K: DepKind> DepNode<K> {
     /// Construct a DepNode from the given DepKind and DefPathHash. This
     /// method will assert that the given DepKind actually requires a
     /// single DefId/DefPathHash parameter.
-    pub fn from_def_path_hash<Ctxt>(tcx: Ctxt, def_path_hash: DefPathHash, kind: K) -> Self
+    pub fn from_def_path_hash<Tcx>(tcx: Tcx, def_path_hash: DefPathHash, kind: K) -> Self
     where
-        Ctxt: super::DepContext<DepKind = K>,
+        Tcx: super::DepContext<DepKind = K>,
     {
         debug_assert!(tcx.fingerprint_style(kind) == FingerprintStyle::DefPathHash);
         DepNode { kind, hash: def_path_hash.0.into() }
@@ -108,18 +108,18 @@ impl<K: DepKind> fmt::Debug for DepNode<K> {
     }
 }
 
-pub trait DepNodeParams<Ctxt: DepContext>: fmt::Debug + Sized {
+pub trait DepNodeParams<Tcx: DepContext>: fmt::Debug + Sized {
     fn fingerprint_style() -> FingerprintStyle;
 
     /// This method turns the parameters of a DepNodeConstructor into an opaque
     /// Fingerprint to be used in DepNode.
     /// Not all DepNodeParams support being turned into a Fingerprint (they
     /// don't need to if the corresponding DepNode is anonymous).
-    fn to_fingerprint(&self, _: Ctxt) -> Fingerprint {
+    fn to_fingerprint(&self, _: Tcx) -> Fingerprint {
         panic!("Not implemented. Accidentally called on anonymous node?")
     }
 
-    fn to_debug_str(&self, _: Ctxt) -> String {
+    fn to_debug_str(&self, _: Tcx) -> String {
         format!("{:?}", self)
     }
 
@@ -129,10 +129,10 @@ pub trait DepNodeParams<Ctxt: DepContext>: fmt::Debug + Sized {
     /// `fingerprint_style()` is not `FingerprintStyle::Opaque`.
     /// It is always valid to return `None` here, in which case incremental
     /// compilation will treat the query as having changed instead of forcing it.
-    fn recover(tcx: Ctxt, dep_node: &DepNode<Ctxt::DepKind>) -> Option<Self>;
+    fn recover(tcx: Tcx, dep_node: &DepNode<Tcx::DepKind>) -> Option<Self>;
 }
 
-impl<Ctxt: DepContext, T> DepNodeParams<Ctxt> for T
+impl<Tcx: DepContext, T> DepNodeParams<Tcx> for T
 where
     T: for<'a> HashStable<StableHashingContext<'a>> + fmt::Debug,
 {
@@ -142,7 +142,7 @@ where
     }
 
     #[inline(always)]
-    default fn to_fingerprint(&self, tcx: Ctxt) -> Fingerprint {
+    default fn to_fingerprint(&self, tcx: Tcx) -> Fingerprint {
         tcx.with_stable_hashing_context(|mut hcx| {
             let mut hasher = StableHasher::new();
             self.hash_stable(&mut hcx, &mut hasher);
@@ -151,12 +151,12 @@ where
     }
 
     #[inline(always)]
-    default fn to_debug_str(&self, _: Ctxt) -> String {
+    default fn to_debug_str(&self, _: Tcx) -> String {
         format!("{:?}", *self)
     }
 
     #[inline(always)]
-    default fn recover(_: Ctxt, _: &DepNode<Ctxt::DepKind>) -> Option<Self> {
+    default fn recover(_: Tcx, _: &DepNode<Tcx::DepKind>) -> Option<Self> {
         None
     }
 }
@@ -166,7 +166,7 @@ where
 /// Information is retrieved by indexing the `DEP_KINDS` array using the integer value
 /// of the `DepKind`. Overall, this allows to implement `DepContext` using this manual
 /// jump table instead of large matches.
-pub struct DepKindStruct<CTX: DepContext> {
+pub struct DepKindStruct<Tcx: DepContext> {
     /// Anonymous queries cannot be replayed from one compiler invocation to the next.
     /// When their result is needed, it is recomputed. They are useful for fine-grained
     /// dependency tracking, and caching within one compiler invocation.
@@ -216,10 +216,10 @@ pub struct DepKindStruct<CTX: DepContext> {
     /// with kind `MirValidated`, we know that the GUID/fingerprint of the `DepNode`
     /// is actually a `DefPathHash`, and can therefore just look up the corresponding
     /// `DefId` in `tcx.def_path_hash_to_def_id`.
-    pub force_from_dep_node: Option<fn(tcx: CTX, dep_node: DepNode<CTX::DepKind>) -> bool>,
+    pub force_from_dep_node: Option<fn(tcx: Tcx, dep_node: DepNode<Tcx::DepKind>) -> bool>,
 
     /// Invoke a query to put the on-disk cached value in memory.
-    pub try_load_from_on_disk_cache: Option<fn(CTX, DepNode<CTX::DepKind>)>,
+    pub try_load_from_on_disk_cache: Option<fn(Tcx, DepNode<Tcx::DepKind>)>,
 }
 
 /// A "work product" corresponds to a `.o` (or other) file that we
diff --git a/compiler/rustc_query_system/src/dep_graph/graph.rs b/compiler/rustc_query_system/src/dep_graph/graph.rs
index 8ff56132749..d86c0bebdcd 100644
--- a/compiler/rustc_query_system/src/dep_graph/graph.rs
+++ b/compiler/rustc_query_system/src/dep_graph/graph.rs
@@ -377,9 +377,9 @@ impl<K: DepKind> DepGraph<K> {
 
     /// Executes something within an "anonymous" task, that is, a task the
     /// `DepNode` of which is determined by the list of inputs it read from.
-    pub fn with_anon_task<Ctxt: DepContext<DepKind = K>, OP, R>(
+    pub fn with_anon_task<Tcx: DepContext<DepKind = K>, OP, R>(
         &self,
-        cx: Ctxt,
+        cx: Tcx,
         dep_kind: K,
         op: OP,
     ) -> (R, DepNodeIndex)
@@ -571,12 +571,12 @@ impl<K: DepKind> DepGraph<K> {
     /// A node will have an index, when it's already been marked green, or when we can mark it
     /// green. This function will mark the current task as a reader of the specified node, when
     /// a node index can be found for that node.
-    pub fn try_mark_green<Ctxt: QueryContext<DepKind = K>>(
+    pub fn try_mark_green<Qcx: QueryContext<DepKind = K>>(
         &self,
-        tcx: Ctxt,
+        qcx: Qcx,
         dep_node: &DepNode<K>,
     ) -> Option<(SerializedDepNodeIndex, DepNodeIndex)> {
-        debug_assert!(!tcx.dep_context().is_eval_always(dep_node.kind));
+        debug_assert!(!qcx.dep_context().is_eval_always(dep_node.kind));
 
         // Return None if the dep graph is disabled
         let data = self.data.as_ref()?;
@@ -592,15 +592,16 @@ impl<K: DepKind> DepGraph<K> {
                 // in the previous compilation session too, so we can try to
                 // mark it as green by recursively marking all of its
                 // dependencies green.
-                self.try_mark_previous_green(tcx, data, prev_index, &dep_node)
+                self.try_mark_previous_green(qcx, data, prev_index, &dep_node)
                     .map(|dep_node_index| (prev_index, dep_node_index))
             }
         }
     }
 
-    fn try_mark_parent_green<Ctxt: QueryContext<DepKind = K>>(
+    #[instrument(skip(self, qcx, data, parent_dep_node_index), level = "debug")]
+    fn try_mark_parent_green<Qcx: QueryContext<DepKind = K>>(
         &self,
-        tcx: Ctxt,
+        qcx: Qcx,
         data: &DepGraphData<K>,
         parent_dep_node_index: SerializedDepNodeIndex,
         dep_node: &DepNode<K>,
@@ -613,11 +614,7 @@ impl<K: DepKind> DepGraph<K> {
                 // This dependency has been marked as green before, we are
                 // still fine and can continue with checking the other
                 // dependencies.
-                debug!(
-                    "try_mark_previous_green({:?}) --- found dependency {:?} to \
-                            be immediately green",
-                    dep_node, dep_dep_node,
-                );
+                debug!("dependency {dep_dep_node:?} was immediately green");
                 return Some(());
             }
             Some(DepNodeColor::Red) => {
@@ -625,10 +622,7 @@ impl<K: DepKind> DepGraph<K> {
                 // compared to the previous compilation session. We cannot
                 // mark the DepNode as green and also don't need to bother
                 // with checking any of the other dependencies.
-                debug!(
-                    "try_mark_previous_green({:?}) - END - dependency {:?} was immediately red",
-                    dep_node, dep_dep_node,
-                );
+                debug!("dependency {dep_dep_node:?} was immediately red");
                 return None;
             }
             None => {}
@@ -636,35 +630,26 @@ impl<K: DepKind> DepGraph<K> {
 
         // We don't know the state of this dependency. If it isn't
         // an eval_always node, let's try to mark it green recursively.
-        if !tcx.dep_context().is_eval_always(dep_dep_node.kind) {
+        if !qcx.dep_context().is_eval_always(dep_dep_node.kind) {
             debug!(
-                "try_mark_previous_green({:?}) --- state of dependency {:?} ({}) \
-                                 is unknown, trying to mark it green",
-                dep_node, dep_dep_node, dep_dep_node.hash,
+                "state of dependency {:?} ({}) is unknown, trying to mark it green",
+                dep_dep_node, dep_dep_node.hash,
             );
 
             let node_index =
-                self.try_mark_previous_green(tcx, data, parent_dep_node_index, dep_dep_node);
+                self.try_mark_previous_green(qcx, data, parent_dep_node_index, dep_dep_node);
+
             if node_index.is_some() {
-                debug!(
-                    "try_mark_previous_green({:?}) --- managed to MARK dependency {:?} as green",
-                    dep_node, dep_dep_node
-                );
+                debug!("managed to MARK dependency {dep_dep_node:?} as green",);
                 return Some(());
             }
         }
 
         // We failed to mark it green, so we try to force the query.
-        debug!(
-            "try_mark_previous_green({:?}) --- trying to force dependency {:?}",
-            dep_node, dep_dep_node
-        );
-        if !tcx.dep_context().try_force_from_dep_node(*dep_dep_node) {
+        debug!("trying to force dependency {dep_dep_node:?}");
+        if !qcx.dep_context().try_force_from_dep_node(*dep_dep_node) {
             // The DepNode could not be forced.
-            debug!(
-                "try_mark_previous_green({:?}) - END - dependency {:?} could not be forced",
-                dep_node, dep_dep_node
-            );
+            debug!("dependency {dep_dep_node:?} could not be forced");
             return None;
         }
 
@@ -672,23 +657,17 @@ impl<K: DepKind> DepGraph<K> {
 
         match dep_dep_node_color {
             Some(DepNodeColor::Green(_)) => {
-                debug!(
-                    "try_mark_previous_green({:?}) --- managed to FORCE dependency {:?} to green",
-                    dep_node, dep_dep_node
-                );
+                debug!("managed to FORCE dependency {dep_dep_node:?} to green");
                 return Some(());
             }
             Some(DepNodeColor::Red) => {
-                debug!(
-                    "try_mark_previous_green({:?}) - END - dependency {:?} was red after forcing",
-                    dep_node, dep_dep_node
-                );
+                debug!("dependency {dep_dep_node:?} was red after forcing",);
                 return None;
             }
             None => {}
         }
 
-        if !tcx.dep_context().sess().has_errors_or_delayed_span_bugs() {
+        if !qcx.dep_context().sess().has_errors_or_delayed_span_bugs() {
             panic!("try_mark_previous_green() - Forcing the DepNode should have set its color")
         }
 
@@ -702,23 +681,19 @@ impl<K: DepKind> DepGraph<K> {
         // invalid state will not be persisted to the
         // incremental compilation cache because of
         // compilation errors being present.
-        debug!(
-            "try_mark_previous_green({:?}) - END - dependency {:?} resulted in compilation error",
-            dep_node, dep_dep_node
-        );
+        debug!("dependency {dep_dep_node:?} resulted in compilation error",);
         return None;
     }
 
     /// Try to mark a dep-node which existed in the previous compilation session as green.
-    fn try_mark_previous_green<Ctxt: QueryContext<DepKind = K>>(
+    #[instrument(skip(self, qcx, data, prev_dep_node_index), level = "debug")]
+    fn try_mark_previous_green<Qcx: QueryContext<DepKind = K>>(
         &self,
-        tcx: Ctxt,
+        qcx: Qcx,
         data: &DepGraphData<K>,
         prev_dep_node_index: SerializedDepNodeIndex,
         dep_node: &DepNode<K>,
     ) -> Option<DepNodeIndex> {
-        debug!("try_mark_previous_green({:?}) - BEGIN", dep_node);
-
         #[cfg(not(parallel_compiler))]
         {
             debug_assert!(!self.dep_node_exists(dep_node));
@@ -726,14 +701,14 @@ impl<K: DepKind> DepGraph<K> {
         }
 
         // We never try to mark eval_always nodes as green
-        debug_assert!(!tcx.dep_context().is_eval_always(dep_node.kind));
+        debug_assert!(!qcx.dep_context().is_eval_always(dep_node.kind));
 
         debug_assert_eq!(data.previous.index_to_node(prev_dep_node_index), *dep_node);
 
         let prev_deps = data.previous.edge_targets_from(prev_dep_node_index);
 
         for &dep_dep_node_index in prev_deps {
-            self.try_mark_parent_green(tcx, data, dep_dep_node_index, dep_node)?
+            self.try_mark_parent_green(qcx, data, dep_dep_node_index, dep_node)?
         }
 
         // If we got here without hitting a `return` that means that all
@@ -745,7 +720,7 @@ impl<K: DepKind> DepGraph<K> {
         // We allocating an entry for the node in the current dependency graph and
         // adding all the appropriate edges imported from the previous graph
         let dep_node_index = data.current.promote_node_and_deps_to_current(
-            tcx.dep_context().profiler(),
+            qcx.dep_context().profiler(),
             &data.previous,
             prev_dep_node_index,
         );
@@ -754,7 +729,7 @@ impl<K: DepKind> DepGraph<K> {
 
         // FIXME: Store the fact that a node has diagnostics in a bit in the dep graph somewhere
         // Maybe store a list on disk and encode this fact in the DepNodeState
-        let side_effects = tcx.load_side_effects(prev_dep_node_index);
+        let side_effects = qcx.load_side_effects(prev_dep_node_index);
 
         #[cfg(not(parallel_compiler))]
         debug_assert!(
@@ -765,14 +740,14 @@ impl<K: DepKind> DepGraph<K> {
         );
 
         if !side_effects.is_empty() {
-            self.emit_side_effects(tcx, data, dep_node_index, side_effects);
+            self.emit_side_effects(qcx, data, dep_node_index, side_effects);
         }
 
         // ... and finally storing a "Green" entry in the color map.
         // Multiple threads can all write the same color here
         data.colors.insert(prev_dep_node_index, DepNodeColor::Green(dep_node_index));
 
-        debug!("try_mark_previous_green({:?}) - END - successfully marked as green", dep_node);
+        debug!("successfully marked {dep_node:?} as green");
         Some(dep_node_index)
     }
 
@@ -780,9 +755,9 @@ impl<K: DepKind> DepGraph<K> {
     /// This may be called concurrently on multiple threads for the same dep node.
     #[cold]
     #[inline(never)]
-    fn emit_side_effects<Ctxt: QueryContext<DepKind = K>>(
+    fn emit_side_effects<Qcx: QueryContext<DepKind = K>>(
         &self,
-        tcx: Ctxt,
+        qcx: Qcx,
         data: &DepGraphData<K>,
         dep_node_index: DepNodeIndex,
         side_effects: QuerySideEffects,
@@ -794,9 +769,9 @@ impl<K: DepKind> DepGraph<K> {
             // must process side effects
 
             // Promote the previous diagnostics to the current session.
-            tcx.store_side_effects(dep_node_index, side_effects.clone());
+            qcx.store_side_effects(dep_node_index, side_effects.clone());
 
-            let handle = tcx.dep_context().sess().diagnostic();
+            let handle = qcx.dep_context().sess().diagnostic();
 
             for mut diagnostic in side_effects.diagnostics {
                 handle.emit_diagnostic(&mut diagnostic);
@@ -824,7 +799,7 @@ impl<K: DepKind> DepGraph<K> {
     //
     // This method will only load queries that will end up in the disk cache.
     // Other queries will not be executed.
-    pub fn exec_cache_promotions<Ctxt: DepContext<DepKind = K>>(&self, tcx: Ctxt) {
+    pub fn exec_cache_promotions<Tcx: DepContext<DepKind = K>>(&self, tcx: Tcx) {
         let _prof_timer = tcx.profiler().generic_activity("incr_comp_query_cache_promotion");
 
         let data = self.data.as_ref().unwrap();
diff --git a/compiler/rustc_query_system/src/dep_graph/mod.rs b/compiler/rustc_query_system/src/dep_graph/mod.rs
index da2075fd5aa..e370c6990a4 100644
--- a/compiler/rustc_query_system/src/dep_graph/mod.rs
+++ b/compiler/rustc_query_system/src/dep_graph/mod.rs
@@ -52,9 +52,8 @@ pub trait DepContext: Copy {
     }
 
     /// Try to force a dep node to execute and see if it's green.
+    #[instrument(skip(self), level = "debug")]
     fn try_force_from_dep_node(self, dep_node: DepNode<Self::DepKind>) -> bool {
-        debug!("try_force_from_dep_node({:?}) --- trying to force", dep_node);
-
         let cb = self.dep_kind_info(dep_node.kind);
         if let Some(f) = cb.force_from_dep_node {
             f(self, dep_node);
diff --git a/compiler/rustc_query_system/src/query/config.rs b/compiler/rustc_query_system/src/query/config.rs
index 0a1cffa3b33..f40e174b7e7 100644
--- a/compiler/rustc_query_system/src/query/config.rs
+++ b/compiler/rustc_query_system/src/query/config.rs
@@ -11,59 +11,57 @@ use rustc_data_structures::fingerprint::Fingerprint;
 use std::fmt::Debug;
 use std::hash::Hash;
 
-pub trait QueryConfig {
+pub trait QueryConfig<Qcx: QueryContext> {
     const NAME: &'static str;
 
     type Key: Eq + Hash + Clone + Debug;
     type Value;
     type Stored: Clone;
+
+    type Cache: QueryCache<Key = Self::Key, Stored = Self::Stored, Value = Self::Value>;
+
+    // Don't use this method to access query results, instead use the methods on TyCtxt
+    fn query_state<'a>(tcx: Qcx) -> &'a QueryState<Self::Key>
+    where
+        Qcx: 'a;
+
+    // Don't use this method to access query results, instead use the methods on TyCtxt
+    fn query_cache<'a>(tcx: Qcx) -> &'a Self::Cache
+    where
+        Qcx: 'a;
+
+    // Don't use this method to compute query results, instead use the methods on TyCtxt
+    fn make_vtable(tcx: Qcx, key: &Self::Key) -> QueryVTable<Qcx, Self::Key, Self::Value>;
+
+    fn cache_on_disk(tcx: Qcx::DepContext, key: &Self::Key) -> bool;
+
+    // Don't use this method to compute query results, instead use the methods on TyCtxt
+    fn execute_query(tcx: Qcx::DepContext, k: Self::Key) -> Self::Stored;
 }
 
 #[derive(Copy, Clone)]
-pub struct QueryVTable<CTX: QueryContext, K, V> {
+pub struct QueryVTable<Qcx: QueryContext, K, V> {
     pub anon: bool,
-    pub dep_kind: CTX::DepKind,
+    pub dep_kind: Qcx::DepKind,
     pub eval_always: bool,
     pub depth_limit: bool,
 
-    pub compute: fn(CTX::DepContext, K) -> V,
+    pub compute: fn(Qcx::DepContext, K) -> V,
     pub hash_result: Option<fn(&mut StableHashingContext<'_>, &V) -> Fingerprint>,
     pub handle_cycle_error: HandleCycleError,
     // NOTE: this is also `None` if `cache_on_disk()` returns false, not just if it's unsupported by the query
-    pub try_load_from_disk: Option<fn(CTX, SerializedDepNodeIndex) -> Option<V>>,
+    pub try_load_from_disk: Option<fn(Qcx, SerializedDepNodeIndex) -> Option<V>>,
 }
 
-impl<CTX: QueryContext, K, V> QueryVTable<CTX, K, V> {
-    pub(crate) fn to_dep_node(&self, tcx: CTX::DepContext, key: &K) -> DepNode<CTX::DepKind>
+impl<Qcx: QueryContext, K, V> QueryVTable<Qcx, K, V> {
+    pub(crate) fn to_dep_node(&self, tcx: Qcx::DepContext, key: &K) -> DepNode<Qcx::DepKind>
     where
-        K: crate::dep_graph::DepNodeParams<CTX::DepContext>,
+        K: crate::dep_graph::DepNodeParams<Qcx::DepContext>,
     {
         DepNode::construct(tcx, self.dep_kind, key)
     }
 
-    pub(crate) fn compute(&self, tcx: CTX::DepContext, key: K) -> V {
+    pub(crate) fn compute(&self, tcx: Qcx::DepContext, key: K) -> V {
         (self.compute)(tcx, key)
     }
 }
-
-pub trait QueryDescription<CTX: QueryContext>: QueryConfig {
-    type Cache: QueryCache<Key = Self::Key, Stored = Self::Stored, Value = Self::Value>;
-
-    // Don't use this method to access query results, instead use the methods on TyCtxt
-    fn query_state<'a>(tcx: CTX) -> &'a QueryState<Self::Key>
-    where
-        CTX: 'a;
-
-    // Don't use this method to access query results, instead use the methods on TyCtxt
-    fn query_cache<'a>(tcx: CTX) -> &'a Self::Cache
-    where
-        CTX: 'a;
-
-    // Don't use this method to compute query results, instead use the methods on TyCtxt
-    fn make_vtable(tcx: CTX, key: &Self::Key) -> QueryVTable<CTX, Self::Key, Self::Value>;
-
-    fn cache_on_disk(tcx: CTX::DepContext, key: &Self::Key) -> bool;
-
-    // Don't use this method to compute query results, instead use the methods on TyCtxt
-    fn execute_query(tcx: CTX::DepContext, k: Self::Key) -> Self::Stored;
-}
diff --git a/compiler/rustc_query_system/src/query/job.rs b/compiler/rustc_query_system/src/query/job.rs
index ed65393f57e..49bbcf57804 100644
--- a/compiler/rustc_query_system/src/query/job.rs
+++ b/compiler/rustc_query_system/src/query/job.rs
@@ -596,8 +596,8 @@ pub(crate) fn report_cycle<'a>(
     cycle_diag.into_diagnostic(&sess.parse_sess.span_diagnostic)
 }
 
-pub fn print_query_stack<CTX: QueryContext>(
-    tcx: CTX,
+pub fn print_query_stack<Qcx: QueryContext>(
+    qcx: Qcx,
     mut current_query: Option<QueryJobId>,
     handler: &Handler,
     num_frames: Option<usize>,
@@ -606,7 +606,7 @@ pub fn print_query_stack<CTX: QueryContext>(
     // a panic hook, which means that the global `Handler` may be in a weird
     // state if it was responsible for triggering the panic.
     let mut i = 0;
-    let query_map = tcx.try_collect_active_jobs();
+    let query_map = qcx.try_collect_active_jobs();
 
     while let Some(query) = current_query {
         if Some(i) == num_frames {
diff --git a/compiler/rustc_query_system/src/query/mod.rs b/compiler/rustc_query_system/src/query/mod.rs
index 118703fc0d4..94adef41e68 100644
--- a/compiler/rustc_query_system/src/query/mod.rs
+++ b/compiler/rustc_query_system/src/query/mod.rs
@@ -12,7 +12,7 @@ pub use self::caches::{
 };
 
 mod config;
-pub use self::config::{QueryConfig, QueryDescription, QueryVTable};
+pub use self::config::{QueryConfig, QueryVTable};
 
 use crate::dep_graph::{DepNodeIndex, HasDepContext, SerializedDepNodeIndex};
 use rustc_data_structures::sync::Lock;
diff --git a/compiler/rustc_query_system/src/query/plumbing.rs b/compiler/rustc_query_system/src/query/plumbing.rs
index 15b89daa6db..f8d93a27d1c 100644
--- a/compiler/rustc_query_system/src/query/plumbing.rs
+++ b/compiler/rustc_query_system/src/query/plumbing.rs
@@ -4,7 +4,7 @@
 
 use crate::dep_graph::{DepContext, DepNode, DepNodeIndex, DepNodeParams};
 use crate::query::caches::QueryCache;
-use crate::query::config::{QueryDescription, QueryVTable};
+use crate::query::config::QueryVTable;
 use crate::query::job::{report_cycle, QueryInfo, QueryJob, QueryJobId, QueryJobInfo};
 use crate::query::{QueryContext, QueryMap, QuerySideEffects, QueryStackFrame};
 use crate::values::Value;
@@ -27,6 +27,8 @@ use std::mem;
 use std::ptr;
 use thin_vec::ThinVec;
 
+use super::QueryConfig;
+
 pub struct QueryState<K> {
     #[cfg(parallel_compiler)]
     active: Sharded<FxHashMap<K, QueryResult>>,
@@ -60,10 +62,10 @@ where
         }
     }
 
-    pub fn try_collect_active_jobs<CTX: Copy>(
+    pub fn try_collect_active_jobs<Qcx: Copy>(
         &self,
-        tcx: CTX,
-        make_query: fn(CTX, K) -> QueryStackFrame,
+        qcx: Qcx,
+        make_query: fn(Qcx, K) -> QueryStackFrame,
         jobs: &mut QueryMap,
     ) -> Option<()> {
         #[cfg(parallel_compiler)]
@@ -74,7 +76,7 @@ where
             for shard in shards.iter() {
                 for (k, v) in shard.iter() {
                     if let QueryResult::Started(ref job) = *v {
-                        let query = make_query(tcx, k.clone());
+                        let query = make_query(qcx, k.clone());
                         jobs.insert(job.id, QueryJobInfo { query, job: job.clone() });
                     }
                 }
@@ -88,7 +90,7 @@ where
             // really hurt much.)
             for (k, v) in self.active.try_lock()?.iter() {
                 if let QueryResult::Started(ref job) = *v {
-                    let query = make_query(tcx, k.clone());
+                    let query = make_query(qcx, k.clone());
                     jobs.insert(job.id, QueryJobInfo { query, job: job.clone() });
                 }
             }
@@ -117,31 +119,31 @@ where
 
 #[cold]
 #[inline(never)]
-fn mk_cycle<CTX, V, R>(
-    tcx: CTX,
+fn mk_cycle<Qcx, V, R>(
+    qcx: Qcx,
     cycle_error: CycleError,
     handler: HandleCycleError,
     cache: &dyn crate::query::QueryStorage<Value = V, Stored = R>,
 ) -> R
 where
-    CTX: QueryContext,
-    V: std::fmt::Debug + Value<CTX::DepContext>,
+    Qcx: QueryContext,
+    V: std::fmt::Debug + Value<Qcx::DepContext>,
     R: Clone,
 {
-    let error = report_cycle(tcx.dep_context().sess(), &cycle_error);
-    let value = handle_cycle_error(*tcx.dep_context(), &cycle_error, error, handler);
+    let error = report_cycle(qcx.dep_context().sess(), &cycle_error);
+    let value = handle_cycle_error(*qcx.dep_context(), &cycle_error, error, handler);
     cache.store_nocache(value)
 }
 
-fn handle_cycle_error<CTX, V>(
-    tcx: CTX,
+fn handle_cycle_error<Tcx, V>(
+    tcx: Tcx,
     cycle_error: &CycleError,
     mut error: DiagnosticBuilder<'_, ErrorGuaranteed>,
     handler: HandleCycleError,
 ) -> V
 where
-    CTX: DepContext,
-    V: Value<CTX>,
+    Tcx: DepContext,
+    V: Value<Tcx>,
 {
     use HandleCycleError::*;
     match handler {
@@ -174,14 +176,14 @@ where
     /// This function is inlined because that results in a noticeable speed-up
     /// for some compile-time benchmarks.
     #[inline(always)]
-    fn try_start<'b, CTX>(
-        tcx: &'b CTX,
+    fn try_start<'b, Qcx>(
+        qcx: &'b Qcx,
         state: &'b QueryState<K>,
         span: Span,
         key: K,
     ) -> TryGetJob<'b, K>
     where
-        CTX: QueryContext,
+        Qcx: QueryContext,
     {
         #[cfg(parallel_compiler)]
         let mut state_lock = state.active.get_shard_by_value(&key).lock();
@@ -191,8 +193,8 @@ where
 
         match lock.entry(key) {
             Entry::Vacant(entry) => {
-                let id = tcx.next_job_id();
-                let job = tcx.current_query_job();
+                let id = qcx.next_job_id();
+                let job = qcx.current_query_job();
                 let job = QueryJob::new(id, span, job);
 
                 let key = entry.key().clone();
@@ -211,8 +213,8 @@ where
                         // If we are single-threaded we know that we have cycle error,
                         // so we just return the error.
                         return TryGetJob::Cycle(id.find_cycle_in_stack(
-                            tcx.try_collect_active_jobs().unwrap(),
-                            &tcx.current_query_job(),
+                            qcx.try_collect_active_jobs().unwrap(),
+                            &qcx.current_query_job(),
                             span,
                         ));
                     }
@@ -221,7 +223,7 @@ where
                         // For parallel queries, we'll block and wait until the query running
                         // in another thread has completed. Record how long we wait in the
                         // self-profiler.
-                        let query_blocked_prof_timer = tcx.dep_context().profiler().query_blocked();
+                        let query_blocked_prof_timer = qcx.dep_context().profiler().query_blocked();
 
                         // Get the latch out
                         let latch = job.latch();
@@ -230,7 +232,7 @@ where
 
                         // With parallel queries we might just have to wait on some other
                         // thread.
-                        let result = latch.wait_on(tcx.current_query_job(), span);
+                        let result = latch.wait_on(qcx.current_query_job(), span);
 
                         match result {
                             Ok(()) => TryGetJob::JobCompleted(query_blocked_prof_timer),
@@ -333,8 +335,8 @@ where
 /// which will be used if the query is not in the cache and we need
 /// to compute it.
 #[inline]
-pub fn try_get_cached<'a, CTX, C, R, OnHit>(
-    tcx: CTX,
+pub fn try_get_cached<'a, Tcx, C, R, OnHit>(
+    tcx: Tcx,
     cache: &'a C,
     key: &C::Key,
     // `on_hit` can be called while holding a lock to the query cache
@@ -342,7 +344,7 @@ pub fn try_get_cached<'a, CTX, C, R, OnHit>(
 ) -> Result<R, ()>
 where
     C: QueryCache,
-    CTX: DepContext,
+    Tcx: DepContext,
     OnHit: FnOnce(&C::Stored) -> R,
 {
     cache.lookup(&key, |value, index| {
@@ -354,29 +356,29 @@ where
     })
 }
 
-fn try_execute_query<CTX, C>(
-    tcx: CTX,
+fn try_execute_query<Qcx, C>(
+    qcx: Qcx,
     state: &QueryState<C::Key>,
     cache: &C,
     span: Span,
     key: C::Key,
-    dep_node: Option<DepNode<CTX::DepKind>>,
-    query: &QueryVTable<CTX, C::Key, C::Value>,
+    dep_node: Option<DepNode<Qcx::DepKind>>,
+    query: &QueryVTable<Qcx, C::Key, C::Value>,
 ) -> (C::Stored, Option<DepNodeIndex>)
 where
     C: QueryCache,
-    C::Key: Clone + DepNodeParams<CTX::DepContext>,
-    C::Value: Value<CTX::DepContext>,
-    CTX: QueryContext,
+    C::Key: Clone + DepNodeParams<Qcx::DepContext>,
+    C::Value: Value<Qcx::DepContext>,
+    Qcx: QueryContext,
 {
-    match JobOwner::<'_, C::Key>::try_start(&tcx, state, span, key.clone()) {
+    match JobOwner::<'_, C::Key>::try_start(&qcx, state, span, key.clone()) {
         TryGetJob::NotYetStarted(job) => {
-            let (result, dep_node_index) = execute_job(tcx, key, dep_node, query, job.id);
+            let (result, dep_node_index) = execute_job(qcx, key, dep_node, query, job.id);
             let result = job.complete(cache, result, dep_node_index);
             (result, Some(dep_node_index))
         }
         TryGetJob::Cycle(error) => {
-            let result = mk_cycle(tcx, error, query.handle_cycle_error, cache);
+            let result = mk_cycle(qcx, error, query.handle_cycle_error, cache);
             (result, None)
         }
         #[cfg(parallel_compiler)]
@@ -385,8 +387,8 @@ where
                 .lookup(&key, |value, index| (value.clone(), index))
                 .unwrap_or_else(|_| panic!("value must be in cache after waiting"));
 
-            if std::intrinsics::unlikely(tcx.dep_context().profiler().enabled()) {
-                tcx.dep_context().profiler().query_cache_hit(index.into());
+            if std::intrinsics::unlikely(qcx.dep_context().profiler().enabled()) {
+                qcx.dep_context().profiler().query_cache_hit(index.into());
             }
             query_blocked_prof_timer.finish_with_query_invocation_id(index.into());
 
@@ -395,25 +397,25 @@ where
     }
 }
 
-fn execute_job<CTX, K, V>(
-    tcx: CTX,
+fn execute_job<Qcx, K, V>(
+    qcx: Qcx,
     key: K,
-    mut dep_node_opt: Option<DepNode<CTX::DepKind>>,
-    query: &QueryVTable<CTX, K, V>,
+    mut dep_node_opt: Option<DepNode<Qcx::DepKind>>,
+    query: &QueryVTable<Qcx, K, V>,
     job_id: QueryJobId,
 ) -> (V, DepNodeIndex)
 where
-    K: Clone + DepNodeParams<CTX::DepContext>,
+    K: Clone + DepNodeParams<Qcx::DepContext>,
     V: Debug,
-    CTX: QueryContext,
+    Qcx: QueryContext,
 {
-    let dep_graph = tcx.dep_context().dep_graph();
+    let dep_graph = qcx.dep_context().dep_graph();
 
     // Fast path for when incr. comp. is off.
     if !dep_graph.is_fully_enabled() {
-        let prof_timer = tcx.dep_context().profiler().query_provider();
-        let result = tcx.start_query(job_id, query.depth_limit, None, || {
-            query.compute(*tcx.dep_context(), key)
+        let prof_timer = qcx.dep_context().profiler().query_provider();
+        let result = qcx.start_query(job_id, query.depth_limit, None, || {
+            query.compute(*qcx.dep_context(), key)
         });
         let dep_node_index = dep_graph.next_virtual_depnode_index();
         prof_timer.finish_with_query_invocation_id(dep_node_index.into());
@@ -423,33 +425,33 @@ where
     if !query.anon && !query.eval_always {
         // `to_dep_node` is expensive for some `DepKind`s.
         let dep_node =
-            dep_node_opt.get_or_insert_with(|| query.to_dep_node(*tcx.dep_context(), &key));
+            dep_node_opt.get_or_insert_with(|| query.to_dep_node(*qcx.dep_context(), &key));
 
         // The diagnostics for this query will be promoted to the current session during
         // `try_mark_green()`, so we can ignore them here.
-        if let Some(ret) = tcx.start_query(job_id, false, None, || {
-            try_load_from_disk_and_cache_in_memory(tcx, &key, &dep_node, query)
+        if let Some(ret) = qcx.start_query(job_id, false, None, || {
+            try_load_from_disk_and_cache_in_memory(qcx, &key, &dep_node, query)
         }) {
             return ret;
         }
     }
 
-    let prof_timer = tcx.dep_context().profiler().query_provider();
+    let prof_timer = qcx.dep_context().profiler().query_provider();
     let diagnostics = Lock::new(ThinVec::new());
 
     let (result, dep_node_index) =
-        tcx.start_query(job_id, query.depth_limit, Some(&diagnostics), || {
+        qcx.start_query(job_id, query.depth_limit, Some(&diagnostics), || {
             if query.anon {
-                return dep_graph.with_anon_task(*tcx.dep_context(), query.dep_kind, || {
-                    query.compute(*tcx.dep_context(), key)
+                return dep_graph.with_anon_task(*qcx.dep_context(), query.dep_kind, || {
+                    query.compute(*qcx.dep_context(), key)
                 });
             }
 
             // `to_dep_node` is expensive for some `DepKind`s.
             let dep_node =
-                dep_node_opt.unwrap_or_else(|| query.to_dep_node(*tcx.dep_context(), &key));
+                dep_node_opt.unwrap_or_else(|| query.to_dep_node(*qcx.dep_context(), &key));
 
-            dep_graph.with_task(dep_node, *tcx.dep_context(), key, query.compute, query.hash_result)
+            dep_graph.with_task(dep_node, *qcx.dep_context(), key, query.compute, query.hash_result)
         });
 
     prof_timer.finish_with_query_invocation_id(dep_node_index.into());
@@ -459,55 +461,55 @@ where
 
     if std::intrinsics::unlikely(!side_effects.is_empty()) {
         if query.anon {
-            tcx.store_side_effects_for_anon_node(dep_node_index, side_effects);
+            qcx.store_side_effects_for_anon_node(dep_node_index, side_effects);
         } else {
-            tcx.store_side_effects(dep_node_index, side_effects);
+            qcx.store_side_effects(dep_node_index, side_effects);
         }
     }
 
     (result, dep_node_index)
 }
 
-fn try_load_from_disk_and_cache_in_memory<CTX, K, V>(
-    tcx: CTX,
+fn try_load_from_disk_and_cache_in_memory<Qcx, K, V>(
+    qcx: Qcx,
     key: &K,
-    dep_node: &DepNode<CTX::DepKind>,
-    query: &QueryVTable<CTX, K, V>,
+    dep_node: &DepNode<Qcx::DepKind>,
+    query: &QueryVTable<Qcx, K, V>,
 ) -> Option<(V, DepNodeIndex)>
 where
     K: Clone,
-    CTX: QueryContext,
+    Qcx: QueryContext,
     V: Debug,
 {
     // Note this function can be called concurrently from the same query
     // We must ensure that this is handled correctly.
 
-    let dep_graph = tcx.dep_context().dep_graph();
-    let (prev_dep_node_index, dep_node_index) = dep_graph.try_mark_green(tcx, &dep_node)?;
+    let dep_graph = qcx.dep_context().dep_graph();
+    let (prev_dep_node_index, dep_node_index) = dep_graph.try_mark_green(qcx, &dep_node)?;
 
     debug_assert!(dep_graph.is_green(dep_node));
 
     // First we try to load the result from the on-disk cache.
     // Some things are never cached on disk.
     if let Some(try_load_from_disk) = query.try_load_from_disk {
-        let prof_timer = tcx.dep_context().profiler().incr_cache_loading();
+        let prof_timer = qcx.dep_context().profiler().incr_cache_loading();
 
         // The call to `with_query_deserialization` enforces that no new `DepNodes`
         // are created during deserialization. See the docs of that method for more
         // details.
         let result =
-            dep_graph.with_query_deserialization(|| try_load_from_disk(tcx, prev_dep_node_index));
+            dep_graph.with_query_deserialization(|| try_load_from_disk(qcx, prev_dep_node_index));
 
         prof_timer.finish_with_query_invocation_id(dep_node_index.into());
 
         if let Some(result) = result {
             if std::intrinsics::unlikely(
-                tcx.dep_context().sess().opts.unstable_opts.query_dep_graph,
+                qcx.dep_context().sess().opts.unstable_opts.query_dep_graph,
             ) {
                 dep_graph.mark_debug_loaded_from_disk(*dep_node)
             }
 
-            let prev_fingerprint = tcx
+            let prev_fingerprint = qcx
                 .dep_context()
                 .dep_graph()
                 .prev_fingerprint_of(dep_node)
@@ -521,9 +523,9 @@ where
             // give us some coverage of potential bugs though.
             let try_verify = prev_fingerprint.as_value().1 % 32 == 0;
             if std::intrinsics::unlikely(
-                try_verify || tcx.dep_context().sess().opts.unstable_opts.incremental_verify_ich,
+                try_verify || qcx.dep_context().sess().opts.unstable_opts.incremental_verify_ich,
             ) {
-                incremental_verify_ich(*tcx.dep_context(), &result, dep_node, query);
+                incremental_verify_ich(*qcx.dep_context(), &result, dep_node, query);
             }
 
             return Some((result, dep_node_index));
@@ -532,7 +534,7 @@ where
         // We always expect to find a cached result for things that
         // can be forced from `DepNode`.
         debug_assert!(
-            !tcx.dep_context().fingerprint_style(dep_node.kind).reconstructible(),
+            !qcx.dep_context().fingerprint_style(dep_node.kind).reconstructible(),
             "missing on-disk cache entry for {:?}",
             dep_node
         );
@@ -540,10 +542,10 @@ where
 
     // We could not load a result from the on-disk cache, so
     // recompute.
-    let prof_timer = tcx.dep_context().profiler().query_provider();
+    let prof_timer = qcx.dep_context().profiler().query_provider();
 
     // The dep-graph for this computation is already in-place.
-    let result = dep_graph.with_ignore(|| query.compute(*tcx.dep_context(), key.clone()));
+    let result = dep_graph.with_ignore(|| query.compute(*qcx.dep_context(), key.clone()));
 
     prof_timer.finish_with_query_invocation_id(dep_node_index.into());
 
@@ -556,34 +558,38 @@ where
     //
     // See issue #82920 for an example of a miscompilation that would get turned into
     // an ICE by this check
-    incremental_verify_ich(*tcx.dep_context(), &result, dep_node, query);
+    incremental_verify_ich(*qcx.dep_context(), &result, dep_node, query);
 
     Some((result, dep_node_index))
 }
 
-fn incremental_verify_ich<CTX, K, V: Debug>(
-    tcx: CTX::DepContext,
+#[instrument(skip(qcx, result, query), level = "debug")]
+fn incremental_verify_ich<Qcx, K, V: Debug>(
+    qcx: Qcx::DepContext,
     result: &V,
-    dep_node: &DepNode<CTX::DepKind>,
-    query: &QueryVTable<CTX, K, V>,
+    dep_node: &DepNode<Qcx::DepKind>,
+    query: &QueryVTable<Qcx, K, V>,
 ) where
-    CTX: QueryContext,
+    Qcx: QueryContext,
 {
     assert!(
-        tcx.dep_graph().is_green(dep_node),
+        qcx.dep_graph().is_green(dep_node),
         "fingerprint for green query instance not loaded from cache: {:?}",
         dep_node,
     );
 
-    debug!("BEGIN verify_ich({:?})", dep_node);
     let new_hash = query.hash_result.map_or(Fingerprint::ZERO, |f| {
-        tcx.with_stable_hashing_context(|mut hcx| f(&mut hcx, result))
+        qcx.with_stable_hashing_context(|mut hcx| f(&mut hcx, result))
     });
-    let old_hash = tcx.dep_graph().prev_fingerprint_of(dep_node);
-    debug!("END verify_ich({:?})", dep_node);
+
+    let old_hash = qcx.dep_graph().prev_fingerprint_of(dep_node);
 
     if Some(new_hash) != old_hash {
-        incremental_verify_ich_cold(tcx.sess(), DebugArg::from(&dep_node), DebugArg::from(&result));
+        incremental_verify_ich_failed(
+            qcx.sess(),
+            DebugArg::from(&dep_node),
+            DebugArg::from(&result),
+        );
     }
 }
 
@@ -629,13 +635,7 @@ impl std::fmt::Debug for DebugArg<'_> {
 // different implementations for LLVM to chew on (and filling up the final
 // binary, too).
 #[cold]
-fn incremental_verify_ich_cold(sess: &Session, dep_node: DebugArg<'_>, result: DebugArg<'_>) {
-    let run_cmd = if let Some(crate_name) = &sess.opts.crate_name {
-        format!("`cargo clean -p {}` or `cargo clean`", crate_name)
-    } else {
-        "`cargo clean`".to_string()
-    };
-
+fn incremental_verify_ich_failed(sess: &Session, dep_node: DebugArg<'_>, result: DebugArg<'_>) {
     // When we emit an error message and panic, we try to debug-print the `DepNode`
     // and query result. Unfortunately, this can cause us to run additional queries,
     // which may result in another fingerprint mismatch while we're in the middle
@@ -651,6 +651,12 @@ fn incremental_verify_ich_cold(sess: &Session, dep_node: DebugArg<'_>, result: D
     if old_in_panic {
         sess.emit_err(crate::error::Reentrant);
     } else {
+        let run_cmd = if let Some(crate_name) = &sess.opts.crate_name {
+            format!("`cargo clean -p {}` or `cargo clean`", crate_name)
+        } else {
+            "`cargo clean`".to_string()
+        };
+
         sess.emit_err(crate::error::IncrementCompilation {
             run_cmd,
             dep_node: format!("{:?}", dep_node),
@@ -670,14 +676,14 @@ fn incremental_verify_ich_cold(sess: &Session, dep_node: DebugArg<'_>, result: D
 ///
 /// Note: The optimization is only available during incr. comp.
 #[inline(never)]
-fn ensure_must_run<CTX, K, V>(
-    tcx: CTX,
+fn ensure_must_run<Qcx, K, V>(
+    qcx: Qcx,
     key: &K,
-    query: &QueryVTable<CTX, K, V>,
-) -> (bool, Option<DepNode<CTX::DepKind>>)
+    query: &QueryVTable<Qcx, K, V>,
+) -> (bool, Option<DepNode<Qcx::DepKind>>)
 where
-    K: crate::dep_graph::DepNodeParams<CTX::DepContext>,
-    CTX: QueryContext,
+    K: crate::dep_graph::DepNodeParams<Qcx::DepContext>,
+    Qcx: QueryContext,
 {
     if query.eval_always {
         return (true, None);
@@ -686,10 +692,10 @@ where
     // Ensuring an anonymous query makes no sense
     assert!(!query.anon);
 
-    let dep_node = query.to_dep_node(*tcx.dep_context(), key);
+    let dep_node = query.to_dep_node(*qcx.dep_context(), key);
 
-    let dep_graph = tcx.dep_context().dep_graph();
-    match dep_graph.try_mark_green(tcx, &dep_node) {
+    let dep_graph = qcx.dep_context().dep_graph();
+    match dep_graph.try_mark_green(qcx, &dep_node) {
         None => {
             // A None return from `try_mark_green` means that this is either
             // a new dep node or that the dep node has already been marked red.
@@ -701,7 +707,7 @@ where
         }
         Some((_, dep_node_index)) => {
             dep_graph.read_index(dep_node_index);
-            tcx.dep_context().profiler().query_cache_hit(dep_node_index.into());
+            qcx.dep_context().profiler().query_cache_hit(dep_node_index.into());
             (false, None)
         }
     }
@@ -713,16 +719,16 @@ pub enum QueryMode {
     Ensure,
 }
 
-pub fn get_query<Q, CTX>(tcx: CTX, span: Span, key: Q::Key, mode: QueryMode) -> Option<Q::Stored>
+pub fn get_query<Q, Qcx>(qcx: Qcx, span: Span, key: Q::Key, mode: QueryMode) -> Option<Q::Stored>
 where
-    Q: QueryDescription<CTX>,
-    Q::Key: DepNodeParams<CTX::DepContext>,
-    Q::Value: Value<CTX::DepContext>,
-    CTX: QueryContext,
+    Q: QueryConfig<Qcx>,
+    Q::Key: DepNodeParams<Qcx::DepContext>,
+    Q::Value: Value<Qcx::DepContext>,
+    Qcx: QueryContext,
 {
-    let query = Q::make_vtable(tcx, &key);
+    let query = Q::make_vtable(qcx, &key);
     let dep_node = if let QueryMode::Ensure = mode {
-        let (must_run, dep_node) = ensure_must_run(tcx, &key, &query);
+        let (must_run, dep_node) = ensure_must_run(qcx, &key, &query);
         if !must_run {
             return None;
         }
@@ -732,33 +738,33 @@ where
     };
 
     let (result, dep_node_index) = try_execute_query(
-        tcx,
-        Q::query_state(tcx),
-        Q::query_cache(tcx),
+        qcx,
+        Q::query_state(qcx),
+        Q::query_cache(qcx),
         span,
         key,
         dep_node,
         &query,
     );
     if let Some(dep_node_index) = dep_node_index {
-        tcx.dep_context().dep_graph().read_index(dep_node_index)
+        qcx.dep_context().dep_graph().read_index(dep_node_index)
     }
     Some(result)
 }
 
-pub fn force_query<Q, CTX>(tcx: CTX, key: Q::Key, dep_node: DepNode<CTX::DepKind>)
+pub fn force_query<Q, Qcx>(qcx: Qcx, key: Q::Key, dep_node: DepNode<Qcx::DepKind>)
 where
-    Q: QueryDescription<CTX>,
-    Q::Key: DepNodeParams<CTX::DepContext>,
-    Q::Value: Value<CTX::DepContext>,
-    CTX: QueryContext,
+    Q: QueryConfig<Qcx>,
+    Q::Key: DepNodeParams<Qcx::DepContext>,
+    Q::Value: Value<Qcx::DepContext>,
+    Qcx: QueryContext,
 {
     // We may be concurrently trying both execute and force a query.
     // Ensure that only one of them runs the query.
-    let cache = Q::query_cache(tcx);
+    let cache = Q::query_cache(qcx);
     let cached = cache.lookup(&key, |_, index| {
-        if std::intrinsics::unlikely(tcx.dep_context().profiler().enabled()) {
-            tcx.dep_context().profiler().query_cache_hit(index.into());
+        if std::intrinsics::unlikely(qcx.dep_context().profiler().enabled()) {
+            qcx.dep_context().profiler().query_cache_hit(index.into());
         }
     });
 
@@ -767,9 +773,9 @@ where
         Err(()) => {}
     }
 
-    let query = Q::make_vtable(tcx, &key);
-    let state = Q::query_state(tcx);
+    let query = Q::make_vtable(qcx, &key);
+    let state = Q::query_state(qcx);
     debug_assert!(!query.anon);
 
-    try_execute_query(tcx, state, cache, DUMMY_SP, key, Some(dep_node), &query);
+    try_execute_query(qcx, state, cache, DUMMY_SP, key, Some(dep_node), &query);
 }
diff --git a/compiler/rustc_query_system/src/values.rs b/compiler/rustc_query_system/src/values.rs
index 67fbf14e612..214656abed4 100644
--- a/compiler/rustc_query_system/src/values.rs
+++ b/compiler/rustc_query_system/src/values.rs
@@ -1,12 +1,12 @@
 use crate::dep_graph::DepContext;
 use crate::query::QueryInfo;
 
-pub trait Value<CTX: DepContext>: Sized {
-    fn from_cycle_error(tcx: CTX, cycle: &[QueryInfo]) -> Self;
+pub trait Value<Tcx: DepContext>: Sized {
+    fn from_cycle_error(tcx: Tcx, cycle: &[QueryInfo]) -> Self;
 }
 
-impl<CTX: DepContext, T> Value<CTX> for T {
-    default fn from_cycle_error(tcx: CTX, _: &[QueryInfo]) -> T {
+impl<Tcx: DepContext, T> Value<Tcx> for T {
+    default fn from_cycle_error(tcx: Tcx, _: &[QueryInfo]) -> T {
         tcx.sess().abort_if_errors();
         // Ideally we would use `bug!` here. But bug! is only defined in rustc_middle, and it's
         // non-trivial to define it earlier.
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index 7961e3f1194..a12918b2979 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -241,10 +241,12 @@ impl<'a> Resolver<'a> {
         ));
 
         err.span_label(span, format!("`{}` re{} here", name, new_participle));
-        err.span_label(
-            self.session.source_map().guess_head_span(old_binding.span),
-            format!("previous {} of the {} `{}` here", old_noun, old_kind, name),
-        );
+        if !old_binding.span.is_dummy() && old_binding.span != span {
+            err.span_label(
+                self.session.source_map().guess_head_span(old_binding.span),
+                format!("previous {} of the {} `{}` here", old_noun, old_kind, name),
+            );
+        }
 
         // See https://github.com/rust-lang/rust/issues/32354
         use NameBindingKind::Import;
diff --git a/compiler/rustc_resolve/src/effective_visibilities.rs b/compiler/rustc_resolve/src/effective_visibilities.rs
index 17ce854cb43..fa6d34be0cc 100644
--- a/compiler/rustc_resolve/src/effective_visibilities.rs
+++ b/compiler/rustc_resolve/src/effective_visibilities.rs
@@ -1,16 +1,38 @@
-use crate::{ImportKind, NameBindingKind, Resolver};
+use crate::{ImportKind, NameBinding, NameBindingKind, Resolver, ResolverTree};
 use rustc_ast::ast;
 use rustc_ast::visit;
 use rustc_ast::visit::Visitor;
 use rustc_ast::Crate;
 use rustc_ast::EnumDef;
+use rustc_data_structures::intern::Interned;
 use rustc_hir::def_id::LocalDefId;
 use rustc_hir::def_id::CRATE_DEF_ID;
-use rustc_middle::middle::privacy::Level;
-use rustc_middle::ty::{DefIdTree, Visibility};
+use rustc_middle::middle::privacy::{EffectiveVisibilities, EffectiveVisibility, Level};
+use rustc_middle::ty::Visibility;
+
+type ImportId<'a> = Interned<'a, NameBinding<'a>>;
+
+#[derive(Clone, Copy)]
+enum ParentId<'a> {
+    Def(LocalDefId),
+    Import(ImportId<'a>),
+}
+
+impl ParentId<'_> {
+    fn level(self) -> Level {
+        match self {
+            ParentId::Def(_) => Level::Direct,
+            ParentId::Import(_) => Level::Reexported,
+        }
+    }
+}
 
 pub struct EffectiveVisibilitiesVisitor<'r, 'a> {
     r: &'r mut Resolver<'a>,
+    /// While walking import chains we need to track effective visibilities per-binding, and def id
+    /// keys in `Resolver::effective_visibilities` are not enough for that, because multiple
+    /// bindings can correspond to a single def id in imports. So we keep a separate table.
+    import_effective_visibilities: EffectiveVisibilities<ImportId<'a>>,
     changed: bool,
 }
 
@@ -19,21 +41,57 @@ impl<'r, 'a> EffectiveVisibilitiesVisitor<'r, 'a> {
     /// For now, this doesn't resolve macros (FIXME) and cannot resolve Impl, as we
     /// need access to a TyCtxt for that.
     pub fn compute_effective_visibilities<'c>(r: &'r mut Resolver<'a>, krate: &'c Crate) {
-        let mut visitor = EffectiveVisibilitiesVisitor { r, changed: false };
+        let mut visitor = EffectiveVisibilitiesVisitor {
+            r,
+            import_effective_visibilities: Default::default(),
+            changed: false,
+        };
 
-        visitor.update(CRATE_DEF_ID, Visibility::Public, CRATE_DEF_ID, Level::Direct);
+        visitor.update(CRATE_DEF_ID, CRATE_DEF_ID);
         visitor.set_bindings_effective_visibilities(CRATE_DEF_ID);
 
         while visitor.changed {
-            visitor.reset();
+            visitor.changed = false;
             visit::walk_crate(&mut visitor, krate);
         }
 
+        // Update visibilities for import def ids. These are not used during the
+        // `EffectiveVisibilitiesVisitor` pass, because we have more detailed binding-based
+        // information, but are used by later passes. Effective visibility of an import def id
+        // is the maximum value among visibilities of bindings corresponding to that def id.
+        for (binding, eff_vis) in visitor.import_effective_visibilities.iter() {
+            let NameBindingKind::Import { import, .. } = binding.kind else { unreachable!() };
+            if let Some(node_id) = import.id() {
+                let mut update = |node_id| {
+                    r.effective_visibilities.update_eff_vis(
+                        r.local_def_id(node_id),
+                        eff_vis,
+                        ResolverTree(&r.definitions, &r.crate_loader),
+                    )
+                };
+                update(node_id);
+                if let ImportKind::Single { additional_ids: (id1, id2), .. } = import.kind {
+                    // In theory all the single import IDs have individual visibilities and
+                    // effective visibilities, but in practice these IDs go straigth to HIR
+                    // where all their few uses assume that their (effective) visibility
+                    // applies to the whole syntactic `use` item. So they all get the same
+                    // value which is the maximum of all bindings. Maybe HIR for imports
+                    // shouldn't use three IDs at all.
+                    if id1 != ast::DUMMY_NODE_ID {
+                        update(id1);
+                    }
+                    if id2 != ast::DUMMY_NODE_ID {
+                        update(id2);
+                    }
+                }
+            }
+        }
+
         info!("resolve::effective_visibilities: {:#?}", r.effective_visibilities);
     }
 
-    fn reset(&mut self) {
-        self.changed = false;
+    fn nearest_normal_mod(&mut self, def_id: LocalDefId) -> LocalDefId {
+        self.r.get_nearest_non_block_module(def_id.to_def_id()).nearest_parent_mod().expect_local()
     }
 
     /// Update effective visibilities of bindings in the given module,
@@ -48,92 +106,83 @@ impl<'r, 'a> EffectiveVisibilitiesVisitor<'r, 'a> {
                 // Set the given effective visibility level to `Level::Direct` and
                 // sets the rest of the `use` chain to `Level::Reexported` until
                 // we hit the actual exported item.
+                let mut parent_id = ParentId::Def(module_id);
+                while let NameBindingKind::Import { binding: nested_binding, .. } = binding.kind {
+                    let binding_id = ImportId::new_unchecked(binding);
+                    self.update_import(binding_id, parent_id);
 
-                // FIXME: tag and is_public() condition should be removed, but assertions occur.
-                let tag = if binding.is_import() { Level::Reexported } else { Level::Direct };
-                if binding.vis.is_public() {
-                    let mut prev_parent_id = module_id;
-                    let mut level = Level::Direct;
-                    while let NameBindingKind::Import { binding: nested_binding, import, .. } =
-                        binding.kind
-                    {
-                        let mut update = |node_id| {
-                            self.update(
-                                self.r.local_def_id(node_id),
-                                binding.vis.expect_local(),
-                                prev_parent_id,
-                                level,
-                            )
-                        };
-                        match import.kind {
-                            ImportKind::Single { id, additional_ids, .. } => {
-                                // In theory all the import IDs have individual visibilities and
-                                // effective visibilities, but in practice these IDs go straigth to
-                                // HIR where all their few uses assume that their (effective)
-                                // visibility applies to the whole syntactic `use` item. So we
-                                // update them all to the maximum value among the potential
-                                // individual effective visibilities. Maybe HIR for imports
-                                // shouldn't use three IDs at all.
-                                update(id);
-                                update(additional_ids.0);
-                                update(additional_ids.1);
-                                prev_parent_id = self.r.local_def_id(id);
-                            }
-                            ImportKind::Glob { id, .. } | ImportKind::ExternCrate { id, .. } => {
-                                update(id);
-                                prev_parent_id = self.r.local_def_id(id);
-                            }
-                            ImportKind::MacroUse => {
-                                // In theory we should reset the parent id to something private
-                                // here, but `macro_use` imports always refer to external items,
-                                // so it doesn't matter and we can just do nothing.
-                            }
-                            ImportKind::MacroExport => {
-                                // In theory we should reset the parent id to something public
-                                // here, but it has the same effect as leaving the previous parent,
-                                // so we can just do nothing.
-                            }
-                        }
-
-                        level = Level::Reexported;
-                        binding = nested_binding;
-                    }
+                    parent_id = ParentId::Import(binding_id);
+                    binding = nested_binding;
                 }
 
                 if let Some(def_id) = binding.res().opt_def_id().and_then(|id| id.as_local()) {
-                    self.update(def_id, binding.vis.expect_local(), module_id, tag);
+                    self.update_def(def_id, binding.vis.expect_local(), parent_id);
                 }
             }
         }
     }
 
-    fn update(
-        &mut self,
-        def_id: LocalDefId,
+    fn effective_vis(&self, parent_id: ParentId<'a>) -> Option<EffectiveVisibility> {
+        match parent_id {
+            ParentId::Def(def_id) => self.r.effective_visibilities.effective_vis(def_id),
+            ParentId::Import(binding) => self.import_effective_visibilities.effective_vis(binding),
+        }
+        .copied()
+    }
+
+    /// The update is guaranteed to not change the table and we can skip it.
+    fn is_noop_update(
+        &self,
+        parent_id: ParentId<'a>,
         nominal_vis: Visibility,
-        parent_id: LocalDefId,
-        tag: Level,
-    ) {
-        let module_id = self
-            .r
-            .get_nearest_non_block_module(def_id.to_def_id())
-            .nearest_parent_mod()
-            .expect_local();
-        if nominal_vis == Visibility::Restricted(module_id)
-            || self.r.visibilities[&parent_id] == Visibility::Restricted(module_id)
-        {
+        default_vis: Visibility,
+    ) -> bool {
+        nominal_vis == default_vis
+            || match parent_id {
+                ParentId::Def(def_id) => self.r.visibilities[&def_id],
+                ParentId::Import(binding) => binding.vis.expect_local(),
+            } == default_vis
+    }
+
+    fn update_import(&mut self, binding: ImportId<'a>, parent_id: ParentId<'a>) {
+        let NameBindingKind::Import { import, .. } = binding.kind else { unreachable!() };
+        let nominal_vis = binding.vis.expect_local();
+        let default_vis = Visibility::Restricted(
+            import
+                .id()
+                .map(|id| self.nearest_normal_mod(self.r.local_def_id(id)))
+                .unwrap_or(CRATE_DEF_ID),
+        );
+        if self.is_noop_update(parent_id, nominal_vis, default_vis) {
             return;
         }
-        let mut effective_visibilities = std::mem::take(&mut self.r.effective_visibilities);
-        self.changed |= effective_visibilities.update(
+        self.changed |= self.import_effective_visibilities.update(
+            binding,
+            nominal_vis,
+            default_vis,
+            self.effective_vis(parent_id),
+            parent_id.level(),
+            ResolverTree(&self.r.definitions, &self.r.crate_loader),
+        );
+    }
+
+    fn update_def(&mut self, def_id: LocalDefId, nominal_vis: Visibility, parent_id: ParentId<'a>) {
+        let default_vis = Visibility::Restricted(self.nearest_normal_mod(def_id));
+        if self.is_noop_update(parent_id, nominal_vis, default_vis) {
+            return;
+        }
+        self.changed |= self.r.effective_visibilities.update(
             def_id,
             nominal_vis,
-            || Visibility::Restricted(module_id),
-            parent_id,
-            tag,
-            &*self.r,
+            if def_id == CRATE_DEF_ID { Visibility::Public } else { default_vis },
+            self.effective_vis(parent_id),
+            parent_id.level(),
+            ResolverTree(&self.r.definitions, &self.r.crate_loader),
         );
-        self.r.effective_visibilities = effective_visibilities;
+    }
+
+    fn update(&mut self, def_id: LocalDefId, parent_id: LocalDefId) {
+        self.update_def(def_id, self.r.visibilities[&def_id], ParentId::Def(parent_id));
     }
 }
 
@@ -151,12 +200,6 @@ impl<'r, 'ast> Visitor<'ast> for EffectiveVisibilitiesVisitor<'ast, 'r> {
                 "ast::ItemKind::MacCall encountered, this should not anymore appear at this stage"
             ),
 
-            // Foreign modules inherit level from parents.
-            ast::ItemKind::ForeignMod(..) => {
-                let parent_id = self.r.local_parent(def_id);
-                self.update(def_id, Visibility::Public, parent_id, Level::Direct);
-            }
-
             ast::ItemKind::Mod(..) => {
                 self.set_bindings_effective_visibilities(def_id);
                 visit::walk_item(self, item);
@@ -167,18 +210,14 @@ impl<'r, 'ast> Visitor<'ast> for EffectiveVisibilitiesVisitor<'ast, 'r> {
                 for variant in variants {
                     let variant_def_id = self.r.local_def_id(variant.id);
                     for field in variant.data.fields() {
-                        let field_def_id = self.r.local_def_id(field.id);
-                        let vis = self.r.visibilities[&field_def_id];
-                        self.update(field_def_id, vis, variant_def_id, Level::Direct);
+                        self.update(self.r.local_def_id(field.id), variant_def_id);
                     }
                 }
             }
 
             ast::ItemKind::Struct(ref def, _) | ast::ItemKind::Union(ref def, _) => {
                 for field in def.fields() {
-                    let field_def_id = self.r.local_def_id(field.id);
-                    let vis = self.r.visibilities[&field_def_id];
-                    self.update(field_def_id, vis, def_id, Level::Direct);
+                    self.update(self.r.local_def_id(field.id), def_id);
                 }
             }
 
@@ -194,6 +233,7 @@ impl<'r, 'ast> Visitor<'ast> for EffectiveVisibilitiesVisitor<'ast, 'r> {
             | ast::ItemKind::TyAlias(..)
             | ast::ItemKind::TraitAlias(..)
             | ast::ItemKind::MacroDef(..)
+            | ast::ItemKind::ForeignMod(..)
             | ast::ItemKind::Fn(..) => return,
         }
     }
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index 103187b00d1..346024bb598 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -322,7 +322,12 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
         }
 
         self.suggest_bare_struct_literal(&mut err);
-        self.suggest_pattern_match_with_let(&mut err, source, span);
+
+        if self.suggest_pattern_match_with_let(&mut err, source, span) {
+            // Fallback label.
+            err.span_label(base_error.span, &base_error.fallback_label);
+            return (err, Vec::new());
+        }
 
         self.suggest_self_or_self_ref(&mut err, path, span);
         self.detect_assoct_type_constraint_meant_as_path(&mut err, &base_error);
@@ -341,7 +346,11 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
         if !self.type_ascription_suggestion(&mut err, base_error.span) {
             let mut fallback =
                 self.suggest_trait_and_bounds(&mut err, source, res, span, &base_error);
+
+            // if we have suggested using pattern matching, then don't add needless suggestions
+            // for typos.
             fallback |= self.suggest_typo(&mut err, source, path, span, &base_error);
+
             if fallback {
                 // Fallback label.
                 err.span_label(base_error.span, &base_error.fallback_label);
@@ -797,14 +806,16 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
         err.code(rustc_errors::error_code!(E0411));
         err.span_label(span, "`Self` is only available in impls, traits, and type definitions");
         if let Some(item_kind) = self.diagnostic_metadata.current_item {
-            err.span_label(
-                item_kind.ident.span,
-                format!(
-                    "`Self` not allowed in {} {}",
-                    item_kind.kind.article(),
-                    item_kind.kind.descr()
-                ),
-            );
+            if !item_kind.ident.span.is_dummy() {
+                err.span_label(
+                    item_kind.ident.span,
+                    format!(
+                        "`Self` not allowed in {} {}",
+                        item_kind.kind.article(),
+                        item_kind.kind.descr()
+                    ),
+                );
+            }
         }
         true
     }
@@ -937,7 +948,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
         err: &mut Diagnostic,
         source: PathSource<'_>,
         span: Span,
-    ) {
+    ) -> bool {
         if let PathSource::Expr(_) = source &&
         let Some(Expr {
                     span: expr_span,
@@ -954,8 +965,10 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
                     "let ",
                     Applicability::MaybeIncorrect,
                 );
+                return true;
             }
         }
+        false
     }
 
     fn get_single_associated_item(
diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs
index ee1c97d5ad2..a1ff477c6fe 100644
--- a/compiler/rustc_resolve/src/lib.rs
+++ b/compiler/rustc_resolve/src/lib.rs
@@ -1106,17 +1106,30 @@ impl<'a> AsMut<Resolver<'a>> for Resolver<'a> {
     }
 }
 
-impl<'a, 'b> DefIdTree for &'a Resolver<'b> {
+/// A minimal subset of resolver that can implemenent `DefIdTree`, sometimes
+/// required to satisfy borrow checker by avoiding borrowing the whole resolver.
+#[derive(Clone, Copy)]
+struct ResolverTree<'a, 'b>(&'a Definitions, &'a CrateLoader<'b>);
+
+impl DefIdTree for ResolverTree<'_, '_> {
     #[inline]
     fn opt_parent(self, id: DefId) -> Option<DefId> {
+        let ResolverTree(definitions, crate_loader) = self;
         match id.as_local() {
-            Some(id) => self.definitions.def_key(id).parent,
-            None => self.cstore().def_key(id).parent,
+            Some(id) => definitions.def_key(id).parent,
+            None => crate_loader.cstore().def_key(id).parent,
         }
         .map(|index| DefId { index, ..id })
     }
 }
 
+impl<'a, 'b> DefIdTree for &'a Resolver<'b> {
+    #[inline]
+    fn opt_parent(self, id: DefId) -> Option<DefId> {
+        ResolverTree(&self.definitions, &self.crate_loader).opt_parent(id)
+    }
+}
+
 impl Resolver<'_> {
     fn opt_local_def_id(&self, node: NodeId) -> Option<LocalDefId> {
         self.node_id_to_def_id.get(&node).copied()
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index aece29ca0cb..be084adb7b7 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -548,6 +548,7 @@ pub enum PrintRequest {
     NativeStaticLibs,
     StackProtectorStrategies,
     LinkArgs,
+    SplitDebuginfo,
 }
 
 pub enum Input {
@@ -1806,6 +1807,7 @@ fn collect_print_requests(
         ("stack-protector-strategies", PrintRequest::StackProtectorStrategies),
         ("target-spec-json", PrintRequest::TargetSpec),
         ("link-args", PrintRequest::LinkArgs),
+        ("split-debuginfo", PrintRequest::SplitDebuginfo),
     ];
 
     prints.extend(matches.opt_strs("print").into_iter().map(|req| {
diff --git a/compiler/rustc_span/src/source_map.rs b/compiler/rustc_span/src/source_map.rs
index f9566eeee94..3baa2e03cba 100644
--- a/compiler/rustc_span/src/source_map.rs
+++ b/compiler/rustc_span/src/source_map.rs
@@ -855,7 +855,8 @@ impl SourceMap {
     /// Returns a new span representing the next character after the end-point of this span.
     /// Special cases:
     /// - if span is a dummy one, returns the same span
-    /// - if next_point reached the end of source, return span with lo = hi
+    /// - if next_point reached the end of source, return a span exceeding the end of source,
+    ///   which means sm.span_to_snippet(next_point) will get `Err`
     /// - respect multi-byte characters
     pub fn next_point(&self, sp: Span) -> Span {
         if sp.is_dummy() {
@@ -864,9 +865,6 @@ impl SourceMap {
         let start_of_next_point = sp.hi().0;
 
         let width = self.find_width_of_character_at_span(sp, true);
-        if width == 0 {
-            return Span::new(sp.hi(), sp.hi(), sp.ctxt(), None);
-        }
         // If the width is 1, then the next span should only contain the next char besides current ending.
         // However, in the case of a multibyte character, where the width != 1, the next span should
         // span multiple bytes to include the whole character.
@@ -938,7 +936,7 @@ impl SourceMap {
         // Ensure indexes are also not malformed.
         if start_index > end_index || end_index > source_len - 1 {
             debug!("find_width_of_character_at_span: source indexes are malformed");
-            return 0;
+            return 1;
         }
 
         let src = local_begin.sf.external_src.borrow();
diff --git a/compiler/rustc_span/src/source_map/tests.rs b/compiler/rustc_span/src/source_map/tests.rs
index 1fd81018fa0..3cab59e8dbe 100644
--- a/compiler/rustc_span/src/source_map/tests.rs
+++ b/compiler/rustc_span/src/source_map/tests.rs
@@ -511,16 +511,17 @@ fn test_next_point() {
     assert_eq!(span.lo().0, 4);
     assert_eq!(span.hi().0, 5);
 
-    // A non-empty span at the last byte should advance to create an empty
-    // span pointing at the end of the file.
+    // Reaching to the end of file, return a span that will get error with `span_to_snippet`
     let span = Span::with_root_ctxt(BytePos(4), BytePos(5));
     let span = sm.next_point(span);
     assert_eq!(span.lo().0, 5);
-    assert_eq!(span.hi().0, 5);
+    assert_eq!(span.hi().0, 6);
+    assert!(sm.span_to_snippet(span).is_err());
 
-    // Empty span pointing just past the last byte.
+    // Reaching to the end of file, return a span that will get error with `span_to_snippet`
     let span = Span::with_root_ctxt(BytePos(5), BytePos(5));
     let span = sm.next_point(span);
     assert_eq!(span.lo().0, 5);
-    assert_eq!(span.hi().0, 5);
+    assert_eq!(span.hi().0, 6);
+    assert!(sm.span_to_snippet(span).is_err());
 }
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index cccc4897ecc..54a61483a11 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -584,6 +584,7 @@ symbols! {
         custom_attribute,
         custom_derive,
         custom_inner_attributes,
+        custom_mir,
         custom_test_frameworks,
         d,
         d32,
diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs
index 2109b3c2496..e540e2f2a21 100644
--- a/compiler/rustc_symbol_mangling/src/v0.rs
+++ b/compiler/rustc_symbol_mangling/src/v0.rs
@@ -218,7 +218,7 @@ impl<'tcx> SymbolMangler<'tcx> {
         let lifetimes = regions
             .into_iter()
             .map(|br| match br {
-                ty::BrAnon(i) => i,
+                ty::BrAnon(i, _) => i,
                 _ => bug!("symbol_names: non-anonymized region `{:?}` in `{:?}`", br, value),
             })
             .max()
@@ -335,7 +335,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> {
 
             // Late-bound lifetimes use indices starting at 1,
             // see `BinderLevel` for more details.
-            ty::ReLateBound(debruijn, ty::BoundRegion { kind: ty::BrAnon(i), .. }) => {
+            ty::ReLateBound(debruijn, ty::BoundRegion { kind: ty::BrAnon(i, _), .. }) => {
                 let binder = &self.binders[self.binders.len() - 1 - debruijn.index()];
                 let depth = binder.lifetime_depths.start + i;
 
diff --git a/compiler/rustc_target/src/spec/aarch64_apple_darwin.rs b/compiler/rustc_target/src/spec/aarch64_apple_darwin.rs
index 6d919a4c2ad..0f6bbc32317 100644
--- a/compiler/rustc_target/src/spec/aarch64_apple_darwin.rs
+++ b/compiler/rustc_target/src/spec/aarch64_apple_darwin.rs
@@ -1,26 +1,25 @@
+use super::apple_base::{macos_link_env_remove, macos_llvm_target, opts, Arch};
 use crate::spec::{FramePointer, SanitizerSet, Target, TargetOptions};
 
 pub fn target() -> Target {
-    let arch = "arm64";
-    let mut base = super::apple_base::opts("macos", arch, "");
+    let arch = Arch::Arm64;
+    let mut base = opts("macos", arch);
     base.cpu = "apple-a14".into();
     base.max_atomic_width = Some(128);
 
     // FIXME: The leak sanitizer currently fails the tests, see #88132.
     base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::CFI | SanitizerSet::THREAD;
 
-    base.link_env_remove.to_mut().extend(super::apple_base::macos_link_env_remove());
-
-    // Clang automatically chooses a more specific target based on
-    // MACOSX_DEPLOYMENT_TARGET.  To enable cross-language LTO to work
-    // correctly, we do too.
-    let llvm_target = super::apple_base::macos_llvm_target(arch);
+    base.link_env_remove.to_mut().extend(macos_link_env_remove());
 
     Target {
-        llvm_target: llvm_target.into(),
+        // Clang automatically chooses a more specific target based on
+        // MACOSX_DEPLOYMENT_TARGET.  To enable cross-language LTO to work
+        // correctly, we do too.
+        llvm_target: macos_llvm_target(arch).into(),
         pointer_width: 64,
         data_layout: "e-m:o-i64:64-i128:128-n32:64-S128".into(),
-        arch: "aarch64".into(),
+        arch: arch.target_arch(),
         options: TargetOptions {
             mcount: "\u{1}mcount".into(),
             frame_pointer: FramePointer::NonLeaf,
diff --git a/compiler/rustc_target/src/spec/aarch64_apple_ios.rs b/compiler/rustc_target/src/spec/aarch64_apple_ios.rs
index beb9042390b..b5f9eb1259d 100644
--- a/compiler/rustc_target/src/spec/aarch64_apple_ios.rs
+++ b/compiler/rustc_target/src/spec/aarch64_apple_ios.rs
@@ -1,19 +1,17 @@
-use super::apple_sdk_base::{opts, Arch};
+use super::apple_base::{ios_llvm_target, opts, Arch};
 use crate::spec::{FramePointer, Target, TargetOptions};
 
 pub fn target() -> Target {
-    // Clang automatically chooses a more specific target based on
-    // IPHONEOS_DEPLOYMENT_TARGET.
-    // This is required for the target to pick the right
-    // MACH-O commands, so we do too.
-    let arch = "arm64";
-    let llvm_target = super::apple_base::ios_llvm_target(arch);
-
+    let arch = Arch::Arm64;
     Target {
-        llvm_target: llvm_target.into(),
+        // Clang automatically chooses a more specific target based on
+        // IPHONEOS_DEPLOYMENT_TARGET.
+        // This is required for the target to pick the right
+        // MACH-O commands, so we do too.
+        llvm_target: ios_llvm_target(arch).into(),
         pointer_width: 64,
         data_layout: "e-m:o-i64:64-i128:128-n32:64-S128".into(),
-        arch: "aarch64".into(),
+        arch: arch.target_arch(),
         options: TargetOptions {
             features: "+neon,+fp-armv8,+apple-a7".into(),
             max_atomic_width: Some(128),
@@ -30,7 +28,7 @@ pub fn target() -> Target {
                 darwinpcs\0\
                 -Os\0"
                 .into(),
-            ..opts("ios", Arch::Arm64)
+            ..opts("ios", arch)
         },
     }
 }
diff --git a/compiler/rustc_target/src/spec/aarch64_apple_ios_macabi.rs b/compiler/rustc_target/src/spec/aarch64_apple_ios_macabi.rs
index 2d2671549cf..0009972cf42 100644
--- a/compiler/rustc_target/src/spec/aarch64_apple_ios_macabi.rs
+++ b/compiler/rustc_target/src/spec/aarch64_apple_ios_macabi.rs
@@ -1,17 +1,18 @@
-use super::apple_sdk_base::{opts, Arch};
+use super::apple_base::{opts, Arch};
 use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, Target, TargetOptions};
 
 pub fn target() -> Target {
     let llvm_target = "arm64-apple-ios14.0-macabi";
 
-    let mut base = opts("ios", Arch::Arm64_macabi);
+    let arch = Arch::Arm64_macabi;
+    let mut base = opts("ios", arch);
     base.add_pre_link_args(LinkerFlavor::Darwin(Cc::Yes, Lld::No), &["-target", llvm_target]);
 
     Target {
         llvm_target: llvm_target.into(),
         pointer_width: 64,
         data_layout: "e-m:o-i64:64-i128:128-n32:64-S128".into(),
-        arch: "aarch64".into(),
+        arch: arch.target_arch(),
         options: TargetOptions {
             features: "+neon,+fp-armv8,+apple-a12".into(),
             max_atomic_width: Some(128),
diff --git a/compiler/rustc_target/src/spec/aarch64_apple_ios_sim.rs b/compiler/rustc_target/src/spec/aarch64_apple_ios_sim.rs
index b4e135f66e9..3374755e2dd 100644
--- a/compiler/rustc_target/src/spec/aarch64_apple_ios_sim.rs
+++ b/compiler/rustc_target/src/spec/aarch64_apple_ios_sim.rs
@@ -1,21 +1,17 @@
-use super::apple_sdk_base::{opts, Arch};
+use super::apple_base::{ios_sim_llvm_target, opts, Arch};
 use crate::spec::{FramePointer, Target, TargetOptions};
 
 pub fn target() -> Target {
-    let base = opts("ios", Arch::Arm64_sim);
-
-    // Clang automatically chooses a more specific target based on
-    // IPHONEOS_DEPLOYMENT_TARGET.
-    // This is required for the simulator target to pick the right
-    // MACH-O commands, so we do too.
-    let arch = "arm64";
-    let llvm_target = super::apple_base::ios_sim_llvm_target(arch);
-
+    let arch = Arch::Arm64_sim;
     Target {
-        llvm_target: llvm_target.into(),
+        // Clang automatically chooses a more specific target based on
+        // IPHONEOS_DEPLOYMENT_TARGET.
+        // This is required for the simulator target to pick the right
+        // MACH-O commands, so we do too.
+        llvm_target: ios_sim_llvm_target(arch).into(),
         pointer_width: 64,
         data_layout: "e-m:o-i64:64-i128:128-n32:64-S128".into(),
-        arch: "aarch64".into(),
+        arch: arch.target_arch(),
         options: TargetOptions {
             features: "+neon,+fp-armv8,+apple-a7".into(),
             max_atomic_width: Some(128),
@@ -32,7 +28,7 @@ pub fn target() -> Target {
                 darwinpcs\0\
                 -Os\0"
                 .into(),
-            ..base
+            ..opts("ios", arch)
         },
     }
 }
diff --git a/compiler/rustc_target/src/spec/aarch64_apple_tvos.rs b/compiler/rustc_target/src/spec/aarch64_apple_tvos.rs
index 2e31d16dc76..bb7c39ff26b 100644
--- a/compiler/rustc_target/src/spec/aarch64_apple_tvos.rs
+++ b/compiler/rustc_target/src/spec/aarch64_apple_tvos.rs
@@ -1,18 +1,19 @@
-use super::apple_sdk_base::{opts, Arch};
+use super::apple_base::{opts, Arch};
 use crate::spec::{FramePointer, Target, TargetOptions};
 
 pub fn target() -> Target {
+    let arch = Arch::Arm64;
     Target {
         llvm_target: "arm64-apple-tvos".into(),
         pointer_width: 64,
         data_layout: "e-m:o-i64:64-i128:128-n32:64-S128".into(),
-        arch: "aarch64".into(),
+        arch: arch.target_arch(),
         options: TargetOptions {
             features: "+neon,+fp-armv8,+apple-a7".into(),
             max_atomic_width: Some(128),
             forces_embed_bitcode: true,
             frame_pointer: FramePointer::NonLeaf,
-            ..opts("tvos", Arch::Arm64)
+            ..opts("tvos", arch)
         },
     }
 }
diff --git a/compiler/rustc_target/src/spec/aarch64_apple_watchos_sim.rs b/compiler/rustc_target/src/spec/aarch64_apple_watchos_sim.rs
index 3059f42140b..e4af4127c22 100644
--- a/compiler/rustc_target/src/spec/aarch64_apple_watchos_sim.rs
+++ b/compiler/rustc_target/src/spec/aarch64_apple_watchos_sim.rs
@@ -1,21 +1,17 @@
-use super::apple_sdk_base::{opts, Arch};
+use super::apple_base::{opts, watchos_sim_llvm_target, Arch};
 use crate::spec::{FramePointer, Target, TargetOptions};
 
 pub fn target() -> Target {
-    let base = opts("watchos", Arch::Arm64_sim);
-
-    // Clang automatically chooses a more specific target based on
-    // WATCHOS_DEPLOYMENT_TARGET.
-    // This is required for the simulator target to pick the right
-    // MACH-O commands, so we do too.
-    let arch = "arm64";
-    let llvm_target = super::apple_base::watchos_sim_llvm_target(arch);
-
+    let arch = Arch::Arm64_sim;
     Target {
-        llvm_target: llvm_target.into(),
+        // Clang automatically chooses a more specific target based on
+        // WATCHOS_DEPLOYMENT_TARGET.
+        // This is required for the simulator target to pick the right
+        // MACH-O commands, so we do too.
+        llvm_target: watchos_sim_llvm_target(arch).into(),
         pointer_width: 64,
         data_layout: "e-m:o-i64:64-i128:128-n32:64-S128".into(),
-        arch: "aarch64".into(),
+        arch: arch.target_arch(),
         options: TargetOptions {
             features: "+neon,+fp-armv8,+apple-a7".into(),
             max_atomic_width: Some(128),
@@ -32,7 +28,7 @@ pub fn target() -> Target {
                 darwinpcs\0\
                 -Os\0"
                 .into(),
-            ..base
+            ..opts("watchos", arch)
         },
     }
 }
diff --git a/compiler/rustc_target/src/spec/apple_base.rs b/compiler/rustc_target/src/spec/apple_base.rs
index 40bc59ca145..23c826cb1bd 100644
--- a/compiler/rustc_target/src/spec/apple_base.rs
+++ b/compiler/rustc_target/src/spec/apple_base.rs
@@ -3,7 +3,88 @@ use std::{borrow::Cow, env};
 use crate::spec::{cvs, Cc, DebuginfoKind, FramePointer, LinkArgs};
 use crate::spec::{LinkerFlavor, Lld, SplitDebuginfo, StaticCow, TargetOptions};
 
-fn pre_link_args(os: &'static str, arch: &'static str, abi: &'static str) -> LinkArgs {
+#[cfg(test)]
+#[path = "apple/tests.rs"]
+mod tests;
+
+use Arch::*;
+#[allow(non_camel_case_types)]
+#[derive(Copy, Clone)]
+pub enum Arch {
+    Armv7,
+    Armv7k,
+    Armv7s,
+    Arm64,
+    Arm64_32,
+    I386,
+    I686,
+    X86_64,
+    X86_64_sim,
+    X86_64_macabi,
+    Arm64_macabi,
+    Arm64_sim,
+}
+
+impl Arch {
+    pub fn target_name(self) -> &'static str {
+        match self {
+            Armv7 => "armv7",
+            Armv7k => "armv7k",
+            Armv7s => "armv7s",
+            Arm64 | Arm64_macabi | Arm64_sim => "arm64",
+            Arm64_32 => "arm64_32",
+            I386 => "i386",
+            I686 => "i686",
+            X86_64 | X86_64_sim | X86_64_macabi => "x86_64",
+        }
+    }
+
+    pub fn target_arch(self) -> Cow<'static, str> {
+        Cow::Borrowed(match self {
+            Armv7 | Armv7k | Armv7s => "arm",
+            Arm64 | Arm64_32 | Arm64_macabi | Arm64_sim => "aarch64",
+            I386 | I686 => "x86",
+            X86_64 | X86_64_sim | X86_64_macabi => "x86_64",
+        })
+    }
+
+    fn target_abi(self) -> &'static str {
+        match self {
+            Armv7 | Armv7k | Armv7s | Arm64 | Arm64_32 | I386 | I686 | X86_64 => "",
+            X86_64_macabi | Arm64_macabi => "macabi",
+            // x86_64-apple-ios is a simulator target, even though it isn't
+            // declared that way in the target like the other ones...
+            Arm64_sim | X86_64_sim => "sim",
+        }
+    }
+
+    fn target_cpu(self) -> &'static str {
+        match self {
+            Armv7 => "cortex-a8", // iOS7 is supported on iPhone 4 and higher
+            Armv7k => "cortex-a8",
+            Armv7s => "cortex-a9",
+            Arm64 => "apple-a7",
+            Arm64_32 => "apple-s4",
+            I386 | I686 => "yonah",
+            X86_64 | X86_64_sim => "core2",
+            X86_64_macabi => "core2",
+            Arm64_macabi => "apple-a12",
+            Arm64_sim => "apple-a12",
+        }
+    }
+
+    fn link_env_remove(self) -> StaticCow<[StaticCow<str>]> {
+        match self {
+            Armv7 | Armv7k | Armv7s | Arm64 | Arm64_32 | I386 | I686 | X86_64 | X86_64_sim
+            | Arm64_sim => {
+                cvs!["MACOSX_DEPLOYMENT_TARGET"]
+            }
+            X86_64_macabi | Arm64_macabi => cvs!["IPHONEOS_DEPLOYMENT_TARGET"],
+        }
+    }
+}
+
+fn pre_link_args(os: &'static str, arch: Arch, abi: &'static str) -> LinkArgs {
     let platform_name: StaticCow<str> = match abi {
         "sim" => format!("{}-simulator", os).into(),
         "macabi" => "mac-catalyst".into(),
@@ -19,6 +100,8 @@ fn pre_link_args(os: &'static str, arch: &'static str, abi: &'static str) -> Lin
     }
     .into();
 
+    let arch = arch.target_name();
+
     let mut args = TargetOptions::link_args(
         LinkerFlavor::Darwin(Cc::No, Lld::No),
         &["-arch", arch, "-platform_version"],
@@ -35,24 +118,29 @@ fn pre_link_args(os: &'static str, arch: &'static str, abi: &'static str) -> Lin
     args
 }
 
-pub fn opts(os: &'static str, arch: &'static str, abi: &'static str) -> TargetOptions {
-    // ELF TLS is only available in macOS 10.7+. If you try to compile for 10.6
+pub fn opts(os: &'static str, arch: Arch) -> TargetOptions {
+    // Static TLS is only available in macOS 10.7+. If you try to compile for 10.6
     // either the linker will complain if it is used or the binary will end up
     // segfaulting at runtime when run on 10.6. Rust by default supports macOS
     // 10.7+, but there is a standard environment variable,
     // MACOSX_DEPLOYMENT_TARGET, which is used to signal targeting older
     // versions of macOS. For example compiling on 10.10 with
     // MACOSX_DEPLOYMENT_TARGET set to 10.6 will cause the linker to generate
-    // warnings about the usage of ELF TLS.
+    // warnings about the usage of static TLS.
     //
-    // Here we detect what version is being requested, defaulting to 10.7. ELF
+    // Here we detect what version is being requested, defaulting to 10.7. Static
     // TLS is flagged as enabled if it looks to be supported. The architecture
     // only matters for default deployment target which is 11.0 for ARM64 and
     // 10.7 for everything else.
-    let has_thread_local = macos_deployment_target("x86_64") >= (10, 7);
+    let has_thread_local = os == "macos" && macos_deployment_target(Arch::X86_64) >= (10, 7);
+
+    let abi = arch.target_abi();
 
     TargetOptions {
+        abi: abi.into(),
         os: os.into(),
+        cpu: arch.target_cpu().into(),
+        link_env_remove: arch.link_env_remove(),
         vendor: "apple".into(),
         linker_flavor: LinkerFlavor::Darwin(Cc::Yes, Lld::No),
         // macOS has -dead_strip, which doesn't rely on function_sections
@@ -103,23 +191,24 @@ fn deployment_target(var_name: &str) -> Option<(u32, u32)> {
         .and_then(|(a, b)| a.parse::<u32>().and_then(|a| b.parse::<u32>().map(|b| (a, b))).ok())
 }
 
-fn macos_default_deployment_target(arch: &str) -> (u32, u32) {
-    if arch == "arm64" { (11, 0) } else { (10, 7) }
+fn macos_default_deployment_target(arch: Arch) -> (u32, u32) {
+    // Note: Arm64_sim is not included since macOS has no simulator.
+    if matches!(arch, Arm64 | Arm64_macabi) { (11, 0) } else { (10, 7) }
 }
 
-fn macos_deployment_target(arch: &str) -> (u32, u32) {
+fn macos_deployment_target(arch: Arch) -> (u32, u32) {
     deployment_target("MACOSX_DEPLOYMENT_TARGET")
         .unwrap_or_else(|| macos_default_deployment_target(arch))
 }
 
-fn macos_lld_platform_version(arch: &str) -> String {
+fn macos_lld_platform_version(arch: Arch) -> String {
     let (major, minor) = macos_deployment_target(arch);
     format!("{}.{}", major, minor)
 }
 
-pub fn macos_llvm_target(arch: &str) -> String {
+pub fn macos_llvm_target(arch: Arch) -> String {
     let (major, minor) = macos_deployment_target(arch);
-    format!("{}-apple-macosx{}.{}.0", arch, major, minor)
+    format!("{}-apple-macosx{}.{}.0", arch.target_name(), major, minor)
 }
 
 pub fn macos_link_env_remove() -> Vec<StaticCow<str>> {
@@ -142,7 +231,7 @@ fn ios_deployment_target() -> (u32, u32) {
     deployment_target("IPHONEOS_DEPLOYMENT_TARGET").unwrap_or((7, 0))
 }
 
-pub fn ios_llvm_target(arch: &str) -> String {
+pub fn ios_llvm_target(arch: Arch) -> String {
     // Modern iOS tooling extracts information about deployment target
     // from LC_BUILD_VERSION. This load command will only be emitted when
     // we build with a version specific `llvm_target`, with the version
@@ -150,7 +239,7 @@ pub fn ios_llvm_target(arch: &str) -> String {
     // to pick it up (since std and core are still built with the fallback
     // of version 7.0 and hence emit the old LC_IPHONE_MIN_VERSION).
     let (major, minor) = ios_deployment_target();
-    format!("{}-apple-ios{}.{}.0", arch, major, minor)
+    format!("{}-apple-ios{}.{}.0", arch.target_name(), major, minor)
 }
 
 fn ios_lld_platform_version() -> String {
@@ -158,9 +247,9 @@ fn ios_lld_platform_version() -> String {
     format!("{}.{}", major, minor)
 }
 
-pub fn ios_sim_llvm_target(arch: &str) -> String {
+pub fn ios_sim_llvm_target(arch: Arch) -> String {
     let (major, minor) = ios_deployment_target();
-    format!("{}-apple-ios{}.{}.0-simulator", arch, major, minor)
+    format!("{}-apple-ios{}.{}.0-simulator", arch.target_name(), major, minor)
 }
 
 fn tvos_deployment_target() -> (u32, u32) {
@@ -181,7 +270,7 @@ fn watchos_lld_platform_version() -> String {
     format!("{}.{}", major, minor)
 }
 
-pub fn watchos_sim_llvm_target(arch: &str) -> String {
+pub fn watchos_sim_llvm_target(arch: Arch) -> String {
     let (major, minor) = watchos_deployment_target();
-    format!("{}-apple-watchos{}.{}.0-simulator", arch, major, minor)
+    format!("{}-apple-watchos{}.{}.0-simulator", arch.target_name(), major, minor)
 }
diff --git a/compiler/rustc_target/src/spec/apple_sdk_base.rs b/compiler/rustc_target/src/spec/apple_sdk_base.rs
deleted file mode 100644
index 148031b1569..00000000000
--- a/compiler/rustc_target/src/spec/apple_sdk_base.rs
+++ /dev/null
@@ -1,81 +0,0 @@
-use crate::spec::{cvs, TargetOptions};
-use std::borrow::Cow;
-
-#[cfg(test)]
-#[path = "apple/tests.rs"]
-mod tests;
-
-use Arch::*;
-#[allow(non_camel_case_types)]
-#[derive(Copy, Clone)]
-pub enum Arch {
-    Armv7,
-    Armv7k,
-    Armv7s,
-    Arm64,
-    Arm64_32,
-    I386,
-    #[allow(dead_code)] // Some targets don't use this enum...
-    X86_64,
-    X86_64_sim,
-    X86_64_macabi,
-    Arm64_macabi,
-    Arm64_sim,
-}
-
-fn target_arch_name(arch: Arch) -> &'static str {
-    match arch {
-        Armv7 => "armv7",
-        Armv7k => "armv7k",
-        Armv7s => "armv7s",
-        Arm64 | Arm64_macabi | Arm64_sim => "arm64",
-        Arm64_32 => "arm64_32",
-        I386 => "i386",
-        X86_64 | X86_64_sim | X86_64_macabi => "x86_64",
-    }
-}
-
-fn target_abi(arch: Arch) -> &'static str {
-    match arch {
-        Armv7 | Armv7k | Armv7s | Arm64 | Arm64_32 | I386 | X86_64 => "",
-        X86_64_macabi | Arm64_macabi => "macabi",
-        // x86_64-apple-ios is a simulator target, even though it isn't
-        // declared that way in the target like the other ones...
-        Arm64_sim | X86_64_sim => "sim",
-    }
-}
-
-fn target_cpu(arch: Arch) -> &'static str {
-    match arch {
-        Armv7 => "cortex-a8", // iOS7 is supported on iPhone 4 and higher
-        Armv7k => "cortex-a8",
-        Armv7s => "cortex-a9",
-        Arm64 => "apple-a7",
-        Arm64_32 => "apple-s4",
-        I386 => "yonah",
-        X86_64 | X86_64_sim => "core2",
-        X86_64_macabi => "core2",
-        Arm64_macabi => "apple-a12",
-        Arm64_sim => "apple-a12",
-    }
-}
-
-fn link_env_remove(arch: Arch) -> Cow<'static, [Cow<'static, str>]> {
-    match arch {
-        Armv7 | Armv7k | Armv7s | Arm64 | Arm64_32 | I386 | X86_64 | X86_64_sim | Arm64_sim => {
-            cvs!["MACOSX_DEPLOYMENT_TARGET"]
-        }
-        X86_64_macabi | Arm64_macabi => cvs!["IPHONEOS_DEPLOYMENT_TARGET"],
-    }
-}
-
-pub fn opts(os: &'static str, arch: Arch) -> TargetOptions {
-    let abi = target_abi(arch);
-    TargetOptions {
-        abi: abi.into(),
-        cpu: target_cpu(arch).into(),
-        link_env_remove: link_env_remove(arch),
-        has_thread_local: false,
-        ..super::apple_base::opts(os, target_arch_name(arch), abi)
-    }
-}
diff --git a/compiler/rustc_target/src/spec/arm64_32_apple_watchos.rs b/compiler/rustc_target/src/spec/arm64_32_apple_watchos.rs
index cb7f5f2a583..2cf2cbc7510 100644
--- a/compiler/rustc_target/src/spec/arm64_32_apple_watchos.rs
+++ b/compiler/rustc_target/src/spec/arm64_32_apple_watchos.rs
@@ -1,4 +1,4 @@
-use super::apple_sdk_base::{opts, Arch};
+use super::apple_base::{opts, Arch};
 use crate::spec::{Target, TargetOptions};
 
 pub fn target() -> Target {
diff --git a/compiler/rustc_target/src/spec/armv7_apple_ios.rs b/compiler/rustc_target/src/spec/armv7_apple_ios.rs
index 57fd74a36b6..3259c854791 100644
--- a/compiler/rustc_target/src/spec/armv7_apple_ios.rs
+++ b/compiler/rustc_target/src/spec/armv7_apple_ios.rs
@@ -1,18 +1,21 @@
-use super::apple_sdk_base::{opts, Arch};
+use super::apple_base::{ios_llvm_target, opts, Arch};
 use crate::spec::{Target, TargetOptions};
 
 pub fn target() -> Target {
-    let llvm_target = super::apple_base::ios_llvm_target("armv7");
-
+    let arch = Arch::Armv7;
     Target {
-        llvm_target: llvm_target.into(),
+        // Clang automatically chooses a more specific target based on
+        // IPHONEOS_DEPLOYMENT_TARGET.
+        // This is required for the target to pick the right
+        // MACH-O commands, so we do too.
+        llvm_target: ios_llvm_target(arch).into(),
         pointer_width: 32,
         data_layout: "e-m:o-p:32:32-Fi8-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32".into(),
-        arch: "arm".into(),
+        arch: arch.target_arch(),
         options: TargetOptions {
             features: "+v7,+vfp3,+neon".into(),
             max_atomic_width: Some(64),
-            ..opts("ios", Arch::Armv7)
+            ..opts("ios", arch)
         },
     }
 }
diff --git a/compiler/rustc_target/src/spec/armv7k_apple_watchos.rs b/compiler/rustc_target/src/spec/armv7k_apple_watchos.rs
index af5d1c2ff45..45ead8d65ab 100644
--- a/compiler/rustc_target/src/spec/armv7k_apple_watchos.rs
+++ b/compiler/rustc_target/src/spec/armv7k_apple_watchos.rs
@@ -1,13 +1,13 @@
-use super::apple_sdk_base::{opts, Arch};
+use super::apple_base::{opts, Arch};
 use crate::spec::{Target, TargetOptions};
 
 pub fn target() -> Target {
-    let base = opts("watchos", Arch::Armv7k);
+    let arch = Arch::Armv7k;
     Target {
         llvm_target: "armv7k-apple-watchos".into(),
         pointer_width: 32,
         data_layout: "e-m:o-p:32:32-Fi8-i64:64-a:0:32-n32-S128".into(),
-        arch: "arm".into(),
+        arch: arch.target_arch(),
         options: TargetOptions {
             features: "+v7,+vfp4,+neon".into(),
             max_atomic_width: Some(64),
@@ -22,7 +22,7 @@ pub fn target() -> Target {
                 darwinpcs\0\
                 -Os\0"
                 .into(),
-            ..base
+            ..opts("watchos", arch)
         },
     }
 }
diff --git a/compiler/rustc_target/src/spec/armv7s_apple_ios.rs b/compiler/rustc_target/src/spec/armv7s_apple_ios.rs
index cc17265b2b8..be4bc675844 100644
--- a/compiler/rustc_target/src/spec/armv7s_apple_ios.rs
+++ b/compiler/rustc_target/src/spec/armv7s_apple_ios.rs
@@ -1,16 +1,17 @@
-use super::apple_sdk_base::{opts, Arch};
+use super::apple_base::{opts, Arch};
 use crate::spec::{Target, TargetOptions};
 
 pub fn target() -> Target {
+    let arch = Arch::Armv7s;
     Target {
         llvm_target: "armv7s-apple-ios".into(),
         pointer_width: 32,
         data_layout: "e-m:o-p:32:32-Fi8-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32".into(),
-        arch: "arm".into(),
+        arch: arch.target_arch(),
         options: TargetOptions {
             features: "+v7,+vfp4,+neon".into(),
             max_atomic_width: Some(64),
-            ..opts("ios", Arch::Armv7s)
+            ..opts("ios", arch)
         },
     }
 }
diff --git a/compiler/rustc_target/src/spec/i386_apple_ios.rs b/compiler/rustc_target/src/spec/i386_apple_ios.rs
index b85214a9c6b..5819981612e 100644
--- a/compiler/rustc_target/src/spec/i386_apple_ios.rs
+++ b/compiler/rustc_target/src/spec/i386_apple_ios.rs
@@ -1,21 +1,23 @@
-use super::apple_sdk_base::{opts, Arch};
+use super::apple_base::{ios_sim_llvm_target, opts, Arch};
 use crate::spec::{StackProbeType, Target, TargetOptions};
 
 pub fn target() -> Target {
-    let base = opts("ios", Arch::I386);
-    let llvm_target = super::apple_base::ios_sim_llvm_target("i386");
-
+    let arch = Arch::I386;
     Target {
-        llvm_target: llvm_target.into(),
+        // Clang automatically chooses a more specific target based on
+        // IPHONEOS_DEPLOYMENT_TARGET.
+        // This is required for the target to pick the right
+        // MACH-O commands, so we do too.
+        llvm_target: ios_sim_llvm_target(arch).into(),
         pointer_width: 32,
         data_layout: "e-m:o-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
             f64:32:64-f80:128-n8:16:32-S128"
             .into(),
-        arch: "x86".into(),
+        arch: arch.target_arch(),
         options: TargetOptions {
             max_atomic_width: Some(64),
             stack_probes: StackProbeType::X86,
-            ..base
+            ..opts("ios", arch)
         },
     }
 }
diff --git a/compiler/rustc_target/src/spec/i686_apple_darwin.rs b/compiler/rustc_target/src/spec/i686_apple_darwin.rs
index 15607c12ea9..8b968af5ecc 100644
--- a/compiler/rustc_target/src/spec/i686_apple_darwin.rs
+++ b/compiler/rustc_target/src/spec/i686_apple_darwin.rs
@@ -1,28 +1,28 @@
+use super::apple_base::{macos_link_env_remove, macos_llvm_target, opts, Arch};
 use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions};
 
 pub fn target() -> Target {
-    // ld64 only understand i386 and not i686
-    let mut base = super::apple_base::opts("macos", "i386", "");
-    base.cpu = "yonah".into();
+    // ld64 only understands i386 and not i686
+    let arch = Arch::I386;
+    let mut base = opts("macos", arch);
     base.max_atomic_width = Some(64);
     base.add_pre_link_args(LinkerFlavor::Darwin(Cc::Yes, Lld::No), &["-m32"]);
-    base.link_env_remove.to_mut().extend(super::apple_base::macos_link_env_remove());
+    base.link_env_remove.to_mut().extend(macos_link_env_remove());
     base.stack_probes = StackProbeType::X86;
     base.frame_pointer = FramePointer::Always;
 
-    // Clang automatically chooses a more specific target based on
-    // MACOSX_DEPLOYMENT_TARGET.  To enable cross-language LTO to work
-    // correctly, we do too.
-    let arch = "i686";
-    let llvm_target = super::apple_base::macos_llvm_target(&arch);
-
     Target {
-        llvm_target: llvm_target.into(),
+        // Clang automatically chooses a more specific target based on
+        // MACOSX_DEPLOYMENT_TARGET.  To enable cross-language LTO to work
+        // correctly, we do too.
+        //
+        // While ld64 doesn't understand i686, LLVM does.
+        llvm_target: macos_llvm_target(Arch::I686).into(),
         pointer_width: 32,
         data_layout: "e-m:o-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
             f64:32:64-f80:128-n8:16:32-S128"
             .into(),
-        arch: "x86".into(),
+        arch: arch.target_arch(),
         options: TargetOptions { mcount: "\u{1}mcount".into(), ..base },
     }
 }
diff --git a/compiler/rustc_target/src/spec/linux_kernel_base.rs b/compiler/rustc_target/src/spec/linux_kernel_base.rs
deleted file mode 100644
index f41533a9548..00000000000
--- a/compiler/rustc_target/src/spec/linux_kernel_base.rs
+++ /dev/null
@@ -1,18 +0,0 @@
-use crate::spec::TargetOptions;
-use crate::spec::{FramePointer, PanicStrategy, RelocModel, RelroLevel, StackProbeType};
-
-pub fn opts() -> TargetOptions {
-    TargetOptions {
-        env: "gnu".into(),
-        disable_redzone: true,
-        panic_strategy: PanicStrategy::Abort,
-        stack_probes: StackProbeType::X86,
-        frame_pointer: FramePointer::Always,
-        position_independent_executables: true,
-        needs_plt: true,
-        relro_level: RelroLevel::Full,
-        relocation_model: RelocModel::Static,
-
-        ..Default::default()
-    }
-}
diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs
index 72b088d663b..1bcb02ecb30 100644
--- a/compiler/rustc_target/src/spec/mod.rs
+++ b/compiler/rustc_target/src/spec/mod.rs
@@ -59,7 +59,6 @@ pub mod crt_objects;
 
 mod android_base;
 mod apple_base;
-mod apple_sdk_base;
 mod avr_gnu_base;
 mod bpf_base;
 mod dragonfly_base;
@@ -71,7 +70,6 @@ mod illumos_base;
 mod l4re_base;
 mod linux_base;
 mod linux_gnu_base;
-mod linux_kernel_base;
 mod linux_musl_base;
 mod linux_uclibc_base;
 mod msvc_base;
@@ -1003,7 +1001,7 @@ macro_rules! supported_targets {
             $(
                 #[test] // `#[test]`
                 fn $module() {
-                    tests_impl::test_target(super::$module::target(), $triple);
+                    tests_impl::test_target(super::$module::target());
                 }
             )+
         }
@@ -1071,8 +1069,6 @@ supported_targets! {
     ("thumbv7neon-linux-androideabi", thumbv7neon_linux_androideabi),
     ("aarch64-linux-android", aarch64_linux_android),
 
-    ("x86_64-unknown-none-linuxkernel", x86_64_unknown_none_linuxkernel),
-
     ("aarch64-unknown-freebsd", aarch64_unknown_freebsd),
     ("armv6-unknown-freebsd", armv6_unknown_freebsd),
     ("armv7-unknown-freebsd", armv7_unknown_freebsd),
@@ -1941,8 +1937,10 @@ impl Target {
             | PlatformIntrinsic
             | Unadjusted
             | Cdecl { .. }
-            | EfiApi
             | RustCold => true,
+            EfiApi => {
+                ["arm", "aarch64", "riscv32", "riscv64", "x86", "x86_64"].contains(&&self.arch[..])
+            }
             X86Interrupt => ["x86", "x86_64"].contains(&&self.arch[..]),
             Aapcs { .. } => "arm" == self.arch,
             CCmseNonSecureCall => ["arm", "aarch64"].contains(&&self.arch[..]),
diff --git a/compiler/rustc_target/src/spec/riscv64gc_unknown_freebsd.rs b/compiler/rustc_target/src/spec/riscv64gc_unknown_freebsd.rs
index 0539eca6c1f..8281bac10f8 100644
--- a/compiler/rustc_target/src/spec/riscv64gc_unknown_freebsd.rs
+++ b/compiler/rustc_target/src/spec/riscv64gc_unknown_freebsd.rs
@@ -4,7 +4,7 @@ pub fn target() -> Target {
     Target {
         llvm_target: "riscv64-unknown-freebsd".into(),
         pointer_width: 64,
-        data_layout: "e-m:e-p:64:64-i64:64-i128:128-n64-S128".into(),
+        data_layout: "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128".into(),
         arch: "riscv64".into(),
         options: TargetOptions {
             code_model: Some(CodeModel::Medium),
diff --git a/compiler/rustc_target/src/spec/riscv64gc_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/riscv64gc_unknown_linux_gnu.rs
index 7d1bf228c37..90dccb28063 100644
--- a/compiler/rustc_target/src/spec/riscv64gc_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/riscv64gc_unknown_linux_gnu.rs
@@ -4,7 +4,7 @@ pub fn target() -> Target {
     Target {
         llvm_target: "riscv64-unknown-linux-gnu".into(),
         pointer_width: 64,
-        data_layout: "e-m:e-p:64:64-i64:64-i128:128-n64-S128".into(),
+        data_layout: "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128".into(),
         arch: "riscv64".into(),
         options: TargetOptions {
             code_model: Some(CodeModel::Medium),
diff --git a/compiler/rustc_target/src/spec/riscv64gc_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/riscv64gc_unknown_linux_musl.rs
index f04f8a48bc8..1a56c78e685 100644
--- a/compiler/rustc_target/src/spec/riscv64gc_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/riscv64gc_unknown_linux_musl.rs
@@ -4,7 +4,7 @@ pub fn target() -> Target {
     Target {
         llvm_target: "riscv64-unknown-linux-musl".into(),
         pointer_width: 64,
-        data_layout: "e-m:e-p:64:64-i64:64-i128:128-n64-S128".into(),
+        data_layout: "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128".into(),
         arch: "riscv64".into(),
         options: TargetOptions {
             code_model: Some(CodeModel::Medium),
diff --git a/compiler/rustc_target/src/spec/riscv64gc_unknown_none_elf.rs b/compiler/rustc_target/src/spec/riscv64gc_unknown_none_elf.rs
index 67806d578c8..409b0b26961 100644
--- a/compiler/rustc_target/src/spec/riscv64gc_unknown_none_elf.rs
+++ b/compiler/rustc_target/src/spec/riscv64gc_unknown_none_elf.rs
@@ -3,7 +3,7 @@ use crate::spec::{RelocModel, Target, TargetOptions};
 
 pub fn target() -> Target {
     Target {
-        data_layout: "e-m:e-p:64:64-i64:64-i128:128-n64-S128".into(),
+        data_layout: "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128".into(),
         llvm_target: "riscv64".into(),
         pointer_width: 64,
         arch: "riscv64".into(),
diff --git a/compiler/rustc_target/src/spec/riscv64gc_unknown_openbsd.rs b/compiler/rustc_target/src/spec/riscv64gc_unknown_openbsd.rs
index cd10f3afaac..ade9d77624b 100644
--- a/compiler/rustc_target/src/spec/riscv64gc_unknown_openbsd.rs
+++ b/compiler/rustc_target/src/spec/riscv64gc_unknown_openbsd.rs
@@ -4,7 +4,7 @@ pub fn target() -> Target {
     Target {
         llvm_target: "riscv64-unknown-openbsd".into(),
         pointer_width: 64,
-        data_layout: "e-m:e-p:64:64-i64:64-i128:128-n64-S128".into(),
+        data_layout: "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128".into(),
         arch: "riscv64".into(),
         options: TargetOptions {
             code_model: Some(CodeModel::Medium),
diff --git a/compiler/rustc_target/src/spec/riscv64imac_unknown_none_elf.rs b/compiler/rustc_target/src/spec/riscv64imac_unknown_none_elf.rs
index f371e09bed7..87aba9171b4 100644
--- a/compiler/rustc_target/src/spec/riscv64imac_unknown_none_elf.rs
+++ b/compiler/rustc_target/src/spec/riscv64imac_unknown_none_elf.rs
@@ -3,7 +3,7 @@ use crate::spec::{RelocModel, Target, TargetOptions};
 
 pub fn target() -> Target {
     Target {
-        data_layout: "e-m:e-p:64:64-i64:64-i128:128-n64-S128".into(),
+        data_layout: "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128".into(),
         llvm_target: "riscv64".into(),
         pointer_width: 64,
         arch: "riscv64".into(),
diff --git a/compiler/rustc_target/src/spec/tests/tests_impl.rs b/compiler/rustc_target/src/spec/tests/tests_impl.rs
index 172da0ed5df..e0ecf8037c3 100644
--- a/compiler/rustc_target/src/spec/tests/tests_impl.rs
+++ b/compiler/rustc_target/src/spec/tests/tests_impl.rs
@@ -2,15 +2,15 @@ use super::super::*;
 use std::assert_matches::assert_matches;
 
 // Test target self-consistency and JSON encoding/decoding roundtrip.
-pub(super) fn test_target(mut target: Target, triple: &str) {
+pub(super) fn test_target(mut target: Target) {
     let recycled_target = Target::from_json(target.to_json()).map(|(j, _)| j);
     target.update_to_cli();
-    target.check_consistency(triple);
+    target.check_consistency();
     assert_eq!(recycled_target, Ok(target));
 }
 
 impl Target {
-    fn check_consistency(&self, triple: &str) {
+    fn check_consistency(&self) {
         assert_eq!(self.is_like_osx, self.vendor == "apple");
         assert_eq!(self.is_like_solaris, self.os == "solaris" || self.os == "illumos");
         assert_eq!(self.is_like_windows, self.os == "windows" || self.os == "uefi");
@@ -129,8 +129,7 @@ impl Target {
         if self.dynamic_linking && !(self.is_like_wasm && self.os != "emscripten") {
             assert_eq!(self.relocation_model, RelocModel::Pic);
         }
-        // PIEs are supported but not enabled by default with linuxkernel target.
-        if self.position_independent_executables && !triple.ends_with("-linuxkernel") {
+        if self.position_independent_executables {
             assert_eq!(self.relocation_model, RelocModel::Pic);
         }
         // The UEFI targets do not support dynamic linking but still require PIC (#101377).
diff --git a/compiler/rustc_target/src/spec/windows_gnullvm_base.rs b/compiler/rustc_target/src/spec/windows_gnullvm_base.rs
index 58210c75a3d..cada28652f9 100644
--- a/compiler/rustc_target/src/spec/windows_gnullvm_base.rs
+++ b/compiler/rustc_target/src/spec/windows_gnullvm_base.rs
@@ -1,4 +1,5 @@
-use crate::spec::{cvs, Cc, LinkerFlavor, Lld, TargetOptions};
+use crate::spec::{cvs, Cc, DebuginfoKind, LinkerFlavor, Lld, SplitDebuginfo, TargetOptions};
+use std::borrow::Cow;
 
 pub fn opts() -> TargetOptions {
     // We cannot use `-nodefaultlibs` because compiler-rt has to be passed
@@ -36,7 +37,10 @@ pub fn opts() -> TargetOptions {
         eh_frame_header: false,
         no_default_libraries: false,
         has_thread_local: true,
-
+        // FIXME(davidtwco): Support Split DWARF on Windows GNU - may require LLVM changes to
+        // output DWO, despite using DWARF, doesn't use ELF..
+        debuginfo_kind: DebuginfoKind::Pdb,
+        supported_split_debuginfo: Cow::Borrowed(&[SplitDebuginfo::Off]),
         ..Default::default()
     }
 }
diff --git a/compiler/rustc_target/src/spec/x86_64_apple_darwin.rs b/compiler/rustc_target/src/spec/x86_64_apple_darwin.rs
index 087be1b957b..c053031612c 100644
--- a/compiler/rustc_target/src/spec/x86_64_apple_darwin.rs
+++ b/compiler/rustc_target/src/spec/x86_64_apple_darwin.rs
@@ -1,29 +1,27 @@
+use super::apple_base::{macos_link_env_remove, macos_llvm_target, opts, Arch};
 use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, SanitizerSet};
 use crate::spec::{StackProbeType, Target, TargetOptions};
 
 pub fn target() -> Target {
-    let arch = "x86_64";
-    let mut base = super::apple_base::opts("macos", arch, "");
-    base.cpu = "core2".into();
-    base.max_atomic_width = Some(128); // core2 support cmpxchg16b
+    let arch = Arch::X86_64;
+    let mut base = opts("macos", arch);
+    base.max_atomic_width = Some(128); // core2 supports cmpxchg16b
     base.frame_pointer = FramePointer::Always;
     base.add_pre_link_args(LinkerFlavor::Darwin(Cc::Yes, Lld::No), &["-m64"]);
-    base.link_env_remove.to_mut().extend(super::apple_base::macos_link_env_remove());
+    base.link_env_remove.to_mut().extend(macos_link_env_remove());
     base.stack_probes = StackProbeType::X86;
     base.supported_sanitizers =
         SanitizerSet::ADDRESS | SanitizerSet::CFI | SanitizerSet::LEAK | SanitizerSet::THREAD;
 
-    // Clang automatically chooses a more specific target based on
-    // MACOSX_DEPLOYMENT_TARGET.  To enable cross-language LTO to work
-    // correctly, we do too.
-    let llvm_target = super::apple_base::macos_llvm_target(&arch);
-
     Target {
-        llvm_target: llvm_target.into(),
+        // Clang automatically chooses a more specific target based on
+        // MACOSX_DEPLOYMENT_TARGET.  To enable cross-language LTO to work
+        // correctly, we do too.
+        llvm_target: macos_llvm_target(arch).into(),
         pointer_width: 64,
         data_layout: "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
             .into(),
-        arch: arch.into(),
+        arch: arch.target_arch(),
         options: TargetOptions { mcount: "\u{1}mcount".into(), ..base },
     }
 }
diff --git a/compiler/rustc_target/src/spec/x86_64_apple_ios.rs b/compiler/rustc_target/src/spec/x86_64_apple_ios.rs
index db23f01c233..fbd3ebd4d04 100644
--- a/compiler/rustc_target/src/spec/x86_64_apple_ios.rs
+++ b/compiler/rustc_target/src/spec/x86_64_apple_ios.rs
@@ -1,20 +1,18 @@
-use super::apple_sdk_base::{opts, Arch};
+use super::apple_base::{ios_sim_llvm_target, opts, Arch};
 use crate::spec::{StackProbeType, Target, TargetOptions};
 
 pub fn target() -> Target {
-    let base = opts("ios", Arch::X86_64_sim);
-    let llvm_target = super::apple_base::ios_sim_llvm_target("x86_64");
-
+    let arch = Arch::X86_64_sim;
     Target {
-        llvm_target: llvm_target.into(),
+        llvm_target: ios_sim_llvm_target(arch).into(),
         pointer_width: 64,
         data_layout: "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
             .into(),
-        arch: "x86_64".into(),
+        arch: arch.target_arch(),
         options: TargetOptions {
             max_atomic_width: Some(64),
             stack_probes: StackProbeType::X86,
-            ..base
+            ..opts("ios", arch)
         },
     }
 }
diff --git a/compiler/rustc_target/src/spec/x86_64_apple_ios_macabi.rs b/compiler/rustc_target/src/spec/x86_64_apple_ios_macabi.rs
index 13259205ac0..0f3f8519963 100644
--- a/compiler/rustc_target/src/spec/x86_64_apple_ios_macabi.rs
+++ b/compiler/rustc_target/src/spec/x86_64_apple_ios_macabi.rs
@@ -1,10 +1,11 @@
-use super::apple_sdk_base::{opts, Arch};
+use super::apple_base::{opts, Arch};
 use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions};
 
 pub fn target() -> Target {
     let llvm_target = "x86_64-apple-ios13.0-macabi";
 
-    let mut base = opts("ios", Arch::X86_64_macabi);
+    let arch = Arch::X86_64_macabi;
+    let mut base = opts("ios", arch);
     base.add_pre_link_args(LinkerFlavor::Darwin(Cc::Yes, Lld::No), &["-target", llvm_target]);
 
     Target {
@@ -12,7 +13,7 @@ pub fn target() -> Target {
         pointer_width: 64,
         data_layout: "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
             .into(),
-        arch: "x86_64".into(),
+        arch: arch.target_arch(),
         options: TargetOptions {
             max_atomic_width: Some(64),
             stack_probes: StackProbeType::X86,
diff --git a/compiler/rustc_target/src/spec/x86_64_apple_tvos.rs b/compiler/rustc_target/src/spec/x86_64_apple_tvos.rs
index c1fd8e1c8b9..550ce0b9ce5 100644
--- a/compiler/rustc_target/src/spec/x86_64_apple_tvos.rs
+++ b/compiler/rustc_target/src/spec/x86_64_apple_tvos.rs
@@ -1,17 +1,17 @@
-use super::apple_sdk_base::{opts, Arch};
+use super::apple_base::{opts, Arch};
 use crate::spec::{StackProbeType, Target, TargetOptions};
 
 pub fn target() -> Target {
-    let base = opts("tvos", Arch::X86_64_sim);
+    let arch = Arch::X86_64_sim;
     Target {
         llvm_target: "x86_64-apple-tvos".into(),
         pointer_width: 64,
         data_layout: "e-m:o-i64:64-f80:128-n8:16:32:64-S128".into(),
-        arch: "x86_64".into(),
+        arch: arch.target_arch(),
         options: TargetOptions {
             max_atomic_width: Some(64),
             stack_probes: StackProbeType::X86,
-            ..base
+            ..opts("tvos", arch)
         },
     }
 }
diff --git a/compiler/rustc_target/src/spec/x86_64_apple_watchos_sim.rs b/compiler/rustc_target/src/spec/x86_64_apple_watchos_sim.rs
index 550566b2aa7..75ce02cba1d 100644
--- a/compiler/rustc_target/src/spec/x86_64_apple_watchos_sim.rs
+++ b/compiler/rustc_target/src/spec/x86_64_apple_watchos_sim.rs
@@ -1,18 +1,14 @@
-use super::apple_sdk_base::{opts, Arch};
+use super::apple_base::{opts, watchos_sim_llvm_target, Arch};
 use crate::spec::{StackProbeType, Target, TargetOptions};
 
 pub fn target() -> Target {
-    let base = opts("watchos", Arch::X86_64_sim);
-
-    let arch = "x86_64";
-    let llvm_target = super::apple_base::watchos_sim_llvm_target(arch);
-
+    let arch = Arch::X86_64_sim;
     Target {
-        llvm_target: llvm_target.into(),
+        llvm_target: watchos_sim_llvm_target(arch).into(),
         pointer_width: 64,
         data_layout: "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
             .into(),
-        arch: "x86_64".into(),
+        arch: arch.target_arch(),
         options: TargetOptions {
             max_atomic_width: Some(64),
             stack_probes: StackProbeType::X86,
@@ -28,7 +24,7 @@ pub fn target() -> Target {
                 darwinpcs\0\
                 -Os\0"
                 .into(),
-            ..base
+            ..opts("watchos", arch)
         },
     }
 }
diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_none_linuxkernel.rs b/compiler/rustc_target/src/spec/x86_64_unknown_none_linuxkernel.rs
deleted file mode 100644
index ebd9636ff51..00000000000
--- a/compiler/rustc_target/src/spec/x86_64_unknown_none_linuxkernel.rs
+++ /dev/null
@@ -1,28 +0,0 @@
-// This defines the amd64 target for the Linux Kernel. See the linux-kernel-base module for
-// generic Linux kernel options.
-
-use crate::spec::{Cc, CodeModel, LinkerFlavor, Lld, Target};
-
-pub fn target() -> Target {
-    let mut base = super::linux_kernel_base::opts();
-    base.cpu = "x86-64".into();
-    base.max_atomic_width = Some(64);
-    base.features =
-        "-mmx,-sse,-sse2,-sse3,-ssse3,-sse4.1,-sse4.2,-3dnow,-3dnowa,-avx,-avx2,+soft-float".into();
-    base.code_model = Some(CodeModel::Kernel);
-    base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]);
-
-    Target {
-        // FIXME: Some dispute, the linux-on-clang folks think this should use
-        // "Linux". We disagree because running *on* Linux is nothing like
-        // running *as" linux, and historically the "os" component as has always
-        // been used to mean the "on" part.
-        llvm_target: "x86_64-unknown-none-elf".into(),
-        pointer_width: 64,
-        data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
-            .into(),
-        arch: "x86_64".into(),
-
-        options: base,
-    }
-}
diff --git a/compiler/rustc_trait_selection/src/autoderef.rs b/compiler/rustc_trait_selection/src/autoderef.rs
index 61cfeec4bbb..46ee2f35976 100644
--- a/compiler/rustc_trait_selection/src/autoderef.rs
+++ b/compiler/rustc_trait_selection/src/autoderef.rs
@@ -27,7 +27,6 @@ pub struct Autoderef<'a, 'tcx> {
     // Meta infos:
     infcx: &'a InferCtxt<'tcx>,
     span: Span,
-    overloaded_span: Span,
     body_id: hir::HirId,
     param_env: ty::ParamEnv<'tcx>,
 
@@ -99,12 +98,10 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> {
         body_id: hir::HirId,
         span: Span,
         base_ty: Ty<'tcx>,
-        overloaded_span: Span,
     ) -> Autoderef<'a, 'tcx> {
         Autoderef {
             infcx,
             span,
-            overloaded_span,
             body_id,
             param_env,
             state: AutoderefSnapshot {
@@ -193,10 +190,6 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> {
         self.span
     }
 
-    pub fn overloaded_span(&self) -> Span {
-        self.overloaded_span
-    }
-
     pub fn reached_recursion_limit(&self) -> bool {
         self.state.reached_recursion_limit
     }
diff --git a/compiler/rustc_trait_selection/src/infer.rs b/compiler/rustc_trait_selection/src/infer.rs
index 96ac4e9c129..0f2e22604dc 100644
--- a/compiler/rustc_trait_selection/src/infer.rs
+++ b/compiler/rustc_trait_selection/src/infer.rs
@@ -93,6 +93,7 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
 
     /// Normalizes associated types in `value`, potentially returning
     /// new obligations that must further be processed.
+    #[instrument(level = "debug", skip(self, cause, param_env), ret)]
     fn partially_normalize_associated_types_in<T>(
         &self,
         cause: ObligationCause<'tcx>,
@@ -102,17 +103,13 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
     where
         T: TypeFoldable<'tcx>,
     {
-        debug!("partially_normalize_associated_types_in(value={:?})", value);
         let mut selcx = traits::SelectionContext::new(self);
         let traits::Normalized { value, obligations } =
             traits::normalize(&mut selcx, param_env, cause, value);
-        debug!(
-            "partially_normalize_associated_types_in: result={:?} predicates={:?}",
-            value, obligations
-        );
         InferOk { value, obligations }
     }
 
+    #[instrument(level = "debug", skip(self), ret)]
     fn type_implements_trait(
         &self,
         trait_def_id: DefId,
@@ -120,11 +117,6 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
         params: SubstsRef<'tcx>,
         param_env: ty::ParamEnv<'tcx>,
     ) -> traits::EvaluationResult {
-        debug!(
-            "type_implements_trait: trait_def_id={:?}, type={:?}, params={:?}, param_env={:?}",
-            trait_def_id, ty, params, param_env
-        );
-
         let trait_ref =
             ty::TraitRef { def_id: trait_def_id, substs: self.tcx.mk_substs_trait(ty, params) };
 
diff --git a/compiler/rustc_trait_selection/src/lib.rs b/compiler/rustc_trait_selection/src/lib.rs
index 5d52aa07523..2dce18e2d3c 100644
--- a/compiler/rustc_trait_selection/src/lib.rs
+++ b/compiler/rustc_trait_selection/src/lib.rs
@@ -10,7 +10,6 @@
 //!
 //! This API is completely unstable and subject to change.
 
-#![allow(rustc::potential_query_instability)]
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
 #![feature(box_patterns)]
 #![feature(control_flow_enum)]
diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs
index ed34ab95ad6..188f8bb7e2a 100644
--- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs
+++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs
@@ -12,7 +12,7 @@ use rustc_middle::ty::fold::{TypeFolder, TypeSuperFoldable};
 use rustc_middle::ty::visit::TypeVisitable;
 use rustc_middle::ty::{PolyTraitRef, Region, RegionVid};
 
-use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
 
 use std::collections::hash_map::Entry;
 use std::collections::VecDeque;
@@ -27,8 +27,8 @@ pub enum RegionTarget<'tcx> {
 
 #[derive(Default, Debug, Clone)]
 pub struct RegionDeps<'tcx> {
-    larger: FxHashSet<RegionTarget<'tcx>>,
-    smaller: FxHashSet<RegionTarget<'tcx>>,
+    larger: FxIndexSet<RegionTarget<'tcx>>,
+    smaller: FxIndexSet<RegionTarget<'tcx>>,
 }
 
 pub enum AutoTraitResult<A> {
@@ -266,7 +266,7 @@ impl<'tcx> AutoTraitFinder<'tcx> {
         }));
 
         let computed_preds = param_env.caller_bounds().iter();
-        let mut user_computed_preds: FxHashSet<_> = user_env.caller_bounds().iter().collect();
+        let mut user_computed_preds: FxIndexSet<_> = user_env.caller_bounds().iter().collect();
 
         let mut new_env = param_env;
         let dummy_cause = ObligationCause::dummy();
@@ -389,7 +389,7 @@ impl<'tcx> AutoTraitFinder<'tcx> {
     /// not just one specific lifetime (e.g., `'static`).
     fn add_user_pred(
         &self,
-        user_computed_preds: &mut FxHashSet<ty::Predicate<'tcx>>,
+        user_computed_preds: &mut FxIndexSet<ty::Predicate<'tcx>>,
         new_pred: ty::Predicate<'tcx>,
     ) {
         let mut should_add_new = true;
@@ -585,7 +585,7 @@ impl<'tcx> AutoTraitFinder<'tcx> {
         &self,
         ty: Ty<'_>,
         nested: impl Iterator<Item = Obligation<'tcx, ty::Predicate<'tcx>>>,
-        computed_preds: &mut FxHashSet<ty::Predicate<'tcx>>,
+        computed_preds: &mut FxIndexSet<ty::Predicate<'tcx>>,
         fresh_preds: &mut FxHashSet<ty::Predicate<'tcx>>,
         predicates: &mut VecDeque<ty::PolyTraitPredicate<'tcx>>,
         select: &mut SelectionContext<'_, 'tcx>,
diff --git a/compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs b/compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs
index 81e1d64493e..d32a990f182 100644
--- a/compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs
+++ b/compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs
@@ -14,6 +14,8 @@ pub struct FulfillmentContext<'tcx> {
     obligations: FxIndexSet<PredicateObligation<'tcx>>,
 
     relationships: FxHashMap<ty::TyVid, ty::FoundRelationships>,
+
+    usable_in_snapshot: bool,
 }
 
 impl FulfillmentContext<'_> {
@@ -21,8 +23,13 @@ impl FulfillmentContext<'_> {
         FulfillmentContext {
             obligations: FxIndexSet::default(),
             relationships: FxHashMap::default(),
+            usable_in_snapshot: false,
         }
     }
+
+    pub(crate) fn new_in_snapshot() -> Self {
+        FulfillmentContext { usable_in_snapshot: true, ..Self::new() }
+    }
 }
 
 impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> {
@@ -41,7 +48,9 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> {
         infcx: &InferCtxt<'tcx>,
         obligation: PredicateObligation<'tcx>,
     ) {
-        assert!(!infcx.is_in_snapshot());
+        if !self.usable_in_snapshot {
+            assert!(!infcx.is_in_snapshot());
+        }
         let obligation = infcx.resolve_vars_if_possible(obligation);
 
         super::relationships::update(self, infcx, &obligation);
@@ -72,7 +81,9 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> {
     }
 
     fn select_where_possible(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<FulfillmentError<'tcx>> {
-        assert!(!infcx.is_in_snapshot());
+        if !self.usable_in_snapshot {
+            assert!(!infcx.is_in_snapshot());
+        }
 
         let mut errors = Vec::new();
         let mut next_round = FxIndexSet::default();
diff --git a/compiler/rustc_trait_selection/src/traits/engine.rs b/compiler/rustc_trait_selection/src/traits/engine.rs
index 21516c93efb..ae29c9f5617 100644
--- a/compiler/rustc_trait_selection/src/traits/engine.rs
+++ b/compiler/rustc_trait_selection/src/traits/engine.rs
@@ -4,7 +4,7 @@ use std::fmt::Debug;
 use super::TraitEngine;
 use super::{ChalkFulfillmentContext, FulfillmentContext};
 use crate::infer::InferCtxtExt;
-use rustc_data_structures::fx::FxHashSet;
+use rustc_data_structures::fx::FxIndexSet;
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_infer::infer::at::ToTrace;
 use rustc_infer::infer::canonical::{
@@ -38,7 +38,7 @@ impl<'tcx> TraitEngineExt<'tcx> for dyn TraitEngine<'tcx> {
 
     fn new_in_snapshot(tcx: TyCtxt<'tcx>) -> Box<Self> {
         if tcx.sess.opts.unstable_opts.chalk {
-            Box::new(ChalkFulfillmentContext::new())
+            Box::new(ChalkFulfillmentContext::new_in_snapshot())
         } else {
             Box::new(FulfillmentContext::new_in_snapshot())
         }
@@ -119,13 +119,10 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> {
         expected: T,
         actual: T,
     ) -> Result<(), TypeError<'tcx>> {
-        match self.infcx.at(cause, param_env).eq(expected, actual) {
-            Ok(InferOk { obligations, value: () }) => {
-                self.register_obligations(obligations);
-                Ok(())
-            }
-            Err(e) => Err(e),
-        }
+        self.infcx
+            .at(cause, param_env)
+            .eq(expected, actual)
+            .map(|infer_ok| self.register_infer_ok_obligations(infer_ok))
     }
 
     pub fn sup<T: ToTrace<'tcx>>(
@@ -144,6 +141,10 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> {
         }
     }
 
+    pub fn select_where_possible(&self) -> Vec<FulfillmentError<'tcx>> {
+        self.engine.borrow_mut().select_where_possible(self.infcx)
+    }
+
     pub fn select_all_or_error(&self) -> Vec<FulfillmentError<'tcx>> {
         self.engine.borrow_mut().select_all_or_error(self.infcx)
     }
@@ -153,10 +154,10 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> {
         param_env: ty::ParamEnv<'tcx>,
         span: Span,
         def_id: LocalDefId,
-    ) -> FxHashSet<Ty<'tcx>> {
+    ) -> FxIndexSet<Ty<'tcx>> {
         let tcx = self.infcx.tcx;
         let assumed_wf_types = tcx.assumed_wf_types(def_id);
-        let mut implied_bounds = FxHashSet::default();
+        let mut implied_bounds = FxIndexSet::default();
         let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
         let cause = ObligationCause::misc(span, hir_id);
         for ty in assumed_wf_types {
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs
new file mode 100644
index 00000000000..58da54afb75
--- /dev/null
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs
@@ -0,0 +1,52 @@
+use rustc_hir::def_id::DefId;
+use rustc_infer::infer::InferCtxt;
+use rustc_infer::traits::{Obligation, ObligationCause, TraitObligation};
+use rustc_span::DUMMY_SP;
+
+use crate::traits::ObligationCtxt;
+
+pub fn recompute_applicable_impls<'tcx>(
+    infcx: &InferCtxt<'tcx>,
+    obligation: &TraitObligation<'tcx>,
+) -> Vec<DefId> {
+    let tcx = infcx.tcx;
+    let param_env = obligation.param_env;
+    let dummy_cause = ObligationCause::dummy();
+    let impl_may_apply = |impl_def_id| {
+        let ocx = ObligationCtxt::new_in_snapshot(infcx);
+        let placeholder_obligation =
+            infcx.replace_bound_vars_with_placeholders(obligation.predicate);
+        let obligation_trait_ref =
+            ocx.normalize(dummy_cause.clone(), param_env, placeholder_obligation.trait_ref);
+
+        let impl_substs = infcx.fresh_substs_for_item(DUMMY_SP, impl_def_id);
+        let impl_trait_ref = tcx.bound_impl_trait_ref(impl_def_id).unwrap().subst(tcx, impl_substs);
+        let impl_trait_ref = ocx.normalize(ObligationCause::dummy(), param_env, impl_trait_ref);
+
+        if let Err(_) = ocx.eq(&dummy_cause, param_env, obligation_trait_ref, impl_trait_ref) {
+            return false;
+        }
+
+        let impl_predicates = tcx.predicates_of(impl_def_id).instantiate(tcx, impl_substs);
+        ocx.register_obligations(
+            impl_predicates
+                .predicates
+                .iter()
+                .map(|&predicate| Obligation::new(dummy_cause.clone(), param_env, predicate)),
+        );
+
+        ocx.select_where_possible().is_empty()
+    };
+
+    let mut impls = Vec::new();
+    tcx.for_each_relevant_impl(
+        obligation.predicate.def_id(),
+        obligation.predicate.skip_binder().trait_ref.self_ty(),
+        |impl_def_id| {
+            if infcx.probe(move |_snapshot| impl_may_apply(impl_def_id)) {
+                impls.push(impl_def_id)
+            }
+        },
+    );
+    impls
+}
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 dacce5cd2f6..e64586407c9 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
@@ -1,17 +1,21 @@
+mod ambiguity;
 pub mod on_unimplemented;
 pub mod suggestions;
 
 use super::{
     FulfillmentContext, FulfillmentError, FulfillmentErrorCode, MismatchedProjectionTypes,
-    Obligation, ObligationCause, ObligationCauseCode, OnUnimplementedDirective,
-    OnUnimplementedNote, OutputTypeParameterMismatch, Overflow, PredicateObligation,
-    SelectionContext, SelectionError, TraitNotObjectSafe,
+    Obligation, ObligationCause, ObligationCauseCode, OutputTypeParameterMismatch, Overflow,
+    PredicateObligation, SelectionContext, SelectionError, TraitNotObjectSafe,
 };
-
 use crate::infer::error_reporting::{TyCategory, TypeAnnotationNeeded as ErrorCode};
 use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use crate::infer::{self, InferCtxt, TyCtxtInferExt};
-use rustc_data_structures::fx::FxHashMap;
+use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
+use crate::traits::query::normalize::AtExt as _;
+use crate::traits::specialize::to_pretty_impl_header;
+use on_unimplemented::OnUnimplementedNote;
+use on_unimplemented::TypeErrCtxtExt as _;
+use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
 use rustc_errors::{
     pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed,
     MultiSpan, Style,
@@ -40,11 +44,6 @@ use rustc_span::{ExpnKind, Span, DUMMY_SP};
 use std::fmt;
 use std::iter;
 use std::ops::ControlFlow;
-
-use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
-use crate::traits::query::normalize::AtExt as _;
-use crate::traits::specialize::to_pretty_impl_header;
-use on_unimplemented::TypeErrCtxtExt as _;
 use suggestions::TypeErrCtxtExt as _;
 
 pub use rustc_infer::traits::error_reporting::*;
@@ -101,7 +100,6 @@ pub trait TypeErrCtxtExt<'tcx> {
         &self,
         errors: &[FulfillmentError<'tcx>],
         body_id: Option<hir::BodyId>,
-        fallback_has_occurred: bool,
     ) -> ErrorGuaranteed;
 
     fn report_overflow_error<T>(
@@ -124,7 +122,6 @@ pub trait TypeErrCtxtExt<'tcx> {
         obligation: PredicateObligation<'tcx>,
         root_obligation: &PredicateObligation<'tcx>,
         error: &SelectionError<'tcx>,
-        fallback_has_occurred: bool,
     );
 }
 
@@ -375,7 +372,6 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
         &self,
         errors: &[FulfillmentError<'tcx>],
         body_id: Option<hir::BodyId>,
-        fallback_has_occurred: bool,
     ) -> ErrorGuaranteed {
         #[derive(Debug)]
         struct ErrorDescriptor<'tcx> {
@@ -383,7 +379,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
             index: Option<usize>, // None if this is an old error
         }
 
-        let mut error_map: FxHashMap<_, Vec<_>> = self
+        let mut error_map: FxIndexMap<_, Vec<_>> = self
             .reported_trait_errors
             .borrow()
             .iter()
@@ -452,7 +448,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
 
         for (error, suppressed) in iter::zip(errors, is_suppressed) {
             if !suppressed {
-                self.report_fulfillment_error(error, body_id, fallback_has_occurred);
+                self.report_fulfillment_error(error, body_id);
             }
         }
 
@@ -534,22 +530,12 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
         mut obligation: PredicateObligation<'tcx>,
         root_obligation: &PredicateObligation<'tcx>,
         error: &SelectionError<'tcx>,
-        fallback_has_occurred: bool,
     ) {
         self.set_tainted_by_errors();
         let tcx = self.tcx;
         let mut span = obligation.cause.span;
 
         let mut err = match *error {
-            SelectionError::Ambiguous(ref impls) => {
-                let mut err = self.tcx.sess.struct_span_err(
-                    obligation.cause.span,
-                    &format!("multiple applicable `impl`s for `{}`", obligation.predicate),
-                );
-                self.annotate_source_of_ambiguity(&mut err, impls, obligation.predicate);
-                err.emit();
-                return;
-            }
             SelectionError::Unimplemented => {
                 // If this obligation was generated as a result of well-formedness checking, see if we
                 // can get a better error message by performing HIR-based well-formedness checking.
@@ -700,6 +686,25 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                             }
                         }
 
+                        if Some(trait_ref.def_id()) == tcx.lang_items().tuple_trait() {
+                            match obligation.cause.code().peel_derives() {
+                                ObligationCauseCode::RustCall => {
+                                    err.set_primary_message("functions with the \"rust-call\" ABI must take a single non-self tuple argument");
+                                }
+                                ObligationCauseCode::BindingObligation(def_id, _)
+                                | ObligationCauseCode::ItemObligation(def_id)
+                                    if ty::ClosureKind::from_def_id(tcx, *def_id).is_some() =>
+                                {
+                                    err.code(rustc_errors::error_code!(E0059));
+                                    err.set_primary_message(format!(
+                                        "type parameter to bare `{}` trait must be a tuple",
+                                        tcx.def_path_str(*def_id)
+                                    ));
+                                }
+                                _ => {}
+                            }
+                        }
+
                         if Some(trait_ref.def_id()) == tcx.lang_items().drop_trait()
                             && predicate_is_const
                         {
@@ -848,12 +853,8 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                             );
                         }
 
-                        let is_fn_trait = [
-                            self.tcx.lang_items().fn_trait(),
-                            self.tcx.lang_items().fn_mut_trait(),
-                            self.tcx.lang_items().fn_once_trait(),
-                        ]
-                        .contains(&Some(trait_ref.def_id()));
+                        let is_fn_trait =
+                            ty::ClosureKind::from_def_id(tcx, trait_ref.def_id()).is_some();
                         let is_target_feature_fn = if let ty::FnDef(def_id, _) =
                             *trait_ref.skip_binder().self_ty().kind()
                         {
@@ -1000,7 +1001,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                         // variable that used to fallback to `()` now falling back to `!`. Issue a
                         // note informing about the change in behaviour.
                         if trait_predicate.skip_binder().self_ty().is_never()
-                            && fallback_has_occurred
+                            && self.fallback_has_occurred
                         {
                             let predicate = trait_predicate.map_bound(|mut trait_pred| {
                                 trait_pred.trait_ref.substs = self.tcx.mk_substs_trait(
@@ -1366,7 +1367,6 @@ trait InferCtxtPrivExt<'tcx> {
         &self,
         error: &FulfillmentError<'tcx>,
         body_id: Option<hir::BodyId>,
-        fallback_has_occurred: bool,
     );
 
     fn report_projection_error(
@@ -1516,7 +1516,6 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
         &self,
         error: &FulfillmentError<'tcx>,
         body_id: Option<hir::BodyId>,
-        fallback_has_occurred: bool,
     ) {
         match error.code {
             FulfillmentErrorCode::CodeSelectionError(ref selection_error) => {
@@ -1524,7 +1523,6 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                     error.obligation.clone(),
                     &error.root_obligation,
                     selection_error,
-                    fallback_has_occurred,
                 );
             }
             FulfillmentErrorCode::CodeProjectionError(ref e) => {
@@ -2138,12 +2136,25 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                     crate::traits::TraitQueryMode::Standard,
                 );
                 match selcx.select_from_obligation(&obligation) {
-                    Err(SelectionError::Ambiguous(impls)) if impls.len() > 1 => {
-                        self.annotate_source_of_ambiguity(&mut err, &impls, predicate);
+                    Ok(None) => {
+                        let impls = ambiguity::recompute_applicable_impls(self.infcx, &obligation);
+                        let has_non_region_infer =
+                            trait_ref.skip_binder().substs.types().any(|t| !t.is_ty_infer());
+                        // It doesn't make sense to talk about applicable impls if there are more
+                        // than a handful of them.
+                        if impls.len() > 1 && impls.len() < 5 && has_non_region_infer {
+                            self.annotate_source_of_ambiguity(&mut err, &impls, predicate);
+                        } else {
+                            if self.is_tainted_by_errors() {
+                                err.delay_as_bug();
+                                return;
+                            }
+                            err.note(&format!("cannot satisfy `{}`", predicate));
+                        }
                     }
                     _ => {
                         if self.is_tainted_by_errors() {
-                            err.cancel();
+                            err.delay_as_bug();
                             return;
                         }
                         err.note(&format!("cannot satisfy `{}`", predicate));
@@ -2435,7 +2446,6 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                 }
             }
         }
-        let msg = format!("multiple `impl`s satisfying `{}` found", predicate);
         let mut crate_names: Vec<_> = crates.iter().map(|n| format!("`{}`", n)).collect();
         crate_names.sort();
         crate_names.dedup();
@@ -2456,13 +2466,9 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
             err.downgrade_to_delayed_bug();
             return;
         }
-        let post = if post.len() > 4 {
-            format!(
-                ":\n{}\nand {} more",
-                post.iter().map(|p| format!("- {}", p)).take(4).collect::<Vec<_>>().join("\n"),
-                post.len() - 4,
-            )
-        } else if post.len() > 1 || (post.len() == 1 && post[0].contains('\n')) {
+
+        let msg = format!("multiple `impl`s satisfying `{}` found", predicate);
+        let post = if post.len() > 1 || (post.len() == 1 && post[0].contains('\n')) {
             format!(":\n{}", post.iter().map(|p| format!("- {}", p)).collect::<Vec<_>>().join("\n"),)
         } else if post.len() == 1 {
             format!(": `{}`", post[0])
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs
index 5eef54c6330..82f0440b307 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs
@@ -1,14 +1,22 @@
-use super::{
-    ObligationCauseCode, OnUnimplementedDirective, OnUnimplementedNote, PredicateObligation,
-};
+use super::{ObligationCauseCode, PredicateObligation};
 use crate::infer::error_reporting::TypeErrCtxt;
+use rustc_ast::{MetaItem, NestedMetaItem};
+use rustc_attr as attr;
+use rustc_data_structures::fx::FxHashMap;
+use rustc_errors::{struct_span_err, ErrorGuaranteed};
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_middle::ty::SubstsRef;
-use rustc_middle::ty::{self, GenericParamDefKind};
-use rustc_span::symbol::sym;
+use rustc_middle::ty::{self, GenericParamDefKind, TyCtxt};
+use rustc_parse_format::{ParseMode, Parser, Piece, Position};
+use rustc_span::symbol::{kw, sym, Symbol};
+use rustc_span::{Span, DUMMY_SP};
 use std::iter;
 
+use crate::errors::{
+    EmptyOnClauseInOnUnimplemented, InvalidOnClauseInOnUnimplemented, NoValueInOnUnimplemented,
+};
+
 use super::InferCtxtPrivExt;
 
 pub trait TypeErrCtxtExt<'tcx> {
@@ -276,3 +284,383 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
         }
     }
 }
+
+#[derive(Clone, Debug)]
+pub struct OnUnimplementedFormatString(Symbol);
+
+#[derive(Debug)]
+pub struct OnUnimplementedDirective {
+    pub condition: Option<MetaItem>,
+    pub subcommands: Vec<OnUnimplementedDirective>,
+    pub message: Option<OnUnimplementedFormatString>,
+    pub label: Option<OnUnimplementedFormatString>,
+    pub note: Option<OnUnimplementedFormatString>,
+    pub parent_label: Option<OnUnimplementedFormatString>,
+    pub append_const_msg: Option<Option<Symbol>>,
+}
+
+/// For the `#[rustc_on_unimplemented]` attribute
+#[derive(Default)]
+pub struct OnUnimplementedNote {
+    pub message: Option<String>,
+    pub label: Option<String>,
+    pub note: Option<String>,
+    pub parent_label: Option<String>,
+    /// Append a message for `~const Trait` errors. `None` means not requested and
+    /// should fallback to a generic message, `Some(None)` suggests using the default
+    /// appended message, `Some(Some(s))` suggests use the `s` message instead of the
+    /// default one..
+    pub append_const_msg: Option<Option<Symbol>>,
+}
+
+impl<'tcx> OnUnimplementedDirective {
+    fn parse(
+        tcx: TyCtxt<'tcx>,
+        item_def_id: DefId,
+        items: &[NestedMetaItem],
+        span: Span,
+        is_root: bool,
+    ) -> Result<Self, ErrorGuaranteed> {
+        let mut errored = None;
+        let mut item_iter = items.iter();
+
+        let parse_value = |value_str| {
+            OnUnimplementedFormatString::try_parse(tcx, item_def_id, value_str, span).map(Some)
+        };
+
+        let condition = if is_root {
+            None
+        } else {
+            let cond = item_iter
+                .next()
+                .ok_or_else(|| tcx.sess.emit_err(EmptyOnClauseInOnUnimplemented { span }))?
+                .meta_item()
+                .ok_or_else(|| tcx.sess.emit_err(InvalidOnClauseInOnUnimplemented { span }))?;
+            attr::eval_condition(cond, &tcx.sess.parse_sess, Some(tcx.features()), &mut |cfg| {
+                if let Some(value) = cfg.value && let Err(guar) = parse_value(value) {
+                    errored = Some(guar);
+                }
+                true
+            });
+            Some(cond.clone())
+        };
+
+        let mut message = None;
+        let mut label = None;
+        let mut note = None;
+        let mut parent_label = None;
+        let mut subcommands = vec![];
+        let mut append_const_msg = None;
+
+        for item in item_iter {
+            if item.has_name(sym::message) && message.is_none() {
+                if let Some(message_) = item.value_str() {
+                    message = parse_value(message_)?;
+                    continue;
+                }
+            } else if item.has_name(sym::label) && label.is_none() {
+                if let Some(label_) = item.value_str() {
+                    label = parse_value(label_)?;
+                    continue;
+                }
+            } else if item.has_name(sym::note) && note.is_none() {
+                if let Some(note_) = item.value_str() {
+                    note = parse_value(note_)?;
+                    continue;
+                }
+            } else if item.has_name(sym::parent_label) && parent_label.is_none() {
+                if let Some(parent_label_) = item.value_str() {
+                    parent_label = parse_value(parent_label_)?;
+                    continue;
+                }
+            } else if item.has_name(sym::on)
+                && is_root
+                && message.is_none()
+                && label.is_none()
+                && note.is_none()
+            {
+                if let Some(items) = item.meta_item_list() {
+                    match Self::parse(tcx, item_def_id, &items, item.span(), false) {
+                        Ok(subcommand) => subcommands.push(subcommand),
+                        Err(reported) => errored = Some(reported),
+                    };
+                    continue;
+                }
+            } else if item.has_name(sym::append_const_msg) && append_const_msg.is_none() {
+                if let Some(msg) = item.value_str() {
+                    append_const_msg = Some(Some(msg));
+                    continue;
+                } else if item.is_word() {
+                    append_const_msg = Some(None);
+                    continue;
+                }
+            }
+
+            // nothing found
+            tcx.sess.emit_err(NoValueInOnUnimplemented { span: item.span() });
+        }
+
+        if let Some(reported) = errored {
+            Err(reported)
+        } else {
+            Ok(OnUnimplementedDirective {
+                condition,
+                subcommands,
+                message,
+                label,
+                note,
+                parent_label,
+                append_const_msg,
+            })
+        }
+    }
+
+    pub fn of_item(tcx: TyCtxt<'tcx>, item_def_id: DefId) -> Result<Option<Self>, ErrorGuaranteed> {
+        let Some(attr) = tcx.get_attr(item_def_id, sym::rustc_on_unimplemented) else {
+            return Ok(None);
+        };
+
+        let result = if let Some(items) = attr.meta_item_list() {
+            Self::parse(tcx, item_def_id, &items, attr.span, true).map(Some)
+        } else if let Some(value) = attr.value_str() {
+            Ok(Some(OnUnimplementedDirective {
+                condition: None,
+                message: None,
+                subcommands: vec![],
+                label: Some(OnUnimplementedFormatString::try_parse(
+                    tcx,
+                    item_def_id,
+                    value,
+                    attr.span,
+                )?),
+                note: None,
+                parent_label: None,
+                append_const_msg: None,
+            }))
+        } else {
+            let reported =
+                tcx.sess.delay_span_bug(DUMMY_SP, "of_item: neither meta_item_list nor value_str");
+            return Err(reported);
+        };
+        debug!("of_item({:?}) = {:?}", item_def_id, result);
+        result
+    }
+
+    pub fn evaluate(
+        &self,
+        tcx: TyCtxt<'tcx>,
+        trait_ref: ty::TraitRef<'tcx>,
+        options: &[(Symbol, Option<String>)],
+    ) -> OnUnimplementedNote {
+        let mut message = None;
+        let mut label = None;
+        let mut note = None;
+        let mut parent_label = None;
+        let mut append_const_msg = None;
+        info!("evaluate({:?}, trait_ref={:?}, options={:?})", self, trait_ref, options);
+
+        let options_map: FxHashMap<Symbol, String> =
+            options.iter().filter_map(|(k, v)| v.as_ref().map(|v| (*k, v.to_owned()))).collect();
+
+        for command in self.subcommands.iter().chain(Some(self)).rev() {
+            if let Some(ref condition) = command.condition && !attr::eval_condition(
+                condition,
+                &tcx.sess.parse_sess,
+                Some(tcx.features()),
+                &mut |cfg| {
+                    let value = cfg.value.map(|v| {
+                        OnUnimplementedFormatString(v).format(tcx, trait_ref, &options_map)
+                    });
+
+                    options.contains(&(cfg.name, value))
+                },
+            ) {
+                debug!("evaluate: skipping {:?} due to condition", command);
+                continue;
+            }
+            debug!("evaluate: {:?} succeeded", command);
+            if let Some(ref message_) = command.message {
+                message = Some(message_.clone());
+            }
+
+            if let Some(ref label_) = command.label {
+                label = Some(label_.clone());
+            }
+
+            if let Some(ref note_) = command.note {
+                note = Some(note_.clone());
+            }
+
+            if let Some(ref parent_label_) = command.parent_label {
+                parent_label = Some(parent_label_.clone());
+            }
+
+            append_const_msg = command.append_const_msg;
+        }
+
+        OnUnimplementedNote {
+            label: label.map(|l| l.format(tcx, trait_ref, &options_map)),
+            message: message.map(|m| m.format(tcx, trait_ref, &options_map)),
+            note: note.map(|n| n.format(tcx, trait_ref, &options_map)),
+            parent_label: parent_label.map(|e_s| e_s.format(tcx, trait_ref, &options_map)),
+            append_const_msg,
+        }
+    }
+}
+
+impl<'tcx> OnUnimplementedFormatString {
+    fn try_parse(
+        tcx: TyCtxt<'tcx>,
+        item_def_id: DefId,
+        from: Symbol,
+        err_sp: Span,
+    ) -> Result<Self, ErrorGuaranteed> {
+        let result = OnUnimplementedFormatString(from);
+        result.verify(tcx, item_def_id, err_sp)?;
+        Ok(result)
+    }
+
+    fn verify(
+        &self,
+        tcx: TyCtxt<'tcx>,
+        item_def_id: DefId,
+        span: Span,
+    ) -> Result<(), ErrorGuaranteed> {
+        let trait_def_id = if tcx.is_trait(item_def_id) {
+            item_def_id
+        } else {
+            tcx.trait_id_of_impl(item_def_id)
+                .expect("expected `on_unimplemented` to correspond to a trait")
+        };
+        let trait_name = tcx.item_name(trait_def_id);
+        let generics = tcx.generics_of(item_def_id);
+        let s = self.0.as_str();
+        let parser = Parser::new(s, None, None, false, ParseMode::Format);
+        let mut result = Ok(());
+        for token in parser {
+            match token {
+                Piece::String(_) => (), // Normal string, no need to check it
+                Piece::NextArgument(a) => match a.position {
+                    Position::ArgumentNamed(s) => {
+                        match Symbol::intern(s) {
+                            // `{Self}` is allowed
+                            kw::SelfUpper => (),
+                            // `{ThisTraitsName}` is allowed
+                            s if s == trait_name => (),
+                            // `{from_method}` is allowed
+                            sym::from_method => (),
+                            // `{from_desugaring}` is allowed
+                            sym::from_desugaring => (),
+                            // `{ItemContext}` is allowed
+                            sym::ItemContext => (),
+                            // `{integral}` and `{integer}` and `{float}` are allowed
+                            sym::integral | sym::integer_ | sym::float => (),
+                            // So is `{A}` if A is a type parameter
+                            s => match generics.params.iter().find(|param| param.name == s) {
+                                Some(_) => (),
+                                None => {
+                                    let reported = struct_span_err!(
+                                        tcx.sess,
+                                        span,
+                                        E0230,
+                                        "there is no parameter `{}` on {}",
+                                        s,
+                                        if trait_def_id == item_def_id {
+                                            format!("trait `{}`", trait_name)
+                                        } else {
+                                            "impl".to_string()
+                                        }
+                                    )
+                                    .emit();
+                                    result = Err(reported);
+                                }
+                            },
+                        }
+                    }
+                    // `{:1}` and `{}` are not to be used
+                    Position::ArgumentIs(..) | Position::ArgumentImplicitlyIs(_) => {
+                        let reported = struct_span_err!(
+                            tcx.sess,
+                            span,
+                            E0231,
+                            "only named substitution parameters are allowed"
+                        )
+                        .emit();
+                        result = Err(reported);
+                    }
+                },
+            }
+        }
+
+        result
+    }
+
+    pub fn format(
+        &self,
+        tcx: TyCtxt<'tcx>,
+        trait_ref: ty::TraitRef<'tcx>,
+        options: &FxHashMap<Symbol, String>,
+    ) -> String {
+        let name = tcx.item_name(trait_ref.def_id);
+        let trait_str = tcx.def_path_str(trait_ref.def_id);
+        let generics = tcx.generics_of(trait_ref.def_id);
+        let generic_map = generics
+            .params
+            .iter()
+            .filter_map(|param| {
+                let value = match param.kind {
+                    GenericParamDefKind::Type { .. } | GenericParamDefKind::Const { .. } => {
+                        trait_ref.substs[param.index as usize].to_string()
+                    }
+                    GenericParamDefKind::Lifetime => return None,
+                };
+                let name = param.name;
+                Some((name, value))
+            })
+            .collect::<FxHashMap<Symbol, String>>();
+        let empty_string = String::new();
+
+        let s = self.0.as_str();
+        let parser = Parser::new(s, None, None, false, ParseMode::Format);
+        let item_context = (options.get(&sym::ItemContext)).unwrap_or(&empty_string);
+        parser
+            .map(|p| match p {
+                Piece::String(s) => s,
+                Piece::NextArgument(a) => match a.position {
+                    Position::ArgumentNamed(s) => {
+                        let s = Symbol::intern(s);
+                        match generic_map.get(&s) {
+                            Some(val) => val,
+                            None if s == name => &trait_str,
+                            None => {
+                                if let Some(val) = options.get(&s) {
+                                    val
+                                } else if s == sym::from_desugaring || s == sym::from_method {
+                                    // don't break messages using these two arguments incorrectly
+                                    &empty_string
+                                } else if s == sym::ItemContext {
+                                    &item_context
+                                } else if s == sym::integral {
+                                    "{integral}"
+                                } else if s == sym::integer_ {
+                                    "{integer}"
+                                } else if s == sym::float {
+                                    "{float}"
+                                } else {
+                                    bug!(
+                                        "broken on_unimplemented {:?} for {:?}: \
+                                      no argument matching {:?}",
+                                        self.0,
+                                        trait_ref,
+                                        s
+                                    )
+                                }
+                            }
+                        }
+                    }
+                    _ => bug!("broken on_unimplemented {:?} - bad format arg", self.0),
+                },
+            })
+            .collect()
+    }
+}
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 d7606d88803..02e880a8e6e 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -714,7 +714,6 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                     obligation.cause.body_id,
                     span,
                     base_ty,
-                    span,
                 );
                 if let Some(steps) = autoderef.find_map(|(ty, steps)| {
                     // Re-add the `&`
@@ -2407,7 +2406,8 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
             | ObligationCauseCode::CheckAssociatedTypeBounds { .. }
             | ObligationCauseCode::LetElse
             | ObligationCauseCode::BinOp { .. }
-            | ObligationCauseCode::AscribeUserTypeProvePredicate(..) => {}
+            | ObligationCauseCode::AscribeUserTypeProvePredicate(..)
+            | ObligationCauseCode::RustCall => {}
             ObligationCauseCode::SliceOrArrayElem => {
                 err.note("slice and array elements must have `Sized` type");
             }
@@ -2445,12 +2445,12 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                             (Ok(l), Ok(r)) => l.line == r.line,
                             _ => true,
                         };
-                    if !ident.span.overlaps(span) && !same_line {
+                    if !ident.span.is_dummy() && !ident.span.overlaps(span) && !same_line {
                         multispan.push_span_label(ident.span, "required by a bound in this");
                     }
                 }
                 let descr = format!("required by a bound in `{}`", item_name);
-                if span != DUMMY_SP {
+                if !span.is_dummy() {
                     let msg = format!("required by this bound in `{}`", item_name);
                     multispan.push_span_label(span, msg);
                     err.span_note(multispan, &descr);
diff --git a/compiler/rustc_trait_selection/src/traits/misc.rs b/compiler/rustc_trait_selection/src/traits/misc.rs
index be603c609cb..b6ded4ce5a3 100644
--- a/compiler/rustc_trait_selection/src/traits/misc.rs
+++ b/compiler/rustc_trait_selection/src/traits/misc.rs
@@ -70,7 +70,7 @@ pub fn can_type_implement_copy<'tcx>(
                     }
                 }
                 Err(errors) => {
-                    infcx.err_ctxt().report_fulfillment_errors(&errors, None, false);
+                    infcx.err_ctxt().report_fulfillment_errors(&errors, None);
                 }
             };
         }
diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs
index 9ee6e0a2bf3..10e48610e3a 100644
--- a/compiler/rustc_trait_selection/src/traits/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/mod.rs
@@ -12,7 +12,6 @@ pub mod error_reporting;
 mod fulfill;
 pub mod misc;
 mod object_safety;
-mod on_unimplemented;
 pub mod outlives_bounds;
 mod project;
 pub mod query;
@@ -58,7 +57,6 @@ pub use self::object_safety::astconv_object_safety_violations;
 pub use self::object_safety::is_vtable_safe_method;
 pub use self::object_safety::MethodViolationCode;
 pub use self::object_safety::ObjectSafetyViolation;
-pub use self::on_unimplemented::{OnUnimplementedDirective, OnUnimplementedNote};
 pub use self::project::{normalize, normalize_projection_type, normalize_to};
 pub use self::select::{EvaluationCache, SelectionCache, SelectionContext};
 pub use self::select::{EvaluationResult, IntercrateAmbiguityCause, OverflowError};
@@ -117,14 +115,12 @@ pub enum TraitQueryMode {
 }
 
 /// Creates predicate obligations from the generic bounds.
+#[instrument(level = "debug", skip(cause, param_env))]
 pub fn predicates_for_generics<'tcx>(
     cause: impl Fn(usize, Span) -> ObligationCause<'tcx>,
     param_env: ty::ParamEnv<'tcx>,
     generic_bounds: ty::InstantiatedPredicates<'tcx>,
 ) -> impl Iterator<Item = PredicateObligation<'tcx>> {
-    let generic_bounds = generic_bounds;
-    debug!("predicates_for_generics(generic_bounds={:?})", generic_bounds);
-
     std::iter::zip(generic_bounds.predicates, generic_bounds.spans).enumerate().map(
         move |(idx, (predicate, span))| Obligation {
             cause: cause(idx, span),
@@ -140,6 +136,7 @@ pub fn predicates_for_generics<'tcx>(
 /// `bound` or is not known to meet bound (note that this is
 /// conservative towards *no impl*, which is the opposite of the
 /// `evaluate` methods).
+#[instrument(level = "debug", skip(infcx, param_env, span), ret)]
 pub fn type_known_to_meet_bound_modulo_regions<'tcx>(
     infcx: &InferCtxt<'tcx>,
     param_env: ty::ParamEnv<'tcx>,
@@ -147,12 +144,6 @@ pub fn type_known_to_meet_bound_modulo_regions<'tcx>(
     def_id: DefId,
     span: Span,
 ) -> bool {
-    debug!(
-        "type_known_to_meet_bound_modulo_regions(ty={:?}, bound={:?})",
-        ty,
-        infcx.tcx.def_path_str(def_id)
-    );
-
     let trait_ref =
         ty::Binder::dummy(ty::TraitRef { def_id, substs: infcx.tcx.mk_substs_trait(ty, &[]) });
     let obligation = Obligation {
@@ -163,12 +154,7 @@ pub fn type_known_to_meet_bound_modulo_regions<'tcx>(
     };
 
     let result = infcx.predicate_must_hold_modulo_regions(&obligation);
-    debug!(
-        "type_known_to_meet_ty={:?} bound={} => {:?}",
-        ty,
-        infcx.tcx.def_path_str(def_id),
-        result
-    );
+    debug!(?result);
 
     if result && ty.has_non_region_infer() {
         // Because of inference "guessing", selection can sometimes claim
@@ -190,21 +176,9 @@ pub fn type_known_to_meet_bound_modulo_regions<'tcx>(
         // *definitively* show that it implements `Copy`. Otherwise,
         // assume it is move; linear is always ok.
         match &errors[..] {
-            [] => {
-                debug!(
-                    "type_known_to_meet_bound_modulo_regions: ty={:?} bound={} success",
-                    ty,
-                    infcx.tcx.def_path_str(def_id)
-                );
-                true
-            }
+            [] => true,
             errors => {
-                debug!(
-                    ?ty,
-                    bound = %infcx.tcx.def_path_str(def_id),
-                    ?errors,
-                    "type_known_to_meet_bound_modulo_regions"
-                );
+                debug!(?errors);
                 false
             }
         }
@@ -238,7 +212,7 @@ fn do_normalize_predicates<'tcx>(
     let predicates = match fully_normalize(&infcx, cause, elaborated_env, predicates) {
         Ok(predicates) => predicates,
         Err(errors) => {
-            let reported = infcx.err_ctxt().report_fulfillment_errors(&errors, None, false);
+            let reported = infcx.err_ctxt().report_fulfillment_errors(&errors, None);
             return Err(reported);
         }
     };
@@ -924,25 +898,13 @@ pub fn vtable_trait_upcasting_coercion_new_vptr_slot<'tcx>(
         def_id: unsize_trait_did,
         substs: tcx.mk_substs_trait(source, &[target.into()]),
     };
-    let obligation = Obligation::new(
-        ObligationCause::dummy(),
-        ty::ParamEnv::reveal_all(),
-        ty::Binder::dummy(ty::TraitPredicate {
-            trait_ref,
-            constness: ty::BoundConstness::NotConst,
-            polarity: ty::ImplPolarity::Positive,
-        }),
-    );
-
-    let infcx = tcx.infer_ctxt().build();
-    let mut selcx = SelectionContext::new(&infcx);
-    let implsrc = selcx.select(&obligation).unwrap();
 
-    let Some(ImplSource::TraitUpcasting(implsrc_traitcasting)) = implsrc else {
-        bug!();
-    };
-
-    implsrc_traitcasting.vtable_vptr_slot
+    match tcx.codegen_select_candidate((ty::ParamEnv::reveal_all(), ty::Binder::dummy(trait_ref))) {
+        Ok(ImplSource::TraitUpcasting(implsrc_traitcasting)) => {
+            implsrc_traitcasting.vtable_vptr_slot
+        }
+        otherwise => bug!("expected TraitUpcasting candidate, got {otherwise:?}"),
+    }
 }
 
 pub fn provide(providers: &mut ty::query::Providers) {
diff --git a/compiler/rustc_trait_selection/src/traits/on_unimplemented.rs b/compiler/rustc_trait_selection/src/traits/on_unimplemented.rs
deleted file mode 100644
index fb062ea71c4..00000000000
--- a/compiler/rustc_trait_selection/src/traits/on_unimplemented.rs
+++ /dev/null
@@ -1,393 +0,0 @@
-use rustc_ast::{MetaItem, NestedMetaItem};
-use rustc_attr as attr;
-use rustc_data_structures::fx::FxHashMap;
-use rustc_errors::{struct_span_err, ErrorGuaranteed};
-use rustc_hir::def_id::DefId;
-use rustc_middle::ty::{self, GenericParamDefKind, TyCtxt};
-use rustc_parse_format::{ParseMode, Parser, Piece, Position};
-use rustc_span::symbol::{kw, sym, Symbol};
-use rustc_span::{Span, DUMMY_SP};
-
-use crate::errors::{
-    EmptyOnClauseInOnUnimplemented, InvalidOnClauseInOnUnimplemented, NoValueInOnUnimplemented,
-};
-
-#[derive(Clone, Debug)]
-pub struct OnUnimplementedFormatString(Symbol);
-
-#[derive(Debug)]
-pub struct OnUnimplementedDirective {
-    pub condition: Option<MetaItem>,
-    pub subcommands: Vec<OnUnimplementedDirective>,
-    pub message: Option<OnUnimplementedFormatString>,
-    pub label: Option<OnUnimplementedFormatString>,
-    pub note: Option<OnUnimplementedFormatString>,
-    pub parent_label: Option<OnUnimplementedFormatString>,
-    pub append_const_msg: Option<Option<Symbol>>,
-}
-
-#[derive(Default)]
-/// For the `#[rustc_on_unimplemented]` attribute
-pub struct OnUnimplementedNote {
-    pub message: Option<String>,
-    pub label: Option<String>,
-    pub note: Option<String>,
-    pub parent_label: Option<String>,
-    /// Append a message for `~const Trait` errors. `None` means not requested and
-    /// should fallback to a generic message, `Some(None)` suggests using the default
-    /// appended message, `Some(Some(s))` suggests use the `s` message instead of the
-    /// default one..
-    pub append_const_msg: Option<Option<Symbol>>,
-}
-
-impl<'tcx> OnUnimplementedDirective {
-    fn parse(
-        tcx: TyCtxt<'tcx>,
-        item_def_id: DefId,
-        items: &[NestedMetaItem],
-        span: Span,
-        is_root: bool,
-    ) -> Result<Self, ErrorGuaranteed> {
-        let mut errored = None;
-        let mut item_iter = items.iter();
-
-        let parse_value = |value_str| {
-            OnUnimplementedFormatString::try_parse(tcx, item_def_id, value_str, span).map(Some)
-        };
-
-        let condition = if is_root {
-            None
-        } else {
-            let cond = item_iter
-                .next()
-                .ok_or_else(|| tcx.sess.emit_err(EmptyOnClauseInOnUnimplemented { span }))?
-                .meta_item()
-                .ok_or_else(|| tcx.sess.emit_err(InvalidOnClauseInOnUnimplemented { span }))?;
-            attr::eval_condition(cond, &tcx.sess.parse_sess, Some(tcx.features()), &mut |cfg| {
-                if let Some(value) = cfg.value && let Err(guar) = parse_value(value) {
-                    errored = Some(guar);
-                }
-                true
-            });
-            Some(cond.clone())
-        };
-
-        let mut message = None;
-        let mut label = None;
-        let mut note = None;
-        let mut parent_label = None;
-        let mut subcommands = vec![];
-        let mut append_const_msg = None;
-
-        for item in item_iter {
-            if item.has_name(sym::message) && message.is_none() {
-                if let Some(message_) = item.value_str() {
-                    message = parse_value(message_)?;
-                    continue;
-                }
-            } else if item.has_name(sym::label) && label.is_none() {
-                if let Some(label_) = item.value_str() {
-                    label = parse_value(label_)?;
-                    continue;
-                }
-            } else if item.has_name(sym::note) && note.is_none() {
-                if let Some(note_) = item.value_str() {
-                    note = parse_value(note_)?;
-                    continue;
-                }
-            } else if item.has_name(sym::parent_label) && parent_label.is_none() {
-                if let Some(parent_label_) = item.value_str() {
-                    parent_label = parse_value(parent_label_)?;
-                    continue;
-                }
-            } else if item.has_name(sym::on)
-                && is_root
-                && message.is_none()
-                && label.is_none()
-                && note.is_none()
-            {
-                if let Some(items) = item.meta_item_list() {
-                    match Self::parse(tcx, item_def_id, &items, item.span(), false) {
-                        Ok(subcommand) => subcommands.push(subcommand),
-                        Err(reported) => errored = Some(reported),
-                    };
-                    continue;
-                }
-            } else if item.has_name(sym::append_const_msg) && append_const_msg.is_none() {
-                if let Some(msg) = item.value_str() {
-                    append_const_msg = Some(Some(msg));
-                    continue;
-                } else if item.is_word() {
-                    append_const_msg = Some(None);
-                    continue;
-                }
-            }
-
-            // nothing found
-            tcx.sess.emit_err(NoValueInOnUnimplemented { span: item.span() });
-        }
-
-        if let Some(reported) = errored {
-            Err(reported)
-        } else {
-            Ok(OnUnimplementedDirective {
-                condition,
-                subcommands,
-                message,
-                label,
-                note,
-                parent_label,
-                append_const_msg,
-            })
-        }
-    }
-
-    pub fn of_item(tcx: TyCtxt<'tcx>, item_def_id: DefId) -> Result<Option<Self>, ErrorGuaranteed> {
-        let Some(attr) = tcx.get_attr(item_def_id, sym::rustc_on_unimplemented) else {
-            return Ok(None);
-        };
-
-        let result = if let Some(items) = attr.meta_item_list() {
-            Self::parse(tcx, item_def_id, &items, attr.span, true).map(Some)
-        } else if let Some(value) = attr.value_str() {
-            Ok(Some(OnUnimplementedDirective {
-                condition: None,
-                message: None,
-                subcommands: vec![],
-                label: Some(OnUnimplementedFormatString::try_parse(
-                    tcx,
-                    item_def_id,
-                    value,
-                    attr.span,
-                )?),
-                note: None,
-                parent_label: None,
-                append_const_msg: None,
-            }))
-        } else {
-            let reported =
-                tcx.sess.delay_span_bug(DUMMY_SP, "of_item: neither meta_item_list nor value_str");
-            return Err(reported);
-        };
-        debug!("of_item({:?}) = {:?}", item_def_id, result);
-        result
-    }
-
-    pub fn evaluate(
-        &self,
-        tcx: TyCtxt<'tcx>,
-        trait_ref: ty::TraitRef<'tcx>,
-        options: &[(Symbol, Option<String>)],
-    ) -> OnUnimplementedNote {
-        let mut message = None;
-        let mut label = None;
-        let mut note = None;
-        let mut parent_label = None;
-        let mut append_const_msg = None;
-        info!("evaluate({:?}, trait_ref={:?}, options={:?})", self, trait_ref, options);
-
-        let options_map: FxHashMap<Symbol, String> =
-            options.iter().filter_map(|(k, v)| v.as_ref().map(|v| (*k, v.to_owned()))).collect();
-
-        for command in self.subcommands.iter().chain(Some(self)).rev() {
-            if let Some(ref condition) = command.condition && !attr::eval_condition(
-                condition,
-                &tcx.sess.parse_sess,
-                Some(tcx.features()),
-                &mut |cfg| {
-                    let value = cfg.value.map(|v| {
-                        OnUnimplementedFormatString(v).format(tcx, trait_ref, &options_map)
-                    });
-
-                    options.contains(&(cfg.name, value))
-                },
-            ) {
-                debug!("evaluate: skipping {:?} due to condition", command);
-                continue;
-            }
-            debug!("evaluate: {:?} succeeded", command);
-            if let Some(ref message_) = command.message {
-                message = Some(message_.clone());
-            }
-
-            if let Some(ref label_) = command.label {
-                label = Some(label_.clone());
-            }
-
-            if let Some(ref note_) = command.note {
-                note = Some(note_.clone());
-            }
-
-            if let Some(ref parent_label_) = command.parent_label {
-                parent_label = Some(parent_label_.clone());
-            }
-
-            append_const_msg = command.append_const_msg;
-        }
-
-        OnUnimplementedNote {
-            label: label.map(|l| l.format(tcx, trait_ref, &options_map)),
-            message: message.map(|m| m.format(tcx, trait_ref, &options_map)),
-            note: note.map(|n| n.format(tcx, trait_ref, &options_map)),
-            parent_label: parent_label.map(|e_s| e_s.format(tcx, trait_ref, &options_map)),
-            append_const_msg,
-        }
-    }
-}
-
-impl<'tcx> OnUnimplementedFormatString {
-    fn try_parse(
-        tcx: TyCtxt<'tcx>,
-        item_def_id: DefId,
-        from: Symbol,
-        err_sp: Span,
-    ) -> Result<Self, ErrorGuaranteed> {
-        let result = OnUnimplementedFormatString(from);
-        result.verify(tcx, item_def_id, err_sp)?;
-        Ok(result)
-    }
-
-    fn verify(
-        &self,
-        tcx: TyCtxt<'tcx>,
-        item_def_id: DefId,
-        span: Span,
-    ) -> Result<(), ErrorGuaranteed> {
-        let trait_def_id = if tcx.is_trait(item_def_id) {
-            item_def_id
-        } else {
-            tcx.trait_id_of_impl(item_def_id)
-                .expect("expected `on_unimplemented` to correspond to a trait")
-        };
-        let trait_name = tcx.item_name(trait_def_id);
-        let generics = tcx.generics_of(item_def_id);
-        let s = self.0.as_str();
-        let parser = Parser::new(s, None, None, false, ParseMode::Format);
-        let mut result = Ok(());
-        for token in parser {
-            match token {
-                Piece::String(_) => (), // Normal string, no need to check it
-                Piece::NextArgument(a) => match a.position {
-                    Position::ArgumentNamed(s) => {
-                        match Symbol::intern(s) {
-                            // `{Self}` is allowed
-                            kw::SelfUpper => (),
-                            // `{ThisTraitsName}` is allowed
-                            s if s == trait_name => (),
-                            // `{from_method}` is allowed
-                            sym::from_method => (),
-                            // `{from_desugaring}` is allowed
-                            sym::from_desugaring => (),
-                            // `{ItemContext}` is allowed
-                            sym::ItemContext => (),
-                            // `{integral}` and `{integer}` and `{float}` are allowed
-                            sym::integral | sym::integer_ | sym::float => (),
-                            // So is `{A}` if A is a type parameter
-                            s => match generics.params.iter().find(|param| param.name == s) {
-                                Some(_) => (),
-                                None => {
-                                    let reported = struct_span_err!(
-                                        tcx.sess,
-                                        span,
-                                        E0230,
-                                        "there is no parameter `{}` on {}",
-                                        s,
-                                        if trait_def_id == item_def_id {
-                                            format!("trait `{}`", trait_name)
-                                        } else {
-                                            "impl".to_string()
-                                        }
-                                    )
-                                    .emit();
-                                    result = Err(reported);
-                                }
-                            },
-                        }
-                    }
-                    // `{:1}` and `{}` are not to be used
-                    Position::ArgumentIs(..) | Position::ArgumentImplicitlyIs(_) => {
-                        let reported = struct_span_err!(
-                            tcx.sess,
-                            span,
-                            E0231,
-                            "only named substitution parameters are allowed"
-                        )
-                        .emit();
-                        result = Err(reported);
-                    }
-                },
-            }
-        }
-
-        result
-    }
-
-    pub fn format(
-        &self,
-        tcx: TyCtxt<'tcx>,
-        trait_ref: ty::TraitRef<'tcx>,
-        options: &FxHashMap<Symbol, String>,
-    ) -> String {
-        let name = tcx.item_name(trait_ref.def_id);
-        let trait_str = tcx.def_path_str(trait_ref.def_id);
-        let generics = tcx.generics_of(trait_ref.def_id);
-        let generic_map = generics
-            .params
-            .iter()
-            .filter_map(|param| {
-                let value = match param.kind {
-                    GenericParamDefKind::Type { .. } | GenericParamDefKind::Const { .. } => {
-                        trait_ref.substs[param.index as usize].to_string()
-                    }
-                    GenericParamDefKind::Lifetime => return None,
-                };
-                let name = param.name;
-                Some((name, value))
-            })
-            .collect::<FxHashMap<Symbol, String>>();
-        let empty_string = String::new();
-
-        let s = self.0.as_str();
-        let parser = Parser::new(s, None, None, false, ParseMode::Format);
-        let item_context = (options.get(&sym::ItemContext)).unwrap_or(&empty_string);
-        parser
-            .map(|p| match p {
-                Piece::String(s) => s,
-                Piece::NextArgument(a) => match a.position {
-                    Position::ArgumentNamed(s) => {
-                        let s = Symbol::intern(s);
-                        match generic_map.get(&s) {
-                            Some(val) => val,
-                            None if s == name => &trait_str,
-                            None => {
-                                if let Some(val) = options.get(&s) {
-                                    val
-                                } else if s == sym::from_desugaring || s == sym::from_method {
-                                    // don't break messages using these two arguments incorrectly
-                                    &empty_string
-                                } else if s == sym::ItemContext {
-                                    &item_context
-                                } else if s == sym::integral {
-                                    "{integral}"
-                                } else if s == sym::integer_ {
-                                    "{integer}"
-                                } else if s == sym::float {
-                                    "{float}"
-                                } else {
-                                    bug!(
-                                        "broken on_unimplemented {:?} for {:?}: \
-                                      no argument matching {:?}",
-                                        self.0,
-                                        trait_ref,
-                                        s
-                                    )
-                                }
-                            }
-                        }
-                    }
-                    _ => bug!("broken on_unimplemented {:?} - bad format arg", self.0),
-                },
-            })
-            .collect()
-    }
-}
diff --git a/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs b/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs
index b1a161c3536..e1092a788e3 100644
--- a/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs
+++ b/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs
@@ -2,7 +2,7 @@ use crate::infer::InferCtxt;
 use crate::traits::query::type_op::{self, TypeOp, TypeOpOutput};
 use crate::traits::query::NoSolution;
 use crate::traits::ObligationCause;
-use rustc_data_structures::fx::FxHashSet;
+use rustc_data_structures::fx::FxIndexSet;
 use rustc_hir as hir;
 use rustc_hir::HirId;
 use rustc_middle::ty::{self, ParamEnv, Ty};
@@ -22,7 +22,7 @@ pub trait InferCtxtExt<'a, 'tcx> {
         &'a self,
         param_env: ty::ParamEnv<'tcx>,
         body_id: hir::HirId,
-        tys: FxHashSet<Ty<'tcx>>,
+        tys: FxIndexSet<Ty<'tcx>>,
     ) -> Bounds<'a, 'tcx>;
 }
 
@@ -103,7 +103,7 @@ impl<'a, 'tcx: 'a> InferCtxtExt<'a, 'tcx> for InferCtxt<'tcx> {
         &'a self,
         param_env: ParamEnv<'tcx>,
         body_id: HirId,
-        tys: FxHashSet<Ty<'tcx>>,
+        tys: FxIndexSet<Ty<'tcx>>,
     ) -> Bounds<'a, 'tcx> {
         tys.into_iter()
             .map(move |ty| {
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index daee5dd8f02..572f82117cc 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -647,7 +647,7 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> {
     #[instrument(skip(self), level = "debug")]
     fn fold_const(&mut self, constant: ty::Const<'tcx>) -> ty::Const<'tcx> {
         let tcx = self.selcx.tcx();
-        if tcx.lazy_normalization() {
+        if tcx.lazy_normalization() || !needs_normalization(&constant, self.param_env.reveal()) {
             constant
         } else {
             let constant = constant.super_fold_with(self);
@@ -2187,7 +2187,7 @@ fn confirm_impl_candidate<'cx, 'tcx>(
 // Verify that the trait item and its implementation have compatible substs lists
 fn check_substs_compatible<'tcx>(
     tcx: TyCtxt<'tcx>,
-    assoc_ty: &ty::AssocItem,
+    assoc_item: &ty::AssocItem,
     substs: ty::SubstsRef<'tcx>,
 ) -> bool {
     fn check_substs_compatible_inner<'tcx>(
@@ -2219,7 +2219,10 @@ fn check_substs_compatible<'tcx>(
         true
     }
 
-    check_substs_compatible_inner(tcx, tcx.generics_of(assoc_ty.def_id), substs.as_slice())
+    let generics = tcx.generics_of(assoc_item.def_id);
+    // Chop off any additional substs (RPITIT) substs
+    let substs = &substs[0..generics.count().min(substs.len())];
+    check_substs_compatible_inner(tcx, generics, substs)
 }
 
 fn confirm_impl_trait_in_trait_candidate<'tcx>(
@@ -2248,11 +2251,27 @@ fn confirm_impl_trait_in_trait_candidate<'tcx>(
         };
     }
 
-    let impl_fn_def_id = leaf_def.item.def_id;
     // Rebase from {trait}::{fn}::{opaque} to {impl}::{fn}::{opaque},
     // since `data.substs` are the impl substs.
     let impl_fn_substs =
         obligation.predicate.substs.rebase_onto(tcx, tcx.parent(trait_fn_def_id), data.substs);
+    let impl_fn_substs = translate_substs(
+        selcx.infcx(),
+        obligation.param_env,
+        data.impl_def_id,
+        impl_fn_substs,
+        leaf_def.defining_node,
+    );
+
+    if !check_substs_compatible(tcx, &leaf_def.item, impl_fn_substs) {
+        let err = tcx.ty_error_with_message(
+            obligation.cause.span,
+            "impl method and trait method have different parameters",
+        );
+        return Progress { term: err.into(), obligations };
+    }
+
+    let impl_fn_def_id = leaf_def.item.def_id;
 
     let cause = ObligationCause::new(
         obligation.cause.span,
diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs
index 715f5be8e2f..a7932b332c9 100644
--- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs
@@ -353,6 +353,10 @@ impl<'cx, 'tcx> FallibleTypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
         &mut self,
         constant: ty::Const<'tcx>,
     ) -> Result<ty::Const<'tcx>, Self::Error> {
+        if !needs_normalization(&constant, self.param_env.reveal()) {
+            return Ok(constant);
+        }
+
         let constant = constant.try_super_fold_with(self)?;
         debug!(?constant, ?self.param_env);
         Ok(crate::traits::project::with_replaced_escaping_bound_vars(
diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
index 4c5bc333961..3671a0d87df 100644
--- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
@@ -20,7 +20,7 @@ use crate::traits;
 use crate::traits::coherence::Conflict;
 use crate::traits::query::evaluate_obligation::InferCtxtExt;
 use crate::traits::{util, SelectionResult};
-use crate::traits::{Ambiguous, ErrorReporting, Overflow, Unimplemented};
+use crate::traits::{ErrorReporting, Overflow, Unimplemented};
 
 use super::BuiltinImplConditions;
 use super::IntercrateAmbiguityCause;
@@ -200,15 +200,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                     // and report ambiguity.
                     if i > 1 {
                         debug!("multiple matches, ambig");
-                        return Err(Ambiguous(
-                            candidates
-                                .into_iter()
-                                .filter_map(|c| match c.candidate {
-                                    SelectionCandidate::ImplCandidate(def_id) => Some(def_id),
-                                    _ => None,
-                                })
-                                .collect(),
-                        ));
+                        return Ok(None);
                     }
                 }
             }
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index 9ebff489201..de158a15d54 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -2,6 +2,12 @@
 //!
 //! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/resolution.html#selection
 
+// FIXME: The `map` field in ProvisionalEvaluationCache should be changed to
+// a `FxIndexMap` to avoid query instability, but right now it causes a perf regression. This would be
+// fixed or at least lightened by the addition of the `drain_filter` method to `FxIndexMap`
+// Relevant: https://github.com/rust-lang/rust/pull/103723 and https://github.com/bluss/indexmap/issues/242
+#![allow(rustc::potential_query_instability)]
+
 use self::EvaluationResult::*;
 use self::SelectionCandidate::*;
 
@@ -24,7 +30,8 @@ use crate::traits::error_reporting::TypeErrCtxtExt;
 use crate::traits::project::ProjectAndUnifyResult;
 use crate::traits::project::ProjectionCacheKeyExt;
 use crate::traits::ProjectionCacheKey;
-use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
+use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
 use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_errors::{Diagnostic, ErrorGuaranteed};
 use rustc_hir as hir;
@@ -294,9 +301,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 assert!(self.query_mode == TraitQueryMode::Canonical);
                 return Err(SelectionError::Overflow(OverflowError::Canonical));
             }
-            Err(SelectionError::Ambiguous(_)) => {
-                return Ok(None);
-            }
             Err(e) => {
                 return Err(e);
             }
@@ -931,7 +935,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
 
         match self.candidate_from_obligation(stack) {
             Ok(Some(c)) => self.evaluate_candidate(stack, &c),
-            Err(SelectionError::Ambiguous(_)) => Ok(EvaluatedToAmbig),
             Ok(None) => Ok(EvaluatedToAmbig),
             Err(Overflow(OverflowError::Canonical)) => Err(OverflowError::Canonical),
             Err(ErrorReporting) => Err(OverflowError::ErrorReporting),
@@ -1132,12 +1135,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
 
     /// filter_impls filters constant trait obligations and candidates that have a positive impl
     /// for a negative goal and a negative impl for a positive goal
-    #[instrument(level = "debug", skip(self))]
+    #[instrument(level = "debug", skip(self, candidates))]
     fn filter_impls(
         &mut self,
         candidates: Vec<SelectionCandidate<'tcx>>,
         obligation: &TraitObligation<'tcx>,
     ) -> Vec<SelectionCandidate<'tcx>> {
+        trace!("{candidates:#?}");
         let tcx = self.tcx();
         let mut result = Vec::with_capacity(candidates.len());
 
@@ -1177,6 +1181,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             }
         }
 
+        trace!("{result:#?}");
         result
     }
 
@@ -1973,6 +1978,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
     /// Bar<i32> where struct Bar<T> { x: T, y: u32 } -> [i32, u32]
     /// Zed<i32> where enum Zed { A(T), B(u32) } -> [i32, u32]
     /// ```
+    #[instrument(level = "debug", skip(self), ret)]
     fn constituent_types_for_ty(
         &self,
         t: ty::Binder<'tcx, Ty<'tcx>>,
diff --git a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
index c891658582a..43819b3f490 100644
--- a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
@@ -16,7 +16,7 @@ use crate::errors::NegativePositiveConflict;
 use crate::infer::{InferCtxt, InferOk, TyCtxtInferExt};
 use crate::traits::select::IntercrateAmbiguityCause;
 use crate::traits::{self, coherence, FutureCompatOverlapErrorKind, ObligationCause};
-use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
+use rustc_data_structures::fx::FxIndexSet;
 use rustc_errors::{struct_span_err, DiagnosticBuilder, EmissionGuarantee};
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_middle::ty::{self, ImplSubject, TyCtxt};
@@ -435,7 +435,7 @@ pub(crate) fn to_pretty_impl_header(tcx: TyCtxt<'_>, impl_def_id: DefId) -> Opti
 
     // FIXME: Currently only handles ?Sized.
     //        Needs to support ?Move and ?DynSized when they are implemented.
-    let mut types_without_default_bounds = FxHashSet::default();
+    let mut types_without_default_bounds = FxIndexSet::default();
     let sized_trait = tcx.lang_items().sized_trait();
 
     if !substs.is_empty() {
diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs
index 8908fe230b0..fc0a9f69003 100644
--- a/compiler/rustc_trait_selection/src/traits/wf.rs
+++ b/compiler/rustc_trait_selection/src/traits/wf.rs
@@ -547,7 +547,7 @@ impl<'tcx> WfPredicates<'tcx> {
                 }
 
                 ty::FnDef(did, substs) => {
-                    let obligations = self.nominal_obligations(did, substs);
+                    let obligations = self.nominal_obligations_without_const(did, substs);
                     self.out.extend(obligations);
                 }
 
diff --git a/compiler/rustc_traits/src/chalk/db.rs b/compiler/rustc_traits/src/chalk/db.rs
index 2035252fe39..07f92299f72 100644
--- a/compiler/rustc_traits/src/chalk/db.rs
+++ b/compiler/rustc_traits/src/chalk/db.rs
@@ -728,7 +728,7 @@ fn bound_vars_for_item<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> SubstsRef<'tcx
         ty::GenericParamDefKind::Lifetime => {
             let br = ty::BoundRegion {
                 var: ty::BoundVar::from_usize(substs.len()),
-                kind: ty::BrAnon(substs.len() as u32),
+                kind: ty::BrAnon(substs.len() as u32, None),
             };
             tcx.mk_region(ty::ReLateBound(ty::INNERMOST, br)).into()
         }
diff --git a/compiler/rustc_traits/src/chalk/lowering.rs b/compiler/rustc_traits/src/chalk/lowering.rs
index 0492e94b94e..b64d53e60de 100644
--- a/compiler/rustc_traits/src/chalk/lowering.rs
+++ b/compiler/rustc_traits/src/chalk/lowering.rs
@@ -498,13 +498,13 @@ impl<'tcx> LowerInto<'tcx, Region<'tcx>> for &chalk_ir::Lifetime<RustInterner<'t
                 ty::DebruijnIndex::from_u32(var.debruijn.depth()),
                 ty::BoundRegion {
                     var: ty::BoundVar::from_usize(var.index),
-                    kind: ty::BrAnon(var.index as u32),
+                    kind: ty::BrAnon(var.index as u32, None),
                 },
             ),
             chalk_ir::LifetimeData::InferenceVar(_var) => unimplemented!(),
             chalk_ir::LifetimeData::Placeholder(p) => ty::RePlaceholder(ty::Placeholder {
                 universe: ty::UniverseIndex::from_usize(p.ui.counter),
-                name: ty::BoundRegionKind::BrAnon(p.idx as u32),
+                name: ty::BoundRegionKind::BrAnon(p.idx as u32, None),
             }),
             chalk_ir::LifetimeData::Static => return interner.tcx.lifetimes.re_static,
             chalk_ir::LifetimeData::Empty(_) => {
@@ -933,7 +933,7 @@ impl<'tcx> TypeVisitor<'tcx> for BoundVarsCollector<'tcx> {
                     }
                 }
 
-                ty::BoundRegionKind::BrAnon(var) => match self.parameters.entry(var) {
+                ty::BoundRegionKind::BrAnon(var, _) => match self.parameters.entry(var) {
                     Entry::Vacant(entry) => {
                         entry.insert(chalk_ir::VariableKind::Lifetime);
                     }
@@ -991,13 +991,13 @@ impl<'a, 'tcx> TypeFolder<'tcx> for NamedBoundVarSubstitutor<'a, 'tcx> {
             ty::ReLateBound(index, br) if index == self.binder_index => match br.kind {
                 ty::BrNamed(def_id, _name) => match self.named_parameters.get(&def_id) {
                     Some(idx) => {
-                        let new_br = ty::BoundRegion { var: br.var, kind: ty::BrAnon(*idx) };
+                        let new_br = ty::BoundRegion { var: br.var, kind: ty::BrAnon(*idx, None) };
                         return self.tcx.mk_region(ty::ReLateBound(index, new_br));
                     }
                     None => panic!("Missing `BrNamed`."),
                 },
                 ty::BrEnv => unimplemented!(),
-                ty::BrAnon(_) => {}
+                ty::BrAnon(..) => {}
             },
             _ => (),
         };
@@ -1072,14 +1072,16 @@ impl<'tcx> TypeFolder<'tcx> for ParamsSubstitutor<'tcx> {
                 Some(idx) => {
                     let br = ty::BoundRegion {
                         var: ty::BoundVar::from_u32(*idx),
-                        kind: ty::BrAnon(*idx),
+                        kind: ty::BrAnon(*idx, None),
                     };
                     self.tcx.mk_region(ty::ReLateBound(self.binder_index, br))
                 }
                 None => {
                     let idx = self.named_regions.len() as u32;
-                    let br =
-                        ty::BoundRegion { var: ty::BoundVar::from_u32(idx), kind: ty::BrAnon(idx) };
+                    let br = ty::BoundRegion {
+                        var: ty::BoundVar::from_u32(idx),
+                        kind: ty::BrAnon(idx, None),
+                    };
                     self.named_regions.insert(_re.def_id, idx);
                     self.tcx.mk_region(ty::ReLateBound(self.binder_index, br))
                 }
@@ -1156,7 +1158,7 @@ impl<'tcx> TypeVisitor<'tcx> for PlaceholdersCollector {
     fn visit_region(&mut self, r: Region<'tcx>) -> ControlFlow<Self::BreakTy> {
         match *r {
             ty::RePlaceholder(p) if p.universe == self.universe_index => {
-                if let ty::BoundRegionKind::BrAnon(anon) = p.name {
+                if let ty::BoundRegionKind::BrAnon(anon, _) = p.name {
                     self.next_anon_region_placeholder = self.next_anon_region_placeholder.max(anon);
                 }
             }
diff --git a/compiler/rustc_transmute/src/layout/tree.rs b/compiler/rustc_transmute/src/layout/tree.rs
index 2bc6bc1fc23..30e20ba6f58 100644
--- a/compiler/rustc_transmute/src/layout/tree.rs
+++ b/compiler/rustc_transmute/src/layout/tree.rs
@@ -436,8 +436,8 @@ pub(crate) mod rustc {
 
             // finally: padding
             let padding_span = trace_span!("adding trailing padding").entered();
-            let padding_needed = layout_summary.total_size - variant_layout.size();
-            if padding_needed > 0 {
+            if layout_summary.total_size > variant_layout.size() {
+                let padding_needed = layout_summary.total_size - variant_layout.size();
                 tree = tree.then(Self::padding(padding_needed));
             };
             drop(padding_span);
diff --git a/library/alloc/src/alloc/tests.rs b/library/alloc/src/alloc/tests.rs
index b2f0194599b..1a5938fd34c 100644
--- a/library/alloc/src/alloc/tests.rs
+++ b/library/alloc/src/alloc/tests.rs
@@ -22,7 +22,6 @@ fn allocate_zeroed() {
 }
 
 #[bench]
-#[cfg_attr(miri, ignore)] // isolated Miri does not support benchmarks
 fn alloc_owned_small(b: &mut Bencher) {
     b.iter(|| {
         let _: Box<_> = Box::new(10);
diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs
index b7e7d5a38a5..66f4c19e0f9 100644
--- a/library/alloc/src/boxed.rs
+++ b/library/alloc/src/boxed.rs
@@ -158,6 +158,8 @@ use core::hash::{Hash, Hasher};
 #[cfg(not(no_global_oom_handling))]
 use core::iter::FromIterator;
 use core::iter::{FusedIterator, Iterator};
+#[cfg(not(bootstrap))]
+use core::marker::Tuple;
 use core::marker::{Destruct, Unpin, Unsize};
 use core::mem;
 use core::ops::{
@@ -1979,6 +1981,7 @@ impl<I: ExactSizeIterator + ?Sized, A: Allocator> ExactSizeIterator for Box<I, A
 #[stable(feature = "fused", since = "1.26.0")]
 impl<I: FusedIterator + ?Sized, A: Allocator> FusedIterator for Box<I, A> {}
 
+#[cfg(bootstrap)]
 #[stable(feature = "boxed_closure_impls", since = "1.35.0")]
 impl<Args, F: FnOnce<Args> + ?Sized, A: Allocator> FnOnce<Args> for Box<F, A> {
     type Output = <F as FnOnce<Args>>::Output;
@@ -1988,6 +1991,17 @@ impl<Args, F: FnOnce<Args> + ?Sized, A: Allocator> FnOnce<Args> for Box<F, A> {
     }
 }
 
+#[cfg(not(bootstrap))]
+#[stable(feature = "boxed_closure_impls", since = "1.35.0")]
+impl<Args: Tuple, F: FnOnce<Args> + ?Sized, A: Allocator> FnOnce<Args> for Box<F, A> {
+    type Output = <F as FnOnce<Args>>::Output;
+
+    extern "rust-call" fn call_once(self, args: Args) -> Self::Output {
+        <F as FnOnce<Args>>::call_once(*self, args)
+    }
+}
+
+#[cfg(bootstrap)]
 #[stable(feature = "boxed_closure_impls", since = "1.35.0")]
 impl<Args, F: FnMut<Args> + ?Sized, A: Allocator> FnMut<Args> for Box<F, A> {
     extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output {
@@ -1995,6 +2009,15 @@ impl<Args, F: FnMut<Args> + ?Sized, A: Allocator> FnMut<Args> for Box<F, A> {
     }
 }
 
+#[cfg(not(bootstrap))]
+#[stable(feature = "boxed_closure_impls", since = "1.35.0")]
+impl<Args: Tuple, F: FnMut<Args> + ?Sized, A: Allocator> FnMut<Args> for Box<F, A> {
+    extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output {
+        <F as FnMut<Args>>::call_mut(self, args)
+    }
+}
+
+#[cfg(bootstrap)]
 #[stable(feature = "boxed_closure_impls", since = "1.35.0")]
 impl<Args, F: Fn<Args> + ?Sized, A: Allocator> Fn<Args> for Box<F, A> {
     extern "rust-call" fn call(&self, args: Args) -> Self::Output {
@@ -2002,6 +2025,14 @@ impl<Args, F: Fn<Args> + ?Sized, A: Allocator> Fn<Args> for Box<F, A> {
     }
 }
 
+#[cfg(not(bootstrap))]
+#[stable(feature = "boxed_closure_impls", since = "1.35.0")]
+impl<Args: Tuple, F: Fn<Args> + ?Sized, A: Allocator> Fn<Args> for Box<F, A> {
+    extern "rust-call" fn call(&self, args: Args) -> Self::Output {
+        <F as Fn<Args>>::call(self, args)
+    }
+}
+
 #[unstable(feature = "coerce_unsized", issue = "27732")]
 impl<T: ?Sized + Unsize<U>, U: ?Sized, A: Allocator> CoerceUnsized<Box<U, A>> for Box<T, A> {}
 
diff --git a/library/alloc/src/collections/btree/node/tests.rs b/library/alloc/src/collections/btree/node/tests.rs
index aadb0dc9c40..64bce0ff8c0 100644
--- a/library/alloc/src/collections/btree/node/tests.rs
+++ b/library/alloc/src/collections/btree/node/tests.rs
@@ -94,6 +94,7 @@ fn test_partial_eq() {
 
 #[test]
 #[cfg(target_arch = "x86_64")]
+#[cfg_attr(miri, ignore)] // We'd like to run Miri with layout randomization
 fn test_sizes() {
     assert_eq!(core::mem::size_of::<LeafNode<(), ()>>(), 16);
     assert_eq!(core::mem::size_of::<LeafNode<i64, i64>>(), 16 + CAPACITY * 2 * 8);
diff --git a/library/alloc/src/collections/mod.rs b/library/alloc/src/collections/mod.rs
index 161a375736c..3e0b0f73550 100644
--- a/library/alloc/src/collections/mod.rs
+++ b/library/alloc/src/collections/mod.rs
@@ -139,7 +139,7 @@ impl Display for TryReserveError {
                 " because the computed capacity exceeded the collection's maximum"
             }
             TryReserveErrorKind::AllocError { .. } => {
-                " because the memory allocator returned a error"
+                " because the memory allocator returned an error"
             }
         };
         fmt.write_str(reason)
diff --git a/library/alloc/src/collections/vec_deque/tests.rs b/library/alloc/src/collections/vec_deque/tests.rs
index 1f2daef213c..6e0f83020f9 100644
--- a/library/alloc/src/collections/vec_deque/tests.rs
+++ b/library/alloc/src/collections/vec_deque/tests.rs
@@ -3,7 +3,6 @@ use core::iter::TrustedLen;
 use super::*;
 
 #[bench]
-#[cfg_attr(miri, ignore)] // isolated Miri does not support benchmarks
 fn bench_push_back_100(b: &mut test::Bencher) {
     let mut deq = VecDeque::with_capacity(101);
     b.iter(|| {
@@ -16,7 +15,6 @@ fn bench_push_back_100(b: &mut test::Bencher) {
 }
 
 #[bench]
-#[cfg_attr(miri, ignore)] // isolated Miri does not support benchmarks
 fn bench_push_front_100(b: &mut test::Bencher) {
     let mut deq = VecDeque::with_capacity(101);
     b.iter(|| {
@@ -29,12 +27,15 @@ fn bench_push_front_100(b: &mut test::Bencher) {
 }
 
 #[bench]
-#[cfg_attr(miri, ignore)] // isolated Miri does not support benchmarks
 fn bench_pop_back_100(b: &mut test::Bencher) {
-    let mut deq = VecDeque::<i32>::with_capacity(101);
+    let size = 100;
+    let mut deq = VecDeque::<i32>::with_capacity(size + 1);
+    // We'll mess with private state to pretend like `deq` is filled.
+    // Make sure the buffer is initialized so that we don't read uninit memory.
+    unsafe { deq.ptr().write_bytes(0u8, size + 1) };
 
     b.iter(|| {
-        deq.head = 100;
+        deq.head = size;
         deq.tail = 0;
         while !deq.is_empty() {
             test::black_box(deq.pop_back());
@@ -43,9 +44,9 @@ fn bench_pop_back_100(b: &mut test::Bencher) {
 }
 
 #[bench]
-#[cfg_attr(miri, ignore)] // isolated Miri does not support benchmarks
 fn bench_retain_whole_10000(b: &mut test::Bencher) {
-    let v = (1..100000).collect::<VecDeque<u32>>();
+    let size = if cfg!(miri) { 1000 } else { 100000 };
+    let v = (1..size).collect::<VecDeque<u32>>();
 
     b.iter(|| {
         let mut v = v.clone();
@@ -54,9 +55,9 @@ fn bench_retain_whole_10000(b: &mut test::Bencher) {
 }
 
 #[bench]
-#[cfg_attr(miri, ignore)] // isolated Miri does not support benchmarks
 fn bench_retain_odd_10000(b: &mut test::Bencher) {
-    let v = (1..100000).collect::<VecDeque<u32>>();
+    let size = if cfg!(miri) { 1000 } else { 100000 };
+    let v = (1..size).collect::<VecDeque<u32>>();
 
     b.iter(|| {
         let mut v = v.clone();
@@ -65,23 +66,26 @@ fn bench_retain_odd_10000(b: &mut test::Bencher) {
 }
 
 #[bench]
-#[cfg_attr(miri, ignore)] // isolated Miri does not support benchmarks
 fn bench_retain_half_10000(b: &mut test::Bencher) {
-    let v = (1..100000).collect::<VecDeque<u32>>();
+    let size = if cfg!(miri) { 1000 } else { 100000 };
+    let v = (1..size).collect::<VecDeque<u32>>();
 
     b.iter(|| {
         let mut v = v.clone();
-        v.retain(|x| *x > 50000)
+        v.retain(|x| *x > size / 2)
     })
 }
 
 #[bench]
-#[cfg_attr(miri, ignore)] // isolated Miri does not support benchmarks
 fn bench_pop_front_100(b: &mut test::Bencher) {
-    let mut deq = VecDeque::<i32>::with_capacity(101);
+    let size = 100;
+    let mut deq = VecDeque::<i32>::with_capacity(size + 1);
+    // We'll mess with private state to pretend like `deq` is filled.
+    // Make sure the buffer is initialized so that we don't read uninit memory.
+    unsafe { deq.ptr().write_bytes(0u8, size + 1) };
 
     b.iter(|| {
-        deq.head = 100;
+        deq.head = size;
         deq.tail = 0;
         while !deq.is_empty() {
             test::black_box(deq.pop_front());
diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs
index ce36b116f13..008926666c1 100644
--- a/library/alloc/src/lib.rs
+++ b/library/alloc/src/lib.rs
@@ -150,6 +150,7 @@
 #![feature(trusted_len)]
 #![feature(trusted_random_access)]
 #![feature(try_trait_v2)]
+#![cfg_attr(not(bootstrap), feature(tuple_trait))]
 #![feature(unchecked_math)]
 #![feature(unicode_internals)]
 #![feature(unsize)]
diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs
index 834c8f58cb2..766006939fa 100644
--- a/library/alloc/src/vec/mod.rs
+++ b/library/alloc/src/vec/mod.rs
@@ -2780,7 +2780,7 @@ impl<T, A: Allocator> IntoIterator for Vec<T, A> {
     /// assert_eq!(v_iter.next(), None);
     /// ```
     #[inline]
-    fn into_iter(self) -> IntoIter<T, A> {
+    fn into_iter(self) -> Self::IntoIter {
         unsafe {
             let mut me = ManuallyDrop::new(self);
             let alloc = ManuallyDrop::new(ptr::read(me.allocator()));
@@ -2808,7 +2808,7 @@ impl<'a, T, A: Allocator> IntoIterator for &'a Vec<T, A> {
     type Item = &'a T;
     type IntoIter = slice::Iter<'a, T>;
 
-    fn into_iter(self) -> slice::Iter<'a, T> {
+    fn into_iter(self) -> Self::IntoIter {
         self.iter()
     }
 }
@@ -2818,7 +2818,7 @@ impl<'a, T, A: Allocator> IntoIterator for &'a mut Vec<T, A> {
     type Item = &'a mut T;
     type IntoIter = slice::IterMut<'a, T>;
 
-    fn into_iter(self) -> slice::IterMut<'a, T> {
+    fn into_iter(self) -> Self::IntoIter {
         self.iter_mut()
     }
 }
diff --git a/library/core/benches/iter.rs b/library/core/benches/iter.rs
index 38887f29af1..9193c79bee8 100644
--- a/library/core/benches/iter.rs
+++ b/library/core/benches/iter.rs
@@ -1,3 +1,4 @@
+use core::borrow::Borrow;
 use core::iter::*;
 use core::mem;
 use core::num::Wrapping;
@@ -403,13 +404,31 @@ fn bench_trusted_random_access_adapters(b: &mut Bencher) {
 
 /// Exercises the iter::Copied specialization for slice::Iter
 #[bench]
-fn bench_copied_array_chunks(b: &mut Bencher) {
+fn bench_copied_chunks(b: &mut Bencher) {
+    let v = vec![1u8; 1024];
+
+    b.iter(|| {
+        let mut iter = black_box(&v).iter().copied();
+        let mut acc = Wrapping(0);
+        // This uses a while-let loop to side-step the TRA specialization in ArrayChunks
+        while let Ok(chunk) = iter.next_chunk::<{ mem::size_of::<u64>() }>() {
+            let d = u64::from_ne_bytes(chunk);
+            acc += Wrapping(d.rotate_left(7).wrapping_add(1));
+        }
+        acc
+    })
+}
+
+/// Exercises the TrustedRandomAccess specialization in ArrayChunks
+#[bench]
+fn bench_trusted_random_access_chunks(b: &mut Bencher) {
     let v = vec![1u8; 1024];
 
     b.iter(|| {
         black_box(&v)
             .iter()
-            .copied()
+            // this shows that we're not relying on the slice::Iter specialization in Copied
+            .map(|b| *b.borrow())
             .array_chunks::<{ mem::size_of::<u64>() }>()
             .map(|ary| {
                 let d = u64::from_ne_bytes(ary);
diff --git a/library/core/benches/lib.rs b/library/core/benches/lib.rs
index 1e462e3fc3f..f1244d93285 100644
--- a/library/core/benches/lib.rs
+++ b/library/core/benches/lib.rs
@@ -1,10 +1,10 @@
 // wasm32 does not support benches (no time).
 #![cfg(not(target_arch = "wasm32"))]
 #![feature(flt2dec)]
-#![feature(int_log)]
 #![feature(test)]
 #![feature(trusted_random_access)]
 #![feature(iter_array_chunks)]
+#![feature(iter_next_chunk)]
 
 extern crate test;
 
diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs
index eae0e1c7618..2090756d7a3 100644
--- a/library/core/src/array/mod.rs
+++ b/library/core/src/array/mod.rs
@@ -865,24 +865,6 @@ where
         return Ok(Try::from_output(unsafe { mem::zeroed() }));
     }
 
-    struct Guard<'a, T, const N: usize> {
-        array_mut: &'a mut [MaybeUninit<T>; N],
-        initialized: usize,
-    }
-
-    impl<T, const N: usize> Drop for Guard<'_, T, N> {
-        fn drop(&mut self) {
-            debug_assert!(self.initialized <= N);
-
-            // SAFETY: this slice will contain only initialized objects.
-            unsafe {
-                crate::ptr::drop_in_place(MaybeUninit::slice_assume_init_mut(
-                    &mut self.array_mut.get_unchecked_mut(..self.initialized),
-                ));
-            }
-        }
-    }
-
     let mut array = MaybeUninit::uninit_array::<N>();
     let mut guard = Guard { array_mut: &mut array, initialized: 0 };
 
@@ -896,13 +878,11 @@ where
                     ControlFlow::Continue(elem) => elem,
                 };
 
-                // SAFETY: `guard.initialized` starts at 0, is increased by one in the
-                // loop and the loop is aborted once it reaches N (which is
-                // `array.len()`).
+                // SAFETY: `guard.initialized` starts at 0, which means push can be called
+                // at most N times, which this loop does.
                 unsafe {
-                    guard.array_mut.get_unchecked_mut(guard.initialized).write(item);
+                    guard.push_unchecked(item);
                 }
-                guard.initialized += 1;
             }
             None => {
                 let alive = 0..guard.initialized;
@@ -920,6 +900,55 @@ where
     Ok(Try::from_output(output))
 }
 
+/// Panic guard for incremental initialization of arrays.
+///
+/// Disarm the guard with `mem::forget` once the array has been initialized.
+///
+/// # Safety
+///
+/// All write accesses to this structure are unsafe and must maintain a correct
+/// count of `initialized` elements.
+///
+/// To minimize indirection fields are still pub but callers should at least use
+/// `push_unchecked` to signal that something unsafe is going on.
+pub(crate) struct Guard<'a, T, const N: usize> {
+    /// The array to be initialized.
+    pub array_mut: &'a mut [MaybeUninit<T>; N],
+    /// The number of items that have been initialized so far.
+    pub initialized: usize,
+}
+
+impl<T, const N: usize> Guard<'_, T, N> {
+    /// Adds an item to the array and updates the initialized item counter.
+    ///
+    /// # Safety
+    ///
+    /// No more than N elements must be initialized.
+    #[inline]
+    pub unsafe fn push_unchecked(&mut self, item: T) {
+        // SAFETY: If `initialized` was correct before and the caller does not
+        // invoke this method more than N times then writes will be in-bounds
+        // and slots will not be initialized more than once.
+        unsafe {
+            self.array_mut.get_unchecked_mut(self.initialized).write(item);
+            self.initialized = self.initialized.unchecked_add(1);
+        }
+    }
+}
+
+impl<T, const N: usize> Drop for Guard<'_, T, N> {
+    fn drop(&mut self) {
+        debug_assert!(self.initialized <= N);
+
+        // SAFETY: this slice will contain only initialized objects.
+        unsafe {
+            crate::ptr::drop_in_place(MaybeUninit::slice_assume_init_mut(
+                &mut self.array_mut.get_unchecked_mut(..self.initialized),
+            ));
+        }
+    }
+}
+
 /// Returns the next chunk of `N` items from the iterator or errors with an
 /// iterator over the remainder. Used for `Iterator::next_chunk`.
 #[inline]
diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs
index e6a11218139..f2975d05457 100644
--- a/library/core/src/cell.rs
+++ b/library/core/src/cell.rs
@@ -1936,7 +1936,7 @@ impl<T> UnsafeCell<T> {
     /// Constructs a new instance of `UnsafeCell` which will wrap the specified
     /// value.
     ///
-    /// All access to the inner value through methods is `unsafe`.
+    /// All access to the inner value through `&UnsafeCell<T>` requires `unsafe` code.
     ///
     /// # Examples
     ///
diff --git a/library/core/src/const_closure.rs b/library/core/src/const_closure.rs
index 9e9c02093be..151c8e6d898 100644
--- a/library/core/src/const_closure.rs
+++ b/library/core/src/const_closure.rs
@@ -1,4 +1,6 @@
 use crate::marker::Destruct;
+#[cfg(not(bootstrap))]
+use crate::marker::Tuple;
 
 /// Struct representing a closure with mutably borrowed data.
 ///
@@ -44,6 +46,7 @@ impl<'a, CapturedData: ?Sized, Function> ConstFnMutClosure<&'a mut CapturedData,
 
 macro_rules! impl_fn_mut_tuple {
     ($($var:ident)*) => {
+        #[cfg(bootstrap)]
         #[allow(unused_parens)]
         impl<'a, $($var,)* ClosureArguments, Function, ClosureReturnValue> const
             FnOnce<ClosureArguments> for ConstFnMutClosure<($(&'a mut $var),*), Function>
@@ -56,6 +59,7 @@ macro_rules! impl_fn_mut_tuple {
             self.call_mut(args)
             }
         }
+        #[cfg(bootstrap)]
         #[allow(unused_parens)]
         impl<'a, $($var,)* ClosureArguments, Function, ClosureReturnValue> const
             FnMut<ClosureArguments> for ConstFnMutClosure<($(&'a mut $var),*), Function>
@@ -68,6 +72,32 @@ macro_rules! impl_fn_mut_tuple {
                 (self.func)(($($var),*), args)
             }
         }
+        #[cfg(not(bootstrap))]
+        #[allow(unused_parens)]
+        impl<'a, $($var,)* ClosureArguments: Tuple, Function, ClosureReturnValue> const
+            FnOnce<ClosureArguments> for ConstFnMutClosure<($(&'a mut $var),*), Function>
+        where
+            Function: ~const Fn(($(&mut $var),*), ClosureArguments) -> ClosureReturnValue+ ~const Destruct,
+        {
+            type Output = ClosureReturnValue;
+
+            extern "rust-call" fn call_once(mut self, args: ClosureArguments) -> Self::Output {
+            self.call_mut(args)
+            }
+        }
+        #[cfg(not(bootstrap))]
+        #[allow(unused_parens)]
+        impl<'a, $($var,)* ClosureArguments: Tuple, Function, ClosureReturnValue> const
+            FnMut<ClosureArguments> for ConstFnMutClosure<($(&'a mut $var),*), Function>
+        where
+            Function: ~const Fn(($(&mut $var),*), ClosureArguments)-> ClosureReturnValue,
+        {
+            extern "rust-call" fn call_mut(&mut self, args: ClosureArguments) -> Self::Output {
+                #[allow(non_snake_case)]
+                let ($($var),*) = &mut self.data;
+                (self.func)(($($var),*), args)
+            }
+        }
     };
 }
 impl_fn_mut_tuple!(A);
diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs
index 1dc79afe83f..cec603dcb10 100644
--- a/library/core/src/intrinsics.rs
+++ b/library/core/src/intrinsics.rs
@@ -55,8 +55,13 @@
 #![allow(missing_docs)]
 
 use crate::marker::DiscriminantKind;
+#[cfg(not(bootstrap))]
+use crate::marker::Tuple;
 use crate::mem;
 
+#[cfg(not(bootstrap))]
+pub mod mir;
+
 // These imports are used for simplifying intra-doc links
 #[allow(unused_imports)]
 #[cfg(all(target_has_atomic = "8", target_has_atomic = "32", target_has_atomic = "ptr"))]
@@ -2169,11 +2174,75 @@ extern "rust-intrinsic" {
     /// `unreachable_unchecked` is actually being reached. The bug is in *crate A*,
     /// which violates the principle that a `const fn` must behave the same at
     /// compile-time and at run-time. The unsafe code in crate B is fine.
+    #[cfg(bootstrap)]
     #[rustc_const_unstable(feature = "const_eval_select", issue = "none")]
     pub fn const_eval_select<ARG, F, G, RET>(arg: ARG, called_in_const: F, called_at_rt: G) -> RET
     where
         G: FnOnce<ARG, Output = RET>,
         F: FnOnce<ARG, Output = RET>;
+
+    /// Selects which function to call depending on the context.
+    ///
+    /// If this function is evaluated at compile-time, then a call to this
+    /// intrinsic will be replaced with a call to `called_in_const`. It gets
+    /// replaced with a call to `called_at_rt` otherwise.
+    ///
+    /// # Type Requirements
+    ///
+    /// The two functions must be both function items. They cannot be function
+    /// pointers or closures. The first function must be a `const fn`.
+    ///
+    /// `arg` will be the tupled arguments that will be passed to either one of
+    /// the two functions, therefore, both functions must accept the same type of
+    /// arguments. Both functions must return RET.
+    ///
+    /// # Safety
+    ///
+    /// The two functions must behave observably equivalent. Safe code in other
+    /// crates may assume that calling a `const fn` at compile-time and at run-time
+    /// produces the same result. A function that produces a different result when
+    /// evaluated at run-time, or has any other observable side-effects, is
+    /// *unsound*.
+    ///
+    /// Here is an example of how this could cause a problem:
+    /// ```no_run
+    /// #![feature(const_eval_select)]
+    /// #![feature(core_intrinsics)]
+    /// use std::hint::unreachable_unchecked;
+    /// use std::intrinsics::const_eval_select;
+    ///
+    /// // Crate A
+    /// pub const fn inconsistent() -> i32 {
+    ///     fn runtime() -> i32 { 1 }
+    ///     const fn compiletime() -> i32 { 2 }
+    ///
+    ///     unsafe {
+    //          // ⚠ This code violates the required equivalence of `compiletime`
+    ///         // and `runtime`.
+    ///         const_eval_select((), compiletime, runtime)
+    ///     }
+    /// }
+    ///
+    /// // Crate B
+    /// const X: i32 = inconsistent();
+    /// let x = inconsistent();
+    /// if x != X { unsafe { unreachable_unchecked(); }}
+    /// ```
+    ///
+    /// This code causes Undefined Behavior when being run, since the
+    /// `unreachable_unchecked` is actually being reached. The bug is in *crate A*,
+    /// which violates the principle that a `const fn` must behave the same at
+    /// compile-time and at run-time. The unsafe code in crate B is fine.
+    #[cfg(not(bootstrap))]
+    #[rustc_const_unstable(feature = "const_eval_select", issue = "none")]
+    pub fn const_eval_select<ARG: Tuple, F, G, RET>(
+        arg: ARG,
+        called_in_const: F,
+        called_at_rt: G,
+    ) -> RET
+    where
+        G: FnOnce<ARG, Output = RET>,
+        F: FnOnce<ARG, Output = RET>;
 }
 
 // Some functions are defined here because they accidentally got made
diff --git a/library/core/src/intrinsics/mir.rs b/library/core/src/intrinsics/mir.rs
new file mode 100644
index 00000000000..1bacdc39148
--- /dev/null
+++ b/library/core/src/intrinsics/mir.rs
@@ -0,0 +1,123 @@
+//! Rustc internal tooling for hand-writing MIR.
+//!
+//! If for some reasons you are not writing rustc tests and have found yourself considering using
+//! this feature, turn back. This is *exceptionally* unstable. There is no attempt at all to make
+//! anything work besides those things which the rustc test suite happened to need. If you make a
+//! typo you'll probably ICE. Really, this is not the solution to your problems. Consider instead
+//! supporting the [stable MIR project group](https://github.com/rust-lang/project-stable-mir).
+//!
+//! The documentation for this module describes how to use this feature. If you are interested in
+//! hacking on the implementation, most of that documentation lives at
+//! `rustc_mir_building/src/build/custom/mod.rs`.
+//!
+//! Typical usage will look like this:
+//!
+//! ```rust
+//! #![feature(core_intrinsics, custom_mir)]
+//!
+//! extern crate core;
+//! use core::intrinsics::mir::*;
+//!
+//! #[custom_mir(dialect = "built")]
+//! pub fn simple(x: i32) -> i32 {
+//!     mir!(
+//!         let temp1: i32;
+//!         let temp2: _;
+//!
+//!         {
+//!             temp1 = x;
+//!             Goto(exit)
+//!         }
+//!
+//!         exit = {
+//!             temp2 = Move(temp1);
+//!             RET = temp2;
+//!             Return()
+//!         }
+//!     )
+//! }
+//! ```
+//!
+//! Hopefully most of this is fairly self-explanatory. Expanding on some notable details:
+//!
+//!  - The `custom_mir` attribute tells the compiler to treat the function as being custom MIR. This
+//!    attribute only works on functions - there is no way to insert custom MIR into the middle of
+//!    another function.
+//!  - The `dialect` and `phase` parameters indicate which version of MIR you are inserting here.
+//!    This will normally be the phase that corresponds to the thing you are trying to test. The
+//!    phase can be omitted for dialects that have just one.
+//!  - You should define your function signature like you normally would. Externally, this function
+//!    can be called like any other function.
+//!  - Type inference works - you don't have to spell out the type of all of your locals.
+//!
+//! For now, all statements and terminators are parsed from nested invocations of the special
+//! functions provided in this module. We additionally want to (but do not yet) support more
+//! "normal" Rust syntax in places where it makes sense. Also, most kinds of instructions are not
+//! supported yet.
+//!
+
+#![unstable(
+    feature = "custom_mir",
+    reason = "MIR is an implementation detail and extremely unstable",
+    issue = "none"
+)]
+#![allow(unused_variables, non_snake_case, missing_debug_implementations)]
+
+/// Type representing basic blocks.
+///
+/// All terminators will have this type as a return type. It helps achieve some type safety.
+pub struct BasicBlock;
+
+macro_rules! define {
+    ($name:literal, $($sig:tt)*) => {
+        #[rustc_diagnostic_item = $name]
+        pub $($sig)* { panic!() }
+    }
+}
+
+define!("mir_return", fn Return() -> BasicBlock);
+define!("mir_goto", fn Goto(destination: BasicBlock) -> BasicBlock);
+define!("mir_retag", fn Retag<T>(place: T));
+define!("mir_retag_raw", fn RetagRaw<T>(place: T));
+define!("mir_move", fn Move<T>(place: T) -> T);
+
+/// Convenience macro for generating custom MIR.
+///
+/// See the module documentation for syntax details. This macro is not magic - it only transforms
+/// your MIR into something that is easier to parse in the compiler.
+#[rustc_macro_transparency = "transparent"]
+pub macro mir {
+    (
+        $(let $local_decl:ident $(: $local_decl_ty:ty)? ;)*
+
+        $entry_block:block
+
+        $(
+            $block_name:ident = $block:block
+        )*
+    ) => {{
+        // First, we declare all basic blocks.
+        $(
+            let $block_name: ::core::intrinsics::mir::BasicBlock;
+        )*
+
+        {
+            // Now all locals
+            #[allow(non_snake_case)]
+            let RET;
+            $(
+                let $local_decl $(: $local_decl_ty)? ;
+            )*
+
+            {
+                // Finally, the contents of the basic blocks
+                $entry_block;
+                $(
+                    $block;
+                )*
+
+                RET
+            }
+        }
+    }}
+}
diff --git a/library/core/src/iter/adapters/array_chunks.rs b/library/core/src/iter/adapters/array_chunks.rs
index d4fb886101f..5e4211058aa 100644
--- a/library/core/src/iter/adapters/array_chunks.rs
+++ b/library/core/src/iter/adapters/array_chunks.rs
@@ -1,6 +1,8 @@
 use crate::array;
-use crate::iter::{ByRefSized, FusedIterator, Iterator};
-use crate::ops::{ControlFlow, Try};
+use crate::const_closure::ConstFnMutClosure;
+use crate::iter::{ByRefSized, FusedIterator, Iterator, TrustedRandomAccessNoCoerce};
+use crate::mem::{self, MaybeUninit};
+use crate::ops::{ControlFlow, NeverShortCircuit, Try};
 
 /// An iterator over `N` elements of the iterator at a time.
 ///
@@ -82,7 +84,13 @@ where
         }
     }
 
-    impl_fold_via_try_fold! { fold -> try_fold }
+    fn fold<B, F>(self, init: B, f: F) -> B
+    where
+        Self: Sized,
+        F: FnMut(B, Self::Item) -> B,
+    {
+        <Self as SpecFold>::fold(self, init, f)
+    }
 }
 
 #[unstable(feature = "iter_array_chunks", reason = "recently added", issue = "100450")]
@@ -168,3 +176,64 @@ where
         self.iter.len() < N
     }
 }
+
+trait SpecFold: Iterator {
+    fn fold<B, F>(self, init: B, f: F) -> B
+    where
+        Self: Sized,
+        F: FnMut(B, Self::Item) -> B;
+}
+
+impl<I, const N: usize> SpecFold for ArrayChunks<I, N>
+where
+    I: Iterator,
+{
+    #[inline]
+    default fn fold<B, F>(mut self, init: B, mut f: F) -> B
+    where
+        Self: Sized,
+        F: FnMut(B, Self::Item) -> B,
+    {
+        let fold = ConstFnMutClosure::new(&mut f, NeverShortCircuit::wrap_mut_2_imp);
+        self.try_fold(init, fold).0
+    }
+}
+
+impl<I, const N: usize> SpecFold for ArrayChunks<I, N>
+where
+    I: Iterator + TrustedRandomAccessNoCoerce,
+{
+    #[inline]
+    fn fold<B, F>(mut self, init: B, mut f: F) -> B
+    where
+        Self: Sized,
+        F: FnMut(B, Self::Item) -> B,
+    {
+        let mut accum = init;
+        let inner_len = self.iter.size();
+        let mut i = 0;
+        // Use a while loop because (0..len).step_by(N) doesn't optimize well.
+        while inner_len - i >= N {
+            let mut chunk = MaybeUninit::uninit_array();
+            let mut guard = array::Guard { array_mut: &mut chunk, initialized: 0 };
+            while guard.initialized < N {
+                // SAFETY: The method consumes the iterator and the loop condition ensures that
+                // all accesses are in bounds and only happen once.
+                unsafe {
+                    let idx = i + guard.initialized;
+                    guard.push_unchecked(self.iter.__iterator_get_unchecked(idx));
+                }
+            }
+            mem::forget(guard);
+            // SAFETY: The loop above initialized all elements
+            let chunk = unsafe { MaybeUninit::array_assume_init(chunk) };
+            accum = f(accum, chunk);
+            i += N;
+        }
+
+        // unlike try_fold this method does not need to take care of the remainder
+        // since `self` will be dropped
+
+        accum
+    }
+}
diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs
index 81f050cb283..404ddff4f9d 100644
--- a/library/core/src/num/int_macros.rs
+++ b/library/core/src/num/int_macros.rs
@@ -2271,15 +2271,16 @@ macro_rules! int_impl {
         /// # Panics
         ///
         /// This function will panic if `self` is less than or equal to zero,
-        /// or if `base` is less then 2.
+        /// or if `base` is less than 2.
         ///
         /// # Examples
         ///
         /// ```
-        /// #![feature(int_log)]
         #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".ilog(5), 1);")]
         /// ```
-        #[unstable(feature = "int_log", issue = "70887")]
+        #[stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")]
+        #[rustc_const_stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")]
+        #[rustc_allow_const_fn_unstable(const_option)]
         #[must_use = "this returns the result of the operation, \
                       without modifying the original"]
         #[inline]
@@ -2298,10 +2299,11 @@ macro_rules! int_impl {
         /// # Examples
         ///
         /// ```
-        /// #![feature(int_log)]
         #[doc = concat!("assert_eq!(2", stringify!($SelfT), ".ilog2(), 1);")]
         /// ```
-        #[unstable(feature = "int_log", issue = "70887")]
+        #[stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")]
+        #[rustc_const_stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")]
+        #[rustc_allow_const_fn_unstable(const_option)]
         #[must_use = "this returns the result of the operation, \
                       without modifying the original"]
         #[inline]
@@ -2319,10 +2321,11 @@ macro_rules! int_impl {
         /// # Example
         ///
         /// ```
-        /// #![feature(int_log)]
         #[doc = concat!("assert_eq!(10", stringify!($SelfT), ".ilog10(), 1);")]
         /// ```
-        #[unstable(feature = "int_log", issue = "70887")]
+        #[stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")]
+        #[rustc_const_stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")]
+        #[rustc_allow_const_fn_unstable(const_option)]
         #[must_use = "this returns the result of the operation, \
                       without modifying the original"]
         #[inline]
@@ -2343,10 +2346,10 @@ macro_rules! int_impl {
         /// # Examples
         ///
         /// ```
-        /// #![feature(int_log)]
         #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".checked_ilog(5), Some(1));")]
         /// ```
-        #[unstable(feature = "int_log", issue = "70887")]
+        #[stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")]
+        #[rustc_const_stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")]
         #[must_use = "this returns the result of the operation, \
                       without modifying the original"]
         #[inline]
@@ -2379,10 +2382,10 @@ macro_rules! int_impl {
         /// # Examples
         ///
         /// ```
-        /// #![feature(int_log)]
         #[doc = concat!("assert_eq!(2", stringify!($SelfT), ".checked_ilog2(), Some(1));")]
         /// ```
-        #[unstable(feature = "int_log", issue = "70887")]
+        #[stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")]
+        #[rustc_const_stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")]
         #[must_use = "this returns the result of the operation, \
                       without modifying the original"]
         #[inline]
@@ -2403,10 +2406,10 @@ macro_rules! int_impl {
         /// # Example
         ///
         /// ```
-        /// #![feature(int_log)]
         #[doc = concat!("assert_eq!(10", stringify!($SelfT), ".checked_ilog10(), Some(1));")]
         /// ```
-        #[unstable(feature = "int_log", issue = "70887")]
+        #[stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")]
+        #[rustc_const_stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")]
         #[must_use = "this returns the result of the operation, \
                       without modifying the original"]
         #[inline]
diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs
index 6b6f3417f8a..5b7521220ac 100644
--- a/library/core/src/num/nonzero.rs
+++ b/library/core/src/num/nonzero.rs
@@ -460,14 +460,14 @@ macro_rules! nonzero_unsigned_operations {
                 /// # Examples
                 ///
                 /// ```
-                /// #![feature(int_log)]
                 #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
                 ///
                 #[doc = concat!("assert_eq!(", stringify!($Ty), "::new(7).unwrap().ilog2(), 2);")]
                 #[doc = concat!("assert_eq!(", stringify!($Ty), "::new(8).unwrap().ilog2(), 3);")]
                 #[doc = concat!("assert_eq!(", stringify!($Ty), "::new(9).unwrap().ilog2(), 3);")]
                 /// ```
-                #[unstable(feature = "int_log", issue = "70887")]
+                #[stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")]
+                #[rustc_const_stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")]
                 #[must_use = "this returns the result of the operation, \
                               without modifying the original"]
                 #[inline]
@@ -485,14 +485,14 @@ macro_rules! nonzero_unsigned_operations {
                 /// # Examples
                 ///
                 /// ```
-                /// #![feature(int_log)]
                 #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
                 ///
                 #[doc = concat!("assert_eq!(", stringify!($Ty), "::new(99).unwrap().ilog10(), 1);")]
                 #[doc = concat!("assert_eq!(", stringify!($Ty), "::new(100).unwrap().ilog10(), 2);")]
                 #[doc = concat!("assert_eq!(", stringify!($Ty), "::new(101).unwrap().ilog10(), 2);")]
                 /// ```
-                #[unstable(feature = "int_log", issue = "70887")]
+                #[stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")]
+                #[rustc_const_stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")]
                 #[must_use = "this returns the result of the operation, \
                               without modifying the original"]
                 #[inline]
diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs
index 93f65c5c7aa..0563f28278d 100644
--- a/library/core/src/num/uint_macros.rs
+++ b/library/core/src/num/uint_macros.rs
@@ -692,15 +692,16 @@ macro_rules! uint_impl {
         ///
         /// # Panics
         ///
-        /// This function will panic if `self` is zero, or if `base` is less then 2.
+        /// This function will panic if `self` is zero, or if `base` is less than 2.
         ///
         /// # Examples
         ///
         /// ```
-        /// #![feature(int_log)]
         #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".ilog(5), 1);")]
         /// ```
-        #[unstable(feature = "int_log", issue = "70887")]
+        #[stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")]
+        #[rustc_const_stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")]
+        #[rustc_allow_const_fn_unstable(const_option)]
         #[must_use = "this returns the result of the operation, \
                       without modifying the original"]
         #[inline]
@@ -719,10 +720,11 @@ macro_rules! uint_impl {
         /// # Examples
         ///
         /// ```
-        /// #![feature(int_log)]
         #[doc = concat!("assert_eq!(2", stringify!($SelfT), ".ilog2(), 1);")]
         /// ```
-        #[unstable(feature = "int_log", issue = "70887")]
+        #[stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")]
+        #[rustc_const_stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")]
+        #[rustc_allow_const_fn_unstable(const_option)]
         #[must_use = "this returns the result of the operation, \
                       without modifying the original"]
         #[inline]
@@ -740,10 +742,11 @@ macro_rules! uint_impl {
         /// # Example
         ///
         /// ```
-        /// #![feature(int_log)]
         #[doc = concat!("assert_eq!(10", stringify!($SelfT), ".ilog10(), 1);")]
         /// ```
-        #[unstable(feature = "int_log", issue = "70887")]
+        #[stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")]
+        #[rustc_const_stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")]
+        #[rustc_allow_const_fn_unstable(const_option)]
         #[must_use = "this returns the result of the operation, \
                       without modifying the original"]
         #[inline]
@@ -764,10 +767,10 @@ macro_rules! uint_impl {
         /// # Examples
         ///
         /// ```
-        /// #![feature(int_log)]
         #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".checked_ilog(5), Some(1));")]
         /// ```
-        #[unstable(feature = "int_log", issue = "70887")]
+        #[stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")]
+        #[rustc_const_stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")]
         #[must_use = "this returns the result of the operation, \
                       without modifying the original"]
         #[inline]
@@ -800,10 +803,10 @@ macro_rules! uint_impl {
         /// # Examples
         ///
         /// ```
-        /// #![feature(int_log)]
         #[doc = concat!("assert_eq!(2", stringify!($SelfT), ".checked_ilog2(), Some(1));")]
         /// ```
-        #[unstable(feature = "int_log", issue = "70887")]
+        #[stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")]
+        #[rustc_const_stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")]
         #[must_use = "this returns the result of the operation, \
                       without modifying the original"]
         #[inline]
@@ -822,10 +825,10 @@ macro_rules! uint_impl {
         /// # Examples
         ///
         /// ```
-        /// #![feature(int_log)]
         #[doc = concat!("assert_eq!(10", stringify!($SelfT), ".checked_ilog10(), Some(1));")]
         /// ```
-        #[unstable(feature = "int_log", issue = "70887")]
+        #[stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")]
+        #[rustc_const_stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")]
         #[must_use = "this returns the result of the operation, \
                       without modifying the original"]
         #[inline]
diff --git a/library/core/src/ops/function.rs b/library/core/src/ops/function.rs
index 2e0a752c815..11b43b621c7 100644
--- a/library/core/src/ops/function.rs
+++ b/library/core/src/ops/function.rs
@@ -1,3 +1,6 @@
+#[cfg(not(bootstrap))]
+use crate::marker::Tuple;
+
 /// The version of the call operator that takes an immutable receiver.
 ///
 /// Instances of `Fn` can be called repeatedly without mutating state.
@@ -51,6 +54,7 @@
 /// let double = |x| x * 2;
 /// assert_eq!(call_with_one(double), 2);
 /// ```
+#[cfg(bootstrap)]
 #[lang = "fn"]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_diagnostic_item = "Fn"]
@@ -71,13 +75,93 @@
 )]
 #[fundamental] // so that regex can rely that `&str: !FnMut`
 #[must_use = "closures are lazy and do nothing unless called"]
-#[cfg_attr(not(bootstrap), const_trait)]
 pub trait Fn<Args>: FnMut<Args> {
     /// Performs the call operation.
     #[unstable(feature = "fn_traits", issue = "29625")]
     extern "rust-call" fn call(&self, args: Args) -> Self::Output;
 }
 
+/// The version of the call operator that takes an immutable receiver.
+///
+/// Instances of `Fn` can be called repeatedly without mutating state.
+///
+/// *This trait (`Fn`) is not to be confused with [function pointers]
+/// (`fn`).*
+///
+/// `Fn` is implemented automatically by closures which only take immutable
+/// references to captured variables or don't capture anything at all, as well
+/// as (safe) [function pointers] (with some caveats, see their documentation
+/// for more details). Additionally, for any type `F` that implements `Fn`, `&F`
+/// implements `Fn`, too.
+///
+/// Since both [`FnMut`] and [`FnOnce`] are supertraits of `Fn`, any
+/// instance of `Fn` can be used as a parameter where a [`FnMut`] or [`FnOnce`]
+/// is expected.
+///
+/// Use `Fn` as a bound when you want to accept a parameter of function-like
+/// type and need to call it repeatedly and without mutating state (e.g., when
+/// calling it concurrently). If you do not need such strict requirements, use
+/// [`FnMut`] or [`FnOnce`] as bounds.
+///
+/// See the [chapter on closures in *The Rust Programming Language*][book] for
+/// some more information on this topic.
+///
+/// Also of note is the special syntax for `Fn` traits (e.g.
+/// `Fn(usize, bool) -> usize`). Those interested in the technical details of
+/// this can refer to [the relevant section in the *Rustonomicon*][nomicon].
+///
+/// [book]: ../../book/ch13-01-closures.html
+/// [function pointers]: fn
+/// [nomicon]: ../../nomicon/hrtb.html
+///
+/// # Examples
+///
+/// ## Calling a closure
+///
+/// ```
+/// let square = |x| x * x;
+/// assert_eq!(square(5), 25);
+/// ```
+///
+/// ## Using a `Fn` parameter
+///
+/// ```
+/// fn call_with_one<F>(func: F) -> usize
+///     where F: Fn(usize) -> usize {
+///     func(1)
+/// }
+///
+/// let double = |x| x * 2;
+/// assert_eq!(call_with_one(double), 2);
+/// ```
+#[cfg(not(bootstrap))]
+#[lang = "fn"]
+#[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_diagnostic_item = "Fn"]
+#[rustc_paren_sugar]
+#[rustc_on_unimplemented(
+    on(
+        Args = "()",
+        note = "wrap the `{Self}` in a closure with no arguments: `|| {{ /* code */ }}`"
+    ),
+    on(
+        _Self = "unsafe fn",
+        note = "unsafe function cannot be called generically without an unsafe block",
+        // SAFETY: tidy is not smart enough to tell that the below unsafe block is a string
+        label = "call the function in a closure: `|| unsafe {{ /* code */ }}`"
+    ),
+    message = "expected a `{Fn}<{Args}>` closure, found `{Self}`",
+    label = "expected an `Fn<{Args}>` closure, found `{Self}`"
+)]
+#[fundamental] // so that regex can rely that `&str: !FnMut`
+#[must_use = "closures are lazy and do nothing unless called"]
+#[const_trait]
+pub trait Fn<Args: Tuple>: FnMut<Args> {
+    /// Performs the call operation.
+    #[unstable(feature = "fn_traits", issue = "29625")]
+    extern "rust-call" fn call(&self, args: Args) -> Self::Output;
+}
+
 /// The version of the call operator that takes a mutable receiver.
 ///
 /// Instances of `FnMut` can be called repeatedly and may mutate state.
@@ -139,6 +223,7 @@ pub trait Fn<Args>: FnMut<Args> {
 ///
 /// assert_eq!(x, 5);
 /// ```
+#[cfg(bootstrap)]
 #[lang = "fn_mut"]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_diagnostic_item = "FnMut"]
@@ -159,13 +244,101 @@ pub trait Fn<Args>: FnMut<Args> {
 )]
 #[fundamental] // so that regex can rely that `&str: !FnMut`
 #[must_use = "closures are lazy and do nothing unless called"]
-#[cfg_attr(not(bootstrap), const_trait)]
 pub trait FnMut<Args>: FnOnce<Args> {
     /// Performs the call operation.
     #[unstable(feature = "fn_traits", issue = "29625")]
     extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output;
 }
 
+/// The version of the call operator that takes a mutable receiver.
+///
+/// Instances of `FnMut` can be called repeatedly and may mutate state.
+///
+/// `FnMut` is implemented automatically by closures which take mutable
+/// references to captured variables, as well as all types that implement
+/// [`Fn`], e.g., (safe) [function pointers] (since `FnMut` is a supertrait of
+/// [`Fn`]). Additionally, for any type `F` that implements `FnMut`, `&mut F`
+/// implements `FnMut`, too.
+///
+/// Since [`FnOnce`] is a supertrait of `FnMut`, any instance of `FnMut` can be
+/// used where a [`FnOnce`] is expected, and since [`Fn`] is a subtrait of
+/// `FnMut`, any instance of [`Fn`] can be used where `FnMut` is expected.
+///
+/// Use `FnMut` as a bound when you want to accept a parameter of function-like
+/// type and need to call it repeatedly, while allowing it to mutate state.
+/// If you don't want the parameter to mutate state, use [`Fn`] as a
+/// bound; if you don't need to call it repeatedly, use [`FnOnce`].
+///
+/// See the [chapter on closures in *The Rust Programming Language*][book] for
+/// some more information on this topic.
+///
+/// Also of note is the special syntax for `Fn` traits (e.g.
+/// `Fn(usize, bool) -> usize`). Those interested in the technical details of
+/// this can refer to [the relevant section in the *Rustonomicon*][nomicon].
+///
+/// [book]: ../../book/ch13-01-closures.html
+/// [function pointers]: fn
+/// [nomicon]: ../../nomicon/hrtb.html
+///
+/// # Examples
+///
+/// ## Calling a mutably capturing closure
+///
+/// ```
+/// let mut x = 5;
+/// {
+///     let mut square_x = || x *= x;
+///     square_x();
+/// }
+/// assert_eq!(x, 25);
+/// ```
+///
+/// ## Using a `FnMut` parameter
+///
+/// ```
+/// fn do_twice<F>(mut func: F)
+///     where F: FnMut()
+/// {
+///     func();
+///     func();
+/// }
+///
+/// let mut x: usize = 1;
+/// {
+///     let add_two_to_x = || x += 2;
+///     do_twice(add_two_to_x);
+/// }
+///
+/// assert_eq!(x, 5);
+/// ```
+#[cfg(not(bootstrap))]
+#[lang = "fn_mut"]
+#[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_diagnostic_item = "FnMut"]
+#[rustc_paren_sugar]
+#[rustc_on_unimplemented(
+    on(
+        Args = "()",
+        note = "wrap the `{Self}` in a closure with no arguments: `|| {{ /* code */ }}`"
+    ),
+    on(
+        _Self = "unsafe fn",
+        note = "unsafe function cannot be called generically without an unsafe block",
+        // SAFETY: tidy is not smart enough to tell that the below unsafe block is a string
+        label = "call the function in a closure: `|| unsafe {{ /* code */ }}`"
+    ),
+    message = "expected a `{FnMut}<{Args}>` closure, found `{Self}`",
+    label = "expected an `FnMut<{Args}>` closure, found `{Self}`"
+)]
+#[fundamental] // so that regex can rely that `&str: !FnMut`
+#[must_use = "closures are lazy and do nothing unless called"]
+#[const_trait]
+pub trait FnMut<Args: Tuple>: FnOnce<Args> {
+    /// Performs the call operation.
+    #[unstable(feature = "fn_traits", issue = "29625")]
+    extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output;
+}
+
 /// The version of the call operator that takes a by-value receiver.
 ///
 /// Instances of `FnOnce` can be called, but might not be callable multiple
@@ -219,6 +392,7 @@ pub trait FnMut<Args>: FnOnce<Args> {
 ///
 /// // `consume_and_return_x` can no longer be invoked at this point
 /// ```
+#[cfg(bootstrap)]
 #[lang = "fn_once"]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_diagnostic_item = "FnOnce"]
@@ -239,7 +413,6 @@ pub trait FnMut<Args>: FnOnce<Args> {
 )]
 #[fundamental] // so that regex can rely that `&str: !FnMut`
 #[must_use = "closures are lazy and do nothing unless called"]
-#[cfg_attr(not(bootstrap), const_trait)]
 pub trait FnOnce<Args> {
     /// The returned type after the call operator is used.
     #[lang = "fn_once_output"]
@@ -251,6 +424,93 @@ pub trait FnOnce<Args> {
     extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
 }
 
+/// The version of the call operator that takes a by-value receiver.
+///
+/// Instances of `FnOnce` can be called, but might not be callable multiple
+/// times. Because of this, if the only thing known about a type is that it
+/// implements `FnOnce`, it can only be called once.
+///
+/// `FnOnce` is implemented automatically by closures that might consume captured
+/// variables, as well as all types that implement [`FnMut`], e.g., (safe)
+/// [function pointers] (since `FnOnce` is a supertrait of [`FnMut`]).
+///
+/// Since both [`Fn`] and [`FnMut`] are subtraits of `FnOnce`, any instance of
+/// [`Fn`] or [`FnMut`] can be used where a `FnOnce` is expected.
+///
+/// Use `FnOnce` as a bound when you want to accept a parameter of function-like
+/// type and only need to call it once. If you need to call the parameter
+/// repeatedly, use [`FnMut`] as a bound; if you also need it to not mutate
+/// state, use [`Fn`].
+///
+/// See the [chapter on closures in *The Rust Programming Language*][book] for
+/// some more information on this topic.
+///
+/// Also of note is the special syntax for `Fn` traits (e.g.
+/// `Fn(usize, bool) -> usize`). Those interested in the technical details of
+/// this can refer to [the relevant section in the *Rustonomicon*][nomicon].
+///
+/// [book]: ../../book/ch13-01-closures.html
+/// [function pointers]: fn
+/// [nomicon]: ../../nomicon/hrtb.html
+///
+/// # Examples
+///
+/// ## Using a `FnOnce` parameter
+///
+/// ```
+/// fn consume_with_relish<F>(func: F)
+///     where F: FnOnce() -> String
+/// {
+///     // `func` consumes its captured variables, so it cannot be run more
+///     // than once.
+///     println!("Consumed: {}", func());
+///
+///     println!("Delicious!");
+///
+///     // Attempting to invoke `func()` again will throw a `use of moved
+///     // value` error for `func`.
+/// }
+///
+/// let x = String::from("x");
+/// let consume_and_return_x = move || x;
+/// consume_with_relish(consume_and_return_x);
+///
+/// // `consume_and_return_x` can no longer be invoked at this point
+/// ```
+#[cfg(not(bootstrap))]
+#[lang = "fn_once"]
+#[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_diagnostic_item = "FnOnce"]
+#[rustc_paren_sugar]
+#[rustc_on_unimplemented(
+    on(
+        Args = "()",
+        note = "wrap the `{Self}` in a closure with no arguments: `|| {{ /* code */ }}`"
+    ),
+    on(
+        _Self = "unsafe fn",
+        note = "unsafe function cannot be called generically without an unsafe block",
+        // SAFETY: tidy is not smart enough to tell that the below unsafe block is a string
+        label = "call the function in a closure: `|| unsafe {{ /* code */ }}`"
+    ),
+    message = "expected a `{FnOnce}<{Args}>` closure, found `{Self}`",
+    label = "expected an `FnOnce<{Args}>` closure, found `{Self}`"
+)]
+#[fundamental] // so that regex can rely that `&str: !FnMut`
+#[must_use = "closures are lazy and do nothing unless called"]
+#[const_trait]
+pub trait FnOnce<Args: Tuple> {
+    /// The returned type after the call operator is used.
+    #[lang = "fn_once_output"]
+    #[stable(feature = "fn_once_output", since = "1.12.0")]
+    type Output;
+
+    /// Performs the call operation.
+    #[unstable(feature = "fn_traits", issue = "29625")]
+    extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
+}
+
+#[cfg(bootstrap)]
 mod impls {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_const_unstable(feature = "const_fn_trait_ref_impls", issue = "101803")]
@@ -310,3 +570,66 @@ mod impls {
         }
     }
 }
+
+#[cfg(not(bootstrap))]
+mod impls {
+    use crate::marker::Tuple;
+
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[rustc_const_unstable(feature = "const_fn_trait_ref_impls", issue = "101803")]
+    impl<A: Tuple, F: ?Sized> const Fn<A> for &F
+    where
+        F: ~const Fn<A>,
+    {
+        extern "rust-call" fn call(&self, args: A) -> F::Output {
+            (**self).call(args)
+        }
+    }
+
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[rustc_const_unstable(feature = "const_fn_trait_ref_impls", issue = "101803")]
+    impl<A: Tuple, F: ?Sized> const FnMut<A> for &F
+    where
+        F: ~const Fn<A>,
+    {
+        extern "rust-call" fn call_mut(&mut self, args: A) -> F::Output {
+            (**self).call(args)
+        }
+    }
+
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[rustc_const_unstable(feature = "const_fn_trait_ref_impls", issue = "101803")]
+    impl<A: Tuple, F: ?Sized> const FnOnce<A> for &F
+    where
+        F: ~const Fn<A>,
+    {
+        type Output = F::Output;
+
+        extern "rust-call" fn call_once(self, args: A) -> F::Output {
+            (*self).call(args)
+        }
+    }
+
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[rustc_const_unstable(feature = "const_fn_trait_ref_impls", issue = "101803")]
+    impl<A: Tuple, F: ?Sized> const FnMut<A> for &mut F
+    where
+        F: ~const FnMut<A>,
+    {
+        extern "rust-call" fn call_mut(&mut self, args: A) -> F::Output {
+            (*self).call_mut(args)
+        }
+    }
+
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[rustc_const_unstable(feature = "const_fn_trait_ref_impls", issue = "101803")]
+    impl<A: Tuple, F: ?Sized> const FnOnce<A> for &mut F
+    where
+        F: ~const FnMut<A>,
+    {
+        type Output = F::Output;
+        extern "rust-call" fn call_once(self, args: A) -> F::Output {
+            (*self).call_mut(args)
+        }
+    }
+}
diff --git a/library/core/src/pin.rs b/library/core/src/pin.rs
index ccef35b4532..f0258640e2a 100644
--- a/library/core/src/pin.rs
+++ b/library/core/src/pin.rs
@@ -1059,7 +1059,7 @@ impl<P, U> DispatchFromDyn<Pin<U>> for Pin<P> where P: DispatchFromDyn<U> {}
 /// 8  | let x: Pin<&mut Foo> = {
 ///    |     - borrow later stored here
 /// 9  |     let x: Pin<&mut Foo> = pin!(Foo { /* … */ });
-///    |                            ^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
+///    |                            ^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
 /// 10 |     x
 /// 11 | }; // <- Foo is dropped
 ///    | - temporary value is freed at the end of this statement
diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs
index 5a083227bb0..926d2ae5113 100644
--- a/library/core/src/ptr/const_ptr.rs
+++ b/library/core/src/ptr/const_ptr.rs
@@ -568,6 +568,31 @@ impl<T: ?Sized> *const T {
     ///
     /// For non-`Sized` pointees this operation changes only the data pointer,
     /// leaving the metadata untouched.
+    ///
+    /// ## Examples
+    ///
+    /// ```
+    /// #![feature(ptr_mask, strict_provenance)]
+    /// let v = 17_u32;
+    /// let ptr: *const u32 = &v;
+    ///
+    /// // `u32` is 4 bytes aligned,
+    /// // which means that lower 2 bits are always 0.
+    /// let tag_mask = 0b11;
+    /// let ptr_mask = !tag_mask;
+    ///
+    /// // We can store something in these lower bits
+    /// let tagged_ptr = ptr.map_addr(|a| a | 0b10);
+    ///
+    /// // Get the "tag" back
+    /// let tag = tagged_ptr.addr() & tag_mask;
+    /// assert_eq!(tag, 0b10);
+    ///
+    /// // Note that `tagged_ptr` is unaligned, it's UB to read from it.
+    /// // To get original pointer `mask` can be used:
+    /// let masked_ptr = tagged_ptr.mask(ptr_mask);
+    /// assert_eq!(unsafe { *masked_ptr }, 17);
+    /// ```
     #[unstable(feature = "ptr_mask", issue = "98290")]
     #[must_use = "returns a new pointer rather than modifying its argument"]
     #[inline(always)]
diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs
index 6764002bcd4..f71696e9ca0 100644
--- a/library/core/src/ptr/mut_ptr.rs
+++ b/library/core/src/ptr/mut_ptr.rs
@@ -588,6 +588,34 @@ impl<T: ?Sized> *mut T {
     ///
     /// For non-`Sized` pointees this operation changes only the data pointer,
     /// leaving the metadata untouched.
+    ///
+    /// ## Examples
+    ///
+    /// ```
+    /// #![feature(ptr_mask, strict_provenance)]
+    /// let mut v = 17_u32;
+    /// let ptr: *mut u32 = &mut v;
+    ///
+    /// // `u32` is 4 bytes aligned,
+    /// // which means that lower 2 bits are always 0.
+    /// let tag_mask = 0b11;
+    /// let ptr_mask = !tag_mask;
+    ///
+    /// // We can store something in these lower bits
+    /// let tagged_ptr = ptr.map_addr(|a| a | 0b10);
+    ///
+    /// // Get the "tag" back
+    /// let tag = tagged_ptr.addr() & tag_mask;
+    /// assert_eq!(tag, 0b10);
+    ///
+    /// // Note that `tagged_ptr` is unaligned, it's UB to read from/write to it.
+    /// // To get original pointer `mask` can be used:
+    /// let masked_ptr = tagged_ptr.mask(ptr_mask);
+    /// assert_eq!(unsafe { *masked_ptr }, 17);
+    ///
+    /// unsafe { *masked_ptr = 0 };
+    /// assert_eq!(v, 0);
+    /// ```
     #[unstable(feature = "ptr_mask", issue = "98290")]
     #[must_use = "returns a new pointer rather than modifying its argument"]
     #[inline(always)]
diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs
index 4f1bb17344b..0f58bc643d9 100644
--- a/library/core/src/slice/mod.rs
+++ b/library/core/src/slice/mod.rs
@@ -3524,8 +3524,8 @@ impl<T> [T] {
         }
     }
 
-    /// Transmute the slice to a slice of another type, ensuring alignment of the types is
-    /// maintained.
+    /// Transmute the mutable slice to a mutable slice of another type, ensuring alignment of the
+    /// types is maintained.
     ///
     /// This method splits the slice into three distinct slices: prefix, correctly aligned middle
     /// slice of a new type, and the suffix slice. The method may make the middle slice the greatest
@@ -3667,7 +3667,8 @@ impl<T> [T] {
         unsafe { self.align_to() }
     }
 
-    /// Split a slice into a prefix, a middle of aligned SIMD types, and a suffix.
+    /// Split a mutable slice into a mutable prefix, a middle of aligned SIMD types,
+    /// and a mutable suffix.
     ///
     /// This is a safe wrapper around [`slice::align_to_mut`], so has the same weak
     /// postconditions as that method.  You're only assured that
diff --git a/library/core/src/tuple.rs b/library/core/src/tuple.rs
index fc91fe468cc..28275798f75 100644
--- a/library/core/src/tuple.rs
+++ b/library/core/src/tuple.rs
@@ -22,7 +22,8 @@ macro_rules! tuple_impls {
         maybe_tuple_doc! {
             $($T)+ @
             #[stable(feature = "rust1", since = "1.0.0")]
-            impl<$($T:PartialEq),+> PartialEq for ($($T,)+)
+            #[rustc_const_unstable(feature = "const_cmp", issue = "92391")]
+            impl<$($T: ~const PartialEq),+> const PartialEq for ($($T,)+)
             where
                 last_type!($($T,)+): ?Sized
             {
@@ -40,7 +41,7 @@ macro_rules! tuple_impls {
         maybe_tuple_doc! {
             $($T)+ @
             #[stable(feature = "rust1", since = "1.0.0")]
-            impl<$($T:Eq),+> Eq for ($($T,)+)
+            impl<$($T: Eq),+> Eq for ($($T,)+)
             where
                 last_type!($($T,)+): ?Sized
             {}
@@ -49,7 +50,8 @@ macro_rules! tuple_impls {
         maybe_tuple_doc! {
             $($T)+ @
             #[stable(feature = "rust1", since = "1.0.0")]
-            impl<$($T:PartialOrd + PartialEq),+> PartialOrd for ($($T,)+)
+            #[rustc_const_unstable(feature = "const_cmp", issue = "92391")]
+            impl<$($T: ~const PartialOrd + ~const PartialEq),+> const PartialOrd for ($($T,)+)
             where
                 last_type!($($T,)+): ?Sized
             {
@@ -79,7 +81,8 @@ macro_rules! tuple_impls {
         maybe_tuple_doc! {
             $($T)+ @
             #[stable(feature = "rust1", since = "1.0.0")]
-            impl<$($T:Ord),+> Ord for ($($T,)+)
+            #[rustc_const_unstable(feature = "const_cmp", issue = "92391")]
+            impl<$($T: ~const Ord),+> const Ord for ($($T,)+)
             where
                 last_type!($($T,)+): ?Sized
             {
diff --git a/library/core/tests/iter/adapters/array_chunks.rs b/library/core/tests/iter/adapters/array_chunks.rs
index 4e9d89e1e58..ef4a7e53bdd 100644
--- a/library/core/tests/iter/adapters/array_chunks.rs
+++ b/library/core/tests/iter/adapters/array_chunks.rs
@@ -139,7 +139,8 @@ fn test_iterator_array_chunks_fold() {
     let result =
         (0..10).map(|_| CountDrop::new(&count)).array_chunks::<3>().fold(0, |acc, _item| acc + 1);
     assert_eq!(result, 3);
-    assert_eq!(count.get(), 10);
+    // fold impls may or may not process the remainder
+    assert!(count.get() <= 10 && count.get() >= 9);
 }
 
 #[test]
diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs
index eda176d9fcb..a7db2a02bd7 100644
--- a/library/core/tests/lib.rs
+++ b/library/core/tests/lib.rs
@@ -64,7 +64,6 @@
 #![feature(try_trait_v2)]
 #![feature(slice_internals)]
 #![feature(slice_partition_dedup)]
-#![feature(int_log)]
 #![feature(iter_advance_by)]
 #![feature(iter_array_chunks)]
 #![feature(iter_collect_into)]
diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml
index bc10b12ec2a..daa6976c301 100644
--- a/library/std/Cargo.toml
+++ b/library/std/Cargo.toml
@@ -23,11 +23,11 @@ hashbrown = { version = "0.12", default-features = false, features = ['rustc-dep
 std_detect = { path = "../stdarch/crates/std_detect", default-features = false, features = ['rustc-dep-of-std'] }
 
 # Dependencies of the `backtrace` crate
-addr2line = { version = "0.16.0", optional = true, default-features = false }
+addr2line = { version = "0.17.0", optional = true, default-features = false }
 rustc-demangle = { version = "0.1.21", features = ['rustc-dep-of-std'] }
-miniz_oxide = { version = "0.4.0", optional = true, default-features = false }
+miniz_oxide = { version = "0.5.0", optional = true, default-features = false }
 [dependencies.object]
-version = "0.26.1"
+version = "0.29.0"
 optional = true
 default-features = false
 features = ['read_core', 'elf', 'macho', 'pe', 'unaligned', 'archive']
diff --git a/library/std/src/f32.rs b/library/std/src/f32.rs
index dafcd876744..4127c4056f2 100644
--- a/library/std/src/f32.rs
+++ b/library/std/src/f32.rs
@@ -77,9 +77,11 @@ impl f32 {
     /// ```
     /// let f = 3.3_f32;
     /// let g = -3.3_f32;
+    /// let h = -3.7_f32;
     ///
     /// assert_eq!(f.round(), 3.0);
     /// assert_eq!(g.round(), -3.0);
+    /// assert_eq!(h.round(), -4.0);
     /// ```
     #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
diff --git a/library/std/src/f64.rs b/library/std/src/f64.rs
index 77048f9a28f..cc64258da60 100644
--- a/library/std/src/f64.rs
+++ b/library/std/src/f64.rs
@@ -77,9 +77,11 @@ impl f64 {
     /// ```
     /// let f = 3.3_f64;
     /// let g = -3.3_f64;
+    /// let h = -3.7_f64;
     ///
     /// assert_eq!(f.round(), 3.0);
     /// assert_eq!(g.round(), -3.0);
+    /// assert_eq!(h.round(), -4.0);
     /// ```
     #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
diff --git a/library/std/src/sync/mpsc/mpsc_queue.rs b/library/std/src/sync/mpsc/mpsc_queue.rs
index cdd64a5def5..7322512e3b4 100644
--- a/library/std/src/sync/mpsc/mpsc_queue.rs
+++ b/library/std/src/sync/mpsc/mpsc_queue.rs
@@ -8,8 +8,15 @@
 //! method, and see the method for more information about it. Due to this
 //! caveat, this queue might not be appropriate for all use-cases.
 
-// https://www.1024cores.net/home/lock-free-algorithms
-//                          /queues/non-intrusive-mpsc-node-based-queue
+// The original implementation is based off:
+// https://www.1024cores.net/home/lock-free-algorithms/queues/non-intrusive-mpsc-node-based-queue
+//
+// Note that back when the code was imported, it was licensed under the BSD-2-Clause license:
+// http://web.archive.org/web/20110411011612/https://www.1024cores.net/home/lock-free-algorithms/queues/unbounded-spsc-queue
+//
+// The original author of the code agreed to relicense it under `MIT OR Apache-2.0` in 2017, so as
+// of today the license of this file is the same as the rest of the codebase:
+// https://github.com/rust-lang/rust/pull/42149
 
 #[cfg(all(test, not(target_os = "emscripten")))]
 mod tests;
diff --git a/library/std/src/sync/mpsc/spsc_queue.rs b/library/std/src/sync/mpsc/spsc_queue.rs
index 7e745eb31de..61f91313ea9 100644
--- a/library/std/src/sync/mpsc/spsc_queue.rs
+++ b/library/std/src/sync/mpsc/spsc_queue.rs
@@ -4,7 +4,15 @@
 //! concurrently between two threads. This data structure is safe to use and
 //! enforces the semantics that there is one pusher and one popper.
 
+// The original implementation is based off:
 // https://www.1024cores.net/home/lock-free-algorithms/queues/unbounded-spsc-queue
+//
+// Note that back when the code was imported, it was licensed under the BSD-2-Clause license:
+// http://web.archive.org/web/20110411011612/https://www.1024cores.net/home/lock-free-algorithms/queues/unbounded-spsc-queue
+//
+// The original author of the code agreed to relicense it under `MIT OR Apache-2.0` in 2017, so as
+// of today the license of this file is the same as the rest of the codebase:
+// https://github.com/rust-lang/rust/pull/42149
 
 #[cfg(all(test, not(target_os = "emscripten")))]
 mod tests;
diff --git a/library/unwind/src/lib.rs b/library/unwind/src/lib.rs
index 46fe50cb945..32c0ef3e116 100644
--- a/library/unwind/src/lib.rs
+++ b/library/unwind/src/lib.rs
@@ -15,7 +15,6 @@ cfg_if::cfg_if! {
         target_os = "espidf",
     ))] {
         // These "unix" family members do not have unwinder.
-        // Note this also matches x86_64-unknown-none-linuxkernel.
     } else if #[cfg(any(
         unix,
         windows,
diff --git a/src/bootstrap/Cargo.lock b/src/bootstrap/Cargo.lock
index baecca44cd9..e1a108cea95 100644
--- a/src/bootstrap/Cargo.lock
+++ b/src/bootstrap/Cargo.lock
@@ -224,13 +224,13 @@ dependencies = [
 
 [[package]]
 name = "fd-lock"
-version = "3.0.6"
+version = "3.0.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e11dcc7e4d79a8c89b9ab4c6f5c30b1fc4a83c420792da3542fd31179ed5f517"
+checksum = "0c93a581058d957dc4176875aad04f82f81613e6611d64aa1a9c755bdfb16711"
 dependencies = [
  "cfg-if",
  "rustix",
- "windows-sys",
+ "windows-sys 0.42.0",
 ]
 
 [[package]]
@@ -528,7 +528,7 @@ dependencies = [
  "io-lifetimes",
  "libc",
  "linux-raw-sys",
- "windows-sys",
+ "windows-sys 0.36.1",
 ]
 
 [[package]]
@@ -721,44 +721,101 @@ version = "0.36.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2"
 dependencies = [
- "windows_aarch64_msvc",
- "windows_i686_gnu",
- "windows_i686_msvc",
- "windows_x86_64_gnu",
- "windows_x86_64_msvc",
+ "windows_aarch64_msvc 0.36.1",
+ "windows_i686_gnu 0.36.1",
+ "windows_i686_msvc 0.36.1",
+ "windows_x86_64_gnu 0.36.1",
+ "windows_x86_64_msvc 0.36.1",
 ]
 
 [[package]]
+name = "windows-sys"
+version = "0.42.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7"
+dependencies = [
+ "windows_aarch64_gnullvm",
+ "windows_aarch64_msvc 0.42.0",
+ "windows_i686_gnu 0.42.0",
+ "windows_i686_msvc 0.42.0",
+ "windows_x86_64_gnu 0.42.0",
+ "windows_x86_64_gnullvm",
+ "windows_x86_64_msvc 0.42.0",
+]
+
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.42.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e"
+
+[[package]]
 name = "windows_aarch64_msvc"
 version = "0.36.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47"
 
 [[package]]
+name = "windows_aarch64_msvc"
+version = "0.42.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4"
+
+[[package]]
 name = "windows_i686_gnu"
 version = "0.36.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6"
 
 [[package]]
+name = "windows_i686_gnu"
+version = "0.42.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7"
+
+[[package]]
 name = "windows_i686_msvc"
 version = "0.36.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024"
 
 [[package]]
+name = "windows_i686_msvc"
+version = "0.42.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246"
+
+[[package]]
 name = "windows_x86_64_gnu"
 version = "0.36.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1"
 
 [[package]]
+name = "windows_x86_64_gnu"
+version = "0.42.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.42.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028"
+
+[[package]]
 name = "windows_x86_64_msvc"
 version = "0.36.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680"
 
 [[package]]
+name = "windows_x86_64_msvc"
+version = "0.42.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5"
+
+[[package]]
 name = "xattr"
 version = "0.2.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml
index 95e71173773..f74738437ea 100644
--- a/src/bootstrap/Cargo.toml
+++ b/src/bootstrap/Cargo.toml
@@ -36,7 +36,7 @@ test = false
 
 [dependencies]
 cmake = "0.1.38"
-fd-lock = "3.0.6"
+fd-lock = "3.0.7"
 filetime = "0.2"
 getopts = "0.2.19"
 cc = "1.0.69"
diff --git a/src/bootstrap/bin/main.rs b/src/bootstrap/bin/main.rs
index 9b4861ccd95..be69f819c64 100644
--- a/src/bootstrap/bin/main.rs
+++ b/src/bootstrap/bin/main.rs
@@ -35,7 +35,7 @@ fn main() {
 
     // NOTE: Since `./configure` generates a `config.toml`, distro maintainers will see the
     // changelog warning, not the `x.py setup` message.
-    let suggest_setup = !config.config.exists() && !matches!(config.cmd, Subcommand::Setup { .. });
+    let suggest_setup = config.config.is_none() && !matches!(config.cmd, Subcommand::Setup { .. });
     if suggest_setup {
         println!("warning: you have not made a `config.toml`");
         println!(
diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs
index e467ce47f4c..6fd36393507 100644
--- a/src/bootstrap/builder.rs
+++ b/src/bootstrap/builder.rs
@@ -2208,6 +2208,24 @@ impl<'a> Builder<'a> {
 
         false
     }
+
+    pub(crate) fn maybe_open_in_browser<S: Step>(&self, path: impl AsRef<Path>) {
+        if self.was_invoked_explicitly::<S>(Kind::Doc) {
+            self.open_in_browser(path);
+        }
+    }
+
+    pub(crate) fn open_in_browser(&self, path: impl AsRef<Path>) {
+        if self.config.dry_run || !self.config.cmd.open() {
+            return;
+        }
+
+        let path = path.as_ref();
+        self.info(&format!("Opening doc {}", path.display()));
+        if let Err(err) = opener::open(path) {
+            self.info(&format!("{}\n", err));
+        }
+    }
 }
 
 #[cfg(test)]
diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs
index 21dc11c4808..ba50ce9ec24 100644
--- a/src/bootstrap/config.rs
+++ b/src/bootstrap/config.rs
@@ -80,7 +80,7 @@ pub struct Config {
     pub keep_stage_std: Vec<u32>,
     pub src: PathBuf,
     /// defaults to `config.toml`
-    pub config: PathBuf,
+    pub config: Option<PathBuf>,
     pub jobs: Option<u32>,
     pub cmd: Subcommand,
     pub incremental: bool,
@@ -926,8 +926,10 @@ impl Config {
         // Give a hard error if `--config` or `RUST_BOOTSTRAP_CONFIG` are set to a missing path,
         // but not if `config.toml` hasn't been created.
         let mut toml = if !using_default_path || toml_path.exists() {
+            config.config = Some(toml_path.clone());
             get_toml(&toml_path)
         } else {
+            config.config = None;
             TomlConfig::default()
         };
 
@@ -942,7 +944,6 @@ impl Config {
         }
 
         config.changelog_seen = toml.changelog_seen;
-        config.config = toml_path;
 
         let build = toml.build.unwrap_or_default();
 
diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs
index 805633c926c..110a3ee4918 100644
--- a/src/bootstrap/dist.rs
+++ b/src/bootstrap/dist.rs
@@ -19,6 +19,7 @@ use crate::cache::{Interned, INTERNER};
 use crate::channel;
 use crate::compile;
 use crate::config::TargetSelection;
+use crate::doc::DocumentationFormat;
 use crate::tarball::{GeneratedTarball, OverlayKind, Tarball};
 use crate::tool::{self, Tool};
 use crate::util::{exe, is_dylib, output, t, timeit};
@@ -97,7 +98,11 @@ impl Step for JsonDocs {
     /// Builds the `rust-docs-json` installer component.
     fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
         let host = self.host;
-        builder.ensure(crate::doc::JsonStd { stage: builder.top_stage, target: host });
+        builder.ensure(crate::doc::Std {
+            stage: builder.top_stage,
+            target: host,
+            format: DocumentationFormat::JSON,
+        });
 
         let dest = "share/doc/rust/json";
 
diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs
index 5d265b9ad0c..280e232ca2d 100644
--- a/src/bootstrap/doc.rs
+++ b/src/bootstrap/doc.rs
@@ -85,18 +85,6 @@ book!(
     StyleGuide, "src/doc/style-guide", "style-guide";
 );
 
-fn open(builder: &Builder<'_>, path: impl AsRef<Path>) {
-    if builder.config.dry_run || !builder.config.cmd.open() {
-        return;
-    }
-
-    let path = path.as_ref();
-    builder.info(&format!("Opening doc {}", path.display()));
-    if let Err(err) = opener::open(path) {
-        builder.info(&format!("{}\n", err));
-    }
-}
-
 // "library/std" -> ["library", "std"]
 //
 // Used for deciding whether a particular step is one requested by the user on
@@ -240,11 +228,9 @@ impl Step for TheBook {
             invoke_rustdoc(builder, compiler, &shared_assets, target, path);
         }
 
-        if builder.was_invoked_explicitly::<Self>(Kind::Doc) {
-            let out = builder.doc_out(target);
-            let index = out.join("book").join("index.html");
-            open(builder, &index);
-        }
+        let out = builder.doc_out(target);
+        let index = out.join("book").join("index.html");
+        builder.maybe_open_in_browser::<Self>(index);
     }
 }
 
@@ -386,7 +372,7 @@ impl Step for Standalone {
         // with no particular explicit doc requested (e.g. library/core).
         if builder.paths.is_empty() || builder.was_invoked_explicitly::<Self>(Kind::Doc) {
             let index = out.join("index.html");
-            open(builder, &index);
+            builder.open_in_browser(&index);
         }
     }
 }
@@ -434,6 +420,7 @@ impl Step for SharedAssets {
 pub struct Std {
     pub stage: u32,
     pub target: TargetSelection,
+    pub format: DocumentationFormat,
 }
 
 impl Step for Std {
@@ -446,7 +433,15 @@ impl Step for Std {
     }
 
     fn make_run(run: RunConfig<'_>) {
-        run.builder.ensure(Std { stage: run.builder.top_stage, target: run.target });
+        run.builder.ensure(Std {
+            stage: run.builder.top_stage,
+            target: run.target,
+            format: if run.builder.config.cmd.json() {
+                DocumentationFormat::JSON
+            } else {
+                DocumentationFormat::HTML
+            },
+        });
     }
 
     /// Compile all standard library documentation.
@@ -456,19 +451,26 @@ impl Step for Std {
     fn run(self, builder: &Builder<'_>) {
         let stage = self.stage;
         let target = self.target;
-        let out = builder.doc_out(target);
+        let out = match self.format {
+            DocumentationFormat::HTML => builder.doc_out(target),
+            DocumentationFormat::JSON => builder.json_doc_out(target),
+        };
+
         t!(fs::create_dir_all(&out));
 
         builder.ensure(SharedAssets { target: self.target });
 
         let index_page = builder.src.join("src/doc/index.md").into_os_string();
-        let mut extra_args = vec![
-            OsStr::new("--markdown-css"),
-            OsStr::new("rust.css"),
-            OsStr::new("--markdown-no-toc"),
-            OsStr::new("--index-page"),
-            &index_page,
-        ];
+        let mut extra_args = match self.format {
+            DocumentationFormat::HTML => vec![
+                OsStr::new("--markdown-css"),
+                OsStr::new("rust.css"),
+                OsStr::new("--markdown-no-toc"),
+                OsStr::new("--index-page"),
+                &index_page,
+            ],
+            DocumentationFormat::JSON => vec![OsStr::new("--output-format"), OsStr::new("json")],
+        };
 
         if !builder.config.docs_minification {
             extra_args.push(OsStr::new("--disable-minification"));
@@ -492,59 +494,24 @@ impl Step for Std {
             })
             .collect::<Vec<_>>();
 
-        doc_std(
-            builder,
-            DocumentationFormat::HTML,
-            stage,
-            target,
-            &out,
-            &extra_args,
-            &requested_crates,
-        );
+        doc_std(builder, self.format, stage, target, &out, &extra_args, &requested_crates);
+
+        // Don't open if the format is json
+        if let DocumentationFormat::JSON = self.format {
+            return;
+        }
 
         // Look for library/std, library/core etc in the `x.py doc` arguments and
         // open the corresponding rendered docs.
         for requested_crate in requested_crates {
             if STD_PUBLIC_CRATES.iter().any(|k| *k == requested_crate.as_str()) {
                 let index = out.join(requested_crate).join("index.html");
-                open(builder, &index);
+                builder.open_in_browser(index);
             }
         }
     }
 }
 
-#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
-pub struct JsonStd {
-    pub stage: u32,
-    pub target: TargetSelection,
-}
-
-impl Step for JsonStd {
-    type Output = ();
-    const DEFAULT: bool = false;
-
-    fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
-        let default = run.builder.config.docs && run.builder.config.cmd.json();
-        run.all_krates("test").path("library").default_condition(default)
-    }
-
-    fn make_run(run: RunConfig<'_>) {
-        run.builder.ensure(Std { stage: run.builder.top_stage, target: run.target });
-    }
-
-    /// Build JSON documentation for the standard library crates.
-    ///
-    /// This is largely just a wrapper around `cargo doc`.
-    fn run(self, builder: &Builder<'_>) {
-        let stage = self.stage;
-        let target = self.target;
-        let out = builder.json_doc_out(target);
-        t!(fs::create_dir_all(&out));
-        let extra_args = [OsStr::new("--output-format"), OsStr::new("json")];
-        doc_std(builder, DocumentationFormat::JSON, stage, target, &out, &extra_args, &[])
-    }
-}
-
 /// Name of the crates that are visible to consumers of the standard library.
 /// Documentation for internal crates is handled by the rustc step, so internal crates will show
 /// up there.
@@ -557,7 +524,7 @@ impl Step for JsonStd {
 const STD_PUBLIC_CRATES: [&str; 5] = ["core", "alloc", "std", "proc_macro", "test"];
 
 #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
-enum DocumentationFormat {
+pub enum DocumentationFormat {
     HTML,
     JSON,
 }
@@ -759,7 +726,7 @@ impl Step for Rustc {
         // Let's open the first crate documentation page:
         if let Some(krate) = to_open {
             let index = out.join(krate).join("index.html");
-            open(builder, &index);
+            builder.open_in_browser(index);
         }
     }
 }
@@ -1019,10 +986,9 @@ impl Step for RustcBook {
             name: INTERNER.intern_str("rustc"),
             src: INTERNER.intern_path(out_base),
         });
-        if builder.was_invoked_explicitly::<Self>(Kind::Doc) {
-            let out = builder.doc_out(self.target);
-            let index = out.join("rustc").join("index.html");
-            open(builder, &index);
-        }
+
+        let out = builder.doc_out(self.target);
+        let index = out.join("rustc").join("index.html");
+        builder.maybe_open_in_browser::<Self>(index);
     }
 }
diff --git a/src/bootstrap/sanity.rs b/src/bootstrap/sanity.rs
index e905517253c..bdfd5fe5c42 100644
--- a/src/bootstrap/sanity.rs
+++ b/src/bootstrap/sanity.rs
@@ -155,6 +155,14 @@ than building it.
             continue;
         }
 
+        // Some environments don't want or need these tools, such as when testing Miri.
+        // FIXME: it would be better to refactor this code to split necessary setup from pure sanity
+        // checks, and have a regular flag for skipping the latter. Also see
+        // <https://github.com/rust-lang/rust/pull/103569#discussion_r1008741742>.
+        if env::var_os("BOOTSTRAP_SKIP_TARGET_SANITY").is_some() {
+            continue;
+        }
+
         if !build.config.dry_run {
             cmd_finder.must_have(build.cc(*target));
             if let Some(ar) = build.ar(*target) {
@@ -212,6 +220,14 @@ than building it.
             }
         }
 
+        // Some environments don't want or need these tools, such as when testing Miri.
+        // FIXME: it would be better to refactor this code to split necessary setup from pure sanity
+        // checks, and have a regular flag for skipping the latter. Also see
+        // <https://github.com/rust-lang/rust/pull/103569#discussion_r1008741742>.
+        if env::var_os("BOOTSTRAP_SKIP_TARGET_SANITY").is_some() {
+            continue;
+        }
+
         if need_cmake && target.contains("msvc") {
             // There are three builds of cmake on windows: MSVC, MinGW, and
             // Cygwin. The Cygwin build does not have generators for Visual
diff --git a/src/bootstrap/setup.rs b/src/bootstrap/setup.rs
index eb7da1bda73..04480277fe0 100644
--- a/src/bootstrap/setup.rs
+++ b/src/bootstrap/setup.rs
@@ -82,7 +82,7 @@ impl fmt::Display for Profile {
 }
 
 pub fn setup(config: &Config, profile: Profile) {
-    let path = &config.config;
+    let path = &config.config.clone().unwrap_or(PathBuf::from("config.toml"));
 
     if path.exists() {
         eprintln!(
diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs
index 08799602a79..46ad0470812 100644
--- a/src/bootstrap/test.rs
+++ b/src/bootstrap/test.rs
@@ -16,6 +16,7 @@ use crate::cache::Interned;
 use crate::compile;
 use crate::config::TargetSelection;
 use crate::dist;
+use crate::doc::DocumentationFormat;
 use crate::flags::Subcommand;
 use crate::native;
 use crate::tool::{self, SourceType, Tool};
@@ -826,7 +827,11 @@ impl Step for RustdocJSStd {
                     command.arg("--test-file").arg(path);
                 }
             }
-            builder.ensure(crate::doc::Std { target: self.target, stage: builder.top_stage });
+            builder.ensure(crate::doc::Std {
+                target: self.target,
+                stage: builder.top_stage,
+                format: DocumentationFormat::HTML,
+            });
             builder.run(&mut command);
         } else {
             builder.info("No nodejs found, skipping \"src/test/rustdoc-js-std\" tests");
diff --git a/src/ci/docker/host-x86_64/dist-various-2/Dockerfile b/src/ci/docker/host-x86_64/dist-various-2/Dockerfile
index 126c292b38e..e1adabaac9b 100644
--- a/src/ci/docker/host-x86_64/dist-various-2/Dockerfile
+++ b/src/ci/docker/host-x86_64/dist-various-2/Dockerfile
@@ -118,6 +118,9 @@ ENV TARGETS=$TARGETS,armv7-unknown-linux-gnueabi
 ENV TARGETS=$TARGETS,armv7-unknown-linux-musleabi
 ENV TARGETS=$TARGETS,i686-unknown-freebsd
 ENV TARGETS=$TARGETS,x86_64-unknown-none
+ENV TARGETS=$TARGETS,aarch64-unknown-uefi
+ENV TARGETS=$TARGETS,i686-unknown-uefi
+ENV TARGETS=$TARGETS,x86_64-unknown-uefi
 
 # As per https://bugs.launchpad.net/ubuntu/+source/gcc-defaults/+bug/1300211
 # we need asm in the search path for gcc-8 (for gnux32) but not in the search path of the
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh b/src/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh
index d8738455610..7dde6370904 100755
--- a/src/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh
+++ b/src/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh
@@ -27,10 +27,7 @@ python3 "$X_PY" test --stage 2 src/tools/rustfmt
 python3 "$X_PY" test --stage 2 src/tools/miri
 # We natively run this script on x86_64-unknown-linux-gnu and x86_64-pc-windows-msvc.
 # Also cover some other targets (on both of these hosts) via cross-testing.
-#
-# Currently disabled -- we end up pulling in a cross-compile of LLVM (maybe
-# just overly eager sanity checks), but in any case this won't work when
-# building LLVM as of this comment.
-#python3 "$X_PY" test --stage 2 src/tools/miri --target i686-pc-windows-msvc
-#FIXME(https://github.com/rust-lang/rust/issues/103519): macOS testing is currently disabled
-# python3 "$X_PY" test --stage 2 src/tools/miri --target aarch64-apple-darwin
+export BOOTSTRAP_SKIP_TARGET_SANITY=1 # we don't need `cc` for these targets
+python3 "$X_PY" test --stage 2 src/tools/miri --target i686-pc-windows-msvc
+python3 "$X_PY" test --stage 2 src/tools/miri --target aarch64-apple-darwin
+unset BOOTSTRAP_SKIP_TARGET_SANITY
diff --git a/src/doc/book b/src/doc/book
-Subproject aa5ee485bd6bd80d205da7c82fcdd776f92fdd5
+Subproject 3f64052c048c6def93b94a2b514ee88bba91874
diff --git a/src/doc/nomicon b/src/doc/nomicon
-Subproject 9c73283775466d22208a0b28afcab44db4c0cc1
+Subproject 05532356e7a4dbea2330aabb77611f5179493bb
diff --git a/src/doc/reference b/src/doc/reference
-Subproject 4ea7c5def38ac81df33a9e48e5637a82a5ac404
+Subproject 9f0cc13ffcd27c1fbe1ab766a9491e15ddcf4d1
diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example
-Subproject 03491f33375c5a2a1661c7fa4be671fe95ce124
+Subproject 2b15c0abf2bada6e00553814336bc3e2d839909
diff --git a/src/doc/rustc-dev-guide b/src/doc/rustc-dev-guide
-Subproject 51a37ad19a15709d0601afbac6581f5aea6a45d
+Subproject d0dc6c97a6486f68bac782fff135086eae6d77e
diff --git a/src/doc/rustc/src/linker-plugin-lto.md b/src/doc/rustc/src/linker-plugin-lto.md
index b1854b22a7c..9272b9ac9b2 100644
--- a/src/doc/rustc/src/linker-plugin-lto.md
+++ b/src/doc/rustc/src/linker-plugin-lto.md
@@ -131,24 +131,47 @@ able to get around this problem by setting `-Clinker=lld-link` in RUSTFLAGS
 
 ## Toolchain Compatibility
 
-<!-- NOTE: to update the below table, you can use this shell script:
-
-```sh
-rustup toolchain install --profile minimal nightly
-MINOR_VERSION=$(rustc +nightly --version | cut -d . -f 2)
-LOWER_BOUND=61
-
-llvm_version() {
-    toolchain="$1"
-    printf "Rust $toolchain    |    Clang "
-    rustc +"$toolchain" -Vv | grep LLVM | cut -d ':' -f 2 | tr -d ' '
-}
-
-for version in `seq $LOWER_BOUND $((MINOR_VERSION - 2))`; do
-    toolchain=1.$version.0
-    rustup toolchain install --no-self-update --profile  minimal $toolchain >/dev/null 2>&1
-    llvm_version $toolchain
-done
+<!-- NOTE: to update the below table, you can use this Python script:
+
+```python
+from collections import defaultdict
+import subprocess
+
+def minor_version(version):
+    return int(version.split('.')[1])
+
+INSTALL_TOOLCHAIN = ["rustup", "toolchain", "install", "--profile", "minimal"]
+subprocess.run(INSTALL_TOOLCHAIN + ["nightly"])
+
+LOWER_BOUND = 65
+NIGHTLY_VERSION = minor_version(subprocess.run(
+    ["rustc", "+nightly", "--version"],
+    capture_output=True,
+    text=True).stdout)
+
+def llvm_version(toolchain):
+    version_text = subprocess.run(
+        ["rustc", "+{}".format(toolchain), "-Vv"],
+        capture_output=True,
+        text=True).stdout
+    return int(version_text.split("LLVM")[1].split(':')[1].split('.')[0])
+
+version_map = defaultdict(lambda: [])
+for version in range(LOWER_BOUND, NIGHTLY_VERSION - 1):
+    toolchain = "1.{}.0".format(version)
+    subprocess.run(
+        INSTALL_TOOLCHAIN + ["--no-self-update", toolchain],
+        capture_output=True)
+    version_map[llvm_version(toolchain)].append(version)
+
+print("| Rust Version | Clang Version |")
+print("|--------------|---------------|")
+for clang, rust in sorted(version_map.items()):
+    if len(rust) > 1:
+        rust_range = "1.{} - 1.{}".format(rust[0], rust[-1])
+    else:
+        rust_range = "1.{}       ".format(rust[0])
+    print("| {}  |      {}       |".format(rust_range, clang))
 ```
 
 -->
@@ -166,32 +189,13 @@ The following table shows known good combinations of toolchain versions.
 
 | Rust Version | Clang Version |
 |--------------|---------------|
-| Rust 1.34    |    Clang 8    |
-| Rust 1.35    |    Clang 8    |
-| Rust 1.36    |    Clang 8    |
-| Rust 1.37    |    Clang 8    |
-| Rust 1.38    |    Clang 9    |
-| Rust 1.39    |    Clang 9    |
-| Rust 1.40    |    Clang 9    |
-| Rust 1.41    |    Clang 9    |
-| Rust 1.42    |    Clang 9    |
-| Rust 1.43    |    Clang 9    |
-| Rust 1.44    |    Clang 9    |
-| Rust 1.45    |    Clang 10   |
-| Rust 1.46    |    Clang 10   |
-| Rust 1.47    |    Clang 11   |
-| Rust 1.48    |    Clang 11   |
-| Rust 1.49    |    Clang 11   |
-| Rust 1.50    |    Clang 11   |
-| Rust 1.51    |    Clang 11   |
-| Rust 1.52    |    Clang 12   |
-| Rust 1.53    |    Clang 12   |
-| Rust 1.54    |    Clang 12   |
-| Rust 1.55    |    Clang 12   |
-| Rust 1.56    |    Clang 13   |
-| Rust 1.57    |    Clang 13   |
-| Rust 1.58    |    Clang 13   |
-| Rust 1.59    |    Clang 13   |
-| Rust 1.60    |    Clang 14   |
+| 1.34 - 1.37  |       8       |
+| 1.38 - 1.44  |       9       |
+| 1.45 - 1.46  |      10       |
+| 1.47 - 1.51  |      11       |
+| 1.52 - 1.55  |      12       |
+| 1.56 - 1.59  |      13       |
+| 1.60 - 1.64  |      14       |
+| 1.65         |      15       |
 
 Note that the compatibility policy for this feature might change in the future.
diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md
index 3ae9872cf62..0315f1e3725 100644
--- a/src/doc/rustc/src/platform-support.md
+++ b/src/doc/rustc/src/platform-support.md
@@ -128,6 +128,7 @@ target | std | notes
 [`aarch64-linux-android`](platform-support/android.md) | ✓ | ARM64 Android
 `aarch64-unknown-none-softfloat` | * | Bare ARM64, softfloat
 `aarch64-unknown-none` | * | Bare ARM64, hardfloat
+[`aarch64-unknown-uefi`](platform-support/unknown-uefi.md) | * | ARM64 UEFI
 [`arm-linux-androideabi`](platform-support/android.md) | ✓ | ARMv7 Android
 `arm-unknown-linux-musleabi` | ✓ | ARMv6 Linux with MUSL
 `arm-unknown-linux-musleabihf` | ✓ | ARMv6 Linux with MUSL, hardfloat
@@ -149,6 +150,7 @@ target | std | notes
 [`i686-linux-android`](platform-support/android.md) | ✓ | 32-bit x86 Android
 `i686-unknown-freebsd` | ✓ | 32-bit FreeBSD
 `i686-unknown-linux-musl` | ✓ | 32-bit Linux with MUSL
+[`i686-unknown-uefi`](platform-support/unknown-uefi.md) | * | 32-bit UEFI
 `mips-unknown-linux-musl` | ✓ | MIPS Linux with MUSL
 `mips64-unknown-linux-muslabi64` | ✓ | MIPS64 Linux, n64 ABI, MUSL
 `mips64el-unknown-linux-muslabi64` | ✓ | MIPS64 (LE) Linux, n64 ABI, MUSL
@@ -181,6 +183,7 @@ target | std | notes
 `x86_64-unknown-linux-gnux32` | ✓ | 64-bit Linux (x32 ABI) (kernel 4.15, glibc 2.27)
 [`x86_64-unknown-none`](platform-support/x86_64-unknown-none.md) | * | Freestanding/bare-metal x86_64, softfloat
 `x86_64-unknown-redox` | ✓ | Redox OS
+[`x86_64-unknown-uefi`](platform-support/unknown-uefi.md) | * | 64-bit UEFI
 
 [Fortanix ABI]: https://edp.fortanix.com/
 
@@ -213,7 +216,6 @@ target | std | host | notes
 [`aarch64-pc-windows-gnullvm`](platform-support/pc-windows-gnullvm.md) | ✓ | ✓ |
 `aarch64-unknown-freebsd` | ✓ | ✓ | ARM64 FreeBSD
 `aarch64-unknown-hermit` | ✓ |  | ARM64 HermitCore
-[`aarch64-unknown-uefi`](platform-support/unknown-uefi.md) | * |  | ARM64 UEFI
 `aarch64-unknown-linux-gnu_ilp32` | ✓ | ✓ | ARM64 Linux (ILP32 ABI)
 `aarch64-unknown-netbsd` | ✓ | ✓ |
 [`aarch64-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | ARM64 OpenBSD
@@ -252,7 +254,6 @@ target | std | host | notes
 `i686-unknown-haiku` | ✓ | ✓ | 32-bit Haiku
 `i686-unknown-netbsd` | ✓ | ✓ | NetBSD/i386 with SSE2
 [`i686-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | 32-bit OpenBSD
-[`i686-unknown-uefi`](platform-support/unknown-uefi.md) | * |  | 32-bit UEFI
 `i686-uwp-windows-gnu` | ? |  |
 `i686-uwp-windows-msvc` | ? |  |
 `i686-wrs-vxworks` | ? |  |
@@ -309,9 +310,7 @@ target | std | host | notes
 `x86_64-unknown-haiku` | ✓ | ✓ | 64-bit Haiku
 `x86_64-unknown-hermit` | ✓ |  | HermitCore
 `x86_64-unknown-l4re-uclibc` | ? |  |
-`x86_64-unknown-none-linuxkernel` | * |  | Linux kernel modules
 [`x86_64-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | 64-bit OpenBSD
-[`x86_64-unknown-uefi`](platform-support/unknown-uefi.md) | * |  | 64-bit UEFI
 `x86_64-uwp-windows-gnu` | ✓ |  |
 `x86_64-uwp-windows-msvc` | ✓ |  |
 `x86_64-wrs-vxworks` | ? |  |
diff --git a/src/doc/rustc/src/platform-support/unknown-uefi.md b/src/doc/rustc/src/platform-support/unknown-uefi.md
index 295dec0f0e4..e2bdf73a929 100644
--- a/src/doc/rustc/src/platform-support/unknown-uefi.md
+++ b/src/doc/rustc/src/platform-support/unknown-uefi.md
@@ -1,6 +1,6 @@
 # `*-unknown-uefi`
 
-**Tier: 3**
+**Tier: 2**
 
 Unified Extensible Firmware Interface (UEFI) targets for application, driver,
 and core UEFI binaries.
@@ -72,28 +72,14 @@ target = ["x86_64-unknown-uefi"]
 
 ## Building Rust programs
 
-Rust does not yet ship pre-compiled artifacts for this target. To compile for
-this target, you will either need to build Rust with the target enabled (see
-"Building rust for UEFI targets" above), or build your own copy of `core` by
-using `build-std`, `cargo-buildx`, or similar.
-
-A native build with the unstable `build-std`-feature can be achieved via:
-
-```sh
-cargo +nightly build \
-    -Zbuild-std=core,compiler_builtins \
-    -Zbuild-std-features=compiler-builtins-mem \
-    --target x86_64-unknown-uefi
-```
-
-Alternatively, you can install `cargo-xbuild` via
-`cargo install --force cargo-xbuild` and build for the UEFI targets via:
+Starting with Rust 1.67, precompiled artifacts are provided via
+`rustup`. For example, to use `x86_64-unknown-uefi`:
 
 ```sh
-cargo \
-    +nightly \
-    xbuild \
-    --target x86_64-unknown-uefi
+# install cross-compile toolchain
+rustup target add x86_64-unknown-uefi
+# target flag may be used with any cargo or rustc command
+cargo build --target x86_64-unknown-uefi
 ```
 
 ## Testing
@@ -167,18 +153,10 @@ The following code is a valid UEFI application returning immediately upon
 execution with an exit code of 0. A panic handler is provided. This is executed
 by rust on panic. For simplicity, we simply end up in an infinite loop.
 
-Note that as of rust-1.31.0, all features used here are stabilized. No unstable
-features are required, nor do we rely on nightly compilers. However, if you do
-not compile rustc for the UEFI targets, you need a nightly compiler to support
-the `-Z build-std` flag.
-
 This example can be compiled as binary crate via `cargo`:
 
 ```sh
-cargo +nightly build \
-    -Zbuild-std=core,compiler_builtins \
-    -Zbuild-std-features=compiler-builtins-mem \
-    --target x86_64-unknown-uefi
+cargo build --target x86_64-unknown-uefi
 ```
 
 ```rust,ignore (platform-specific,eh-personality-is-unstable)
diff --git a/src/etc/natvis/intrinsic.natvis b/src/etc/natvis/intrinsic.natvis
index 277e57aaf6f..8c16a562e34 100644
--- a/src/etc/natvis/intrinsic.natvis
+++ b/src/etc/natvis/intrinsic.natvis
@@ -1,6 +1,10 @@
 <?xml version="1.0" encoding="utf-8"?>
 <AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
-  <Type Name="str">
+  <Type Name="ref$&lt;str$&gt;">
+    <AlternativeType Name="ref_mut$&lt;str$&gt;" />
+    <AlternativeType Name="ptr_const$&lt;str$&gt;" />
+    <AlternativeType Name="ptr_mut$&lt;str$&gt;" />
+
     <DisplayString>{(char*)data_ptr,[length]s8}</DisplayString>
     <StringView>(char*)data_ptr,[length]s8</StringView>
     <Expand>
@@ -15,7 +19,11 @@
       </Synthetic>
     </Expand>
   </Type>
-  <Type Name="slice$&lt;*&gt;">
+  <Type Name="ref$&lt;slice2$&lt;*&gt; &gt;">
+    <AlternativeType Name="ref_mut$&lt;slice2$&lt;*&gt; &gt;" />
+    <AlternativeType Name="ptr_const$&lt;slice2$&lt;*&gt; &gt;" />
+    <AlternativeType Name="ptr_mut$&lt;slice2$&lt;*&gt; &gt;" />
+
     <DisplayString>{{ len={length} }}</DisplayString>
     <Expand>
       <Item Name="[len]" ExcludeView="simple">length</Item>
diff --git a/src/etc/natvis/liballoc.natvis b/src/etc/natvis/liballoc.natvis
index bf6c02b9146..41f4a3767f5 100644
--- a/src/etc/natvis/liballoc.natvis
+++ b/src/etc/natvis/liballoc.natvis
@@ -85,7 +85,7 @@
   </Type>
 
   <!-- alloc::rc::Rc<[T]> -->
-  <Type Name="alloc::rc::Rc&lt;slice$&lt;*&gt; &gt;">
+  <Type Name="alloc::rc::Rc&lt;slice2$&lt;*&gt; &gt;">
     <DisplayString>{{ len={ptr.pointer.length} }}</DisplayString>
     <Expand>
       <Item Name="[Length]" ExcludeView="simple">ptr.pointer.length</Item>
@@ -115,7 +115,7 @@
   </Type>
 
   <!-- alloc::rc::Weak<[T]> -->
-  <Type Name="alloc::rc::Weak&lt;slice$&lt;*&gt; &gt;">
+  <Type Name="alloc::rc::Weak&lt;slice2$&lt;*&gt; &gt;">
     <DisplayString>{{ len={ptr.pointer.length} }}</DisplayString>
     <Expand>
       <Item Name="[Length]" ExcludeView="simple">ptr.pointer.length</Item>
@@ -144,7 +144,7 @@
   </Type>
 
   <!-- alloc::sync::Arc<[T]> -->
-  <Type Name="alloc::sync::Arc&lt;slice$&lt;*&gt; &gt;">
+  <Type Name="alloc::sync::Arc&lt;slice2$&lt;*&gt; &gt;">
     <DisplayString>{{ len={ptr.pointer.length} }}</DisplayString>
     <Expand>
       <Item Name="[Length]" ExcludeView="simple">ptr.pointer.length</Item>
@@ -173,7 +173,7 @@
   </Type>
 
   <!-- alloc::sync::Weak<[T]> -->
-  <Type Name="alloc::sync::Weak&lt;slice$&lt;*&gt; &gt;">
+  <Type Name="alloc::sync::Weak&lt;slice2$&lt;*&gt; &gt;">
     <DisplayString>{{ len={ptr.pointer.length} }}</DisplayString>
     <Expand>
       <Item Name="[Length]" ExcludeView="simple">ptr.pointer.length</Item>
diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs
index 84e77e69ecf..85bd8446640 100644
--- a/src/librustdoc/clean/auto_trait.rs
+++ b/src/librustdoc/clean/auto_trait.rs
@@ -336,10 +336,7 @@ where
                 match br {
                     // We only care about named late bound regions, as we need to add them
                     // to the 'for<>' section
-                    ty::BrNamed(_, name) => Some(GenericParamDef {
-                        name,
-                        kind: GenericParamDefKind::Lifetime { outlives: vec![] },
-                    }),
+                    ty::BrNamed(_, name) => Some(GenericParamDef::lifetime(name)),
                     _ => None,
                 }
             })
diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index 841c4f9d530..3fc4aae923a 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -3,7 +3,7 @@
 use std::iter::once;
 use std::sync::Arc;
 
-use thin_vec::ThinVec;
+use thin_vec::{thin_vec, ThinVec};
 
 use rustc_ast as ast;
 use rustc_data_structures::fx::FxHashSet;
@@ -243,10 +243,19 @@ pub(crate) fn build_external_trait(cx: &mut DocContext<'_>, did: DefId) -> clean
 fn build_external_function<'tcx>(cx: &mut DocContext<'tcx>, did: DefId) -> Box<clean::Function> {
     let sig = cx.tcx.fn_sig(did);
 
-    let predicates = cx.tcx.predicates_of(did);
+    let late_bound_regions = sig.bound_vars().into_iter().filter_map(|var| match var {
+        ty::BoundVariableKind::Region(ty::BrNamed(_, name)) if name != kw::UnderscoreLifetime => {
+            Some(clean::GenericParamDef::lifetime(name))
+        }
+        _ => None,
+    });
+
+    let predicates = cx.tcx.explicit_predicates_of(did);
     let (generics, decl) = clean::enter_impl_trait(cx, |cx| {
         // NOTE: generics need to be cleaned before the decl!
-        let generics = clean_ty_generics(cx, cx.tcx.generics_of(did), predicates);
+        let mut generics = clean_ty_generics(cx, cx.tcx.generics_of(did), predicates);
+        // FIXME: This does not place parameters in source order (late-bound ones come last)
+        generics.params.extend(late_bound_regions);
         let decl = clean_fn_decl_from_did_and_sig(cx, Some(did), sig);
         (generics, decl)
     });
@@ -596,7 +605,7 @@ fn build_module_items(
                         clean::ImportSource {
                             path: clean::Path {
                                 res,
-                                segments: vec![clean::PathSegment {
+                                segments: thin_vec![clean::PathSegment {
                                     name: prim_ty.as_sym(),
                                     args: clean::GenericArgs::AngleBracketed {
                                         args: Default::default(),
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 16e2d9a3cfc..56a873e3e82 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -12,7 +12,7 @@ pub(crate) mod utils;
 
 use rustc_ast as ast;
 use rustc_attr as attr;
-use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
 use rustc_hir as hir;
 use rustc_hir::def::{CtorKind, DefKind, Res};
 use rustc_hir::def_id::{DefId, LOCAL_CRATE};
@@ -182,10 +182,9 @@ fn clean_poly_trait_ref_with_bindings<'tcx>(
         .collect_referenced_late_bound_regions(&poly_trait_ref)
         .into_iter()
         .filter_map(|br| match br {
-            ty::BrNamed(_, name) if name != kw::UnderscoreLifetime => Some(GenericParamDef {
-                name,
-                kind: GenericParamDefKind::Lifetime { outlives: vec![] },
-            }),
+            ty::BrNamed(_, name) if name != kw::UnderscoreLifetime => {
+                Some(GenericParamDef::lifetime(name))
+            }
             _ => None,
         })
         .collect();
@@ -227,7 +226,7 @@ pub(crate) fn clean_middle_const<'tcx>(
     // FIXME: instead of storing the stringified expression, store `self` directly instead.
     Constant {
         type_: clean_middle_ty(constant.ty(), cx, None),
-        kind: ConstantKind::TyConst { expr: constant.to_string() },
+        kind: ConstantKind::TyConst { expr: constant.to_string().into() },
     }
 }
 
@@ -741,10 +740,7 @@ fn clean_ty_generics<'tcx>(
                             p.get_bound_params()
                                 .into_iter()
                                 .flatten()
-                                .map(|param| GenericParamDef {
-                                    name: param.0,
-                                    kind: GenericParamDefKind::Lifetime { outlives: Vec::new() },
-                                })
+                                .map(|param| GenericParamDef::lifetime(param.0))
                                 .collect(),
                         ));
                     }
@@ -957,12 +953,14 @@ fn clean_args_from_types_and_names<'tcx>(
         values: types
             .iter()
             .enumerate()
-            .map(|(i, ty)| {
-                let mut name = names.get(i).map_or(kw::Empty, |ident| ident.name);
-                if name.is_empty() {
-                    name = kw::Underscore;
-                }
-                Argument { name, type_: clean_ty(ty, cx), is_const: false }
+            .map(|(i, ty)| Argument {
+                type_: clean_ty(ty, cx),
+                name: names
+                    .get(i)
+                    .map(|ident| ident.name)
+                    .filter(|ident| !ident.is_empty())
+                    .unwrap_or(kw::Underscore),
+                is_const: false,
             })
             .collect(),
     }
@@ -1024,7 +1022,11 @@ fn clean_fn_decl_from_did_and_sig<'tcx>(
                 .iter()
                 .map(|t| Argument {
                     type_: clean_middle_ty(*t, cx, None),
-                    name: names.next().map_or(kw::Empty, |i| i.name),
+                    name: names
+                        .next()
+                        .map(|i| i.name)
+                        .filter(|i| !i.is_empty())
+                        .unwrap_or(kw::Underscore),
                     is_const: false,
                 })
                 .collect(),
@@ -1144,12 +1146,25 @@ pub(crate) fn clean_middle_assoc_item<'tcx>(
             }
         }
         ty::AssocKind::Fn => {
-            let generics = clean_ty_generics(
+            let sig = tcx.fn_sig(assoc_item.def_id);
+
+            let late_bound_regions = sig.bound_vars().into_iter().filter_map(|var| match var {
+                ty::BoundVariableKind::Region(ty::BrNamed(_, name))
+                    if name != kw::UnderscoreLifetime =>
+                {
+                    Some(GenericParamDef::lifetime(name))
+                }
+                _ => None,
+            });
+
+            let mut generics = clean_ty_generics(
                 cx,
                 tcx.generics_of(assoc_item.def_id),
                 tcx.explicit_predicates_of(assoc_item.def_id),
             );
-            let sig = tcx.fn_sig(assoc_item.def_id);
+            // FIXME: This does not place parameters in source order (late-bound ones come last)
+            generics.params.extend(late_bound_regions);
+
             let mut decl = clean_fn_decl_from_did_and_sig(cx, Some(assoc_item.def_id), sig);
 
             if assoc_item.fn_has_self_parameter {
@@ -1200,7 +1215,7 @@ pub(crate) fn clean_middle_assoc_item<'tcx>(
                         true
                     }
                     (GenericParamDefKind::Const { .. }, GenericArg::Const(c)) => match &c.kind {
-                        ConstantKind::TyConst { expr } => expr == param.name.as_str(),
+                        ConstantKind::TyConst { expr } => **expr == *param.name.as_str(),
                         _ => false,
                     },
                     _ => false,
@@ -1281,7 +1296,16 @@ pub(crate) fn clean_middle_assoc_item<'tcx>(
                         ..
                     }) = generics.params.iter_mut().find(|param| &param.name == arg)
                     {
-                        param_bounds.extend(mem::take(bounds));
+                        param_bounds.append(bounds);
+                    } else if let WherePredicate::RegionPredicate { lifetime: Lifetime(arg), bounds } = &mut pred
+                    && let Some(GenericParamDef {
+                        kind: GenericParamDefKind::Lifetime { outlives: param_bounds },
+                        ..
+                    }) = generics.params.iter_mut().find(|param| &param.name == arg) {
+                        param_bounds.extend(bounds.drain(..).map(|bound| match bound {
+                            GenericBound::Outlives(lifetime) => lifetime,
+                            _ => unreachable!(),
+                        }));
                     } else {
                         where_predicates.push(pred);
                     }
@@ -1530,7 +1554,7 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T
                 }
             };
 
-            Array(Box::new(clean_ty(ty, cx)), length)
+            Array(Box::new(clean_ty(ty, cx)), length.into())
         }
         TyKind::Tup(tys) => Tuple(tys.iter().map(|ty| clean_ty(ty, cx)).collect()),
         TyKind::OpaqueDef(item_id, _, _) => {
@@ -1602,7 +1626,7 @@ pub(crate) fn clean_middle_ty<'tcx>(
         ty::Array(ty, mut n) => {
             n = n.eval(cx.tcx, ty::ParamEnv::reveal_all());
             let n = print_const(cx, n);
-            Array(Box::new(clean_middle_ty(ty, cx, None)), n)
+            Array(Box::new(clean_middle_ty(ty, cx, None)), n.into())
         }
         ty::RawPtr(mt) => RawPointer(mt.mutbl, Box::new(clean_middle_ty(mt.ty, cx, None))),
         ty::Ref(r, ty, mutbl) => BorrowedRef {
@@ -1653,6 +1677,9 @@ pub(crate) fn clean_middle_ty<'tcx>(
 
             inline::record_extern_fqn(cx, did, ItemType::Trait);
 
+            // FIXME(fmease): Hide the trait-object lifetime bound if it coincides with its default
+            // to partially address #44306. Follow the rules outlined at
+            // https://doc.rust-lang.org/reference/lifetime-elision.html#default-trait-object-lifetimes
             let lifetime = clean_middle_region(*reg);
             let mut bounds = dids
                 .map(|did| {
@@ -1680,8 +1707,22 @@ pub(crate) fn clean_middle_ty<'tcx>(
                 })
                 .collect();
 
+            let late_bound_regions: FxIndexSet<_> = obj
+                .iter()
+                .flat_map(|pb| pb.bound_vars())
+                .filter_map(|br| match br {
+                    ty::BoundVariableKind::Region(ty::BrNamed(_, name))
+                        if name != kw::UnderscoreLifetime =>
+                    {
+                        Some(GenericParamDef::lifetime(name))
+                    }
+                    _ => None,
+                })
+                .collect();
+            let late_bound_regions = late_bound_regions.into_iter().collect();
+
             let path = external_path(cx, did, false, bindings, substs);
-            bounds.insert(0, PolyTrait { trait_: path, generic_params: Vec::new() });
+            bounds.insert(0, PolyTrait { trait_: path, generic_params: late_bound_regions });
 
             DynTrait(bounds, lifetime)
         }
diff --git a/src/librustdoc/clean/simplify.rs b/src/librustdoc/clean/simplify.rs
index 1c184f9b269..7d97d2994e4 100644
--- a/src/librustdoc/clean/simplify.rs
+++ b/src/librustdoc/clean/simplify.rs
@@ -51,10 +51,7 @@ pub(crate) fn where_clauses(cx: &DocContext<'_>, clauses: Vec<WP>) -> ThinVec<WP
         let Some((bounds, _)) = tybounds.get_mut(ty) else { return true };
         let bound_params = bound_params
             .into_iter()
-            .map(|param| clean::GenericParamDef {
-                name: param.0,
-                kind: clean::GenericParamDefKind::Lifetime { outlives: Vec::new() },
-            })
+            .map(|param| clean::GenericParamDef::lifetime(param.0))
             .collect();
         merge_bounds(cx, bounds, bound_params, trait_did, name, rhs)
     });
@@ -99,9 +96,8 @@ pub(crate) fn merge_bounds(
         let last = trait_ref.trait_.segments.last_mut().expect("segments were empty");
 
         trait_ref.generic_params.append(&mut bound_params);
-        // Since the parameters (probably) originate from `tcx.collect_*_late_bound_regions` which
-        // returns a hash set, sort them alphabetically to guarantee a stable and deterministic
-        // output (and to fully deduplicate them).
+        // Sort parameters (likely) originating from a hashset alphabetically to
+        // produce predictable output (and to allow for full deduplication).
         trait_ref.generic_params.sort_unstable_by(|p, q| p.name.as_str().cmp(q.name.as_str()));
         trait_ref.generic_params.dedup_by_key(|p| p.name);
 
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index fea3690e50a..3d13f7463cb 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -1437,6 +1437,10 @@ pub(crate) struct GenericParamDef {
 }
 
 impl GenericParamDef {
+    pub(crate) fn lifetime(name: Symbol) -> Self {
+        Self { name, kind: GenericParamDefKind::Lifetime { outlives: Vec::new() } }
+    }
+
     pub(crate) fn is_synthetic_type_param(&self) -> bool {
         match self.kind {
             GenericParamDefKind::Lifetime { .. } | GenericParamDefKind::Const { .. } => false,
@@ -1621,7 +1625,7 @@ pub(crate) enum Type {
     /// An array type.
     ///
     /// The `String` field is a stringified version of the array's length parameter.
-    Array(Box<Type>, String),
+    Array(Box<Type>, Box<str>),
     /// A raw pointer type: `*const i32`, `*mut i32`
     RawPointer(Mutability, Box<Type>),
     /// A reference type: `&i32`, `&'a mut Foo`
@@ -2206,7 +2210,7 @@ impl Span {
 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
 pub(crate) struct Path {
     pub(crate) res: Res,
-    pub(crate) segments: Vec<PathSegment>,
+    pub(crate) segments: ThinVec<PathSegment>,
 }
 
 impl Path {
@@ -2356,7 +2360,7 @@ pub(crate) enum ConstantKind {
     ///
     /// Note that `ty::Const` includes generic parameters, and may not always be uniquely identified
     /// by a DefId. So this field must be different from `Extern`.
-    TyConst { expr: String },
+    TyConst { expr: Box<str> },
     /// A constant (expression) that's not an item or associated item. These are usually found
     /// nested inside types (e.g., array lengths) or expressions (e.g., repeat counts), and also
     /// used to define explicit discriminant values for enum variants.
@@ -2384,7 +2388,7 @@ impl Constant {
 impl ConstantKind {
     pub(crate) fn expr(&self, tcx: TyCtxt<'_>) -> String {
         match *self {
-            ConstantKind::TyConst { ref expr } => expr.clone(),
+            ConstantKind::TyConst { ref expr } => expr.to_string(),
             ConstantKind::Extern { def_id } => print_inlined_const(tcx, def_id),
             ConstantKind::Local { body, .. } | ConstantKind::Anonymous { body } => {
                 print_const_expr(tcx, body)
@@ -2570,13 +2574,13 @@ mod size_asserts {
     // tidy-alphabetical-start
     static_assert_size!(Crate, 72); // frequently moved by-value
     static_assert_size!(DocFragment, 32);
-    static_assert_size!(GenericArg, 48);
+    static_assert_size!(GenericArg, 32);
     static_assert_size!(GenericArgs, 32);
     static_assert_size!(GenericParamDef, 56);
     static_assert_size!(Generics, 16);
     static_assert_size!(Item, 56);
-    static_assert_size!(ItemKind, 88);
+    static_assert_size!(ItemKind, 64);
     static_assert_size!(PathSegment, 40);
-    static_assert_size!(Type, 48);
+    static_assert_size!(Type, 32);
     // tidy-alphabetical-end
 }
diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs
index df20dc3fc3f..21f8fbe36f1 100644
--- a/src/librustdoc/clean/utils.rs
+++ b/src/librustdoc/clean/utils.rs
@@ -4,7 +4,7 @@ use crate::clean::render_macro_matchers::render_macro_matcher;
 use crate::clean::{
     clean_doc_module, clean_middle_const, clean_middle_region, clean_middle_ty, inline, Crate,
     ExternalCrate, Generic, GenericArg, GenericArgs, ImportSource, Item, ItemKind, Lifetime, Path,
-    PathSegment, Primitive, PrimitiveType, Type, TypeBinding,
+    PathSegment, Primitive, PrimitiveType, Term, Type, TypeBinding, TypeBindingKind,
 };
 use crate::core::DocContext;
 use crate::html::format::visibility_to_src_with_space;
@@ -21,7 +21,7 @@ use rustc_middle::ty::{self, DefIdTree, TyCtxt};
 use rustc_span::symbol::{kw, sym, Symbol};
 use std::fmt::Write as _;
 use std::mem;
-use thin_vec::ThinVec;
+use thin_vec::{thin_vec, ThinVec};
 
 #[cfg(test)]
 mod tests;
@@ -113,12 +113,12 @@ fn external_generic_args<'tcx>(
                 ty::Tuple(tys) => tys.iter().map(|t| clean_middle_ty(t, cx, None)).collect::<Vec<_>>().into(),
                 _ => return GenericArgs::AngleBracketed { args: args.into(), bindings },
             };
-        let output = None;
-        // FIXME(#20299) return type comes from a projection now
-        // match types[1].kind {
-        //     ty::Tuple(ref v) if v.is_empty() => None, // -> ()
-        //     _ => Some(types[1].clean(cx))
-        // };
+        let output = bindings.into_iter().next().and_then(|binding| match binding.kind {
+            TypeBindingKind::Equality { term: Term::Type(ty) } if ty != Type::Tuple(Vec::new()) => {
+                Some(Box::new(ty))
+            }
+            _ => None,
+        });
         GenericArgs::Parenthesized { inputs, output }
     } else {
         GenericArgs::AngleBracketed { args: args.into(), bindings: bindings.into() }
@@ -136,7 +136,7 @@ pub(super) fn external_path<'tcx>(
     let name = cx.tcx.item_name(did);
     Path {
         res: Res::Def(def_kind, did),
-        segments: vec![PathSegment {
+        segments: thin_vec![PathSegment {
             name,
             args: external_generic_args(cx, did, has_self, bindings, substs),
         }],
@@ -242,19 +242,13 @@ pub(crate) fn print_const(cx: &DocContext<'_>, n: ty::Const<'_>) -> String {
 
             s
         }
-        _ => {
-            let mut s = n.to_string();
-            // array lengths are obviously usize
-            if s.ends_with("_usize") {
-                let n = s.len() - "_usize".len();
-                s.truncate(n);
-                if s.ends_with(": ") {
-                    let n = s.len() - ": ".len();
-                    s.truncate(n);
-                }
-            }
-            s
+        // array lengths are obviously usize
+        ty::ConstKind::Value(ty::ValTree::Leaf(scalar))
+            if *n.ty().kind() == ty::Uint(ty::UintTy::Usize) =>
+        {
+            scalar.to_string()
         }
+        _ => n.to_string(),
     }
 }
 
diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs
index 67ea39fb965..789dd398be5 100644
--- a/src/librustdoc/config.rs
+++ b/src/librustdoc/config.rs
@@ -239,9 +239,6 @@ pub(crate) struct RenderOptions {
     pub(crate) default_settings: FxHashMap<String, String>,
     /// If present, suffix added to CSS/JavaScript files when referencing them in generated pages.
     pub(crate) resource_suffix: String,
-    /// Whether to run the static CSS/JavaScript through a minifier when outputting them. `true` by
-    /// default.
-    pub(crate) enable_minification: bool,
     /// Whether to create an index page in the root of the output directory. If this is true but
     /// `enable_index_page` is None, generate a static listing of crates instead.
     pub(crate) enable_index_page: bool,
@@ -329,7 +326,7 @@ impl Options {
             crate::usage("rustdoc");
             return Err(0);
         } else if matches.opt_present("version") {
-            rustc_driver::version("rustdoc", matches);
+            rustc_driver::version!("rustdoc", matches);
             return Err(0);
         }
 
@@ -416,7 +413,9 @@ impl Options {
 
         let to_check = matches.opt_strs("check-theme");
         if !to_check.is_empty() {
-            let paths = match theme::load_css_paths(static_files::themes::LIGHT) {
+            let paths = match theme::load_css_paths(
+                std::str::from_utf8(static_files::STATIC_FILES.theme_light_css.bytes).unwrap(),
+            ) {
                 Ok(p) => p,
                 Err(e) => {
                     diag.struct_err(&e.to_string()).emit();
@@ -557,7 +556,9 @@ impl Options {
 
         let mut themes = Vec::new();
         if matches.opt_present("theme") {
-            let paths = match theme::load_css_paths(static_files::themes::LIGHT) {
+            let paths = match theme::load_css_paths(
+                std::str::from_utf8(static_files::STATIC_FILES.theme_light_css.bytes).unwrap(),
+            ) {
                 Ok(p) => p,
                 Err(e) => {
                     diag.struct_err(&e.to_string()).emit();
@@ -675,7 +676,6 @@ impl Options {
             ModuleSorting::Alphabetical
         };
         let resource_suffix = matches.opt_str("resource-suffix").unwrap_or_default();
-        let enable_minification = !matches.opt_present("disable-minification");
         let markdown_no_toc = matches.opt_present("markdown-no-toc");
         let markdown_css = matches.opt_strs("markdown-css");
         let markdown_playground_url = matches.opt_str("markdown-playground-url");
@@ -768,7 +768,6 @@ impl Options {
             extern_html_root_takes_precedence,
             default_settings,
             resource_suffix,
-            enable_minification,
             enable_index_page,
             index_page,
             static_root_path,
diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs
index 06db3fb0ec4..a5c3d35b1b5 100644
--- a/src/librustdoc/html/format.rs
+++ b/src/librustdoc/html/format.rs
@@ -1232,9 +1232,8 @@ impl clean::Arguments {
     ) -> impl fmt::Display + 'a + Captures<'tcx> {
         display_fn(move |f| {
             for (i, input) in self.values.iter().enumerate() {
-                if !input.name.is_empty() {
-                    write!(f, "{}: ", input.name)?;
-                }
+                write!(f, "{}: ", input.name)?;
+
                 if f.alternate() {
                     write!(f, "{:#}", input.type_.print(cx))?;
                 } else {
@@ -1367,10 +1366,8 @@ impl clean::FnDecl {
                     args.push_str("const ");
                     args_plain.push_str("const ");
                 }
-                if !input.name.is_empty() {
-                    write!(args, "{}: ", input.name);
-                    write!(args_plain, "{}: ", input.name);
-                }
+                write!(args, "{}: ", input.name);
+                write!(args_plain, "{}: ", input.name);
 
                 if f.alternate() {
                     write!(args, "{:#}", input.type_.print(cx));
diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs
index 7d6d4b71e2e..a60e7cb10fa 100644
--- a/src/librustdoc/html/layout.rs
+++ b/src/librustdoc/html/layout.rs
@@ -2,13 +2,14 @@ use std::path::PathBuf;
 
 use rustc_data_structures::fx::FxHashMap;
 
-use crate::error::Error;
 use crate::externalfiles::ExternalHtml;
 use crate::html::format::{Buffer, Print};
 use crate::html::render::{ensure_trailing_slash, StylePath};
 
 use askama::Template;
 
+use super::static_files::{StaticFiles, STATIC_FILES};
+
 #[derive(Clone)]
 pub(crate) struct Layout {
     pub(crate) logo: String,
@@ -34,17 +35,23 @@ pub(crate) struct Page<'a> {
 }
 
 impl<'a> Page<'a> {
-    pub(crate) fn get_static_root_path(&self) -> &str {
-        self.static_root_path.unwrap_or(self.root_path)
+    pub(crate) fn get_static_root_path(&self) -> String {
+        match self.static_root_path {
+            Some(s) => s.to_string(),
+            None => format!("{}static.files/", self.root_path),
+        }
     }
 }
 
 #[derive(Template)]
 #[template(path = "page.html")]
 struct PageLayout<'a> {
-    static_root_path: &'a str,
+    static_root_path: String,
     page: &'a Page<'a>,
     layout: &'a Layout,
+
+    files: &'static StaticFiles,
+
     themes: Vec<String>,
     sidebar: String,
     content: String,
@@ -61,19 +68,17 @@ pub(crate) fn render<T: Print, S: Print>(
 ) -> String {
     let static_root_path = page.get_static_root_path();
     let krate_with_trailing_slash = ensure_trailing_slash(&layout.krate).to_string();
-    let mut themes: Vec<String> = style_files
-        .iter()
-        .map(StylePath::basename)
-        .collect::<Result<_, Error>>()
-        .unwrap_or_default();
+    let mut themes: Vec<String> = style_files.iter().map(|s| s.basename().unwrap()).collect();
     themes.sort();
-    let rustdoc_version = rustc_interface::util::version_str().unwrap_or("unknown version");
+
+    let rustdoc_version = rustc_interface::util::version_str!().unwrap_or("unknown version");
     let content = Buffer::html().to_display(t); // Note: This must happen before making the sidebar.
     let sidebar = Buffer::html().to_display(sidebar);
     PageLayout {
         static_root_path,
         page,
         layout,
+        files: &STATIC_FILES,
         themes,
         sidebar,
         content,
diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs
index 5733d1f9c79..51843a505f7 100644
--- a/src/librustdoc/html/render/context.rs
+++ b/src/librustdoc/html/render/context.rs
@@ -32,7 +32,7 @@ use crate::html::escape::Escape;
 use crate::html::format::{join_with_double_colon, Buffer};
 use crate::html::markdown::{self, plain_text_summary, ErrorCodes, IdMap};
 use crate::html::url_parts_builder::UrlPartsBuilder;
-use crate::html::{layout, sources};
+use crate::html::{layout, sources, static_files};
 use crate::scrape_examples::AllCallLocations;
 use crate::try_err;
 
@@ -498,7 +498,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
         );
 
         let (sender, receiver) = channel();
-        let mut scx = SharedContext {
+        let scx = SharedContext {
             tcx,
             src_root,
             local_sources,
@@ -521,19 +521,6 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
             call_locations,
         };
 
-        // Add the default themes to the `Vec` of stylepaths
-        //
-        // Note that these must be added before `sources::render` is called
-        // so that the resulting source pages are styled
-        //
-        // `light.css` is not disabled because it is the stylesheet that stays loaded
-        // by the browser as the theme stylesheet. The theme system (hackily) works by
-        // changing the href to this stylesheet. All other themes are disabled to
-        // prevent rule conflicts
-        scx.style_files.push(StylePath { path: PathBuf::from("light.css") });
-        scx.style_files.push(StylePath { path: PathBuf::from("dark.css") });
-        scx.style_files.push(StylePath { path: PathBuf::from("ayu.css") });
-
         let dst = output;
         scx.ensure_dir(&dst)?;
 
@@ -647,10 +634,11 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
                         </section>\
                      </noscript>\
                      <link rel=\"stylesheet\" type=\"text/css\" \
-                         href=\"{root_path}settings{suffix}.css\">\
-                     <script defer src=\"{root_path}settings{suffix}.js\"></script>",
-                    root_path = page.static_root_path.unwrap_or(""),
-                    suffix = page.resource_suffix,
+                         href=\"{static_root_path}{settings_css}\">\
+                     <script defer src=\"{static_root_path}{settings_js}\"></script>",
+                    static_root_path = page.get_static_root_path(),
+                    settings_css = static_files::STATIC_FILES.settings_css,
+                    settings_js = static_files::STATIC_FILES.settings_js,
                 )
             },
             &shared.style_files,
diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs
index 3225ddabe2e..ce4fc4d68fa 100644
--- a/src/librustdoc/html/render/print_item.rs
+++ b/src/librustdoc/html/render/print_item.rs
@@ -30,10 +30,10 @@ use crate::html::format::{
     join_with_double_colon, print_abi_with_space, print_constness_with_space, print_where_clause,
     visibility_print_with_space, Buffer, Ending, PrintWithSpace,
 };
-use crate::html::highlight;
 use crate::html::layout::Page;
 use crate::html::markdown::{HeadingOffset, MarkdownSummaryLine};
 use crate::html::url_parts_builder::UrlPartsBuilder;
+use crate::html::{highlight, static_files};
 
 use askama::Template;
 use itertools::Itertools;
@@ -52,8 +52,8 @@ struct PathComponent {
 #[derive(Template)]
 #[template(path = "print_item.html")]
 struct ItemVars<'a> {
-    page: &'a Page<'a>,
     static_root_path: &'a str,
+    clipboard_svg: &'static static_files::StaticFile,
     typ: &'a str,
     name: &'a str,
     item_type: &'a str,
@@ -147,8 +147,8 @@ pub(super) fn print_item(
     };
 
     let item_vars = ItemVars {
-        page,
-        static_root_path: page.get_static_root_path(),
+        static_root_path: &page.get_static_root_path(),
+        clipboard_svg: &static_files::STATIC_FILES.clipboard_svg,
         typ,
         name: item.name.as_ref().unwrap().as_str(),
         item_type: &item.type_().to_string(),
diff --git a/src/librustdoc/html/render/write_shared.rs b/src/librustdoc/html/render/write_shared.rs
index 85f63c985b3..94d8a9feca6 100644
--- a/src/librustdoc/html/render/write_shared.rs
+++ b/src/librustdoc/html/render/write_shared.rs
@@ -1,10 +1,8 @@
-use std::ffi::OsStr;
 use std::fs::{self, File};
 use std::io::prelude::*;
 use std::io::{self, BufReader};
-use std::path::{Component, Path, PathBuf};
+use std::path::{Component, Path};
 use std::rc::Rc;
-use std::sync::LazyLock as Lazy;
 
 use itertools::Itertools;
 use rustc_data_structures::flock;
@@ -20,123 +18,20 @@ use crate::error::Error;
 use crate::html::{layout, static_files};
 use crate::{try_err, try_none};
 
-static FILES_UNVERSIONED: Lazy<FxHashMap<&str, &[u8]>> = Lazy::new(|| {
-    map! {
-        "FiraSans-Regular.woff2" => static_files::fira_sans::REGULAR,
-        "FiraSans-Medium.woff2" => static_files::fira_sans::MEDIUM,
-        "FiraSans-LICENSE.txt" => static_files::fira_sans::LICENSE,
-        "SourceSerif4-Regular.ttf.woff2" => static_files::source_serif_4::REGULAR,
-        "SourceSerif4-Bold.ttf.woff2" => static_files::source_serif_4::BOLD,
-        "SourceSerif4-It.ttf.woff2" => static_files::source_serif_4::ITALIC,
-        "SourceSerif4-LICENSE.md" => static_files::source_serif_4::LICENSE,
-        "SourceCodePro-Regular.ttf.woff2" => static_files::source_code_pro::REGULAR,
-        "SourceCodePro-Semibold.ttf.woff2" => static_files::source_code_pro::SEMIBOLD,
-        "SourceCodePro-It.ttf.woff2" => static_files::source_code_pro::ITALIC,
-        "SourceCodePro-LICENSE.txt" => static_files::source_code_pro::LICENSE,
-        "NanumBarunGothic.ttf.woff2" => static_files::nanum_barun_gothic::REGULAR,
-        "NanumBarunGothic-LICENSE.txt" => static_files::nanum_barun_gothic::LICENSE,
-        "LICENSE-MIT.txt" => static_files::LICENSE_MIT,
-        "LICENSE-APACHE.txt" => static_files::LICENSE_APACHE,
-        "COPYRIGHT.txt" => static_files::COPYRIGHT,
-    }
-});
-
-enum SharedResource<'a> {
-    /// This file will never change, no matter what toolchain is used to build it.
-    ///
-    /// It does not have a resource suffix.
-    Unversioned { name: &'static str },
-    /// This file may change depending on the toolchain.
-    ///
-    /// It has a resource suffix.
-    ToolchainSpecific { basename: &'static str },
-    /// This file may change for any crate within a build, or based on the CLI arguments.
-    ///
-    /// This differs from normal invocation-specific files because it has a resource suffix.
-    InvocationSpecific { basename: &'a str },
-}
-
-impl SharedResource<'_> {
-    fn extension(&self) -> Option<&OsStr> {
-        use SharedResource::*;
-        match self {
-            Unversioned { name }
-            | ToolchainSpecific { basename: name }
-            | InvocationSpecific { basename: name } => Path::new(name).extension(),
-        }
-    }
-
-    fn path(&self, cx: &Context<'_>) -> PathBuf {
-        match self {
-            SharedResource::Unversioned { name } => cx.dst.join(name),
-            SharedResource::ToolchainSpecific { basename } => cx.suffix_path(basename),
-            SharedResource::InvocationSpecific { basename } => cx.suffix_path(basename),
-        }
-    }
-
-    fn should_emit(&self, emit: &[EmitType]) -> bool {
-        if emit.is_empty() {
-            return true;
-        }
-        let kind = match self {
-            SharedResource::Unversioned { .. } => EmitType::Unversioned,
-            SharedResource::ToolchainSpecific { .. } => EmitType::Toolchain,
-            SharedResource::InvocationSpecific { .. } => EmitType::InvocationSpecific,
-        };
-        emit.contains(&kind)
-    }
-}
-
-impl Context<'_> {
-    fn suffix_path(&self, filename: &str) -> PathBuf {
-        // We use splitn vs Path::extension here because we might get a filename
-        // like `style.min.css` and we want to process that into
-        // `style-suffix.min.css`.  Path::extension would just return `css`
-        // which would result in `style.min-suffix.css` which isn't what we
-        // want.
-        let (base, ext) = filename.split_once('.').unwrap();
-        let filename = format!("{}{}.{}", base, self.shared.resource_suffix, ext);
-        self.dst.join(&filename)
-    }
-
-    fn write_shared(
-        &self,
-        resource: SharedResource<'_>,
-        contents: impl 'static + Send + AsRef<[u8]>,
-        emit: &[EmitType],
-    ) -> Result<(), Error> {
-        if resource.should_emit(emit) {
-            self.shared.fs.write(resource.path(self), contents)
-        } else {
-            Ok(())
-        }
-    }
-
-    fn write_minify(
-        &self,
-        resource: SharedResource<'_>,
-        contents: impl 'static + Send + AsRef<str> + AsRef<[u8]>,
-        minify: bool,
-        emit: &[EmitType],
-    ) -> Result<(), Error> {
-        if minify {
-            let contents = contents.as_ref();
-            let contents = if resource.extension() == Some(OsStr::new("css")) {
-                minifier::css::minify(contents)
-                    .map_err(|e| {
-                        Error::new(format!("failed to minify CSS file: {}", e), resource.path(self))
-                    })?
-                    .to_string()
-            } else {
-                minifier::js::minify(contents).to_string()
-            };
-            self.write_shared(resource, contents, emit)
-        } else {
-            self.write_shared(resource, contents, emit)
-        }
-    }
-}
-
+/// Rustdoc writes out two kinds of shared files:
+///  - Static files, which are embedded in the rustdoc binary and are written with a
+///    filename that includes a hash of their contents. These will always have a new
+///    URL if the contents change, so they are safe to cache with the
+///    `Cache-Control: immutable` directive. They are written under the static.files/
+///    directory and are written when --emit-type is empty (default) or contains
+///    "toolchain-specific". If using the --static-root-path flag, it should point
+///    to a URL path prefix where each of these filenames can be fetched.
+///  - Invocation specific files. These are generated based on the crate(s) being
+///    documented. Their filenames need to be predictable without knowing their
+///    contents, so they do not include a hash in their filename and are not safe to
+///    cache with `Cache-Control: immutable`. They include the contents of the
+///    --resource-suffix flag and are emitted when --emit-type is empty (default)
+///    or contains "invocation-specific".
 pub(super) fn write_shared(
     cx: &mut Context<'_>,
     krate: &Crate,
@@ -149,139 +44,52 @@ pub(super) fn write_shared(
     let lock_file = cx.dst.join(".lock");
     let _lock = try_err!(flock::Lock::new(&lock_file, true, true, true), &lock_file);
 
-    // Minified resources are usually toolchain resources. If they're not, they should use `cx.write_minify` directly.
-    fn write_minify(
-        basename: &'static str,
-        contents: impl 'static + Send + AsRef<str> + AsRef<[u8]>,
-        cx: &Context<'_>,
-        options: &RenderOptions,
-    ) -> Result<(), Error> {
-        cx.write_minify(
-            SharedResource::ToolchainSpecific { basename },
-            contents,
-            options.enable_minification,
-            &options.emit,
-        )
-    }
-
-    // Toolchain resources should never be dynamic.
-    let write_toolchain = |p: &'static _, c: &'static _| {
-        cx.write_shared(SharedResource::ToolchainSpecific { basename: p }, c, &options.emit)
-    };
-
-    // Crate resources should always be dynamic.
-    let write_crate = |p: &_, make_content: &dyn Fn() -> Result<Vec<u8>, Error>| {
+    // InvocationSpecific resources should always be dynamic.
+    let write_invocation_specific = |p: &str, make_content: &dyn Fn() -> Result<Vec<u8>, Error>| {
         let content = make_content()?;
-        cx.write_shared(SharedResource::InvocationSpecific { basename: p }, content, &options.emit)
+        if options.emit.is_empty() || options.emit.contains(&EmitType::InvocationSpecific) {
+            let output_filename = static_files::suffix_path(p, &cx.shared.resource_suffix);
+            cx.shared.fs.write(cx.dst.join(output_filename), content)
+        } else {
+            Ok(())
+        }
     };
 
-    // Given "foo.svg", return e.g. "url(\"foo1.58.0.svg\")"
-    fn ver_url(cx: &Context<'_>, basename: &'static str) -> String {
-        format!(
-            "url(\"{}\")",
-            SharedResource::ToolchainSpecific { basename }
-                .path(cx)
-                .file_name()
-                .unwrap()
-                .to_str()
-                .unwrap()
-        )
-    }
-
-    // We use the AUTOREPLACE mechanism to inject into our static JS and CSS certain
-    // values that are only known at doc build time. Since this mechanism is somewhat
-    // surprising when reading the code, please limit it to rustdoc.css.
-    write_minify(
-        "rustdoc.css",
-        static_files::RUSTDOC_CSS
-            .replace(
-                "/* AUTOREPLACE: */url(\"toggle-minus.svg\")",
-                &ver_url(cx, "toggle-minus.svg"),
-            )
-            .replace("/* AUTOREPLACE: */url(\"toggle-plus.svg\")", &ver_url(cx, "toggle-plus.svg"))
-            .replace("/* AUTOREPLACE: */url(\"down-arrow.svg\")", &ver_url(cx, "down-arrow.svg")),
-        cx,
-        options,
-    )?;
-
-    // Add all the static files. These may already exist, but we just
-    // overwrite them anyway to make sure that they're fresh and up-to-date.
-    write_minify("settings.css", static_files::SETTINGS_CSS, cx, options)?;
-    write_minify("noscript.css", static_files::NOSCRIPT_CSS, cx, options)?;
-
-    // To avoid "light.css" to be overwritten, we'll first run over the received themes and only
-    // then we'll run over the "official" styles.
-    let mut themes: FxHashSet<String> = FxHashSet::default();
+    cx.shared
+        .fs
+        .create_dir_all(cx.dst.join("static.files"))
+        .map_err(|e| PathError::new(e, "static.files"))?;
 
+    // Handle added third-party themes
     for entry in &cx.shared.style_files {
         let theme = entry.basename()?;
         let extension =
             try_none!(try_none!(entry.path.extension(), &entry.path).to_str(), &entry.path);
 
-        // Handle the official themes
-        match theme.as_str() {
-            "light" => write_minify("light.css", static_files::themes::LIGHT, cx, options)?,
-            "dark" => write_minify("dark.css", static_files::themes::DARK, cx, options)?,
-            "ayu" => write_minify("ayu.css", static_files::themes::AYU, cx, options)?,
-            _ => {
-                // Handle added third-party themes
-                let filename = format!("{}.{}", theme, extension);
-                write_crate(&filename, &|| Ok(try_err!(fs::read(&entry.path), &entry.path)))?;
-            }
-        };
-
-        themes.insert(theme.to_owned());
-    }
-
-    if (*cx.shared).layout.logo.is_empty() {
-        write_toolchain("rust-logo.svg", static_files::RUST_LOGO_SVG)?;
-    }
-    if (*cx.shared).layout.favicon.is_empty() {
-        write_toolchain("favicon.svg", static_files::RUST_FAVICON_SVG)?;
-        write_toolchain("favicon-16x16.png", static_files::RUST_FAVICON_PNG_16)?;
-        write_toolchain("favicon-32x32.png", static_files::RUST_FAVICON_PNG_32)?;
-    }
-    write_toolchain("wheel.svg", static_files::WHEEL_SVG)?;
-    write_toolchain("clipboard.svg", static_files::CLIPBOARD_SVG)?;
-    write_toolchain("down-arrow.svg", static_files::DOWN_ARROW_SVG)?;
-    write_toolchain("toggle-minus.svg", static_files::TOGGLE_MINUS_PNG)?;
-    write_toolchain("toggle-plus.svg", static_files::TOGGLE_PLUS_PNG)?;
-
-    let mut themes: Vec<&String> = themes.iter().collect();
-    themes.sort();
-
-    write_minify("main.js", static_files::MAIN_JS, cx, options)?;
-    write_minify("search.js", static_files::SEARCH_JS, cx, options)?;
-    write_minify("settings.js", static_files::SETTINGS_JS, cx, options)?;
-
-    if cx.include_sources {
-        write_minify("source-script.js", static_files::sidebar::SOURCE_SCRIPT, cx, options)?;
-    }
-
-    write_minify("storage.js", static_files::STORAGE_JS, cx, options)?;
+        // Skip the official themes. They are written below as part of STATIC_FILES_LIST.
+        if matches!(theme.as_str(), "light" | "dark" | "ayu") {
+            continue;
+        }
 
-    if cx.shared.layout.scrape_examples_extension {
-        cx.write_minify(
-            SharedResource::InvocationSpecific { basename: "scrape-examples.js" },
-            static_files::SCRAPE_EXAMPLES_JS,
-            options.enable_minification,
-            &options.emit,
-        )?;
+        let bytes = try_err!(fs::read(&entry.path), &entry.path);
+        let filename = format!("{}{}.{}", theme, cx.shared.resource_suffix, extension);
+        cx.shared.fs.write(cx.dst.join(filename), bytes)?;
     }
 
+    // When the user adds their own CSS files with --extend-css, we write that as an
+    // invocation-specific file (that is, with a resource suffix).
     if let Some(ref css) = cx.shared.layout.css_file_extension {
         let buffer = try_err!(fs::read_to_string(css), css);
-        // This varies based on the invocation, so it can't go through the write_minify wrapper.
-        cx.write_minify(
-            SharedResource::InvocationSpecific { basename: "theme.css" },
-            buffer,
-            options.enable_minification,
-            &options.emit,
-        )?;
+        let path = static_files::suffix_path("theme.css", &cx.shared.resource_suffix);
+        cx.shared.fs.write(cx.dst.join(path), buffer)?;
     }
-    write_minify("normalize.css", static_files::NORMALIZE_CSS, cx, options)?;
-    for (name, contents) in &*FILES_UNVERSIONED {
-        cx.write_shared(SharedResource::Unversioned { name }, contents, &options.emit)?;
+
+    if options.emit.is_empty() || options.emit.contains(&EmitType::Toolchain) {
+        let static_dir = cx.dst.join(Path::new("static.files"));
+        static_files::for_each(|f: &static_files::StaticFile| {
+            let filename = static_dir.join(f.output_filename());
+            cx.shared.fs.write(filename, f.minified())
+        })?;
     }
 
     /// Read a file and return all lines that match the `"{crate}":{data},` format,
@@ -463,7 +271,7 @@ pub(super) fn write_shared(
             v.push_str("\\\n}');\ncreateSourceSidebar();\n");
             Ok(v.into_bytes())
         };
-        write_crate("source-files.js", &make_sources)?;
+        write_invocation_specific("source-files.js", &make_sources)?;
     }
 
     // Update the search index and crate list.
@@ -477,7 +285,7 @@ pub(super) fn write_shared(
     // Sort the indexes by crate so the file will be generated identically even
     // with rustdoc running in parallel.
     all_indexes.sort();
-    write_crate("search-index.js", &|| {
+    write_invocation_specific("search-index.js", &|| {
         let mut v = String::from("var searchIndex = JSON.parse('{\\\n");
         v.push_str(&all_indexes.join(",\\\n"));
         v.push_str(
@@ -490,7 +298,7 @@ if (typeof exports !== 'undefined') {exports.searchIndex = searchIndex};
         Ok(v.into_bytes())
     })?;
 
-    write_crate("crates.js", &|| {
+    write_invocation_specific("crates.js", &|| {
         let krates = krates.iter().map(|k| format!("\"{}\"", k)).join(",");
         Ok(format!("window.ALL_CRATES = [{}];", krates).into_bytes())
     })?;
diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css
index 7c0dab1c527..f58d2c60942 100644
--- a/src/librustdoc/html/static/css/rustdoc.css
+++ b/src/librustdoc/html/static/css/rustdoc.css
@@ -4,7 +4,7 @@
 	font-style: normal;
 	font-weight: 400;
 	src: local('Fira Sans'),
-		url("FiraSans-Regular.woff2") format("woff2");
+		url("FiraSans-Regular-018c141bf0843ffd.woff2") format("woff2");
 	font-display: swap;
 }
 @font-face {
@@ -12,7 +12,7 @@
 	font-style: normal;
 	font-weight: 500;
 	src: local('Fira Sans Medium'),
-		url("FiraSans-Medium.woff2") format("woff2");
+		url("FiraSans-Medium-8f9a781e4970d388.woff2") format("woff2");
 	font-display: swap;
 }
 
@@ -22,7 +22,7 @@
 	font-style: normal;
 	font-weight: 400;
 	src: local('Source Serif 4'),
-		url("SourceSerif4-Regular.ttf.woff2") format("woff2");
+		url("SourceSerif4-Regular-1f7d512b176f0f72.ttf.woff2") format("woff2");
 	font-display: swap;
 }
 @font-face {
@@ -30,7 +30,7 @@
 	font-style: italic;
 	font-weight: 400;
 	src: local('Source Serif 4 Italic'),
-		url("SourceSerif4-It.ttf.woff2") format("woff2");
+		url("SourceSerif4-It-d034fe4ef9d0fa00.ttf.woff2") format("woff2");
 	font-display: swap;
 }
 @font-face {
@@ -38,7 +38,7 @@
 	font-style: normal;
 	font-weight: 700;
 	src: local('Source Serif 4 Bold'),
-		url("SourceSerif4-Bold.ttf.woff2") format("woff2");
+		url("SourceSerif4-Bold-124a1ca42af929b6.ttf.woff2") format("woff2");
 	font-display: swap;
 }
 
@@ -49,28 +49,28 @@
 	font-weight: 400;
 	/* Avoid using locally installed font because bad versions are in circulation:
 	 * see https://github.com/rust-lang/rust/issues/24355 */
-	src: url("SourceCodePro-Regular.ttf.woff2") format("woff2");
+	src: url("SourceCodePro-Regular-562dcc5011b6de7d.ttf.woff2") format("woff2");
 	font-display: swap;
 }
 @font-face {
 	font-family: 'Source Code Pro';
 	font-style: italic;
 	font-weight: 400;
-	src: url("SourceCodePro-It.ttf.woff2") format("woff2");
+	src: url("SourceCodePro-It-1cc31594bf4f1f79.ttf.woff2") format("woff2");
 	font-display: swap;
 }
 @font-face {
 	font-family: 'Source Code Pro';
 	font-style: normal;
 	font-weight: 600;
-	src: url("SourceCodePro-Semibold.ttf.woff2") format("woff2");
+	src: url("SourceCodePro-Semibold-d899c5a5c4aeb14a.ttf.woff2") format("woff2");
 	font-display: swap;
 }
 
 /* Avoid using legacy CJK serif fonts in Windows like Batang. */
 @font-face {
 	font-family: 'NanumBarunGothic';
-	src: url("NanumBarunGothic.ttf.woff2") format("woff2");
+	src: url("NanumBarunGothic-0f09457c7a19b7c6.ttf.woff2") format("woff2");
 	font-display: swap;
 	unicode-range: U+AC00-D7AF, U+1100-11FF, U+3130-318F, U+A960-A97F, U+D7B0-D7FF;
 }
@@ -367,7 +367,8 @@ img {
 	overflow: visible;
 }
 
-.sub-logo-container {
+.sub-logo-container, .logo-container {
+	/* zero text boxes so that computed line height = image height exactly */
 	line-height: 0;
 }
 
@@ -377,6 +378,10 @@ img {
 	object-fit: contain;
 }
 
+.rust-logo {
+	filter: var(--rust-logo-filter);
+}
+
 .sidebar, .mobile-topbar, .sidebar-menu-toggle {
 	background-color: var(--sidebar-background-color);
 }
@@ -465,10 +470,9 @@ img {
 }
 
 .sidebar .logo-container {
-	display: flex;
 	margin-top: 10px;
 	margin-bottom: 10px;
-	justify-content: center;
+	text-align: center;
 }
 
 .version {
@@ -850,7 +854,7 @@ so that we can apply CSS-filters to change the arrow color in themes */
 	background-size: 20px;
 	background-position: calc(100% - 2px) 56%;
 	/* image is black color, themes should apply a "filter" property to change the color */
-	background-image: /* AUTOREPLACE: */url("down-arrow.svg");
+	background-image: url("down-arrow-927217e04c7463ac.svg");
 }
 #crate-search > option {
 	font-size: 1rem;
@@ -886,7 +890,7 @@ so that we can apply CSS-filters to change the arrow color in themes */
 	/* A little margin ensures the browser's outlining of focused links has room to display. */
 	margin-left: 2px;
 	margin-right: 2px;
-	border-bottom: 1px solid var(--border-color);
+	border-bottom: 1px solid var(--search-result-border-color);
 	gap: 1em;
 }
 
@@ -1204,6 +1208,12 @@ a.test-arrow {
 	top: 5px;
 	right: 5px;
 	z-index: 1;
+	color: var(--test-arrow-color);
+	background-color: var(--test-arrow-background-color);
+}
+a.test-arrow:hover {
+	color: var(--test-arrow-hover-color);
+	background-color: var(--test-arrow-hover-background-color);
 }
 .example-wrap:hover .test-arrow {
 	visibility: visible;
@@ -1617,11 +1627,11 @@ details.rustdoc-toggle[open] > summary.hideme > span {
 
 details.rustdoc-toggle[open] > summary::before,
 details.rustdoc-toggle[open] > summary.hideme::before {
-	background-image: /* AUTOREPLACE: */url("toggle-minus.svg");
+	background-image: url("toggle-minus-31bbd6e4c77f5c96.svg");
 }
 
 details.rustdoc-toggle > summary::before {
-	background-image: /* AUTOREPLACE: */url("toggle-plus.svg");
+	background-image: url("toggle-plus-1092eb4930d581b0.svg");
 }
 
 details.rustdoc-toggle[open] > summary::before,
@@ -1755,10 +1765,6 @@ in storage.js
 		white-space: nowrap;
 	}
 
-	.mobile-topbar .logo-container {
-		max-height: 45px;
-	}
-
 	.mobile-topbar .logo-container > img {
 		max-width: 35px;
 		max-height: 35px;
@@ -1802,21 +1808,6 @@ in storage.js
 		display: block;
 	}
 
-	/* Because of ios, we need to actually have a full height sidebar title so the
-	 * actual sidebar can show up. But then we need to make it transparent so we don't
-	 * hide content. The filler just allows to create the background for the sidebar
-	 * title. But because of the absolute position, I had to lower the z-index.
-	 */
-	#sidebar-filler {
-		position: fixed;
-		left: 45px;
-		width: calc(100% - 45px);
-		top: 0;
-		height: 45px;
-		z-index: -1;
-		border-bottom: 1px solid;
-	}
-
 	#main-content > details.rustdoc-toggle > summary::before,
 	#main-content > div > details.rustdoc-toggle > summary::before {
 		left: -11px;
diff --git a/src/librustdoc/html/static/css/themes/ayu.css b/src/librustdoc/html/static/css/themes/ayu.css
index fdfdb3e1966..bf8a60affaa 100644
--- a/src/librustdoc/html/static/css/themes/ayu.css
+++ b/src/librustdoc/html/static/css/themes/ayu.css
@@ -38,6 +38,7 @@ Original by Dempfi (https://github.com/dempfi/ayu)
 	--sidebar-link-color: #53b1db;
 	--sidebar-current-link-background-color: transparent;
 	--search-result-link-focus-background-color: #3c3c3c;
+	--search-result-border-color: #aaa3;
 	--stab-background-color: #314559;
 	--stab-code-color: #e6e1cf;
 	--search-color: #fff;
@@ -58,6 +59,14 @@ Original by Dempfi (https://github.com/dempfi/ayu)
 	--example-line-numbers-border-color: none;
 	--src-line-numbers-span-color: #5c6773;
 	--src-line-number-highlighted-background-color: rgba(255, 236, 164, 0.06);
+	--test-arrow-color: #788797;
+	--test-arrow-background-color: rgba(57, 175, 215, 0.09);
+	--test-arrow-hover-color: #c5c5c5;
+	--test-arrow-hover-background-color: rgba(57, 175, 215, 0.368);
+	--rust-logo-filter: drop-shadow(1px 0 0px #fff)
+		drop-shadow(0 1px 0 #fff)
+		drop-shadow(-1px 0 0 #fff)
+		drop-shadow(0 -1px 0 #fff);
 }
 
 .slider {
@@ -99,13 +108,6 @@ pre, .rustdoc.source .example-wrap {
 	color: #e6e1cf;
 }
 
-.rust-logo {
-	filter: drop-shadow(1px 0 0px #fff)
-		drop-shadow(0 1px 0 #fff)
-		drop-shadow(-1px 0 0 #fff)
-		drop-shadow(0 -1px 0 #fff);
-}
-
 .sidebar .current,
 .sidebar a:hover {
 	color: #ffb44c;
@@ -171,18 +173,6 @@ details.rustdoc-toggle > summary::before {
 	color: #788797;
 }
 
-a.test-arrow {
-	font-size: 100%;
-	color: #788797;
-	border-radius: 4px;
-	background-color: rgba(57, 175, 215, 0.09);
-}
-
-a.test-arrow:hover {
-	background-color: rgba(57, 175, 215, 0.368);
-	color: #c5c5c5;
-}
-
 :target {
 	background: rgba(255, 236, 164, 0.06);
 	border-right: 3px solid rgba(255, 180, 76, 0.85);
diff --git a/src/librustdoc/html/static/css/themes/dark.css b/src/librustdoc/html/static/css/themes/dark.css
index 361d3d4a225..ac6e527848f 100644
--- a/src/librustdoc/html/static/css/themes/dark.css
+++ b/src/librustdoc/html/static/css/themes/dark.css
@@ -33,6 +33,7 @@
 	--sidebar-link-color: #fdbf35;
 	--sidebar-current-link-background-color: #444;
 	--search-result-link-focus-background-color: #616161;
+	--search-result-border-color: #aaa3;
 	--stab-background-color: #314559;
 	--stab-code-color: #e6e1cf;
 	--search-color: #111;
@@ -53,6 +54,14 @@
 	--example-line-numbers-border-color: #4a4949;
 	--src-line-numbers-span-color: #3b91e2;
 	--src-line-number-highlighted-background-color: #0a042f;
+	--test-arrow-color: #dedede;
+	--test-arrow-background-color: rgba(78, 139, 202, 0.2);
+	--test-arrow-hover-color: #dedede;
+	--test-arrow-hover-background-color: #4e8bca;
+	--rust-logo-filter: drop-shadow(1px 0 0px #fff)
+		drop-shadow(0 1px 0 #fff)
+		drop-shadow(-1px 0 0 #fff)
+		drop-shadow(0 -1px 0 #fff);
 }
 
 .slider {
@@ -65,13 +74,6 @@ input:focus + .slider {
 	box-shadow: 0 0 0 2px #0a84ff, 0 0 0 6px rgba(10, 132, 255, 0.3);
 }
 
-.rust-logo {
-	filter: drop-shadow(1px 0 0px #fff)
-		drop-shadow(0 1px 0 #fff)
-		drop-shadow(-1px 0 0 #fff)
-		drop-shadow(0 -1px 0 #fff)
-}
-
 .content .item-info::before { color: #ccc; }
 
 body.source .example-wrap pre.rust a {
@@ -93,15 +95,6 @@ details.rustdoc-toggle > summary::before {
 	filter: invert(69%) sepia(60%) saturate(6613%) hue-rotate(184deg) brightness(100%) contrast(91%);
 }
 
-a.test-arrow {
-	color: #dedede;
-	background-color: rgba(78, 139, 202, 0.2);
-}
-
-a.test-arrow:hover{
-	background-color: #4e8bca;
-}
-
 :target {
 	background-color: #494a3d;
 	border-right: 3px solid #bb7410;
diff --git a/src/librustdoc/html/static/css/themes/light.css b/src/librustdoc/html/static/css/themes/light.css
index 5eb4bbcf834..608fc5aba7f 100644
--- a/src/librustdoc/html/static/css/themes/light.css
+++ b/src/librustdoc/html/static/css/themes/light.css
@@ -33,6 +33,7 @@
 	--sidebar-link-color: #356da4;
 	--sidebar-current-link-background-color: #fff;
 	--search-result-link-focus-background-color: #ccc;
+	--search-result-border-color: #aaa3;
 	--stab-background-color: #fff5d6;
 	--stab-code-color: #000;
 	--search-color: #000;
@@ -53,6 +54,11 @@
 	--example-line-numbers-border-color: #c7c7c7;
 	--src-line-numbers-span-color: #c67e2d;
 	--src-line-number-highlighted-background-color: #fdffd3;
+	--test-arrow-color: #f5f5f5;
+	--test-arrow-background-color: rgba(78, 139, 202, 0.2);
+	--test-arrow-hover-color: #f5f5f5;
+	--test-arrow-hover-background-color: #4e8bca;
+	--rust-logo-filter: initial;
 }
 
 .slider {
@@ -65,12 +71,6 @@ input:focus + .slider {
 	box-shadow: 0 0 0 2px #0a84ff, 0 0 0 6px rgba(10, 132, 255, 0.3);
 }
 
-.rust-logo {
-	/* This rule exists to force other themes to explicitly style the logo.
-	 * Rustdoc has a custom linter for this purpose.
-	 */
-}
-
 .content .item-info::before { color: #ccc; }
 
 body.source .example-wrap pre.rust a {
@@ -88,15 +88,6 @@ body.source .example-wrap pre.rust a {
 	filter: invert(44%) sepia(18%) saturate(23%) hue-rotate(317deg) brightness(96%) contrast(93%);
 }
 
-a.test-arrow {
-	color: #f5f5f5;
-	background-color: rgba(78, 139, 202, 0.2);
-}
-
-a.test-arrow:hover{
-	background-color: #4e8bca;
-}
-
 :target {
 	background: #FDFFD3;
 	border-right: 3px solid #AD7C37;
diff --git a/src/librustdoc/html/static/fonts/README.txt b/src/librustdoc/html/static/fonts/README.txt
new file mode 100644
index 00000000000..0db15996d2e
--- /dev/null
+++ b/src/librustdoc/html/static/fonts/README.txt
@@ -0,0 +1,12 @@
+The Nanum Barun Gothic fonts are shipped with rustdoc because the default fonts
+on many Windows installs render Korean very badly. See:
+ - https://github.com/rust-lang/rust/pull/84048,
+ - https://github.com/rust-lang/rust/issues/84035
+ - https://github.com/rust-lang/rust/pull/90232
+
+The font files were generated with these commands:
+
+```sh
+pyftsubset NanumBarunGothic.ttf \
+--unicodes=U+AC00-D7AF:U+1100-11FF,U+3130-318F,U+A960-A97F,U+D7B0-D7FF \
+--output-file=NanumBarunGothic.ttf.woff2 --flavor=woff2
diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js
index 33480fa41cf..1c84393cb4e 100644
--- a/src/librustdoc/html/static/js/main.js
+++ b/src/librustdoc/html/static/js/main.js
@@ -183,9 +183,9 @@ function browserSupportsHistoryApi() {
 }
 
 // eslint-disable-next-line no-unused-vars
-function loadCss(cssFileName) {
+function loadCss(cssUrl) {
     const link = document.createElement("link");
-    link.href = resourcePath(cssFileName, ".css");
+    link.href = cssUrl;
     link.type = "text/css";
     link.rel = "stylesheet";
     document.getElementsByTagName("head")[0].appendChild(link);
@@ -208,8 +208,8 @@ function loadCss(cssFileName) {
         event.preventDefault();
         // Sending request for the CSS and the JS files at the same time so it will
         // hopefully be loaded when the JS will generate the settings content.
-        loadCss("settings");
-        loadScript(resourcePath("settings", ".js"));
+        loadCss(getVar("static-root-path") + getVar("settings-css"));
+        loadScript(getVar("static-root-path") + getVar("settings-js"));
     };
 
     window.searchState = {
@@ -286,7 +286,7 @@ function loadCss(cssFileName) {
             function loadSearch() {
                 if (!searchLoaded) {
                     searchLoaded = true;
-                    loadScript(resourcePath("search", ".js"));
+                    loadScript(getVar("static-root-path") + getVar("search-js"));
                     loadScript(resourcePath("search-index", ".js"));
                 }
             }
diff --git a/src/librustdoc/html/static/js/settings.js b/src/librustdoc/html/static/js/settings.js
index 5e1c7e6f03e..141563bd46a 100644
--- a/src/librustdoc/html/static/js/settings.js
+++ b/src/librustdoc/html/static/js/settings.js
@@ -154,7 +154,9 @@
      * @return {HTMLElement}
      */
     function buildSettingsPage() {
-        const themes = getVar("themes").split(",");
+        const theme_names = getVar("themes").split(",").filter(t => t);
+        theme_names.push("light", "dark", "ayu");
+
         const settings = [
             {
                 "name": "Use system theme",
@@ -165,19 +167,19 @@
                 "name": "Theme",
                 "js_name": "theme",
                 "default": "light",
-                "options": themes,
+                "options": theme_names,
             },
             {
                 "name": "Preferred light theme",
                 "js_name": "preferred-light-theme",
                 "default": "light",
-                "options": themes,
+                "options": theme_names,
             },
             {
                 "name": "Preferred dark theme",
                 "js_name": "preferred-dark-theme",
                 "default": "dark",
-                "options": themes,
+                "options": theme_names,
             },
             {
                 "name": "Auto-hide item contents for large items",
diff --git a/src/librustdoc/html/static/js/storage.js b/src/librustdoc/html/static/js/storage.js
index b462a2c50f1..db2db83ca63 100644
--- a/src/librustdoc/html/static/js/storage.js
+++ b/src/librustdoc/html/static/js/storage.js
@@ -126,33 +126,29 @@ function getCurrentValue(name) {
     }
 }
 
-function switchTheme(styleElem, mainStyleElem, newTheme, saveTheme) {
-    const newHref = mainStyleElem.href.replace(
-        /\/rustdoc([^/]*)\.css/, "/" + newTheme + "$1" + ".css");
-
+function switchTheme(styleElem, mainStyleElem, newThemeName, saveTheme) {
     // If this new value comes from a system setting or from the previously
     // saved theme, no need to save it.
     if (saveTheme) {
-        updateLocalStorage("theme", newTheme);
-    }
-
-    if (styleElem.href === newHref) {
-        return;
+        updateLocalStorage("theme", newThemeName);
     }
 
-    let found = false;
     if (savedHref.length === 0) {
         onEachLazy(document.getElementsByTagName("link"), el => {
             savedHref.push(el.href);
         });
     }
-    onEach(savedHref, el => {
-        if (el === newHref) {
-            found = true;
+    const newHref = savedHref.find(url => {
+        const m = url.match(/static\.files\/(.*)-[a-f0-9]{16}\.css$/);
+        if (m && m[1] === newThemeName) {
+            return true;
+        }
+        const m2 = url.match(/\/([^/]*)\.css$/);
+        if (m2 && m2[1].startsWith(newThemeName)) {
             return true;
         }
     });
-    if (found) {
+    if (newHref && newHref !== styleElem.href) {
         styleElem.href = newHref;
     }
 }
diff --git a/src/librustdoc/html/static_files.rs b/src/librustdoc/html/static_files.rs
index 75f2b7e3570..afe920b7fa1 100644
--- a/src/librustdoc/html/static_files.rs
+++ b/src/librustdoc/html/static_files.rs
@@ -2,167 +2,128 @@
 //!
 //! All the static files are included here for centralized access in case anything other than the
 //! HTML rendering code (say, the theme checker) needs to access one of these files.
-//!
-//! Note about types: CSS and JavaScript files are included as `&'static str` to allow for the
-//! minifier to run on them. All other files are included as `&'static [u8]` so they can be
-//! directly written to a `Write` handle.
-
-/// The file contents of the main `rustdoc.css` file, responsible for the core layout of the page.
-pub(crate) static RUSTDOC_CSS: &str = include_str!("static/css/rustdoc.css");
-
-/// The file contents of `settings.css`, responsible for the items on the settings page.
-pub(crate) static SETTINGS_CSS: &str = include_str!("static/css/settings.css");
-
-/// The file contents of the `noscript.css` file, used in case JS isn't supported or is disabled.
-pub(crate) static NOSCRIPT_CSS: &str = include_str!("static/css/noscript.css");
-
-/// The file contents of `normalize.css`, included to even out standard elements between browser
-/// implementations.
-pub(crate) static NORMALIZE_CSS: &str = include_str!("static/css/normalize.css");
-
-/// The file contents of `main.js`, which contains the core JavaScript used on documentation pages,
-/// including search behavior and docblock folding, among others.
-pub(crate) static MAIN_JS: &str = include_str!("static/js/main.js");
-
-/// The file contents of `search.js`, which contains the search behavior.
-pub(crate) static SEARCH_JS: &str = include_str!("static/js/search.js");
-
-/// The file contents of `settings.js`, which contains the JavaScript used to handle the settings
-/// page.
-pub(crate) static SETTINGS_JS: &str = include_str!("static/js/settings.js");
-
-/// The file contents of `storage.js`, which contains functionality related to browser Local
-/// Storage, used to store documentation settings.
-pub(crate) static STORAGE_JS: &str = include_str!("static/js/storage.js");
-
-/// The file contents of `scraped-examples.js`, which contains functionality related to the
-/// --scrape-examples flag that inserts automatically-found examples of usages of items.
-pub(crate) static SCRAPE_EXAMPLES_JS: &str = include_str!("static/js/scrape-examples.js");
-
-pub(crate) static SCRAPE_EXAMPLES_HELP_MD: &str = include_str!("static/scrape-examples-help.md");
-
-/// The file contents of `wheel.svg`, the icon used for the settings button.
-pub(crate) static WHEEL_SVG: &[u8] = include_bytes!("static/images/wheel.svg");
-
-/// The file contents of `clipboard.svg`, the icon used for the "copy path" button.
-pub(crate) static CLIPBOARD_SVG: &[u8] = include_bytes!("static/images/clipboard.svg");
-
-/// The file contents of `down-arrow.svg`, the icon used for the crate choice combobox.
-pub(crate) static DOWN_ARROW_SVG: &[u8] = include_bytes!("static/images/down-arrow.svg");
-
-/// The file contents of `toggle-minus.svg`, the icon used for opened toggles.
-pub(crate) static TOGGLE_MINUS_PNG: &[u8] = include_bytes!("static/images/toggle-minus.svg");
-
-/// The file contents of `toggle-plus.svg`, the icon used for closed toggles.
-pub(crate) static TOGGLE_PLUS_PNG: &[u8] = include_bytes!("static/images/toggle-plus.svg");
 
-/// The contents of `COPYRIGHT.txt`, the license listing for files distributed with documentation
-/// output.
-pub(crate) static COPYRIGHT: &[u8] = include_bytes!("static/COPYRIGHT.txt");
+use rustc_data_structures::fx::FxHasher;
+use std::hash::Hasher;
+use std::path::{Path, PathBuf};
+use std::{fmt, str};
 
-/// The contents of `LICENSE-APACHE.txt`, the text of the Apache License, version 2.0.
-pub(crate) static LICENSE_APACHE: &[u8] = include_bytes!("static/LICENSE-APACHE.txt");
-
-/// The contents of `LICENSE-MIT.txt`, the text of the MIT License.
-pub(crate) static LICENSE_MIT: &[u8] = include_bytes!("static/LICENSE-MIT.txt");
-
-/// The contents of `rust-logo.svg`, the default icon of the documentation.
-pub(crate) static RUST_LOGO_SVG: &[u8] = include_bytes!("static/images/rust-logo.svg");
-
-/// The default documentation favicons (SVG and PNG fallbacks)
-pub(crate) static RUST_FAVICON_SVG: &[u8] = include_bytes!("static/images/favicon.svg");
-pub(crate) static RUST_FAVICON_PNG_16: &[u8] = include_bytes!("static/images/favicon-16x16.png");
-pub(crate) static RUST_FAVICON_PNG_32: &[u8] = include_bytes!("static/images/favicon-32x32.png");
-
-/// The built-in themes given to every documentation site.
-pub(crate) mod themes {
-    /// The "light" theme, selected by default when no setting is available. Used as the basis for
-    /// the `--check-theme` functionality.
-    pub(crate) static LIGHT: &str = include_str!("static/css/themes/light.css");
-
-    /// The "dark" theme.
-    pub(crate) static DARK: &str = include_str!("static/css/themes/dark.css");
-
-    /// The "ayu" theme.
-    pub(crate) static AYU: &str = include_str!("static/css/themes/ayu.css");
+pub(crate) struct StaticFile {
+    pub(crate) filename: PathBuf,
+    pub(crate) bytes: &'static [u8],
 }
 
-/// Files related to the Fira Sans font.
-pub(crate) mod fira_sans {
-    /// The file `FiraSans-Regular.woff2`, the Regular variant of the Fira Sans font in woff2.
-    pub(crate) static REGULAR: &[u8] = include_bytes!("static/fonts/FiraSans-Regular.woff2");
-
-    /// The file `FiraSans-Medium.woff2`, the Medium variant of the Fira Sans font in woff2.
-    pub(crate) static MEDIUM: &[u8] = include_bytes!("static/fonts/FiraSans-Medium.woff2");
-
-    /// The file `FiraSans-LICENSE.txt`, the license text for the Fira Sans font.
-    pub(crate) static LICENSE: &[u8] = include_bytes!("static/fonts/FiraSans-LICENSE.txt");
+impl StaticFile {
+    fn new(filename: &str, bytes: &'static [u8]) -> StaticFile {
+        Self { filename: static_filename(filename, bytes), bytes }
+    }
+
+    pub(crate) fn minified(&self) -> Vec<u8> {
+        if self.filename.ends_with(".css") {
+            minifier::css::minify(str::from_utf8(self.bytes).unwrap()).unwrap().to_string().into()
+        } else if self.filename.ends_with(".js") {
+            minifier::js::minify(str::from_utf8(self.bytes).unwrap()).to_string().into()
+        } else {
+            self.bytes.to_owned()
+        }
+    }
+
+    pub(crate) fn output_filename(&self) -> &Path {
+        &self.filename
+    }
 }
 
-/// Files related to the Source Serif 4 font.
-pub(crate) mod source_serif_4 {
-    /// The file `SourceSerif4-Regular.ttf.woff2`, the Regular variant of the Source Serif 4 font in
-    /// woff2.
-    pub(crate) static REGULAR: &[u8] =
-        include_bytes!("static/fonts/SourceSerif4-Regular.ttf.woff2");
-
-    /// The file `SourceSerif4-Bold.ttf.woff2`, the Bold variant of the Source Serif 4 font in
-    /// woff2.
-    pub(crate) static BOLD: &[u8] = include_bytes!("static/fonts/SourceSerif4-Bold.ttf.woff2");
-
-    /// The file `SourceSerif4-It.ttf.woff2`, the Italic variant of the Source Serif 4 font in
-    /// woff2.
-    pub(crate) static ITALIC: &[u8] = include_bytes!("static/fonts/SourceSerif4-It.ttf.woff2");
-
-    /// The file `SourceSerif4-LICENSE.txt`, the license text for the Source Serif 4 font.
-    pub(crate) static LICENSE: &[u8] = include_bytes!("static/fonts/SourceSerif4-LICENSE.md");
+/// The Display implementation for a StaticFile outputs its filename. This makes it
+/// convenient to interpolate static files into HTML templates.
+impl fmt::Display for StaticFile {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        write!(f, "{}", self.output_filename().display())
+    }
 }
 
-/// Files related to the Source Code Pro font.
-pub(crate) mod source_code_pro {
-    /// The file `SourceCodePro-Regular.ttf.woff2`, the Regular variant of the Source Code Pro font
-    /// in woff2.
-    pub(crate) static REGULAR: &[u8] =
-        include_bytes!("static/fonts/SourceCodePro-Regular.ttf.woff2");
-
-    /// The file `SourceCodePro-Semibold.ttf.woff2`, the Semibold variant of the Source Code Pro
-    /// font in woff2.
-    pub(crate) static SEMIBOLD: &[u8] =
-        include_bytes!("static/fonts/SourceCodePro-Semibold.ttf.woff2");
-
-    /// The file `SourceCodePro-It.ttf.woff2`, the Italic variant of the Source Code Pro font in
-    /// woff2.
-    pub(crate) static ITALIC: &[u8] = include_bytes!("static/fonts/SourceCodePro-It.ttf.woff2");
+/// Insert the provided suffix into a filename just before the extension.
+pub(crate) fn suffix_path(filename: &str, suffix: &str) -> PathBuf {
+    // We use splitn vs Path::extension here because we might get a filename
+    // like `style.min.css` and we want to process that into
+    // `style-suffix.min.css`.  Path::extension would just return `css`
+    // which would result in `style.min-suffix.css` which isn't what we
+    // want.
+    let (base, ext) = filename.split_once('.').unwrap();
+    let filename = format!("{}{}.{}", base, suffix, ext);
+    filename.into()
+}
 
-    /// The file `SourceCodePro-LICENSE.txt`, the license text of the Source Code Pro font.
-    pub(crate) static LICENSE: &[u8] = include_bytes!("static/fonts/SourceCodePro-LICENSE.txt");
+pub(crate) fn static_filename(filename: &str, contents: &[u8]) -> PathBuf {
+    let filename = filename.rsplit("/").next().unwrap();
+    suffix_path(filename, &static_suffix(contents))
 }
 
-/// Files related to the Nanum Barun Gothic font.
-///
-/// These files are used to avoid some legacy CJK serif fonts in Windows.
-///
-/// Note that the Noto Sans KR font, which was used previously but was not very readable on Windows,
-/// has been replaced by the Nanum Barun Gothic font. This is due to Windows' implementation of font
-/// rendering that distorts OpenType fonts too much.
-///
-/// The font files were generated with these commands:
-///
-/// ```sh
-/// pyftsubset NanumBarunGothic.ttf \
-/// --unicodes=U+AC00-D7AF,U+1100-11FF,U+3130-318F,U+A960-A97F,U+D7B0-D7FF \
-/// --output-file=NanumBarunGothic.ttf.woff2 --flavor=woff2
-/// ```
-pub(crate) mod nanum_barun_gothic {
-    /// The file `NanumBarunGothic.ttf.woff2`, the Regular variant of the Nanum Barun Gothic font.
-    pub(crate) static REGULAR: &[u8] = include_bytes!("static/fonts/NanumBarunGothic.ttf.woff2");
+fn static_suffix(bytes: &[u8]) -> String {
+    let mut hasher = FxHasher::default();
+    hasher.write(bytes);
+    format!("-{:016x}", hasher.finish())
+}
 
-    /// The file `NanumBarunGothic-LICENSE.txt`, the license text of the Nanum Barun Gothic font.
-    pub(crate) static LICENSE: &[u8] = include_bytes!("static/fonts/NanumBarunGothic-LICENSE.txt");
+macro_rules! static_files {
+    ($($field:ident => $file_path:literal,)+) => {
+        pub(crate) struct StaticFiles {
+            $(pub $field: StaticFile,)+
+        }
+
+        pub(crate) static STATIC_FILES: std::sync::LazyLock<StaticFiles> = std::sync::LazyLock::new(|| StaticFiles {
+            $($field: StaticFile::new($file_path, include_bytes!($file_path)),)+
+        });
+
+        pub(crate) fn for_each<E>(f: impl Fn(&StaticFile) -> Result<(), E>) -> Result<(), E> {
+            for sf in [
+            $(&STATIC_FILES.$field,)+
+            ] {
+                f(sf)?
+            }
+            Ok(())
+        }
+    }
 }
 
-/// Files related to the sidebar in rustdoc sources.
-pub(crate) mod sidebar {
-    /// File script to handle sidebar.
-    pub(crate) static SOURCE_SCRIPT: &str = include_str!("static/js/source-script.js");
+static_files! {
+    rustdoc_css => "static/css/rustdoc.css",
+    settings_css => "static/css/settings.css",
+    noscript_css => "static/css/noscript.css",
+    normalize_css => "static/css/normalize.css",
+    main_js => "static/js/main.js",
+    search_js => "static/js/search.js",
+    settings_js => "static/js/settings.js",
+    source_script_js => "static/js/source-script.js",
+    storage_js => "static/js/storage.js",
+    scrape_examples_js => "static/js/scrape-examples.js",
+    wheel_svg => "static/images/wheel.svg",
+    clipboard_svg => "static/images/clipboard.svg",
+    down_arrow_svg => "static/images/down-arrow.svg",
+    toggle_minus_png => "static/images/toggle-minus.svg",
+    toggle_plus_png => "static/images/toggle-plus.svg",
+    copyright => "static/COPYRIGHT.txt",
+    license_apache => "static/LICENSE-APACHE.txt",
+    license_mit => "static/LICENSE-MIT.txt",
+    rust_logo_svg => "static/images/rust-logo.svg",
+    rust_favicon_svg => "static/images/favicon.svg",
+    rust_favicon_png_16 => "static/images/favicon-16x16.png",
+    rust_favicon_png_32 => "static/images/favicon-32x32.png",
+    theme_light_css => "static/css/themes/light.css",
+    theme_dark_css => "static/css/themes/dark.css",
+    theme_ayu_css => "static/css/themes/ayu.css",
+    fira_sans_regular => "static/fonts/FiraSans-Regular.woff2",
+    fira_sans_medium => "static/fonts/FiraSans-Medium.woff2",
+    fira_sans_license => "static/fonts/FiraSans-LICENSE.txt",
+    source_serif_4_regular => "static/fonts/SourceSerif4-Regular.ttf.woff2",
+    source_serif_4_bold => "static/fonts/SourceSerif4-Bold.ttf.woff2",
+    source_serif_4_italic => "static/fonts/SourceSerif4-It.ttf.woff2",
+    source_serif_4_license => "static/fonts/SourceSerif4-LICENSE.md",
+    source_code_pro_regular => "static/fonts/SourceCodePro-Regular.ttf.woff2",
+    source_code_pro_semibold => "static/fonts/SourceCodePro-Semibold.ttf.woff2",
+    source_code_pro_italic => "static/fonts/SourceCodePro-It.ttf.woff2",
+    source_code_pro_license => "static/fonts/SourceCodePro-LICENSE.txt",
+    nanum_barun_gothic_regular => "static/fonts/NanumBarunGothic.ttf.woff2",
+    nanum_barun_gothic_license => "static/fonts/NanumBarunGothic-LICENSE.txt",
 }
+
+pub(crate) static SCRAPE_EXAMPLES_HELP_MD: &str = include_str!("static/js/scrape-examples.js");
diff --git a/src/librustdoc/html/templates/page.html b/src/librustdoc/html/templates/page.html
index c3238691687..4efcfc510a2 100644
--- a/src/librustdoc/html/templates/page.html
+++ b/src/librustdoc/html/templates/page.html
@@ -7,48 +7,44 @@
     <meta name="description" content="{{page.description}}"> {#- -#}
     <meta name="keywords" content="{{page.keywords}}"> {#- -#}
     <title>{{page.title}}</title> {#- -#}
-    <link rel="preload" as="font" type="font/woff2" crossorigin href="{{static_root_path|safe}}SourceSerif4-Regular.ttf.woff2"> {#- -#}
-    <link rel="preload" as="font" type="font/woff2" crossorigin href="{{static_root_path|safe}}FiraSans-Regular.woff2"> {#- -#}
-    <link rel="preload" as="font" type="font/woff2" crossorigin href="{{static_root_path|safe}}FiraSans-Medium.woff2"> {#- -#}
-    <link rel="preload" as="font" type="font/woff2" crossorigin href="{{static_root_path|safe}}SourceCodePro-Regular.ttf.woff2"> {#- -#}
-    <link rel="preload" as="font" type="font/woff2" crossorigin href="{{static_root_path|safe}}SourceSerif4-Bold.ttf.woff2"> {#- -#}
-    <link rel="preload" as="font" type="font/woff2" crossorigin href="{{static_root_path|safe}}SourceCodePro-Semibold.ttf.woff2"> {#- -#}
+    <link rel="preload" as="font" type="font/woff2" crossorigin href="{{static_root_path|safe}}{{files.source_serif_4_regular}}"> {#- -#}
+    <link rel="preload" as="font" type="font/woff2" crossorigin href="{{static_root_path|safe}}{{files.fira_sans_regular}}"> {#- -#}
+    <link rel="preload" as="font" type="font/woff2" crossorigin href="{{static_root_path|safe}}{{files.fira_sans_medium}}"> {#- -#}
+    <link rel="preload" as="font" type="font/woff2" crossorigin href="{{static_root_path|safe}}{{files.source_code_pro_regular}}"> {#- -#}
+    <link rel="preload" as="font" type="font/woff2" crossorigin href="{{static_root_path|safe}}{{files.source_serif_4_bold}}"> {#- -#}
+    <link rel="preload" as="font" type="font/woff2" crossorigin href="{{static_root_path|safe}}{{files.source_code_pro_semibold}}"> {#- -#}
     <link rel="stylesheet" {# -#}
-          href="{{static_root_path|safe}}normalize{{page.resource_suffix}}.css"> {#- -#}
+          href="{{static_root_path|safe}}{{files.normalize_css}}"> {#- -#}
     <link rel="stylesheet" {# -#}
-          href="{{static_root_path|safe}}rustdoc{{page.resource_suffix}}.css" {# -#}
+          href="{{static_root_path|safe}}{{files.rustdoc_css}}" {# -#}
           id="mainThemeStyle"> {#- -#}
+    <link rel="stylesheet" id="themeStyle" href="{{static_root_path|safe}}{{files.theme_light_css}}"> {#- -#}
+    <link rel="stylesheet" disabled href="{{static_root_path|safe}}{{files.theme_dark_css}}"> {#- -#}
+    <link rel="stylesheet" disabled href="{{static_root_path|safe}}{{files.theme_ayu_css}}"> {#- -#}
     {%- for theme in themes -%}
-        <link rel="stylesheet" {# -#}
-            href="{{static_root_path|safe}}{{theme}}{{page.resource_suffix}}.css" {# -#}
-        {%- if theme == "light" -%}
-            id="themeStyle"
-        {%- else -%}
-            disabled
-        {%- endif -%}
-        >
+        <link rel="stylesheet" disabled href="{{page.root_path|safe}}{{theme}}{{page.resource_suffix}}.css"> {#- -#}
     {%- endfor -%}
     <script id="default-settings" {# -#}
       {% for (k, v) in layout.default_settings %}
         data-{{k}}="{{v}}"
       {%- endfor -%}
     ></script> {#- -#}
-    <script src="{{static_root_path|safe}}storage{{page.resource_suffix}}.js"></script> {#- -#}
+    <script src="{{static_root_path|safe}}{{files.storage_js}}"></script> {#- -#}
     {%- if page.css_class.contains("crate") -%}
     <script defer src="{{page.root_path|safe}}crates{{page.resource_suffix}}.js"></script> {#- -#}
     {%- else if page.css_class == "source" -%}
-    <script defer src="{{static_root_path|safe}}source-script{{page.resource_suffix}}.js"></script> {#- -#}
+    <script defer src="{{static_root_path|safe}}{{files.source_script_js}}"></script> {#- -#}
     <script defer src="{{page.root_path|safe}}source-files{{page.resource_suffix}}.js"></script> {#- -#}
     {%- else if !page.css_class.contains("mod") -%}
     <script defer src="sidebar-items{{page.resource_suffix}}.js"></script> {#- -#}
     {%- endif -%}
-    <script defer src="{{static_root_path|safe}}main{{page.resource_suffix}}.js"></script> {#- -#}
+    <script defer src="{{static_root_path|safe}}{{files.main_js}}"></script> {#- -#}
     {%- if layout.scrape_examples_extension -%}
-    <script defer src="{{page.root_path|safe}}scrape-examples{{page.resource_suffix}}.js"></script> {#- -#}
+    <script defer src="{{page.root_path|safe}}{{files.scrape_examples_js}}"></script> {#- -#}
     {%- endif -%}
     <noscript> {#- -#}
         <link rel="stylesheet" {# -#}
-           href="{{static_root_path|safe}}noscript{{page.resource_suffix}}.css"> {#- -#}
+           href="{{static_root_path|safe}}{{files.noscript_css}}"> {#- -#}
     </noscript> {#- -#}
     {%- if layout.css_file_extension.is_some() -%}
         <link rel="stylesheet" {# -#}
@@ -58,11 +54,11 @@
         <link rel="icon" href="{{layout.favicon}}"> {#- -#}
     {%- else -%}
         <link rel="alternate icon" type="image/png" {# -#}
-            href="{{static_root_path|safe}}favicon-16x16{{page.resource_suffix}}.png"> {#- -#}
+            href="{{static_root_path|safe}}{{files.rust_favicon_png_16}}"> {#- -#}
         <link rel="alternate icon" type="image/png" {# -#}
-            href="{{static_root_path|safe}}favicon-32x32{{page.resource_suffix}}.png"> {#- -#}
+            href="{{static_root_path|safe}}{{files.rust_favicon_png_32}}"> {#- -#}
         <link rel="icon" type="image/svg+xml" {# -#}
-            href="{{static_root_path|safe}}favicon{{page.resource_suffix}}.svg"> {#- -#}
+            href="{{static_root_path|safe}}{{files.rust_favicon_svg}}"> {#- -#}
     {%- endif -%}
     {{- layout.external_html.in_header|safe -}}
 </head> {#- -#}
@@ -81,7 +77,7 @@
             {%- if !layout.logo.is_empty() -%}
                 <img src="{{layout.logo}}" alt="logo"> {#- -#}
             {%- else -%}
-                <img class="rust-logo" src="{{static_root_path|safe}}rust-logo{{page.resource_suffix}}.svg" alt="logo"> {#- -#}
+                <img class="rust-logo" src="{{static_root_path|safe}}{{files.rust_logo_svg}}" alt="logo"> {#- -#}
             {%- endif -%}
             </div> {#- -#}
         </a> {#- -#}
@@ -95,7 +91,7 @@
                 {%- if !layout.logo.is_empty()  %}
                     <img src="{{layout.logo}}" alt="logo"> {#- -#}
                 {%- else -%}
-                    <img class="rust-logo" src="{{static_root_path|safe}}rust-logo{{page.resource_suffix}}.svg" alt="logo"> {#- -#}
+                    <img class="rust-logo" src="{{static_root_path|safe}}{{files.rust_logo_svg}}" alt="logo"> {#- -#}
                 {%- endif -%}
             </div> {#- -#}
         </a> {#- -#}
@@ -110,7 +106,7 @@
                     {%- if !layout.logo.is_empty()  %}
                         <img src="{{layout.logo}}" alt="logo"> {#- -#}
                     {%- else -%}
-                        <img class="rust-logo" src="{{static_root_path|safe}}rust-logo{{page.resource_suffix}}.svg" alt="logo"> {#- -#}
+                        <img class="rust-logo" src="{{static_root_path|safe}}{{files.rust_logo_svg}}" alt="logo"> {#- -#}
                     {%- endif -%}
                 </a> {#- -#}
                 {%- endif -%}
@@ -129,7 +125,7 @@
                     <div id="settings-menu" tabindex="-1"> {#- -#}
                         <a href="{{page.root_path|safe}}settings.html" title="settings"> {#- -#}
                             <img width="22" height="22" alt="Change settings" {# -#}
-                             src="{{static_root_path|safe}}wheel{{page.resource_suffix}}.svg"> {#- -#}
+                            src="{{static_root_path|safe}}{{files.wheel_svg}}"> {#- -#}
                         </a> {#- -#}
                     </div> {#- -#}
                 </form> {#- -#}
@@ -140,10 +136,14 @@
     {{- layout.external_html.after_content|safe -}}
     <div id="rustdoc-vars" {# -#}
          data-root-path="{{page.root_path|safe}}" {# -#}
+         data-static-root-path="{{static_root_path|safe}}" {# -#}
          data-current-crate="{{layout.krate}}" {# -#}
          data-themes="{{themes|join(",") }}" {# -#}
          data-resource-suffix="{{page.resource_suffix}}" {# -#}
          data-rustdoc-version="{{rustdoc_version}}" {# -#}
+         data-search-js="{{files.search_js}}" {# -#}
+         data-settings-js="{{files.settings_js}}" {# -#}
+         data-settings-css="{{files.settings_css}}" {# -#}
     > {#- -#}
     </div> {#- -#}
 </body> {#- -#}
diff --git a/src/librustdoc/html/templates/print_item.html b/src/librustdoc/html/templates/print_item.html
index e497b619366..611d124d4b9 100644
--- a/src/librustdoc/html/templates/print_item.html
+++ b/src/librustdoc/html/templates/print_item.html
@@ -7,7 +7,7 @@
         {%- endfor -%}
         <a class="{{item_type}}" href="#">{{name}}</a> {#- -#}
         <button id="copy-path" onclick="copy_path(this)" title="Copy item path to clipboard"> {#- -#}
-            <img src="{{static_root_path|safe}}clipboard{{page.resource_suffix}}.svg" {# -#}
+        <img src="{{static_root_path|safe}}{{clipboard_svg}}" {# -#}
                 width="19" height="18" {# -#}
                 alt="Copy item path"> {#- -#}
         </button> {#- -#}
diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs
index cb8b7c18029..091a1ba70ca 100644
--- a/src/librustdoc/json/conversions.rs
+++ b/src/librustdoc/json/conversions.rs
@@ -485,7 +485,7 @@ impl FromWithTcx<clean::Type> for Type {
             BareFunction(f) => Type::FunctionPointer(Box::new((*f).into_tcx(tcx))),
             Tuple(t) => Type::Tuple(t.into_tcx(tcx)),
             Slice(t) => Type::Slice(Box::new((*t).into_tcx(tcx))),
-            Array(t, s) => Type::Array { type_: Box::new((*t).into_tcx(tcx)), len: s },
+            Array(t, s) => Type::Array { type_: Box::new((*t).into_tcx(tcx)), len: s.to_string() },
             ImplTrait(g) => Type::ImplTrait(g.into_tcx(tcx)),
             Infer => Type::Infer,
             RawPointer(mutability, type_) => Type::RawPointer {
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index 4cf9435d9c8..1982c066b6f 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -469,9 +469,6 @@ fn opts() -> Vec<RustcOptGroup> {
         stable("json", |o| {
             o.optopt("", "json", "Configure the structure of JSON diagnostics", "CONFIG")
         }),
-        unstable("disable-minification", |o| {
-            o.optflagmulti("", "disable-minification", "Disable minification applied on JS files")
-        }),
         stable("allow", |o| o.optmulti("A", "allow", "Set lint allowed", "LINT")),
         stable("warn", |o| o.optmulti("W", "warn", "Set lint warnings", "LINT")),
         stable("force-warn", |o| o.optmulti("", "force-warn", "Set lint force-warn", "LINT")),
@@ -610,6 +607,7 @@ fn opts() -> Vec<RustcOptGroup> {
             )
         }),
         // deprecated / removed options
+        unstable("disable-minification", |o| o.optflagmulti("", "disable-minification", "removed")),
         stable("plugin-path", |o| {
             o.optmulti(
                 "",
diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs
index 0bd0dbbeb70..37a28b6b7bd 100644
--- a/src/librustdoc/passes/collect_intra_doc_links.rs
+++ b/src/librustdoc/passes/collect_intra_doc_links.rs
@@ -402,6 +402,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
             })
             .and_then(|self_id| match tcx.def_kind(self_id) {
                 DefKind::Impl => self.def_id_to_res(self_id),
+                DefKind::Use => None,
                 def_kind => Some(Res::Def(def_kind, self_id)),
             })
     }
@@ -1772,7 +1773,6 @@ fn resolution_failure(
 
                     // Otherwise, it must be an associated item or variant
                     let res = partial_res.expect("None case was handled by `last_found_module`");
-                    let name = res.name(tcx);
                     let kind = match res {
                         Res::Def(kind, _) => Some(kind),
                         Res::Primitive(_) => None,
@@ -1814,6 +1814,7 @@ fn resolution_failure(
                     } else {
                         "associated item"
                     };
+                    let name = res.name(tcx);
                     let note = format!(
                         "the {} `{}` has no {} named `{}`",
                         res.descr(),
diff --git a/src/test/assembly/strict_provenance.rs b/src/test/assembly/strict_provenance.rs
new file mode 100644
index 00000000000..01f1957d5f6
--- /dev/null
+++ b/src/test/assembly/strict_provenance.rs
@@ -0,0 +1,37 @@
+// assembly-output: emit-asm
+// compile-flags: -Copt-level=1
+// only-x86_64
+// min-llvm-version: 15.0
+#![crate_type = "rlib"]
+
+// CHECK-LABEL: old_style
+// CHECK: movq %{{.*}}, %rax
+// CHECK: orq $1, %rax
+// CHECK: retq
+#[no_mangle]
+pub fn old_style(a: *mut u8) -> *mut u8 {
+    (a as usize | 1) as *mut u8
+}
+
+// CHECK-LABEL: cheri_compat
+// CHECK: movq %{{.*}}, %rax
+// CHECK: orq $1, %rax
+// CHECK: retq
+#[no_mangle]
+pub fn cheri_compat(a: *mut u8) -> *mut u8 {
+    let old = a as usize;
+    let new = old | 1;
+    let diff = new.wrapping_sub(old);
+    a.wrapping_add(diff)
+}
+
+// CHECK-LABEL: definitely_not_a_null_pointer
+// CHECK: movq %{{.*}}, %rax
+// CHECK: orq $1, %rax
+// CHECK: retq
+#[no_mangle]
+pub fn definitely_not_a_null_pointer(a: *mut u8) -> *mut u8 {
+    let old = a as usize;
+    let new = old | 1;
+    a.wrapping_sub(old).wrapping_add(new)
+}
diff --git a/src/test/codegen/auxiliary/static_dllimport_aux.rs b/src/test/codegen/auxiliary/static_dllimport_aux.rs
new file mode 100644
index 00000000000..afb0dc42f44
--- /dev/null
+++ b/src/test/codegen/auxiliary/static_dllimport_aux.rs
@@ -0,0 +1,13 @@
+use std::sync::atomic::{AtomicPtr, Ordering};
+
+#[inline(always)]
+pub fn memrchr() {
+    fn detect() {}
+
+    static CROSS_CRATE_STATIC_ITEM: AtomicPtr<()> = AtomicPtr::new(detect as *mut ());
+
+    unsafe {
+        let fun = CROSS_CRATE_STATIC_ITEM.load(Ordering::SeqCst);
+        std::mem::transmute::<*mut (), fn()>(fun)()
+    }
+}
diff --git a/src/test/codegen/avr/avr-func-addrspace.rs b/src/test/codegen/avr/avr-func-addrspace.rs
index a038dfe76f7..cbbcfad3ef4 100644
--- a/src/test/codegen/avr/avr-func-addrspace.rs
+++ b/src/test/codegen/avr/avr-func-addrspace.rs
@@ -19,6 +19,8 @@ pub trait Sized { }
 pub trait Copy { }
 #[lang = "receiver"]
 pub trait Receiver { }
+#[lang = "tuple_trait"]
+pub trait Tuple { }
 
 pub struct Result<T, E> { _a: T, _b: E }
 
@@ -29,7 +31,7 @@ impl Copy for &usize {}
 pub unsafe fn drop_in_place<T: ?Sized>(_: *mut T) {}
 
 #[lang = "fn_once"]
-pub trait FnOnce<Args> {
+pub trait FnOnce<Args: Tuple> {
     #[lang = "fn_once_output"]
     type Output;
 
@@ -37,24 +39,16 @@ pub trait FnOnce<Args> {
 }
 
 #[lang = "fn_mut"]
-pub trait FnMut<Args> : FnOnce<Args> {
+pub trait FnMut<Args: Tuple> : FnOnce<Args> {
     extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output;
 }
 
 #[lang = "fn"]
-pub trait Fn<Args>: FnOnce<Args> {
+pub trait Fn<Args: Tuple>: FnOnce<Args> {
     /// Performs the call operation.
     extern "rust-call" fn call(&self, args: Args) -> Self::Output;
 }
 
-impl<'a, A, R> FnOnce<A> for &'a fn(A) -> R {
-    type Output = R;
-
-    extern "rust-call" fn call_once(self, args: A) -> R {
-        (*self)(args)
-    }
-}
-
 pub static mut STORAGE_FOO: fn(&usize, &mut u32) -> Result<(), ()> = arbitrary_black_box;
 pub static mut STORAGE_BAR: u32 = 12;
 
diff --git a/src/test/codegen/issue-81408-dllimport-thinlto-windows.rs b/src/test/codegen/issue-81408-dllimport-thinlto-windows.rs
new file mode 100644
index 00000000000..0b6ab4f7ecb
--- /dev/null
+++ b/src/test/codegen/issue-81408-dllimport-thinlto-windows.rs
@@ -0,0 +1,15 @@
+// compile-flags: -O -C lto=thin -C prefer-dynamic=no
+// only-windows
+// aux-build:static_dllimport_aux.rs
+
+// Test that on Windows, when performing ThinLTO, we do not mark cross-crate static items with
+// dllimport because lld does not fix the symbol names for us.
+
+extern crate static_dllimport_aux;
+
+// CHECK-LABEL: @{{.+}}CROSS_CRATE_STATIC_ITEM{{.+}} =
+// CHECK-SAME: external local_unnamed_addr global %"{{.+}}AtomicPtr
+
+pub fn main() {
+    static_dllimport_aux::memrchr();
+}
diff --git a/src/test/debuginfo/basic-types.rs b/src/test/debuginfo/basic-types.rs
index 07d33be2a07..9e82f071469 100644
--- a/src/test/debuginfo/basic-types.rs
+++ b/src/test/debuginfo/basic-types.rs
@@ -47,7 +47,6 @@
 // gdbg-check:$15 = {data_ptr = [...] "Hello, World!", length = 13}
 // gdbr-check:$15 = "Hello, World!"
 
-
 // === LLDB TESTS ==================================================================================
 
 // lldb-command:run
@@ -96,7 +95,6 @@
 // lldbg-check:[...]$12 = 3.5
 // lldbr-check:(f64) f64 = 3.5
 
-
 // === CDB TESTS ===================================================================================
 
 // cdb-command:g
@@ -131,7 +129,7 @@
 // cdb-command:.enable_unicode 1
 // FIXME(#88840): The latest version of the Windows SDK broke the visualizer for str.
 // cdb-command:dx  s
-// cdb-check:s                : [...] [Type: str]
+// cdb-check:s                : [...] [Type: ref$<str$>]
 
 #![allow(unused_variables)]
 #![feature(omit_gdb_pretty_printer_section)]
@@ -156,4 +154,6 @@ fn main() {
     _zzz(); // #break
 }
 
-fn _zzz() {()}
+fn _zzz() {
+    ()
+}
diff --git a/src/test/debuginfo/msvc-pretty-enums.rs b/src/test/debuginfo/msvc-pretty-enums.rs
index 7f1be6f2784..d66e4c660f7 100644
--- a/src/test/debuginfo/msvc-pretty-enums.rs
+++ b/src/test/debuginfo/msvc-pretty-enums.rs
@@ -116,13 +116,13 @@
 // cdb-check: niche_w_fields_3_niche5,d : F [Type: enum2$<msvc_pretty_enums::NicheLayoutWithFields3>]
 
 // cdb-command: dx -r3 niche_w_fields_std_result_ok,d
-// cdb-check: niche_w_fields_std_result_ok,d : Ok [Type: enum2$<core::result::Result<alloc::boxed::Box<slice$<u8>,alloc::alloc::Global>,u64> >]
-// cdb-check:    [+0x[...]] __0              [Type: alloc::boxed::Box<slice$<u8>,alloc::alloc::Global>]
+// cdb-check: niche_w_fields_std_result_ok,d : Ok [Type: enum2$<core::result::Result<alloc::boxed::Box<slice2$<u8>,alloc::alloc::Global>,u64> >]
+// cdb-check:    [+0x[...]] __0              [Type: alloc::boxed::Box<slice2$<u8>,alloc::alloc::Global>]
 // cdb-check:        [+0x[...]] data_ptr         : [...]
 // cdb-check:        [+0x[...]] length           : 3 [...]
 
 // cdb-command: dx -r3 niche_w_fields_std_result_err,d
-// cdb-check: niche_w_fields_std_result_err,d : Err [Type: enum2$<core::result::Result<alloc::boxed::Box<slice$<u8>,alloc::alloc::Global>,u64> >]
+// cdb-check: niche_w_fields_std_result_err,d : Err [Type: enum2$<core::result::Result<alloc::boxed::Box<slice2$<u8>,alloc::alloc::Global>,u64> >]
 // cdb-check:    [+0x[...]] __0              : 789 [Type: unsigned __int64]
 
 // cdb-command: dx -r2 arbitrary_discr1,d
diff --git a/src/test/debuginfo/msvc-scalarpair-params.rs b/src/test/debuginfo/msvc-scalarpair-params.rs
index 9630952cbaa..ae67f698151 100644
--- a/src/test/debuginfo/msvc-scalarpair-params.rs
+++ b/src/test/debuginfo/msvc-scalarpair-params.rs
@@ -38,14 +38,14 @@
 // cdb-command: g
 
 // cdb-command: dx s
-// cdb-check:s                : "this is a static str" [Type: str]
+// cdb-check:s                : "this is a static str" [Type: ref$<str$>]
 // cdb-check:    [len]            : 0x14 [Type: unsigned [...]]
 // cdb-check:    [chars]
 
 // cdb-command: g
 
 // cdb-command: dx s
-// cdb-check:s                : { len=0x5 } [Type: slice$<u8>]
+// cdb-check:s                : { len=0x5 } [Type: ref$<slice2$<u8> >]
 // cdb-check:    [len]            : 0x5 [Type: unsigned [...]]
 // cdb-check:    [0]              : 0x1 [Type: unsigned char]
 // cdb-check:    [1]              : 0x2 [Type: unsigned char]
diff --git a/src/test/debuginfo/pretty-std.rs b/src/test/debuginfo/pretty-std.rs
index a51b37205e8..d8c6344e0b6 100644
--- a/src/test/debuginfo/pretty-std.rs
+++ b/src/test/debuginfo/pretty-std.rs
@@ -69,7 +69,7 @@
 // cdb-command: g
 
 // cdb-command: dx slice,d
-// cdb-check:slice,d          : { len=4 } [Type: slice$<i32>]
+// cdb-check:slice,d          : { len=4 } [Type: ref$<slice2$<i32> >]
 // cdb-check:    [len]            : 4 [Type: [...]]
 // cdb-check:    [0]              : 0 [Type: int]
 // cdb-check:    [1]              : 1 [Type: int]
@@ -86,7 +86,7 @@
 // cdb-check:    [3]              : 7 [Type: unsigned __int64]
 
 // cdb-command: dx str_slice
-// cdb-check:str_slice        : "IAMA string slice!" [Type: str]
+// cdb-check:str_slice        : "IAMA string slice!" [Type: ref$<str$>]
 
 // cdb-command: dx string
 // cdb-check:string           : "IAMA string!" [Type: [...]::String]
diff --git a/src/test/debuginfo/rc_arc.rs b/src/test/debuginfo/rc_arc.rs
index c05c565d956..5d5492d7217 100644
--- a/src/test/debuginfo/rc_arc.rs
+++ b/src/test/debuginfo/rc_arc.rs
@@ -57,7 +57,7 @@
 // cdb-check:    [Weak reference count] : 2 [Type: core::cell::Cell<usize>]
 
 // cdb-command:dx slice_rc,d
-// cdb-check:slice_rc,d       : { len=3 } [Type: alloc::rc::Rc<slice$<u32> >]
+// cdb-check:slice_rc,d       : { len=3 } [Type: alloc::rc::Rc<slice2$<u32> >]
 // cdb-check:    [Length]         : 3 [Type: [...]]
 // cdb-check:    [Reference count] : 41 [Type: core::cell::Cell<usize>]
 // cdb-check:    [Weak reference count] : 2 [Type: core::cell::Cell<usize>]
@@ -66,7 +66,7 @@
 // cdb-check:    [2]              : 3 [Type: u32]
 
 // cdb-command:dx slice_rc_weak,d
-// cdb-check:slice_rc_weak,d  : { len=3 } [Type: alloc::rc::Weak<slice$<u32> >]
+// cdb-check:slice_rc_weak,d  : { len=3 } [Type: alloc::rc::Weak<slice2$<u32> >]
 // cdb-check:    [Length]         : 3 [Type: [...]]
 // cdb-check:    [Reference count] : 41 [Type: core::cell::Cell<usize>]
 // cdb-check:    [Weak reference count] : 2 [Type: core::cell::Cell<usize>]
@@ -85,7 +85,7 @@
 // cdb-check:    [Weak reference count] : 2 [Type: core::sync::atomic::AtomicUsize]
 
 // cdb-command:dx slice_arc,d
-// cdb-check:slice_arc,d      : { len=3 } [Type: alloc::sync::Arc<slice$<u32> >]
+// cdb-check:slice_arc,d      : { len=3 } [Type: alloc::sync::Arc<slice2$<u32> >]
 // cdb-check:    [Length]         : 3 [Type: [...]]
 // cdb-check:    [Reference count] : 61 [Type: core::sync::atomic::AtomicUsize]
 // cdb-check:    [Weak reference count] : 2 [Type: core::sync::atomic::AtomicUsize]
@@ -94,7 +94,7 @@
 // cdb-check:    [2]              : 6 [Type: u32]
 
 // cdb-command:dx slice_arc_weak,d
-// cdb-check:slice_arc_weak,d : { len=3 } [Type: alloc::sync::Weak<slice$<u32> >]
+// cdb-check:slice_arc_weak,d : { len=3 } [Type: alloc::sync::Weak<slice2$<u32> >]
 // cdb-check:    [Length]         : 3 [Type: [...]]
 // cdb-check:    [Reference count] : 61 [Type: core::sync::atomic::AtomicUsize]
 // cdb-check:    [Weak reference count] : 2 [Type: core::sync::atomic::AtomicUsize]
diff --git a/src/test/debuginfo/result-types.rs b/src/test/debuginfo/result-types.rs
index cdac47a784d..f1944fa38d2 100644
--- a/src/test/debuginfo/result-types.rs
+++ b/src/test/debuginfo/result-types.rs
@@ -7,12 +7,12 @@
 // cdb-command: g
 
 // cdb-command: dx x,d
-// cdb-check:x,d              : Ok [Type: enum2$<core::result::Result<i32,str> >]
+// cdb-check:x,d              : Ok [Type: enum2$<core::result::Result<i32,ref$<str$> > >]
 // cdb-check:    [...] __0              : -3 [Type: int]
 
 // cdb-command: dx y
-// cdb-check:y                : Err [Type: enum2$<core::result::Result<i32,str> >]
-// cdb-check:    [...] __0              : "Some error message" [Type: str]
+// cdb-check:y                : Err [Type: enum2$<core::result::Result<i32,ref$<str$> > >]
+// cdb-check:    [...] __0              : "Some error message" [Type: ref$<str$>]
 
 fn main() {
     let x: Result<i32, &str> = Ok(-3);
diff --git a/src/test/debuginfo/type-names.rs b/src/test/debuginfo/type-names.rs
index 9cc99d7767c..d7b79a845d2 100644
--- a/src/test/debuginfo/type-names.rs
+++ b/src/test/debuginfo/type-names.rs
@@ -95,7 +95,7 @@
 // gdb-check:type = &[usize]
 
 // gdb-command:whatis slice2
-// gdb-check:type = &[type_names::mod1::Enum2]
+// gdb-check:type = &mut [type_names::mod1::Enum2]
 
 // TRAITS
 // gdb-command:whatis box_trait
@@ -218,8 +218,8 @@
 // cdb-check:struct alloc::vec::Vec<usize,alloc::alloc::Global> vec1 = [...]
 // cdb-check:struct alloc::vec::Vec<enum2$<type_names::mod1::Enum2>,alloc::alloc::Global> vec2 = [...]
 // cdb-command:dv /t slice*
-// cdb-check:struct slice$<usize> slice1 = [...]
-// cdb-check:struct slice$<enum2$<type_names::mod1::Enum2> > slice2 = [...]
+// cdb-check:struct ref$<slice2$<usize> > slice1 = [...]
+// cdb-check:struct ref_mut$<slice2$<enum2$<type_names::mod1::Enum2> > > slice2 = [...]
 
 // TRAITS
 // cdb-command:dv /t *_trait
@@ -417,8 +417,8 @@ fn main() {
 
     let vec1 = vec![0_usize, 2, 3];
     let slice1 = &*vec1;
-    let vec2 = vec![mod1::Enum2::Variant2(Struct1)];
-    let slice2 = &*vec2;
+    let mut vec2 = vec![mod1::Enum2::Variant2(Struct1)];
+    let slice2 = &mut *vec2;
 
     // Trait Objects
     let box_trait = Box::new(0_isize) as Box<dyn Trait1>;
diff --git a/src/test/debuginfo/unsized.rs b/src/test/debuginfo/unsized.rs
index 7cb0002ca51..b1ec9b06830 100644
--- a/src/test/debuginfo/unsized.rs
+++ b/src/test/debuginfo/unsized.rs
@@ -32,13 +32,13 @@
 
 // cdb-command: g
 // cdb-command:dx a
-// cdb-check:a                [Type: ref$<unsized::Foo<slice$<u8> > >]
-// cdb-check:    [+0x000] data_ptr         : 0x[...] [Type: unsized::Foo<slice$<u8> > *]
+// cdb-check:a                [Type: ref$<unsized::Foo<slice2$<u8> > >]
+// cdb-check:    [+0x000] data_ptr         : 0x[...] [Type: unsized::Foo<slice2$<u8> > *]
 // cdb-check:    [...] length           : 0x4 [Type: unsigned [...]int[...]
 
 // cdb-command:dx b
-// cdb-check:b                [Type: ref$<unsized::Foo<unsized::Foo<slice$<u8> > > >]
-// cdb-check:    [+0x000] data_ptr         : 0x[...] [Type: unsized::Foo<unsized::Foo<slice$<u8> > > *]
+// cdb-check:b                [Type: ref$<unsized::Foo<unsized::Foo<slice2$<u8> > > >]
+// cdb-check:    [+0x000] data_ptr         : 0x[...] [Type: unsized::Foo<unsized::Foo<slice2$<u8> > > *]
 // cdb-check:    [...] length           : 0x4 [Type: unsigned [...]int[...]
 
 // cdb-command:dx c
@@ -53,8 +53,8 @@
 // cdb-check:[...] vtable           : 0x[...] [Type: unsigned [...]int[...] (*)[3]]
 
 // cdb-command:dx tuple_slice
-// cdb-check:tuple_slice      [Type: ref$<tuple$<i32,i32,slice$<i32> > >]
-// cdb-check:    [+0x000] data_ptr         : 0x[...] [Type: tuple$<i32,i32,slice$<i32> > *]
+// cdb-check:tuple_slice      [Type: ref$<tuple$<i32,i32,slice2$<i32> > >]
+// cdb-check:    [+0x000] data_ptr         : 0x[...] [Type: tuple$<i32,i32,slice2$<i32> > *]
 // cdb-check:    [...] length           : 0x2 [Type: unsigned [...]int[...]
 
 // cdb-command:dx tuple_dyn
diff --git a/src/test/incremental/hashes/extern_mods.rs b/src/test/incremental/hashes/extern_mods.rs
index ff79acc7f63..3121abbea36 100644
--- a/src/test/incremental/hashes/extern_mods.rs
+++ b/src/test/incremental/hashes/extern_mods.rs
@@ -128,7 +128,7 @@ extern "C" {
 // Change calling convention ---------------------------------------------------
 #[cfg(any(cfail1,cfail4))]
 extern "C" {
-    pub fn change_calling_convention(c: i32);
+    pub fn change_calling_convention(c: (i32,));
 }
 
 #[cfg(not(any(cfail1,cfail4)))]
@@ -137,7 +137,7 @@ extern "C" {
 #[rustc_clean(cfg = "cfail5", except = "hir_owner,hir_owner_nodes")]
 #[rustc_clean(cfg = "cfail6")]
 extern "rust-call" {
-    pub fn change_calling_convention(c: i32);
+    pub fn change_calling_convention(c: (i32,));
 }
 
 // Make function public --------------------------------------------------------
diff --git a/src/test/mir-opt/building/custom/references.immut_ref.built.after.mir b/src/test/mir-opt/building/custom/references.immut_ref.built.after.mir
new file mode 100644
index 00000000000..4a5ddde4081
--- /dev/null
+++ b/src/test/mir-opt/building/custom/references.immut_ref.built.after.mir
@@ -0,0 +1,14 @@
+// MIR for `immut_ref` after built
+
+fn immut_ref(_1: &i32) -> &i32 {
+    let mut _0: &i32;                    // return place in scope 0 at $DIR/references.rs:+0:30: +0:34
+    let mut _2: *const i32;              // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
+
+    bb0: {
+        _2 = &raw const (*_1);           // scope 0 at $DIR/references.rs:+0:1: +0:34
+        Retag([raw] _2);                 // scope 0 at $DIR/references.rs:+0:1: +0:34
+        _0 = &(*_2);                     // scope 0 at $DIR/references.rs:+0:1: +0:34
+        Retag(_0);                       // scope 0 at $DIR/references.rs:+0:1: +0:34
+        return;                          // scope 0 at $DIR/references.rs:+0:1: +0:34
+    }
+}
diff --git a/src/test/mir-opt/building/custom/references.mut_ref.built.after.mir b/src/test/mir-opt/building/custom/references.mut_ref.built.after.mir
new file mode 100644
index 00000000000..ec8509f69d1
--- /dev/null
+++ b/src/test/mir-opt/building/custom/references.mut_ref.built.after.mir
@@ -0,0 +1,14 @@
+// MIR for `mut_ref` after built
+
+fn mut_ref(_1: &mut i32) -> &mut i32 {
+    let mut _0: &mut i32;                // return place in scope 0 at $DIR/references.rs:+0:32: +0:40
+    let mut _2: *mut i32;                // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
+
+    bb0: {
+        _2 = &raw mut (*_1);             // scope 0 at $DIR/references.rs:+0:1: +0:40
+        Retag([raw] _2);                 // scope 0 at $DIR/references.rs:+0:1: +0:40
+        _0 = &mut (*_2);                 // scope 0 at $DIR/references.rs:+0:1: +0:40
+        Retag(_0);                       // scope 0 at $DIR/references.rs:+0:1: +0:40
+        return;                          // scope 0 at $DIR/references.rs:+0:1: +0:40
+    }
+}
diff --git a/src/test/mir-opt/building/custom/references.rs b/src/test/mir-opt/building/custom/references.rs
new file mode 100644
index 00000000000..dee85722e86
--- /dev/null
+++ b/src/test/mir-opt/building/custom/references.rs
@@ -0,0 +1,43 @@
+#![feature(custom_mir, core_intrinsics)]
+
+extern crate core;
+use core::intrinsics::mir::*;
+use core::ptr::{addr_of, addr_of_mut};
+
+// EMIT_MIR references.mut_ref.built.after.mir
+#[custom_mir(dialect = "runtime", phase = "optimized")]
+pub fn mut_ref(x: &mut i32) -> &mut i32 {
+    mir!(
+        let t: *mut i32;
+
+        {
+            t = addr_of_mut!(*x);
+            RetagRaw(t);
+            RET = &mut *t;
+            Retag(RET);
+            Return()
+        }
+    )
+}
+
+// EMIT_MIR references.immut_ref.built.after.mir
+#[custom_mir(dialect = "runtime", phase = "optimized")]
+pub fn immut_ref(x: &i32) -> &i32 {
+    mir!(
+        let t: *const i32;
+
+        {
+            t = addr_of!(*x);
+            RetagRaw(t);
+            RET = & *t;
+            Retag(RET);
+            Return()
+        }
+    )
+}
+
+fn main() {
+    let mut x = 5;
+    assert_eq!(*mut_ref(&mut x), 5);
+    assert_eq!(*immut_ref(&x), 5);
+}
diff --git a/src/test/mir-opt/building/custom/simple_assign.rs b/src/test/mir-opt/building/custom/simple_assign.rs
new file mode 100644
index 00000000000..ec6dbe1d052
--- /dev/null
+++ b/src/test/mir-opt/building/custom/simple_assign.rs
@@ -0,0 +1,37 @@
+#![feature(custom_mir, core_intrinsics)]
+
+extern crate core;
+use core::intrinsics::mir::*;
+
+// EMIT_MIR simple_assign.simple.built.after.mir
+#[custom_mir(dialect = "built")]
+pub fn simple(x: i32) -> i32 {
+    mir!(
+        let temp1: i32;
+        let temp2: _;
+
+        {
+            temp1 = x;
+            Goto(exit)
+        }
+
+        exit = {
+            temp2 = Move(temp1);
+            RET = temp2;
+            Return()
+        }
+    )
+}
+
+// EMIT_MIR simple_assign.simple_ref.built.after.mir
+#[custom_mir(dialect = "built")]
+pub fn simple_ref(x: &mut i32) -> &mut i32 {
+    mir!({
+        RET = Move(x);
+        Return()
+    })
+}
+
+fn main() {
+    assert_eq!(5, simple(5));
+}
diff --git a/src/test/mir-opt/building/custom/simple_assign.simple.built.after.mir b/src/test/mir-opt/building/custom/simple_assign.simple.built.after.mir
new file mode 100644
index 00000000000..a5a2834c2e1
--- /dev/null
+++ b/src/test/mir-opt/building/custom/simple_assign.simple.built.after.mir
@@ -0,0 +1,18 @@
+// MIR for `simple` after built
+
+fn simple(_1: i32) -> i32 {
+    let mut _0: i32;                     // return place in scope 0 at $DIR/simple_assign.rs:+0:26: +0:29
+    let mut _2: i32;                     // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
+    let mut _3: i32;                     // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
+
+    bb0: {
+        _2 = _1;                         // scope 0 at $DIR/simple_assign.rs:+0:1: +0:29
+        goto -> bb1;                     // scope 0 at $DIR/simple_assign.rs:+0:1: +0:29
+    }
+
+    bb1: {
+        _3 = move _2;                    // scope 0 at $DIR/simple_assign.rs:+0:1: +0:29
+        _0 = _3;                         // scope 0 at $DIR/simple_assign.rs:+0:1: +0:29
+        return;                          // scope 0 at $DIR/simple_assign.rs:+0:1: +0:29
+    }
+}
diff --git a/src/test/mir-opt/building/custom/simple_assign.simple_ref.built.after.mir b/src/test/mir-opt/building/custom/simple_assign.simple_ref.built.after.mir
new file mode 100644
index 00000000000..6c90f0130a2
--- /dev/null
+++ b/src/test/mir-opt/building/custom/simple_assign.simple_ref.built.after.mir
@@ -0,0 +1,10 @@
+// MIR for `simple_ref` after built
+
+fn simple_ref(_1: &mut i32) -> &mut i32 {
+    let mut _0: &mut i32;                // return place in scope 0 at $DIR/simple_assign.rs:+0:35: +0:43
+
+    bb0: {
+        _0 = move _1;                    // scope 0 at $DIR/simple_assign.rs:+0:1: +0:43
+        return;                          // scope 0 at $DIR/simple_assign.rs:+0:1: +0:43
+    }
+}
diff --git a/src/test/run-make/emit-shared-files/Makefile b/src/test/run-make/emit-shared-files/Makefile
index 09b4c29c1dd..cad0c9e5b81 100644
--- a/src/test/run-make/emit-shared-files/Makefile
+++ b/src/test/run-make/emit-shared-files/Makefile
@@ -23,24 +23,24 @@ invocation-only:
 
 toolchain-only:
 	$(RUSTDOC) -Z unstable-options --emit=toolchain-shared-resources --output $(TOOLCHAIN_ONLY) --resource-suffix=-xxx --extend-css z.css x.rs
-	[ -e $(TOOLCHAIN_ONLY)/storage-xxx.js ]
-	! [ -e $(TOOLCHAIN_ONLY)/SourceSerif4-It.ttf.woff2 ]
+	[ -e $(TOOLCHAIN_ONLY)/static.files/storage-*.js ]
+	[ -e $(TOOLCHAIN_ONLY)/static.files/SourceSerif4-It-*.ttf.woff2 ]
 	! [ -e $(TOOLCHAIN_ONLY)/search-index-xxx.js ]
 	! [ -e $(TOOLCHAIN_ONLY)/x/index.html ]
 	! [ -e $(TOOLCHAIN_ONLY)/theme.css ]
 
-	[ -e $(TOOLCHAIN_ONLY)/main-xxx.js ]
+	[ -e $(TOOLCHAIN_ONLY)/static.files/main-*.js ]
 	! [ -e $(TOOLCHAIN_ONLY)/y-xxx.css ]
 
 all-shared:
 	$(RUSTDOC) -Z unstable-options --emit=toolchain-shared-resources,unversioned-shared-resources --output $(ALL_SHARED) --resource-suffix=-xxx --extend-css z.css x.rs
-	[ -e $(ALL_SHARED)/storage-xxx.js ]
-	[ -e $(ALL_SHARED)/SourceSerif4-It.ttf.woff2 ]
+	[ -e $(ALL_SHARED)/static.files/storage-*.js ]
+	[ -e $(ALL_SHARED)/static.files/SourceSerif4-It-*.ttf.woff2 ]
 	! [ -e $(ALL_SHARED)/search-index-xxx.js ]
 	! [ -e $(ALL_SHARED)/settings.html ]
 	! [ -e $(ALL_SHARED)/x ]
 	! [ -e $(ALL_SHARED)/src ]
 	! [ -e $(ALL_SHARED)/theme.css ]
 
-	[ -e $(ALL_SHARED)/main-xxx.js ]
+	[ -e $(ALL_SHARED)/static.files/main-*.js ]
 	! [ -e $(ALL_SHARED)/y-xxx.css ]
diff --git a/src/test/run-make/issue-88756-default-output/output-default.stdout b/src/test/run-make/issue-88756-default-output/output-default.stdout
index 80cd08ee167..b280698230d 100644
--- a/src/test/run-make/issue-88756-default-output/output-default.stdout
+++ b/src/test/run-make/issue-88756-default-output/output-default.stdout
@@ -115,8 +115,6 @@ Options:
                         Provide width of the output for truncated error
                         messages
         --json CONFIG   Configure the structure of JSON diagnostics
-        --disable-minification 
-                        Disable minification applied on JS files
     -A, --allow LINT    Set lint allowed
     -W, --warn LINT     Set lint warnings
         --force-warn LINT
@@ -173,6 +171,8 @@ Options:
         --scrape-tests  Include test code when scraping examples
         --with-examples path to function call information (for displaying examples in the documentation)
                         
+        --disable-minification 
+                        removed
         --plugin-path DIR
                         removed, see issue #44136
                         <https://github.com/rust-lang/rust/issues/44136> for
diff --git a/src/test/run-make/valid-print-requests/valid-print-requests.stderr b/src/test/run-make/valid-print-requests/valid-print-requests.stderr
index 85782866d12..5191e467648 100644
--- a/src/test/run-make/valid-print-requests/valid-print-requests.stderr
+++ b/src/test/run-make/valid-print-requests/valid-print-requests.stderr
@@ -1,2 +1,2 @@
-error: unknown print request `uwu`. Valid print requests are: `crate-name`, `file-names`, `sysroot`, `target-libdir`, `cfg`, `calling-conventions`, `target-list`, `target-cpus`, `target-features`, `relocation-models`, `code-models`, `tls-models`, `native-static-libs`, `stack-protector-strategies`, `target-spec-json`, `link-args`
+error: unknown print request `uwu`. Valid print requests are: `crate-name`, `file-names`, `sysroot`, `target-libdir`, `cfg`, `calling-conventions`, `target-list`, `target-cpus`, `target-features`, `relocation-models`, `code-models`, `tls-models`, `native-static-libs`, `stack-protector-strategies`, `target-spec-json`, `link-args`, `split-debuginfo`
 
diff --git a/src/test/run-pass-valgrind/unsized-locals/by-value-trait-objects-rust-call.rs b/src/test/run-pass-valgrind/unsized-locals/by-value-trait-objects-rust-call.rs
index 7f365ce2bba..ece4dea9aaf 100644
--- a/src/test/run-pass-valgrind/unsized-locals/by-value-trait-objects-rust-call.rs
+++ b/src/test/run-pass-valgrind/unsized-locals/by-value-trait-objects-rust-call.rs
@@ -1,7 +1,8 @@
 #![feature(unsized_locals)]
 #![feature(unboxed_closures)]
+#![feature(tuple_trait)]
 
-pub trait FnOnce<Args> {
+pub trait FnOnce<Args: std::marker::Tuple> {
     type Output;
     extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
 }
diff --git a/src/test/run-pass-valgrind/unsized-locals/by-value-trait-objects-rust-call2.rs b/src/test/run-pass-valgrind/unsized-locals/by-value-trait-objects-rust-call2.rs
index a78b897d194..94df2b0b83f 100644
--- a/src/test/run-pass-valgrind/unsized-locals/by-value-trait-objects-rust-call2.rs
+++ b/src/test/run-pass-valgrind/unsized-locals/by-value-trait-objects-rust-call2.rs
@@ -1,7 +1,8 @@
 #![feature(unsized_locals)]
 #![feature(unboxed_closures)]
+#![feature(tuple_trait)]
 
-pub trait FnOnce<Args> {
+pub trait FnOnce<Args: std::marker::Tuple> {
     type Output;
     extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
 }
diff --git a/src/test/rustdoc-gui/huge-logo.goml b/src/test/rustdoc-gui/huge-logo.goml
new file mode 100644
index 00000000000..01f06771c15
--- /dev/null
+++ b/src/test/rustdoc-gui/huge-logo.goml
@@ -0,0 +1,21 @@
+// huge_logo crate has a custom 712x860 logo
+// test to ensure the maximum size in the layout works correctly
+goto: "file://" + |DOC_PATH| + "/huge_logo/index.html"
+
+size: (1280, 1024)
+// offsetWidth = width of sidebar
+assert-property: (".sidebar .logo-container", {"offsetWidth": "200", "offsetHeight": 100})
+assert-property: (".sidebar .logo-container img", {"offsetWidth": "100", "offsetHeight": 100})
+
+size: (400, 600)
+// offset = size + margin
+assert-property: (".mobile-topbar .logo-container", {"offsetWidth": "55", "offsetHeight": 45})
+assert-property: (".mobile-topbar .logo-container img", {"offsetWidth": "35", "offsetHeight": 35})
+
+goto: "file://" + |DOC_PATH| + "/src/huge_logo/lib.rs.html"
+
+size: (1280, 1024)
+assert-property: (".sub-logo-container", {"offsetWidth": "60", "offsetHeight": 60})
+
+size: (400, 600)
+assert-property: (".sub-logo-container", {"offsetWidth": "35", "offsetHeight": 35})
diff --git a/src/test/rustdoc-gui/run-on-hover.goml b/src/test/rustdoc-gui/run-on-hover.goml
index 6c785e1c4bb..57d63049f28 100644
--- a/src/test/rustdoc-gui/run-on-hover.goml
+++ b/src/test/rustdoc-gui/run-on-hover.goml
@@ -1,7 +1,54 @@
 // Example code blocks sometimes have a "Run" button to run them on the
 // Playground. That button is hidden until the user hovers over the code block.
-// This test checks that it is hidden, and that it shows on hover.
+// This test checks that it is hidden, and that it shows on hover. It also
+// checks for its color.
 goto: "file://" + |DOC_PATH| + "/test_docs/fn.foo.html"
-assert-css: (".test-arrow", {"visibility": "hidden"})
-move-cursor-to: ".example-wrap"
-assert-css: (".test-arrow", {"visibility": "visible"})
+show-text: true
+
+define-function: (
+    "check-run-button",
+    (theme, color, background, hover_color, hover_background),
+    [
+        ("local-storage", {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}),
+        ("reload"),
+        ("assert-css", (".test-arrow", {"visibility": "hidden"})),
+        ("move-cursor-to", ".example-wrap"),
+        ("assert-css", (".test-arrow", {
+            "visibility": "visible",
+            "color": |color|,
+            "background-color": |background|,
+            "font-size": "22px",
+            "border-radius": "5px",
+        })),
+        ("move-cursor-to", ".test-arrow"),
+        ("assert-css", (".test-arrow:hover", {
+            "visibility": "visible",
+            "color": |hover_color|,
+            "background-color": |hover_background|,
+            "font-size": "22px",
+            "border-radius": "5px",
+        })),
+    ],
+)
+
+call-function: ("check-run-button", {
+    "theme": "ayu",
+    "color": "rgb(120, 135, 151)",
+    "background": "rgba(57, 175, 215, 0.09)",
+    "hover_color": "rgb(197, 197, 197)",
+    "hover_background": "rgba(57, 175, 215, 0.37)",
+})
+call-function: ("check-run-button", {
+    "theme": "dark",
+    "color": "rgb(222, 222, 222)",
+    "background": "rgba(78, 139, 202, 0.2)",
+    "hover_color": "rgb(222, 222, 222)",
+    "hover_background": "rgb(78, 139, 202)",
+})
+call-function: ("check-run-button", {
+    "theme": "light",
+    "color": "rgb(245, 245, 245)",
+    "background": "rgba(78, 139, 202, 0.2)",
+    "hover_color": "rgb(245, 245, 245)",
+    "hover_background": "rgb(78, 139, 202)",
+})
diff --git a/src/test/rustdoc-gui/rust-logo.goml b/src/test/rustdoc-gui/rust-logo.goml
index 6c8dc859419..816cc9abd69 100644
--- a/src/test/rustdoc-gui/rust-logo.goml
+++ b/src/test/rustdoc-gui/rust-logo.goml
@@ -17,6 +17,15 @@ define-function: (
         ("local-storage", {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}),
         ("reload"),
         ("assert-css", (".rust-logo", {"filter": |filter|})),
+        // Now we check that the non-rust logos don't have a CSS filter set.
+        ("goto", "file://" + |DOC_PATH| + "/huge_logo/index.html"),
+        // Changing theme on the new page (again...).
+        ("local-storage", {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}),
+        ("reload"),
+        // Check there is no rust logo
+        ("assert-false", ".rust-logo"),
+        // Check there is no filter.
+        ("assert-css", (".sidebar .logo-container img", {"filter": "none"})),
     ],
 )
 
diff --git a/src/test/rustdoc-gui/search-filter.goml b/src/test/rustdoc-gui/search-filter.goml
index 27db816e685..e0228694eec 100644
--- a/src/test/rustdoc-gui/search-filter.goml
+++ b/src/test/rustdoc-gui/search-filter.goml
@@ -14,6 +14,7 @@ click: "#crate-search"
 // We select "lib2" option then press enter to change the filter.
 press-key: "ArrowDown"
 press-key: "ArrowDown"
+press-key: "ArrowDown"
 press-key: "Enter"
 // Waiting for the search results to appear...
 wait-for: "#titles"
@@ -37,6 +38,7 @@ assert-property: ("#crate-search", {"value": "lib2"})
 click: "#crate-search"
 press-key: "ArrowUp"
 press-key: "ArrowUp"
+press-key: "ArrowUp"
 press-key: "Enter"
 // Waiting for the search results to appear...
 wait-for: "#titles"
diff --git a/src/test/rustdoc-gui/search-result-color.goml b/src/test/rustdoc-gui/search-result-color.goml
index 0c3b1119074..d437ad75970 100644
--- a/src/test/rustdoc-gui/search-result-color.goml
+++ b/src/test/rustdoc-gui/search-result-color.goml
@@ -78,7 +78,7 @@ assert-css: (
 // Checking the color of the bottom border.
 assert-css: (
     ".search-results > a",
-    {"border-bottom-color": "rgb(92, 103, 115)"}
+    {"border-bottom-color": "rgba(170, 170, 170, 0.2)"}
 )
 
 // Checking the color of "keyword" text.
@@ -190,7 +190,7 @@ assert-css: (
 // Checking the color of the bottom border.
 assert-css: (
     ".search-results > a",
-    {"border-bottom-color": "rgb(224, 224, 224)"}
+    {"border-bottom-color": "rgba(170, 170, 170, 0.2)"}
 )
 
 // Checking the color for "keyword" text.
@@ -287,7 +287,7 @@ assert-css: (
 // Checking the color of the bottom border.
 assert-css: (
     ".search-results > a",
-    {"border-bottom-color": "rgb(224, 224, 224)"}
+    {"border-bottom-color": "rgba(170, 170, 170, 0.2)"}
 )
 
 // Checking the color for "keyword" text.
diff --git a/src/test/rustdoc-gui/sidebar-source-code.goml b/src/test/rustdoc-gui/sidebar-source-code.goml
index 9ba66368772..e9a987d52bb 100644
--- a/src/test/rustdoc-gui/sidebar-source-code.goml
+++ b/src/test/rustdoc-gui/sidebar-source-code.goml
@@ -28,7 +28,7 @@ assert: "//*[@class='dir-entry' and @open]/*[text()='sub_mod']"
 // Only "another_folder" should be "open" in "lib2".
 assert: "//*[@class='dir-entry' and not(@open)]/*[text()='another_mod']"
 // All other trees should be collapsed.
-assert-count: ("//*[@id='source-sidebar']/details[not(text()='lib2') and not(@open)]", 5)
+assert-count: ("//*[@id='source-sidebar']/details[not(text()='lib2') and not(@open)]", 6)
 
 // We now switch to mobile mode.
 size: (600, 600)
diff --git a/src/test/rustdoc-gui/source-code-page.goml b/src/test/rustdoc-gui/source-code-page.goml
index a2dac2aa681..3c4db978d5f 100644
--- a/src/test/rustdoc-gui/source-code-page.goml
+++ b/src/test/rustdoc-gui/source-code-page.goml
@@ -78,7 +78,7 @@ assert: ".source-sidebar-expanded"
 
 // We check that the first entry of the sidebar is collapsed
 assert-property: ("#source-sidebar details:first-of-type", {"open": "false"})
-assert-text: ("#source-sidebar details:first-of-type > summary", "implementors")
+assert-text: ("#source-sidebar details:first-of-type > summary", "huge_logo")
 // We now click on it.
 click: "#source-sidebar details:first-of-type > summary"
 assert-property: ("#source-sidebar details:first-of-type", {"open": "true"})
diff --git a/src/test/rustdoc-gui/src/huge_logo/Cargo.lock b/src/test/rustdoc-gui/src/huge_logo/Cargo.lock
new file mode 100644
index 00000000000..14280575064
--- /dev/null
+++ b/src/test/rustdoc-gui/src/huge_logo/Cargo.lock
@@ -0,0 +1,7 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "huge_logo"
+version = "0.1.0"
diff --git a/src/test/rustdoc-gui/src/huge_logo/Cargo.toml b/src/test/rustdoc-gui/src/huge_logo/Cargo.toml
new file mode 100644
index 00000000000..3f10d09c80a
--- /dev/null
+++ b/src/test/rustdoc-gui/src/huge_logo/Cargo.toml
@@ -0,0 +1,8 @@
+[package]
+name = "huge_logo"
+version = "0.1.0"
+edition = "2021"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
diff --git a/src/test/rustdoc-gui/src/huge_logo/src/lib.rs b/src/test/rustdoc-gui/src/huge_logo/src/lib.rs
new file mode 100644
index 00000000000..ec137fb9a88
--- /dev/null
+++ b/src/test/rustdoc-gui/src/huge_logo/src/lib.rs
@@ -0,0 +1,17 @@
+// ignore-tidy-linelength
+#![doc(html_logo_url = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAsgAAANcCAQAAADoIpEcAAAAAmJLR0QA/4ePzL8AAHSISURBVHja7Z15vFbT/sefzNflXtzr+qHOXvs5p051KtVJIg1IhqRoQlHKVKbKUBkaRQiRpEhKkqIQkURyJJUkQxNKs4bTPJ7h8/uj5Ax772fvZ6+999r7+bzXP14vPXufs9b3+znr+a7v+n5jMUIIIYQQ95zxTz1Tr6e10Dpp3bX+4nkxRrwnZonvxW/iN/Gb2CpyRa7YIyAgIHaLXJErcsVqsUxfoM0QU7Sx+ouij9ZFuyZ+oZ6ZeTLnkxBCbJJ1XLy8uEx01p4Wb4vZYrnYfVhqZY1csVC8qz+j3y0u1zXONyGEFCPt1PiF4nZtqJgpVol8yQJsObRdYp4YrT+gXZTxL64DISRlySirXSsGielirZ8SbDoKxBJtrH63qB47imtDCEkJxAnaRdrD4j2xXgkZNg5qvCe6UpgJIdHlmLRs0UObIfYpK8QlwxmbxUT9pvi/uXSEkMig6frdYnp4hLjE2C+m67ee/R+uIyEkzBwVv1AMEj+FVIiLj4PiI/0mHvwRQkJIWpboK36LhBQXHfvExHijWBmuLyEkFIiK+sAISnHR8YvolnYqV5oQojAZx+uttBmiMNJi/Hf+8ghRkWtOCFFyXyyeF7mpIMXFMpenaBdw7QkhChG/UEz0936dSkPPEQ1pA4SQwMk+Vr9RfJ+qUlxkTIufS2sghAQpxjdpKyjGh0ehmKjptApCiP8cpbcSyynDJcYB8Tzv9RFCfEW7Riyj/JqM9XprWgghxB8xriG+oOwmGJ/HK9BSCCGeIv5PvCYKKLg2xh6tO2vFEUK8oox+k9hCqXUwvk7PoNkQQqSjZ4ovKbGOxw5xM22HECKTo7WHQls6M/gxPuskmhAhRM7eWOPe2OVYGq9KOyKEuEa0Fzsoqa7Hbq0tbYkQ4oKsk8QEiqm08QSzLgghSRKvoP1IGZU6PmK/EUJIEmgtxE5KqPSxqNxZtC1CiBPK6I+lRpH5AMbv8fI0MEKITTKO18dROD0cW0QdWhkhxAYV/qvnUDS9vi6i16OlEUISIARLavrTj4+STAixJF5BrKZY+lZ86CJaHCHETI6rig0USj93ydr5tDpCiAFaTVZy833kpleh5RFCSqBnio0UyADGOnbhI4QUD1aUZ7AisLE843RaICHkMELwKC/IoedkHE8rJITEYrGyp4mlFMWAx4RYGVoiISlPxvGsdaxExsXDtEVCUp0y2liKoRKjUDSnORKS0oi+lEJ1UuCYb0FICqM3FQUUQpVKc551Iq2SkJQkXkFspwgqNkbQLglJQbJOYjcQJVPgWtM2CUm96PEYip+akeR4Gq2TkNSS4zaUPmXHTLZCJSSFyCgrtlL4FA5b3EUbJSRVOErMpugpXpaTCXCEpEi4ohslT/nxOa9SE5ICpMXFbgpeCHbJnWirhESdMuJTil0oxtYK/6W5EhJp9FsodaHZI79CeyUkyuGKU8UmCl1oRgE77hES5f3xMMpcqPbI85mRTEhESa+i5VHkQpaRfCPtlpBIwkL0IRyry/6DlktI5IhfRXljJxFCiAocLX6iuIVybE87leZLSKTQOlLaQjv60H4JiRBZx4k/KGyhHdvi/6YNExIZ9Fspa6EevWnDhEQnfrycohbuOLI4hWZMSCQQ7Slpoc9HfoR2TEgUKCN+oaCFv9RQxr9oyoSEHq0J5SwS+cgP0ZYJCX/AYibFLBJjffaxtGZCQk28qiikmEVktKE9ExLu/fFrFLLIBC2+oj0TEub98b/FHgpZdEZaNm2akNCi300RYw8RQogSaD9SxCI19p79H1o1IeGU4wsoYZHbI99HuyYklIiXKWCRG7+xqRMhISTrOLGFAhbB0ZC2TUj4AhYtKF482COEqBGwmELximZ1ZHECrZuQUJF5sthH8Ypo5beWtG9CwhWwuIHCFdkxhfZNSKjQ36FwRXYcYDYyISHirBPFbgpXhMfttHFCwrM/vpqiFekxmzZOSHgEeRhFK9KjsOzZtHJCQoL4laLFoAUhRAE0nYIV+dS3D2nnhIRjf9yZghX5sT/rJFo6IWEQZN7RS4XRjJZOiPocI7ZTrlIgaPEqTZ0Q5dHrUaxSYvzJQpyEKI82gGKVIuM8WjshqkeQZ1OqUiRo8RitnRClyT6WfaZTZsylvROidsCiJoUqZUrV52X8ixZPiMoBC+Ygp5IkN6HFE6KyIL9OmUqhKPJgWjwhKgvyUspUCo3vaPGEqCvHp4gCylQKjYK0U2n1hKgqyJdRpHiBmhCihiD3pkSl2BhCqydEVUGeTIlKsbGIVk+IqoK8jBKValHkzJNp94QoSMbxWh4lKuVGA1o+IQqin0N5SsFc5Ado+YQoiHYD5SkFx0RaPiEq7pAfozyl4FhFyydEQdi6KUWDFmfQ9glRT5CZY5GagtyUtk+IanJ8gsinOKVkzbf+tH5CFCMti9KUouNjWj8hiqFdSWlK0bGW1k+IaiELlqZP2XH2f2j/hKglyIMoTCl7rFef9k+IWoL8FoUpZY/1utD+CVFLkOdQmFJ2vET7J0QtQV5HYUrZHfJXtH9CFCLrODZvSuGxPVaGPkCIMpRLpyyl8sgoSx8gRJ2ARQOKUkoHLa6gDxCiDHprilJKj3voA4Qog3YnRSlhti7qoAXaojO6oAs6oA0aoEJUfrvn6QOEqBOy6EvBNRuX4FG8g+U4ACPWYjoGowXSw/3H5kP6ACHqCPJLFF4jKR6O32GPXLyD66CH9XddSh8gRJ2QxSTKb/HwRGfMRSGcshL9UCmMv/GB2NH0AkJU2SHPogj/PW7FL0ieLXgcmeH7rQW9gBBVBPlnyvCh0RBfwj3r0T1kv3e8Eb2AEFVCFpspxQIZeAEHIYvPUDtMv/0d9AJC1OAotm8SaIBFkEsu7grP1ZCn6QaEKEHmyZTjztgNLxgXllzlifQDQtQIWJwpOR6JZngaH2MZcgEAediM7zEJPXCBmvFTDE0io8Iui1AnDII8h35AiBLEK8hz7Dp4ERtNxakQC/GAYjkIFTAN3rIBjdUPWayhHxCixg65phynzsYY5NkQqM3ojQxFhKgyvoL37EAb1SU5P3YMPYEQBZBT663L4QCFPVbheiXkeAH8Ya/ykswSnISosUNu4l7YPnAsUQUYHnAFiPKYBf/Yi9ZqBy3OpycQosIO+Tp3rlwXS5IUqfmoFeBR3nT4y3ZcovJ18Vb0BEIUQL/FjSNfjPWuDryuDEiAhsF/ViNb3R1yd3oCISrskLsm78aNsMX1gVfzAOTnLg8T3ayYq26hzmfpCYSoIMg9k3Xi+tggQaR2oYXP4lPfo2sgdnheVUEeT08gRIWQxaPJuXAVLJckUrtwha81KxYhOAqUyC8xiCF/Rk8gRAG0/sk4cDpmS7084d99tucRLGtRWUVJXkxPIESFkMUTyTjwc5Jl6nufqj5cZNKMyU9GqyjIG+kJhKgQsnjGuftea+tOnjPG+NIL5BsET0EgB5kJ7+odRV8gJPiQxQvOr1Ss8ESobvZcdu6BGixUsP9exun0BUKCD1kMd+q6T3kkUxtxjsd381ZBFdSrlZxWmb5ASPCCPMppESHvksbe8FRy+kAdVqO8apLckL5ASPAhi7HOHHeMp9HVZp4JTkVshkr0VC3xrTV9gZDgBfkNJ257vsS+c0bM8UxwekMt/lDt1l5n+gIhIdshj/RcqLypipaOP6Aa96lVzeIh+gIhwceQxzi5nbfLc5n62qPqFerxi1o75CfpC4QEL8iv23faHr4IlRd75HlQEaXK1o+gLxASvCCPtu+0/lyryJEuNo2hJh+rJMhv0xcICV6QX7N/oFfgk1A1kSw2YxQV5LwAS/SXGp/SFwgJXpBt5yE/6ZtQyb1GneGo35+/DFBHkOfRFwgJHP1Vuy671DeZ2olKEqXmZkk50ovxKcbhNXyKn6WVKFLoYG85fYGQwNFesdusyU+6SpSaKa5/msXojprFnlkV3ZAj5TdtpIogb6IvEBJ8yOIlFS9WzJGYgbzD1U+yCreYlgJqj19d/6ZPqSLIB+gLhAQvyEPsOezHvgpyIRpIEprWrn6Oj1AtQcGiSa4rQasStMg+lt5ASNAhi6fs7TO3+Xzc1T/w/tIF6G3zsLPQ1Z8eVXpRx/9NbyAkYPTH7DhrU9/zD76UJDOLk3x/PrrZfsdjrn7TOxUR5HJn0RsICTpk0duOsw5Kaoe5DhuSzkfYLyXTolKSvU0KHR4ruqnxMU6VHXJ5egMhQQtyTzvOOs2hFH+Ctsg65OZogTFJyXJHCSLTJkmRHOG4OdQXSQvyClWiyNXpDYQEHUPubsdZlzsQmDW4ttTn6ybRpVrG9ZBBSUlkThKlMc9LOspecPhPV+A9Q+rSGwgJOoZ8l527bva/+P9o0ogpjucdCtWvEkTmvSQEcg8uSOpdXZPeI7dSo0R9Y3oDIUEL8i2JXbWRAxGtafGcAQ53jpVdi8wvScjjoKTftihJQe6rRkXka+kNhAQdsmib2FU72xSWfWic4EnPOBKqa1xfCtnvWBx/ddHt7qYkBfkNNXbI7egNhAQtyNckdtXBNoWlt43Dr88cCNVDLiXmwiTEsZurN85XpOBoUjvkjvQGQoIOWTSWVb5yma2jsHOwybedYyvH0rgeGa7eeG9SgryaXfUIIbFYLBa/MLGrfmBLVm636fjdbQvVApcSc7djaezj8o2Z2J7UJRQlGp52pTcQEnTIokZiV51lqwiPbjtnd4FNodruUmKc3qDbKyEBLbli+EoUqu9BbyAk6JBFZmJX/cGGpAz25PDL3W29oQ5l8T0JstYiKUG+XAVB7k1vICRgMsomdtWVNiSlricVJuq5kpjXHcpiBynlPpPpT9JWhSyLgfQGQgKm7GmJXTXXxoGeN4df17qSmMmORDFXUiT3/SQE+Q4VBPkZegMhAZN1XGJXTXwp+BXHh187fBAqZxU4PpQkbN2TEORuKgjyi/QGQgJH7E3kqps9KAQ03pZQPepKYj51JIoPSxK2ZJpdPaRCDHkEfYGQ4AX5z0SuusGDLIEbbAnV864k5jNHonixrDKW2O1YkJ9Q4WLIK/QFQoIX5OWJXHVtAjnZkIT7Z2CnB2Uwi4+ZjiLI8qTtW8eCPESFHfIo+gIhgaPNd5tlMcuzCO/rvgnyfInSNs6xIA9WQZBH0xcICX6HPDORq65IICdvJiUAfWwI1Zu+HepNkChtzzgW5CdVEOQx9AVCghfkyW4vhjyblABcY0Oo3nElMU46Qj8mUdoedCzIA1WIIb9BXyAkeEEe7fZwrGeSdR8Sl73/wLdrzDJbjbZ3LMi9VNghv0lfICR4QX7ebYpaslm0vycUqimuJGZYQHflWoaz8/Rb9AVCAkfrn8hVhySQk7uSlIDEjUHddWTu70ASm0iUtmscC3I7FQT5bfoCIYGj35/IVR/y6D5d4pDCSFcSc6cDSbxQorRd5ViQr1Lhpt479AVCghfkWxO56i0J5KRrkhLwlMf5uU5CBzUkStsVjgW5pgo75Mn0BUKCjyG3SeSqTRLIySNJSkDfhEL1uCuJqeOgXLxMSbzeoRzvs11L2tPxHn2BkOAF+XK3+RDJ9mnuYVksfjruQzXX15ivwkB8buMy83kSpa2zQ0H+XY0WTh/QFwgJHO38xM66zFJQXk5SAu4xfFoB5uA+VJYqNulog5H4zacY8kMOBfkzNbpOf0hfICRw0rISO+sUS0GZmqQE3FrqSZsxxGGpe2ejAQbgGxQY/A4NJb7lKYeCPEyNHfI0+gIhgWOnZ8hAS0FZlKQEdCz2lCW4HxV8kZ46GIifSvwOzSU+f7RDQb5XDUGeTl8gJHCyTkrsrO08qZTW7cgTfrFZUbkyLsdt6I9hGIXx+BAfYSrGYwyGYwA6o6mjo7lGGIp1nlzN+NKhIF+qhCBrM+gLhCiAOJjIWasbfs3/mzouLm6sxF2IW/67LNyAwfgMf9oQtz2Yj9HohkYJnvnXoV8n5EjI5yg+1jmS4+22flIfxkx6AiEqCPKmxO66yFJUbkuyK/R+DLEMU9RHf8yxUfPCiF2Yjl64wMbP0RSTMUqasFVGoaOfc6YacgzxKT2BEBUEeVlid7W+Pv1iklkWDUz/X1U8ip8hg2UYYSNCnClN2FqFsfQmBMTH9ARCVBDkb93WZ1gkVRqaYjz2QC6/YQjq+yJsQxz+ZE0UEWSmvRGihiB/YieTN9dCVAqS6KpnlnmxGF5RgDno7nkmxzxHP9OfatzS48UQQpQR5LfsOOz7lsLygJSylXPhPVswRGrlipIR5IOOfpq3VZFjiCn0BEJUEOThdhz2dkth+dp1mOIr+MdevCH1Ksjfo6vDn+RmZQSZ1d4IUUOQH7d3/XiThbAUuojQVsaryIffFGAaGkmXtVmOfoZcZKizQ2Y9ZEKUEOQH7bnsCEtxGZqkEHTAGgRFAT6yyPRwPrIdpui9oY4cs2MIIWqQuCLyoXGRZYbtTlR1LAJVE1TJ8IMDGI1sSaL2tMN3t1BIkPVx9ARCVBDkVnaddr6lvDzhUAKuxh9Qgz0YgooS9sfbHL11iUr7Y4gx9ARCFCDeyHn1CeOIqJPshV4O8xG85g+b9TTMr2F/6vCNj6olyK/REwhRQZBr2XXajATx3rdsH+NNh4p86qIu8gjHV7urKCXI+qv0BEIUoFy6fbd9JMEh2Q22yl/+mECs8vEtnsGduBpN0RYP4ytH9SE2YCg6oiWuwo3ojSmOAgn7MCSpa9R9HIv/y2rtjyFG0BMIUYCM0+27bQVsSHDtIlHlt5bYYvmElRhgcMh2m+0Ax7RSd/HScRM+TVCvrnhLpfaOe4QUOpTjA1KbRkkZL9ETCFEAcYLzopnmLLbshHcPDlh8diPuNy1G+blNqatjWv/YSY7wdNSzPSO9HcsxME41OYY2lJ5AiBqSfNDJHvn3BGLzo+nhXh/Lfeosi6hqA+yQUD3tQQcXUPbheVuJfN0c7L3/Yr+tsqA+j+fpB4SoIci5ybdeMuJXXGLwuUGWn1mDSoZvq4J2eMtR9bd5eND03uBQR8K5G8NxToLZaIxhjq+2DFdPjiGepR8QooYgr3bmvJ8lEJwfSrUqjWNcgs+MNris3RPfJn2pej1exfkG8umUnRhm8JzStThGY7PtC9NVFRRk7Wn6ASFqCPLPzpy3PvZZCM6oUhUa0jExoUx9WeIz9fC96zS2Xehe6nAwuSvWOeiC9IRJgR0xBXsTPu0RFffHEIPoB4SoIchznbrvw6Z33u4yEKoPbZairFHk8G8b5PD2kUPGOLpaVnVOfHVkiI3KF1XQC79YPOU7VXrolRyP0w8IUQJthnMHnmIYO25scAg4w7bk5WE+JuA1yUXqczERYzANWyU8qxAL8IiNG4lNMd5wr3zAgwpzkkIWA+gHhKixQ57s3IGzsLKE2ExB5VL/qhJmI3rkIwfdkZWwV/cA/FrikwMVlWMB0Zd+QIgaO+SxybhwY2wvUvK9h2G5nfmILnsxFbcmaAml4zq8fyT3eqY6DZtKj970A0KUQB+WnBM3w24AwApcZvi1fT2iz3ZMwA0J4sLZGIJcrPOwdZSEkMXD9ANC1AhZDEq+D94eTDbMIH4E+5E6bMCLuMhypiqqeBmk6OhJPyBEjZDFw8k78nmGheenIhVZjH5K74ItgysP0A8IUWOH3FWma7fEOqQuezEJzUIoyNp99ANC1Igh3yXLreMY7LCvXFT3yj0Mck6UHl3pB4SosUO+XY5Tn4scanGRS9evK5t1bBCyuJt+QIgaMeSOMlz6BvxJFS7FfHRSOdnt75BFF/oBIWqELG50687peDGJMpSpwlJ0Vl+U76AfEKJGyOI6d858fqQvgMjhe1yntiDfTj8gRI0dcms3rtzJVcmeVOIjg+ZU3CETQorHkNsm68bl8WoSDYxSl224V1VB7kw/IESNkEWH5Jy4Lr6jxjpmsklvlIAP9e6kHxCixg65UzIufCd2Ul2TzFKuxbQ3QojJDvkOp+6bidHUVResRkNenSaEGAryPc6c9xIspaa6LkekWLGhvvQDQtQIWfR34rr3O+oBTcxYoVQhIjY5JUSVHfJwu25bGZOppNL4XKHrIvow+gEhauyQJ9lz2jr4mSoqlcfU2SG/QT8gRI0d8pd2XLYpNlJBJbMX56siydPoB4SoIcg/J3bYy7CD+ukB76siyPPoB4SoIcibEgcr1lM7bVKId9ERbfEoltj41wVooIYg/0Y/IEQFjhL5iWq5/UidtUk+7izS3soOr6ohyDvoCIQogHZmImcdTJ21zePFuk3bYaMiuRaZJ9MXCAmctGxrR62HA9RZm8wsJq6P2fzU1WrkWVSiLxASOHpTa0d9jTpr+/Zd0aseNbDF5uf6qJGJ3Ji+QEjgWHfUq4JdVFpb5KFNUXnDdNuffFuNHXIn+gIhwQtyX+uabqWZjevwNDZTg4tlSxSvdPyCg89+qYYgD6AvEBI42kgrNx1rkNZV+/BX8kXU4cMcRPdis9bDUdn+xWrkWUygLxASfAz5Qys3LZ1L+8eR/1eTfaYBALkl+uV1d9jwVRFB/p6+QEjwO+Qfrdy0dL+8VUX+bxeqMeajTrEZexD5jp+ghCDvjpWhNxAStCDvMnfSuIG4HEBmkX+R2v2mC/EaMorNWN8kegx+qMj16fRy9AZCAiXjdOvOIEYU/YLeIoXleDPalbjROCqp57ysSsW3JvQHQoKNINe2dlKjYvQfFfsXH6SoHOfg3GLzUA2zknzS3aoI8kP0B0KCFeTW1k662rBeQ+Mi/6IWNqRgxYpnEC82Txfh16SfpkwJzrfpD4QEiuhh7aQ5hhLyCyoU+TdXGBz9RftGXusSs9QO25N+2q/qNHJaRn8gJFhBftnaSc0uOEwqtkNslEK75M9L9cLrizwXzxuqjiAXVvgvPYKQIAX5c2snvdFUSD4oll9QF7+nxPXo50qEKrLwvstnNlap93QzegQhQQry+kRtTc17TM8olgBXK/Id91aheYnZuRIrXT7zG5XkGPpgegQhgZHxr8ROOslCTuaiSrE8gyhnJb+LrBIz0w17XT/1VqUEWXxLnyAkuP3xeYmdtE2Ca79FI6qV8EVEL0ffXqoK3lQJz12sSHH6I4lveVkn0SsICUqQ29v4GotllqKyotjV4QzLHXU4mXW4nNLf42rXoYpD3KTW/hgCaZfQKwgJSpAft+OktyWQlTVoWEzAh0ZIjPegd4ldbHkMdZVV8TcfKyfHAqIvvYKQoAR5iq2jHixMeIn4ymKf6CVJsoLm01KXNprY6iVth90lihIpMj6nVxASlCCvtOemrRKWzNmDDtKuSqjBRnQr1X17EA5Ke/4DKsoxxD5GkQkJRo5PEYV2HfV1Gzm6PYt9ogFWhFaMCzC+VE5FYyyW+IZpasoxBLRr6RmEBIB2kX03rWTj4kchBpcot/NlSA/xLi+Vjf2SxL0x8CuqKivIYgw9g5AgBLm7E0e9xlZceEqxyyLpeN5h94ygWYy2pX7z27FO6ju2FzsEVW5sjR1D3yDEf0Ee68xVH7IlNwtLJIm1w5aQiPFq3FsqL7iJSXml5DmA60u8o4ZqktyQvkGI/4L8o1NXtVeAfQOaFvvUefg2BBXcHkb5Er/tBXhH+v4+H11KSf7nqgnyc/QNQnzmrBO1PMdNfjDTluzsR98SraD64oCyYrwVg1CxxG9aE8OxX/qb8nFfifdUx2ocRGW1BPl3egchPiMaJuOslfGNTfGZXEJm5GYpyGILnkClEr9jNl7BPk9qxd1Tqmfhl0re2NOr0T8I8VeQeyXnrJXwtU0B+g2XlcrjVWmfvBZ9S4lxdTyHXZ68bZ9BIaGRh//fSNUEeSD9gxB/I8hTk3XXivjKpgjtxSMljskuSbrznFyWoVuJftECVTHEIzEGctGy1DwOOPJ/f1Itirw2djQ9hBD/KCM2Je+wmfjYthTloG6JT3fCqkDFeC5uKZVNURlPY5uH8t+g1Bz2LpbBna2aJF9GFyHEN/RMl19qMSjhdeq/2IWeJQSwAgZhRyClgsYZdOiohIHY6uFb3zc4tOteIn/jbtUEeQJ9hBD/Isjt3TvtPQ7yEL4stUesisG+Nkf9FX2KldP/6zbh057mSe/DowYzdz/yS/y7CcrVtCh7Gr2EEL8EebQMt22O9Q4uRAwvVR+iMh7HZs+leBcm4QaDUvDnYrhnMeND/IhLDWbN6LvFWvVqWnShlxDilyCvluO25zjqnPEnupcSxop40LPWTwcwHV2KXeb+a9THOA/yjItyEC+UumoikIG3Tf79RaoJ8nx6CSGhiCAXH10cxYMX4gaDZ1yCEVL3yvvxFXrgHMPod1tMLxUykM18w27SWZht+on+yu2RmY1MiC9od8p13foO97gLSlRP/mv32BETXMvyb3gNHUrlF/8liL19KAq6weB7wKGrMVbNsGarV2ZoBD2FED8CFpNlO28cPR2mjS3GbYayFcfVeAJfYKdDGVyF9/EQLjT9CRtjDHb7kMcxxOQidPcEt/8OqHaBGmK/fgZ9hRCvOVrkupXfqobx5NEOi/EsxwDUNE2sa4A7MRRTsdgkKW0/1uAbjEM/tEN1i5/2fDyOX3xJqhtdqh3qXzNjJ2/7VvX2yH3oLIR4vT8+z62j1sB6g7rBAgItsdTx4dfH6Ij0hGWNzkVjNEULtMU1aIoGtopWVkcvfOtLReYdGG56ueNmrLX1jPHqCfKf4gT6CyGeog9066gXAyjEeMMv2enohz1JxF1fRgvEJUa1e2OW1C4fVnWUB6Gayc9RG5MdzIGu3sHeLfQXQjzFeR3kkqPFYQn5A60N/39D2wWIStZem4SurroxZ6MLxuJXny6bHMRHuMn0z0gcvRzmOV+u3h55aawMPYYQ7wIWwr2bdixS4XeU4T5Zx2Mu9qcrMQWP4TrbvTRq4wYMxAf43fZ1brcUYgH6msa/BQRuSKLc6FMqtnS6nD5DiHeCfI97J72vmIxsxB2G/+oqG41RE7EdP+ADvIbB6IEuuANt0RZt0Rld0BPPYAym4UcfcieKsxQDcYHl/DSzWci/JPNUFOSZ9BlCvBPkme6ddEApKZmKcw3zfj9DlMjFaFyVYG4a49Ok9+l5ltki7LFHSNTk+BRx0L2LjjDcy/Y0OJTSMSQiYrwW/Uyum/w9rsMnLnM6uqooyLPpN4R4I8gdZLjo+6YXhhsZBjgOhFyMV6F7qXL2okRB0e5Scp2nqSjIiDei5xDihSBPl+Ggcy1qSDxmsE++1oeabl6xDYNQwXI2GmCotHrKewxLIQU+5jHXghDppP/Peadpo2Hd8SPHIJ58oWUdB1XJwwjDO4l/X5DphfmSMzs6KrlH1q6k9xAiGf1uOe6ZqCfzRjQzKAU/L2RyPNewYtuhUQUPIMeTmnFvKSnI+gLukQmRHbD4WoZzVrfVKeMug+aoM0Ijxptxr+nv3wbvYq+Hb44rKcmiOf2HEJn7Y00UynDNpjavTgwvFU1Ox1uhkOOPTK6k6OiERZ6/vYWaQYsVWcfRhwiRhvawHNe807a0vF/qiEr9NLg/0M7k974dy335CV5Wc4cM0ZU+RIgsymgr5Djm0w7EZaFBDbQ+nvfrSP4Q72VUNLl7518E/DdVBTm3wn/pRoTICVhcKssx33ZYl6J+qSd0SqIenPcsRhOTgkXv+FYj4xCNFJVkbSj9iBApiImy3PJbh/KyCVeWesbl2KCUGO9EP8OazHE8iu2+/zRPqbpHzk+vQk8ixDUV/iv2y3JL51K6y6CxaR38rIwcz8T5hr/pFT4c4Rnxo6qCDP0z+hIh7gMW98tyyaykvr4fxN2lnlTVogezf/xu0vukIob4VODeiAbKSjKviBDiPmDxiyyHbJ6kxBRggEF3kSG+NFgyv+g9xOSqcjv8EeifiSfUFeQVbOtEiLv98aXyHLKHC5mZYFCi52bkBiJ5hfjQ4LjxUEvS8T4f4pXmB2UFWUDrT48ixM3+eJo8d3zFldDMQpVST6yFT30XvO/Q0uTqx4MB/YEo+efiQnUl+UBaZfoUIcnujzNFgTx3/NKl1CxDXcN99w4fxbiDye92OeYrc9A4UOE9spjNyhaEJLs/HiHTGde7lpo/cbVhhYzRPlwYmY9OpuWCRiFPoUS8hSoLMrSO9CtCkqDsaWK3PEesLiW6uh8PmXTh+9yz6O0BTME1pr/XPdio2DWVQpNUPEXG1vT/0bcIcYysChaHRltpgjPFsFu1QBNMk5558QcGWXSIvgQ5Sl7k7q/2HnksfYsQh2QcL9bLdMPHpWYAX2vyljoYhJVS3rEeo9HSoIfJX+NcjFMqUFE8vCLUluQr6F+EOIsfd5brhB9IlZx8jDBtWaSjBV7E4iR3y3uRg2fQ3EKKBbIwRMmaGn9nbtdRW5LXpZ1KDyPENtnHipVynfB3D2qb3Wz5xhrojKGYgTW2rmgvwiQ8jpYon+D3qIrBSqS3hTjTAgLidfoYIbbRb5HrgFU8ulc3C5fYurTdCNejKwZiOIZjOEZjPMbjZTyBHrgdrW0fgtXAkAAKBiXDYtUFGdq19DJC7HG0WC7X/dp4Jj15mIiLfRCQJngb+xEeGqouyRvO/g8djRA78eP2st1vkMcx0w9NKhLLKYrUXaFrH3YZrPweWbxJTyPEzv54qWzn86NJ6XLLFLVkRjraYrLSx3fm/Kq+IEO7hs5GSKL48Y3yXW+zTzJ0ANPwAM5z/fNegJ6Y5uOlbC+4TH1B3qydSX8jxIKs48Rvsh2vnu931X7By7jVcZmdDFyFXngLKxAFhoVgjyw+ZW0LQizQust3u3sDE6Ud+AavYwDuRWtcXOqGXzXUwqXogIcwDO/hBxxAlPjDMpdamdGNPkeICfF/iy3yne51hWRqP7YjF9tDlTGRLM3DIMj7RXX6HSHG8eOBXjjdUpAgGBUGQYb45awT6XmElA5XnCmzvttfo2bgXTRSlT8N+2ErOF6i7xFSCrn1j/8ad1IZA6NdOAS5UL+a3kdIMdKytDwv3G0cdTEw3g2HIEPkajo9kJCi++MvvHG236mLgbHHpHa0gmNe1nH0QUL+kuM23jjaeVTFQLk3LIIMMYReSEgsFovFyv5DrPLGzbpREwPli/AIMvSW9ERCYrGY1t8rJ5tITQyUPJwbGkHWdomK9EWS8sTTxB6vnGwNNTFg+oVojywWl/0H/ZGkevx4ilcOVp96GDg/hEmQoY2kP5LUDldc6Z179aAeKkDjUEmyfhN9kqQsmSeL1d451xSqoQIMDZUgi91plemXJFX3x0M93OvgT6qhAqxBPFySvDTzZHomSUH02iLfO8dqSi1UhLbhEmSIt+ibJPU4RnzvpVsNoRIqwpSwCTL0W+meJNXCFQ9761SLqYSKsA/VwibJ+7Sa9FCSQsQriH1eulRtlt1UiIdDt0fWVohT6KUkVThKzPbWoXpSBRViUegEWUBMjx1NRyUpgejptTvNoAoqxeVhlOS+9FSSCtHjSt6GKwQqYg81UClGhlGQC7Vr6a0k6hwj5nntSh2pgIqxBRlhlOSdWiU6LIl2uKKv9470BhVQOW4LoyBDLMn4F32WRDdcUUMc9N6N1lL/lGNGOAUZYnKsDP2WRHN3fIL4yXsXupLqpyB5qB1SSda603NJNAV5lB8ONJjqpySPh3WPnK83pu+SyKE/4I8DLaL2KcmKsAoyxBYh6L8kWnLc2MtSQn+PC3hHT1muCa8kL2Q3ERIlOc4U2/xxncepe8oyPryCDDGGXkwiQsa/xM9+Oc4P1D1l2YVKIZZk1oAj0eBoMc0vp7mQAQul6RbmPfJ+cR6dmYQ/XDHYP6dhwEJt5oRZkCE2pJejP5Nwy/GNfroMAxZqU4gG4ZbkhWf8kz5NQktattjrn7swYKE+z4dbkKG/w5t7JKRoZ4q1fjrLE9Q75dmA9JBLsuhNzyYhRJwg5vrrKgxYhIEbwy7IhaINvZuET5BH+eso9RiwCAUfh12QIfbGz6V/k3DJ8YN+uwkDFuEgD3XCL8nryp5NHyfhkePL/LkozT7TYeTZ8AsytPm8TE1Cgn8Xpf8eDRiw4MGev5I8lp5OQkDWSf5dlP57DKHOhYhbIyDIAuJBejtRnTLapACyQ7GKKhciZkVDkAv0q+nwhId5pUZLalyoCP2NvSNtUNOy6PNEWbSLtbwgHONNalzIGB4NQYZYLk6h3xMlSS8nNgXhFOWRS4ULGbmoEBVJ/iB2FH2fKEfG8WJeMC7RmfoWQu6JiiBDf5TeT9QLV4wMyiFmUN1CyLeREWRRoF1J/ydK4W+ZzaKjBg5S3UJJ4+hIcm65dGoAUWd3XFPsC8oZelPZQsro6AgyxPdnnUgdIEqQebJYGpwrLKKyhZSdqBwlSX6TSkBUoIz+TnBu0JBXpkNMjygJMvS7KQYkcES3IJ1gKFUtxPwQKUEWB/X61AMS7GFebXEgOBeIYy1VLdQ0jZYkb2RZThIgaaeKlUE6wM1UtJAzIVqCDPFN1nHUBRJQ9Fi8F6z5f0xFCzl7cU7EJFkbSmEgwUSPewZr+rWQR0ULPX2itkeGfiO1gfgfPa4fTCGhv8fjVLMIsDxygix2a5WoD8RXMk4X64I2/BVUs0hwQ/QkeTEbPBF/o8fvB230ralkEWFG9AQZ4mWKBPEN7b7gTf5dKllEKMBFEZRkrS11gvhCWnaQuceHRlXspZJFhteiKMi74hWoFcRzsk4Sy4I390epYhFiN6pGUJL1BRnHUy+I19kV41Qw9h+pYpGiXxTjyBDPUS+It3J8iwqGfjkVLGKsRnoUBblQNKdmEM+IV9B2qWDoY6lgkeOWaO6Rc4WgbhBPECeIRSoYeWXson5Fjq+jKcgQc7OPpXYQL8IVw9QwcR7oRZMroirJT1A7iPz98eWiUA0DX0rtiiTuK79dgv5orWATVL0x9YNIJeN0sUEN825F5Yoo+1DDlWWciwMADuJO9ST5z3JnUUOIPMqID1Qx7g+oXJFlsCvLqH34Kfl4WD1JnhU7mjJCJKHdqYph18QB6lZk2Yjyrqxj4ZEnDVdPkntRR4gcOa4k9qhi1oOpWpHmXlfW0anIk15W7Sp1nl6bWkJck32smKeKUaezh17EWezSQiYXedYrqu2Rl5x1IvWEuN0fP6WOSd9KxYo817osOrWqyLNGqFbd4kXqCXGFXk/kq2PQs6lXkWeqSxtpgFx1d8mFWhNqCkmatFPFanXMuSEKqVeRJw91XNrJ9cUOfhU73ttQ4b/UFZIk4k2VjPkVqlVK8JJrS7mlWPvbQWpJ8nvUFZJc9LiFSoZcGdupVSnBNmS5tpbORSS5EL3UyrfoRG0hjsk4XWxUyYwfolKlDI9JsJe7ikhyPu5SSZJ36Br1hTg9zntHqfNpLKdOpQwbXF4QKS3JB9FeJUmeGStDhSFOosft1UoYupEqlVI8IMVqigYu9qK5SmGLLtQYYpuyZ4tctQR5JjUqpfgNcemSvAl11bHo3ekZ1BlijzJimhyzq415uF/CcxqggBqVYtwuSfruLZIsuQzV1AnC5bDcELEXrugsy+g+hNvqBIfGaOpTyrFImvQ9UeSpc1FBnV1yV2oNSZzspoudcgyuHQDgMtfPqcKWTSnJddKkb0yRp74LXRVB3pdWmXpDrDlKzJZjbuXxG4BVEp7Uj9qUknwhTfri+KTIc59UZ4/8dewoSg6xClfcK8vYngEAPC8h4e13alOK0kSa9FXEd0eeWoCO6kSS76bmEFN0Tdslx9DqYx8A4FLXT+pIXUpZ3pMofdnYcOS5O3GxMtkWaXHqDjHbH0+Xm6b2rYQn5VCXUpZ8NJAofs2KFB36XZ18i4+pO8T4OK+jLCO77bDZd3b9pMas8JbSjJEqfr2KPPlzSZnOEsIW7ag9pPTu+P9kXQapjHUAgHVId/2st6lJKc0+ZEsVv6L29IIqe+Qt6f+j/pCSgvyuLAMbftjgn3D9pFrYT01KcYZKFb9M/FDkcE+Z+hbjqT+k+HFea1nGdTEOAgD2orrrZw2lHqU82yUU4yw66hbpKJLruhi+tNGMGkSOcPZ/5JXa/PKwsb8mIfSxjXpEMFCy+HUsci6xABlqCPLqrJOoQ+Sv47w3ZB/nHZSw9+hNLSKQVYyz6Bhb5OmqdN3TB1OHyCE5vkJehG71YTOf4PpZ6cX6B5NU5iHJ4lcJK448uxC3qVGQM09UpxaR2Bn/FH/IMqpnj+SPNpRQOJEQHM7Xkb1HbnL4pAMAduACXqQmyhznDZZlUOdjz2ETf1/C076jDpEj9JAuf8VrwKmRk8xueylPvKo4KMucph35Eui+BkFLahApwlrpe+Q4vvbw4DDJsTXjdGpSKnOUmCPLmNoeMe7pEp72CTWIeLxHPh87jjz9AK5UQ5Jfoyil8nFeF1mGlI6lR/bHV0goTZRPBSIe75EFehZ5/gpUUkGQC0VD6lKqyvGZYpssQ+p/xLA/kpyWRMghHvSgl/ncIs8fo0Yc+cfYMdSmlERMkFfacOdhoy5AY9dPq4G9VB9SilUSaqOUvle6v0gC3A1qhC3uoTalohxfJs+E3jxi1DIq2D5L7SE+xZEFBhd5/hrJ17STHLk82ks5yv5D/CrLgBodabWej0tcP60CNlF5iCEbUFG6/KXjZ+XCFuJlKlSq7Y8fl2c+s46Y8zuSD1oIKU5/D+SvWZEj5AK0UUGQC+K1qFEpRFplcUCW8dxwxJjzcZGEY5blVB1iSq4nQYWiXalXo7IKkvwlVSqV9sfT5X3hW3rElCdIeB476BFrBnsgf1WKhcleVaPYUGvqVIqgt/KiKc5+nC/hed9QcYglOyXU2S49ehR5QwGaq5D+tuaMf1KrUuM4b6Uso6mMP4+Y8UgJz2tKvSEJGeaB/MWxuMgbFnuQYJfE6Eu1SgG0/vJM5u+OHrul9D57n2pDErLPkz4f1xV7x6MqCPKesmdTryJOPE3skWUwdYpc4HhGyvPyqDbEBt4kp00v8oZdqK2CJI+iYkX9OO89eeYy+Yj5bpFy9v0KlYbY4iDqeyB/DYvUSAamKJH+ptWgZkV5f9xIZonvgiPG21fC887BbioNsclkTwSw+JZAiYvU06hakSX7WLFEnqn8XU12LSpIeN7TVBliGxk1U0qPakU6UgMrlGiAql9K5Ypqutv98sykbRHDvV9KN77NVBnigE89kb8+xd7RV4U98iI2doqmHJ8htsszk4VHjPY3KSlCj1BhiEOu9UD+KmBDkTdsRw0V9sjtqF5RPM57XZ6J3FLEaO+Qct+PHaaJU+Z4In+9i71DiVt7q8QJ1K+oZR/XFAXykuiXHDHYH6FLeOKdVBeSBG093yMflNA/XcIe+X4qWNQCFp/JM497ixjszVKeuJjaQpJgvg975Okq7JG3ZPyLGhalcEUzmfVjfztirD9I2R+3pbKQJLnB8z2yN/twx3vkR6li0eEY8bM3ZVjkmOpX1BWSJPN82CMvlrLtcDm2lz2NQhaV+PGdMncP644Y6lxJF0wIUXuPfIcCe2RtAJUsEmSeLDbKM4t+0l1hKjWFKB5HXoZ48IK8K/1/VLMoxI8HyTOKykWubyyU8sT6RdrnEKLKHjmzSGFZAOiqwh75KapZ6MkoK6+6W/HrzZ2kPPEN6glRco88uNg7VqlQIXkvy3GGf3/8pjyDqIrtRwx0iZSDjmzso54QJffINYoUlwWAHiqkvz1PRQs18VqiUJ45PFPEPO+WXOCeENX2yGOLvWOdlBJaLse+jLJUtTDvj2fJM4asIpWwVkr5AlcZ26glRAqtPamPXFDsHY+osEceQlULb7rbFTJN4YkiptlLyhP7U0eIJD73RP5mFnvHHyrEkfdknE5lCydlxLfyDKESthwxzG2oJOGJGUUymglxy5UeyF/HEu+4V4Vci/6UtnDuj1vINIMBRcxyqJQn3kcNIRLxoodIHKuLvWOJEnf24v+muoWPo8QP3txcypPS81fHMmoIkUge6nogf4NKvKWjCnHkHpS30KHfKNMEeknfiXSkghDJvOZJ8tuBYu+Yp4Igbyz7DypcqMg+Vvwq84vbyiIm2VTKM7+lfhDJ7PWkv8dHJd7SUoU48p3UuHClu90uc/nvKGKOcgoKXU31IB7wrAfi16HEOz5TYY+8Ous4qlx45PgEbY3M5f+uiDl29mTXQYgMclFZuvill6j8VqhEDxHRnjoXHkHuJnPp2xQxxs1SGqPXQx61g3hCbw/E7+US7xipQtDix1gZKl0oOOOfMsttFk+OHy7lia9TN4hHrPbg8kajEu/YhooqSPJF1Lpw5B8/LHPZL0VhkS9rDSQ8sTr2UDeIZ9zjgfj9XOIdD6oQtHifWhcCMv4lcmUu+1tFzPArD8oaEiKX7z0QvydLvONnFQS5ID2Deqd+/LinzEU/p9huVsaBXgVsomYQT2kmXfzqFfmeeIhrWYyT2MmvEOu9uqck50CvJ/WCeMy7HojfDyXeMUUFQd7JS9SqC3JXuQk/Rcv/vCzlwvQK6gXxmAPIli5+A0u94xwVDva6U/MUJus48YfM5e5SzAQvk/DEW6gWxAcGS5e++qXe8bAKe+RVsWOoe8qi3yZ3uecXMb8lUp44j1pBfGCjlPBa8bG8xDu+U0GQoV1L3VOVo7UVMpf6ymLmN0jCE5tRKYhPdJEufcNLveMiBQRZ/4zCp2r8uL3cpR5XxPQKcaGEJ06jThCf+Fa69LUs9Y6hKuyRC+PlqX0qcpT4SeZCV8YuyeZdH/nUCeIbl0uvabG1xBvWIa6CJA+i+KkYP24td5mLp6fJ6KE3hhpBfOQt6dL3fql3XK9CFHlzxvHUP9UoI77zLu/yIKrzwjQJGXslWG3x8WCpd0xS4mBPb0UBVIz4VXKXuEkxs5NRAZYXponfDJQsfHVLvWG7B9kcSeyRZ1ABVTvQm+XdgZ6MUirleWGa+M5q6THelaXe0U6Jgz1WtVAKrYbcBa5U7ECvALUkXzEhxB86SJa+N0q94Q0lghbicaqgSoI8Vu7ydi1mcgskPDGH2kACYJpk4bu71Bs2qZFpsTH7WOqgKnJ8pjggd3m/KmZyT0qolVVAbSABkIdzPY4iK1L3Ddo1VEJVEt4Gyl3a80rkC1/q+okvUhlIQDwuWfg2lHrDCDWCFu9SCZXgrBPFFrlLO6iYua2SkFC/kbpAAuJ36FK9Y5rB0aESgnzg7P9QDVXIr7hD9tIuK2Zuo1w/7zaqAgmQVp6W4QSAxmpkI99GNVThQsgvcpe1aQljc38X6XNqAgkQueXqWxq8ob8ae+TZlMPgD/SayF7WUcVMbY/rxPcLWMGCBMpeZEn0jyqlmjkBM9UQ5EJNpyIGfaD3meSvPVhfzNS+dP3EIVQEEjAPSPWR1aWev1uJ+3oC2sNUxEBJryIK5S5pixKm9pTL58WLNYEiJAjmSPWR6QZvaKnGHnkJNTHYgMVIbwMW7nMsO1INSOAUop5EHzH6zjdEDUGGqE5VDIzMk8VO2QGLdZIjyJ9SDYgCyOyxd4fB8+crIsjaAOpicAlvnWUv5zUlzGy2y+fVQB61gCjASonZyI0Nnp+HKmpI8jLqYnCC/J3s5RxZwsyedvm8h6gERBGukVh6q9Dg+R0U2SOnZVEZg8mvqC1/MVdLPqqYSx0gijDW0+vTCkWRe1Mbg9kfj5K9lCW/iu1FeZc1MVhSiKhCLtKlecq3Bs//QhVB/oHaGADxf4vdspfyiRIm5rax6QCqAFGIG6V5ytuGgq8rIsl6JvXR/4S3LvIXsmSA4XWJXfkICZq3pXnKM4bPb6DKHrkX9dH/gMVC2ctYtVRGhLv7TQ0Mjz4ICYodqOBJR/a/uFcVQZ5DffRbjuvIX8a7ShnYVR7sIggJjk6SfKWT4dNHqSLIBen/o0b6K8ivyV/Gd0qYV57L/cQy+j9RjCkeVUQ8xAJVBBlaW2qkvwd6e6QfBGBLCfNa6up5l9H7iXLsRkUp3lLHJCSiiiCLN6mSfmYg3yp/CUvfPprs6nnD6P1EQTpL8ZYMk/OR81QR5K2xo6mT/gUsZslfwj6ljOsxV/vt1fR9EuGgxV7Dp9+gTtDiAuqkT6SXEwXyF7B0p7C2Lp7WnJ5PlGSHy8tOf43Nhk/vrY4gs8iQb/vjBz1IJcfWUsaVzS7TJILcJMVjVhk+e4w6UeSFVEq/BHmxHxHkXcywIJFknBSPWWL47K/VEeTCCv+lVvpAWmUvlq93KdP6ycXT6tLribL8ibgEj5lv8myhTtCiBdXSj/3xIC8W76NSpvWRVHknRB1aSPCYHJNnV1RHkIdSLb2njFjpxeKVLic4zMXTvqTPE4UZKcFjvjZ5dgN19sg/US69z0Cu78XS1TIwrIeTflplHKDPE4VZ6eEOuY1CUWT9DCqm1wGLEV4snVEj0uRv/d9OjyeK09CzHfK9CkWR9dZUTE/JOk5s8WLhjLroNpVaK5YQlejnmSA/rpAgi+HUTG8DFld7s3AzDQwr2UugcWyivxPFme3aZ+aYPPk1lQR5CTXTU7Sx3ixc6VtH+Um3u2lGbyfKsx+VXfrMQpMnT1NJkJmL7ClHexOwuMDArHKTftoL9HYSAtxWRl5u8tz5KgkytCspm97tjy/2ZtE6ST2H/om+TkLAGy69Zr3Jc5cqJciiL3XTuwyL571ZtMcNzGpR0nVi2baJhIG1Lr1mp8lz16glyB9TN70T5N+9WbQJEg89utPTSUi41FUxrnyTp+aqJchbY2WonN7IcXWvFm2egVl9mOSz3qWfk5DgJvWtiulTD6glyIiXp3Z6I8h9vFqyrQZmNUnaFWxC1ORTFz7TyOK55dU61mN3PY8EeaE3C3aOoVGNl26mhKjFzqRTOwXaWjy3ulqC/AK10wPiaaLQmwW7xtCokiu0zSpvJEw0T9prulk89UKlBFnPoXp6sT++x6sFMz6GeyWpZ02nj5MQ8VTSXvOkxVMbqBVF3s5jPS8EeaZXC/a0oVENT+rS9Db6OAkROUl7zZjQ7JAF0stRPyWTdZI44NVyGZvWCCltoAhRmf3ITNJrPrd46vmKCbLWhAoq+47eFd4t18eGRvVqEk96hB5OQsZ1SXrNGotnnqeYIIseVFDJ6IO9W64F0g713qN/k5DxfFI+UwkFFs88V7Ud8htUUNkR5O+9Wy7jv/XJ3PRfT/8mKRFFbmr5zJqq7ZAXUUGlcvZ/RIF3y7XP0KjedvycC+ndJHTsSSoXuavlM2uoJsj7Y8dQRWUGLFp6t1jVTIxqmmQjJURNrkrCa4ZZPjFLNUGGnkkVlRmwGO7dUjWQ9lVuDH2bhJA+EhucAkAedOUEWbuCKipTkJd7t1SXmZjVYsdPWkzfJiHkgyTy7XdZPG+zcnIsoN1JFZVGejkvl6qZiVk5LVCfiYP0bRJCNjj2mcstn7dcQUHWB1NH5e2PO3i5VG1MzGqbw+dcS88mIcXpRY6elk+br6Agi8nUUXmXQt7wcqnamxpWRUfPGUC/JiHlLoc+M9HyaZ+qKMhMfJO4Q17t5VLdbmpYzkqkfEC/JiFllEOfWWn5tEkqCvJO6qis/fGZ3i6VebKas0ulq+jXJKTMc2Tp9RI8baSKgoyM06mlcvbHzbxdqAdNDaurg6dkWV4lJURldiMuseb3ACUFWa9NLZVzKWSgtwtl3pT0aQdPaUWvJiHmEge2PjPBs25RUpBFM2qpnJDFDG8X6i5Tw5rs4Cl96dMkxNxr29IrYE+CZ12q5g75NmqpDMqIbd4u1K2mhrVY2rkzIWpjvz/OjQmeVJB0hWWPBflRiqmMCHJFrxeqvalp7XFwBfQX+jQJMd/YtvTxCZ60Xs2ABfQXqaYyIsg3er1Q11kYl92E+Qze0iOhZqfNzUcGcqVJu8+C/A7VVEYE+QWvF8rqht3NNp9xKT2ahJyGtiy9Y8LnTFBUkLWvqKYyQhZzvV6oJhbG9ZzNZ3ShP5OQswQ5yEEOZmEyRuIxdEUrg7rGiXviPKGoIIvlVFPXZB0n9nm9UFZl5T+3+Yzn6M8kkmzBHLyB+3ExBAQqJ8ywANqqKsg7qKeuScv2fqEqoNDUuLbafMaH9FwScXLxGaYk/FeFqKaqIBfGjqaiug1YdPBjqayOKerZesJy+ishAH5VVY4hkHkyFdXtkd7TfizUEgsD68YcC0JsM0VhQdbOpKK63SF/7MdCfWFhYO/a+PzF9ENCACTXDsqvES9PRXUryKv9WKgJFga20UZ+Zkf6ISEAgGtU3iHXoKK6IuNfotCPhXrB0sQS38zvRz8kBECew6YOPu+QL6SmurulV9ufhephaWT92G2aEFvkYwquUneHzM7TLo/0bvBnoZpZGllOws/PoicScoT56IJ0FS9Pt6SmutshP+rPQlVEvuVf/Wz2CiHEEavQD5VVE+R21FR3R3pj/Fqq3yyNq4flZ9ORR/8jpBTbMBTVVRLkG6mp7gT5a7+W6iNLw/rS8rMX0PMIMWEPhuMcCnJEBHmjX0s1OMHZsdXf+Zb0OhKZPe0vWIzF+B45WIQ1NipX2GEnhihxoVq/iZrqRo5P8CfpTUCgUwKT6p1U12pCwrCH/QrPoTOuMhTNCqiDVngIo5GDDS7esgPPoQoFOczEy/u3VOcnMKefLT77FH2ahJJ9mIyOjhou1UJnvIbFlofg5mxFX5SnIIc26e1iPxdrbQJjamr6yXH0bBI6tmKQizBCFm7C61iTxHv/wD0OGqNJHu2pqm6S3m7yc7HeTWBIb5p+8nN6NwkVBzBUUkraZXgaC1Hg8P0/oh0FOYQ75If8XKwHExjRLlMT/pkeTkLET7hEsu/UwUDLiolGfI6LKMgh2yEP83Ox6iY0of4mn9xEHyehYQIqeORBl2OEo2O/g3gZWf7GkFtRVd3skCf5+/dzWQIDWocMo4IlSR5wEOI/g70u34P2+MyBR2xENx8jyqxl4S7tbZa/gvxSQvPpavCpbHo5CQnP+ORJF+IlbLX9U823UU9R0g65HlXVjSD/5K8gJ77gscTgr/nl9HMSCsb56k0V0BU/2D5kfNaXdDitJlXVjSD/6XO1VGxMaDodS32qHT2dhID5hgE3r8f1+NLmz7cMzb338ApU1eQpo+X5bT6jE5rNL4jznh4JHbttNuv1YjTBB7aiyvl41dElFeej3FmU1aTJ+Jf/ptPChtmUjCP3obcT5ekd8KXl+phgqybiMjT2cof8b+pq0pQ9O4CrlTYqG68pkTb0LL2dKM4yJcrF17MlyvvR27O8i9jR1NXks5AzgzCap22Yd/GWTqPo70RxOilTkdieKM9EDS/evoOq6qa0UK0gDOY8G+aSW8xc3qG/E8X3x7oygiwg0BDTUJjgZ16LK+W/eSlV1U2ORcNgzOVTGyb+dpF/P4MeT5Smh4Ld7a7BvAQ/9R50kf3WWVRVN/f0mgRjKtfbMPFCtDzy7+fR44nC7FGus91f4xb8nsDLhpbKaXI13qaquhHka4IylJ9sfQ38K6vzF/o8UZh3FJXjQ5dHnkrQk+QDmdnTz1FV3RzqtQrKTLrZMvRBh//1Svo8UZhbFRbkQx0ppyU44Kso6109qapuYsjXB2UiGbYKb+8/nDG5kT5PlGUfKikuyAICHSyrxM2V1fqJxTdd7ZDbBWcgPWwZ+y+oAIEd9HqiLF+HQI4FBKpigkXmxfdy4uCXUVXd7JDbB2ceGVhty9xHQuAgvZ4oy5CQCLKAQHuLffKXEmLJ+jlUVTeC3CFI47jflrkX4Eb6PFGYm0IkyAI1MMv0N5nsNpu6MOskqmpIQxYCcZuNmbbQ54nC1A6VIAvoeMr0atZL7p69jprqbofcJljTuIHeTEJObsjk+NC4DtsMf5tCd1fAeS3EZR7ytUEbxmf0aBJq5oVSkAUuNinylYs6yRenf4Wa6i5k0TT4Qih76dMkxLwdUkEWqInvDH+jucnXrXuQmuouZHFZ8GYxiD5NQsyToRVkgUr4xvB3Srays3YNNdUV8QuDN4p0m0d7hKhI5xALskBlfGvwO21PsjRnWhY11V3IopoKRtHUVp8DQtRjAxqEWpAFqhrWlRmdzLMKyv6DmuouZCHUMIpn6NkkZOThU3RUokuI+0oXWw1+u/rOAxYrqKguKXuaGiaRju/p4SQ07MfrLnIRVEyCK/0ddaTz50ygorrlGFVMogF20s9JCNiH13BehMT40Bhc6vfc5rwCHHMsJAQtdqhiEp0TtpwhJGimoW7kxFhAoDyWlfpdH3B687YR9dS9IC9XxyjYypSozO+4IZJifGi0QEGJ33emwzoWZU+jnrq/q/eVOiaRgfn0eqIkhRgTiqrHMjtd7nZW/e13qqkMQZ6k1t2h1fR9ohxbcWPExfjQHrkkrZzkWEyimsoQ5KFqGUVj7KL/E6X4AeengBwLCCwo8ZsPdvLpXlRTGVdDHlGv1QyviRB1mIIKKSLHAn1L/O6O6nSwV4gUQb5RPbPoWup4gZBgGI14ysixQN0Sv7395lRaXsa/qKYRqWZRegygEhAFeCKFxPjQ+LXY77/a/ifnUkulUO4sNQ1jKNWABMyglJNjgY+LzYCD4vtPUEvlUEbsUdM0hlERSIA8Y8NGr8W0iAnySyWySxhB9v9qyM/OlqwCzsOlaIm2uA5N0RCZnhnHi1QFEhDjE1rneZiMQhRK6NSs0nik2Cxsth1BzjyZSion7a2G2GZv0uujL97BUoMciE1YgHF4CI3d9qwtNV6gMpAA+DJBFTcdfbDn8L+tHSlB7llsHjbY/dwcKqkcOa4ptti5rjEIi20Z8mZMwa1S98z9mHFBfGYVqibYG+cU+ddXRkqQexSbiUU2P6UPpJbKyLCoJbYmmuo6eM1x17tdeAOXSzORe3GQGkF8Yx+usLTH1thU7N/fHClB7l3sd3vfriBfSjWVkfCWoNJbJp7HgaQNew7aSjKSm3h7j/hGT0tbfKBUyK5vpAR5ZLHfbai9T+0960TqqVs5rpoodnwdfndt3N+hpaQL1axxQfzgM0s7fMqgROyYSAnytGK/W3d7n3qfeuqSjLLaGsvKpnhOUuy2ENOkVAKoyUpwxHO2WR7RPWf4mVmREuTiVZHttXHSOlFRXVH2NLHEaoJrYJZUM9+NvhJ6j1XABCoG8RSrHeETJp9ZEyE5rlnsG8A6e58qEP9HTXWTd3yCnmN9n/1XD0x9oZTuvN2OJBsRIpv5Fmmbd5r2sylEjcgI8p3FfrN3mfLmiyCPsprey7HRI3Pfgc4STOZyrKRyEA/IQ2NTq2uG/RafbBsZQW6NQUVGM3bS80GOu1lNblPs8NDkC/GChKsjVTCF6kGkY344VznB8XbqlSAqlvKWSVVNmrRLtDzzqb0CuZ6b/UxUkdIQdRsVhEhkD2qZWtukBJ+dlsJyrK2gqiZ/L0+3upfX2Ac5BoCfcYEEQzgfc6giRBrPW/zxT0RuStVMLjGGU1eTJPtY8Y2VwG3wzfg3J7gLZfOrEnphN5WESGA3qplek95u4/NXpHLIIkdvFTuG+uo8evy8VVz2F18dYIfdA4OEFbdmUE2Ia0aZWtg7tj4/IKWjyAJilX4bRdnZzbyrRKHZdGYUK5biDztxjSRjuM/WHoYQM/JQz8S2rrJ5PerzVBdkCIhleqtYGSqtvd2xELnmU/l2IG6wE9dKMoVamExVIUkz1dSy7G5UDkg5qo7AEd9X8QpUWzvR4znmk/hogJG7FtJMoSPWUVlIUjQ3sanbHTzjbsrxobFP9IgdTc213h8/a9WEJsjilttwiTRTqIThyKe6EIfMMz00Xu7gKR9Siv8e38TTqLrmyW5NzKPH55Wo7eo/q3GuRFNoUaI4CiGJuNfElto7esoeVKYQ/z22xBtReQ3RNfMi9PEADvNK86NUU87AIBc1nEmqYS6ksx0+6YFQS2gGzkEd1EcTND0yLkZ9nJtkjrWWJ7pSfR1Gj4co4hRfSKgFV3Q04KURYpPJptekCh0+aX4ohfhVbE1QLiEff+JnTMcL6IwGzkofvMxocsno8ZPm03W9QhHX8ZLNLI6H2WWE2OAmEwtKptRro9DJ8VDHv+NWTEYXZNndJ0/KOJ4q/LccXy4KzCufblTKMXpKN7a6+IZ6QyzZYvLd7BzL6m5mjA6ZHD+W9LztxVsWtfGKjfd4YeQw5c4Sm8yvHX+mmGscwNXyL3WiH+PJxIJRtnov249HVw+RHA90HJQpTiG+sld49HVeF4nFYrGj9M/MJ+lJBZ1jnSeFvi/z+VI4CRNmF/iTPYMYHBo5HiRpBmfiwsRv6005jol+wqLcdp6S7pEj+XDvr/PjIcxPJobx0LhJMmiy/SS3oGIYygGV6C3tjr0YjPLWbywUzVNdjhuIfLPpqY61yrrIUI9M8Fqsov6QEkw2/TKfPE8qL8cVPGjwsBh1rd+6XYhUvgpyplhv/tdR5fpoBbjKIzPMwngqEClGVxNbWezimTsV77BXA996Mpe5aGf95tkpmwKXfayY7cXJqj9846Ex3ootVCFy5I9/tkllcG8OClUYl3r4TTEfj1u/vVuqhitGmE/K1YFWrrBHBw8NMluJu4lEBRZLzbD4m4PK5iPf5XnP9tFW9/r2pGTYQtxuviDVsDoEjrLCk6O9v0Y6hiR9ZEOihNl5xTTXT16oYEundAz3ZVbHWl4TSb3o8cXigHn0+JOQuMqDHhtnB5+6BxKVaW0iXDL6rj+imBzXxXzf5vUxi58jrW5qyXENsdN8MvqHxlU2el45q46PBkpUJA+VTOoFymCXnexc30Y37PR1ZptbHe2lDhlltTXhjh7/zWAfvsIxdJHK/GBiFy9Ie34FJcS4qgdJbolYZ3FjMWX2yOkZYrlVssuaULnLLtT0wVg7YhuVKUUxqzsh75vTGAXk+LaAKtZMsaptkRJHeXW0zVa7wa9D5zBjfIqtfU9tSknuMbSH8kkVFTKjW6BiXFvC8WSyFJr3yyzUKkVfjtuLfVZLMyaUMb6GPt1bmkh1SkGMb5Y1l/qOg4kuS3g24nhIyuFk8nxvWjlZGxlpMT77P9ok68W5L6QuM8038+2laG0P4hV/mlhCP8nv2Y2mAchxa/yowBx3NW2DWva06O6Nm5lfkj40rgttAcpCiT2pEyfC7aRKpRCfmNjBVOlv2oIrfRXjC/GRInP8m3k29h3RTHKrKT5PtDyNsT3EbrPQWcMYV6MhfqVOpQzPmljBOg/etROtfLLhbLwqNQbullvMbkTkRG9nXFEba94N5O9s23Uhd5w7fNxbnMNr1SnD7SZlN71hH271oWjQS55fjHbKt6YHe+XSI3X9QxtrXlyzqMAsC73j/I6MCF4vJUHT0CQN0rvw2zAPCwLUxouKdpC8Otol68v+Q79JfG3368tPkXCd3j4fiPTkAV/k2Wsijt720ZmHOh7Y6xV4R+ErX6bNi5eEP0hRXTwvcu0u0wX4LSLOs8V2h1tZoy12U7MijVmdtykev3cn+kncJ2fiLuXvF+xAplliXvnQSnG5s8S94jsnS3Ul1kfIfYb6njZ0NbZStSLMRJN196P74lJcL8FCm2JMSI7ru0SpOrI4Rb9Jm6rlOVus+7EvYl8w6/guyQ3Y8inCDDDpvehXguh36Jxkgc44mmEYlodormea/S4zwyXFJ+hNxUTzUpoqlRLxngkBJNefh6VUrohyk0k3DT9ZhSG4wpE93onx+DN0c52Hqsa/0UFxSkgaMOlNxZtidzIicn2kQhV/k4/LApDkah51HyNB08Ckn4b//IHR6I7LTXKJ4qiLtuiNyaFoLGHGPWbZyC2VF+O0ymKQ2JhsHuLYCJeT/Dyg/rwfUb0iR56J/D0b4M90AEvxNT7BRIzCOEzBdORgmVKXPJLnA7OaFkMVluIz/inucHZwVzz61SvyPTDaBtT4ZgIVLGKsMlnrdzk1nrAT5Y1nfLGqFz3OFH3FluTrOt0RmRQ3KxYH1KdMD2WtPGLOl55XQia2NlOFFf6rnhhXEm85zaIoujPuHqoTV3d0DaiUISU5Wpi14dzMqfGIF818q7lSYqxrYkTyYlwNfbE2pZZ1TWBNcXSMpVdFBuMmnJVRyKnxiO/MPOs5ZcS4wn/Fy+Jg8mnh45UrJOIHAwPrvkBJjg7GNcgu58R4Rp7ZbduFquyNW4lNyXZLHpjC+bHbLZonei/J4+lZkeByw/W9nRPjIe2NvSpfgVzktLiYnlz32PuRk/J9kkcG2KOMu+RocI7h6g7kxHjIy2apb02CvoF3s9jrVAgqohMmYy9XFcBBk6R+vyT5HS5ByNlrsravcWo8ZJGZID8VoBhnHK+NdHoxoRMms/ZYMd4LtJNvOj7lEoSa301WdhqnxkPyUc143r8NTI7Ty4m5Thz/RrzDPm8GFAbSNvLvUQnfcRFCzNcm67qQU+MpHY13yHlZJwUTqjhP22zX5S/BEKzhCpoyN1BBFqiREhdxosq7Jqu6gVPjKWanP2mXBHH94yKx096+uBP7uiX919a/UR+buAghZZiJ57FPjLf8YOZNfXyX43gjsc9OB7xnQ1hcLxiWedifzG4m+B4uQyjpbZJOSrwlD5WMgxYz/M45rif2JHLvLAzCDq6ZA3oELMgCN3FPFUqM+00348R4ThtjQd4VO8bP2HHFRH3wMvCEoh1jVWYjKgcuyX25DCHkWsO1vI0T4zlPmZVHq+XnBelfrZ26JZZxpZLimcAFWWASlyF0GOexP8yJ8ZzPAu+ud5T4xMqdy+N1FjRJmt2oFbggZ2IxFyJkGFdVeI4T4zm50I2vW73jV7iil3VVCuazumOsAnvkupFvDBAt9pmsIy/F+8HFxrO/KVbGj1S3mlalNdvQkV2TZ7bAvo62yOdShIa1vKcXIA+YlSTI9F6Pj7FqyNSaSVNS+EQBQRZ4igsRGsyyYdnO1g/eMvOhzt6HK3pSjv2gpQKCrONzLkRIMGuWy7uXfrDMzIfe9bpuxf/EDjP3vQb7uDLS+M7koMDfUZsBqJAwyWQFt3FqfKDArJ75ttjR3saPXzGvg8AqFXLprETYguXNw8EIk7sAzHbyh9uCyEXWKol8sw7Rs7kmkvnDrMm4z+N9LkUIeMrkGw7xh1FmdZEf9lKQ3zBz2he4Ih7QRwlBrob1XArlechw7RpzYnziFzP/meuZHJdLN9sfN8QBrogH5KKqEpLcjl98ledOw5VrxYnxiULUMPaeAvF/Xu2PnzZz2FlcD494UQlBFnibS6E47QzXrRMnxjfMzny0Tp7IcdZx4k/jF3bmWnjGPlyghCBns2af4lxluG73c2J8Y6KZ97zvTf5xM7Oabsyu8JJJiuyRH+NSKE09rlrAbEHc2Hf2p53qhSCPMXbUrlwJTylAEyUEOZ3V+5TG+LRhKCfGR5qbXbC6xYsL01uMX7aI6+AxsxTZI3fgUihLvsk1IpYW8pMXzHxnlvxmTbWMX9WCq+ADbRWR5JlcCkXZzhxyBVhi5jkF8TTZAYtuxq8axVXwgV/MolM+j0tQwMVQErNab6xF4i+Xm/nO47JT3iYZv4hxRX/opsgemcUcw7U3m8+p8ZURZp6z9awT5e6Qlxu95lxeGPCJDSadbf0eV3MplGS+yXot4dT4ykbzrvEyC3GedaIoMHrJPVwB33hCkT1yDpdCQcyKb67l1PiM6XnPMok9qPVzWMEiaHaYXc30/Ro1UY8PWHxTET409x15e2S9qfErPuD8+8goRfbIbH+qHuNN1iqPU+Mz+SbdvwXEpvi/ZUWQ7zB+xY+cfx85gDpKCPJ9XArlGGm4UpU5MQEwxtRztKdkCXIP4xewm4S/vKGEIFfGbi6FYjzLasjKsBc1zQQ5T68nJ+mtP78QqUCeScUC1n5LdfobrtPFnJhAeM7cdzZIKcapP2P08EzOvO9MVEKQb+RCKIZxG/pmnJhA2I1sc++ZLqHLnnjZ6NE1OfO+U4CmCghyBk/vFcO4Fm9bTkxAjLbyn5c9at10Iec9AOYosUeewoVQihvZoFYp8nCZlf/c43aH/KbRY+tw3gPhVgUEmYXP1aI5V0kxFpnf2YMoEM3dxZBfNXpsLc56IKxD5cAF+QIug1I0MlylvpyYAHnMyoP2ivPcCPKLRg+tzjkPiFcV2CNv4DIohHGG+jOcmAA5YN1aYoOuSW5vyrTzoMhX4GiPtZFVIstwjUZwYgLld1Sz8qGfxSnJCvIAw8YkzEMOjCXICFiQ2RxIHQpM+oW8yakJmK+sIskQX2Qdl5wg32f8wC2c8cAYGLAgP8glUAb2C1GX0dZ+9FJyMeR2xo9bwfkOjL2oH6ggM8dVHZabrNEsTo0C9LH2pJuTEeRLjR82j7MdIME2P72MC6AMOWDxL5UDSpaJqvvSsp0LcjXjh33M2Q6UhwIU5PqcfmV4l5kwin+bbWblS6sq/NepIJ9h/KhXONcBL/TFgQkyK4mpw8swPnQ/wKlRhI3WpXM/dVrf4iixz+hBvTnTAfMjygckyPU4+crQG7y4pTrLUNXKn/o6vTy9xOgxHTnPgTM0IEFuzKlXBuM+bs05MUoxy/IytXals8S3qUaPacRZDpwCXMfeeimO8dfhuzgxivG6lUdtLXeWkx3yEOOKyIWc5cBZj3MCEOQenHhF2GVyLWQQp0Y5ulpHksvYP9a72/ghGznHCjAlAEF+ndOuCN+brNBkTo1y7LOub3GH/ZDFlcaPWMA5VoL7fRfkhZx0RZhkskI/c2oUZKXV4d7ueHm7O+RMFipXmf24wlc5roaDnHRFML4Jls6kN0WZYRJiEhAQc2wmwGUdJ/KNHvAC51cRfkcVHwW5GydcGa4xXKFLOTHK8riVb/W0e6y3ko6pNu/5KMg5nG5FyENF5liEbs3amPvWfr2avaDFZ+xrqzoP+ZaDzOwaVfjZZI1e5NQozAarzKhvYkfZ2SEPN/pwFbqmQhzAVb4I8iecamUYb7JGn3FqlGaShX/pt9gR5G4sYKI+q6wvaEoZ13GaFaKnySqt4dQozi3mPrbFRrmh+FWMJoaB6VZnuBJGZazkJCvEJaxjEVK2Itt8j/xiYkGuYPzRMZxZxRjsoRzrmMoJVsqpjf/83sGpCcXmyczPtDytUiJFPkYcZMW3MFCAjp4J8jBOr1J8YrJOIzk1oeAuc1+bnDiKvJStfMLBbjTyRI5ZHUE1+pus1PecmlCw2eL2QLxWUhXf6nBWFeRX6ddEMjGR06ocTQ3XqiLvUYaGYeY+916iTOTBxh/cxVlVMj4l83DvEvZnU5BdJhV2W3FqQsNBNDTzusIE3fbE7cYfXMxZVZKnJIlxJQxhXQQlmWGyYk9yakK1dTI9Qh9nHbK4yPhjH3JOlaQAN0tIcuuHTZxKReltsmozOTWh4iYz/zsg/s8qZKHx5D1cbEcDF2LcFOOxm5OoMBeZ1HnbzqkJFYvNvbCPZeKblsfeEeFiRRKHew3QA5N5A1N51pqs39WcmtDR1swb/7Csa2Fc8a0N51NhPrE83KuMy9EMbXELumMIJmMBtnLKQsJbJmv6FKcmdOSY+2gDK0H+wugjdTmfSvOEhSBn4VdOUEjpzNKoEaKp2Z29kVaC/LrRR8qz4pvSFKCDhSRfhj2cohCSj+omOcj7OTkh5EMzD91oEbQQjxt/KJfzqTTbLA/37uEEhRCz1qa8ORtO8kxLDVnc2BP3Gn9kCedTcZagMjtIR4qhJmv5EqcmpJi1l9AfNU98a238kVmcTeV530KQMzCPExQyWoPXtKLFHDP//NhckOsbf2QyZzMEDLSQ5HOxkRMUInYjw3AdqyOfkxNS8nGusXdujZUxEeS0LGN3HsfZDMWCWx3utWBBmhAxg+cBEaSHWaaFbhZDFqy+GmasD/cGcIJCg9ml6SmcmhAzziyK3NhEkDNON/7AC5zLkGB9uMfQU1gw/sMaxxZOTYhZZLZD7mIiyGX/wcLlYedji5t7lbGMExQCfjVZv2s5NaFmv8nJgP6YeeJbodEH+nMuQ8TjFnvkhtjJCVKekSarN5RTE8lvPvow87563CGHnny0s5DkW3jvUnnMStGwiUDYucZZXWRxgrEhDOFMhoptqGchycM5QUqzG+UN1602/5SGntbOBDnzZGMXfpkzGTJ+RkVTQU7HfE6Qwph1mmYZ3PDTwnhtXzcR5PT/GZvCaM5k6HjLYo9ch9VJFMYsW/UTTk3oqW28ti+ZNXGqYWwK7EccRh60kOSO/PqrKIWoA+Oai+zuEnb2mGRAaQ+bCHL8KmP3/YZzGUL2m9ZgFRAYxQlSkp9Z5S2ymLZyutlsh9zF+APrOJehZB1qWBQcWsgJUpAXTdbrVU5N6HnOrADnuWZZFs8Zuy4LmoSVHKSbSnJ95iQrSEuT1fqNUxN6LjUOWOSV/YfZDnm+cVNMEr2/ygICnTk9irHd5A8ofTD8/GLmh/NM5DjrJOOu0x05lyEmH9dZSPIbnCClMKtq3ZdTE3o6mXlhP7OAxeW8sBlFNpvVYYVABfzECVKGj3COyTp9yckJOfNNfVCvbRawGMkut9HkC4uCQxezCaoSbMGtFkWh2Ng03Bw0z3haZlKePvtYbbNxl9u9nM/QY1Vw6BFOjwJ/Mmtb1h8h4aav+eo+6DBg0YGzGQHyzC5tQkDH55ygANmO+yzEWEDgTU5SqLEoibsj7VQzQX6Nxz5RZg2qmTp8NgufB8ZMk5t5vAcQFRZYNY143CzD4jix1bgQDV01KkyzcPnbOD0BsAXdE4qxwJWcqBCzEFnma7u17Glm/aabGn+kHWc0QvSwcPt3OT0+M8XiHmXR8TSnKrTMR1Wrtb3DtFOIPs74IxM4pxFij0UT1KrYwAnyjVW4yZYYCwh8x+kKKVMtiuAK6Dmxo80L0+8wvjTNMo1R+4udblEBjvjBPgxBBdtyXJ2FC0JJIYZYJJsKaLvKpZvvj682/tDNnNfIMdDCSKZyejxnpmU3l9KjK6cshGxBxwTrqt0QM0e8xLhiqnAAl5kaSU1+I/KU3xK6aenxAactdHxlmVUuIKANjVkhfjO+VstqYFHkJ5OebQICt/NOmEfswACTJvBWI51/IkPGHvS2DFUICIgpsWMs5DhenjHF1OIFC2NpwHYE0inAZGQ7FmMBgeacvFDxBS5MuKbajIzjLffH+l3GHxzL+Y0oebjawmDi6MP6FhKZgcZJibGAwLOcvtCwDb3srOmcrJNi1mhTjT+6inMcWZYk+Pp8IWZzkiSwEG2SFmMBwf7godnijEZ1Oyv6dfzfCeQ46zhtl9FH63GWI82AhMZzH29puvyj19GVGAtUQR6nMQTk2P0O9K5pb5Ai++OLjT/8KOc50uy1Ee2qhlGUhKRYhrsRdynHAndwIkOw0u3trufzsaNiidEHGn/8U851xPnElhldhC84VQ5dtLvF9RsnYzwnU2nWoZfNldbyROeYPcRM43QbprxFn1ts79RWc7Jshik6S9gZ/zU46+qSi0H271v+kVbXphzHyohtRo9oxRlPAdZaFQYsNjIxAFs5YZbMRcfEGagOxsWcUkXZhIG2PUdATDat6WY/B3kwZz0lGOFAICpjEHZwygwowExcK1GKD43enFgF2YC+liWDSoy9FhXdDI/02ho/6BPOfEqQh4sciUQNjMQ+TlsR9mCsRQ09N2MaJ1cx1qGfEzGG9pWoGHOGeM74USzFmCpMcywUdTCKF0cAAL+jL6p4IsYCOpMOlWIt+iHTyQpuF/fayqoosUP+yuhhtTj/KUSLpDJk++HPlA5S5KCT1IhxydGYhqkMq9HLaR2SyeXOiiXB0WI3q1ikOvOSlIwK6J6Stzk3YDjqeyjFjCCrxDJ0dZrE+LPeOJYc5dKNHzmE65BSJH+jLAN34hsUpsg87cd7aCsxrY0RZLX5xXlGea7okXVcLFn0xrwUQoClLi8yNMLrEc9bL8Bc9LLo280IctSY7zwkdVB7wUGCm2EE+U7jRy/leqQY97uWkMroie8jOTeL8Rjq+CbFjCCrIMZtna5YoZiYnhFziz7Y+PG8pZdqrLMoWu9kXITnIxNXLsQPeNphWiAjyGFf85lo5ny9PtVqxmQg3jQuKUNSjwckft1ugbGh7nRxELPxiO+74qLjPRqk7+RjSjKVq79OuyQmC/G50Suu4NqkIL9JPqxKRxu8Errd8jpMQBdUDVCKWYs8CArwES5xvk7f6E1jMhE/Gb3mFq5PSnK7R9HQp7BQ+Vb2e/AF+qFR4EJ8aFRPmbwVVcIUTZyv0hxxWUw2Yq3Rq3pyjVKSeR5KTGW0xXAsVk5odiEHg9BSUgRd1uhAY/SNHFwV/M74iCBvN3pdH65SitLEc6nJxt14HQsD7m19AD/gDTyIRp7etUt+sJOeX2J8tTpiHIvFYlqe0SsHcqVSlDd9k5wMNMUjmIRfcMC33y4X8/AmeuEqp9dgfR8zaYo+iHES2RTfaFfEvEQUGr32Sa5WirIHWb6LTzoa4jY8hSlYLD0zYx+WYybG4BFcj2zFRbjo2ExT9JSv0dJ57lCOhzvjI4Kcz4vTpCj3BSxFlXApOuAhDMUEfIr5WIEttg4EC7Adq7EQn+FtvIj+uAvNUStEEly84zfxjhXooqYYx2KxmDhg9PpnuGop/EVORYk6B9VRHw3QFFejLdqiLZoeHpehPqo7K4uo/OhMM/SIDXjAcXKnNkM7P+YXYqvRj9CLK5eyFAR6HYKD31C9C8cNcVRcXkAUalP12jE/0VYwD5kUpzclMeDxIY1Q+jZjAmo6W4UCbWpadsxvxLdGP0wzrmAK8wUlMeCxjEYolcVO+x0WiLe0SrEgEJONW/SQ1GU/KlEUAxzpPiYCRp9c9HMWNS7Upmo1YkGhPWX8Y23iSqYwHSiLAY6GNEBJ5GOUw6ok2owAwhTFym/exm4FpCRDKYsBjltpgFJY4vTix8fxc2NBo9c2/uH6cz1TmBzKYoCD17JkhN2GOKpOoueIhjEVyDpO7Ge/AlKc3T51jeMwGu/SAF0yz1khTZn1jCUc631j/GMu5LqmMMxFDm7Mo/m5YA96OikYtciDEpouBbmv8Y96H9c2hbmewsjS9CFkERraP8Bbo98WOzqmGuI84x+3IgucpDAPURgDG3tofkmRh+H2q/jlih5l/xFTkqPESuMfuivXOGUZTGEMaFSh8SXFGtv127Q87YWyp8XURetv9qN/xXVOUV6mNAY0LqbxJcEkVLY7w1/Eq8bUJi1uXIRToB62cq1TkjcpjQGN62h8DjmAfnZnd6XWIhYGxESzX6EpI1oUZA4fxz00PkesR3N7M7tP9FE1alx6j5xt3DlEQKATDnLVU45XKI0BjcdofA6YY7cPzCw9MxYmxNvmv0wrBi5SjhcojQGNoTQ+mxRgiL0LTNvEvbGjYuFCCLHP/Feqh6Vc/5SiH6UxoDGKxmczcny3vRmdmP6/WBgRPa1+rQwMCrhxO/GT2ymNAY3xND4bbEMrO7O50adOeB7lI89OlJCTQ0tIEZpRGgMaU2h8CVmJBnbmcpp2ZizM6JrYlOiXbImZKKRFRJ7alMaAxgc0vgQstHOQt1O/LRZ+tIu1vMQm0wQTsIt2EWHyWO0tsPEezc+SaXY6jM/W9Fg00NuJAjtmUxFdMRt5tI9IsoLCyJCFkkxFeqIZLBTPZx8biw6is3lOcslRGZ0wHhtpJxHjAwojqyEryOTEcpwb5mM8813yQScmFMeV6IOp2ECLiQhPUxgDG2/Q/Ex4L7EcL0yLx6KI3lhsTcaY6qIzhmIm1tN6Qk1HCmNg4yWanyETEp9rvJxxfCyqpMXF927MqjraoCdGYiZWMtIcOtgvJLjxFM3PgPGJuoDk63fFok32saKvWRU4p+McNEUXDMJ4zMRi7KZ9Kc1KymKAoycNsBQfJtod745g5Nikm8h3XhjduWiGzhiAUfgIC7Cee2ilYKW3IEd7GmAJvk2U6LZOqxlLGY4Wd2hrvDbCOGqjGW5DHwzHFMzFakp0gNwZLgnbJ9aJJdp8bYaYoo8TI8QoMVFMFBPFFG2GvkAs0dZYVWlRb7Dfe3GW4xzrGfshvVwstcg4XtwhVvlrlumoizbojucwCd9QoH2kADXVlKrdYomYLd7WXtAf0TrqTeMXpmWVO8tehdvMk+MV0uqK5vpd2tPibTFXbFBXkLN4E7YIG3GB5WxpX2X8K5aKZB+rdRK/BGemhwT6PgzFh/gZe2mpHn5BVESa9oif9Q/1F/X79ZbxWhX+KzkYd4KeqV+q36IN0MaKOYlLBvg51tIID7MbV1rP1RdZJ8VSGe18baTYEbzJ6rgA7dAb47CAl7gl80hgq6rt0uZrY0VPvbVe2++SifF/x2uJ6/RHxBgxR9scrHXPoBECAPLQ1tpeZpx1YoycdaJ+o/hI7FVnR1EPt2AwPsJq2rAEJ/A5YLFVz9FGat3FZboWK6PMYfYp8VriOu1h8Zr4Uqy1f3OVJerlUYjuCWq5haYhk0+yfLU2UqxTK/5WEx0xBF8gl/acJLP8WKeD4gcxRuuedol+RihyjU5Iy9Kbiq7aUDFNLPP+iLADzRDAM9a746kRvgTigjLxqloX8aZYrdrRSAM8iMm8zO2YW71bk23iCzFE3KzVyDou5Ifcp+vVtCb6baKvGCU+Fj+JXLkzVZldLDHBOmSZw91xohhcmnaD9rQ2Q2xRTZh7YArLH9lkpfyym6vF+6KfaC5ExL8vZooG2jVaJ/0BMUgbKSZqM8RsfYFYJlaKXJErcrVdRbJFcrU14jfxg77A7BvmvJT/nlaqakXRGpRLyp5GxbVNern4VaKXNlabL3aqlN05CPNRQM314UBPyxM/izf1B+KNzv4P/cEyGNLeeAYfT2krXIQso6KaBw7/1/po/3H3WpwbiTvEk2KiNl+FvXMtPIiPsYfKa8hWVHIzuyv1D8Ugra2ozuieXcqdZXxgeB7yU9YKl6K6WZ3j3aJQ7NRq0G5kxd7+pZ8jmotu2gvaVPGT2B2ULGeiEz5inK4UvZ3O5AbxjXhLPK7fop2foun57hNJfzSe229SNmh2rnVOzqW0Gc9IOzVeNX6V6Cwe18aKL8XvR76U+DKqoTtmpvBOpCS/I8Nsrv4Qv+oL9AXaDDFBH6b117poV6ZV5rGKlKBFP+M5vzMlbXAd6lr3AulAi/E1Z0M7U5yntdDu04ZqU8VPYo/3snw+BjMXAwBwm9kcLVYnPziCm5Iss5upq1LOAjegvrW39qG9BB2D/p9eW28tHhTDxcdiiVcZoOm4HTkpXkHgC/MUo1a0wyCCFg+nmAWuQQNrP32NGwPldtC6pl+qddFeEJ+I3+01Y3WSIDc8ZS+U7DAvSf9T7CganqdBi3uMZ748/kghC1yNetb++UmkGpdGkbNOjNfSOopntRlio7yU/IHYlIKCfK/5nDSnpXksyKeYhea6pYz9/ZqoR833mSfTUkIV2tCuEL21qTLKKlZE3xSLKr9nPhszaVs+BC1GmlUJ/zEl7O/nRPVTlon/o5WEVZrLaddoT4tvtTw3olwe3VPmUOUn8+zjfP0cWpT3lEs3a5XWPgXs7xtUs/bGVSlXgD6KZJ0kLtMH6jnJp9JloEcK1I/70+LLov4i7cgf9HFma/BlxO1vKipY++H69AzaR4Q445/61eLlZIsfRV2Ud6GZxc27FC/+7SPx8uKg8SrUjfS90tEJaqdom9OyaB3R3INUEz3E7GS6aGegO1ZG0h32oI1FEj7vRPlqny+arcSgiIpxIZ5I5Hvb07JpGdE+PjlT3Cu+cV5wPAP3Y1nEHGI3WloVOBxGa/H17ON/ZqW40vFTBOV4t/lFpCPXpOO1aBepYfzlxL16jvO2UTdHqMLAJqtgBcQPvBjt+x75UbPVaBq5uiu/45JE/vYnD5RTbbdcU3vFtMBRoblzfBiB+hdLrHv57oiXp334f9oh1putyMBIyfGsRHkVEOu0SrSIVDxM+bd+t0Ev7ULroMb5GIrNIXaI6Ub1ZouWAm9Gywhkj3yj+bezzyMTOX4xcROEP5hZkdKIhuL9ohJsJ4e5PLqEsv7FPvSDbn2y3Z0WEZglfmLeLTIKl5VycXPi4OBSXaMlcHdyjph4uDpGvv0qGZdjdKjqX/yAixP9Ti/RFgIUZGFeJfxa7Au5HM/BeYl9ag67zJDDpFXWxmp5TmvKpaNtKMrd70C/0p3KSu6OJ8WOph0EKsndzFenc4hbkOVjSELrExDvnXUibYAUjSqX115J5tp1TfTDd8qGMAowHjUS/xZTYsfQAgLmaDHXfIWeDG1WRQs7eUzDuB0gBpRLF6OTq4VRB/2Ua6VagI8SJxlBQExhLzwVSM8Q281XaVzoxLgAr6BiYusrFD259sQqmjci2QJFddAHX2K/Ekd4ExKV/f5rjOHuWJnzjJZW2fBjQyXHf1jdBv07VLZLu4brThLulPVXxf7ky3i2xWisDcwVfsMgO2GKQ+MJdmNQSpJftJLkN0MixgcxzFYfc21FWmWuObH3BfJ/oq/Y6qaU5yV4CO/jTx8dYT1es7wWXWLsZ+tI1cg4Xl9gJcljQiDHOfYCZRCfpJ3KFScOyDxZu09b47bw/UXoibex1MN7fgX4CS+jeYI845J3osR5XGElQ2aWzRZ6IU9hMf4T3e1ZYaH2FA/ySBJkH6u3szr/dtImqiX6YzIWY68k88/DTxiHLvYDFH/vtT7MOJ1rqyZp2douq7Vrj11KivEeDEcVe/a3RW/KdSaunES8JvbK6uCnox46YCDGYCaWYIcjs9+PFZiJ19ADV6F8cu/fp9/NyLHKaE2sj5WvwK/KRY3HINum/WlfsRMIkUDZ0/T7xa9yO14fGlVwCVqiE+7HY3gRwzEa4zEeUzEe4/E6huMF9ENXtEdTnOcsLGE0vtQzuZbKBy5uT/Rt6y1lxDgPU+xm9EAU6I8xq4fI4yjtIjHG/Jqr4iNXv41745BIcq9Eq9lZgcv7BzDevhhDrI434soS+Xvlf+ittBnOy90HOg6KEen/49qFKHBxX6I1rY7xAV5G2oNRFn0ZDcbEsqdxVYlnlEvXHhaLQiHGBdqkeAWuWOh2yfck/qN/NX4IQIx/RR9UdWKBa7UruZ7EB+IVFJflAjEhvQrXKaSS3DlxBUIdt/nY7OkgpqGt05OM18UpXEviqyyLB8WsZK9cezZ2iOe5Mw65JDezToL7S5RvwULPS8zPx8Oo7tQGf9Eu5iqSYJznFNFGjBGbVBBjbb7WJfNkrkn40c8Rf9hb8yswFjs9KaG5AE/iQudWuFv0zDqOK0iC5ai0bO0+bapV7S5Px0rxBGsEREqSzxBz7F8/uhtTpV0dycVUdE3i4pGAgJgcT+PaEXU4Oi1bu0+8J9b5dnQ3X3+UPXujSMbx4jknWT0V0B6v4vukr1n/gcnohUuTz3r/VruIq0YUpezZopn+mJgutniU0LZIe0G7hklFEQ+IXWbendq88mBrDMCbmJOwyNU+/IYcjMFDaOksf6L0WKa3ZLY7CcdO53TRUNyhvaDNEH+4OwLUNou54mX9tngtlpdPIet5L3mLqYjz0RQdcC96HRl3oRPa4vJkgxJGJavuyD6WK0XCyDHxtPiFWlvRSzyvvSE+Et+IZWKLwZn6XpErVovvxMfaG+I50VNvpdWM/5vTl6L75OvEWkUTLH8Tt3NzQKLpdieknZp2atqp/OpHSpJ5sva0OKiYGP+kt2ONCkJISpJWWXysiBQXiul609hRXBNCSCp/i6qjTQ24nsp2MSItiytBCCGxWEzUER8FIsoFYpbW8awTuQKEEFKE9AwxyNfboT+LvmlxzjshhBjvlE/QbxSzRL7Hu+JvRe94Vc42IYQk3iv/T79NfOJBBkaumCjas5o2IYQ4JO1UvaX2gliUuHBnwrFKe0PckV6FORSEEOIujHFK/Cr9UTFBLBYHHIjwHm2+eE27T29c7izOISGEyOYYPVNcpt+kPyCe1ceJ97UZ2gztK32BmKvNEJPFeDFCPKHfpV+t1dTP4GQRQghJYf4fTci7RwYvH54AAAAASUVORK5CYII=")]
+
+pub fn add(left: usize, right: usize) -> usize {
+    left + right
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    #[test]
+    fn it_works() {
+        let result = add(2, 2);
+        assert_eq!(result, 4);
+    }
+}
diff --git a/src/test/rustdoc-ui/issue-103997.rs b/src/test/rustdoc-ui/issue-103997.rs
new file mode 100644
index 00000000000..36f42fb15f7
--- /dev/null
+++ b/src/test/rustdoc-ui/issue-103997.rs
@@ -0,0 +1,6 @@
+// check-pass
+
+pub fn foo() {}
+
+/// [`foo`](Self::foo) //~ WARNING unresolved link to `Self::foo`
+pub use foo as bar;
diff --git a/src/test/rustdoc-ui/issue-103997.stderr b/src/test/rustdoc-ui/issue-103997.stderr
new file mode 100644
index 00000000000..c06db91496f
--- /dev/null
+++ b/src/test/rustdoc-ui/issue-103997.stderr
@@ -0,0 +1,10 @@
+warning: unresolved link to `Self::foo`
+  --> $DIR/issue-103997.rs:5:13
+   |
+LL | /// [`foo`](Self::foo)
+   |             ^^^^^^^^^ no item named `Self` in scope
+   |
+   = note: `#[warn(rustdoc::broken_intra_doc_links)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/src/test/rustdoc/assoc-consts.rs b/src/test/rustdoc/assoc-consts.rs
index a3e10ee5555..3da19a13e53 100644
--- a/src/test/rustdoc/assoc-consts.rs
+++ b/src/test/rustdoc/assoc-consts.rs
@@ -46,6 +46,7 @@ pub fn f(_: &(ToString + 'static)) {}
 impl Bar {
     // @has assoc_consts/struct.Bar.html '//*[@id="associatedconstant.F"]' \
     //      "const F: fn(_: &(dyn ToString + 'static))"
+    // FIXME(fmease): Hide default lifetime, render "const F: fn(_: &dyn ToString)"
     pub const F: fn(_: &(ToString + 'static)) = f;
 }
 
diff --git a/src/test/rustdoc/inline_cross/assoc_item_trait_bounds.rs b/src/test/rustdoc/inline_cross/assoc_item_trait_bounds.rs
index 5f4712aab5b..db2491b87b4 100644
--- a/src/test/rustdoc/inline_cross/assoc_item_trait_bounds.rs
+++ b/src/test/rustdoc/inline_cross/assoc_item_trait_bounds.rs
@@ -33,8 +33,12 @@ extern crate assoc_item_trait_bounds as aux;
 // @snapshot out9 - '//*[@id="associatedtype.Out9"]/*[@class="code-header"]'
 //
 // @has - '//*[@id="tymethod.make"]' \
-// "fn make<F>(F, impl FnMut(&str) -> bool)\
+// "fn make<F>(_: F, _: impl FnMut(&str) -> bool)\
 // where \
 //     F: FnOnce(u32) -> String, \
 //     Self::Out2<()>: Protocol<u8, Q0 = Self::Item, Q1 = ()>"
 pub use aux::Main;
+
+// @has main/trait.Aid.html
+// @has - '//*[@id="associatedtype.Result"]' "type Result<'inter: 'src>"
+pub use aux::Aid;
diff --git a/src/test/rustdoc/inline_cross/auxiliary/assoc_item_trait_bounds.rs b/src/test/rustdoc/inline_cross/auxiliary/assoc_item_trait_bounds.rs
index d326e61daea..6644c8e4147 100644
--- a/src/test/rustdoc/inline_cross/auxiliary/assoc_item_trait_bounds.rs
+++ b/src/test/rustdoc/inline_cross/auxiliary/assoc_item_trait_bounds.rs
@@ -42,5 +42,5 @@ pub trait Helper {
 }
 
 pub trait Aid<'src> {
-    type Result<'inter>;
+    type Result<'inter: 'src>;
 }
diff --git a/src/test/rustdoc/inline_cross/auxiliary/dyn_trait.rs b/src/test/rustdoc/inline_cross/auxiliary/dyn_trait.rs
new file mode 100644
index 00000000000..9ac2e3d96de
--- /dev/null
+++ b/src/test/rustdoc/inline_cross/auxiliary/dyn_trait.rs
@@ -0,0 +1,17 @@
+pub type Ty0 = dyn for<'any> FnOnce(&'any str) -> bool;
+
+pub type Ty1<'obj> = dyn std::fmt::Display + 'obj;
+
+pub type Ty2 = dyn for<'a, 'r> Container<'r, Item<'a, 'static> = ()>;
+
+pub type Ty3<'s> = &'s dyn ToString;
+
+pub fn func0(_: &(dyn Fn() + '_)) {}
+
+pub fn func1<'func>(_: &(dyn Fn() + 'func)) {}
+
+pub trait Container<'r> {
+    type Item<'a, 'ctx>;
+}
+
+pub trait Shape<'a> {}
diff --git a/src/test/rustdoc/inline_cross/dyn_trait.rs b/src/test/rustdoc/inline_cross/dyn_trait.rs
new file mode 100644
index 00000000000..fa760540e43
--- /dev/null
+++ b/src/test/rustdoc/inline_cross/dyn_trait.rs
@@ -0,0 +1,31 @@
+#![crate_name = "user"]
+
+// aux-crate:dyn_trait=dyn_trait.rs
+// edition:2021
+
+// @has user/type.Ty0.html
+// @has - '//*[@class="item-decl"]//code' "dyn for<'any> FnOnce(&'any str) -> bool + 'static"
+// FIXME(fmease): Hide default lifetime bound `'static`
+pub use dyn_trait::Ty0;
+
+// @has user/type.Ty1.html
+// @has - '//*[@class="item-decl"]//code' "dyn Display + 'obj"
+pub use dyn_trait::Ty1;
+
+// @has user/type.Ty2.html
+// @has - '//*[@class="item-decl"]//code' "dyn for<'a, 'r> Container<'r, Item<'a, 'static> = ()>"
+pub use dyn_trait::Ty2;
+
+// @has user/type.Ty3.html
+// @has - '//*[@class="item-decl"]//code' "&'s (dyn ToString + 's)"
+// FIXME(fmease): Hide default lifetime bound, render "&'s dyn ToString"
+pub use dyn_trait::Ty3;
+
+// @has user/fn.func0.html
+// @has - '//pre[@class="rust fn"]' "func0(_: &dyn Fn())"
+// FIXME(fmease): Show placeholder-lifetime bound, render "func0(_: &(dyn Fn() + '_))"
+pub use dyn_trait::func0;
+
+// @has user/fn.func1.html
+// @has - '//pre[@class="rust fn"]' "func1<'func>(_: &(dyn Fn() + 'func))"
+pub use dyn_trait::func1;
diff --git a/src/test/rustdoc/inline_cross/impl_trait.rs b/src/test/rustdoc/inline_cross/impl_trait.rs
index 6c1cf8252a9..9c4f6465920 100644
--- a/src/test/rustdoc/inline_cross/impl_trait.rs
+++ b/src/test/rustdoc/inline_cross/impl_trait.rs
@@ -29,7 +29,7 @@ pub use impl_trait_aux::func4;
 // @has impl_trait/fn.func5.html
 // @has - '//pre[@class="rust fn"]' "func5("
 // @has - '//pre[@class="rust fn"]' "_f: impl for<'any> Fn(&'any str, &'any str) -> bool + for<'r> Other<T<'r> = ()>,"
-// @has - '//pre[@class="rust fn"]' "_a: impl for<'alpha, 'beta> Auxiliary<'alpha, Item<'beta> = fn(&'beta ())>"
+// @has - '//pre[@class="rust fn"]' "_a: impl for<'alpha, 'beta> Auxiliary<'alpha, Item<'beta> = fn(_: &'beta ())>"
 // @!has - '//pre[@class="rust fn"]' 'where'
 pub use impl_trait_aux::func5;
 
diff --git a/src/test/rustdoc/issue-20727.rs b/src/test/rustdoc/issue-20727.rs
index f7acffcb4e5..c1a98cd57da 100644
--- a/src/test/rustdoc/issue-20727.rs
+++ b/src/test/rustdoc/issue-20727.rs
@@ -19,6 +19,6 @@ pub mod reexport {
     // @has - '//*[@class="rust trait"]' 'trait Deref {'
     // @has - '//*[@class="rust trait"]' 'type Target: ?Sized;'
     // @has - '//*[@class="rust trait"]' \
-    //      "fn deref(&'a self) -> &'a Self::Target;"
+    //      "fn deref<'a>(&'a self) -> &'a Self::Target;"
     pub use issue_20727::Deref;
 }
diff --git a/src/test/rustdoc/static-root-path.rs b/src/test/rustdoc/static-root-path.rs
index 08c055c5b8d..86928b0fb0a 100644
--- a/src/test/rustdoc/static-root-path.rs
+++ b/src/test/rustdoc/static-root-path.rs
@@ -1,18 +1,18 @@
 // compile-flags:-Z unstable-options --static-root-path /cache/
 
 // @has static_root_path/struct.SomeStruct.html
-// @matchesraw - '"/cache/main\.js"'
-// @!matchesraw - '"\.\./main\.js"'
+// @matchesraw - '"/cache/main-'
+// @!matchesraw - '"\.\./main'
 // @matchesraw - 'data-root-path="\.\./"'
 // @!matchesraw - '"/cache/search-index\.js"'
 pub struct SomeStruct;
 
 // @has src/static_root_path/static-root-path.rs.html
-// @matchesraw - '"/cache/source-script\.js"'
-// @!matchesraw - '"\.\./\.\./source-script\.js"'
+// @matchesraw - '"/cache/source-script-'
+// @!matchesraw - '"\.\./\.\./source-script'
 // @matchesraw - '"\.\./\.\./source-files.js"'
 // @!matchesraw - '"/cache/source-files\.js"'
 
 // @has settings.html
-// @matchesraw - '/cache/settings\.js'
-// @!matchesraw - '\./settings\.js'
+// @matchesraw - '/cache/settings-'
+// @!matchesraw - '\../settings'
diff --git a/src/test/ui/abi/homogenous-floats-target-feature-mixup.rs b/src/test/ui/abi/homogenous-floats-target-feature-mixup.rs
new file mode 100644
index 00000000000..d7f5e19219e
--- /dev/null
+++ b/src/test/ui/abi/homogenous-floats-target-feature-mixup.rs
@@ -0,0 +1,192 @@
+// This test check that even if we mixup target feature of function with homogenous floats,
+// the abi is sound and still produce the right answer.
+//
+// This is basically the same test as src/test/ui/simd/target-feature-mixup.rs but for floats and
+// without #[repr(simd)]
+
+// run-pass
+// ignore-emscripten
+// ignore-sgx no processes
+
+#![feature(avx512_target_feature)]
+
+#![allow(overflowing_literals)]
+#![allow(unused_variables)]
+
+use std::process::{Command, ExitStatus};
+use std::env;
+
+fn main() {
+    if let Some(level) = env::args().nth(1) {
+        return test::main(&level)
+    }
+
+    match std::env::var("TARGET") {
+        Ok(s) => {
+            // Skip this tests on i586-unknown-linux-gnu where sse2 is disabled
+            if s.contains("i586") {
+                return
+            }
+        }
+        Err(_) => return,
+    }
+
+    let me = env::current_exe().unwrap();
+    for level in ["sse", "avx", "avx512"].iter() {
+        let status = Command::new(&me).arg(level).status().unwrap();
+        if status.success() {
+            println!("success with {}", level);
+            continue
+        }
+
+        // We don't actually know if our computer has the requisite target features
+        // for the test below. Testing for that will get added to libstd later so
+        // for now just assume sigill means this is a machine that can't run this test.
+        if is_sigill(status) {
+            println!("sigill with {}, assuming spurious", level);
+            continue
+        }
+        panic!("invalid status at {}: {}", level, status);
+    }
+}
+
+#[cfg(unix)]
+fn is_sigill(status: ExitStatus) -> bool {
+    use std::os::unix::prelude::*;
+    status.signal() == Some(4)
+}
+
+#[cfg(windows)]
+fn is_sigill(status: ExitStatus) -> bool {
+    status.code() == Some(0xc000001d)
+}
+
+#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
+#[allow(nonstandard_style)]
+mod test {
+    #[derive(PartialEq, Debug, Clone, Copy)]
+    struct f32x2(f32, f32);
+
+    #[derive(PartialEq, Debug, Clone, Copy)]
+    struct f32x4(f32, f32, f32, f32);
+
+    #[derive(PartialEq, Debug, Clone, Copy)]
+    struct f32x8(f32, f32, f32, f32, f32, f32, f32, f32);
+
+    pub fn main(level: &str) {
+        unsafe {
+            main_normal(level);
+            main_sse(level);
+            if level == "sse" {
+                return
+            }
+            main_avx(level);
+            if level == "avx" {
+                return
+            }
+            main_avx512(level);
+        }
+    }
+
+    macro_rules! mains {
+        ($(
+            $(#[$attr:meta])*
+            unsafe fn $main:ident(level: &str) {
+                ...
+            }
+        )*) => ($(
+            $(#[$attr])*
+            unsafe fn $main(level: &str) {
+                let m128 = f32x2(1., 2.);
+                let m256 = f32x4(3., 4., 5., 6.);
+                let m512 = f32x8(7., 8., 9., 10., 11., 12., 13., 14.);
+                assert_eq!(id_sse_128(m128), m128);
+                assert_eq!(id_sse_256(m256), m256);
+                assert_eq!(id_sse_512(m512), m512);
+
+                if level == "sse" {
+                    return
+                }
+                assert_eq!(id_avx_128(m128), m128);
+                assert_eq!(id_avx_256(m256), m256);
+                assert_eq!(id_avx_512(m512), m512);
+
+                if level == "avx" {
+                    return
+                }
+                assert_eq!(id_avx512_128(m128), m128);
+                assert_eq!(id_avx512_256(m256), m256);
+                assert_eq!(id_avx512_512(m512), m512);
+            }
+        )*)
+    }
+
+    mains! {
+        unsafe fn main_normal(level: &str) { ... }
+        #[target_feature(enable = "sse2")]
+        unsafe fn main_sse(level: &str) { ... }
+        #[target_feature(enable = "avx")]
+        unsafe fn main_avx(level: &str) { ... }
+        #[target_feature(enable = "avx512bw")]
+        unsafe fn main_avx512(level: &str) { ... }
+    }
+
+    #[target_feature(enable = "sse2")]
+    unsafe fn id_sse_128(a: f32x2) -> f32x2 {
+        assert_eq!(a, f32x2(1., 2.));
+        a.clone()
+    }
+
+    #[target_feature(enable = "sse2")]
+    unsafe fn id_sse_256(a: f32x4) -> f32x4 {
+        assert_eq!(a, f32x4(3., 4., 5., 6.));
+        a.clone()
+    }
+
+    #[target_feature(enable = "sse2")]
+    unsafe fn id_sse_512(a: f32x8) -> f32x8 {
+        assert_eq!(a, f32x8(7., 8., 9., 10., 11., 12., 13., 14.));
+        a.clone()
+    }
+
+    #[target_feature(enable = "avx")]
+    unsafe fn id_avx_128(a: f32x2) -> f32x2 {
+        assert_eq!(a, f32x2(1., 2.));
+        a.clone()
+    }
+
+    #[target_feature(enable = "avx")]
+    unsafe fn id_avx_256(a: f32x4) -> f32x4 {
+        assert_eq!(a, f32x4(3., 4., 5., 6.));
+        a.clone()
+    }
+
+    #[target_feature(enable = "avx")]
+    unsafe fn id_avx_512(a: f32x8) -> f32x8 {
+        assert_eq!(a, f32x8(7., 8., 9., 10., 11., 12., 13., 14.));
+        a.clone()
+    }
+
+    #[target_feature(enable = "avx512bw")]
+    unsafe fn id_avx512_128(a: f32x2) -> f32x2 {
+        assert_eq!(a, f32x2(1., 2.));
+        a.clone()
+    }
+
+    #[target_feature(enable = "avx512bw")]
+    unsafe fn id_avx512_256(a: f32x4) -> f32x4 {
+        assert_eq!(a, f32x4(3., 4., 5., 6.));
+        a.clone()
+    }
+
+    #[target_feature(enable = "avx512bw")]
+    unsafe fn id_avx512_512(a: f32x8) -> f32x8 {
+        assert_eq!(a, f32x8(7., 8., 9., 10., 11., 12., 13., 14.));
+        a.clone()
+    }
+}
+
+#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
+mod test {
+    pub fn main(level: &str) {}
+}
diff --git a/src/test/ui/abi/issues/issue-22565-rust-call.rs b/src/test/ui/abi/issues/issue-22565-rust-call.rs
index a08e0bfb5e5..a572666c888 100644
--- a/src/test/ui/abi/issues/issue-22565-rust-call.rs
+++ b/src/test/ui/abi/issues/issue-22565-rust-call.rs
@@ -1,32 +1,31 @@
 #![feature(unboxed_closures)]
 
 extern "rust-call" fn b(_i: i32) {}
-//~^ ERROR functions with the "rust-call" ABI must take a single non-self argument that is a tuple
+//~^ ERROR functions with the "rust-call" ABI must take a single non-self tuple argument
 
 trait Tr {
     extern "rust-call" fn a();
+    //~^ ERROR functions with the "rust-call" ABI must take a single non-self tuple argument
 
     extern "rust-call" fn b() {}
-    //~^ ERROR functions with the "rust-call" ABI must take a single non-self argument
+    //~^ ERROR functions with the "rust-call" ABI must take a single non-self tuple argument
 }
 
 struct Foo;
 
 impl Foo {
     extern "rust-call" fn bar() {}
-    //~^ ERROR functions with the "rust-call" ABI must take a single non-self argument
+    //~^ ERROR functions with the "rust-call" ABI must take a single non-self tuple argument
 }
 
 impl Tr for Foo {
     extern "rust-call" fn a() {}
-    //~^ ERROR functions with the "rust-call" ABI must take a single non-self argument
+    //~^ ERROR functions with the "rust-call" ABI must take a single non-self tuple argument
 }
 
-fn main () {
+fn main() {
     b(10);
-
     Foo::bar();
-
     <Foo as Tr>::a();
     <Foo as Tr>::b();
 }
diff --git a/src/test/ui/abi/issues/issue-22565-rust-call.stderr b/src/test/ui/abi/issues/issue-22565-rust-call.stderr
index 3eee10bc5e9..9d205b444fa 100644
--- a/src/test/ui/abi/issues/issue-22565-rust-call.stderr
+++ b/src/test/ui/abi/issues/issue-22565-rust-call.stderr
@@ -1,26 +1,33 @@
-error: functions with the "rust-call" ABI must take a single non-self argument that is a tuple
+error[E0277]: functions with the "rust-call" ABI must take a single non-self tuple argument
   --> $DIR/issue-22565-rust-call.rs:3:1
    |
 LL | extern "rust-call" fn b(_i: i32) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Tuple` is not implemented for `i32`
 
-error: functions with the "rust-call" ABI must take a single non-self argument that is a tuple
-  --> $DIR/issue-22565-rust-call.rs:9:5
-   |
-LL |     extern "rust-call" fn b() {}
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: functions with the "rust-call" ABI must take a single non-self argument that is a tuple
-  --> $DIR/issue-22565-rust-call.rs:16:5
+error: functions with the "rust-call" ABI must take a single non-self tuple argument
+  --> $DIR/issue-22565-rust-call.rs:17:5
    |
 LL |     extern "rust-call" fn bar() {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: functions with the "rust-call" ABI must take a single non-self argument that is a tuple
-  --> $DIR/issue-22565-rust-call.rs:21:5
+error: functions with the "rust-call" ABI must take a single non-self tuple argument
+  --> $DIR/issue-22565-rust-call.rs:22:5
    |
 LL |     extern "rust-call" fn a() {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 4 previous errors
+error: functions with the "rust-call" ABI must take a single non-self tuple argument
+  --> $DIR/issue-22565-rust-call.rs:7:5
+   |
+LL |     extern "rust-call" fn a();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: functions with the "rust-call" ABI must take a single non-self tuple argument
+  --> $DIR/issue-22565-rust-call.rs:10:5
+   |
+LL |     extern "rust-call" fn b() {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 5 previous errors
 
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/abi/rustcall-generic.rs b/src/test/ui/abi/rustcall-generic.rs
index 411c98e1031..6eaccc436b6 100644
--- a/src/test/ui/abi/rustcall-generic.rs
+++ b/src/test/ui/abi/rustcall-generic.rs
@@ -2,9 +2,9 @@
 // check-pass
 //[opt] compile-flags: -Zmir-opt-level=3
 
-#![feature(unboxed_closures)]
+#![feature(unboxed_closures, tuple_trait)]
 
-extern "rust-call" fn foo<T>(_: T) {}
+extern "rust-call" fn foo<T: std::marker::Tuple>(_: T) {}
 
 fn main() {
     foo(());
diff --git a/src/test/ui/asm/issue-92378.rs b/src/test/ui/asm/issue-92378.rs
index 6e3c26e98c3..809b0d1555a 100644
--- a/src/test/ui/asm/issue-92378.rs
+++ b/src/test/ui/asm/issue-92378.rs
@@ -3,7 +3,7 @@
 // needs-asm-support
 // build-pass
 
-#![feature(no_core, lang_items, rustc_attrs, isa_attribute)]
+#![feature(no_core, lang_items, rustc_attrs)]
 #![no_core]
 #![crate_type = "rlib"]
 
diff --git a/src/test/ui/asm/naked-invalid-attr.stderr b/src/test/ui/asm/naked-invalid-attr.stderr
index 58344be9334..e8ddccc854a 100644
--- a/src/test/ui/asm/naked-invalid-attr.stderr
+++ b/src/test/ui/asm/naked-invalid-attr.stderr
@@ -36,7 +36,7 @@ error: attribute should be applied to a function definition
   --> $DIR/naked-invalid-attr.rs:5:1
    |
 LL | #![naked]
-   | ^^^^^^^^^
+   | ^^^^^^^^^ cannot be applied to crates
 
 error: aborting due to 5 previous errors
 
diff --git a/src/test/ui/attributes/key-value-non-ascii.rs b/src/test/ui/attributes/key-value-non-ascii.rs
index 12942eabdf7..e14e2fc05ad 100644
--- a/src/test/ui/attributes/key-value-non-ascii.rs
+++ b/src/test/ui/attributes/key-value-non-ascii.rs
@@ -1,4 +1,4 @@
 #![feature(rustc_attrs)]
 
-#[rustc_dummy = b"ffi.rs"] //~ ERROR non-ASCII character in byte constant
+#[rustc_dummy = b"ffi.rs"] //~ ERROR non-ASCII character in byte string literal
 fn main() {}
diff --git a/src/test/ui/attributes/key-value-non-ascii.stderr b/src/test/ui/attributes/key-value-non-ascii.stderr
index 422107867f7..23d482de6a8 100644
--- a/src/test/ui/attributes/key-value-non-ascii.stderr
+++ b/src/test/ui/attributes/key-value-non-ascii.stderr
@@ -1,8 +1,8 @@
-error: non-ASCII character in byte constant
+error: non-ASCII character in byte string literal
   --> $DIR/key-value-non-ascii.rs:3:19
    |
 LL | #[rustc_dummy = b"ffi.rs"]
-   |                   ^ byte constant must be ASCII
+   |                   ^ must be ASCII
    |
 help: if you meant to use the UTF-8 encoding of 'ffi', use \xHH escapes
    |
diff --git a/src/test/ui/borrowck/borrow-immutable-upvar-mutation.rs b/src/test/ui/borrowck/borrow-immutable-upvar-mutation.rs
index e2f016614bf..a3350024e75 100644
--- a/src/test/ui/borrowck/borrow-immutable-upvar-mutation.rs
+++ b/src/test/ui/borrowck/borrow-immutable-upvar-mutation.rs
@@ -1,4 +1,4 @@
-#![feature(unboxed_closures)]
+#![feature(unboxed_closures, tuple_trait)]
 
 // Tests that we can't assign to or mutably borrow upvars from `Fn`
 // closures (issue #17780)
@@ -7,10 +7,10 @@ fn set(x: &mut usize) {
     *x = 5;
 }
 
-fn to_fn<A, F: Fn<A>>(f: F) -> F {
+fn to_fn<A: std::marker::Tuple, F: Fn<A>>(f: F) -> F {
     f
 }
-fn to_fn_mut<A, F: FnMut<A>>(f: F) -> F {
+fn to_fn_mut<A: std::marker::Tuple, F: FnMut<A>>(f: F) -> F {
     f
 }
 
diff --git a/src/test/ui/borrowck/borrow-immutable-upvar-mutation.stderr b/src/test/ui/borrowck/borrow-immutable-upvar-mutation.stderr
index 093589ed092..a0eaf1f163b 100644
--- a/src/test/ui/borrowck/borrow-immutable-upvar-mutation.stderr
+++ b/src/test/ui/borrowck/borrow-immutable-upvar-mutation.stderr
@@ -1,8 +1,8 @@
 error[E0594]: cannot assign to `x`, as it is a captured variable in a `Fn` closure
   --> $DIR/borrow-immutable-upvar-mutation.rs:21:27
    |
-LL | fn to_fn<A, F: Fn<A>>(f: F) -> F {
-   |                          - change this to accept `FnMut` instead of `Fn`
+LL | fn to_fn<A: std::marker::Tuple, F: Fn<A>>(f: F) -> F {
+   |                                              - change this to accept `FnMut` instead of `Fn`
 ...
 LL |         let _f = to_fn(|| x = 42);
    |                  ----- -- ^^^^^^ cannot assign
@@ -13,8 +13,8 @@ LL |         let _f = to_fn(|| x = 42);
 error[E0596]: cannot borrow `y` as mutable, as it is a captured variable in a `Fn` closure
   --> $DIR/borrow-immutable-upvar-mutation.rs:24:31
    |
-LL | fn to_fn<A, F: Fn<A>>(f: F) -> F {
-   |                          - change this to accept `FnMut` instead of `Fn`
+LL | fn to_fn<A: std::marker::Tuple, F: Fn<A>>(f: F) -> F {
+   |                                              - change this to accept `FnMut` instead of `Fn`
 ...
 LL |         let _g = to_fn(|| set(&mut y));
    |                  ----- --     ^^^^^^ cannot borrow as mutable
@@ -25,8 +25,8 @@ LL |         let _g = to_fn(|| set(&mut y));
 error[E0594]: cannot assign to `z`, as it is a captured variable in a `Fn` closure
   --> $DIR/borrow-immutable-upvar-mutation.rs:29:22
    |
-LL | fn to_fn<A, F: Fn<A>>(f: F) -> F {
-   |                          - change this to accept `FnMut` instead of `Fn`
+LL | fn to_fn<A: std::marker::Tuple, F: Fn<A>>(f: F) -> F {
+   |                                              - change this to accept `FnMut` instead of `Fn`
 ...
 LL |             to_fn(|| z = 42);
    |             ----- -- ^^^^^^ cannot assign
@@ -37,8 +37,8 @@ LL |             to_fn(|| z = 42);
 error[E0594]: cannot assign to `x`, as it is a captured variable in a `Fn` closure
   --> $DIR/borrow-immutable-upvar-mutation.rs:36:32
    |
-LL | fn to_fn<A, F: Fn<A>>(f: F) -> F {
-   |                          - change this to accept `FnMut` instead of `Fn`
+LL | fn to_fn<A: std::marker::Tuple, F: Fn<A>>(f: F) -> F {
+   |                                              - change this to accept `FnMut` instead of `Fn`
 ...
 LL |         let _f = to_fn(move || x = 42);
    |                  ----- ------- ^^^^^^ cannot assign
@@ -49,8 +49,8 @@ LL |         let _f = to_fn(move || x = 42);
 error[E0596]: cannot borrow `y` as mutable, as it is a captured variable in a `Fn` closure
   --> $DIR/borrow-immutable-upvar-mutation.rs:39:36
    |
-LL | fn to_fn<A, F: Fn<A>>(f: F) -> F {
-   |                          - change this to accept `FnMut` instead of `Fn`
+LL | fn to_fn<A: std::marker::Tuple, F: Fn<A>>(f: F) -> F {
+   |                                              - change this to accept `FnMut` instead of `Fn`
 ...
 LL |         let _g = to_fn(move || set(&mut y));
    |                  ----- -------     ^^^^^^ cannot borrow as mutable
@@ -61,8 +61,8 @@ LL |         let _g = to_fn(move || set(&mut y));
 error[E0594]: cannot assign to `z`, as it is a captured variable in a `Fn` closure
   --> $DIR/borrow-immutable-upvar-mutation.rs:44:27
    |
-LL | fn to_fn<A, F: Fn<A>>(f: F) -> F {
-   |                          - change this to accept `FnMut` instead of `Fn`
+LL | fn to_fn<A: std::marker::Tuple, F: Fn<A>>(f: F) -> F {
+   |                                              - change this to accept `FnMut` instead of `Fn`
 ...
 LL |             to_fn(move || z = 42);
    |             ----- ------- ^^^^^^ cannot assign
diff --git a/src/test/ui/borrowck/borrowck-borrowed-uniq-rvalue-2.stderr b/src/test/ui/borrowck/borrowck-borrowed-uniq-rvalue-2.stderr
index a6af129bf39..4eeec09b910 100644
--- a/src/test/ui/borrowck/borrowck-borrowed-uniq-rvalue-2.stderr
+++ b/src/test/ui/borrowck/borrowck-borrowed-uniq-rvalue-2.stderr
@@ -4,7 +4,7 @@ error[E0716]: temporary value dropped while borrowed
 LL |     let x = defer(&vec!["Goodbye", "world!"]);
    |                    ^^^^^^^^^^^^^^^^^^^^^^^^^ - temporary value is freed at the end of this statement
    |                    |
-   |                    creates a temporary which is freed while still in use
+   |                    creates a temporary value which is freed while still in use
 LL |     x.x[0];
    |     ------ borrow later used here
    |
diff --git a/src/test/ui/borrowck/borrowck-borrowed-uniq-rvalue.stderr b/src/test/ui/borrowck/borrowck-borrowed-uniq-rvalue.stderr
index dea8ac90bec..c62d5f903c8 100644
--- a/src/test/ui/borrowck/borrowck-borrowed-uniq-rvalue.stderr
+++ b/src/test/ui/borrowck/borrowck-borrowed-uniq-rvalue.stderr
@@ -4,7 +4,7 @@ error[E0716]: temporary value dropped while borrowed
 LL |     buggy_map.insert(42, &*Box::new(1));
    |                            ^^^^^^^^^^^ - temporary value is freed at the end of this statement
    |                            |
-   |                            creates a temporary which is freed while still in use
+   |                            creates a temporary value which is freed while still in use
 ...
 LL |     buggy_map.insert(43, &*tmp);
    |     --------------------------- borrow later used here
diff --git a/src/test/ui/borrowck/borrowck-move-by-capture.rs b/src/test/ui/borrowck/borrowck-move-by-capture.rs
index f26edef17f3..6f0eb1870f3 100644
--- a/src/test/ui/borrowck/borrowck-move-by-capture.rs
+++ b/src/test/ui/borrowck/borrowck-move-by-capture.rs
@@ -1,7 +1,7 @@
-#![feature(unboxed_closures)]
+#![feature(unboxed_closures, tuple_trait)]
 
-fn to_fn_mut<A,F:FnMut<A>>(f: F) -> F { f }
-fn to_fn_once<A,F:FnOnce<A>>(f: F) -> F { f }
+fn to_fn_mut<A:std::marker::Tuple,F:FnMut<A>>(f: F) -> F { f }
+fn to_fn_once<A:std::marker::Tuple,F:FnOnce<A>>(f: F) -> F { f }
 
 pub fn main() {
     let bar: Box<_> = Box::new(3);
diff --git a/src/test/ui/borrowck/issue-11493.stderr b/src/test/ui/borrowck/issue-11493.stderr
index a5d1f2816f1..2720b09b0fc 100644
--- a/src/test/ui/borrowck/issue-11493.stderr
+++ b/src/test/ui/borrowck/issue-11493.stderr
@@ -4,7 +4,7 @@ error[E0716]: temporary value dropped while borrowed
 LL |     let y = x.as_ref().unwrap_or(&id(5));
    |                                   ^^^^^ - temporary value is freed at the end of this statement
    |                                   |
-   |                                   creates a temporary which is freed while still in use
+   |                                   creates a temporary value which is freed while still in use
 LL |     let _ = &y;
    |             -- borrow later used here
    |
diff --git a/src/test/ui/borrowck/issue-17545.stderr b/src/test/ui/borrowck/issue-17545.stderr
index 79a1e09bd7c..3ae7e64d202 100644
--- a/src/test/ui/borrowck/issue-17545.stderr
+++ b/src/test/ui/borrowck/issue-17545.stderr
@@ -5,7 +5,7 @@ LL |   pub fn foo<'a, F: Fn(&'a ())>(bar: F) {
    |              -- lifetime `'a` defined here
 LL | /     bar.call((
 LL | |         &id(()),
-   | |          ^^^^^^ creates a temporary which is freed while still in use
+   | |          ^^^^^^ creates a temporary value which is freed while still in use
 LL | |     ));
    | |      -- temporary value is freed at the end of this statement
    | |______|
diff --git a/src/test/ui/borrowck/issue-36082.fixed b/src/test/ui/borrowck/issue-36082.fixed
index 8640ca7a509..8fc963a8566 100644
--- a/src/test/ui/borrowck/issue-36082.fixed
+++ b/src/test/ui/borrowck/issue-36082.fixed
@@ -10,7 +10,7 @@ fn main() {
     let val: &_ = binding.0;
     //~^ ERROR temporary value dropped while borrowed [E0716]
     //~| NOTE temporary value is freed at the end of this statement
-    //~| NOTE creates a temporary which is freed while still in use
+    //~| NOTE creates a temporary value which is freed while still in use
     //~| HELP consider using a `let` binding to create a longer lived value
     println!("{}", val);
     //~^ borrow later used here
diff --git a/src/test/ui/borrowck/issue-36082.rs b/src/test/ui/borrowck/issue-36082.rs
index 877d372fb84..20f66b4d45d 100644
--- a/src/test/ui/borrowck/issue-36082.rs
+++ b/src/test/ui/borrowck/issue-36082.rs
@@ -9,7 +9,7 @@ fn main() {
     let val: &_ = x.borrow().0;
     //~^ ERROR temporary value dropped while borrowed [E0716]
     //~| NOTE temporary value is freed at the end of this statement
-    //~| NOTE creates a temporary which is freed while still in use
+    //~| NOTE creates a temporary value which is freed while still in use
     //~| HELP consider using a `let` binding to create a longer lived value
     println!("{}", val);
     //~^ borrow later used here
diff --git a/src/test/ui/borrowck/issue-36082.stderr b/src/test/ui/borrowck/issue-36082.stderr
index 4bd586db1cd..a6357f8182f 100644
--- a/src/test/ui/borrowck/issue-36082.stderr
+++ b/src/test/ui/borrowck/issue-36082.stderr
@@ -4,7 +4,7 @@ error[E0716]: temporary value dropped while borrowed
 LL |     let val: &_ = x.borrow().0;
    |                   ^^^^^^^^^^  - temporary value is freed at the end of this statement
    |                   |
-   |                   creates a temporary which is freed while still in use
+   |                   creates a temporary value which is freed while still in use
 ...
 LL |     println!("{}", val);
    |                    --- borrow later used here
diff --git a/src/test/ui/c-variadic/issue-86053-1.stderr b/src/test/ui/c-variadic/issue-86053-1.stderr
index 60b379faf4e..075bd1fc488 100644
--- a/src/test/ui/c-variadic/issue-86053-1.stderr
+++ b/src/test/ui/c-variadic/issue-86053-1.stderr
@@ -66,8 +66,8 @@ LL |     self , ... ,   self ,   self , ... ) where F : FnOnce ( & 'a & 'b usize
    |
   ::: $SRC_DIR/core/src/ops/function.rs:LL:COL
    |
-LL | pub trait Fn<Args>: FnMut<Args> {
-   | ------------------------------- similarly named trait `Fn` defined here
+LL | pub trait Fn<Args: Tuple>: FnMut<Args> {
+   | -------------------------------------- similarly named trait `Fn` defined here
    |
 help: a trait with a similar name exists
    |
diff --git a/src/test/ui/cannot-mutate-captured-non-mut-var.rs b/src/test/ui/cannot-mutate-captured-non-mut-var.rs
index a83884acb1d..952dab25bf9 100644
--- a/src/test/ui/cannot-mutate-captured-non-mut-var.rs
+++ b/src/test/ui/cannot-mutate-captured-non-mut-var.rs
@@ -1,8 +1,8 @@
-#![feature(unboxed_closures)]
+#![feature(unboxed_closures, tuple_trait)]
 
 use std::io::Read;
 
-fn to_fn_once<A,F:FnOnce<A>>(f: F) -> F { f }
+fn to_fn_once<A:std::marker::Tuple,F:FnOnce<A>>(f: F) -> F { f }
 
 fn main() {
     let x = 1;
diff --git a/src/test/ui/chalkify/closure.rs b/src/test/ui/chalkify/closure.rs
index 81114d491d7..408e8802d86 100644
--- a/src/test/ui/chalkify/closure.rs
+++ b/src/test/ui/chalkify/closure.rs
@@ -1,4 +1,5 @@
-// check-fail
+// known-bug: unknown
+// FIXME(chalk): Chalk needs support for the Tuple trait
 // compile-flags: -Z chalk
 
 fn main() -> () {
@@ -25,7 +26,7 @@ fn main() -> () {
     let mut c = b;
 
     c();
-    b(); //~ ERROR
+    b(); // FIXME: reenable when this is fixed ~ ERROR
 
     // FIXME(chalk): this doesn't quite work
     /*
diff --git a/src/test/ui/chalkify/closure.stderr b/src/test/ui/chalkify/closure.stderr
index 515e0cf0142..bcee0cab96a 100644
--- a/src/test/ui/chalkify/closure.stderr
+++ b/src/test/ui/chalkify/closure.stderr
@@ -1,22 +1,80 @@
-error[E0382]: borrow of moved value: `b`
-  --> $DIR/closure.rs:28:5
+error[E0277]: `()` is not a tuple
+  --> $DIR/closure.rs:7:5
+   |
+LL |     t();
+   |     ^^^ the trait `Tuple` is not implemented for `()`
+   |
+help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
+   |
+LL | fn main() -> () where (): Tuple {
+   |                 +++++++++++++++
+
+error[E0277]: `()` is not a tuple
+  --> $DIR/closure.rs:13:5
+   |
+LL |     b();
+   |     ^^^ the trait `Tuple` is not implemented for `()`
+   |
+help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
+   |
+LL | fn main() -> () where (): Tuple {
+   |                 +++++++++++++++
+
+error[E0277]: `()` is not a tuple
+  --> $DIR/closure.rs:17:5
+   |
+LL |     c();
+   |     ^^^ the trait `Tuple` is not implemented for `()`
+   |
+help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
+   |
+LL | fn main() -> () where (): Tuple {
+   |                 +++++++++++++++
+
+error[E0277]: `()` is not a tuple
+  --> $DIR/closure.rs:18:5
    |
-LL |     let mut c = b;
-   |                 - value moved here
-...
 LL |     b();
-   |     ^ value borrowed here after move
+   |     ^^^ the trait `Tuple` is not implemented for `()`
+   |
+help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
+   |
+LL | fn main() -> () where (): Tuple {
+   |                 +++++++++++++++
+
+error[E0277]: `()` is not a tuple
+  --> $DIR/closure.rs:24:5
+   |
+LL |     b();
+   |     ^^^ the trait `Tuple` is not implemented for `()`
+   |
+help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
+   |
+LL | fn main() -> () where (): Tuple {
+   |                 +++++++++++++++
+
+error[E0277]: `()` is not a tuple
+  --> $DIR/closure.rs:28:5
+   |
+LL |     c();
+   |     ^^^ the trait `Tuple` is not implemented for `()`
+   |
+help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
+   |
+LL | fn main() -> () where (): Tuple {
+   |                 +++++++++++++++
+
+error[E0277]: `()` is not a tuple
+  --> $DIR/closure.rs:29:5
    |
-note: closure cannot be moved more than once as it is not `Copy` due to moving the variable `a` out of its environment
-  --> $DIR/closure.rs:21:9
+LL |     b(); // FIXME: reenable when this is fixed ~ ERROR
+   |     ^^^ the trait `Tuple` is not implemented for `()`
    |
-LL |         a = 1;
-   |         ^
-help: consider mutably borrowing `b`
+help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
    |
-LL |     let mut c = &mut b;
-   |                 ++++
+LL | fn main() -> () where (): Tuple {
+   |                 +++++++++++++++
 
-error: aborting due to previous error
+error: aborting due to 7 previous errors
 
-For more information about this error, try `rustc --explain E0382`.
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/chalkify/trait-objects.rs b/src/test/ui/chalkify/trait-objects.rs
index d56abc42bf5..30929e943bd 100644
--- a/src/test/ui/chalkify/trait-objects.rs
+++ b/src/test/ui/chalkify/trait-objects.rs
@@ -1,4 +1,5 @@
-// check-pass
+// known-bug: unknown
+// FIXME(chalk): Chalk needs support for the Tuple trait
 // compile-flags: -Z chalk
 
 use std::fmt::Display;
diff --git a/src/test/ui/chalkify/trait-objects.stderr b/src/test/ui/chalkify/trait-objects.stderr
new file mode 100644
index 00000000000..098bd2d3226
--- /dev/null
+++ b/src/test/ui/chalkify/trait-objects.stderr
@@ -0,0 +1,28 @@
+error: the type `&dyn Fn(i32) -> _` is not well-formed (chalk)
+  --> $DIR/trait-objects.rs:11:12
+   |
+LL |     let f: &dyn Fn(i32) -> _ = &|x| x + x;
+   |            ^^^^^^^^^^^^^^^^^
+
+error[E0277]: `(i32,)` is not a tuple
+  --> $DIR/trait-objects.rs:12:5
+   |
+LL |     f(2);
+   |     ^^^^ the trait `Tuple` is not implemented for `(i32,)`
+   |
+help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
+   |
+LL | fn main() where (i32,): Tuple {
+   |           +++++++++++++++++++
+
+error[E0277]: expected a `Fn<(i32,)>` closure, found `dyn Fn(i32) -> i32`
+  --> $DIR/trait-objects.rs:12:5
+   |
+LL |     f(2);
+   |     ^^^^ expected an `Fn<(i32,)>` closure, found `dyn Fn(i32) -> i32`
+   |
+   = help: the trait `Fn<(i32,)>` is not implemented for `dyn Fn(i32) -> i32`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/cleanup-rvalue-scopes-cf.stderr b/src/test/ui/cleanup-rvalue-scopes-cf.stderr
index 40f14c38984..425cd75141c 100644
--- a/src/test/ui/cleanup-rvalue-scopes-cf.stderr
+++ b/src/test/ui/cleanup-rvalue-scopes-cf.stderr
@@ -4,7 +4,7 @@ error[E0716]: temporary value dropped while borrowed
 LL |     let x1 = arg(&AddFlags(1));
    |                   ^^^^^^^^^^^ - temporary value is freed at the end of this statement
    |                   |
-   |                   creates a temporary which is freed while still in use
+   |                   creates a temporary value which is freed while still in use
 ...
 LL |     (x1, x2, x3, x4, x5, x6, x7);
    |      -- borrow later used here
@@ -21,7 +21,7 @@ error[E0716]: temporary value dropped while borrowed
 LL |     let x2 = AddFlags(1).get();
    |              ^^^^^^^^^^^      - temporary value is freed at the end of this statement
    |              |
-   |              creates a temporary which is freed while still in use
+   |              creates a temporary value which is freed while still in use
 ...
 LL |     (x1, x2, x3, x4, x5, x6, x7);
    |          -- borrow later used here
@@ -38,7 +38,7 @@ error[E0716]: temporary value dropped while borrowed
 LL |     let x3 = &*arg(&AddFlags(1));
    |                     ^^^^^^^^^^^ - temporary value is freed at the end of this statement
    |                     |
-   |                     creates a temporary which is freed while still in use
+   |                     creates a temporary value which is freed while still in use
 ...
 LL |     (x1, x2, x3, x4, x5, x6, x7);
    |              -- borrow later used here
@@ -55,7 +55,7 @@ error[E0716]: temporary value dropped while borrowed
 LL |     let ref x4 = *arg(&AddFlags(1));
    |                        ^^^^^^^^^^^ - temporary value is freed at the end of this statement
    |                        |
-   |                        creates a temporary which is freed while still in use
+   |                        creates a temporary value which is freed while still in use
 ...
 LL |     (x1, x2, x3, x4, x5, x6, x7);
    |                  -- borrow later used here
@@ -72,7 +72,7 @@ error[E0716]: temporary value dropped while borrowed
 LL |     let &ref x5 = arg(&AddFlags(1));
    |                        ^^^^^^^^^^^ - temporary value is freed at the end of this statement
    |                        |
-   |                        creates a temporary which is freed while still in use
+   |                        creates a temporary value which is freed while still in use
 ...
 LL |     (x1, x2, x3, x4, x5, x6, x7);
    |                      -- borrow later used here
@@ -89,7 +89,7 @@ error[E0716]: temporary value dropped while borrowed
 LL |     let x6 = AddFlags(1).get();
    |              ^^^^^^^^^^^      - temporary value is freed at the end of this statement
    |              |
-   |              creates a temporary which is freed while still in use
+   |              creates a temporary value which is freed while still in use
 ...
 LL |     (x1, x2, x3, x4, x5, x6, x7);
    |                          -- borrow later used here
@@ -106,7 +106,7 @@ error[E0716]: temporary value dropped while borrowed
 LL |     let StackBox { f: x7 } = StackBox { f: AddFlags(1).get() };
    |                                            ^^^^^^^^^^^        - temporary value is freed at the end of this statement
    |                                            |
-   |                                            creates a temporary which is freed while still in use
+   |                                            creates a temporary value which is freed while still in use
 LL |
 LL |     (x1, x2, x3, x4, x5, x6, x7);
    |                              -- borrow later used here
diff --git a/src/test/ui/closures/issue-78720.stderr b/src/test/ui/closures/issue-78720.stderr
index 3dd13877298..da3f539a007 100644
--- a/src/test/ui/closures/issue-78720.stderr
+++ b/src/test/ui/closures/issue-78720.stderr
@@ -12,8 +12,8 @@ LL |     _func: F,
    |
   ::: $SRC_DIR/core/src/ops/function.rs:LL:COL
    |
-LL | pub trait Fn<Args>: FnMut<Args> {
-   | ------------------------------- similarly named trait `Fn` defined here
+LL | pub trait Fn<Args: Tuple>: FnMut<Args> {
+   | -------------------------------------- similarly named trait `Fn` defined here
    |
 help: a trait with a similar name exists
    |
diff --git a/src/test/ui/closures/supertrait-hint-references-assoc-ty.rs b/src/test/ui/closures/supertrait-hint-references-assoc-ty.rs
new file mode 100644
index 00000000000..270bf14c35e
--- /dev/null
+++ b/src/test/ui/closures/supertrait-hint-references-assoc-ty.rs
@@ -0,0 +1,17 @@
+// check-pass
+
+pub trait Fn0: Fn(i32) -> Self::Out {
+    type Out;
+}
+
+impl<F: Fn(i32) -> ()> Fn0 for F {
+    type Out = ();
+}
+
+pub fn closure_typer(_: impl Fn0) {}
+
+fn main() {
+    closure_typer(move |x| {
+        let _: i64 = x.into();
+    });
+}
diff --git a/src/test/ui/conditional-compilation/cfg_accessible-not_sure.rs b/src/test/ui/conditional-compilation/cfg_accessible-not_sure.rs
index d68acd2451f..99a7949db17 100644
--- a/src/test/ui/conditional-compilation/cfg_accessible-not_sure.rs
+++ b/src/test/ui/conditional-compilation/cfg_accessible-not_sure.rs
@@ -46,7 +46,7 @@ const C: bool = true;
 trait Trait {}
 impl dyn Trait { fn existing() {} }
 
-// FIXME: Should be a error for edition > 2015
+// FIXME: Should be an error for edition > 2015
 #[cfg_accessible(Trait::existing)] //~ ERROR not sure
 const A: bool = true;
 #[cfg_accessible(Trait::unresolved)] //~ ERROR not sure
diff --git a/src/test/ui/consts/const-eval/const-eval-intrinsic-promotion.stderr b/src/test/ui/consts/const-eval/const-eval-intrinsic-promotion.stderr
index 78143042ece..ed6a6ee6e0f 100644
--- a/src/test/ui/consts/const-eval/const-eval-intrinsic-promotion.stderr
+++ b/src/test/ui/consts/const-eval/const-eval-intrinsic-promotion.stderr
@@ -4,7 +4,7 @@ error[E0716]: temporary value dropped while borrowed
 LL |     let x: &'static usize =
    |            -------------- type annotation requires that borrow lasts for `'static`
 LL |         &std::intrinsics::size_of::<i32>();
-   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
 LL | }
    | - temporary value is freed at the end of this statement
 
diff --git a/src/test/ui/consts/const-eval/dont_promote_unstable_const_fn.stderr b/src/test/ui/consts/const-eval/dont_promote_unstable_const_fn.stderr
index 69e3ca716a9..2e697b219c5 100644
--- a/src/test/ui/consts/const-eval/dont_promote_unstable_const_fn.stderr
+++ b/src/test/ui/consts/const-eval/dont_promote_unstable_const_fn.stderr
@@ -10,7 +10,7 @@ error[E0716]: temporary value dropped while borrowed
   --> $DIR/dont_promote_unstable_const_fn.rs:17:28
    |
 LL |     let _: &'static u32 = &foo();
-   |            ------------    ^^^^^ creates a temporary which is freed while still in use
+   |            ------------    ^^^^^ creates a temporary value which is freed while still in use
    |            |
    |            type annotation requires that borrow lasts for `'static`
 LL | }
@@ -20,7 +20,7 @@ error[E0716]: temporary value dropped while borrowed
   --> $DIR/dont_promote_unstable_const_fn.rs:21:28
    |
 LL |     let _: &'static u32 = &meh();
-   |            ------------    ^^^^^ creates a temporary which is freed while still in use
+   |            ------------    ^^^^^ creates a temporary value which is freed while still in use
    |            |
    |            type annotation requires that borrow lasts for `'static`
 ...
@@ -31,7 +31,7 @@ error[E0716]: temporary value dropped while borrowed
   --> $DIR/dont_promote_unstable_const_fn.rs:22:26
    |
 LL |     let x: &'static _ = &std::time::Duration::from_millis(42).subsec_millis();
-   |            ----------    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
+   |            ----------    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
    |            |
    |            type annotation requires that borrow lasts for `'static`
 LL |
diff --git a/src/test/ui/consts/const-eval/dont_promote_unstable_const_fn_cross_crate.stderr b/src/test/ui/consts/const-eval/dont_promote_unstable_const_fn_cross_crate.stderr
index 129f0615107..aa742d784e0 100644
--- a/src/test/ui/consts/const-eval/dont_promote_unstable_const_fn_cross_crate.stderr
+++ b/src/test/ui/consts/const-eval/dont_promote_unstable_const_fn_cross_crate.stderr
@@ -2,7 +2,7 @@ error[E0716]: temporary value dropped while borrowed
   --> $DIR/dont_promote_unstable_const_fn_cross_crate.rs:8:28
    |
 LL |     let _: &'static u32 = &foo();
-   |            ------------    ^^^^^ creates a temporary which is freed while still in use
+   |            ------------    ^^^^^ creates a temporary value which is freed while still in use
    |            |
    |            type annotation requires that borrow lasts for `'static`
 LL |     let _x: &'static u32 = &foo();
@@ -13,7 +13,7 @@ error[E0716]: temporary value dropped while borrowed
   --> $DIR/dont_promote_unstable_const_fn_cross_crate.rs:9:29
    |
 LL |     let _x: &'static u32 = &foo();
-   |             ------------    ^^^^^ creates a temporary which is freed while still in use
+   |             ------------    ^^^^^ creates a temporary value which is freed while still in use
    |             |
    |             type annotation requires that borrow lasts for `'static`
 LL | }
diff --git a/src/test/ui/consts/const-eval/promoted_const_fn_fail.stderr b/src/test/ui/consts/const-eval/promoted_const_fn_fail.stderr
index 596fa090d97..2d4e7c83d3e 100644
--- a/src/test/ui/consts/const-eval/promoted_const_fn_fail.stderr
+++ b/src/test/ui/consts/const-eval/promoted_const_fn_fail.stderr
@@ -2,7 +2,7 @@ error[E0716]: temporary value dropped while borrowed
   --> $DIR/promoted_const_fn_fail.rs:17:27
    |
 LL |     let x: &'static u8 = &(bar() + 1);
-   |            -----------    ^^^^^^^^^^^ creates a temporary which is freed while still in use
+   |            -----------    ^^^^^^^^^^^ creates a temporary value which is freed while still in use
    |            |
    |            type annotation requires that borrow lasts for `'static`
 ...
diff --git a/src/test/ui/consts/const-eval/promoted_const_fn_fail_deny_const_err.stderr b/src/test/ui/consts/const-eval/promoted_const_fn_fail_deny_const_err.stderr
index 63dc43a41a8..9ebae3a18a3 100644
--- a/src/test/ui/consts/const-eval/promoted_const_fn_fail_deny_const_err.stderr
+++ b/src/test/ui/consts/const-eval/promoted_const_fn_fail_deny_const_err.stderr
@@ -2,7 +2,7 @@ error[E0716]: temporary value dropped while borrowed
   --> $DIR/promoted_const_fn_fail_deny_const_err.rs:18:27
    |
 LL |     let x: &'static u8 = &(bar() + 1);
-   |            -----------    ^^^^^^^^^^^ creates a temporary which is freed while still in use
+   |            -----------    ^^^^^^^^^^^ creates a temporary value which is freed while still in use
    |            |
    |            type annotation requires that borrow lasts for `'static`
 ...
diff --git a/src/test/ui/consts/const-eval/promoted_raw_ptr_ops.stderr b/src/test/ui/consts/const-eval/promoted_raw_ptr_ops.stderr
index 8ac60da3863..01fcf2ec213 100644
--- a/src/test/ui/consts/const-eval/promoted_raw_ptr_ops.stderr
+++ b/src/test/ui/consts/const-eval/promoted_raw_ptr_ops.stderr
@@ -2,7 +2,7 @@ error[E0716]: temporary value dropped while borrowed
   --> $DIR/promoted_raw_ptr_ops.rs:2:29
    |
 LL |     let x: &'static bool = &(42 as *const i32 == 43 as *const i32);
-   |            -------------    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
+   |            -------------    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
    |            |
    |            type annotation requires that borrow lasts for `'static`
 ...
@@ -13,7 +13,7 @@ error[E0716]: temporary value dropped while borrowed
   --> $DIR/promoted_raw_ptr_ops.rs:4:30
    |
 LL |     let y: &'static usize = &(&1 as *const i32 as usize + 1);
-   |            --------------    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
+   |            --------------    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
    |            |
    |            type annotation requires that borrow lasts for `'static`
 ...
@@ -24,7 +24,7 @@ error[E0716]: temporary value dropped while borrowed
   --> $DIR/promoted_raw_ptr_ops.rs:6:28
    |
 LL |     let z: &'static i32 = &(unsafe { *(42 as *const i32) });
-   |            ------------    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
+   |            ------------    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
    |            |
    |            type annotation requires that borrow lasts for `'static`
 ...
@@ -35,7 +35,7 @@ error[E0716]: temporary value dropped while borrowed
   --> $DIR/promoted_raw_ptr_ops.rs:8:29
    |
 LL |     let a: &'static bool = &(main as fn() == main as fn());
-   |            -------------    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
+   |            -------------    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
    |            |
    |            type annotation requires that borrow lasts for `'static`
 LL |
diff --git a/src/test/ui/consts/const-eval/transmute-const-promotion.stderr b/src/test/ui/consts/const-eval/transmute-const-promotion.stderr
index 15b9b56ea66..434a957f648 100644
--- a/src/test/ui/consts/const-eval/transmute-const-promotion.stderr
+++ b/src/test/ui/consts/const-eval/transmute-const-promotion.stderr
@@ -2,7 +2,7 @@ error[E0716]: temporary value dropped while borrowed
   --> $DIR/transmute-const-promotion.rs:4:37
    |
 LL |     let x: &'static u32 = unsafe { &mem::transmute(3.0f32) };
-   |            ------------             ^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
+   |            ------------             ^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
    |            |
    |            type annotation requires that borrow lasts for `'static`
 LL |
diff --git a/src/test/ui/consts/const-eval/union_promotion.stderr b/src/test/ui/consts/const-eval/union_promotion.stderr
index 70808c520d3..42f17de2003 100644
--- a/src/test/ui/consts/const-eval/union_promotion.stderr
+++ b/src/test/ui/consts/const-eval/union_promotion.stderr
@@ -7,7 +7,7 @@ LL |       let x: &'static bool = &unsafe {
    | |            type annotation requires that borrow lasts for `'static`
 LL | |         Foo { a: &1 }.b == Foo { a: &2 }.b
 LL | |     };
-   | |_____^ creates a temporary which is freed while still in use
+   | |_____^ creates a temporary value which is freed while still in use
 LL |   }
    |   - temporary value is freed at the end of this statement
 
diff --git a/src/test/ui/consts/const-int-conversion.stderr b/src/test/ui/consts/const-int-conversion.stderr
index 61162a79226..5dd757e3f5e 100644
--- a/src/test/ui/consts/const-int-conversion.stderr
+++ b/src/test/ui/consts/const-int-conversion.stderr
@@ -2,7 +2,7 @@ error[E0716]: temporary value dropped while borrowed
   --> $DIR/const-int-conversion.rs:2:28
    |
 LL |     let x: &'static i32 = &(5_i32.reverse_bits());
-   |            ------------    ^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
+   |            ------------    ^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
    |            |
    |            type annotation requires that borrow lasts for `'static`
 ...
@@ -13,7 +13,7 @@ error[E0716]: temporary value dropped while borrowed
   --> $DIR/const-int-conversion.rs:4:28
    |
 LL |     let y: &'static i32 = &(i32::from_be_bytes([0x12, 0x34, 0x56, 0x78]));
-   |            ------------    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
+   |            ------------    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
    |            |
    |            type annotation requires that borrow lasts for `'static`
 ...
@@ -24,7 +24,7 @@ error[E0716]: temporary value dropped while borrowed
   --> $DIR/const-int-conversion.rs:6:28
    |
 LL |     let z: &'static i32 = &(i32::from_le_bytes([0x12, 0x34, 0x56, 0x78]));
-   |            ------------    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
+   |            ------------    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
    |            |
    |            type annotation requires that borrow lasts for `'static`
 ...
@@ -35,7 +35,7 @@ error[E0716]: temporary value dropped while borrowed
   --> $DIR/const-int-conversion.rs:8:28
    |
 LL |     let a: &'static i32 = &(i32::from_be(i32::from_ne_bytes([0x80, 0, 0, 0])));
-   |            ------------    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
+   |            ------------    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
    |            |
    |            type annotation requires that borrow lasts for `'static`
 ...
@@ -46,7 +46,7 @@ error[E0716]: temporary value dropped while borrowed
   --> $DIR/const-int-conversion.rs:10:29
    |
 LL |     let b: &'static [u8] = &(0x12_34_56_78_i32.to_be_bytes());
-   |            -------------    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
+   |            -------------    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
    |            |
    |            type annotation requires that borrow lasts for `'static`
 ...
@@ -57,7 +57,7 @@ error[E0716]: temporary value dropped while borrowed
   --> $DIR/const-int-conversion.rs:12:29
    |
 LL |     let c: &'static [u8] = &(0x12_34_56_78_i32.to_le_bytes());
-   |            -------------    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
+   |            -------------    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
    |            |
    |            type annotation requires that borrow lasts for `'static`
 ...
@@ -68,7 +68,7 @@ error[E0716]: temporary value dropped while borrowed
   --> $DIR/const-int-conversion.rs:14:29
    |
 LL |     let d: &'static [u8] = &(i32::MIN.to_be().to_ne_bytes());
-   |            -------------    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
+   |            -------------    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
    |            |
    |            type annotation requires that borrow lasts for `'static`
 LL |
diff --git a/src/test/ui/consts/const-int-overflowing.stderr b/src/test/ui/consts/const-int-overflowing.stderr
index 56c7f7f092d..7d3689e6ec7 100644
--- a/src/test/ui/consts/const-int-overflowing.stderr
+++ b/src/test/ui/consts/const-int-overflowing.stderr
@@ -2,7 +2,7 @@ error[E0716]: temporary value dropped while borrowed
   --> $DIR/const-int-overflowing.rs:2:36
    |
 LL |     let x: &'static (i32, bool) = &(5_i32.overflowing_add(3));
-   |            --------------------    ^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
+   |            --------------------    ^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
    |            |
    |            type annotation requires that borrow lasts for `'static`
 ...
@@ -13,7 +13,7 @@ error[E0716]: temporary value dropped while borrowed
   --> $DIR/const-int-overflowing.rs:4:36
    |
 LL |     let y: &'static (i32, bool) = &(5_i32.overflowing_sub(3));
-   |            --------------------    ^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
+   |            --------------------    ^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
    |            |
    |            type annotation requires that borrow lasts for `'static`
 ...
@@ -24,7 +24,7 @@ error[E0716]: temporary value dropped while borrowed
   --> $DIR/const-int-overflowing.rs:6:36
    |
 LL |     let z: &'static (i32, bool) = &(5_i32.overflowing_mul(3));
-   |            --------------------    ^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
+   |            --------------------    ^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
    |            |
    |            type annotation requires that borrow lasts for `'static`
 LL |
diff --git a/src/test/ui/consts/const-int-rotate.stderr b/src/test/ui/consts/const-int-rotate.stderr
index ed265804bbc..039da1c31c5 100644
--- a/src/test/ui/consts/const-int-rotate.stderr
+++ b/src/test/ui/consts/const-int-rotate.stderr
@@ -2,7 +2,7 @@ error[E0716]: temporary value dropped while borrowed
   --> $DIR/const-int-rotate.rs:2:28
    |
 LL |     let x: &'static i32 = &(5_i32.rotate_left(3));
-   |            ------------    ^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
+   |            ------------    ^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
    |            |
    |            type annotation requires that borrow lasts for `'static`
 ...
@@ -13,7 +13,7 @@ error[E0716]: temporary value dropped while borrowed
   --> $DIR/const-int-rotate.rs:4:28
    |
 LL |     let y: &'static i32 = &(5_i32.rotate_right(3));
-   |            ------------    ^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
+   |            ------------    ^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
    |            |
    |            type annotation requires that borrow lasts for `'static`
 LL |
diff --git a/src/test/ui/consts/const-int-sign.stderr b/src/test/ui/consts/const-int-sign.stderr
index 5f8fd414180..fc23d9d2b29 100644
--- a/src/test/ui/consts/const-int-sign.stderr
+++ b/src/test/ui/consts/const-int-sign.stderr
@@ -2,7 +2,7 @@ error[E0716]: temporary value dropped while borrowed
   --> $DIR/const-int-sign.rs:2:29
    |
 LL |     let x: &'static bool = &(5_i32.is_negative());
-   |            -------------    ^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
+   |            -------------    ^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
    |            |
    |            type annotation requires that borrow lasts for `'static`
 ...
@@ -13,7 +13,7 @@ error[E0716]: temporary value dropped while borrowed
   --> $DIR/const-int-sign.rs:4:29
    |
 LL |     let y: &'static bool = &(5_i32.is_positive());
-   |            -------------    ^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
+   |            -------------    ^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
    |            |
    |            type annotation requires that borrow lasts for `'static`
 LL |
diff --git a/src/test/ui/consts/const-int-wrapping.stderr b/src/test/ui/consts/const-int-wrapping.stderr
index 5174b72659c..1342fadc405 100644
--- a/src/test/ui/consts/const-int-wrapping.stderr
+++ b/src/test/ui/consts/const-int-wrapping.stderr
@@ -2,7 +2,7 @@ error[E0716]: temporary value dropped while borrowed
   --> $DIR/const-int-wrapping.rs:2:28
    |
 LL |     let x: &'static i32 = &(5_i32.wrapping_add(3));
-   |            ------------    ^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
+   |            ------------    ^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
    |            |
    |            type annotation requires that borrow lasts for `'static`
 ...
@@ -13,7 +13,7 @@ error[E0716]: temporary value dropped while borrowed
   --> $DIR/const-int-wrapping.rs:4:28
    |
 LL |     let y: &'static i32 = &(5_i32.wrapping_sub(3));
-   |            ------------    ^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
+   |            ------------    ^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
    |            |
    |            type annotation requires that borrow lasts for `'static`
 ...
@@ -24,7 +24,7 @@ error[E0716]: temporary value dropped while borrowed
   --> $DIR/const-int-wrapping.rs:6:28
    |
 LL |     let z: &'static i32 = &(5_i32.wrapping_mul(3));
-   |            ------------    ^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
+   |            ------------    ^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
    |            |
    |            type annotation requires that borrow lasts for `'static`
 ...
@@ -35,7 +35,7 @@ error[E0716]: temporary value dropped while borrowed
   --> $DIR/const-int-wrapping.rs:8:28
    |
 LL |     let a: &'static i32 = &(5_i32.wrapping_shl(3));
-   |            ------------    ^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
+   |            ------------    ^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
    |            |
    |            type annotation requires that borrow lasts for `'static`
 ...
@@ -46,7 +46,7 @@ error[E0716]: temporary value dropped while borrowed
   --> $DIR/const-int-wrapping.rs:10:28
    |
 LL |     let b: &'static i32 = &(5_i32.wrapping_shr(3));
-   |            ------------    ^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
+   |            ------------    ^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
    |            |
    |            type annotation requires that borrow lasts for `'static`
 LL |
diff --git a/src/test/ui/consts/const-mut-refs/mut_ref_in_final.stderr b/src/test/ui/consts/const-mut-refs/mut_ref_in_final.stderr
index 3a9ce79f10e..78c58b5ab09 100644
--- a/src/test/ui/consts/const-mut-refs/mut_ref_in_final.stderr
+++ b/src/test/ui/consts/const-mut-refs/mut_ref_in_final.stderr
@@ -11,7 +11,7 @@ LL | const B3: Option<&mut i32> = Some(&mut 42);
    |                              ----------^^-
    |                              |         | |
    |                              |         | temporary value is freed at the end of this statement
-   |                              |         creates a temporary which is freed while still in use
+   |                              |         creates a temporary value which is freed while still in use
    |                              using this value as a constant requires that borrow lasts for `'static`
 
 error[E0716]: temporary value dropped while borrowed
@@ -21,7 +21,7 @@ LL | const B4: Option<&mut i32> = helper(&mut 42);
    |                              ------------^^-
    |                              |           | |
    |                              |           | temporary value is freed at the end of this statement
-   |                              |           creates a temporary which is freed while still in use
+   |                              |           creates a temporary value which is freed while still in use
    |                              using this value as a constant requires that borrow lasts for `'static`
 
 error[E0716]: temporary value dropped while borrowed
@@ -31,7 +31,7 @@ LL | const FOO: NotAMutex<&mut i32> = NotAMutex(UnsafeCell::new(&mut 42));
    |                                  -------------------------------^^--
    |                                  |                              |  |
    |                                  |                              |  temporary value is freed at the end of this statement
-   |                                  |                              creates a temporary which is freed while still in use
+   |                                  |                              creates a temporary value which is freed while still in use
    |                                  using this value as a constant requires that borrow lasts for `'static`
 
 error[E0716]: temporary value dropped while borrowed
@@ -41,7 +41,7 @@ LL | static FOO2: NotAMutex<&mut i32> = NotAMutex(UnsafeCell::new(&mut 42));
    |                                    -------------------------------^^--
    |                                    |                              |  |
    |                                    |                              |  temporary value is freed at the end of this statement
-   |                                    |                              creates a temporary which is freed while still in use
+   |                                    |                              creates a temporary value which is freed while still in use
    |                                    using this value as a static requires that borrow lasts for `'static`
 
 error[E0716]: temporary value dropped while borrowed
@@ -51,7 +51,7 @@ LL | static mut FOO3: NotAMutex<&mut i32> = NotAMutex(UnsafeCell::new(&mut 42));
    |                                        -------------------------------^^--
    |                                        |                              |  |
    |                                        |                              |  temporary value is freed at the end of this statement
-   |                                        |                              creates a temporary which is freed while still in use
+   |                                        |                              creates a temporary value which is freed while still in use
    |                                        using this value as a static requires that borrow lasts for `'static`
 
 error: aborting due to 6 previous errors
diff --git a/src/test/ui/consts/const-ptr-nonnull.stderr b/src/test/ui/consts/const-ptr-nonnull.stderr
index 26946fb9902..dbcb0c86052 100644
--- a/src/test/ui/consts/const-ptr-nonnull.stderr
+++ b/src/test/ui/consts/const-ptr-nonnull.stderr
@@ -2,7 +2,7 @@ error[E0716]: temporary value dropped while borrowed
   --> $DIR/const-ptr-nonnull.rs:4:37
    |
 LL |     let x: &'static NonNull<u32> = &(NonNull::dangling());
-   |            ---------------------    ^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
+   |            ---------------------    ^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
    |            |
    |            type annotation requires that borrow lasts for `'static`
 ...
@@ -13,7 +13,7 @@ error[E0716]: temporary value dropped while borrowed
   --> $DIR/const-ptr-nonnull.rs:9:37
    |
 LL |     let x: &'static NonNull<u32> = &(non_null.cast());
-   |            ---------------------    ^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
+   |            ---------------------    ^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
    |            |
    |            type annotation requires that borrow lasts for `'static`
 LL |
diff --git a/src/test/ui/consts/const-ptr-unique.stderr b/src/test/ui/consts/const-ptr-unique.stderr
index 3644cf4cec7..83448c3e8d8 100644
--- a/src/test/ui/consts/const-ptr-unique.stderr
+++ b/src/test/ui/consts/const-ptr-unique.stderr
@@ -2,7 +2,7 @@ error[E0716]: temporary value dropped while borrowed
   --> $DIR/const-ptr-unique.rs:8:33
    |
 LL |     let x: &'static *mut u32 = &(unique.as_ptr());
-   |            -----------------    ^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
+   |            -----------------    ^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
    |            |
    |            type annotation requires that borrow lasts for `'static`
 LL |
diff --git a/src/test/ui/consts/control-flow/interior-mutability.stderr b/src/test/ui/consts/control-flow/interior-mutability.stderr
index 4f9c7d34c35..db2ffb91b98 100644
--- a/src/test/ui/consts/control-flow/interior-mutability.stderr
+++ b/src/test/ui/consts/control-flow/interior-mutability.stderr
@@ -2,7 +2,7 @@ error[E0716]: temporary value dropped while borrowed
   --> $DIR/interior-mutability.rs:40:26
    |
 LL |     let x: &'static _ = &X;
-   |            ----------    ^ creates a temporary which is freed while still in use
+   |            ----------    ^ creates a temporary value which is freed while still in use
    |            |
    |            type annotation requires that borrow lasts for `'static`
 ...
@@ -13,7 +13,7 @@ error[E0716]: temporary value dropped while borrowed
   --> $DIR/interior-mutability.rs:41:26
    |
 LL |     let y: &'static _ = &Y;
-   |            ----------    ^ creates a temporary which is freed while still in use
+   |            ----------    ^ creates a temporary value which is freed while still in use
    |            |
    |            type annotation requires that borrow lasts for `'static`
 LL |     let z: &'static _ = &Z;
@@ -24,7 +24,7 @@ error[E0716]: temporary value dropped while borrowed
   --> $DIR/interior-mutability.rs:42:26
    |
 LL |     let z: &'static _ = &Z;
-   |            ----------    ^ creates a temporary which is freed while still in use
+   |            ----------    ^ creates a temporary value which is freed while still in use
    |            |
    |            type annotation requires that borrow lasts for `'static`
 LL | }
diff --git a/src/test/ui/consts/fn_trait_refs.rs b/src/test/ui/consts/fn_trait_refs.rs
new file mode 100644
index 00000000000..b507492970a
--- /dev/null
+++ b/src/test/ui/consts/fn_trait_refs.rs
@@ -0,0 +1,77 @@
+// check-pass
+
+#![feature(const_fn_trait_ref_impls)]
+#![feature(fn_traits)]
+#![feature(unboxed_closures)]
+#![feature(const_trait_impl)]
+#![feature(const_mut_refs)]
+#![feature(const_cmp)]
+#![feature(const_refs_to_cell)]
+
+use std::marker::Destruct;
+
+const fn tester_fn<T>(f: T) -> T::Output
+where
+    T: ~const Fn<()> + ~const Destruct,
+{
+    f()
+}
+
+const fn tester_fn_mut<T>(mut f: T) -> T::Output
+where
+    T: ~const FnMut<()> + ~const Destruct,
+{
+    f()
+}
+
+const fn tester_fn_once<T>(f: T) -> T::Output
+where
+    T: ~const FnOnce<()>,
+{
+    f()
+}
+
+const fn test_fn<T>(mut f: T) -> (T::Output, T::Output, T::Output)
+where
+    T: ~const Fn<()> + ~const Destruct,
+{
+    (
+        // impl<A: Tuple, F: ~const Fn + ?Sized> const Fn<A> for &F
+        tester_fn(&f),
+        // impl<A: Tuple, F: ~const Fn + ?Sized> const FnMut<A> for &F
+        tester_fn_mut(&f),
+        // impl<A: Tuple, F: ~const Fn + ?Sized> const FnOnce<A> for &F
+        tester_fn_once(&f),
+    )
+}
+
+const fn test_fn_mut<T>(mut f: T) -> (T::Output, T::Output)
+where
+    T: ~const FnMut<()> + ~const Destruct,
+{
+    (
+        // impl<A: Tuple, F: ~const FnMut + ?Sized> const FnMut<A> for &mut F
+        tester_fn_mut(&mut f),
+        // impl<A: Tuple, F: ~const FnMut + ?Sized> const FnOnce<A> for &mut F
+        tester_fn_once(&mut f),
+    )
+}
+const fn test(i: i32) -> i32 {
+    i + 1
+}
+
+fn main() {
+    const fn one() -> i32 {
+        1
+    };
+    const fn two() -> i32 {
+        2
+    };
+    const _: () = {
+        let test_one = test_fn(one);
+        assert!(test_one == (1, 1, 1));
+
+        let test_two = test_fn_mut(two);
+        assert!(test_two == (2, 2));
+    };
+}
diff --git a/src/test/ui/consts/issue-102117.rs b/src/test/ui/consts/issue-102117.rs
index b77342c4135..3ed90aed235 100644
--- a/src/test/ui/consts/issue-102117.rs
+++ b/src/test/ui/consts/issue-102117.rs
@@ -14,11 +14,11 @@ pub struct VTable {
 impl VTable {
     pub fn new<T>() -> &'static Self {
         const {
-          //~^ ERROR the parameter type `T` may not live long enough
-          //~| ERROR the parameter type `T` may not live long enough
             &VTable {
                 layout: Layout::new::<T>(),
                 type_id: TypeId::of::<T>(),
+                //~^ ERROR the parameter type `T` may not live long enough
+                //~| ERROR the parameter type `T` may not live long enough
                 drop_in_place: unsafe {
                     transmute::<unsafe fn(*mut T), unsafe fn(*mut ())>(drop_in_place::<T>)
                 },
diff --git a/src/test/ui/consts/issue-102117.stderr b/src/test/ui/consts/issue-102117.stderr
index eb4b329bd81..f42bcf90fb7 100644
--- a/src/test/ui/consts/issue-102117.stderr
+++ b/src/test/ui/consts/issue-102117.stderr
@@ -1,14 +1,8 @@
 error[E0310]: the parameter type `T` may not live long enough
-  --> $DIR/issue-102117.rs:16:9
+  --> $DIR/issue-102117.rs:19:26
    |
-LL | /         const {
-LL | |
-LL | |
-LL | |             &VTable {
-...  |
-LL | |             }
-LL | |         }
-   | |_________^ ...so that the type `T` will meet its required lifetime bounds
+LL |                 type_id: TypeId::of::<T>(),
+   |                          ^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
    |
 help: consider adding an explicit lifetime bound...
    |
@@ -16,16 +10,10 @@ LL |     pub fn new<T: 'static>() -> &'static Self {
    |                 +++++++++
 
 error[E0310]: the parameter type `T` may not live long enough
-  --> $DIR/issue-102117.rs:16:9
+  --> $DIR/issue-102117.rs:19:26
    |
-LL | /         const {
-LL | |
-LL | |
-LL | |             &VTable {
-...  |
-LL | |             }
-LL | |         }
-   | |_________^ ...so that the type `T` will meet its required lifetime bounds
+LL |                 type_id: TypeId::of::<T>(),
+   |                          ^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
    |
 help: consider adding an explicit lifetime bound...
    |
diff --git a/src/test/ui/consts/issue-104155.rs b/src/test/ui/consts/issue-104155.rs
new file mode 100644
index 00000000000..1cc8f81b0d2
--- /dev/null
+++ b/src/test/ui/consts/issue-104155.rs
@@ -0,0 +1,5 @@
+// check-pass
+const _: () = core::mem::forget(Box::<u32>::default);
+const _: () = core::mem::forget(|| Box::<u32>::default());
+
+fn main() {}
diff --git a/src/test/ui/consts/issue-54224.stderr b/src/test/ui/consts/issue-54224.stderr
index 8dcb4daca3b..55fe55759df 100644
--- a/src/test/ui/consts/issue-54224.stderr
+++ b/src/test/ui/consts/issue-54224.stderr
@@ -5,7 +5,7 @@ LL | const FOO: Option<&[[u8; 3]]> = Some(&[*b"foo"]);
    |                                 ------^^^^^^^^^-
    |                                 |     |        |
    |                                 |     |        temporary value is freed at the end of this statement
-   |                                 |     creates a temporary which is freed while still in use
+   |                                 |     creates a temporary value which is freed while still in use
    |                                 using this value as a constant requires that borrow lasts for `'static`
 
 error[E0716]: temporary value dropped while borrowed
@@ -15,7 +15,7 @@ LL | pub const Z: Cow<'static, [ [u8; 3] ]> = Cow::Borrowed(&[*b"ABC"]);
    |                                          ---------------^^^^^^^^^-
    |                                          |              |        |
    |                                          |              |        temporary value is freed at the end of this statement
-   |                                          |              creates a temporary which is freed while still in use
+   |                                          |              creates a temporary value which is freed while still in use
    |                                          using this value as a constant requires that borrow lasts for `'static`
 
 error: aborting due to 2 previous errors
diff --git a/src/test/ui/issues/issue-54954.rs b/src/test/ui/consts/issue-54954.rs
index d4e1df22770..d4e1df22770 100644
--- a/src/test/ui/issues/issue-54954.rs
+++ b/src/test/ui/consts/issue-54954.rs
diff --git a/src/test/ui/issues/issue-54954.stderr b/src/test/ui/consts/issue-54954.stderr
index 668985c2b59..668985c2b59 100644
--- a/src/test/ui/issues/issue-54954.stderr
+++ b/src/test/ui/consts/issue-54954.stderr
diff --git a/src/test/ui/consts/min_const_fn/promotion.stderr b/src/test/ui/consts/min_const_fn/promotion.stderr
index 550423c2d93..0b8dc0ce0e9 100644
--- a/src/test/ui/consts/min_const_fn/promotion.stderr
+++ b/src/test/ui/consts/min_const_fn/promotion.stderr
@@ -2,7 +2,7 @@ error[E0716]: temporary value dropped while borrowed
   --> $DIR/promotion.rs:11:27
    |
 LL |     let x: &'static () = &foo1();
-   |            -----------    ^^^^^^ creates a temporary which is freed while still in use
+   |            -----------    ^^^^^^ creates a temporary value which is freed while still in use
    |            |
    |            type annotation requires that borrow lasts for `'static`
 ...
@@ -13,7 +13,7 @@ error[E0716]: temporary value dropped while borrowed
   --> $DIR/promotion.rs:12:28
    |
 LL |     let y: &'static i32 = &foo2(42);
-   |            ------------    ^^^^^^^^ creates a temporary which is freed while still in use
+   |            ------------    ^^^^^^^^ creates a temporary value which is freed while still in use
    |            |
    |            type annotation requires that borrow lasts for `'static`
 ...
@@ -24,7 +24,7 @@ error[E0716]: temporary value dropped while borrowed
   --> $DIR/promotion.rs:13:28
    |
 LL |     let z: &'static i32 = &foo3();
-   |            ------------    ^^^^^^ creates a temporary which is freed while still in use
+   |            ------------    ^^^^^^ creates a temporary value which is freed while still in use
    |            |
    |            type annotation requires that borrow lasts for `'static`
 ...
@@ -35,7 +35,7 @@ error[E0716]: temporary value dropped while borrowed
   --> $DIR/promotion.rs:14:34
    |
 LL |     let a: &'static Cell<i32> = &foo4();
-   |            ------------------    ^^^^^^ creates a temporary which is freed while still in use
+   |            ------------------    ^^^^^^ creates a temporary value which is freed while still in use
    |            |
    |            type annotation requires that borrow lasts for `'static`
 ...
@@ -46,7 +46,7 @@ error[E0716]: temporary value dropped while borrowed
   --> $DIR/promotion.rs:15:42
    |
 LL |     let a: &'static Option<Cell<i32>> = &foo5();
-   |            --------------------------    ^^^^^^ creates a temporary which is freed while still in use
+   |            --------------------------    ^^^^^^ creates a temporary value which is freed while still in use
    |            |
    |            type annotation requires that borrow lasts for `'static`
 LL |     let a: &'static Option<Cell<i32>> = &foo6();
@@ -57,7 +57,7 @@ error[E0716]: temporary value dropped while borrowed
   --> $DIR/promotion.rs:16:42
    |
 LL |     let a: &'static Option<Cell<i32>> = &foo6();
-   |            --------------------------    ^^^^^^ creates a temporary which is freed while still in use
+   |            --------------------------    ^^^^^^ creates a temporary value which is freed while still in use
    |            |
    |            type annotation requires that borrow lasts for `'static`
 LL | }
diff --git a/src/test/ui/consts/promote-not.stderr b/src/test/ui/consts/promote-not.stderr
index 0d0b0f9c689..b93358e8dcc 100644
--- a/src/test/ui/consts/promote-not.stderr
+++ b/src/test/ui/consts/promote-not.stderr
@@ -5,14 +5,14 @@ LL | static mut TEST1: Option<&mut [i32]> = Some(&mut [1, 2, 3]);
    |                                        ----------^^^^^^^^^-
    |                                        |         |        |
    |                                        |         |        temporary value is freed at the end of this statement
-   |                                        |         creates a temporary which is freed while still in use
+   |                                        |         creates a temporary value which is freed while still in use
    |                                        using this value as a static requires that borrow lasts for `'static`
 
 error[E0716]: temporary value dropped while borrowed
   --> $DIR/promote-not.rs:11:18
    |
 LL |     let x = &mut [1,2,3];
-   |                  ^^^^^^^ creates a temporary which is freed while still in use
+   |                  ^^^^^^^ creates a temporary value which is freed while still in use
 LL |     x
    |     - using this value as a static requires that borrow lasts for `'static`
 LL | };
@@ -22,7 +22,7 @@ error[E0716]: temporary value dropped while borrowed
   --> $DIR/promote-not.rs:20:32
    |
 LL |         let _x: &'static () = &foo();
-   |                 -----------    ^^^^^ creates a temporary which is freed while still in use
+   |                 -----------    ^^^^^ creates a temporary value which is freed while still in use
    |                 |
    |                 type annotation requires that borrow lasts for `'static`
 LL |     }
@@ -32,7 +32,7 @@ error[E0716]: temporary value dropped while borrowed
   --> $DIR/promote-not.rs:28:29
    |
 LL |     let _x: &'static i32 = &unsafe { U { x: 0 }.x };
-   |             ------------    ^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
+   |             ------------    ^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
    |             |
    |             type annotation requires that borrow lasts for `'static`
 LL | }
@@ -42,7 +42,7 @@ error[E0716]: temporary value dropped while borrowed
   --> $DIR/promote-not.rs:33:29
    |
 LL |     let _x: &'static i32 = &unsafe { U { x: 0 }.x };
-   |             ------------    ^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
+   |             ------------    ^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
    |             |
    |             type annotation requires that borrow lasts for `'static`
 LL | };
@@ -52,7 +52,7 @@ error[E0716]: temporary value dropped while borrowed
   --> $DIR/promote-not.rs:39:29
    |
 LL |     let _val: &'static _ = &(Cell::new(1), 2).1;
-   |               ----------    ^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
+   |               ----------    ^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
    |               |
    |               type annotation requires that borrow lasts for `'static`
 LL | };
@@ -62,7 +62,7 @@ error[E0716]: temporary value dropped while borrowed
   --> $DIR/promote-not.rs:46:29
    |
 LL |     let _val: &'static _ = &(Cell::new(1), 2).0;
-   |               ----------    ^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
+   |               ----------    ^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
    |               |
    |               type annotation requires that borrow lasts for `'static`
 ...
@@ -73,7 +73,7 @@ error[E0716]: temporary value dropped while borrowed
   --> $DIR/promote-not.rs:47:29
    |
 LL |     let _val: &'static _ = &(Cell::new(1), 2).1;
-   |               ----------    ^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
+   |               ----------    ^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
    |               |
    |               type annotation requires that borrow lasts for `'static`
 ...
@@ -84,7 +84,7 @@ error[E0716]: temporary value dropped while borrowed
   --> $DIR/promote-not.rs:50:29
    |
 LL |     let _val: &'static _ = &(1/0);
-   |               ----------    ^^^^^ creates a temporary which is freed while still in use
+   |               ----------    ^^^^^ creates a temporary value which is freed while still in use
    |               |
    |               type annotation requires that borrow lasts for `'static`
 ...
@@ -95,7 +95,7 @@ error[E0716]: temporary value dropped while borrowed
   --> $DIR/promote-not.rs:51:29
    |
 LL |     let _val: &'static _ = &(1/(1-1));
-   |               ----------    ^^^^^^^^^ creates a temporary which is freed while still in use
+   |               ----------    ^^^^^^^^^ creates a temporary value which is freed while still in use
    |               |
    |               type annotation requires that borrow lasts for `'static`
 ...
@@ -106,7 +106,7 @@ error[E0716]: temporary value dropped while borrowed
   --> $DIR/promote-not.rs:52:29
    |
 LL |     let _val: &'static _ = &(1%0);
-   |               ----------    ^^^^^ creates a temporary which is freed while still in use
+   |               ----------    ^^^^^ creates a temporary value which is freed while still in use
    |               |
    |               type annotation requires that borrow lasts for `'static`
 ...
@@ -117,7 +117,7 @@ error[E0716]: temporary value dropped while borrowed
   --> $DIR/promote-not.rs:53:29
    |
 LL |     let _val: &'static _ = &(1%(1-1));
-   |               ----------    ^^^^^^^^^ creates a temporary which is freed while still in use
+   |               ----------    ^^^^^^^^^ creates a temporary value which is freed while still in use
    |               |
    |               type annotation requires that borrow lasts for `'static`
 ...
@@ -128,7 +128,7 @@ error[E0716]: temporary value dropped while borrowed
   --> $DIR/promote-not.rs:54:29
    |
 LL |     let _val: &'static _ = &([1,2,3][4]+1);
-   |               ----------    ^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
+   |               ----------    ^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
    |               |
    |               type annotation requires that borrow lasts for `'static`
 ...
@@ -139,7 +139,7 @@ error[E0716]: temporary value dropped while borrowed
   --> $DIR/promote-not.rs:57:29
    |
 LL |     let _val: &'static _ = &TEST_DROP;
-   |               ----------    ^^^^^^^^^ creates a temporary which is freed while still in use
+   |               ----------    ^^^^^^^^^ creates a temporary value which is freed while still in use
    |               |
    |               type annotation requires that borrow lasts for `'static`
 ...
@@ -150,7 +150,7 @@ error[E0716]: temporary value dropped while borrowed
   --> $DIR/promote-not.rs:59:29
    |
 LL |     let _val: &'static _ = &&TEST_DROP;
-   |               ----------    ^^^^^^^^^^ creates a temporary which is freed while still in use
+   |               ----------    ^^^^^^^^^^ creates a temporary value which is freed while still in use
    |               |
    |               type annotation requires that borrow lasts for `'static`
 ...
@@ -161,7 +161,7 @@ error[E0716]: temporary value dropped while borrowed
   --> $DIR/promote-not.rs:59:30
    |
 LL |     let _val: &'static _ = &&TEST_DROP;
-   |               ----------     ^^^^^^^^^ creates a temporary which is freed while still in use
+   |               ----------     ^^^^^^^^^ creates a temporary value which is freed while still in use
    |               |
    |               type annotation requires that borrow lasts for `'static`
 ...
@@ -172,7 +172,7 @@ error[E0716]: temporary value dropped while borrowed
   --> $DIR/promote-not.rs:62:29
    |
 LL |     let _val: &'static _ = &(&TEST_DROP,);
-   |               ----------    ^^^^^^^^^^^^^ creates a temporary which is freed while still in use
+   |               ----------    ^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
    |               |
    |               type annotation requires that borrow lasts for `'static`
 ...
@@ -183,7 +183,7 @@ error[E0716]: temporary value dropped while borrowed
   --> $DIR/promote-not.rs:62:31
    |
 LL |     let _val: &'static _ = &(&TEST_DROP,);
-   |               ----------      ^^^^^^^^^ creates a temporary which is freed while still in use
+   |               ----------      ^^^^^^^^^ creates a temporary value which is freed while still in use
    |               |
    |               type annotation requires that borrow lasts for `'static`
 ...
@@ -194,7 +194,7 @@ error[E0716]: temporary value dropped while borrowed
   --> $DIR/promote-not.rs:65:29
    |
 LL |     let _val: &'static _ = &[&TEST_DROP; 1];
-   |               ----------    ^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
+   |               ----------    ^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
    |               |
    |               type annotation requires that borrow lasts for `'static`
 ...
@@ -207,7 +207,7 @@ error[E0716]: temporary value dropped while borrowed
 LL |     let _val: &'static _ = &[&TEST_DROP; 1];
    |               ----------      ^^^^^^^^^    - temporary value is freed at the end of this statement
    |               |               |
-   |               |               creates a temporary which is freed while still in use
+   |               |               creates a temporary value which is freed while still in use
    |               type annotation requires that borrow lasts for `'static`
 
 error: aborting due to 20 previous errors
diff --git a/src/test/ui/consts/promote_const_let.stderr b/src/test/ui/consts/promote_const_let.stderr
index c47d297c904..975a235a649 100644
--- a/src/test/ui/consts/promote_const_let.stderr
+++ b/src/test/ui/consts/promote_const_let.stderr
@@ -19,7 +19,7 @@ LL |       let x: &'static u32 = &{
 LL | |         let y = 42;
 LL | |         y
 LL | |     };
-   | |_____^ creates a temporary which is freed while still in use
+   | |_____^ creates a temporary value which is freed while still in use
 LL |   }
    |   - temporary value is freed at the end of this statement
 
diff --git a/src/test/ui/consts/promoted-const-drop.stderr b/src/test/ui/consts/promoted-const-drop.stderr
index 184ba0ea3b3..4802834173f 100644
--- a/src/test/ui/consts/promoted-const-drop.stderr
+++ b/src/test/ui/consts/promoted-const-drop.stderr
@@ -2,7 +2,7 @@ error[E0716]: temporary value dropped while borrowed
   --> $DIR/promoted-const-drop.rs:13:26
    |
 LL |     let _: &'static A = &A();
-   |            ----------    ^^^ creates a temporary which is freed while still in use
+   |            ----------    ^^^ creates a temporary value which is freed while still in use
    |            |
    |            type annotation requires that borrow lasts for `'static`
 LL |     let _: &'static [A] = &[C];
@@ -13,7 +13,7 @@ error[E0716]: temporary value dropped while borrowed
   --> $DIR/promoted-const-drop.rs:14:28
    |
 LL |     let _: &'static [A] = &[C];
-   |            ------------    ^^^ creates a temporary which is freed while still in use
+   |            ------------    ^^^ creates a temporary value which is freed while still in use
    |            |
    |            type annotation requires that borrow lasts for `'static`
 LL | }
diff --git a/src/test/ui/consts/qualif-union.stderr b/src/test/ui/consts/qualif-union.stderr
index 8ec68ada048..d847cf88f50 100644
--- a/src/test/ui/consts/qualif-union.stderr
+++ b/src/test/ui/consts/qualif-union.stderr
@@ -2,7 +2,7 @@ error[E0716]: temporary value dropped while borrowed
   --> $DIR/qualif-union.rs:28:26
    |
 LL |     let _: &'static _ = &C1;
-   |            ----------    ^^ creates a temporary which is freed while still in use
+   |            ----------    ^^ creates a temporary value which is freed while still in use
    |            |
    |            type annotation requires that borrow lasts for `'static`
 ...
@@ -13,7 +13,7 @@ error[E0716]: temporary value dropped while borrowed
   --> $DIR/qualif-union.rs:29:26
    |
 LL |     let _: &'static _ = &C2;
-   |            ----------    ^^ creates a temporary which is freed while still in use
+   |            ----------    ^^ creates a temporary value which is freed while still in use
    |            |
    |            type annotation requires that borrow lasts for `'static`
 ...
@@ -24,7 +24,7 @@ error[E0716]: temporary value dropped while borrowed
   --> $DIR/qualif-union.rs:30:26
    |
 LL |     let _: &'static _ = &C3;
-   |            ----------    ^^ creates a temporary which is freed while still in use
+   |            ----------    ^^ creates a temporary value which is freed while still in use
    |            |
    |            type annotation requires that borrow lasts for `'static`
 ...
@@ -35,7 +35,7 @@ error[E0716]: temporary value dropped while borrowed
   --> $DIR/qualif-union.rs:31:26
    |
 LL |     let _: &'static _ = &C4;
-   |            ----------    ^^ creates a temporary which is freed while still in use
+   |            ----------    ^^ creates a temporary value which is freed while still in use
    |            |
    |            type annotation requires that borrow lasts for `'static`
 LL |     let _: &'static _ = &C5;
@@ -46,7 +46,7 @@ error[E0716]: temporary value dropped while borrowed
   --> $DIR/qualif-union.rs:32:26
    |
 LL |     let _: &'static _ = &C5;
-   |            ----------    ^^ creates a temporary which is freed while still in use
+   |            ----------    ^^ creates a temporary value which is freed while still in use
    |            |
    |            type annotation requires that borrow lasts for `'static`
 LL | }
diff --git a/src/test/ui/did_you_mean/issue-103909.rs b/src/test/ui/did_you_mean/issue-103909.rs
new file mode 100644
index 00000000000..20b67cd102d
--- /dev/null
+++ b/src/test/ui/did_you_mean/issue-103909.rs
@@ -0,0 +1,9 @@
+#![allow(unused_variables)]
+use std::fs::File;
+
+fn main() {
+    if Err(err) = File::open("hello.txt") {
+        //~^ ERROR: cannot find value `err` in this scope
+        //~| ERROR: mismatched types
+    }
+}
diff --git a/src/test/ui/did_you_mean/issue-103909.stderr b/src/test/ui/did_you_mean/issue-103909.stderr
new file mode 100644
index 00000000000..8641017470b
--- /dev/null
+++ b/src/test/ui/did_you_mean/issue-103909.stderr
@@ -0,0 +1,26 @@
+error[E0425]: cannot find value `err` in this scope
+  --> $DIR/issue-103909.rs:5:12
+   |
+LL |     if Err(err) = File::open("hello.txt") {
+   |            ^^^ not found in this scope
+   |
+help: you might have meant to use pattern matching
+   |
+LL |     if let Err(err) = File::open("hello.txt") {
+   |        +++
+
+error[E0308]: mismatched types
+  --> $DIR/issue-103909.rs:5:8
+   |
+LL |     if Err(err) = File::open("hello.txt") {
+   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found `()`
+   |
+help: consider adding `let`
+   |
+LL |     if let Err(err) = File::open("hello.txt") {
+   |        +++
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0308, E0425.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-54943-1.rs b/src/test/ui/dropck/issue-54943-1.rs
index ec682d96081..ec682d96081 100644
--- a/src/test/ui/issues/issue-54943-1.rs
+++ b/src/test/ui/dropck/issue-54943-1.rs
diff --git a/src/test/ui/issues/issue-54943-2.rs b/src/test/ui/dropck/issue-54943-2.rs
index d400ae58db4..d400ae58db4 100644
--- a/src/test/ui/issues/issue-54943-2.rs
+++ b/src/test/ui/dropck/issue-54943-2.rs
diff --git a/src/test/ui/error-codes/E0059.stderr b/src/test/ui/error-codes/E0059.stderr
index a1b8aeaedbb..f331d014226 100644
--- a/src/test/ui/error-codes/E0059.stderr
+++ b/src/test/ui/error-codes/E0059.stderr
@@ -1,8 +1,14 @@
-error[E0059]: cannot use call notation; the first type parameter for the function trait is neither a tuple nor unit
-  --> $DIR/E0059.rs:3:41
+error[E0059]: type parameter to bare `Fn` trait must be a tuple
+  --> $DIR/E0059.rs:3:11
    |
 LL | fn foo<F: Fn<i32>>(f: F) -> F::Output { f(3) }
-   |                                         ^^^^
+   |           ^^^^^^^ the trait `Tuple` is not implemented for `i32`
+   |
+note: required by a bound in `Fn`
+  --> $SRC_DIR/core/src/ops/function.rs:LL:COL
+   |
+LL | pub trait Fn<Args: Tuple>: FnMut<Args> {
+   |                    ^^^^^ required by this bound in `Fn`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/error-codes/E0282.rs b/src/test/ui/error-codes/E0282.rs
index 9bd16abb7bb..f1f93b3aed6 100644
--- a/src/test/ui/error-codes/E0282.rs
+++ b/src/test/ui/error-codes/E0282.rs
@@ -1,3 +1,4 @@
 fn main() {
-    let x = "hello".chars().rev().collect(); //~ ERROR E0282
+    let x = "hello".chars().rev().collect();
+    //~^ ERROR E0282
 }
diff --git a/src/test/ui/error-codes/E0401.rs b/src/test/ui/error-codes/E0401.rs
index c30e5f47188..8f8d6b87ef2 100644
--- a/src/test/ui/error-codes/E0401.rs
+++ b/src/test/ui/error-codes/E0401.rs
@@ -8,7 +8,9 @@ fn foo<T>(x: T) {
            W: Fn()>
            (y: T) { //~ ERROR E0401
     }
-    bfnr(x); //~ ERROR type annotations needed
+    bfnr(x);
+    //~^ ERROR type annotations needed
+    //~| ERROR type annotations needed
 }
 
 
diff --git a/src/test/ui/error-codes/E0401.stderr b/src/test/ui/error-codes/E0401.stderr
index b0e2ef5b6f7..9687eca61fa 100644
--- a/src/test/ui/error-codes/E0401.stderr
+++ b/src/test/ui/error-codes/E0401.stderr
@@ -21,7 +21,7 @@ LL |            (y: T) {
    |                ^ use of generic parameter from outer function
 
 error[E0401]: can't use generic parameters from outer function
-  --> $DIR/E0401.rs:22:25
+  --> $DIR/E0401.rs:24:25
    |
 LL | impl<T> Iterator for A<T> {
    | ---- `Self` type implicitly declared here, by this `impl`
@@ -43,7 +43,28 @@ help: consider specifying the generic arguments
 LL |     bfnr::<U, V, W>(x);
    |         +++++++++++
 
-error: aborting due to 4 previous errors
+error[E0283]: type annotations needed
+  --> $DIR/E0401.rs:11:5
+   |
+LL |     bfnr(x);
+   |     ^^^^ cannot infer type of the type parameter `W` declared on the function `bfnr`
+   |
+   = note: multiple `impl`s satisfying `_: Fn<()>` found in the following crates: `alloc`, `core`:
+           - impl<A, F> Fn<A> for &F
+             where A: Tuple, F: Fn<A>, F: ?Sized;
+           - impl<Args, F, A> Fn<Args> for Box<F, A>
+             where Args: Tuple, F: Fn<Args>, A: Allocator, F: ?Sized;
+note: required by a bound in `bfnr`
+  --> $DIR/E0401.rs:4:30
+   |
+LL |     fn bfnr<U, V: Baz<U>, W: Fn()>(y: T) {
+   |                              ^^^^ required by this bound in `bfnr`
+help: consider specifying the type arguments in the function call
+   |
+LL |     bfnr::<U, V, W>(x);
+   |         +++++++++++
+
+error: aborting due to 5 previous errors
 
-Some errors have detailed explanations: E0282, E0401.
+Some errors have detailed explanations: E0282, E0283, E0401.
 For more information about an error, try `rustc --explain E0282`.
diff --git a/src/test/ui/error-codes/E0778.rs b/src/test/ui/error-codes/E0778.rs
index 60e5c2598f1..74653886d41 100644
--- a/src/test/ui/error-codes/E0778.rs
+++ b/src/test/ui/error-codes/E0778.rs
@@ -1,8 +1,4 @@
-#![feature(isa_attribute)]
-
 #[instruction_set()] //~ ERROR
-fn no_isa_defined() {
-}
+fn no_isa_defined() {}
 
-fn main() {
-}
+fn main() {}
diff --git a/src/test/ui/error-codes/E0778.stderr b/src/test/ui/error-codes/E0778.stderr
index 6ecae792423..42647e5c6a1 100644
--- a/src/test/ui/error-codes/E0778.stderr
+++ b/src/test/ui/error-codes/E0778.stderr
@@ -1,5 +1,5 @@
 error[E0778]: `#[instruction_set]` requires an argument
-  --> $DIR/E0778.rs:3:1
+  --> $DIR/E0778.rs:1:1
    |
 LL | #[instruction_set()]
    | ^^^^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/error-codes/E0779.rs b/src/test/ui/error-codes/E0779.rs
index 1b4dbce2036..c32dae12c9c 100644
--- a/src/test/ui/error-codes/E0779.rs
+++ b/src/test/ui/error-codes/E0779.rs
@@ -1,6 +1,2 @@
-#![feature(isa_attribute)]
-
 #[instruction_set(arm::magic)] //~ ERROR
-fn main() {
-
-}
+fn main() {}
diff --git a/src/test/ui/error-codes/E0779.stderr b/src/test/ui/error-codes/E0779.stderr
index da787260d4f..7c6a119a096 100644
--- a/src/test/ui/error-codes/E0779.stderr
+++ b/src/test/ui/error-codes/E0779.stderr
@@ -1,5 +1,5 @@
 error[E0779]: invalid instruction set specified
-  --> $DIR/E0779.rs:3:1
+  --> $DIR/E0779.rs:1:1
    |
 LL | #[instruction_set(arm::magic)]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/feature-gates/feature-gate-abi-efiapi.rs b/src/test/ui/feature-gates/feature-gate-abi-efiapi.rs
new file mode 100644
index 00000000000..0c0d736acd0
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-abi-efiapi.rs
@@ -0,0 +1,33 @@
+// needs-llvm-components: x86
+// compile-flags: --target=x86_64-unknown-linux-gnu --crate-type=rlib
+#![no_core]
+#![feature(no_core, lang_items)]
+#[lang="sized"]
+trait Sized { }
+
+// Functions
+extern "efiapi" fn f1() {} //~ ERROR efiapi ABI is experimental
+
+// Methods in trait defintion
+trait Tr {
+    extern "efiapi" fn f2(); //~ ERROR efiapi ABI is experimental
+    extern "efiapi" fn f3() {} //~ ERROR efiapi ABI is experimental
+}
+
+struct S;
+
+// Methods in trait impl
+impl Tr for S {
+    extern "efiapi" fn f2() {} //~ ERROR efiapi ABI is experimental
+}
+
+// Methods in inherent impl
+impl S {
+    extern "efiapi" fn f4() {} //~ ERROR efiapi ABI is experimental
+}
+
+// Function pointer types
+type A = extern "efiapi" fn(); //~ ERROR efiapi ABI is experimental
+
+// Foreign modules
+extern "efiapi" {} //~ ERROR efiapi ABI is experimental
diff --git a/src/test/ui/feature-gates/feature-gate-abi-efiapi.stderr b/src/test/ui/feature-gates/feature-gate-abi-efiapi.stderr
new file mode 100644
index 00000000000..5b01dcc6d85
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-abi-efiapi.stderr
@@ -0,0 +1,66 @@
+error[E0658]: efiapi ABI is experimental and subject to change
+  --> $DIR/feature-gate-abi-efiapi.rs:9:8
+   |
+LL | extern "efiapi" fn f1() {}
+   |        ^^^^^^^^
+   |
+   = note: see issue #65815 <https://github.com/rust-lang/rust/issues/65815> for more information
+   = help: add `#![feature(abi_efiapi)]` to the crate attributes to enable
+
+error[E0658]: efiapi ABI is experimental and subject to change
+  --> $DIR/feature-gate-abi-efiapi.rs:13:12
+   |
+LL |     extern "efiapi" fn f2();
+   |            ^^^^^^^^
+   |
+   = note: see issue #65815 <https://github.com/rust-lang/rust/issues/65815> for more information
+   = help: add `#![feature(abi_efiapi)]` to the crate attributes to enable
+
+error[E0658]: efiapi ABI is experimental and subject to change
+  --> $DIR/feature-gate-abi-efiapi.rs:14:12
+   |
+LL |     extern "efiapi" fn f3() {}
+   |            ^^^^^^^^
+   |
+   = note: see issue #65815 <https://github.com/rust-lang/rust/issues/65815> for more information
+   = help: add `#![feature(abi_efiapi)]` to the crate attributes to enable
+
+error[E0658]: efiapi ABI is experimental and subject to change
+  --> $DIR/feature-gate-abi-efiapi.rs:21:12
+   |
+LL |     extern "efiapi" fn f2() {}
+   |            ^^^^^^^^
+   |
+   = note: see issue #65815 <https://github.com/rust-lang/rust/issues/65815> for more information
+   = help: add `#![feature(abi_efiapi)]` to the crate attributes to enable
+
+error[E0658]: efiapi ABI is experimental and subject to change
+  --> $DIR/feature-gate-abi-efiapi.rs:26:12
+   |
+LL |     extern "efiapi" fn f4() {}
+   |            ^^^^^^^^
+   |
+   = note: see issue #65815 <https://github.com/rust-lang/rust/issues/65815> for more information
+   = help: add `#![feature(abi_efiapi)]` to the crate attributes to enable
+
+error[E0658]: efiapi ABI is experimental and subject to change
+  --> $DIR/feature-gate-abi-efiapi.rs:30:17
+   |
+LL | type A = extern "efiapi" fn();
+   |                 ^^^^^^^^
+   |
+   = note: see issue #65815 <https://github.com/rust-lang/rust/issues/65815> for more information
+   = help: add `#![feature(abi_efiapi)]` to the crate attributes to enable
+
+error[E0658]: efiapi ABI is experimental and subject to change
+  --> $DIR/feature-gate-abi-efiapi.rs:33:8
+   |
+LL | extern "efiapi" {}
+   |        ^^^^^^^^
+   |
+   = note: see issue #65815 <https://github.com/rust-lang/rust/issues/65815> for more information
+   = help: add `#![feature(abi_efiapi)]` to the crate attributes to enable
+
+error: aborting due to 7 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-abi.rs b/src/test/ui/feature-gates/feature-gate-abi.rs
index 855263595d0..712655f9775 100644
--- a/src/test/ui/feature-gates/feature-gate-abi.rs
+++ b/src/test/ui/feature-gates/feature-gate-abi.rs
@@ -1,6 +1,5 @@
 // gate-test-intrinsics
 // gate-test-platform_intrinsics
-// gate-test-abi_efiapi
 // compile-flags: --crate-type=rlib
 
 #![feature(no_core, lang_items)]
@@ -9,13 +8,15 @@
 #[lang="sized"]
 trait Sized { }
 
+#[lang="tuple_trait"]
+trait Tuple { }
+
 // Functions
 extern "rust-intrinsic" fn f1() {} //~ ERROR intrinsics are subject to change
                                    //~^ ERROR intrinsic must be in
 extern "platform-intrinsic" fn f2() {} //~ ERROR platform intrinsics are experimental
                                        //~^ ERROR intrinsic must be in
 extern "rust-call" fn f4(_: ()) {} //~ ERROR rust-call ABI is subject to change
-extern "efiapi" fn f10() {} //~ ERROR efiapi ABI is experimental and subject to change
 
 // Methods in trait definition
 trait Tr {
@@ -24,10 +25,8 @@ trait Tr {
     extern "platform-intrinsic" fn m2(); //~ ERROR platform intrinsics are experimental
                                          //~^ ERROR intrinsic must be in
     extern "rust-call" fn m4(_: ()); //~ ERROR rust-call ABI is subject to change
-    extern "efiapi" fn m10(); //~ ERROR efiapi ABI is experimental and subject to change
 
     extern "rust-call" fn dm4(_: ()) {} //~ ERROR rust-call ABI is subject to change
-    extern "efiapi" fn dm10() {} //~ ERROR efiapi ABI is experimental and subject to change
 }
 
 struct S;
@@ -39,7 +38,6 @@ impl Tr for S {
     extern "platform-intrinsic" fn m2() {} //~ ERROR platform intrinsics are experimental
                                            //~^ ERROR intrinsic must be in
     extern "rust-call" fn m4(_: ()) {} //~ ERROR rust-call ABI is subject to change
-    extern "efiapi" fn m10() {} //~ ERROR efiapi ABI is experimental and subject to change
 }
 
 // Methods in inherent impl
@@ -49,17 +47,14 @@ impl S {
     extern "platform-intrinsic" fn im2() {} //~ ERROR platform intrinsics are experimental
                                             //~^ ERROR intrinsic must be in
     extern "rust-call" fn im4(_: ()) {} //~ ERROR rust-call ABI is subject to change
-    extern "efiapi" fn im10() {} //~ ERROR efiapi ABI is experimental and subject to change
 }
 
 // Function pointer types
 type A1 = extern "rust-intrinsic" fn(); //~ ERROR intrinsics are subject to change
 type A2 = extern "platform-intrinsic" fn(); //~ ERROR platform intrinsics are experimental
 type A4 = extern "rust-call" fn(_: ()); //~ ERROR rust-call ABI is subject to change
-type A10 = extern "efiapi" fn(); //~ ERROR efiapi ABI is experimental and subject to change
 
 // Foreign modules
 extern "rust-intrinsic" {} //~ ERROR intrinsics are subject to change
 extern "platform-intrinsic" {} //~ ERROR platform intrinsics are experimental
 extern "rust-call" {} //~ ERROR rust-call ABI is subject to change
-extern "efiapi" {} //~ ERROR efiapi ABI is experimental and subject to change
diff --git a/src/test/ui/feature-gates/feature-gate-abi.stderr b/src/test/ui/feature-gates/feature-gate-abi.stderr
index bcca39c8fb8..e9791b9513f 100644
--- a/src/test/ui/feature-gates/feature-gate-abi.stderr
+++ b/src/test/ui/feature-gates/feature-gate-abi.stderr
@@ -1,5 +1,5 @@
 error[E0658]: intrinsics are subject to change
-  --> $DIR/feature-gate-abi.rs:13:8
+  --> $DIR/feature-gate-abi.rs:15:8
    |
 LL | extern "rust-intrinsic" fn f1() {}
    |        ^^^^^^^^^^^^^^^^
@@ -7,7 +7,7 @@ LL | extern "rust-intrinsic" fn f1() {}
    = help: add `#![feature(intrinsics)]` to the crate attributes to enable
 
 error[E0658]: platform intrinsics are experimental and possibly buggy
-  --> $DIR/feature-gate-abi.rs:15:8
+  --> $DIR/feature-gate-abi.rs:17:8
    |
 LL | extern "platform-intrinsic" fn f2() {}
    |        ^^^^^^^^^^^^^^^^^^^^
@@ -16,7 +16,7 @@ LL | extern "platform-intrinsic" fn f2() {}
    = help: add `#![feature(platform_intrinsics)]` to the crate attributes to enable
 
 error[E0658]: rust-call ABI is subject to change
-  --> $DIR/feature-gate-abi.rs:17:8
+  --> $DIR/feature-gate-abi.rs:19:8
    |
 LL | extern "rust-call" fn f4(_: ()) {}
    |        ^^^^^^^^^^^
@@ -24,17 +24,8 @@ LL | extern "rust-call" fn f4(_: ()) {}
    = note: see issue #29625 <https://github.com/rust-lang/rust/issues/29625> for more information
    = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable
 
-error[E0658]: efiapi ABI is experimental and subject to change
-  --> $DIR/feature-gate-abi.rs:18:8
-   |
-LL | extern "efiapi" fn f10() {}
-   |        ^^^^^^^^
-   |
-   = note: see issue #65815 <https://github.com/rust-lang/rust/issues/65815> for more information
-   = help: add `#![feature(abi_efiapi)]` to the crate attributes to enable
-
 error[E0658]: intrinsics are subject to change
-  --> $DIR/feature-gate-abi.rs:22:12
+  --> $DIR/feature-gate-abi.rs:23:12
    |
 LL |     extern "rust-intrinsic" fn m1();
    |            ^^^^^^^^^^^^^^^^
@@ -42,7 +33,7 @@ LL |     extern "rust-intrinsic" fn m1();
    = help: add `#![feature(intrinsics)]` to the crate attributes to enable
 
 error[E0658]: platform intrinsics are experimental and possibly buggy
-  --> $DIR/feature-gate-abi.rs:24:12
+  --> $DIR/feature-gate-abi.rs:25:12
    |
 LL |     extern "platform-intrinsic" fn m2();
    |            ^^^^^^^^^^^^^^^^^^^^
@@ -51,7 +42,7 @@ LL |     extern "platform-intrinsic" fn m2();
    = help: add `#![feature(platform_intrinsics)]` to the crate attributes to enable
 
 error[E0658]: rust-call ABI is subject to change
-  --> $DIR/feature-gate-abi.rs:26:12
+  --> $DIR/feature-gate-abi.rs:27:12
    |
 LL |     extern "rust-call" fn m4(_: ());
    |            ^^^^^^^^^^^
@@ -59,15 +50,6 @@ LL |     extern "rust-call" fn m4(_: ());
    = note: see issue #29625 <https://github.com/rust-lang/rust/issues/29625> for more information
    = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable
 
-error[E0658]: efiapi ABI is experimental and subject to change
-  --> $DIR/feature-gate-abi.rs:27:12
-   |
-LL |     extern "efiapi" fn m10();
-   |            ^^^^^^^^
-   |
-   = note: see issue #65815 <https://github.com/rust-lang/rust/issues/65815> for more information
-   = help: add `#![feature(abi_efiapi)]` to the crate attributes to enable
-
 error[E0658]: rust-call ABI is subject to change
   --> $DIR/feature-gate-abi.rs:29:12
    |
@@ -77,17 +59,8 @@ LL |     extern "rust-call" fn dm4(_: ()) {}
    = note: see issue #29625 <https://github.com/rust-lang/rust/issues/29625> for more information
    = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable
 
-error[E0658]: efiapi ABI is experimental and subject to change
-  --> $DIR/feature-gate-abi.rs:30:12
-   |
-LL |     extern "efiapi" fn dm10() {}
-   |            ^^^^^^^^
-   |
-   = note: see issue #65815 <https://github.com/rust-lang/rust/issues/65815> for more information
-   = help: add `#![feature(abi_efiapi)]` to the crate attributes to enable
-
 error[E0658]: intrinsics are subject to change
-  --> $DIR/feature-gate-abi.rs:37:12
+  --> $DIR/feature-gate-abi.rs:36:12
    |
 LL |     extern "rust-intrinsic" fn m1() {}
    |            ^^^^^^^^^^^^^^^^
@@ -95,7 +68,7 @@ LL |     extern "rust-intrinsic" fn m1() {}
    = help: add `#![feature(intrinsics)]` to the crate attributes to enable
 
 error[E0658]: platform intrinsics are experimental and possibly buggy
-  --> $DIR/feature-gate-abi.rs:39:12
+  --> $DIR/feature-gate-abi.rs:38:12
    |
 LL |     extern "platform-intrinsic" fn m2() {}
    |            ^^^^^^^^^^^^^^^^^^^^
@@ -104,7 +77,7 @@ LL |     extern "platform-intrinsic" fn m2() {}
    = help: add `#![feature(platform_intrinsics)]` to the crate attributes to enable
 
 error[E0658]: rust-call ABI is subject to change
-  --> $DIR/feature-gate-abi.rs:41:12
+  --> $DIR/feature-gate-abi.rs:40:12
    |
 LL |     extern "rust-call" fn m4(_: ()) {}
    |            ^^^^^^^^^^^
@@ -112,17 +85,8 @@ LL |     extern "rust-call" fn m4(_: ()) {}
    = note: see issue #29625 <https://github.com/rust-lang/rust/issues/29625> for more information
    = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable
 
-error[E0658]: efiapi ABI is experimental and subject to change
-  --> $DIR/feature-gate-abi.rs:42:12
-   |
-LL |     extern "efiapi" fn m10() {}
-   |            ^^^^^^^^
-   |
-   = note: see issue #65815 <https://github.com/rust-lang/rust/issues/65815> for more information
-   = help: add `#![feature(abi_efiapi)]` to the crate attributes to enable
-
 error[E0658]: intrinsics are subject to change
-  --> $DIR/feature-gate-abi.rs:47:12
+  --> $DIR/feature-gate-abi.rs:45:12
    |
 LL |     extern "rust-intrinsic" fn im1() {}
    |            ^^^^^^^^^^^^^^^^
@@ -130,7 +94,7 @@ LL |     extern "rust-intrinsic" fn im1() {}
    = help: add `#![feature(intrinsics)]` to the crate attributes to enable
 
 error[E0658]: platform intrinsics are experimental and possibly buggy
-  --> $DIR/feature-gate-abi.rs:49:12
+  --> $DIR/feature-gate-abi.rs:47:12
    |
 LL |     extern "platform-intrinsic" fn im2() {}
    |            ^^^^^^^^^^^^^^^^^^^^
@@ -139,7 +103,7 @@ LL |     extern "platform-intrinsic" fn im2() {}
    = help: add `#![feature(platform_intrinsics)]` to the crate attributes to enable
 
 error[E0658]: rust-call ABI is subject to change
-  --> $DIR/feature-gate-abi.rs:51:12
+  --> $DIR/feature-gate-abi.rs:49:12
    |
 LL |     extern "rust-call" fn im4(_: ()) {}
    |            ^^^^^^^^^^^
@@ -147,17 +111,8 @@ LL |     extern "rust-call" fn im4(_: ()) {}
    = note: see issue #29625 <https://github.com/rust-lang/rust/issues/29625> for more information
    = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable
 
-error[E0658]: efiapi ABI is experimental and subject to change
-  --> $DIR/feature-gate-abi.rs:52:12
-   |
-LL |     extern "efiapi" fn im10() {}
-   |            ^^^^^^^^
-   |
-   = note: see issue #65815 <https://github.com/rust-lang/rust/issues/65815> for more information
-   = help: add `#![feature(abi_efiapi)]` to the crate attributes to enable
-
 error[E0658]: intrinsics are subject to change
-  --> $DIR/feature-gate-abi.rs:56:18
+  --> $DIR/feature-gate-abi.rs:53:18
    |
 LL | type A1 = extern "rust-intrinsic" fn();
    |                  ^^^^^^^^^^^^^^^^
@@ -165,7 +120,7 @@ LL | type A1 = extern "rust-intrinsic" fn();
    = help: add `#![feature(intrinsics)]` to the crate attributes to enable
 
 error[E0658]: platform intrinsics are experimental and possibly buggy
-  --> $DIR/feature-gate-abi.rs:57:18
+  --> $DIR/feature-gate-abi.rs:54:18
    |
 LL | type A2 = extern "platform-intrinsic" fn();
    |                  ^^^^^^^^^^^^^^^^^^^^
@@ -174,7 +129,7 @@ LL | type A2 = extern "platform-intrinsic" fn();
    = help: add `#![feature(platform_intrinsics)]` to the crate attributes to enable
 
 error[E0658]: rust-call ABI is subject to change
-  --> $DIR/feature-gate-abi.rs:58:18
+  --> $DIR/feature-gate-abi.rs:55:18
    |
 LL | type A4 = extern "rust-call" fn(_: ());
    |                  ^^^^^^^^^^^
@@ -182,17 +137,8 @@ LL | type A4 = extern "rust-call" fn(_: ());
    = note: see issue #29625 <https://github.com/rust-lang/rust/issues/29625> for more information
    = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable
 
-error[E0658]: efiapi ABI is experimental and subject to change
-  --> $DIR/feature-gate-abi.rs:59:19
-   |
-LL | type A10 = extern "efiapi" fn();
-   |                   ^^^^^^^^
-   |
-   = note: see issue #65815 <https://github.com/rust-lang/rust/issues/65815> for more information
-   = help: add `#![feature(abi_efiapi)]` to the crate attributes to enable
-
 error[E0658]: intrinsics are subject to change
-  --> $DIR/feature-gate-abi.rs:62:8
+  --> $DIR/feature-gate-abi.rs:58:8
    |
 LL | extern "rust-intrinsic" {}
    |        ^^^^^^^^^^^^^^^^
@@ -200,7 +146,7 @@ LL | extern "rust-intrinsic" {}
    = help: add `#![feature(intrinsics)]` to the crate attributes to enable
 
 error[E0658]: platform intrinsics are experimental and possibly buggy
-  --> $DIR/feature-gate-abi.rs:63:8
+  --> $DIR/feature-gate-abi.rs:59:8
    |
 LL | extern "platform-intrinsic" {}
    |        ^^^^^^^^^^^^^^^^^^^^
@@ -209,7 +155,7 @@ LL | extern "platform-intrinsic" {}
    = help: add `#![feature(platform_intrinsics)]` to the crate attributes to enable
 
 error[E0658]: rust-call ABI is subject to change
-  --> $DIR/feature-gate-abi.rs:64:8
+  --> $DIR/feature-gate-abi.rs:60:8
    |
 LL | extern "rust-call" {}
    |        ^^^^^^^^^^^
@@ -217,63 +163,54 @@ LL | extern "rust-call" {}
    = note: see issue #29625 <https://github.com/rust-lang/rust/issues/29625> for more information
    = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable
 
-error[E0658]: efiapi ABI is experimental and subject to change
-  --> $DIR/feature-gate-abi.rs:65:8
-   |
-LL | extern "efiapi" {}
-   |        ^^^^^^^^
-   |
-   = note: see issue #65815 <https://github.com/rust-lang/rust/issues/65815> for more information
-   = help: add `#![feature(abi_efiapi)]` to the crate attributes to enable
-
 error: intrinsic must be in `extern "rust-intrinsic" { ... }` block
-  --> $DIR/feature-gate-abi.rs:22:32
+  --> $DIR/feature-gate-abi.rs:23:32
    |
 LL |     extern "rust-intrinsic" fn m1();
    |                                ^^
 
 error: intrinsic must be in `extern "rust-intrinsic" { ... }` block
-  --> $DIR/feature-gate-abi.rs:24:36
+  --> $DIR/feature-gate-abi.rs:25:36
    |
 LL |     extern "platform-intrinsic" fn m2();
    |                                    ^^
 
 error: intrinsic must be in `extern "rust-intrinsic" { ... }` block
-  --> $DIR/feature-gate-abi.rs:13:33
+  --> $DIR/feature-gate-abi.rs:15:33
    |
 LL | extern "rust-intrinsic" fn f1() {}
    |                                 ^^
 
 error: intrinsic must be in `extern "rust-intrinsic" { ... }` block
-  --> $DIR/feature-gate-abi.rs:15:37
+  --> $DIR/feature-gate-abi.rs:17:37
    |
 LL | extern "platform-intrinsic" fn f2() {}
    |                                     ^^
 
 error: intrinsic must be in `extern "rust-intrinsic" { ... }` block
-  --> $DIR/feature-gate-abi.rs:37:37
+  --> $DIR/feature-gate-abi.rs:36:37
    |
 LL |     extern "rust-intrinsic" fn m1() {}
    |                                     ^^
 
 error: intrinsic must be in `extern "rust-intrinsic" { ... }` block
-  --> $DIR/feature-gate-abi.rs:39:41
+  --> $DIR/feature-gate-abi.rs:38:41
    |
 LL |     extern "platform-intrinsic" fn m2() {}
    |                                         ^^
 
 error: intrinsic must be in `extern "rust-intrinsic" { ... }` block
-  --> $DIR/feature-gate-abi.rs:47:38
+  --> $DIR/feature-gate-abi.rs:45:38
    |
 LL |     extern "rust-intrinsic" fn im1() {}
    |                                      ^^
 
 error: intrinsic must be in `extern "rust-intrinsic" { ... }` block
-  --> $DIR/feature-gate-abi.rs:49:42
+  --> $DIR/feature-gate-abi.rs:47:42
    |
 LL |     extern "platform-intrinsic" fn im2() {}
    |                                          ^^
 
-error: aborting due to 34 previous errors
+error: aborting due to 27 previous errors
 
 For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-custom_mir.rs b/src/test/ui/feature-gates/feature-gate-custom_mir.rs
new file mode 100644
index 00000000000..0126dde2f7d
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-custom_mir.rs
@@ -0,0 +1,12 @@
+#![feature(core_intrinsics)]
+
+extern crate core;
+
+#[custom_mir(dialect = "built")] //~ ERROR the `#[custom_mir]` attribute is just used for the Rust test suite
+pub fn foo(_x: i32) -> i32 {
+    0
+}
+
+fn main() {
+    assert_eq!(2, foo(2));
+}
diff --git a/src/test/ui/feature-gates/feature-gate-custom_mir.stderr b/src/test/ui/feature-gates/feature-gate-custom_mir.stderr
new file mode 100644
index 00000000000..3c149d30d82
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-custom_mir.stderr
@@ -0,0 +1,11 @@
+error[E0658]: the `#[custom_mir]` attribute is just used for the Rust test suite
+  --> $DIR/feature-gate-custom_mir.rs:5:1
+   |
+LL | #[custom_mir(dialect = "built")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add `#![feature(custom_mir)]` to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-isa_attribute.rs b/src/test/ui/feature-gates/feature-gate-isa_attribute.rs
deleted file mode 100644
index cb02a0955e9..00000000000
--- a/src/test/ui/feature-gates/feature-gate-isa_attribute.rs
+++ /dev/null
@@ -1,6 +0,0 @@
-#[instruction_set]
-//~^ ERROR the `#[instruction_set]` attribute is an experimental feature [E0658]
-//~| ERROR malformed `instruction_set` attribute input
-//~| ERROR must specify an instruction set [E0778]
-fn main() {
-}
diff --git a/src/test/ui/feature-gates/feature-gate-isa_attribute.stderr b/src/test/ui/feature-gates/feature-gate-isa_attribute.stderr
deleted file mode 100644
index 2a95a80ca61..00000000000
--- a/src/test/ui/feature-gates/feature-gate-isa_attribute.stderr
+++ /dev/null
@@ -1,25 +0,0 @@
-error: malformed `instruction_set` attribute input
-  --> $DIR/feature-gate-isa_attribute.rs:1:1
-   |
-LL | #[instruction_set]
-   | ^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[instruction_set(set)]`
-
-error[E0658]: the `#[instruction_set]` attribute is an experimental feature
-  --> $DIR/feature-gate-isa_attribute.rs:1:1
-   |
-LL | #[instruction_set]
-   | ^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #74727 <https://github.com/rust-lang/rust/issues/74727> for more information
-   = help: add `#![feature(isa_attribute)]` to the crate attributes to enable
-
-error[E0778]: must specify an instruction set
-  --> $DIR/feature-gate-isa_attribute.rs:1:1
-   |
-LL | #[instruction_set]
-   | ^^^^^^^^^^^^^^^^^^
-
-error: aborting due to 3 previous errors
-
-Some errors have detailed explanations: E0658, E0778.
-For more information about an error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr b/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr
index 5a645cf4ef9..78767040421 100644
--- a/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr
+++ b/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr
@@ -110,19 +110,19 @@ error: attribute should be applied to an `extern crate` item
   --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:25:1
    |
 LL | #![no_link]
-   | ^^^^^^^^^^^
+   | ^^^^^^^^^^^ not an `extern crate` item
 
 error: attribute should be applied to a free function, impl method or static
   --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:27:1
    |
 LL | #![export_name = "2200"]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^^^^^ not a free function, impl method or static
 
 error[E0518]: attribute should be applied to function or closure
   --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:29:1
    |
 LL | #![inline]
-   | ^^^^^^^^^^
+   | ^^^^^^^^^^ not a function or closure
 
 error: `macro_export` attribute cannot be used at crate level
   --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:12:1
diff --git a/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs b/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs
index 8db12e55d25..1fa315f3d21 100644
--- a/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs
+++ b/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs
@@ -1,6 +1,6 @@
 //~ NOTE not a function
 //~| NOTE not a foreign function or static
-//~| NOTE not a function or static
+//~| NOTE cannot be applied to crates
 //~| NOTE not an `extern` block
 // This test enumerates as many compiler-builtin ungated attributes as
 // possible (that is, all the mutually compatible ones), and checks
diff --git a/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr b/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr
index 310d1f720eb..30039267979 100644
--- a/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr
+++ b/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr
@@ -403,7 +403,7 @@ warning: attribute should be applied to a function definition
   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:62:1
    |
 LL | #![cold]
-   | ^^^^^^^^
+   | ^^^^^^^^ cannot be applied to crates
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 
@@ -411,7 +411,7 @@ warning: attribute should be applied to an `extern` block with non-Rust ABI
   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:64:1
    |
 LL | #![link()]
-   | ^^^^^^^^^^
+   | ^^^^^^^^^^ not an `extern` block
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 
@@ -419,7 +419,7 @@ warning: attribute should be applied to a foreign function or static
   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:66:1
    |
 LL | #![link_name = "1900"]
-   | ^^^^^^^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^^^ not a foreign function or static
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 
@@ -427,7 +427,7 @@ warning: attribute should be applied to a function or static
   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:69:1
    |
 LL | #![link_section = "1800"]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^ not a function or static
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 
diff --git a/src/test/ui/fmt/unicode-escape-spans.rs b/src/test/ui/fmt/unicode-escape-spans.rs
new file mode 100644
index 00000000000..753d91ce58e
--- /dev/null
+++ b/src/test/ui/fmt/unicode-escape-spans.rs
@@ -0,0 +1,19 @@
+fn main() {
+    // 1 byte in UTF-8
+    format!("\u{000041}{a}"); //~ ERROR cannot find value
+    format!("\u{0041}{a}"); //~ ERROR cannot find value
+    format!("\u{41}{a}"); //~ ERROR cannot find value
+    format!("\u{0}{a}"); //~ ERROR cannot find value
+
+    // 2 bytes
+    format!("\u{0df}{a}"); //~ ERROR cannot find value
+    format!("\u{df}{a}"); //~ ERROR cannot find value
+
+    // 3 bytes
+    format!("\u{00211d}{a}"); //~ ERROR cannot find value
+    format!("\u{211d}{a}"); //~ ERROR cannot find value
+
+    // 4 bytes
+    format!("\u{1f4a3}{a}"); //~ ERROR cannot find value
+    format!("\u{10ffff}{a}"); //~ ERROR cannot find value
+}
diff --git a/src/test/ui/fmt/unicode-escape-spans.stderr b/src/test/ui/fmt/unicode-escape-spans.stderr
new file mode 100644
index 00000000000..1d8473f01b8
--- /dev/null
+++ b/src/test/ui/fmt/unicode-escape-spans.stderr
@@ -0,0 +1,63 @@
+error[E0425]: cannot find value `a` in this scope
+  --> $DIR/unicode-escape-spans.rs:3:25
+   |
+LL |     format!("\u{000041}{a}");
+   |                         ^ not found in this scope
+
+error[E0425]: cannot find value `a` in this scope
+  --> $DIR/unicode-escape-spans.rs:4:23
+   |
+LL |     format!("\u{0041}{a}");
+   |                       ^ not found in this scope
+
+error[E0425]: cannot find value `a` in this scope
+  --> $DIR/unicode-escape-spans.rs:5:21
+   |
+LL |     format!("\u{41}{a}");
+   |                     ^ not found in this scope
+
+error[E0425]: cannot find value `a` in this scope
+  --> $DIR/unicode-escape-spans.rs:6:20
+   |
+LL |     format!("\u{0}{a}");
+   |                    ^ not found in this scope
+
+error[E0425]: cannot find value `a` in this scope
+  --> $DIR/unicode-escape-spans.rs:9:22
+   |
+LL |     format!("\u{0df}{a}");
+   |                      ^ not found in this scope
+
+error[E0425]: cannot find value `a` in this scope
+  --> $DIR/unicode-escape-spans.rs:10:21
+   |
+LL |     format!("\u{df}{a}");
+   |                     ^ not found in this scope
+
+error[E0425]: cannot find value `a` in this scope
+  --> $DIR/unicode-escape-spans.rs:13:25
+   |
+LL |     format!("\u{00211d}{a}");
+   |                         ^ not found in this scope
+
+error[E0425]: cannot find value `a` in this scope
+  --> $DIR/unicode-escape-spans.rs:14:23
+   |
+LL |     format!("\u{211d}{a}");
+   |                       ^ not found in this scope
+
+error[E0425]: cannot find value `a` in this scope
+  --> $DIR/unicode-escape-spans.rs:17:24
+   |
+LL |     format!("\u{1f4a3}{a}");
+   |                        ^ not found in this scope
+
+error[E0425]: cannot find value `a` in this scope
+  --> $DIR/unicode-escape-spans.rs:18:25
+   |
+LL |     format!("\u{10ffff}{a}");
+   |                         ^ not found in this scope
+
+error: aborting due to 10 previous errors
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/function-pointer/unsized-ret.rs b/src/test/ui/function-pointer/unsized-ret.rs
index 60af5769d6d..79009c5cb6c 100644
--- a/src/test/ui/function-pointer/unsized-ret.rs
+++ b/src/test/ui/function-pointer/unsized-ret.rs
@@ -1,7 +1,8 @@
 #![feature(fn_traits)]
 #![feature(unboxed_closures)]
+#![feature(tuple_trait)]
 
-fn foo<F: Fn<T>, T>(f: Option<F>, t: T) {
+fn foo<F: Fn<T>, T:std::marker::Tuple>(f: Option<F>, t: T) {
     let y = (f.unwrap()).call(t);
 }
 
diff --git a/src/test/ui/function-pointer/unsized-ret.stderr b/src/test/ui/function-pointer/unsized-ret.stderr
index bec3e2aa3fe..40bf7a3898a 100644
--- a/src/test/ui/function-pointer/unsized-ret.stderr
+++ b/src/test/ui/function-pointer/unsized-ret.stderr
@@ -1,5 +1,5 @@
 error[E0277]: the size for values of type `str` cannot be known at compilation time
-  --> $DIR/unsized-ret.rs:9:27
+  --> $DIR/unsized-ret.rs:10:27
    |
 LL |     foo::<fn() -> str, _>(None, ());
    |     --------------------- ^^^^ doesn't have a size known at compile-time
@@ -9,13 +9,13 @@ LL |     foo::<fn() -> str, _>(None, ());
    = help: within `fn() -> str`, the trait `Sized` is not implemented for `str`
    = note: required because it appears within the type `fn() -> str`
 note: required by a bound in `foo`
-  --> $DIR/unsized-ret.rs:4:11
+  --> $DIR/unsized-ret.rs:5:11
    |
-LL | fn foo<F: Fn<T>, T>(f: Option<F>, t: T) {
+LL | fn foo<F: Fn<T>, T:std::marker::Tuple>(f: Option<F>, t: T) {
    |           ^^^^^ required by this bound in `foo`
 
 error[E0277]: the size for values of type `(dyn std::fmt::Display + 'a)` cannot be known at compilation time
-  --> $DIR/unsized-ret.rs:12:66
+  --> $DIR/unsized-ret.rs:13:66
    |
 LL |     foo::<for<'a> fn(&'a ()) -> (dyn std::fmt::Display + 'a), _>(None, (&(),));
    |     ------------------------------------------------------------ ^^^^ doesn't have a size known at compile-time
@@ -25,9 +25,9 @@ LL |     foo::<for<'a> fn(&'a ()) -> (dyn std::fmt::Display + 'a), _>(None, (&()
    = help: within `for<'a> fn(&'a ()) -> (dyn std::fmt::Display + 'a)`, the trait `for<'a> Sized` is not implemented for `(dyn std::fmt::Display + 'a)`
    = note: required because it appears within the type `for<'a> fn(&'a ()) -> (dyn std::fmt::Display + 'a)`
 note: required by a bound in `foo`
-  --> $DIR/unsized-ret.rs:4:11
+  --> $DIR/unsized-ret.rs:5:11
    |
-LL | fn foo<F: Fn<T>, T>(f: Option<F>, t: T) {
+LL | fn foo<F: Fn<T>, T:std::marker::Tuple>(f: Option<F>, t: T) {
    |           ^^^^^ required by this bound in `foo`
 
 error: aborting due to 2 previous errors
diff --git a/src/test/ui/generator/auto-trait-regions.stderr b/src/test/ui/generator/auto-trait-regions.stderr
index 23324af6171..0b1f34aeb96 100644
--- a/src/test/ui/generator/auto-trait-regions.stderr
+++ b/src/test/ui/generator/auto-trait-regions.stderr
@@ -4,7 +4,7 @@ error[E0716]: temporary value dropped while borrowed
 LL |         let a = A(&mut true, &mut true, No);
    |                        ^^^^                - temporary value is freed at the end of this statement
    |                        |
-   |                        creates a temporary which is freed while still in use
+   |                        creates a temporary value which is freed while still in use
 ...
 LL |         assert_foo(a);
    |                    - borrow later used here
@@ -17,7 +17,7 @@ error[E0716]: temporary value dropped while borrowed
 LL |         let a = A(&mut true, &mut true, No);
    |                                   ^^^^     - temporary value is freed at the end of this statement
    |                                   |
-   |                                   creates a temporary which is freed while still in use
+   |                                   creates a temporary value which is freed while still in use
 ...
 LL |         assert_foo(a);
    |                    - borrow later used here
diff --git a/src/test/ui/generic-associated-types/bugs/hrtb-implied-1.stderr b/src/test/ui/generic-associated-types/bugs/hrtb-implied-1.stderr
index 414999881d4..1c9abc4e837 100644
--- a/src/test/ui/generic-associated-types/bugs/hrtb-implied-1.stderr
+++ b/src/test/ui/generic-associated-types/bugs/hrtb-implied-1.stderr
@@ -2,7 +2,7 @@ error[E0716]: temporary value dropped while borrowed
   --> $DIR/hrtb-implied-1.rs:31:22
    |
 LL |     let slice = &mut ();
-   |                      ^^ creates a temporary which is freed while still in use
+   |                      ^^ creates a temporary value which is freed while still in use
 ...
 LL |     print_items::<WindowsMut<'_>>(windows);
    |     -------------------------------------- argument requires that borrow lasts for `'static`
diff --git a/src/test/ui/generic-associated-types/bugs/issue-100013.rs b/src/test/ui/generic-associated-types/bugs/issue-100013.rs
new file mode 100644
index 00000000000..fc4e47a3ba1
--- /dev/null
+++ b/src/test/ui/generic-associated-types/bugs/issue-100013.rs
@@ -0,0 +1,39 @@
+// check-fail
+// known-bug
+// edition: 2021
+
+// We really should accept this, but we need implied bounds between the regions
+// in a generator interior.
+
+pub trait FutureIterator {
+    type Future<'s, 'cx>: Send
+    where
+        's: 'cx;
+}
+
+fn call<I: FutureIterator>() -> impl Send {
+    async { // a generator checked for autotrait impl `Send`
+        //~^ lifetime bound not satisfied
+        let x = None::<I::Future<'_, '_>>; // a type referencing GAT
+        async {}.await; // a yield point
+    }
+}
+
+fn call2<'a, 'b, I: FutureIterator>() -> impl Send {
+    async { // a generator checked for autotrait impl `Send`
+        //~^ lifetime bound not satisfied
+        let x = None::<I::Future<'a, 'b>>; // a type referencing GAT
+        //~^ lifetime may not live long enough
+        async {}.await; // a yield point
+    }
+}
+
+fn call3<'a: 'b, 'b, I: FutureIterator>() -> impl Send {
+    async { // a generator checked for autotrait impl `Send`
+        //~^ lifetime bound not satisfied
+        let x = None::<I::Future<'a, 'b>>; // a type referencing GAT
+        async {}.await; // a yield point
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/generic-associated-types/bugs/issue-100013.stderr b/src/test/ui/generic-associated-types/bugs/issue-100013.stderr
new file mode 100644
index 00000000000..72ae288dcab
--- /dev/null
+++ b/src/test/ui/generic-associated-types/bugs/issue-100013.stderr
@@ -0,0 +1,82 @@
+error: lifetime bound not satisfied
+  --> $DIR/issue-100013.rs:15:5
+   |
+LL | /     async { // a generator checked for autotrait impl `Send`
+LL | |
+LL | |         let x = None::<I::Future<'_, '_>>; // a type referencing GAT
+LL | |         async {}.await; // a yield point
+LL | |     }
+   | |_____^
+   |
+note: the lifetime defined here...
+  --> $DIR/issue-100013.rs:17:38
+   |
+LL |         let x = None::<I::Future<'_, '_>>; // a type referencing GAT
+   |                                      ^^
+note: ...must outlive the lifetime defined here
+  --> $DIR/issue-100013.rs:17:34
+   |
+LL |         let x = None::<I::Future<'_, '_>>; // a type referencing GAT
+   |                                  ^^
+   = note: this is a known limitation that will be removed in the future (see issue #100013 <https://github.com/rust-lang/rust/issues/100013> for more information)
+
+error: lifetime bound not satisfied
+  --> $DIR/issue-100013.rs:23:5
+   |
+LL | /     async { // a generator checked for autotrait impl `Send`
+LL | |
+LL | |         let x = None::<I::Future<'a, 'b>>; // a type referencing GAT
+LL | |
+LL | |         async {}.await; // a yield point
+LL | |     }
+   | |_____^
+   |
+note: the lifetime defined here...
+  --> $DIR/issue-100013.rs:22:14
+   |
+LL | fn call2<'a, 'b, I: FutureIterator>() -> impl Send {
+   |              ^^
+note: ...must outlive the lifetime defined here
+  --> $DIR/issue-100013.rs:22:10
+   |
+LL | fn call2<'a, 'b, I: FutureIterator>() -> impl Send {
+   |          ^^
+   = note: this is a known limitation that will be removed in the future (see issue #100013 <https://github.com/rust-lang/rust/issues/100013> for more information)
+
+error: lifetime may not live long enough
+  --> $DIR/issue-100013.rs:25:17
+   |
+LL | fn call2<'a, 'b, I: FutureIterator>() -> impl Send {
+   |          --  -- lifetime `'b` defined here
+   |          |
+   |          lifetime `'a` defined here
+...
+LL |         let x = None::<I::Future<'a, 'b>>; // a type referencing GAT
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'b`
+   |
+   = help: consider adding the following bound: `'a: 'b`
+
+error: lifetime bound not satisfied
+  --> $DIR/issue-100013.rs:32:5
+   |
+LL | /     async { // a generator checked for autotrait impl `Send`
+LL | |
+LL | |         let x = None::<I::Future<'a, 'b>>; // a type referencing GAT
+LL | |         async {}.await; // a yield point
+LL | |     }
+   | |_____^
+   |
+note: the lifetime defined here...
+  --> $DIR/issue-100013.rs:31:18
+   |
+LL | fn call3<'a: 'b, 'b, I: FutureIterator>() -> impl Send {
+   |                  ^^
+note: ...must outlive the lifetime defined here
+  --> $DIR/issue-100013.rs:31:10
+   |
+LL | fn call3<'a: 'b, 'b, I: FutureIterator>() -> impl Send {
+   |          ^^
+   = note: this is a known limitation that will be removed in the future (see issue #100013 <https://github.com/rust-lang/rust/issues/100013> for more information)
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/generic-associated-types/issue-91139.rs b/src/test/ui/generic-associated-types/issue-91139.rs
index 5fc6071c939..e321da53d56 100644
--- a/src/test/ui/generic-associated-types/issue-91139.rs
+++ b/src/test/ui/generic-associated-types/issue-91139.rs
@@ -21,6 +21,7 @@ fn foo<T>() {
     //~| ERROR `T` does not live long enough
     //~| ERROR `T` does not live long enough
     //~| ERROR `T` may not live long enough
+    //~| ERROR `T` may not live long enough
     //
     // FIXME: This error is bogus, but it arises because we try to validate
     // that `<() as Foo<T>>::Type<'a>` is valid, which requires proving
diff --git a/src/test/ui/generic-associated-types/issue-91139.stderr b/src/test/ui/generic-associated-types/issue-91139.stderr
index 8bbe98fa1e5..5485570cecd 100644
--- a/src/test/ui/generic-associated-types/issue-91139.stderr
+++ b/src/test/ui/generic-associated-types/issue-91139.stderr
@@ -22,6 +22,17 @@ error: `T` does not live long enough
 LL |     let _: for<'a> fn(<() as Foo<T>>::Type<'a>, &'a T) = |_, _| ();
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
+error[E0310]: the parameter type `T` may not live long enough
+  --> $DIR/issue-91139.rs:14:58
+   |
+LL |     let _: for<'a> fn(<() as Foo<T>>::Type<'a>, &'a T) = |_, _| ();
+   |                                                          ^^^^^^ ...so that the type `T` will meet its required lifetime bounds
+   |
+help: consider adding an explicit lifetime bound...
+   |
+LL | fn foo<T: 'static>() {
+   |         +++++++++
+
 error: `T` does not live long enough
   --> $DIR/issue-91139.rs:14:58
    |
@@ -57,6 +68,6 @@ error: `T` does not live long enough
 LL |     let _: for<'a> fn(<() as Foo<T>>::Type<'a>, &'a T) = |_, _| ();
    |                                                          ^^^^^^^^^
 
-error: aborting due to 9 previous errors
+error: aborting due to 10 previous errors
 
 For more information about this error, try `rustc --explain E0310`.
diff --git a/src/test/ui/impl-trait/cross-return-site-inference.rs b/src/test/ui/impl-trait/cross-return-site-inference.rs
index d881af9ed8f..00aed2ad95a 100644
--- a/src/test/ui/impl-trait/cross-return-site-inference.rs
+++ b/src/test/ui/impl-trait/cross-return-site-inference.rs
@@ -30,16 +30,19 @@ fn baa(b: bool) -> impl std::fmt::Debug {
 
 fn muh() -> Result<(), impl std::fmt::Debug> {
     Err("whoops")?;
-    Ok(()) //~ ERROR type annotations needed
+    Ok(())
+    //~^ ERROR type annotations needed
 }
 
 fn muh2() -> Result<(), impl std::fmt::Debug> {
-    return Err(From::from("foo")); //~ ERROR type annotations needed
+    return Err(From::from("foo"));
+    //~^ ERROR type annotations needed
     Ok(())
 }
 
 fn muh3() -> Result<(), impl std::fmt::Debug> {
-    Err(From::from("foo")) //~ ERROR type annotations needed
+    Err(From::from("foo"))
+    //~^ ERROR type annotations needed
 }
 
 fn main() {}
diff --git a/src/test/ui/impl-trait/cross-return-site-inference.stderr b/src/test/ui/impl-trait/cross-return-site-inference.stderr
index 1ff777e6503..766614e9e50 100644
--- a/src/test/ui/impl-trait/cross-return-site-inference.stderr
+++ b/src/test/ui/impl-trait/cross-return-site-inference.stderr
@@ -10,7 +10,7 @@ LL |     Ok::<(), E>(())
    |       +++++++++
 
 error[E0282]: type annotations needed
-  --> $DIR/cross-return-site-inference.rs:37:12
+  --> $DIR/cross-return-site-inference.rs:38:12
    |
 LL |     return Err(From::from("foo"));
    |            ^^^ cannot infer type of the type parameter `E` declared on the enum `Result`
@@ -21,7 +21,7 @@ LL |     return Err::<(), E>(From::from("foo"));
    |               +++++++++
 
 error[E0282]: type annotations needed
-  --> $DIR/cross-return-site-inference.rs:42:5
+  --> $DIR/cross-return-site-inference.rs:44:5
    |
 LL |     Err(From::from("foo"))
    |     ^^^ cannot infer type of the type parameter `E` declared on the enum `Result`
diff --git a/src/test/ui/impl-trait/in-trait/generics-mismatch.rs b/src/test/ui/impl-trait/in-trait/generics-mismatch.rs
new file mode 100644
index 00000000000..cc0fc720ebb
--- /dev/null
+++ b/src/test/ui/impl-trait/in-trait/generics-mismatch.rs
@@ -0,0 +1,17 @@
+#![feature(return_position_impl_trait_in_trait)]
+#![allow(incomplete_features)]
+
+struct U;
+
+trait Foo {
+    fn bar(&self) -> impl Sized;
+}
+
+impl Foo for U {
+    fn bar<T>(&self) {}
+    //~^ ERROR method `bar` has 1 type parameter but its trait declaration has 0 type parameters
+}
+
+fn main() {
+    U.bar();
+}
diff --git a/src/test/ui/impl-trait/in-trait/generics-mismatch.stderr b/src/test/ui/impl-trait/in-trait/generics-mismatch.stderr
new file mode 100644
index 00000000000..cd42683e022
--- /dev/null
+++ b/src/test/ui/impl-trait/in-trait/generics-mismatch.stderr
@@ -0,0 +1,12 @@
+error[E0049]: method `bar` has 1 type parameter but its trait declaration has 0 type parameters
+  --> $DIR/generics-mismatch.rs:11:12
+   |
+LL |     fn bar(&self) -> impl Sized;
+   |           - expected 0 type parameters
+...
+LL |     fn bar<T>(&self) {}
+   |            ^ found 1 type parameter
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0049`.
diff --git a/src/test/ui/impl-trait/in-trait/specialization-broken.rs b/src/test/ui/impl-trait/in-trait/specialization-broken.rs
new file mode 100644
index 00000000000..9d27d3710a6
--- /dev/null
+++ b/src/test/ui/impl-trait/in-trait/specialization-broken.rs
@@ -0,0 +1,26 @@
+// FIXME(compiler-errors): I'm not exactly sure if this is expected to pass or not.
+// But we fixed an ICE anyways.
+
+#![feature(specialization)]
+#![feature(return_position_impl_trait_in_trait)]
+#![allow(incomplete_features)]
+
+trait Foo {
+    fn bar(&self) -> impl Sized;
+}
+
+default impl<U> Foo for U
+where
+    U: Copy,
+{
+    fn bar(&self) -> U {
+        //~^ ERROR method `bar` has an incompatible type for trait
+        *self
+    }
+}
+
+impl Foo for i32 {}
+
+fn main() {
+    1i32.bar();
+}
diff --git a/src/test/ui/impl-trait/in-trait/specialization-broken.stderr b/src/test/ui/impl-trait/in-trait/specialization-broken.stderr
new file mode 100644
index 00000000000..a30e6346b29
--- /dev/null
+++ b/src/test/ui/impl-trait/in-trait/specialization-broken.stderr
@@ -0,0 +1,23 @@
+error[E0053]: method `bar` has an incompatible type for trait
+  --> $DIR/specialization-broken.rs:16:22
+   |
+LL | default impl<U> Foo for U
+   |              - this type parameter
+...
+LL |     fn bar(&self) -> U {
+   |                      ^
+   |                      |
+   |                      expected associated type, found type parameter `U`
+   |                      help: change the output type to match the trait: `impl Sized`
+   |
+note: type in trait
+  --> $DIR/specialization-broken.rs:9:22
+   |
+LL |     fn bar(&self) -> impl Sized;
+   |                      ^^^^^^^^^^
+   = note: expected fn pointer `fn(&U) -> impl Sized`
+              found fn pointer `fn(&U) -> U`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0053`.
diff --git a/src/test/ui/impl-trait/in-trait/specialization-substs-remap.rs b/src/test/ui/impl-trait/in-trait/specialization-substs-remap.rs
new file mode 100644
index 00000000000..c9ee877db8e
--- /dev/null
+++ b/src/test/ui/impl-trait/in-trait/specialization-substs-remap.rs
@@ -0,0 +1,24 @@
+// check-pass
+
+#![feature(specialization)]
+#![feature(return_position_impl_trait_in_trait)]
+#![allow(incomplete_features)]
+
+trait Foo {
+    fn bar(&self) -> impl Sized;
+}
+
+impl<U> Foo for U
+where
+    U: Copy,
+{
+    fn bar(&self) -> U {
+        *self
+    }
+}
+
+impl Foo for i32 {}
+
+fn main() {
+    let _: i32 = 1i32.bar();
+}
diff --git a/src/test/ui/inference/cannot-infer-async.rs b/src/test/ui/inference/cannot-infer-async.rs
index e7fabd0ffbc..b5152d04f69 100644
--- a/src/test/ui/inference/cannot-infer-async.rs
+++ b/src/test/ui/inference/cannot-infer-async.rs
@@ -10,6 +10,7 @@ fn main() {
     let fut = async {
         make_unit()?;
 
-        Ok(()) //~ ERROR type annotations needed
+        Ok(())
+        //~^ ERROR type annotations needed
     };
 }
diff --git a/src/test/ui/inference/cannot-infer-closure.rs b/src/test/ui/inference/cannot-infer-closure.rs
index 1c350b18f5a..bd5d10b4173 100644
--- a/src/test/ui/inference/cannot-infer-closure.rs
+++ b/src/test/ui/inference/cannot-infer-closure.rs
@@ -1,6 +1,7 @@
 fn main() {
     let x = |a: (), b: ()| {
         Err(a)?;
-        Ok(b) //~ ERROR type annotations needed
+        Ok(b)
+        //~^ ERROR type annotations needed
     };
 }
diff --git a/src/test/ui/inference/issue-103587.rs b/src/test/ui/inference/issue-103587.rs
new file mode 100644
index 00000000000..11536f9f4cc
--- /dev/null
+++ b/src/test/ui/inference/issue-103587.rs
@@ -0,0 +1,12 @@
+fn main() {
+    let x = Some(123);
+
+    if let Some(_) == x {}
+    //~^ ERROR expected `=`, found `==`
+
+    if Some(_) = x {}
+    //~^ ERROR mismatched types
+
+    if None = x { }
+    //~^ ERROR mismatched types
+}
diff --git a/src/test/ui/inference/issue-103587.stderr b/src/test/ui/inference/issue-103587.stderr
new file mode 100644
index 00000000000..b373fbfbb94
--- /dev/null
+++ b/src/test/ui/inference/issue-103587.stderr
@@ -0,0 +1,40 @@
+error: expected `=`, found `==`
+  --> $DIR/issue-103587.rs:4:20
+   |
+LL |     if let Some(_) == x {}
+   |                    ^^
+   |
+help: consider using `=` here
+   |
+LL |     if let Some(_) = x {}
+   |                    ~
+
+error[E0308]: mismatched types
+  --> $DIR/issue-103587.rs:7:8
+   |
+LL |     if Some(_) = x {}
+   |        ^^^^^^^^^^^ expected `bool`, found `()`
+   |
+help: consider adding `let`
+   |
+LL |     if let Some(_) = x {}
+   |        +++
+
+error[E0308]: mismatched types
+  --> $DIR/issue-103587.rs:10:8
+   |
+LL |     if None = x { }
+   |        ^^^^^^^^ expected `bool`, found `()`
+   |
+help: you might have meant to use pattern matching
+   |
+LL |     if let None = x { }
+   |        +++
+help: you might have meant to compare for equality
+   |
+LL |     if None == x { }
+   |              +
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/inference/issue-71732.rs b/src/test/ui/inference/issue-71732.rs
index 30063a0957c..8a9d2b235f0 100644
--- a/src/test/ui/inference/issue-71732.rs
+++ b/src/test/ui/inference/issue-71732.rs
@@ -15,7 +15,8 @@ use std::collections::hash_map::HashMap;
 
 fn foo(parameters: &HashMap<String, String>) -> bool {
     parameters
-        .get(&"key".into()) //~ ERROR: type annotations needed
+        .get(&"key".into())
+        //~^ ERROR type annotations needed
         .and_then(|found: &String| Some(false))
         .unwrap_or(false)
 }
diff --git a/src/test/ui/inference/issue-72616.rs b/src/test/ui/inference/issue-72616.rs
index 5e5a3babfe0..69ade1a7515 100644
--- a/src/test/ui/inference/issue-72616.rs
+++ b/src/test/ui/inference/issue-72616.rs
@@ -1,3 +1,5 @@
+// ignore-wasm32 FIXME: ignoring wasm as it suggests slightly different impls
+
 // Regression test for #72616, it used to emit incorrect diagnostics, like:
 // error[E0283]: type annotations needed for `String`
 //  --> src/main.rs:8:30
@@ -18,7 +20,8 @@ pub fn main() {
     }
     {
         if String::from("a") == "a".try_into().unwrap() {}
-        //~^ ERROR: type annotations needed
+        //~^ ERROR type annotations needed
+        //~| ERROR type annotations needed
     }
     {
         let _: String = match "_".try_into() {
diff --git a/src/test/ui/inference/issue-72616.stderr b/src/test/ui/inference/issue-72616.stderr
index a71ce9a8ef2..6ee0626cab8 100644
--- a/src/test/ui/inference/issue-72616.stderr
+++ b/src/test/ui/inference/issue-72616.stderr
@@ -1,5 +1,5 @@
 error[E0283]: type annotations needed
-  --> $DIR/issue-72616.rs:20:37
+  --> $DIR/issue-72616.rs:22:37
    |
 LL |         if String::from("a") == "a".try_into().unwrap() {}
    |                              --     ^^^^^^^^
@@ -16,6 +16,22 @@ help: try using a fully qualified path to specify the expected types
 LL |         if String::from("a") == <&str as TryInto<T>>::try_into("a").unwrap() {}
    |                                 +++++++++++++++++++++++++++++++   ~
 
-error: aborting due to previous error
+error[E0283]: type annotations needed
+  --> $DIR/issue-72616.rs:22:37
+   |
+LL |         if String::from("a") == "a".try_into().unwrap() {}
+   |                                     ^^^^^^^^
+   |
+   = note: multiple `impl`s satisfying `_: TryFrom<&str>` found in the following crates: `core`, `std`:
+           - impl<> TryFrom<&str> for std::sys_common::net::LookupHost;
+           - impl<T, U> TryFrom<U> for T
+             where U: Into<T>;
+   = note: required for `&str` to implement `TryInto<_>`
+help: try using a fully qualified path to specify the expected types
+   |
+LL |         if String::from("a") == <&str as TryInto<T>>::try_into("a").unwrap() {}
+   |                                 +++++++++++++++++++++++++++++++   ~
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0283`.
diff --git a/src/test/ui/inference/question-mark-type-infer.rs b/src/test/ui/inference/question-mark-type-infer.rs
index 64333a29313..10560f85ed4 100644
--- a/src/test/ui/inference/question-mark-type-infer.rs
+++ b/src/test/ui/inference/question-mark-type-infer.rs
@@ -7,7 +7,8 @@ fn f(x: &i32) -> Result<i32, ()> {
 
 fn g() -> Result<Vec<i32>, ()> {
     let l = [1, 2, 3, 4];
-    l.iter().map(f).collect()? //~ ERROR type annotations needed
+    l.iter().map(f).collect()?
+    //~^ ERROR type annotations needed
 }
 
 fn main() {
diff --git a/src/test/ui/issues/issue-12127.rs b/src/test/ui/issues/issue-12127.rs
index 8b30ddc2de6..199d542e816 100644
--- a/src/test/ui/issues/issue-12127.rs
+++ b/src/test/ui/issues/issue-12127.rs
@@ -1,6 +1,6 @@
-#![feature(unboxed_closures)]
+#![feature(unboxed_closures, tuple_trait)]
 
-fn to_fn_once<A,F:FnOnce<A>>(f: F) -> F { f }
+fn to_fn_once<A:std::marker::Tuple,F:FnOnce<A>>(f: F) -> F { f }
 fn do_it(x: &isize) { }
 
 fn main() {
diff --git a/src/test/ui/issues/issue-23024.stderr b/src/test/ui/issues/issue-23024.stderr
index 73f93c51d34..dc8b34a70c3 100644
--- a/src/test/ui/issues/issue-23024.stderr
+++ b/src/test/ui/issues/issue-23024.stderr
@@ -16,7 +16,7 @@ LL |     println!("{:?}",(vfnfer[0] as dyn Fn)(3));
 note: trait defined here, with 1 generic parameter: `Args`
   --> $SRC_DIR/core/src/ops/function.rs:LL:COL
    |
-LL | pub trait Fn<Args>: FnMut<Args> {
+LL | pub trait Fn<Args: Tuple>: FnMut<Args> {
    |           ^^ ----
 help: add missing generic argument
    |
diff --git a/src/test/ui/issues/issue-3707.stderr b/src/test/ui/issues/issue-3707.stderr
index 6ca2deee377..07c8101cbc6 100644
--- a/src/test/ui/issues/issue-3707.stderr
+++ b/src/test/ui/issues/issue-3707.stderr
@@ -2,10 +2,10 @@ error[E0599]: no method named `boom` found for reference `&Obj` in the current s
   --> $DIR/issue-3707.rs:10:14
    |
 LL |         self.boom();
-   |         -----^^^^
+   |         -----^^^^--
    |         |    |
    |         |    this is an associated function, not a method
-   |         help: use associated function syntax instead: `Obj::boom`
+   |         help: use associated function syntax instead: `Obj::boom()`
    |
    = note: found the following associated functions; to be used as methods, functions must have a `self` parameter
 note: the candidate is defined in an impl for the type `Obj`
diff --git a/src/test/ui/issues/issue-47184.stderr b/src/test/ui/issues/issue-47184.stderr
index f97713b4ac4..c2c7df7a333 100644
--- a/src/test/ui/issues/issue-47184.stderr
+++ b/src/test/ui/issues/issue-47184.stderr
@@ -4,7 +4,7 @@ error[E0716]: temporary value dropped while borrowed
 LL |     let _vec: Vec<&'static String> = vec![&String::new()];
    |               --------------------         ^^^^^^^^^^^^^ - temporary value is freed at the end of this statement
    |               |                            |
-   |               |                            creates a temporary which is freed while still in use
+   |               |                            creates a temporary value which is freed while still in use
    |               type annotation requires that borrow lasts for `'static`
 
 error: aborting due to previous error
diff --git a/src/test/ui/issues/issue-47511.stderr b/src/test/ui/issues/issue-47511.stderr
deleted file mode 100644
index 9998ee0e8d0..00000000000
--- a/src/test/ui/issues/issue-47511.stderr
+++ /dev/null
@@ -1,18 +0,0 @@
-error[E0581]: return type references an anonymous lifetime, which is not constrained by the fn input types
-  --> $DIR/issue-47511.rs:8:15
-   |
-LL | fn f(_: X) -> X {
-   |               ^
-   |
-   = note: lifetimes appearing in an associated or opaque type are not considered constrained
-   = note: consider introducing a named lifetime parameter
-
-error[E0581]: return type references lifetime `'a`, which is not constrained by the fn input types
-  --> $DIR/issue-47511.rs:12:23
-   |
-LL | fn g<'a>(_: X<'a>) -> X<'a> {
-   |                       ^^^^^
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0581`.
diff --git a/src/test/ui/issues/issue-52049.stderr b/src/test/ui/issues/issue-52049.stderr
index 55929d85da4..b25dbd1cb8b 100644
--- a/src/test/ui/issues/issue-52049.stderr
+++ b/src/test/ui/issues/issue-52049.stderr
@@ -4,7 +4,7 @@ error[E0716]: temporary value dropped while borrowed
 LL |     foo(&unpromotable(5u32));
    |     -----^^^^^^^^^^^^^^^^^^-
    |     |    |
-   |     |    creates a temporary which is freed while still in use
+   |     |    creates a temporary value which is freed while still in use
    |     argument requires that borrow lasts for `'static`
 LL | }
    | - temporary value is freed at the end of this statement
diff --git a/src/test/ui/issues/issue-69396-const-no-type-in-macro.stderr b/src/test/ui/issues/issue-69396-const-no-type-in-macro.stderr
index f581429a281..89aeafebac4 100644
--- a/src/test/ui/issues/issue-69396-const-no-type-in-macro.stderr
+++ b/src/test/ui/issues/issue-69396-const-no-type-in-macro.stderr
@@ -2,10 +2,7 @@ error[E0428]: the name `A` is defined multiple times
   --> $DIR/issue-69396-const-no-type-in-macro.rs:4:13
    |
 LL |               const A = "A".$fn();
-   |               ^^^^^^^^^^^^^^^^^^^^
-   |               |
-   |               `A` redefined here
-   |               previous definition of the value `A` here
+   |               ^^^^^^^^^^^^^^^^^^^^ `A` redefined here
 ...
 LL | / suite! {
 LL | |     len;
diff --git a/src/test/ui/issues/issue-71584.rs b/src/test/ui/issues/issue-71584.rs
index c96cd598f0c..7bf3ed60ec1 100644
--- a/src/test/ui/issues/issue-71584.rs
+++ b/src/test/ui/issues/issue-71584.rs
@@ -1,5 +1,6 @@
 fn main() {
     let n: u32 = 1;
     let mut d: u64 = 2;
-    d = d % n.into(); //~ ERROR type annotations needed
+    d = d % n.into();
+    //~^ ERROR type annotations needed
 }
diff --git a/src/test/ui/issues/issue-7607-1.stderr b/src/test/ui/issues/issue-7607-1.stderr
index ecff8b42b0e..f1ab0ad26d7 100644
--- a/src/test/ui/issues/issue-7607-1.stderr
+++ b/src/test/ui/issues/issue-7607-1.stderr
@@ -6,8 +6,8 @@ LL | impl Fo {
    |
   ::: $SRC_DIR/core/src/ops/function.rs:LL:COL
    |
-LL | pub trait Fn<Args>: FnMut<Args> {
-   | ------------------------------- similarly named trait `Fn` defined here
+LL | pub trait Fn<Args: Tuple>: FnMut<Args> {
+   | -------------------------------------- similarly named trait `Fn` defined here
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/iterators/collect-into-array.rs b/src/test/ui/iterators/collect-into-array.rs
index 7d35da82532..4c424999b75 100644
--- a/src/test/ui/iterators/collect-into-array.rs
+++ b/src/test/ui/iterators/collect-into-array.rs
@@ -1,5 +1,4 @@
 fn main() {
-    //~^ NOTE required by a bound in this
     let whatever: [u32; 10] = (0..10).collect();
     //~^ ERROR an array of type `[u32; 10]` cannot be built directly from an iterator
     //~| NOTE try collecting into a `Vec<{integer}>`, then using `.try_into()`
diff --git a/src/test/ui/iterators/collect-into-array.stderr b/src/test/ui/iterators/collect-into-array.stderr
index 7fe9707e6d2..a23a36a88ab 100644
--- a/src/test/ui/iterators/collect-into-array.stderr
+++ b/src/test/ui/iterators/collect-into-array.stderr
@@ -1,5 +1,5 @@
 error[E0277]: an array of type `[u32; 10]` cannot be built directly from an iterator
-  --> $DIR/collect-into-array.rs:3:31
+  --> $DIR/collect-into-array.rs:2:31
    |
 LL |     let whatever: [u32; 10] = (0..10).collect();
    |                               ^^^^^^^ ------- required by a bound introduced by this call
diff --git a/src/test/ui/iterators/collect-into-slice.rs b/src/test/ui/iterators/collect-into-slice.rs
index 5eade075613..09832c260d0 100644
--- a/src/test/ui/iterators/collect-into-slice.rs
+++ b/src/test/ui/iterators/collect-into-slice.rs
@@ -1,6 +1,4 @@
 fn process_slice(data: &[i32]) {
-    //~^ NOTE required by a bound in this
-    //~| NOTE required by a bound in this
     todo!()
 }
 
diff --git a/src/test/ui/iterators/collect-into-slice.stderr b/src/test/ui/iterators/collect-into-slice.stderr
index bce40118bdf..bc152467ce3 100644
--- a/src/test/ui/iterators/collect-into-slice.stderr
+++ b/src/test/ui/iterators/collect-into-slice.stderr
@@ -1,5 +1,5 @@
 error[E0277]: the size for values of type `[i32]` cannot be known at compilation time
-  --> $DIR/collect-into-slice.rs:8:9
+  --> $DIR/collect-into-slice.rs:6:9
    |
 LL |     let some_generated_vec = (0..10).collect();
    |         ^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
@@ -9,7 +9,7 @@ LL |     let some_generated_vec = (0..10).collect();
    = help: unsized locals are gated as an unstable feature
 
 error[E0277]: the size for values of type `[i32]` cannot be known at compilation time
-  --> $DIR/collect-into-slice.rs:8:38
+  --> $DIR/collect-into-slice.rs:6:38
    |
 LL |     let some_generated_vec = (0..10).collect();
    |                                      ^^^^^^^ doesn't have a size known at compile-time
@@ -22,7 +22,7 @@ LL |     fn collect<B: FromIterator<Self::Item>>(self) -> B
    |                ^ required by this bound in `collect`
 
 error[E0277]: a slice of type `[i32]` cannot be built since `[i32]` has no definite size
-  --> $DIR/collect-into-slice.rs:8:30
+  --> $DIR/collect-into-slice.rs:6:30
    |
 LL |     let some_generated_vec = (0..10).collect();
    |                              ^^^^^^^ ------- required by a bound introduced by this call
diff --git a/src/test/ui/lang-items/lang-item-missing-generator.rs b/src/test/ui/lang-items/lang-item-missing-generator.rs
index 0c329542928..9b9aff38e52 100644
--- a/src/test/ui/lang-items/lang-item-missing-generator.rs
+++ b/src/test/ui/lang-items/lang-item-missing-generator.rs
@@ -1,12 +1,14 @@
 // error-pattern: requires `generator` lang_item
-#![feature(no_core, lang_items, unboxed_closures)]
+#![feature(no_core, lang_items, unboxed_closures, tuple_trait)]
 #![no_core]
 
 #[lang = "sized"] pub trait Sized { }
 
+#[lang = "tuple_trait"] pub trait Tuple { }
+
 #[lang = "fn_once"]
 #[rustc_paren_sugar]
-pub trait FnOnce<Args> {
+pub trait FnOnce<Args: Tuple> {
     type Output;
 
     extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
diff --git a/src/test/ui/lang-items/lang-item-missing-generator.stderr b/src/test/ui/lang-items/lang-item-missing-generator.stderr
index fa13bf0b127..a24fdb5fb65 100644
--- a/src/test/ui/lang-items/lang-item-missing-generator.stderr
+++ b/src/test/ui/lang-items/lang-item-missing-generator.stderr
@@ -1,8 +1,15 @@
+error[E0635]: unknown feature `tuple_trait`
+  --> $DIR/lang-item-missing-generator.rs:2:51
+   |
+LL | #![feature(no_core, lang_items, unboxed_closures, tuple_trait)]
+   |                                                   ^^^^^^^^^^^
+
 error: requires `generator` lang_item
-  --> $DIR/lang-item-missing-generator.rs:15:17
+  --> $DIR/lang-item-missing-generator.rs:17:17
    |
 LL | pub fn abc() -> impl FnOnce(f32) {
    |                 ^^^^^^^^^^^^^^^^
 
-error: aborting due to previous error
+error: aborting due to 2 previous errors
 
+For more information about this error, try `rustc --explain E0635`.
diff --git a/src/test/ui/late-bound-lifetimes/auxiliary/upstream_alias.rs b/src/test/ui/late-bound-lifetimes/auxiliary/upstream_alias.rs
new file mode 100644
index 00000000000..5b9dc0e4308
--- /dev/null
+++ b/src/test/ui/late-bound-lifetimes/auxiliary/upstream_alias.rs
@@ -0,0 +1,5 @@
+pub trait Trait<'a> {
+    type Assoc;
+}
+
+pub type Alias<'a, T> = <T as Trait<'a>>::Assoc;
diff --git a/src/test/ui/late-bound-lifetimes/cross_crate_alias.rs b/src/test/ui/late-bound-lifetimes/cross_crate_alias.rs
new file mode 100644
index 00000000000..4154c279243
--- /dev/null
+++ b/src/test/ui/late-bound-lifetimes/cross_crate_alias.rs
@@ -0,0 +1,10 @@
+// aux-build:upstream_alias.rs
+// check-pass
+
+extern crate upstream_alias;
+
+fn foo<'a, T: for<'b> upstream_alias::Trait<'b>>(_: upstream_alias::Alias<'a, T>) -> &'a () {
+    todo!()
+}
+
+fn main() {}
diff --git a/src/test/ui/late-bound-lifetimes/downgraded_to_early_through_alias.rs b/src/test/ui/late-bound-lifetimes/downgraded_to_early_through_alias.rs
new file mode 100644
index 00000000000..e56a34218e2
--- /dev/null
+++ b/src/test/ui/late-bound-lifetimes/downgraded_to_early_through_alias.rs
@@ -0,0 +1,24 @@
+// check-pass
+
+trait Gats<'a> {
+    type Assoc;
+    type Assoc2;
+}
+
+trait Trait: for<'a> Gats<'a> {
+    fn foo<'a>(_: &mut <Self as Gats<'a>>::Assoc) -> <Self as Gats<'a>>::Assoc2;
+}
+
+impl<'a> Gats<'a> for () {
+    type Assoc = &'a u32;
+    type Assoc2 = ();
+}
+
+type GatsAssoc<'a, T> = <T as Gats<'a>>::Assoc;
+type GatsAssoc2<'a, T> = <T as Gats<'a>>::Assoc2;
+
+impl Trait for () {
+    fn foo<'a>(_: &mut GatsAssoc<'a, Self>) -> GatsAssoc2<'a, Self> {}
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-47511.rs b/src/test/ui/late-bound-lifetimes/issue-47511.rs
index eb4860e75d7..78944351540 100644
--- a/src/test/ui/issues/issue-47511.rs
+++ b/src/test/ui/late-bound-lifetimes/issue-47511.rs
@@ -1,9 +1,4 @@
-// check-fail
-// known-bug: #47511
-
-// Regression test for #47511: anonymous lifetimes can appear
-// unconstrained in a return type, but only if they appear just once
-// in the input, as the input to a projection.
+// check-pass
 
 fn f(_: X) -> X {
     unimplemented!()
diff --git a/src/test/ui/late-bound-lifetimes/late_bound_through_alias.rs b/src/test/ui/late-bound-lifetimes/late_bound_through_alias.rs
new file mode 100644
index 00000000000..91839673c1f
--- /dev/null
+++ b/src/test/ui/late-bound-lifetimes/late_bound_through_alias.rs
@@ -0,0 +1,16 @@
+// check-pass
+
+fn f(_: X) -> X {
+    unimplemented!()
+}
+
+fn g<'a>(_: X<'a>) -> X<'a> {
+    unimplemented!()
+}
+
+type X<'a> = &'a ();
+
+fn main() {
+    let _: for<'a> fn(X<'a>) -> X<'a> = g;
+    let _: for<'a> fn(X<'a>) -> X<'a> = f;
+}
diff --git a/src/test/ui/late-bound-lifetimes/mismatched_arg_count.rs b/src/test/ui/late-bound-lifetimes/mismatched_arg_count.rs
new file mode 100644
index 00000000000..0b331e2039f
--- /dev/null
+++ b/src/test/ui/late-bound-lifetimes/mismatched_arg_count.rs
@@ -0,0 +1,12 @@
+// ensures that we don't ICE when there are too many args supplied to the alias.
+
+trait Trait<'a> {
+    type Assoc;
+}
+
+type Alias<'a, T> = <T as Trait<'a>>::Assoc;
+
+fn bar<'a, T: Trait<'a>>(_: Alias<'a, 'a, T>) {}
+//~^ error: this type alias takes 1 lifetime argument but 2 lifetime arguments were supplied
+
+fn main() {}
diff --git a/src/test/ui/late-bound-lifetimes/mismatched_arg_count.stderr b/src/test/ui/late-bound-lifetimes/mismatched_arg_count.stderr
new file mode 100644
index 00000000000..3704d9bb957
--- /dev/null
+++ b/src/test/ui/late-bound-lifetimes/mismatched_arg_count.stderr
@@ -0,0 +1,17 @@
+error[E0107]: this type alias takes 1 lifetime argument but 2 lifetime arguments were supplied
+  --> $DIR/mismatched_arg_count.rs:9:29
+   |
+LL | fn bar<'a, T: Trait<'a>>(_: Alias<'a, 'a, T>) {}
+   |                             ^^^^^     -- help: remove this lifetime argument
+   |                             |
+   |                             expected 1 lifetime argument
+   |
+note: type alias defined here, with 1 lifetime parameter: `'a`
+  --> $DIR/mismatched_arg_count.rs:7:6
+   |
+LL | type Alias<'a, T> = <T as Trait<'a>>::Assoc;
+   |      ^^^^^ --
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0107`.
diff --git a/src/test/ui/lifetimes/borrowck-let-suggestion.stderr b/src/test/ui/lifetimes/borrowck-let-suggestion.stderr
index bbf04c98436..987b051b111 100644
--- a/src/test/ui/lifetimes/borrowck-let-suggestion.stderr
+++ b/src/test/ui/lifetimes/borrowck-let-suggestion.stderr
@@ -4,7 +4,7 @@ error[E0716]: temporary value dropped while borrowed
 LL |     let mut x = vec![1].iter();
    |                 ^^^^^^^       - temporary value is freed at the end of this statement
    |                 |
-   |                 creates a temporary which is freed while still in use
+   |                 creates a temporary value which is freed while still in use
 LL |
 LL |     x.use_mut();
    |     ----------- borrow later used here
diff --git a/src/test/ui/issues/issue-12552.rs b/src/test/ui/match/issue-12552.rs
index b7f71dd1ce3..b7f71dd1ce3 100644
--- a/src/test/ui/issues/issue-12552.rs
+++ b/src/test/ui/match/issue-12552.rs
diff --git a/src/test/ui/issues/issue-12552.stderr b/src/test/ui/match/issue-12552.stderr
index 4b027eba2c2..4b027eba2c2 100644
--- a/src/test/ui/issues/issue-12552.stderr
+++ b/src/test/ui/match/issue-12552.stderr
diff --git a/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.rs b/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.rs
index 8dbe3472ea8..307104e47a1 100644
--- a/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.rs
+++ b/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.rs
@@ -1,8 +1,8 @@
-#![feature(unboxed_closures)]
+#![feature(unboxed_closures,tuple_trait)]
 
 use std::ops::FnMut;
 
-fn to_fn_mut<A, F: FnMut<A>>(f: F) -> F { f }
+fn to_fn_mut<A:std::marker::Tuple, F:FnMut<A>>(f: F) -> F { f }
 
 fn call_it<F: FnMut(isize, isize) -> isize>(y: isize, mut f: F) -> isize {
     //~^ NOTE required by this bound in `call_it`
diff --git a/src/test/ui/moves/moves-based-on-type-move-out-of-closure-env-issue-1965.rs b/src/test/ui/moves/moves-based-on-type-move-out-of-closure-env-issue-1965.rs
index 76b7aab542d..490d91ac118 100644
--- a/src/test/ui/moves/moves-based-on-type-move-out-of-closure-env-issue-1965.rs
+++ b/src/test/ui/moves/moves-based-on-type-move-out-of-closure-env-issue-1965.rs
@@ -1,6 +1,6 @@
-#![feature(unboxed_closures)]
+#![feature(unboxed_closures, tuple_trait)]
 
-fn to_fn<A,F:Fn<A>>(f: F) -> F { f }
+fn to_fn<A:std::marker::Tuple,F:Fn<A>>(f: F) -> F { f }
 
 fn test(_x: Box<usize>) {}
 
diff --git a/src/test/ui/nll/borrowed-temporary-error.stderr b/src/test/ui/nll/borrowed-temporary-error.stderr
index 2c6bd92641f..89781d96fab 100644
--- a/src/test/ui/nll/borrowed-temporary-error.stderr
+++ b/src/test/ui/nll/borrowed-temporary-error.stderr
@@ -2,7 +2,7 @@ error[E0716]: temporary value dropped while borrowed
   --> $DIR/borrowed-temporary-error.rs:8:10
    |
 LL |         &(v,)
-   |          ^^^^ creates a temporary which is freed while still in use
+   |          ^^^^ creates a temporary value which is freed while still in use
 LL |
 LL |     });
    |       - temporary value is freed at the end of this statement
diff --git a/src/test/ui/nll/closure-requirements/propagate-from-trait-match.rs b/src/test/ui/nll/closure-requirements/propagate-from-trait-match.rs
index 3bdb5433948..cda781d8e26 100644
--- a/src/test/ui/nll/closure-requirements/propagate-from-trait-match.rs
+++ b/src/test/ui/nll/closure-requirements/propagate-from-trait-match.rs
@@ -30,8 +30,6 @@ where
     T: Trait<'a>,
 {
     establish_relationships(value, |value| {
-        //~^ ERROR the parameter type `T` may not live long enough
-
         // This function call requires that
         //
         // (a) T: Trait<'a>
@@ -43,6 +41,7 @@ where
         // The latter does not hold.
 
         require(value);
+        //~^ ERROR the parameter type `T` may not live long enough
     });
 }
 
diff --git a/src/test/ui/nll/closure-requirements/propagate-from-trait-match.stderr b/src/test/ui/nll/closure-requirements/propagate-from-trait-match.stderr
index 750b08bbe85..038a5e11f88 100644
--- a/src/test/ui/nll/closure-requirements/propagate-from-trait-match.stderr
+++ b/src/test/ui/nll/closure-requirements/propagate-from-trait-match.stderr
@@ -23,17 +23,10 @@ LL | |     T: Trait<'a>,
    = note: defining type: supply::<'_#1r, T>
 
 error[E0309]: the parameter type `T` may not live long enough
-  --> $DIR/propagate-from-trait-match.rs:32:36
+  --> $DIR/propagate-from-trait-match.rs:43:9
    |
-LL |       establish_relationships(value, |value| {
-   |  ____________________________________^
-LL | |
-LL | |
-LL | |         // This function call requires that
-...  |
-LL | |         require(value);
-LL | |     });
-   | |_____^ ...so that the type `T` will meet its required lifetime bounds
+LL |         require(value);
+   |         ^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
    |
 help: consider adding an explicit lifetime bound...
    |
diff --git a/src/test/ui/issues/issue-54943.rs b/src/test/ui/nll/issue-54943.rs
index 85722300bf0..85722300bf0 100644
--- a/src/test/ui/issues/issue-54943.rs
+++ b/src/test/ui/nll/issue-54943.rs
diff --git a/src/test/ui/issues/issue-54943.stderr b/src/test/ui/nll/issue-54943.stderr
index 59be0f983b9..59be0f983b9 100644
--- a/src/test/ui/issues/issue-54943.stderr
+++ b/src/test/ui/nll/issue-54943.stderr
diff --git a/src/test/ui/nll/issue-57265-return-type-wf-check.stderr b/src/test/ui/nll/issue-57265-return-type-wf-check.stderr
index 20add62b91d..bb45575fa64 100644
--- a/src/test/ui/nll/issue-57265-return-type-wf-check.stderr
+++ b/src/test/ui/nll/issue-57265-return-type-wf-check.stderr
@@ -4,7 +4,7 @@ error[E0716]: temporary value dropped while borrowed
 LL |     let (_, z) = foo(&"hello".to_string());
    |                  -----^^^^^^^^^^^^^^^^^^^-- temporary value is freed at the end of this statement
    |                  |    |
-   |                  |    creates a temporary which is freed while still in use
+   |                  |    creates a temporary value which is freed while still in use
    |                  argument requires that borrow lasts for `'static`
 
 error: aborting due to previous error
diff --git a/src/test/ui/nll/issue-98589-closures-relate-named-regions.stderr b/src/test/ui/nll/issue-98589-closures-relate-named-regions.stderr
index 6def5602e70..d8b26f0b017 100644
--- a/src/test/ui/nll/issue-98589-closures-relate-named-regions.stderr
+++ b/src/test/ui/nll/issue-98589-closures-relate-named-regions.stderr
@@ -35,10 +35,10 @@ LL |     || { None::<&'a &'b ()>; };
    = help: consider adding the following bound: `'b: 'a`
 
 error[E0309]: the parameter type `T` may not live long enough
-  --> $DIR/issue-98589-closures-relate-named-regions.rs:26:5
+  --> $DIR/issue-98589-closures-relate-named-regions.rs:26:10
    |
 LL |     || { None::<&'a T>; };
-   |     ^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
+   |          ^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
    |
 help: consider adding an explicit lifetime bound...
    |
@@ -46,10 +46,10 @@ LL | fn test_early_type<'a: 'a, T: 'a>() {
    |                             ++++
 
 error[E0309]: the parameter type `T` may not live long enough
-  --> $DIR/issue-98589-closures-relate-named-regions.rs:32:5
+  --> $DIR/issue-98589-closures-relate-named-regions.rs:32:10
    |
 LL |     || { None::<&'a T>; };
-   |     ^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
+   |          ^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
    |
 help: consider adding an explicit lifetime bound...
    |
diff --git a/src/test/ui/nll/issue-98693.rs b/src/test/ui/nll/issue-98693.rs
index 18e6ec63046..7a325e2e998 100644
--- a/src/test/ui/nll/issue-98693.rs
+++ b/src/test/ui/nll/issue-98693.rs
@@ -13,8 +13,8 @@ where
 
 fn test<T>() {
     || {
-        //~^ ERROR the parameter type `T` may not live long enough
         assert_static::<T>();
+        //~^ ERROR the parameter type `T` may not live long enough
     };
 }
 
diff --git a/src/test/ui/nll/issue-98693.stderr b/src/test/ui/nll/issue-98693.stderr
index 31689620c64..15ca38aa25d 100644
--- a/src/test/ui/nll/issue-98693.stderr
+++ b/src/test/ui/nll/issue-98693.stderr
@@ -1,11 +1,8 @@
 error[E0310]: the parameter type `T` may not live long enough
-  --> $DIR/issue-98693.rs:15:5
+  --> $DIR/issue-98693.rs:16:9
    |
-LL | /     || {
-LL | |
-LL | |         assert_static::<T>();
-LL | |     };
-   | |_____^ ...so that the type `T` will meet its required lifetime bounds
+LL |         assert_static::<T>();
+   |         ^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
    |
 help: consider adding an explicit lifetime bound...
    |
diff --git a/src/test/ui/nll/ty-outlives/projection-implied-bounds.stderr b/src/test/ui/nll/ty-outlives/projection-implied-bounds.stderr
index 3b9b2956c51..d949e29b2b8 100644
--- a/src/test/ui/nll/ty-outlives/projection-implied-bounds.stderr
+++ b/src/test/ui/nll/ty-outlives/projection-implied-bounds.stderr
@@ -1,8 +1,8 @@
 error[E0310]: the parameter type `T` may not live long enough
-  --> $DIR/projection-implied-bounds.rs:30:18
+  --> $DIR/projection-implied-bounds.rs:30:36
    |
 LL |     twice(value, |value_ref, item| invoke2(value_ref, item));
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
+   |                                    ^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
    |
 help: consider adding an explicit lifetime bound...
    |
diff --git a/src/test/ui/nll/ty-outlives/projection-no-regions-closure.stderr b/src/test/ui/nll/ty-outlives/projection-no-regions-closure.stderr
index ee1f7b64bb2..4933b934868 100644
--- a/src/test/ui/nll/ty-outlives/projection-no-regions-closure.stderr
+++ b/src/test/ui/nll/ty-outlives/projection-no-regions-closure.stderr
@@ -23,10 +23,10 @@ LL | |     T: Iterator,
    = note: defining type: no_region::<'_#1r, T>
 
 error[E0309]: the associated type `<T as Iterator>::Item` may not live long enough
-  --> $DIR/projection-no-regions-closure.rs:25:23
+  --> $DIR/projection-no-regions-closure.rs:25:31
    |
 LL |     with_signature(x, |mut y| Box::new(y.next()))
-   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                               ^^^^^^^^^^^^^^^^^^
    |
    = help: consider adding an explicit lifetime bound `<T as Iterator>::Item: 'a`...
    = note: ...so that the type `<T as Iterator>::Item` will meet its required lifetime bounds
@@ -80,10 +80,10 @@ LL | |     T: 'b + Iterator,
    = note: defining type: wrong_region::<'_#1r, '_#2r, T>
 
 error[E0309]: the associated type `<T as Iterator>::Item` may not live long enough
-  --> $DIR/projection-no-regions-closure.rs:42:23
+  --> $DIR/projection-no-regions-closure.rs:42:31
    |
 LL |     with_signature(x, |mut y| Box::new(y.next()))
-   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                               ^^^^^^^^^^^^^^^^^^
    |
    = help: consider adding an explicit lifetime bound `<T as Iterator>::Item: 'a`...
    = note: ...so that the type `<T as Iterator>::Item` will meet its required lifetime bounds
diff --git a/src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr b/src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr
index 4e57dfad794..dbda04c42c5 100644
--- a/src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr
+++ b/src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr
@@ -25,10 +25,10 @@ LL | |     T: Anything<'b>,
    = note: defining type: no_relationships_late::<'_#1r, T>
 
 error[E0309]: the parameter type `T` may not live long enough
-  --> $DIR/projection-one-region-closure.rs:45:29
+  --> $DIR/projection-one-region-closure.rs:45:39
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
-   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
+   |                                       ^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
    |
 help: consider adding an explicit lifetime bound...
    |
@@ -75,10 +75,10 @@ LL | |     'a: 'a,
    = note: defining type: no_relationships_early::<'_#1r, '_#2r, T>
 
 error[E0309]: the parameter type `T` may not live long enough
-  --> $DIR/projection-one-region-closure.rs:56:29
+  --> $DIR/projection-one-region-closure.rs:56:39
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
-   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
+   |                                       ^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
    |
 help: consider adding an explicit lifetime bound...
    |
diff --git a/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr b/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr
index 0195a693e5f..90f04914286 100644
--- a/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr
+++ b/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr
@@ -24,10 +24,10 @@ LL | |     T: Anything<'b, 'c>,
    = note: defining type: no_relationships_late::<'_#1r, '_#2r, T>
 
 error[E0309]: the associated type `<T as Anything<ReEarlyBound(0, 'b), ReEarlyBound(1, 'c)>>::AssocType` may not live long enough
-  --> $DIR/projection-two-region-trait-bound-closure.rs:38:29
+  --> $DIR/projection-two-region-trait-bound-closure.rs:38:39
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
-   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                                       ^^^^^^^^^^^^^^^^
    |
    = help: consider adding an explicit lifetime bound `<T as Anything<ReEarlyBound(0, 'b), ReEarlyBound(1, 'c)>>::AssocType: 'a`...
    = note: ...so that the type `<T as Anything<ReEarlyBound(0, 'b), ReEarlyBound(1, 'c)>>::AssocType` will meet its required lifetime bounds
@@ -58,10 +58,10 @@ LL | |     'a: 'a,
    = note: defining type: no_relationships_early::<'_#1r, '_#2r, '_#3r, T>
 
 error[E0309]: the associated type `<T as Anything<ReEarlyBound(1, 'b), ReEarlyBound(2, 'c)>>::AssocType` may not live long enough
-  --> $DIR/projection-two-region-trait-bound-closure.rs:48:29
+  --> $DIR/projection-two-region-trait-bound-closure.rs:48:39
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
-   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                                       ^^^^^^^^^^^^^^^^
    |
    = help: consider adding an explicit lifetime bound `<T as Anything<ReEarlyBound(1, 'b), ReEarlyBound(2, 'c)>>::AssocType: 'a`...
    = note: ...so that the type `<T as Anything<ReEarlyBound(1, 'b), ReEarlyBound(2, 'c)>>::AssocType` will meet its required lifetime bounds
@@ -167,7 +167,7 @@ LL | |     T: Anything<'b, 'b>,
    = note: defining type: two_regions::<'_#1r, T>
 
 error: lifetime may not live long enough
-  --> $DIR/projection-two-region-trait-bound-closure.rs:87:29
+  --> $DIR/projection-two-region-trait-bound-closure.rs:87:5
    |
 LL | fn two_regions<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
    |                --  -- lifetime `'b` defined here
@@ -175,9 +175,12 @@ LL | fn two_regions<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
    |                lifetime `'a` defined here
 ...
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
-   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^ closure body requires that `'b` must outlive `'a`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a`
    |
    = help: consider adding the following bound: `'b: 'a`
+   = note: requirement occurs because of the type `Cell<&'_#8r ()>`, which makes the generic argument `&'_#8r ()` invariant
+   = note: the struct `Cell<T>` is invariant over the parameter `T`
+   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
 
 note: external requirements
   --> $DIR/projection-two-region-trait-bound-closure.rs:97:29
diff --git a/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr b/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr
index 61c7d2550ca..f316a551cff 100644
--- a/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr
+++ b/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr
@@ -44,10 +44,10 @@ LL | fn generic_fail<'a, T>(cell: Cell<&'a ()>, value: T) {
    = note: defining type: generic_fail::<T>
 
 error[E0309]: the parameter type `T` may not live long enough
-  --> $DIR/ty-param-closure-approximate-lower-bound.rs:29:24
+  --> $DIR/ty-param-closure-approximate-lower-bound.rs:29:31
    |
 LL |     twice(cell, value, |a, b| invoke(a, b));
-   |                        ^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
+   |                               ^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
    |
 help: consider adding an explicit lifetime bound...
    |
diff --git a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.stderr b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.stderr
index 50d9e3aabe2..35979c8bf51 100644
--- a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.stderr
+++ b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.stderr
@@ -23,10 +23,10 @@ LL | |     T: Debug,
    = note: defining type: no_region::<'_#1r, T>
 
 error[E0309]: the parameter type `T` may not live long enough
-  --> $DIR/ty-param-closure-outlives-from-return-type.rs:26:23
+  --> $DIR/ty-param-closure-outlives-from-return-type.rs:26:27
    |
 LL |     with_signature(x, |y| y)
-   |                       ^^^^^ ...so that the type `T` will meet its required lifetime bounds
+   |                           ^ ...so that the type `T` will meet its required lifetime bounds
    |
 help: consider adding an explicit lifetime bound...
    |
diff --git a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.rs b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.rs
index d7702def32c..b8028761050 100644
--- a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.rs
+++ b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.rs
@@ -25,13 +25,12 @@ where
 #[rustc_regions]
 fn no_region<'a, T>(a: Cell<&'a ()>, b: T) {
     with_signature(a, b, |x, y| {
-        //~^ ERROR the parameter type `T` may not live long enough
-        //
         // See `correct_region`, which explains the point of this
         // test.  The only difference is that, in the case of this
         // function, there is no where clause *anywhere*, and hence we
         // get an error (but reported by the closure creator).
         require(&x, &y)
+        //~^ ERROR the parameter type `T` may not live long enough
     })
 }
 
@@ -62,9 +61,9 @@ where
     T: 'b,
 {
     with_signature(a, b, |x, y| {
-        //~^ ERROR the parameter type `T` may not live long enough
         // See `correct_region`
         require(&x, &y)
+        //~^ ERROR the parameter type `T` may not live long enough
     })
 }
 
diff --git a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.stderr b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.stderr
index 14c55e32a3e..4c97db58c6c 100644
--- a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.stderr
+++ b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.stderr
@@ -22,17 +22,10 @@ LL | fn no_region<'a, T>(a: Cell<&'a ()>, b: T) {
    = note: defining type: no_region::<T>
 
 error[E0309]: the parameter type `T` may not live long enough
-  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:27:26
+  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:32:9
    |
-LL |       with_signature(a, b, |x, y| {
-   |  __________________________^
-LL | |
-LL | |         //
-LL | |         // See `correct_region`, which explains the point of this
-...  |
-LL | |         require(&x, &y)
-LL | |     })
-   | |_____^ ...so that the type `T` will meet its required lifetime bounds
+LL |         require(&x, &y)
+   |         ^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
    |
 help: consider adding an explicit lifetime bound...
    |
@@ -40,7 +33,7 @@ LL | fn no_region<'a, T: 'a>(a: Cell<&'a ()>, b: T) {
    |                   ++++
 
 note: external requirements
-  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:43:26
+  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:42:26
    |
 LL |     with_signature(a, b, |x, y| {
    |                          ^^^^^^
@@ -54,7 +47,7 @@ LL |     with_signature(a, b, |x, y| {
    = note: where T: '_#2r
 
 note: no external requirements
-  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:39:1
+  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:38:1
    |
 LL | / fn correct_region<'a, T>(a: Cell<&'a ()>, b: T)
 LL | | where
@@ -64,7 +57,7 @@ LL | |     T: 'a,
    = note: defining type: correct_region::<'_#1r, T>
 
 note: external requirements
-  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:64:26
+  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:63:26
    |
 LL |     with_signature(a, b, |x, y| {
    |                          ^^^^^^
@@ -79,7 +72,7 @@ LL |     with_signature(a, b, |x, y| {
    = note: where T: '_#2r
 
 note: no external requirements
-  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:60:1
+  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:59:1
    |
 LL | / fn wrong_region<'a, 'b, T>(a: Cell<&'a ()>, b: T)
 LL | | where
@@ -89,15 +82,10 @@ LL | |     T: 'b,
    = note: defining type: wrong_region::<'_#1r, T>
 
 error[E0309]: the parameter type `T` may not live long enough
-  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:64:26
+  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:65:9
    |
-LL |       with_signature(a, b, |x, y| {
-   |  __________________________^
-LL | |
-LL | |         // See `correct_region`
-LL | |         require(&x, &y)
-LL | |     })
-   | |_____^ ...so that the type `T` will meet its required lifetime bounds
+LL |         require(&x, &y)
+   |         ^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
    |
 help: consider adding an explicit lifetime bound...
    |
@@ -105,7 +93,7 @@ LL |     T: 'b + 'a,
    |           ++++
 
 note: external requirements
-  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:77:26
+  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:76:26
    |
 LL |     with_signature(a, b, |x, y| {
    |                          ^^^^^^
@@ -119,7 +107,7 @@ LL |     with_signature(a, b, |x, y| {
    = note: where T: '_#3r
 
 note: no external requirements
-  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:72:1
+  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:71:1
    |
 LL | / fn outlives_region<'a, 'b, T>(a: Cell<&'a ()>, b: T)
 LL | | where
diff --git a/src/test/ui/nll/user-annotations/patterns.stderr b/src/test/ui/nll/user-annotations/patterns.stderr
index 60d6e6db363..de6f8f80fe2 100644
--- a/src/test/ui/nll/user-annotations/patterns.stderr
+++ b/src/test/ui/nll/user-annotations/patterns.stderr
@@ -76,7 +76,7 @@ error[E0716]: temporary value dropped while borrowed
 LL |     let _: Vec<&'static String> = vec![&String::new()];
    |            --------------------         ^^^^^^^^^^^^^ - temporary value is freed at the end of this statement
    |            |                            |
-   |            |                            creates a temporary which is freed while still in use
+   |            |                            creates a temporary value which is freed while still in use
    |            type annotation requires that borrow lasts for `'static`
 
 error[E0716]: temporary value dropped while borrowed
@@ -85,7 +85,7 @@ error[E0716]: temporary value dropped while borrowed
 LL |     let (_, a): (Vec<&'static String>, _) = (vec![&String::new()], 44);
    |                 -------------------------          ^^^^^^^^^^^^^      - temporary value is freed at the end of this statement
    |                 |                                  |
-   |                 |                                  creates a temporary which is freed while still in use
+   |                 |                                  creates a temporary value which is freed while still in use
    |                 type annotation requires that borrow lasts for `'static`
 
 error[E0716]: temporary value dropped while borrowed
@@ -94,7 +94,7 @@ error[E0716]: temporary value dropped while borrowed
 LL |     let (_a, b): (Vec<&'static String>, _) = (vec![&String::new()], 44);
    |                  -------------------------          ^^^^^^^^^^^^^      - temporary value is freed at the end of this statement
    |                  |                                  |
-   |                  |                                  creates a temporary which is freed while still in use
+   |                  |                                  creates a temporary value which is freed while still in use
    |                  type annotation requires that borrow lasts for `'static`
 
 error[E0597]: `x` does not live long enough
diff --git a/src/test/ui/overloaded/overloaded-calls-nontuple.rs b/src/test/ui/overloaded/overloaded-calls-nontuple.rs
index 07d44ff82b1..32a3b93e0a1 100644
--- a/src/test/ui/overloaded/overloaded-calls-nontuple.rs
+++ b/src/test/ui/overloaded/overloaded-calls-nontuple.rs
@@ -8,22 +8,23 @@ struct S {
 }
 
 impl FnMut<isize> for S {
+    //~^ ERROR type parameter to bare `FnMut` trait must be a tuple
     extern "rust-call" fn call_mut(&mut self, z: isize) -> isize {
+        //~^ ERROR functions with the "rust-call" ABI must take a single non-self tuple argument
         self.x + self.y + z
     }
-    //~^^^ ERROR functions with the "rust-call" ABI must take a single non-self argument
 }
 
 impl FnOnce<isize> for S {
+    //~^ ERROR type parameter to bare `FnOnce` trait must be a tuple
     type Output = isize;
-    extern "rust-call" fn call_once(mut self, z: isize) -> isize { self.call_mut(z) }
-    //~^ ERROR functions with the "rust-call" ABI must take a single non-self argument
+    extern "rust-call" fn call_once(mut self, z: isize) -> isize {
+        //~^ ERROR functions with the "rust-call" ABI must take a single non-self tuple argument
+        self.call_mut(z)
+    }
 }
 
 fn main() {
-    let mut s = S {
-        x: 1,
-        y: 2,
-    };
-    drop(s(3))  //~ ERROR cannot use call notation
+    let mut s = S { x: 1, y: 2 };
+    drop(s(3))
 }
diff --git a/src/test/ui/overloaded/overloaded-calls-nontuple.stderr b/src/test/ui/overloaded/overloaded-calls-nontuple.stderr
index 8f299bc9434..794535aeb11 100644
--- a/src/test/ui/overloaded/overloaded-calls-nontuple.stderr
+++ b/src/test/ui/overloaded/overloaded-calls-nontuple.stderr
@@ -1,21 +1,40 @@
-error: functions with the "rust-call" ABI must take a single non-self argument that is a tuple
-  --> $DIR/overloaded-calls-nontuple.rs:11:5
+error[E0059]: type parameter to bare `FnMut` trait must be a tuple
+  --> $DIR/overloaded-calls-nontuple.rs:10:6
    |
-LL |     extern "rust-call" fn call_mut(&mut self, z: isize) -> isize {
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | impl FnMut<isize> for S {
+   |      ^^^^^^^^^^^^ the trait `Tuple` is not implemented for `isize`
+   |
+note: required by a bound in `FnMut`
+  --> $SRC_DIR/core/src/ops/function.rs:LL:COL
+   |
+LL | pub trait FnMut<Args: Tuple>: FnOnce<Args> {
+   |                       ^^^^^ required by this bound in `FnMut`
+
+error[E0059]: type parameter to bare `FnOnce` trait must be a tuple
+  --> $DIR/overloaded-calls-nontuple.rs:18:6
+   |
+LL | impl FnOnce<isize> for S {
+   |      ^^^^^^^^^^^^^ the trait `Tuple` is not implemented for `isize`
+   |
+note: required by a bound in `FnOnce`
+  --> $SRC_DIR/core/src/ops/function.rs:LL:COL
+   |
+LL | pub trait FnOnce<Args: Tuple> {
+   |                        ^^^^^ required by this bound in `FnOnce`
 
-error: functions with the "rust-call" ABI must take a single non-self argument that is a tuple
-  --> $DIR/overloaded-calls-nontuple.rs:19:5
+error[E0277]: functions with the "rust-call" ABI must take a single non-self tuple argument
+  --> $DIR/overloaded-calls-nontuple.rs:12:5
    |
-LL |     extern "rust-call" fn call_once(mut self, z: isize) -> isize { self.call_mut(z) }
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     extern "rust-call" fn call_mut(&mut self, z: isize) -> isize {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Tuple` is not implemented for `isize`
 
-error[E0059]: cannot use call notation; the first type parameter for the function trait is neither a tuple nor unit
-  --> $DIR/overloaded-calls-nontuple.rs:28:10
+error[E0277]: functions with the "rust-call" ABI must take a single non-self tuple argument
+  --> $DIR/overloaded-calls-nontuple.rs:21:5
    |
-LL |     drop(s(3))
-   |          ^^^^
+LL |     extern "rust-call" fn call_once(mut self, z: isize) -> isize {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Tuple` is not implemented for `isize`
 
-error: aborting due to 3 previous errors
+error: aborting due to 4 previous errors
 
-For more information about this error, try `rustc --explain E0059`.
+Some errors have detailed explanations: E0059, E0277.
+For more information about an error, try `rustc --explain E0059`.
diff --git a/src/test/ui/parser/byte-literals.rs b/src/test/ui/parser/byte-literals.rs
index 05a510b24a7..896dc1a1a5f 100644
--- a/src/test/ui/parser/byte-literals.rs
+++ b/src/test/ui/parser/byte-literals.rs
@@ -7,6 +7,6 @@ pub fn main() {
     b'\x0Z';  //~ ERROR invalid character in numeric character escape: `Z`
     b'	';  //~ ERROR byte constant must be escaped
     b''';  //~ ERROR byte constant must be escaped
-    b'é';  //~ ERROR non-ASCII character in byte constant
+    b'é';  //~ ERROR non-ASCII character in byte literal
     b'a  //~ ERROR unterminated byte constant [E0763]
 }
diff --git a/src/test/ui/parser/byte-literals.stderr b/src/test/ui/parser/byte-literals.stderr
index c3d00061630..efa55ae05bd 100644
--- a/src/test/ui/parser/byte-literals.stderr
+++ b/src/test/ui/parser/byte-literals.stderr
@@ -32,11 +32,11 @@ error: byte constant must be escaped: `'`
 LL |     b''';
    |       ^ help: escape the character: `\'`
 
-error: non-ASCII character in byte constant
+error: non-ASCII character in byte literal
   --> $DIR/byte-literals.rs:10:7
    |
 LL |     b'é';
-   |       ^ byte constant must be ASCII
+   |       ^ must be ASCII
    |
 help: if you meant to use the unicode code point for 'é', use a \xHH escape
    |
diff --git a/src/test/ui/parser/byte-string-literals.rs b/src/test/ui/parser/byte-string-literals.rs
index b1f11024a7b..30a4f50c4e4 100644
--- a/src/test/ui/parser/byte-string-literals.rs
+++ b/src/test/ui/parser/byte-string-literals.rs
@@ -3,7 +3,7 @@ static FOO: &'static [u8] = b"\f";  //~ ERROR unknown byte escape
 pub fn main() {
     b"\f";  //~ ERROR unknown byte escape
     b"\x0Z";  //~ ERROR invalid character in numeric character escape: `Z`
-    b"é";  //~ ERROR non-ASCII character in byte constant
-    br##"é"##;  //~ ERROR raw byte string must be ASCII
+    b"é";  //~ ERROR non-ASCII character in byte string literal
+    br##"é"##;  //~ ERROR non-ASCII character in raw byte string literal
     b"a  //~ ERROR unterminated double quote byte string
 }
diff --git a/src/test/ui/parser/byte-string-literals.stderr b/src/test/ui/parser/byte-string-literals.stderr
index 3b8b3692e05..5b96cc3d18a 100644
--- a/src/test/ui/parser/byte-string-literals.stderr
+++ b/src/test/ui/parser/byte-string-literals.stderr
@@ -20,18 +20,18 @@ error: invalid character in numeric character escape: `Z`
 LL |     b"\x0Z";
    |          ^ invalid character in numeric character escape
 
-error: non-ASCII character in byte constant
+error: non-ASCII character in byte string literal
   --> $DIR/byte-string-literals.rs:6:7
    |
 LL |     b"é";
-   |       ^ byte constant must be ASCII
+   |       ^ must be ASCII
    |
 help: if you meant to use the unicode code point for 'é', use a \xHH escape
    |
 LL |     b"\xE9";
    |       ~~~~
 
-error: raw byte string must be ASCII
+error: non-ASCII character in raw byte string literal
   --> $DIR/byte-string-literals.rs:7:10
    |
 LL |     br##"é"##;
diff --git a/src/test/ui/parser/issue-102806.rs b/src/test/ui/parser/issue-102806.rs
new file mode 100644
index 00000000000..ba297bdc967
--- /dev/null
+++ b/src/test/ui/parser/issue-102806.rs
@@ -0,0 +1,25 @@
+#![allow(dead_code)]
+
+#[derive(Default)]
+struct V3 {
+    x: f32,
+    y: f32,
+    z: f32,
+}
+
+fn pz(v: V3) {
+    let _ = V3 { z: 0.0, ...v};
+    //~^ ERROR expected `..`
+
+    let _ = V3 { z: 0.0, ...Default::default() };
+    //~^ ERROR expected `..`
+
+    let _ = V3 { z: 0.0, ... };
+    //~^ expected identifier
+    //~| ERROR missing fields `x` and `y` in initializer of `V3`
+
+    let V3 { z: val, ... } = v;
+    //~^ ERROR expected field pattern
+}
+
+fn main() {}
diff --git a/src/test/ui/parser/issue-102806.stderr b/src/test/ui/parser/issue-102806.stderr
new file mode 100644
index 00000000000..6872b8bc0af
--- /dev/null
+++ b/src/test/ui/parser/issue-102806.stderr
@@ -0,0 +1,45 @@
+error: expected `..`, found `...`
+  --> $DIR/issue-102806.rs:11:26
+   |
+LL |     let _ = V3 { z: 0.0, ...v};
+   |                          ^^^
+   |
+help: use `..` to fill in the rest of the fields
+   |
+LL |     let _ = V3 { z: 0.0, ..v};
+   |                          ~~
+
+error: expected `..`, found `...`
+  --> $DIR/issue-102806.rs:14:26
+   |
+LL |     let _ = V3 { z: 0.0, ...Default::default() };
+   |                          ^^^
+   |
+help: use `..` to fill in the rest of the fields
+   |
+LL |     let _ = V3 { z: 0.0, ..Default::default() };
+   |                          ~~
+
+error: expected identifier, found `...`
+  --> $DIR/issue-102806.rs:17:26
+   |
+LL |     let _ = V3 { z: 0.0, ... };
+   |             --           ^^^ expected identifier
+   |             |
+   |             while parsing this struct
+
+error: expected field pattern, found `...`
+  --> $DIR/issue-102806.rs:21:22
+   |
+LL |     let V3 { z: val, ... } = v;
+   |                      ^^^ help: to omit remaining fields, use one fewer `.`: `..`
+
+error[E0063]: missing fields `x` and `y` in initializer of `V3`
+  --> $DIR/issue-102806.rs:17:13
+   |
+LL |     let _ = V3 { z: 0.0, ... };
+   |             ^^ missing `x` and `y`
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0063`.
diff --git a/src/test/ui/parser/issue-103451.rs b/src/test/ui/parser/issue-103451.rs
new file mode 100644
index 00000000000..1fdb0014881
--- /dev/null
+++ b/src/test/ui/parser/issue-103451.rs
@@ -0,0 +1,5 @@
+// error-pattern: this file contains an unclosed delimiter
+// error-pattern: expected value, found struct `R`
+struct R { }
+struct S {
+    x: [u8; R
diff --git a/src/test/ui/parser/issue-103451.stderr b/src/test/ui/parser/issue-103451.stderr
new file mode 100644
index 00000000000..eb3c92fb43d
--- /dev/null
+++ b/src/test/ui/parser/issue-103451.stderr
@@ -0,0 +1,32 @@
+error: this file contains an unclosed delimiter
+  --> $DIR/issue-103451.rs:5:15
+   |
+LL | struct S {
+   |          - unclosed delimiter
+LL |     x: [u8; R
+   |        -      ^
+   |        |
+   |        unclosed delimiter
+
+error: this file contains an unclosed delimiter
+  --> $DIR/issue-103451.rs:5:15
+   |
+LL | struct S {
+   |          - unclosed delimiter
+LL |     x: [u8; R
+   |        -      ^
+   |        |
+   |        unclosed delimiter
+
+error[E0423]: expected value, found struct `R`
+  --> $DIR/issue-103451.rs:5:13
+   |
+LL | struct R { }
+   | ------------ `R` defined here
+LL | struct S {
+LL |     x: [u8; R
+   |             ^ help: use struct literal syntax instead: `R {}`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0423`.
diff --git a/src/test/ui/parser/kw-in-trait-bounds.stderr b/src/test/ui/parser/kw-in-trait-bounds.stderr
index 28196c7ce2d..546ad84eeee 100644
--- a/src/test/ui/parser/kw-in-trait-bounds.stderr
+++ b/src/test/ui/parser/kw-in-trait-bounds.stderr
@@ -94,8 +94,8 @@ LL | fn _f<F: fn(), G>(_: impl fn(), _: &dyn fn())
    |
   ::: $SRC_DIR/core/src/ops/function.rs:LL:COL
    |
-LL | pub trait Fn<Args>: FnMut<Args> {
-   | ------------------------------- similarly named trait `Fn` defined here
+LL | pub trait Fn<Args: Tuple>: FnMut<Args> {
+   | -------------------------------------- similarly named trait `Fn` defined here
 
 error[E0405]: cannot find trait `r#fn` in this scope
   --> $DIR/kw-in-trait-bounds.rs:17:4
@@ -105,8 +105,8 @@ LL | G: fn(),
    |
   ::: $SRC_DIR/core/src/ops/function.rs:LL:COL
    |
-LL | pub trait Fn<Args>: FnMut<Args> {
-   | ------------------------------- similarly named trait `Fn` defined here
+LL | pub trait Fn<Args: Tuple>: FnMut<Args> {
+   | -------------------------------------- similarly named trait `Fn` defined here
 
 error[E0405]: cannot find trait `r#fn` in this scope
   --> $DIR/kw-in-trait-bounds.rs:3:27
@@ -116,8 +116,8 @@ LL | fn _f<F: fn(), G>(_: impl fn(), _: &dyn fn())
    |
   ::: $SRC_DIR/core/src/ops/function.rs:LL:COL
    |
-LL | pub trait Fn<Args>: FnMut<Args> {
-   | ------------------------------- similarly named trait `Fn` defined here
+LL | pub trait Fn<Args: Tuple>: FnMut<Args> {
+   | -------------------------------------- similarly named trait `Fn` defined here
 
 error[E0405]: cannot find trait `r#fn` in this scope
   --> $DIR/kw-in-trait-bounds.rs:3:41
@@ -127,8 +127,8 @@ LL | fn _f<F: fn(), G>(_: impl fn(), _: &dyn fn())
    |
   ::: $SRC_DIR/core/src/ops/function.rs:LL:COL
    |
-LL | pub trait Fn<Args>: FnMut<Args> {
-   | ------------------------------- similarly named trait `Fn` defined here
+LL | pub trait Fn<Args: Tuple>: FnMut<Args> {
+   | -------------------------------------- similarly named trait `Fn` defined here
 
 error[E0405]: cannot find trait `r#struct` in this scope
   --> $DIR/kw-in-trait-bounds.rs:24:10
diff --git a/src/test/ui/parser/label-after-block-like.rs b/src/test/ui/parser/label-after-block-like.rs
new file mode 100644
index 00000000000..55f3f8f9f5f
--- /dev/null
+++ b/src/test/ui/parser/label-after-block-like.rs
@@ -0,0 +1,43 @@
+fn a() {
+    if let () = () 'a {}
+    //~^ ERROR labeled expression must be followed by `:`
+    //~| ERROR expected `{`, found `'a`
+}
+
+fn b() {
+    if true 'a {}
+    //~^ ERROR labeled expression must be followed by `:`
+    //~| ERROR expected `{`, found `'a`
+}
+
+fn c() {
+    loop 'a {}
+    //~^ ERROR labeled expression must be followed by `:`
+    //~| ERROR expected `{`, found `'a`
+}
+
+fn d() {
+    while true 'a {}
+    //~^ ERROR labeled expression must be followed by `:`
+    //~| ERROR expected `{`, found `'a`
+}
+
+fn e() {
+    while let () = () 'a {}
+    //~^ ERROR labeled expression must be followed by `:`
+    //~| ERROR expected `{`, found `'a`
+}
+
+fn f() {
+    for _ in 0..0 'a {}
+    //~^ ERROR labeled expression must be followed by `:`
+    //~| ERROR expected `{`, found `'a`
+}
+
+fn g() {
+    unsafe 'a {}
+    //~^ ERROR labeled expression must be followed by `:`
+    //~| ERROR expected `{`, found `'a`
+}
+
+fn main() {}
diff --git a/src/test/ui/parser/label-after-block-like.stderr b/src/test/ui/parser/label-after-block-like.stderr
new file mode 100644
index 00000000000..8ff50b124b3
--- /dev/null
+++ b/src/test/ui/parser/label-after-block-like.stderr
@@ -0,0 +1,176 @@
+error: labeled expression must be followed by `:`
+  --> $DIR/label-after-block-like.rs:2:20
+   |
+LL |     if let () = () 'a {}
+   |                    ---^^
+   |                    | |
+   |                    | help: add `:` after the label
+   |                    the label
+   |
+   = note: labels are used before loops and blocks, allowing e.g., `break 'label` to them
+
+error: expected `{`, found `'a`
+  --> $DIR/label-after-block-like.rs:2:20
+   |
+LL |     if let () = () 'a {}
+   |                    ^^ expected `{`
+   |
+note: the `if` expression is missing a block after this condition
+  --> $DIR/label-after-block-like.rs:2:8
+   |
+LL |     if let () = () 'a {}
+   |        ^^^^^^^^^^^
+help: try placing this code inside a block
+   |
+LL |     if let () = () { 'a {} }
+   |                    +       +
+
+error: labeled expression must be followed by `:`
+  --> $DIR/label-after-block-like.rs:8:13
+   |
+LL |     if true 'a {}
+   |             ---^^
+   |             | |
+   |             | help: add `:` after the label
+   |             the label
+   |
+   = note: labels are used before loops and blocks, allowing e.g., `break 'label` to them
+
+error: expected `{`, found `'a`
+  --> $DIR/label-after-block-like.rs:8:13
+   |
+LL |     if true 'a {}
+   |             ^^ expected `{`
+   |
+note: the `if` expression is missing a block after this condition
+  --> $DIR/label-after-block-like.rs:8:8
+   |
+LL |     if true 'a {}
+   |        ^^^^
+help: try placing this code inside a block
+   |
+LL |     if true { 'a {} }
+   |             +       +
+
+error: labeled expression must be followed by `:`
+  --> $DIR/label-after-block-like.rs:14:10
+   |
+LL |     loop 'a {}
+   |          ---^^
+   |          | |
+   |          | help: add `:` after the label
+   |          the label
+   |
+   = note: labels are used before loops and blocks, allowing e.g., `break 'label` to them
+
+error: expected `{`, found `'a`
+  --> $DIR/label-after-block-like.rs:14:10
+   |
+LL |     loop 'a {}
+   |     ---- ^^ expected `{`
+   |     |
+   |     while parsing this `loop` expression
+   |
+help: try placing this code inside a block
+   |
+LL |     loop { 'a {} }
+   |          +       +
+
+error: labeled expression must be followed by `:`
+  --> $DIR/label-after-block-like.rs:20:16
+   |
+LL |     while true 'a {}
+   |                ---^^
+   |                | |
+   |                | help: add `:` after the label
+   |                the label
+   |
+   = note: labels are used before loops and blocks, allowing e.g., `break 'label` to them
+
+error: expected `{`, found `'a`
+  --> $DIR/label-after-block-like.rs:20:16
+   |
+LL |     while true 'a {}
+   |     ----- ---- ^^ expected `{`
+   |     |     |
+   |     |     this `while` condition successfully parsed
+   |     while parsing the body of this `while` expression
+   |
+help: try placing this code inside a block
+   |
+LL |     while true { 'a {} }
+   |                +       +
+
+error: labeled expression must be followed by `:`
+  --> $DIR/label-after-block-like.rs:26:23
+   |
+LL |     while let () = () 'a {}
+   |                       ---^^
+   |                       | |
+   |                       | help: add `:` after the label
+   |                       the label
+   |
+   = note: labels are used before loops and blocks, allowing e.g., `break 'label` to them
+
+error: expected `{`, found `'a`
+  --> $DIR/label-after-block-like.rs:26:23
+   |
+LL |     while let () = () 'a {}
+   |     ----- ----------- ^^ expected `{`
+   |     |     |
+   |     |     this `while` condition successfully parsed
+   |     while parsing the body of this `while` expression
+   |
+help: try placing this code inside a block
+   |
+LL |     while let () = () { 'a {} }
+   |                       +       +
+
+error: labeled expression must be followed by `:`
+  --> $DIR/label-after-block-like.rs:32:19
+   |
+LL |     for _ in 0..0 'a {}
+   |                   ---^^
+   |                   | |
+   |                   | help: add `:` after the label
+   |                   the label
+   |
+   = note: labels are used before loops and blocks, allowing e.g., `break 'label` to them
+
+error: expected `{`, found `'a`
+  --> $DIR/label-after-block-like.rs:32:19
+   |
+LL |     for _ in 0..0 'a {}
+   |                   ^^ expected `{`
+   |
+help: try placing this code inside a block
+   |
+LL |     for _ in 0..0 { 'a {} }
+   |                   +       +
+
+error: labeled expression must be followed by `:`
+  --> $DIR/label-after-block-like.rs:38:12
+   |
+LL |     unsafe 'a {}
+   |            ---^^
+   |            | |
+   |            | help: add `:` after the label
+   |            the label
+   |
+   = note: labels are used before loops and blocks, allowing e.g., `break 'label` to them
+
+error: expected `{`, found `'a`
+  --> $DIR/label-after-block-like.rs:38:12
+   |
+LL |     unsafe 'a {}
+   |     ------ ^^ expected `{`
+   |     |
+   |     while parsing this `unsafe` expression
+   |
+help: try placing this code inside a block
+   |
+LL |     unsafe { 'a {} }
+   |            +       +
+
+error: aborting due to 14 previous errors
+
diff --git a/src/test/ui/parser/raw/raw-byte-string-literals.rs b/src/test/ui/parser/raw/raw-byte-string-literals.rs
index 163c8ac66b0..1b859fee596 100644
--- a/src/test/ui/parser/raw/raw-byte-string-literals.rs
+++ b/src/test/ui/parser/raw/raw-byte-string-literals.rs
@@ -2,6 +2,6 @@
 
 pub fn main() {
     br"a
"; //~ ERROR bare CR not allowed in raw string
-    br"é";  //~ ERROR raw byte string must be ASCII
+    br"é";  //~ ERROR non-ASCII character in raw byte string literal
     br##~"a"~##;  //~ ERROR only `#` is allowed in raw string delimitation
 }
diff --git a/src/test/ui/parser/raw/raw-byte-string-literals.stderr b/src/test/ui/parser/raw/raw-byte-string-literals.stderr
index cfc877104bd..a2f27d1ed70 100644
--- a/src/test/ui/parser/raw/raw-byte-string-literals.stderr
+++ b/src/test/ui/parser/raw/raw-byte-string-literals.stderr
@@ -4,7 +4,7 @@ error: bare CR not allowed in raw string
 LL |     br"a
";
    |         ^
 
-error: raw byte string must be ASCII
+error: non-ASCII character in raw byte string literal
   --> $DIR/raw-byte-string-literals.rs:5:8
    |
 LL |     br"é";
diff --git a/src/test/ui/parser/underscore-suffix-for-string.rs b/src/test/ui/parser/underscore-suffix-for-string.rs
index 2e0ebe2cfa4..bd260752e04 100644
--- a/src/test/ui/parser/underscore-suffix-for-string.rs
+++ b/src/test/ui/parser/underscore-suffix-for-string.rs
@@ -1,8 +1,17 @@
-// check-pass
+macro_rules! sink {
+    ($tt:tt) => {()}
+}
 
 fn main() {
     let _ = "Foo"_;
-    //~^ WARNING underscore literal suffix is not allowed
-    //~| WARNING this was previously accepted
-    //~| NOTE issue #42326
+    //~^ ERROR underscore literal suffix is not allowed
+
+    // This is ok, because `__` is a valid identifier and the macro consumes it
+    // before proper parsing happens.
+    let _ = sink!("Foo"__);
+
+    // This is not ok, even as an input to a macro, because the `_` suffix is
+    // never allowed.
+    sink!("Foo"_);
+    //~^ ERROR underscore literal suffix is not allowed
 }
diff --git a/src/test/ui/parser/underscore-suffix-for-string.stderr b/src/test/ui/parser/underscore-suffix-for-string.stderr
index 00c7657f17b..2fe2c130eb2 100644
--- a/src/test/ui/parser/underscore-suffix-for-string.stderr
+++ b/src/test/ui/parser/underscore-suffix-for-string.stderr
@@ -1,11 +1,14 @@
-warning: underscore literal suffix is not allowed
-  --> $DIR/underscore-suffix-for-string.rs:4:18
+error: underscore literal suffix is not allowed
+  --> $DIR/underscore-suffix-for-string.rs:6:18
    |
 LL |     let _ = "Foo"_;
    |                  ^
+
+error: underscore literal suffix is not allowed
+  --> $DIR/underscore-suffix-for-string.rs:15:16
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: see issue #42326 <https://github.com/rust-lang/rust/issues/42326> for more information
+LL |     sink!("Foo"_);
+   |                ^
 
-warning: 1 warning emitted
+error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/parser/unicode-control-codepoints.rs b/src/test/ui/parser/unicode-control-codepoints.rs
index 5af0b585a12..df099bb62ad 100644
--- a/src/test/ui/parser/unicode-control-codepoints.rs
+++ b/src/test/ui/parser/unicode-control-codepoints.rs
@@ -14,15 +14,15 @@ fn main() {
     println!("{:?}", r##"/*‮ } ⁦if isAdmin⁩ ⁦ begin admins only "##);
     //~^ ERROR unicode codepoint changing visible direction of text present in literal
     println!("{:?}", b"/*‮ } ⁦if isAdmin⁩ ⁦ begin admins only ");
-    //~^ ERROR non-ASCII character in byte constant
-    //~| ERROR non-ASCII character in byte constant
-    //~| ERROR non-ASCII character in byte constant
-    //~| ERROR non-ASCII character in byte constant
+    //~^ ERROR non-ASCII character in byte string literal
+    //~| ERROR non-ASCII character in byte string literal
+    //~| ERROR non-ASCII character in byte string literal
+    //~| ERROR non-ASCII character in byte string literal
     println!("{:?}", br##"/*‮ } ⁦if isAdmin⁩ ⁦ begin admins only "##);
-    //~^ ERROR raw byte string must be ASCII
-    //~| ERROR raw byte string must be ASCII
-    //~| ERROR raw byte string must be ASCII
-    //~| ERROR raw byte string must be ASCII
+    //~^ ERROR non-ASCII character in raw byte string literal
+    //~| ERROR non-ASCII character in raw byte string literal
+    //~| ERROR non-ASCII character in raw byte string literal
+    //~| ERROR non-ASCII character in raw byte string literal
     println!("{:?}", '‮');
     //~^ ERROR unicode codepoint changing visible direction of text present in literal
 }
diff --git a/src/test/ui/parser/unicode-control-codepoints.stderr b/src/test/ui/parser/unicode-control-codepoints.stderr
index 44548c72ff5..fc071a94191 100644
--- a/src/test/ui/parser/unicode-control-codepoints.stderr
+++ b/src/test/ui/parser/unicode-control-codepoints.stderr
@@ -14,69 +14,69 @@ LL |     println!("{:?}", b"us\u{202B}e\u{202A}r");
    |
    = help: unicode escape sequences cannot be used as a byte or in a byte string
 
-error: non-ASCII character in byte constant
+error: non-ASCII character in byte string literal
   --> $DIR/unicode-control-codepoints.rs:16:26
    |
 LL |     println!("{:?}", b"/* } if isAdmin  begin admins only ");
-   |                          ^ byte constant must be ASCII but is '\u{202e}'
+   |                          ^ must be ASCII but is '\u{202e}'
    |
 help: if you meant to use the UTF-8 encoding of '\u{202e}', use \xHH escapes
    |
 LL |     println!("{:?}", b"/*\xE2\x80\xAE } if isAdmin  begin admins only ");
    |                          ~~~~~~~~~~~~
 
-error: non-ASCII character in byte constant
+error: non-ASCII character in byte string literal
   --> $DIR/unicode-control-codepoints.rs:16:30
    |
 LL |     println!("{:?}", b"/* } if isAdmin  begin admins only ");
-   |                             ^ byte constant must be ASCII but is '\u{2066}'
+   |                             ^ must be ASCII but is '\u{2066}'
    |
 help: if you meant to use the UTF-8 encoding of '\u{2066}', use \xHH escapes
    |
 LL |     println!("{:?}", b"/* } \xE2\x81\xA6if isAdmin  begin admins only ");
    |                             ~~~~~~~~~~~~
 
-error: non-ASCII character in byte constant
+error: non-ASCII character in byte string literal
   --> $DIR/unicode-control-codepoints.rs:16:41
    |
 LL |     println!("{:?}", b"/* } if isAdmin  begin admins only ");
-   |                                       ^ byte constant must be ASCII but is '\u{2069}'
+   |                                       ^ must be ASCII but is '\u{2069}'
    |
 help: if you meant to use the UTF-8 encoding of '\u{2069}', use \xHH escapes
    |
 LL |     println!("{:?}", b"/* } if isAdmin\xE2\x81\xA9  begin admins only ");
    |                                       ~~~~~~~~~~~~
 
-error: non-ASCII character in byte constant
+error: non-ASCII character in byte string literal
   --> $DIR/unicode-control-codepoints.rs:16:43
    |
 LL |     println!("{:?}", b"/* } if isAdmin  begin admins only ");
-   |                                        ^ byte constant must be ASCII but is '\u{2066}'
+   |                                        ^ must be ASCII but is '\u{2066}'
    |
 help: if you meant to use the UTF-8 encoding of '\u{2066}', use \xHH escapes
    |
 LL |     println!("{:?}", b"/* } if isAdmin \xE2\x81\xA6 begin admins only ");
    |                                        ~~~~~~~~~~~~
 
-error: raw byte string must be ASCII
+error: non-ASCII character in raw byte string literal
   --> $DIR/unicode-control-codepoints.rs:21:29
    |
 LL |     println!("{:?}", br##"/* } if isAdmin  begin admins only "##);
    |                             ^ must be ASCII but is '\u{202e}'
 
-error: raw byte string must be ASCII
+error: non-ASCII character in raw byte string literal
   --> $DIR/unicode-control-codepoints.rs:21:33
    |
 LL |     println!("{:?}", br##"/* } if isAdmin  begin admins only "##);
    |                                ^ must be ASCII but is '\u{2066}'
 
-error: raw byte string must be ASCII
+error: non-ASCII character in raw byte string literal
   --> $DIR/unicode-control-codepoints.rs:21:44
    |
 LL |     println!("{:?}", br##"/* } if isAdmin  begin admins only "##);
    |                                          ^ must be ASCII but is '\u{2069}'
 
-error: raw byte string must be ASCII
+error: non-ASCII character in raw byte string literal
   --> $DIR/unicode-control-codepoints.rs:21:46
    |
 LL |     println!("{:?}", br##"/* } if isAdmin  begin admins only "##);
diff --git a/src/test/ui/pin-macro/lifetime_errors_on_promotion_misusage.stderr b/src/test/ui/pin-macro/lifetime_errors_on_promotion_misusage.stderr
index 4971263af08..fc1be052fb7 100644
--- a/src/test/ui/pin-macro/lifetime_errors_on_promotion_misusage.stderr
+++ b/src/test/ui/pin-macro/lifetime_errors_on_promotion_misusage.stderr
@@ -4,7 +4,7 @@ error[E0716]: temporary value dropped while borrowed
 LL |     let phantom_pinned = identity(pin!(PhantomPinned));
    |                                   ^^^^^^^^^^^^^^^^^^^ - temporary value is freed at the end of this statement
    |                                   |
-   |                                   creates a temporary which is freed while still in use
+   |                                   creates a temporary value which is freed while still in use
 LL |
 LL |     stuff(phantom_pinned)
    |           -------------- borrow later used here
@@ -18,7 +18,7 @@ error[E0716]: temporary value dropped while borrowed
 LL |     let phantom_pinned = {
    |         -------------- borrow later stored here
 LL |         let phantom_pinned = pin!(PhantomPinned);
-   |                              ^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
+   |                              ^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
 ...
 LL |     };
    |     - temporary value is freed at the end of this statement
diff --git a/src/test/ui/privacy/effective_visibilities.rs b/src/test/ui/privacy/effective_visibilities.rs
index c1f9ee8dfdf..4479b0d8f61 100644
--- a/src/test/ui/privacy/effective_visibilities.rs
+++ b/src/test/ui/privacy/effective_visibilities.rs
@@ -6,7 +6,7 @@ mod outer { //~ ERROR Direct: pub(crate), Reexported: pub(crate), Reachable: pub
     pub mod inner1 { //~ ERROR Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub
 
         #[rustc_effective_visibility]
-        extern "C" {} //~ ERROR Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub
+        extern "C" {} //~ ERROR not in the table
 
         #[rustc_effective_visibility]
         pub trait PubTrait { //~ ERROR Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub
@@ -18,6 +18,7 @@ mod outer { //~ ERROR Direct: pub(crate), Reexported: pub(crate), Reachable: pub
 
         #[rustc_effective_visibility]
         struct PrivStruct; //~ ERROR not in the table
+                           //~| ERROR not in the table
 
         #[rustc_effective_visibility]
         pub union PubUnion { //~ ERROR Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub
@@ -31,6 +32,7 @@ mod outer { //~ ERROR Direct: pub(crate), Reexported: pub(crate), Reachable: pub
         pub enum Enum { //~ ERROR Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub
             #[rustc_effective_visibility]
             A( //~ ERROR Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub
+               //~| ERROR Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub
                 #[rustc_effective_visibility]
                 PubUnion,  //~ ERROR Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub
             ),
diff --git a/src/test/ui/privacy/effective_visibilities.stderr b/src/test/ui/privacy/effective_visibilities.stderr
index 5a8f7db38fc..019aaf8086a 100644
--- a/src/test/ui/privacy/effective_visibilities.stderr
+++ b/src/test/ui/privacy/effective_visibilities.stderr
@@ -10,7 +10,7 @@ error: Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImpl
 LL |     pub mod inner1 {
    |     ^^^^^^^^^^^^^^
 
-error: Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub
+error: not in the table
   --> $DIR/effective_visibilities.rs:9:9
    |
 LL |         extern "C" {}
@@ -28,92 +28,104 @@ error: not in the table
 LL |         struct PrivStruct;
    |         ^^^^^^^^^^^^^^^^^
 
+error: not in the table
+  --> $DIR/effective_visibilities.rs:20:9
+   |
+LL |         struct PrivStruct;
+   |         ^^^^^^^^^^^^^^^^^
+
 error: Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub
-  --> $DIR/effective_visibilities.rs:23:9
+  --> $DIR/effective_visibilities.rs:24:9
    |
 LL |         pub union PubUnion {
    |         ^^^^^^^^^^^^^^^^^^
 
 error: not in the table
-  --> $DIR/effective_visibilities.rs:25:13
+  --> $DIR/effective_visibilities.rs:26:13
    |
 LL |             a: u8,
    |             ^^^^^
 
 error: Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub
-  --> $DIR/effective_visibilities.rs:27:13
+  --> $DIR/effective_visibilities.rs:28:13
    |
 LL |             pub b: u8,
    |             ^^^^^^^^^
 
 error: Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub
-  --> $DIR/effective_visibilities.rs:31:9
+  --> $DIR/effective_visibilities.rs:32:9
    |
 LL |         pub enum Enum {
    |         ^^^^^^^^^^^^^
 
 error: Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub
-  --> $DIR/effective_visibilities.rs:33:13
+  --> $DIR/effective_visibilities.rs:34:13
+   |
+LL |             A(
+   |             ^
+
+error: Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub
+  --> $DIR/effective_visibilities.rs:34:13
    |
 LL |             A(
    |             ^
 
 error: Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub
-  --> $DIR/effective_visibilities.rs:35:17
+  --> $DIR/effective_visibilities.rs:37:17
    |
 LL |                 PubUnion,
    |                 ^^^^^^^^
 
 error: not in the table
-  --> $DIR/effective_visibilities.rs:41:5
+  --> $DIR/effective_visibilities.rs:43:5
    |
 LL |     macro_rules! none_macro {
    |     ^^^^^^^^^^^^^^^^^^^^^^^
 
 error: Direct: pub(self), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub
-  --> $DIR/effective_visibilities.rs:47:5
+  --> $DIR/effective_visibilities.rs:49:5
    |
 LL |     macro_rules! public_macro {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: Direct: pub(crate), Reexported: pub(crate), Reachable: pub, ReachableThroughImplTrait: pub
-  --> $DIR/effective_visibilities.rs:52:5
+  --> $DIR/effective_visibilities.rs:54:5
    |
 LL |     pub struct ReachableStruct {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: Direct: pub(crate), Reexported: pub(crate), Reachable: pub, ReachableThroughImplTrait: pub
-  --> $DIR/effective_visibilities.rs:54:9
+  --> $DIR/effective_visibilities.rs:56:9
    |
 LL |         pub a: u8,
    |         ^^^^^^^^^
 
 error: Direct: pub, Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub
-  --> $DIR/effective_visibilities.rs:59:9
+  --> $DIR/effective_visibilities.rs:61:9
    |
 LL | pub use outer::inner1;
    |         ^^^^^^^^^^^^^
 
 error: Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub
-  --> $DIR/effective_visibilities.rs:65:5
+  --> $DIR/effective_visibilities.rs:67:5
    |
 LL |     pub type HalfPublicImport = u8;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: Direct: pub(crate), Reexported: pub(crate), Reachable: pub(crate), ReachableThroughImplTrait: pub(crate)
-  --> $DIR/effective_visibilities.rs:68:5
+  --> $DIR/effective_visibilities.rs:70:5
    |
 LL |     pub(crate) const HalfPublicImport: u8 = 0;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: Direct: pub, Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub
-  --> $DIR/effective_visibilities.rs:72:9
+  --> $DIR/effective_visibilities.rs:74:9
    |
 LL | pub use half_public_import::HalfPublicImport;
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: Direct: pub, Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub
-  --> $DIR/effective_visibilities.rs:72:9
+  --> $DIR/effective_visibilities.rs:74:9
    |
 LL | pub use half_public_import::HalfPublicImport;
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -130,5 +142,5 @@ error: Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImpl
 LL |             type B;
    |             ^^^^^^
 
-error: aborting due to 22 previous errors
+error: aborting due to 24 previous errors
 
diff --git a/src/test/ui/privacy/effective_visibilities_glob.rs b/src/test/ui/privacy/effective_visibilities_glob.rs
new file mode 100644
index 00000000000..eb9dcd6cd1f
--- /dev/null
+++ b/src/test/ui/privacy/effective_visibilities_glob.rs
@@ -0,0 +1,21 @@
+// Effective visibility tracking for imports is fine-grained, so `S2` is not fully exported
+// even if its parent import (`m::*`) is fully exported as a `use` item.
+
+#![feature(rustc_attrs)]
+
+mod m {
+    #[rustc_effective_visibility]
+    pub struct S1 {} //~ ERROR Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub
+    #[rustc_effective_visibility]
+    pub struct S2 {} //~ ERROR Direct: pub(crate), Reexported: pub(crate), Reachable: pub(crate), ReachableThroughImplTrait: pub(crate)
+}
+
+mod glob {
+    #[rustc_effective_visibility]
+    pub use crate::m::*; //~ ERROR Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub
+}
+
+#[rustc_effective_visibility]
+pub use glob::S1; //~ ERROR Direct: pub, Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub
+
+fn main() {}
diff --git a/src/test/ui/privacy/effective_visibilities_glob.stderr b/src/test/ui/privacy/effective_visibilities_glob.stderr
new file mode 100644
index 00000000000..0496cd5df8d
--- /dev/null
+++ b/src/test/ui/privacy/effective_visibilities_glob.stderr
@@ -0,0 +1,26 @@
+error: Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub
+  --> $DIR/effective_visibilities_glob.rs:8:5
+   |
+LL |     pub struct S1 {}
+   |     ^^^^^^^^^^^^^
+
+error: Direct: pub(crate), Reexported: pub(crate), Reachable: pub(crate), ReachableThroughImplTrait: pub(crate)
+  --> $DIR/effective_visibilities_glob.rs:10:5
+   |
+LL |     pub struct S2 {}
+   |     ^^^^^^^^^^^^^
+
+error: Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub
+  --> $DIR/effective_visibilities_glob.rs:15:13
+   |
+LL |     pub use crate::m::*;
+   |             ^^^^^^^^
+
+error: Direct: pub, Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub
+  --> $DIR/effective_visibilities_glob.rs:19:9
+   |
+LL | pub use glob::S1;
+   |         ^^^^^^^^
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/regions/regions-free-region-ordering-caller1.stderr b/src/test/ui/regions/regions-free-region-ordering-caller1.stderr
index 8042b1740b1..8ef7e22536b 100644
--- a/src/test/ui/regions/regions-free-region-ordering-caller1.stderr
+++ b/src/test/ui/regions/regions-free-region-ordering-caller1.stderr
@@ -5,7 +5,7 @@ LL | fn call1<'a>(x: &'a usize) {
    |          -- lifetime `'a` defined here
 ...
 LL |     let z: &'a & usize = &(&y);
-   |            -----------    ^^^^ creates a temporary which is freed while still in use
+   |            -----------    ^^^^ creates a temporary value which is freed while still in use
    |            |
    |            type annotation requires that borrow lasts for `'a`
 ...
diff --git a/src/test/ui/regions/regions-var-type-out-of-scope.stderr b/src/test/ui/regions/regions-var-type-out-of-scope.stderr
index 476e82f046f..c32bbe0ee1f 100644
--- a/src/test/ui/regions/regions-var-type-out-of-scope.stderr
+++ b/src/test/ui/regions/regions-var-type-out-of-scope.stderr
@@ -4,7 +4,7 @@ error[E0716]: temporary value dropped while borrowed
 LL |         x = &id(3);
    |              ^^^^^- temporary value is freed at the end of this statement
    |              |
-   |              creates a temporary which is freed while still in use
+   |              creates a temporary value which is freed while still in use
 LL |         assert_eq!(*x, 3);
    |         ----------------- borrow later used here
    |
diff --git a/src/test/ui/span/borrowck-let-suggestion-suffixes.rs b/src/test/ui/span/borrowck-let-suggestion-suffixes.rs
index 6240f103c99..18abfb5c3fb 100644
--- a/src/test/ui/span/borrowck-let-suggestion-suffixes.rs
+++ b/src/test/ui/span/borrowck-let-suggestion-suffixes.rs
@@ -18,7 +18,7 @@ fn f() {
 
     v3.push(&id('x'));           // statement 6
     //~^ ERROR temporary value dropped while borrowed
-    //~| NOTE creates a temporary which is freed while still in use
+    //~| NOTE creates a temporary value which is freed while still in use
     //~| NOTE temporary value is freed at the end of this statement
     //~| HELP consider using a `let` binding to create a longer lived value
 
@@ -28,7 +28,7 @@ fn f() {
 
         v4.push(&id('y'));
         //~^ ERROR temporary value dropped while borrowed
-        //~| NOTE creates a temporary which is freed while still in use
+        //~| NOTE creates a temporary value which is freed while still in use
         //~| NOTE temporary value is freed at the end of this statement
         //~| NOTE consider using a `let` binding to create a longer lived value
         v4.use_ref();
@@ -39,7 +39,7 @@ fn f() {
 
     v5.push(&id('z'));
     //~^ ERROR temporary value dropped while borrowed
-    //~| NOTE creates a temporary which is freed while still in use
+    //~| NOTE creates a temporary value which is freed while still in use
     //~| NOTE temporary value is freed at the end of this statement
     //~| HELP consider using a `let` binding to create a longer lived value
 
diff --git a/src/test/ui/span/borrowck-let-suggestion-suffixes.stderr b/src/test/ui/span/borrowck-let-suggestion-suffixes.stderr
index a236dab3ae5..2dc29a78d20 100644
--- a/src/test/ui/span/borrowck-let-suggestion-suffixes.stderr
+++ b/src/test/ui/span/borrowck-let-suggestion-suffixes.stderr
@@ -16,7 +16,7 @@ error[E0716]: temporary value dropped while borrowed
 LL |     v3.push(&id('x'));           // statement 6
    |              ^^^^^^^ - temporary value is freed at the end of this statement
    |              |
-   |              creates a temporary which is freed while still in use
+   |              creates a temporary value which is freed while still in use
 ...
 LL |     (v1, v2, v3, /* v4 is above. */ v5).use_ref();
    |              -- borrow later used here
@@ -33,7 +33,7 @@ error[E0716]: temporary value dropped while borrowed
 LL |         v4.push(&id('y'));
    |                  ^^^^^^^ - temporary value is freed at the end of this statement
    |                  |
-   |                  creates a temporary which is freed while still in use
+   |                  creates a temporary value which is freed while still in use
 ...
 LL |         v4.use_ref();
    |         ------------ borrow later used here
@@ -46,7 +46,7 @@ error[E0716]: temporary value dropped while borrowed
 LL |     v5.push(&id('z'));
    |              ^^^^^^^ - temporary value is freed at the end of this statement
    |              |
-   |              creates a temporary which is freed while still in use
+   |              creates a temporary value which is freed while still in use
 ...
 LL |     (v1, v2, v3, /* v4 is above. */ v5).use_ref();
    |                                     -- borrow later used here
diff --git a/src/test/ui/span/borrowck-ref-into-rvalue.stderr b/src/test/ui/span/borrowck-ref-into-rvalue.stderr
index cb5289d24b4..25e344fedfb 100644
--- a/src/test/ui/span/borrowck-ref-into-rvalue.stderr
+++ b/src/test/ui/span/borrowck-ref-into-rvalue.stderr
@@ -2,7 +2,7 @@ error[E0716]: temporary value dropped while borrowed
   --> $DIR/borrowck-ref-into-rvalue.rs:4:11
    |
 LL |     match Some("Hello".to_string()) {
-   |           ^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
+   |           ^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
 ...
 LL |     }
    |     - temporary value is freed at the end of this statement
diff --git a/src/test/ui/span/issue-11925.rs b/src/test/ui/span/issue-11925.rs
index d9c08fbdd0f..cac9fd5bfb6 100644
--- a/src/test/ui/span/issue-11925.rs
+++ b/src/test/ui/span/issue-11925.rs
@@ -1,6 +1,6 @@
-#![feature(unboxed_closures)]
+#![feature(unboxed_closures, tuple_trait)]
 
-fn to_fn_once<A,F:FnOnce<A>>(f: F) -> F { f }
+fn to_fn_once<A:std::marker::Tuple,F:FnOnce<A>>(f: F) -> F { f }
 
 fn main() {
     let r = {
diff --git a/src/test/ui/span/issue-15480.stderr b/src/test/ui/span/issue-15480.stderr
index 460ad9ac744..d9cce2254dd 100644
--- a/src/test/ui/span/issue-15480.stderr
+++ b/src/test/ui/span/issue-15480.stderr
@@ -2,7 +2,7 @@ error[E0716]: temporary value dropped while borrowed
   --> $DIR/issue-15480.rs:6:10
    |
 LL |         &id(3)
-   |          ^^^^^ creates a temporary which is freed while still in use
+   |          ^^^^^ creates a temporary value which is freed while still in use
 LL |     ];
    |      - temporary value is freed at the end of this statement
 ...
diff --git a/src/test/ui/span/regions-close-over-borrowed-ref-in-obj.stderr b/src/test/ui/span/regions-close-over-borrowed-ref-in-obj.stderr
index ba0c45acf23..81e858fa0ce 100644
--- a/src/test/ui/span/regions-close-over-borrowed-ref-in-obj.stderr
+++ b/src/test/ui/span/regions-close-over-borrowed-ref-in-obj.stderr
@@ -2,7 +2,7 @@ error[E0716]: temporary value dropped while borrowed
   --> $DIR/regions-close-over-borrowed-ref-in-obj.rs:12:27
    |
 LL |         let ss: &isize = &id(1);
-   |                           ^^^^^ creates a temporary which is freed while still in use
+   |                           ^^^^^ creates a temporary value which is freed while still in use
 ...
 LL |     }
    |     - temporary value is freed at the end of this statement
diff --git a/src/test/ui/span/slice-borrow.stderr b/src/test/ui/span/slice-borrow.stderr
index 27df25be3fa..b70bf69d688 100644
--- a/src/test/ui/span/slice-borrow.stderr
+++ b/src/test/ui/span/slice-borrow.stderr
@@ -2,7 +2,7 @@ error[E0716]: temporary value dropped while borrowed
   --> $DIR/slice-borrow.rs:6:28
    |
 LL |         let x: &[isize] = &vec![1, 2, 3, 4, 5];
-   |                            ^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
+   |                            ^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
 ...
 LL |     }
    |     - temporary value is freed at the end of this statement
diff --git a/src/test/ui/static/static-drop-scope.stderr b/src/test/ui/static/static-drop-scope.stderr
index 112bfc00304..cedcb736794 100644
--- a/src/test/ui/static/static-drop-scope.stderr
+++ b/src/test/ui/static/static-drop-scope.stderr
@@ -13,7 +13,7 @@ LL | static PROMOTION_FAIL_S: Option<&'static WithDtor> = Some(&WithDtor);
    |                                                      ------^^^^^^^^-
    |                                                      |     |       |
    |                                                      |     |       temporary value is freed at the end of this statement
-   |                                                      |     creates a temporary which is freed while still in use
+   |                                                      |     creates a temporary value which is freed while still in use
    |                                                      using this value as a static requires that borrow lasts for `'static`
 
 error[E0493]: destructor of `WithDtor` cannot be evaluated at compile-time
@@ -31,7 +31,7 @@ LL | const PROMOTION_FAIL_C: Option<&'static WithDtor> = Some(&WithDtor);
    |                                                     ------^^^^^^^^-
    |                                                     |     |       |
    |                                                     |     |       temporary value is freed at the end of this statement
-   |                                                     |     creates a temporary which is freed while still in use
+   |                                                     |     creates a temporary value which is freed while still in use
    |                                                     using this value as a constant requires that borrow lasts for `'static`
 
 error[E0493]: destructor of `(WithDtor, i32)` cannot be evaluated at compile-time
diff --git a/src/test/ui/static/static-reference-to-fn-2.stderr b/src/test/ui/static/static-reference-to-fn-2.stderr
index ff15884bd44..133d8ec2e1e 100644
--- a/src/test/ui/static/static-reference-to-fn-2.stderr
+++ b/src/test/ui/static/static-reference-to-fn-2.stderr
@@ -6,7 +6,7 @@ LL | fn state1(self_: &mut StateMachineIter) -> Option<&'static str> {
 LL |     self_.statefn = &id(state2 as StateMachineFunc);
    |     -----------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- temporary value is freed at the end of this statement
    |     |                |
-   |     |                creates a temporary which is freed while still in use
+   |     |                creates a temporary value which is freed while still in use
    |     assignment requires that borrow lasts for `'1`
 
 error[E0716]: temporary value dropped while borrowed
@@ -17,7 +17,7 @@ LL | fn state2(self_: &mut StateMachineIter) -> Option<(&'static str)> {
 LL |     self_.statefn = &id(state3 as StateMachineFunc);
    |     -----------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- temporary value is freed at the end of this statement
    |     |                |
-   |     |                creates a temporary which is freed while still in use
+   |     |                creates a temporary value which is freed while still in use
    |     assignment requires that borrow lasts for `'1`
 
 error[E0716]: temporary value dropped while borrowed
@@ -28,7 +28,7 @@ LL | fn state3(self_: &mut StateMachineIter) -> Option<(&'static str)> {
 LL |     self_.statefn = &id(finished as StateMachineFunc);
    |     -----------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- temporary value is freed at the end of this statement
    |     |                |
-   |     |                creates a temporary which is freed while still in use
+   |     |                creates a temporary value which is freed while still in use
    |     assignment requires that borrow lasts for `'1`
 
 error[E0515]: cannot return value referencing temporary value
diff --git a/src/test/ui/static/static-region-bound.stderr b/src/test/ui/static/static-region-bound.stderr
index 15261259ed4..1a607e3c014 100644
--- a/src/test/ui/static/static-region-bound.stderr
+++ b/src/test/ui/static/static-region-bound.stderr
@@ -2,7 +2,7 @@ error[E0716]: temporary value dropped while borrowed
   --> $DIR/static-region-bound.rs:10:14
    |
 LL |     let x = &id(3);
-   |              ^^^^^ creates a temporary which is freed while still in use
+   |              ^^^^^ creates a temporary value which is freed while still in use
 LL |     f(x);
    |     ---- argument requires that borrow lasts for `'static`
 LL | }
diff --git a/src/test/ui/statics/issue-44373.stderr b/src/test/ui/statics/issue-44373.stderr
index 6f92fbb1eb6..2d29dec888e 100644
--- a/src/test/ui/statics/issue-44373.stderr
+++ b/src/test/ui/statics/issue-44373.stderr
@@ -2,7 +2,7 @@ error[E0716]: temporary value dropped while borrowed
   --> $DIR/issue-44373.rs:4:42
    |
 LL |     let _val: &'static [&'static u32] = &[&FOO];
-   |               -----------------------    ^^^^^^ creates a temporary which is freed while still in use
+   |               -----------------------    ^^^^^^ creates a temporary value which is freed while still in use
    |               |
    |               type annotation requires that borrow lasts for `'static`
 LL | }
diff --git a/src/test/ui/suggestions/if-let-typo.stderr b/src/test/ui/suggestions/if-let-typo.stderr
index 3d9ac40ec36..02148b7f7ad 100644
--- a/src/test/ui/suggestions/if-let-typo.stderr
+++ b/src/test/ui/suggestions/if-let-typo.stderr
@@ -25,12 +25,22 @@ error[E0308]: mismatched types
    |
 LL |     if Some(x) = foo {}
    |        ^^^^^^^^^^^^^ expected `bool`, found `()`
+   |
+help: consider adding `let`
+   |
+LL |     if let Some(x) = foo {}
+   |        +++
 
 error[E0308]: mismatched types
   --> $DIR/if-let-typo.rs:6:8
    |
 LL |     if Some(foo) = bar {}
    |        ^^^^^^^^^^^^^^^ expected `bool`, found `()`
+   |
+help: consider adding `let`
+   |
+LL |     if let Some(foo) = bar {}
+   |        +++
 
 error[E0308]: mismatched types
   --> $DIR/if-let-typo.rs:7:8
@@ -51,6 +61,11 @@ error[E0308]: mismatched types
    |
 LL |     if Some(3) = foo {}
    |        ^^^^^^^^^^^^^ expected `bool`, found `()`
+   |
+help: consider adding `let`
+   |
+LL |     if let Some(3) = foo {}
+   |        +++
 
 error: aborting due to 7 previous errors
 
diff --git a/src/test/ui/suggestions/inner_type2.rs b/src/test/ui/suggestions/inner_type2.rs
index c56ea7c030d..fac68c053eb 100644
--- a/src/test/ui/suggestions/inner_type2.rs
+++ b/src/test/ui/suggestions/inner_type2.rs
@@ -22,5 +22,5 @@ fn main() {
     let item = std::mem::MaybeUninit::new(Struct { p: 42_u32 });
     item.method();
     //~^ ERROR no method named `method` found for union `MaybeUninit` in the current scope [E0599]
-    //~| HELP if this `MaybeUninit::<Struct<u32>>` has been initialized, use one of the `assume_init` methods to access the inner value
+    //~| HELP if this `MaybeUninit<Struct<u32>>` has been initialized, use one of the `assume_init` methods to access the inner value
 }
diff --git a/src/test/ui/suggestions/inner_type2.stderr b/src/test/ui/suggestions/inner_type2.stderr
index eddfd9d6340..984366123c8 100644
--- a/src/test/ui/suggestions/inner_type2.stderr
+++ b/src/test/ui/suggestions/inner_type2.stderr
@@ -17,7 +17,7 @@ error[E0599]: no method named `method` found for union `MaybeUninit` in the curr
 LL |     item.method();
    |          ^^^^^^ method not found in `MaybeUninit<Struct<u32>>`
    |
-   = help: if this `MaybeUninit::<Struct<u32>>` has been initialized, use one of the `assume_init` methods to access the inner value
+   = help: if this `MaybeUninit<Struct<u32>>` has been initialized, use one of the `assume_init` methods to access the inner value
 note: the method `method` exists on the type `Struct<u32>`
   --> $DIR/inner_type2.rs:6:5
    |
diff --git a/src/test/ui/suggestions/issue-102354.stderr b/src/test/ui/suggestions/issue-102354.stderr
index 4f76c5f2e75..b17c4dc5dfb 100644
--- a/src/test/ui/suggestions/issue-102354.stderr
+++ b/src/test/ui/suggestions/issue-102354.stderr
@@ -13,7 +13,7 @@ LL |     fn func() {}
 help: use associated function syntax instead
    |
 LL |     i32::func();
-   |     ~~~~~~~~~
+   |     ~~~~~~~~~~~
 help: disambiguate the associated function for the candidate
    |
 LL |     <i32 as Trait>::func(x);
diff --git a/src/test/ui/suggestions/multibyte-escapes.rs b/src/test/ui/suggestions/multibyte-escapes.rs
index fd5d46a4e92..c4105186244 100644
--- a/src/test/ui/suggestions/multibyte-escapes.rs
+++ b/src/test/ui/suggestions/multibyte-escapes.rs
@@ -2,17 +2,17 @@
 
 fn main() {
     b'µ';
-    //~^ ERROR: non-ASCII character in byte constant
+    //~^ ERROR: non-ASCII character in byte literal
     //~| HELP: if you meant to use the unicode code point for 'µ', use a \xHH escape
-    //~| NOTE: byte constant must be ASCII
+    //~| NOTE: must be ASCII
 
     b'字';
-    //~^ ERROR: non-ASCII character in byte constant
+    //~^ ERROR: non-ASCII character in byte literal
     //~| NOTE: this multibyte character does not fit into a single byte
-    //~| NOTE: byte constant must be ASCII
+    //~| NOTE: must be ASCII
 
     b"字";
-    //~^ ERROR: non-ASCII character in byte constant
+    //~^ ERROR: non-ASCII character in byte string literal
     //~| HELP: if you meant to use the UTF-8 encoding of '字', use \xHH escapes
-    //~| NOTE: byte constant must be ASCII
+    //~| NOTE: must be ASCII
 }
diff --git a/src/test/ui/suggestions/multibyte-escapes.stderr b/src/test/ui/suggestions/multibyte-escapes.stderr
index 6e26bc1f01c..1e7c43e6538 100644
--- a/src/test/ui/suggestions/multibyte-escapes.stderr
+++ b/src/test/ui/suggestions/multibyte-escapes.stderr
@@ -1,28 +1,28 @@
-error: non-ASCII character in byte constant
+error: non-ASCII character in byte literal
   --> $DIR/multibyte-escapes.rs:4:7
    |
 LL |     b'µ';
-   |       ^ byte constant must be ASCII
+   |       ^ must be ASCII
    |
 help: if you meant to use the unicode code point for 'µ', use a \xHH escape
    |
 LL |     b'\xB5';
    |       ~~~~
 
-error: non-ASCII character in byte constant
+error: non-ASCII character in byte literal
   --> $DIR/multibyte-escapes.rs:9:7
    |
 LL |     b'字';
    |       ^^
    |       |
-   |       byte constant must be ASCII
+   |       must be ASCII
    |       this multibyte character does not fit into a single byte
 
-error: non-ASCII character in byte constant
+error: non-ASCII character in byte string literal
   --> $DIR/multibyte-escapes.rs:14:7
    |
 LL |     b"字";
-   |       ^^ byte constant must be ASCII
+   |       ^^ must be ASCII
    |
 help: if you meant to use the UTF-8 encoding of '字', use \xHH escapes
    |
diff --git a/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish-placeholder.rs b/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish-placeholder.rs
new file mode 100644
index 00000000000..a39b8711dd8
--- /dev/null
+++ b/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish-placeholder.rs
@@ -0,0 +1,11 @@
+struct GenericAssocMethod<T>(T);
+
+impl<T> GenericAssocMethod<T> {
+    fn default_hello() {}
+}
+
+fn main() {
+    let x = GenericAssocMethod(33);
+    x.default_hello();
+    //~^ ERROR no method named `default_hello` found
+}
diff --git a/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish-placeholder.stderr b/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish-placeholder.stderr
new file mode 100644
index 00000000000..c247e73b39c
--- /dev/null
+++ b/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish-placeholder.stderr
@@ -0,0 +1,22 @@
+error[E0599]: no method named `default_hello` found for struct `GenericAssocMethod<{integer}>` in the current scope
+  --> $DIR/suggest-assoc-fn-call-with-turbofish-placeholder.rs:9:7
+   |
+LL | struct GenericAssocMethod<T>(T);
+   | ---------------------------- method `default_hello` not found for this struct
+...
+LL |     x.default_hello();
+   |     --^^^^^^^^^^^^^--
+   |     | |
+   |     | this is an associated function, not a method
+   |     help: use associated function syntax instead: `GenericAssocMethod::<_>::default_hello()`
+   |
+   = note: found the following associated functions; to be used as methods, functions must have a `self` parameter
+note: the candidate is defined in an impl for the type `GenericAssocMethod<T>`
+  --> $DIR/suggest-assoc-fn-call-with-turbofish-placeholder.rs:4:5
+   |
+LL |     fn default_hello() {}
+   |     ^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish-through-deref.stderr b/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish-through-deref.stderr
index 996d5773118..7c9f0b6c212 100644
--- a/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish-through-deref.stderr
+++ b/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish-through-deref.stderr
@@ -2,10 +2,10 @@ error[E0599]: no method named `hello` found for struct `RefMut<'_, HasAssocMetho
   --> $DIR/suggest-assoc-fn-call-with-turbofish-through-deref.rs:11:11
    |
 LL |     state.hello();
-   |     ------^^^^^
+   |     ------^^^^^--
    |     |     |
    |     |     this is an associated function, not a method
-   |     help: use associated function syntax instead: `HasAssocMethod::hello`
+   |     help: use associated function syntax instead: `HasAssocMethod::hello()`
    |
    = note: found the following associated functions; to be used as methods, functions must have a `self` parameter
 note: the candidate is defined in an impl for the type `HasAssocMethod`
diff --git a/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.fixed b/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.fixed
new file mode 100644
index 00000000000..02dd0715c80
--- /dev/null
+++ b/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.fixed
@@ -0,0 +1,26 @@
+// run-rustfix
+
+struct GenericAssocMethod<T>(T);
+
+impl<T> GenericAssocMethod<T> {
+    fn default_hello() {}
+    fn self_ty_hello(_: Self) {}
+    fn self_ty_ref_hello(_: &Self) {}
+}
+
+fn main() {
+    // Test for inferred types
+    let x = GenericAssocMethod(33);
+    GenericAssocMethod::<_>::self_ty_ref_hello(&x);
+    //~^ ERROR no method named `self_ty_ref_hello` found
+    GenericAssocMethod::<_>::self_ty_hello(x);
+    //~^ ERROR no method named `self_ty_hello` found
+    // Test for known types
+    let y = GenericAssocMethod(33i32);
+    GenericAssocMethod::<i32>::default_hello();
+    //~^ ERROR no method named `default_hello` found
+    GenericAssocMethod::<i32>::self_ty_ref_hello(&y);
+    //~^ ERROR no method named `self_ty_ref_hello` found
+    GenericAssocMethod::<i32>::self_ty_hello(y);
+    //~^ ERROR no method named `self_ty_hello` found
+}
diff --git a/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.rs b/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.rs
index 2a829db5383..1d0ca8e780a 100644
--- a/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.rs
+++ b/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.rs
@@ -1,11 +1,26 @@
+// run-rustfix
+
 struct GenericAssocMethod<T>(T);
 
 impl<T> GenericAssocMethod<T> {
     fn default_hello() {}
+    fn self_ty_hello(_: Self) {}
+    fn self_ty_ref_hello(_: &Self) {}
 }
 
 fn main() {
-    let x = GenericAssocMethod(33i32);
-    x.default_hello();
+    // Test for inferred types
+    let x = GenericAssocMethod(33);
+    x.self_ty_ref_hello();
+    //~^ ERROR no method named `self_ty_ref_hello` found
+    x.self_ty_hello();
+    //~^ ERROR no method named `self_ty_hello` found
+    // Test for known types
+    let y = GenericAssocMethod(33i32);
+    y.default_hello();
     //~^ ERROR no method named `default_hello` found
+    y.self_ty_ref_hello();
+    //~^ ERROR no method named `self_ty_ref_hello` found
+    y.self_ty_hello();
+    //~^ ERROR no method named `self_ty_hello` found
 }
diff --git a/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.stderr b/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.stderr
index 3fb418b1c0a..92b03fc7714 100644
--- a/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.stderr
+++ b/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.stderr
@@ -1,22 +1,98 @@
+error[E0599]: no method named `self_ty_ref_hello` found for struct `GenericAssocMethod<{integer}>` in the current scope
+  --> $DIR/suggest-assoc-fn-call-with-turbofish.rs:14:7
+   |
+LL | struct GenericAssocMethod<T>(T);
+   | ---------------------------- method `self_ty_ref_hello` not found for this struct
+...
+LL |     x.self_ty_ref_hello();
+   |     --^^^^^^^^^^^^^^^^^--
+   |     | |
+   |     | this is an associated function, not a method
+   |     help: use associated function syntax instead: `GenericAssocMethod::<_>::self_ty_ref_hello(&x)`
+   |
+   = note: found the following associated functions; to be used as methods, functions must have a `self` parameter
+note: the candidate is defined in an impl for the type `GenericAssocMethod<T>`
+  --> $DIR/suggest-assoc-fn-call-with-turbofish.rs:8:5
+   |
+LL |     fn self_ty_ref_hello(_: &Self) {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0599]: no method named `self_ty_hello` found for struct `GenericAssocMethod<{integer}>` in the current scope
+  --> $DIR/suggest-assoc-fn-call-with-turbofish.rs:16:7
+   |
+LL | struct GenericAssocMethod<T>(T);
+   | ---------------------------- method `self_ty_hello` not found for this struct
+...
+LL |     x.self_ty_hello();
+   |     --^^^^^^^^^^^^^--
+   |     | |
+   |     | this is an associated function, not a method
+   |     help: use associated function syntax instead: `GenericAssocMethod::<_>::self_ty_hello(x)`
+   |
+   = note: found the following associated functions; to be used as methods, functions must have a `self` parameter
+note: the candidate is defined in an impl for the type `GenericAssocMethod<T>`
+  --> $DIR/suggest-assoc-fn-call-with-turbofish.rs:7:5
+   |
+LL |     fn self_ty_hello(_: Self) {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+
 error[E0599]: no method named `default_hello` found for struct `GenericAssocMethod<i32>` in the current scope
-  --> $DIR/suggest-assoc-fn-call-with-turbofish.rs:9:7
+  --> $DIR/suggest-assoc-fn-call-with-turbofish.rs:20:7
    |
 LL | struct GenericAssocMethod<T>(T);
    | ---------------------------- method `default_hello` not found for this struct
 ...
-LL |     x.default_hello();
-   |     --^^^^^^^^^^^^^
+LL |     y.default_hello();
+   |     --^^^^^^^^^^^^^--
    |     | |
    |     | this is an associated function, not a method
-   |     help: use associated function syntax instead: `GenericAssocMethod::<i32>::default_hello`
+   |     help: use associated function syntax instead: `GenericAssocMethod::<i32>::default_hello()`
    |
    = note: found the following associated functions; to be used as methods, functions must have a `self` parameter
 note: the candidate is defined in an impl for the type `GenericAssocMethod<T>`
-  --> $DIR/suggest-assoc-fn-call-with-turbofish.rs:4:5
+  --> $DIR/suggest-assoc-fn-call-with-turbofish.rs:6:5
    |
 LL |     fn default_hello() {}
    |     ^^^^^^^^^^^^^^^^^^
 
-error: aborting due to previous error
+error[E0599]: no method named `self_ty_ref_hello` found for struct `GenericAssocMethod<i32>` in the current scope
+  --> $DIR/suggest-assoc-fn-call-with-turbofish.rs:22:7
+   |
+LL | struct GenericAssocMethod<T>(T);
+   | ---------------------------- method `self_ty_ref_hello` not found for this struct
+...
+LL |     y.self_ty_ref_hello();
+   |     --^^^^^^^^^^^^^^^^^--
+   |     | |
+   |     | this is an associated function, not a method
+   |     help: use associated function syntax instead: `GenericAssocMethod::<i32>::self_ty_ref_hello(&y)`
+   |
+   = note: found the following associated functions; to be used as methods, functions must have a `self` parameter
+note: the candidate is defined in an impl for the type `GenericAssocMethod<T>`
+  --> $DIR/suggest-assoc-fn-call-with-turbofish.rs:8:5
+   |
+LL |     fn self_ty_ref_hello(_: &Self) {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0599]: no method named `self_ty_hello` found for struct `GenericAssocMethod<i32>` in the current scope
+  --> $DIR/suggest-assoc-fn-call-with-turbofish.rs:24:7
+   |
+LL | struct GenericAssocMethod<T>(T);
+   | ---------------------------- method `self_ty_hello` not found for this struct
+...
+LL |     y.self_ty_hello();
+   |     --^^^^^^^^^^^^^--
+   |     | |
+   |     | this is an associated function, not a method
+   |     help: use associated function syntax instead: `GenericAssocMethod::<i32>::self_ty_hello(y)`
+   |
+   = note: found the following associated functions; to be used as methods, functions must have a `self` parameter
+note: the candidate is defined in an impl for the type `GenericAssocMethod<T>`
+  --> $DIR/suggest-assoc-fn-call-with-turbofish.rs:7:5
+   |
+LL |     fn self_ty_hello(_: Self) {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 5 previous errors
 
 For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/target-feature/tied-features-cli.one.stderr b/src/test/ui/target-feature/tied-features-cli.one.stderr
index 0cc901eecaa..b4b50d98192 100644
--- a/src/test/ui/target-feature/tied-features-cli.one.stderr
+++ b/src/test/ui/target-feature/tied-features-cli.one.stderr
@@ -1,4 +1,4 @@
-error: target features paca, pacg must all be enabled or disabled together
+error: the target features paca, pacg must all be either enabled or disabled together
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/target-feature/tied-features-cli.three.stderr b/src/test/ui/target-feature/tied-features-cli.three.stderr
index 0cc901eecaa..b4b50d98192 100644
--- a/src/test/ui/target-feature/tied-features-cli.three.stderr
+++ b/src/test/ui/target-feature/tied-features-cli.three.stderr
@@ -1,4 +1,4 @@
-error: target features paca, pacg must all be enabled or disabled together
+error: the target features paca, pacg must all be either enabled or disabled together
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/target-feature/tied-features-cli.two.stderr b/src/test/ui/target-feature/tied-features-cli.two.stderr
index 0cc901eecaa..b4b50d98192 100644
--- a/src/test/ui/target-feature/tied-features-cli.two.stderr
+++ b/src/test/ui/target-feature/tied-features-cli.two.stderr
@@ -1,4 +1,4 @@
-error: target features paca, pacg must all be enabled or disabled together
+error: the target features paca, pacg must all be either enabled or disabled together
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/traits/issue-77982.stderr b/src/test/ui/traits/issue-77982.stderr
index e210f11b3e0..b6a04585583 100644
--- a/src/test/ui/traits/issue-77982.stderr
+++ b/src/test/ui/traits/issue-77982.stderr
@@ -46,12 +46,7 @@ LL |     let ips: Vec<_> = (0..100_000).map(|_| u32::from(0u32.into())).collect(
    |                                            |
    |                                            required by a bound introduced by this call
    |
-   = note: multiple `impl`s satisfying `u32: From<_>` found in the following crates: `core`, `std`:
-           - impl From<Ipv4Addr> for u32;
-           - impl From<NonZeroU32> for u32;
-           - impl From<bool> for u32;
-           - impl From<char> for u32;
-           and 3 more
+   = note: cannot satisfy `u32: From<_>`
 help: try using a fully qualified path to specify the expected types
    |
 LL |     let ips: Vec<_> = (0..100_000).map(|_| u32::from(<u32 as Into<T>>::into(0u32))).collect();
diff --git a/src/test/ui/transmute/transmute-padding-ice.rs b/src/test/ui/transmute/transmute-padding-ice.rs
new file mode 100644
index 00000000000..a1be7075a8a
--- /dev/null
+++ b/src/test/ui/transmute/transmute-padding-ice.rs
@@ -0,0 +1,29 @@
+#![crate_type = "lib"]
+#![feature(transmutability)]
+#![allow(dead_code)]
+
+mod assert {
+    use std::mem::{Assume, BikeshedIntrinsicFrom};
+    pub struct Context;
+
+    pub fn is_maybe_transmutable<Src, Dst>()
+    where
+        Dst: BikeshedIntrinsicFrom<
+            Src,
+            Context,
+            { Assume { alignment: true, lifetimes: true, safety: true, validity: true } },
+        >,
+    {
+    }
+}
+
+fn test() {
+    #[repr(C, align(2))]
+    struct A(u8, u8);
+
+    #[repr(C)]
+    struct B(u8, u8);
+
+    assert::is_maybe_transmutable::<B, A>();
+    //~^ ERROR cannot be safely transmuted
+}
diff --git a/src/test/ui/transmute/transmute-padding-ice.stderr b/src/test/ui/transmute/transmute-padding-ice.stderr
new file mode 100644
index 00000000000..c9233890f7a
--- /dev/null
+++ b/src/test/ui/transmute/transmute-padding-ice.stderr
@@ -0,0 +1,24 @@
+error[E0277]: `B` cannot be safely transmuted into `A` in the defining scope of `assert::Context`.
+  --> $DIR/transmute-padding-ice.rs:27:40
+   |
+LL |     assert::is_maybe_transmutable::<B, A>();
+   |                                        ^ `B` cannot be safely transmuted into `A` in the defining scope of `assert::Context`.
+   |
+   = help: the trait `BikeshedIntrinsicFrom<B, assert::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `A`
+note: required by a bound in `is_maybe_transmutable`
+  --> $DIR/transmute-padding-ice.rs:11:14
+   |
+LL |       pub fn is_maybe_transmutable<Src, Dst>()
+   |              --------------------- required by a bound in this
+LL |       where
+LL |           Dst: BikeshedIntrinsicFrom<
+   |  ______________^
+LL | |             Src,
+LL | |             Context,
+LL | |             { Assume { alignment: true, lifetimes: true, safety: true, validity: true } },
+LL | |         >,
+   | |_________^ required by this bound in `is_maybe_transmutable`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/issues/issue-10969.rs b/src/test/ui/typeck/issue-10969.rs
index 0b78fc1bb7f..0b78fc1bb7f 100644
--- a/src/test/ui/issues/issue-10969.rs
+++ b/src/test/ui/typeck/issue-10969.rs
diff --git a/src/test/ui/issues/issue-10969.stderr b/src/test/ui/typeck/issue-10969.stderr
index f64b61aaeb0..f64b61aaeb0 100644
--- a/src/test/ui/issues/issue-10969.stderr
+++ b/src/test/ui/typeck/issue-10969.stderr
diff --git a/src/test/ui/issues/issue-50687-ice-on-borrow.rs b/src/test/ui/typeck/issue-50687-ice-on-borrow.rs
index 7a8a12c2a93..7a8a12c2a93 100644
--- a/src/test/ui/issues/issue-50687-ice-on-borrow.rs
+++ b/src/test/ui/typeck/issue-50687-ice-on-borrow.rs
diff --git a/src/test/ui/issues/issue-50687-ice-on-borrow.stderr b/src/test/ui/typeck/issue-50687-ice-on-borrow.stderr
index e6a0edac4b1..e6a0edac4b1 100644
--- a/src/test/ui/issues/issue-50687-ice-on-borrow.stderr
+++ b/src/test/ui/typeck/issue-50687-ice-on-borrow.stderr
diff --git a/src/test/ui/typeck/issue-83693.stderr b/src/test/ui/typeck/issue-83693.stderr
index 0d8bbf1ce98..1e45c2d35df 100644
--- a/src/test/ui/typeck/issue-83693.stderr
+++ b/src/test/ui/typeck/issue-83693.stderr
@@ -6,8 +6,8 @@ LL | impl F {
    |
   ::: $SRC_DIR/core/src/ops/function.rs:LL:COL
    |
-LL | pub trait Fn<Args>: FnMut<Args> {
-   | ------------------------------- similarly named trait `Fn` defined here
+LL | pub trait Fn<Args: Tuple>: FnMut<Args> {
+   | -------------------------------------- similarly named trait `Fn` defined here
 
 error[E0412]: cannot find type `TestResult` in this scope
   --> $DIR/issue-83693.rs:9:22
diff --git a/src/test/ui/unboxed-closures/non-tupled-arg-mismatch.rs b/src/test/ui/unboxed-closures/non-tupled-arg-mismatch.rs
index 925463d6dee..d2e48600227 100644
--- a/src/test/ui/unboxed-closures/non-tupled-arg-mismatch.rs
+++ b/src/test/ui/unboxed-closures/non-tupled-arg-mismatch.rs
@@ -1,8 +1,8 @@
 #![feature(unboxed_closures)]
 
 fn a<F: Fn<usize>>(f: F) {}
+//~^ ERROR type parameter to bare `Fn` trait must be a tuple
 
 fn main() {
     a(|_: usize| {});
-    //~^ ERROR mismatched types
 }
diff --git a/src/test/ui/unboxed-closures/non-tupled-arg-mismatch.stderr b/src/test/ui/unboxed-closures/non-tupled-arg-mismatch.stderr
index 9a24fb8c2be..1c18eb0fc49 100644
--- a/src/test/ui/unboxed-closures/non-tupled-arg-mismatch.stderr
+++ b/src/test/ui/unboxed-closures/non-tupled-arg-mismatch.stderr
@@ -1,17 +1,15 @@
-error[E0308]: mismatched types
-  --> $DIR/non-tupled-arg-mismatch.rs:6:5
-   |
-LL |     a(|_: usize| {});
-   |     ^ types differ
-   |
-   = note: expected trait `Fn<usize>`
-              found trait `Fn<(usize,)>`
-note: required by a bound in `a`
+error[E0059]: type parameter to bare `Fn` trait must be a tuple
   --> $DIR/non-tupled-arg-mismatch.rs:3:9
    |
 LL | fn a<F: Fn<usize>>(f: F) {}
-   |         ^^^^^^^^^ required by this bound in `a`
+   |         ^^^^^^^^^ the trait `Tuple` is not implemented for `usize`
+   |
+note: required by a bound in `Fn`
+  --> $SRC_DIR/core/src/ops/function.rs:LL:COL
+   |
+LL | pub trait Fn<Args: Tuple>: FnMut<Args> {
+   |                    ^^^^^ required by this bound in `Fn`
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0308`.
+For more information about this error, try `rustc --explain E0059`.
diff --git a/src/test/ui/unboxed-closures/unboxed-closure-illegal-move.rs b/src/test/ui/unboxed-closures/unboxed-closure-illegal-move.rs
index ed8d7211461..7377359b6b0 100644
--- a/src/test/ui/unboxed-closures/unboxed-closure-illegal-move.rs
+++ b/src/test/ui/unboxed-closures/unboxed-closure-illegal-move.rs
@@ -1,12 +1,12 @@
-#![feature(unboxed_closures)]
+#![feature(unboxed_closures, tuple_trait)]
 
 // Tests that we can't move out of an unboxed closure environment
 // if the upvar is captured by ref or the closure takes self by
 // reference.
 
-fn to_fn<A,F:Fn<A>>(f: F) -> F { f }
-fn to_fn_mut<A,F:FnMut<A>>(f: F) -> F { f }
-fn to_fn_once<A,F:FnOnce<A>>(f: F) -> F { f }
+fn to_fn<A:std::marker::Tuple,F:Fn<A>>(f: F) -> F { f }
+fn to_fn_mut<A:std::marker::Tuple,F:FnMut<A>>(f: F) -> F { f }
+fn to_fn_once<A:std::marker::Tuple,F:FnOnce<A>>(f: F) -> F { f }
 
 fn main() {
     // By-ref cases
diff --git a/src/test/ui/unboxed-closures/unboxed-closures-mutate-upvar.rs b/src/test/ui/unboxed-closures/unboxed-closures-mutate-upvar.rs
index 57e6d30658c..c57312b4387 100644
--- a/src/test/ui/unboxed-closures/unboxed-closures-mutate-upvar.rs
+++ b/src/test/ui/unboxed-closures/unboxed-closures-mutate-upvar.rs
@@ -2,12 +2,12 @@
 // as `mut` through a closure. Also test that we CAN mutate a moved copy,
 // unless this is a `Fn` closure. Issue #16749.
 
-#![feature(unboxed_closures)]
+#![feature(unboxed_closures, tuple_trait)]
 
 use std::mem;
 
-fn to_fn<A,F:Fn<A>>(f: F) -> F { f }
-fn to_fn_mut<A,F:FnMut<A>>(f: F) -> F { f }
+fn to_fn<A:std::marker::Tuple,F:Fn<A>>(f: F) -> F { f }
+fn to_fn_mut<A:std::marker::Tuple,F:FnMut<A>>(f: F) -> F { f }
 
 fn a() {
     let n = 0;
diff --git a/src/test/ui/unboxed-closures/unboxed-closures-mutate-upvar.stderr b/src/test/ui/unboxed-closures/unboxed-closures-mutate-upvar.stderr
index d6e74b5b8b9..26f97b51913 100644
--- a/src/test/ui/unboxed-closures/unboxed-closures-mutate-upvar.stderr
+++ b/src/test/ui/unboxed-closures/unboxed-closures-mutate-upvar.stderr
@@ -28,8 +28,8 @@ LL |         n += 1;
 error[E0594]: cannot assign to `n`, as it is a captured variable in a `Fn` closure
   --> $DIR/unboxed-closures-mutate-upvar.rs:53:9
    |
-LL | fn to_fn<A,F:Fn<A>>(f: F) -> F { f }
-   |                        - change this to accept `FnMut` instead of `Fn`
+LL | fn to_fn<A:std::marker::Tuple,F:Fn<A>>(f: F) -> F { f }
+   |                                           - change this to accept `FnMut` instead of `Fn`
 ...
 LL |     let mut f = to_fn(move || {
    |                 ----- ------- in this closure
diff --git a/src/test/ui/unboxed-closures/unboxed-closures-static-call-wrong-trait.rs b/src/test/ui/unboxed-closures/unboxed-closures-static-call-wrong-trait.rs
index 0e727b11cd2..7289d9322d0 100644
--- a/src/test/ui/unboxed-closures/unboxed-closures-static-call-wrong-trait.rs
+++ b/src/test/ui/unboxed-closures/unboxed-closures-static-call-wrong-trait.rs
@@ -1,6 +1,6 @@
-#![feature(unboxed_closures)]
+#![feature(unboxed_closures, tuple_trait)]
 
-fn to_fn_mut<A,F:FnMut<A>>(f: F) -> F { f }
+fn to_fn_mut<A:std::marker::Tuple,F:FnMut<A>>(f: F) -> F { f }
 
 fn main() {
     let mut_ = to_fn_mut(|x| x);
diff --git a/src/test/ui/weird-exprs.rs b/src/test/ui/weird-exprs.rs
index 4066bcf3bad..d65703ef5ca 100644
--- a/src/test/ui/weird-exprs.rs
+++ b/src/test/ui/weird-exprs.rs
@@ -8,6 +8,7 @@
 #![allow(unreachable_code)]
 #![allow(unused_braces, unused_must_use, unused_parens)]
 #![allow(uncommon_codepoints, confusable_idents)]
+#![allow(unreachable_patterns)]
 
 #![recursion_limit = "256"]
 
@@ -194,6 +195,15 @@ fn bathroom_stall() {
     assert_eq!(i, 13);
 }
 
+fn closure_matching() {
+    let x = |_| Some(1);
+    let (|x| x) = match x(..) {
+        |_| Some(2) => |_| Some(3),
+        |_| _ => unreachable!(),
+    };
+    assert!(matches!(x(..), |_| Some(4)));
+}
+
 pub fn main() {
     strange();
     funny();
@@ -216,4 +226,5 @@ pub fn main() {
     𝚌𝚘𝚗𝚝𝚒𝚗𝚞𝚎();
     function();
     bathroom_stall();
+    closure_matching();
 }
diff --git a/src/tools/build-manifest/README.md b/src/tools/build-manifest/README.md
index 44c96f31d0b..9d30c554186 100644
--- a/src/tools/build-manifest/README.md
+++ b/src/tools/build-manifest/README.md
@@ -1,7 +1,16 @@
 # build-manifest
 
-This tool generates the manifests uploaded to static.rust-lang.org and used by
-rustup. The tool is invoked by the bootstrap tool.
+This tool generates the manifests uploaded to static.rust-lang.org and used by rustup.
+You can see a full list of all manifests at <https://static.rust-lang.org/manifests.txt>.
+This listing is updated by <https://github.com/rust-lang/generate-manifest-list> every 7 days.
+
+This gets called by `promote-release` <https://github.com/rust-lang/promote-release> via `x.py dist hash-and-sign`.
+
+## Adding a new component
+
+1. Add a new `Step` to `dist.rs`. This should usually be named after the filename of the uploaded tarball. See https://github.com/rust-lang/rust/pull/101799/files#diff-2c56335faa24486df09ba392d8900c57e2fac4633e1f7038469bcf9ed3feb871 for an example.
+    a. If appropriate, call `tarball.is_preview(true)` for the component.
+2. Add a new `PkgType` to build-manifest. Fix all the compile errors as appropriate.
 
 ## Testing changes locally
 
@@ -9,19 +18,16 @@ In order to test the changes locally you need to have a valid dist directory
 available locally. If you don't want to build all the compiler, you can easily
 create one from the nightly artifacts with:
 
-```
-#!/bin/bash
-for cmpn in rust rustc rust-std rust-docs cargo; do
-    wget https://static.rust-lang.org/dist/${cmpn}-nightly-x86_64-unknown-linux-gnu.tar.gz
+```sh
+for component in rust rustc rust-std rust-docs cargo; do
+    wget -P build/dist https://static.rust-lang.org/dist/${component}-nightly-x86_64-unknown-linux-gnu.tar.gz
 done
 ```
 
-Then, you can generate the manifest and all the packages from `path/to/dist` to
-`path/to/output` with:
+Then, you can generate the manifest and all the packages from `build/dist` to
+`build/manifest` with:
 
+```sh
+mkdir -p build/manifest
+cargo +nightly run --release -p build-manifest build/dist build/manifest 1970-01-01 http://example.com nightly
 ```
-$ cargo +nightly run path/to/dist path/to/output 1970-01-01 http://example.com CHANNEL
-```
-
-Remember to replace `CHANNEL` with the channel you produced dist artifacts of
-and `VERSION` with the current Rust version.
diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs
index b0006cb90bd..0551e835bb0 100644
--- a/src/tools/build-manifest/src/main.rs
+++ b/src/tools/build-manifest/src/main.rs
@@ -1,8 +1,4 @@
-//! Build a dist manifest, hash and sign everything.
-//! This gets called by `promote-release`
-//! (https://github.com/rust-lang/rust-central-station/tree/master/promote-release)
-//! via `x.py dist hash-and-sign`; the cmdline arguments are set up
-//! by rustbuild (in `src/bootstrap/dist.rs`).
+#![doc = include_str!("../README.md")]
 
 mod checksum;
 mod manifest;
@@ -64,6 +60,7 @@ static TARGETS: &[&str] = &[
     "aarch64-unknown-none",
     "aarch64-unknown-none-softfloat",
     "aarch64-unknown-redox",
+    "aarch64-unknown-uefi",
     "arm-linux-androideabi",
     "arm-unknown-linux-gnueabi",
     "arm-unknown-linux-gnueabihf",
@@ -99,6 +96,7 @@ static TARGETS: &[&str] = &[
     "i686-unknown-freebsd",
     "i686-unknown-linux-gnu",
     "i686-unknown-linux-musl",
+    "i686-unknown-uefi",
     "m68k-unknown-linux-gnu",
     "mips-unknown-linux-gnu",
     "mips-unknown-linux-musl",
@@ -155,6 +153,7 @@ static TARGETS: &[&str] = &[
     "x86_64-unknown-none",
     "x86_64-unknown-redox",
     "x86_64-unknown-hermit",
+    "x86_64-unknown-uefi",
 ];
 
 /// This allows the manifest to contain rust-docs for hosts that don't build
@@ -184,7 +183,7 @@ static PKG_INSTALLERS: &[&str] = &["x86_64-apple-darwin", "aarch64-apple-darwin"
 
 static MINGW: &[&str] = &["i686-pc-windows-gnu", "x86_64-pc-windows-gnu"];
 
-static NIGHTLY_ONLY_COMPONENTS: &[&str] = &["miri-preview", "rust-docs-json-preview"];
+static NIGHTLY_ONLY_COMPONENTS: &[PkgType] = &[PkgType::Miri, PkgType::JsonDocs];
 
 macro_rules! t {
     ($e:expr) => {
@@ -287,28 +286,9 @@ impl Builder {
     }
 
     fn add_packages_to(&mut self, manifest: &mut Manifest) {
-        macro_rules! package {
-            ($name:expr, $targets:expr) => {
-                self.package($name, &mut manifest.pkg, $targets, &[])
-            };
+        for pkg in PkgType::all() {
+            self.package(pkg, &mut manifest.pkg);
         }
-        package!("rustc", HOSTS);
-        package!("rustc-dev", HOSTS);
-        package!("reproducible-artifacts", HOSTS);
-        package!("rustc-docs", HOSTS);
-        package!("cargo", HOSTS);
-        package!("rust-mingw", MINGW);
-        package!("rust-std", TARGETS);
-        self.package("rust-docs", &mut manifest.pkg, HOSTS, DOCS_FALLBACK);
-        self.package("rust-docs-json-preview", &mut manifest.pkg, HOSTS, DOCS_FALLBACK);
-        package!("rust-src", &["*"]);
-        package!("rls-preview", HOSTS);
-        package!("rust-analyzer-preview", HOSTS);
-        package!("clippy-preview", HOSTS);
-        package!("miri-preview", HOSTS);
-        package!("rustfmt-preview", HOSTS);
-        package!("rust-analysis", TARGETS);
-        package!("llvm-tools-preview", TARGETS);
     }
 
     fn add_artifacts_to(&mut self, manifest: &mut Manifest) {
@@ -333,44 +313,28 @@ impl Builder {
     }
 
     fn add_profiles_to(&mut self, manifest: &mut Manifest) {
-        let mut profile = |name, pkgs| self.profile(name, &mut manifest.profiles, pkgs);
-        profile("minimal", &["rustc", "cargo", "rust-std", "rust-mingw"]);
-        profile(
-            "default",
-            &[
-                "rustc",
-                "cargo",
-                "rust-std",
-                "rust-mingw",
-                "rust-docs",
-                "rustfmt-preview",
-                "clippy-preview",
-            ],
-        );
-        profile(
-            "complete",
-            &[
-                "rustc",
-                "cargo",
-                "rust-std",
-                "rust-mingw",
-                "rust-docs",
-                "rustfmt-preview",
-                "clippy-preview",
-                "rls-preview",
-                "rust-analyzer-preview",
-                "rust-src",
-                "llvm-tools-preview",
-                "rust-analysis",
-                "miri-preview",
-            ],
-        );
+        use PkgType::*;
+
+        let mut profile = |name, pkgs: &_| self.profile(name, &mut manifest.profiles, pkgs);
+
+        // Use a Vec here to make sure we don't exclude any components in an earlier profile.
+        let minimal = vec![Rustc, Cargo, RustStd, RustMingw];
+        profile("minimal", &minimal);
+
+        let mut default = minimal;
+        default.extend([HtmlDocs, Rustfmt, Clippy]);
+        profile("default", &default);
+
+        // NOTE: this profile is effectively deprecated; do not add new components to it.
+        let mut complete = default;
+        complete.extend([Rls, RustAnalyzer, RustSrc, LlvmTools, RustAnalysis, Miri]);
+        profile("complete", &complete);
 
         // The compiler libraries are not stable for end users, and they're also huge, so we only
         // `rustc-dev` for nightly users, and only in the "complete" profile. It's still possible
         // for users to install the additional component manually, if needed.
         if self.versions.channel() == "nightly" {
-            self.extend_profile("complete", &mut manifest.profiles, &["rustc-dev"]);
+            self.extend_profile("complete", &mut manifest.profiles, &[RustcDev]);
             // Do not include the rustc-docs component for now, as it causes
             // conflicts with the rust-docs component when installed. See
             // #75833.
@@ -382,12 +346,11 @@ impl Builder {
         let mut rename = |from: &str, to: &str| {
             manifest.renames.insert(from.to_owned(), Rename { to: to.to_owned() })
         };
-        rename("rls", "rls-preview");
-        rename("rustfmt", "rustfmt-preview");
-        rename("clippy", "clippy-preview");
-        rename("miri", "miri-preview");
-        rename("rust-docs-json", "rust-docs-json-preview");
-        rename("rust-analyzer", "rust-analyzer-preview");
+        for pkg in PkgType::all() {
+            if pkg.is_preview() {
+                rename(pkg.tarball_component_name(), &pkg.manifest_component_name());
+            }
+        }
     }
 
     fn rust_package(&mut self, manifest: &Manifest) -> Package {
@@ -419,42 +382,52 @@ impl Builder {
         let mut components = Vec::new();
         let mut extensions = Vec::new();
 
-        let host_component = |pkg| Component::from_str(pkg, host);
-
-        // rustc/rust-std/cargo/docs are all required,
-        // and so is rust-mingw if it's available for the target.
-        components.extend(vec![
-            host_component("rustc"),
-            host_component("rust-std"),
-            host_component("cargo"),
-            host_component("rust-docs"),
-        ]);
-        if host.contains("pc-windows-gnu") {
-            components.push(host_component("rust-mingw"));
-        }
+        let host_component = |pkg: &_| Component::from_pkg(pkg, host);
 
-        // Tools are always present in the manifest,
-        // but might be marked as unavailable if they weren't built.
-        extensions.extend(vec![
-            host_component("clippy-preview"),
-            host_component("miri-preview"),
-            host_component("rls-preview"),
-            host_component("rust-analyzer-preview"),
-            host_component("rustfmt-preview"),
-            host_component("llvm-tools-preview"),
-            host_component("rust-analysis"),
-            host_component("rust-docs-json-preview"),
-        ]);
-
-        extensions.extend(
-            TARGETS
-                .iter()
-                .filter(|&&target| target != host)
-                .map(|target| Component::from_str("rust-std", target)),
-        );
-        extensions.extend(HOSTS.iter().map(|target| Component::from_str("rustc-dev", target)));
-        extensions.extend(HOSTS.iter().map(|target| Component::from_str("rustc-docs", target)));
-        extensions.push(Component::from_str("rust-src", "*"));
+        for pkg in PkgType::all() {
+            match pkg {
+                // rustc/rust-std/cargo/docs are all required
+                PkgType::Rustc | PkgType::Cargo | PkgType::HtmlDocs => {
+                    components.push(host_component(pkg));
+                }
+                PkgType::RustStd => {
+                    components.push(host_component(pkg));
+                    extensions.extend(
+                        TARGETS
+                            .iter()
+                            .filter(|&&target| target != host)
+                            .map(|target| Component::from_pkg(pkg, target)),
+                    );
+                }
+                // so is rust-mingw if it's available for the target
+                PkgType::RustMingw => {
+                    if host.contains("pc-windows-gnu") {
+                        components.push(host_component(pkg));
+                    }
+                }
+                // Tools are always present in the manifest,
+                // but might be marked as unavailable if they weren't built.
+                PkgType::Clippy
+                | PkgType::Miri
+                | PkgType::Rls
+                | PkgType::RustAnalyzer
+                | PkgType::Rustfmt
+                | PkgType::LlvmTools
+                | PkgType::RustAnalysis
+                | PkgType::JsonDocs => {
+                    extensions.push(host_component(pkg));
+                }
+                PkgType::RustcDev | PkgType::RustcDocs => {
+                    extensions.extend(HOSTS.iter().map(|target| Component::from_pkg(pkg, target)));
+                }
+                PkgType::RustSrc => {
+                    extensions.push(Component::from_pkg(pkg, "*"));
+                }
+                PkgType::Rust => {}
+                // NOTE: this is intentional, these artifacts aren't intended to be used with rustup
+                PkgType::ReproducibleArtifacts => {}
+            }
+        }
 
         // If the components/extensions don't actually exist for this
         // particular host/target combination then nix it entirely from our
@@ -481,43 +454,44 @@ impl Builder {
         &mut self,
         profile_name: &str,
         dst: &mut BTreeMap<String, Vec<String>>,
-        pkgs: &[&str],
+        pkgs: &[PkgType],
     ) {
-        dst.insert(profile_name.to_owned(), pkgs.iter().map(|s| (*s).to_owned()).collect());
+        dst.insert(
+            profile_name.to_owned(),
+            pkgs.iter().map(|s| s.manifest_component_name()).collect(),
+        );
     }
 
     fn extend_profile(
         &mut self,
         profile_name: &str,
         dst: &mut BTreeMap<String, Vec<String>>,
-        pkgs: &[&str],
+        pkgs: &[PkgType],
     ) {
         dst.get_mut(profile_name)
             .expect("existing profile")
-            .extend(pkgs.iter().map(|s| (*s).to_owned()));
+            .extend(pkgs.iter().map(|s| s.manifest_component_name()));
     }
 
-    fn package(
-        &mut self,
-        pkgname: &str,
-        dst: &mut BTreeMap<String, Package>,
-        targets: &[&str],
-        fallback: &[(&str, &str)],
-    ) {
-        let version_info = self
-            .versions
-            .version(&PkgType::from_component(pkgname))
-            .expect("failed to load package version");
+    fn package(&mut self, pkg: &PkgType, dst: &mut BTreeMap<String, Package>) {
+        if *pkg == PkgType::Rust {
+            // This is handled specially by `rust_package` later.
+            // Order is important, so don't call `rust_package` here.
+            return;
+        }
+
+        let fallback = if pkg.use_docs_fallback() { DOCS_FALLBACK } else { &[] };
+        let version_info = self.versions.version(&pkg).expect("failed to load package version");
         let mut is_present = version_info.present;
 
         // Never ship nightly-only components for other trains.
-        if self.versions.channel() != "nightly" && NIGHTLY_ONLY_COMPONENTS.contains(&pkgname) {
+        if self.versions.channel() != "nightly" && NIGHTLY_ONLY_COMPONENTS.contains(&pkg) {
             is_present = false; // Pretend the component is entirely missing.
         }
 
         macro_rules! tarball_name {
             ($target_name:expr) => {
-                self.versions.tarball_name(&PkgType::from_component(pkgname), $target_name).unwrap()
+                self.versions.tarball_name(pkg, $target_name).unwrap()
             };
         }
         let mut target_from_compressed_tar = |target_name| {
@@ -546,7 +520,8 @@ impl Builder {
             Target::unavailable()
         };
 
-        let targets = targets
+        let targets = pkg
+            .targets()
             .iter()
             .map(|name| {
                 let target = if is_present {
@@ -561,7 +536,7 @@ impl Builder {
             .collect();
 
         dst.insert(
-            pkgname.to_string(),
+            pkg.manifest_component_name(),
             Package {
                 version: version_info.version.unwrap_or_default(),
                 git_commit_hash: version_info.git_commit,
diff --git a/src/tools/build-manifest/src/manifest.rs b/src/tools/build-manifest/src/manifest.rs
index 547c270d89a..a9f19d8e565 100644
--- a/src/tools/build-manifest/src/manifest.rs
+++ b/src/tools/build-manifest/src/manifest.rs
@@ -1,3 +1,4 @@
+use crate::versions::PkgType;
 use crate::Builder;
 use serde::{Serialize, Serializer};
 use std::collections::BTreeMap;
@@ -116,8 +117,8 @@ pub(crate) struct Component {
 }
 
 impl Component {
-    pub(crate) fn from_str(pkg: &str, target: &str) -> Self {
-        Self { pkg: pkg.to_string(), target: target.to_string() }
+    pub(crate) fn from_pkg(pkg: &PkgType, target: &str) -> Self {
+        Self { pkg: pkg.manifest_component_name(), target: target.to_string() }
     }
 }
 
diff --git a/src/tools/build-manifest/src/versions.rs b/src/tools/build-manifest/src/versions.rs
index 0186194a41f..dde9745afb7 100644
--- a/src/tools/build-manifest/src/versions.rs
+++ b/src/tools/build-manifest/src/versions.rs
@@ -8,55 +8,63 @@ use tar::Archive;
 
 const DEFAULT_TARGET: &str = "x86_64-unknown-linux-gnu";
 
-#[derive(Debug, Hash, Eq, PartialEq, Clone)]
-pub(crate) enum PkgType {
-    Rust,
-    RustSrc,
-    Rustc,
-    Cargo,
-    Rls,
-    RustAnalyzer,
-    Clippy,
-    Rustfmt,
-    LlvmTools,
-    Miri,
-    JsonDocs,
-    Other(String),
-}
+macro_rules! pkg_type {
+    ( $($variant:ident = $component:literal $(; preview = true $(@$is_preview:tt)? )? ),+ $(,)? ) => {
+        #[derive(Debug, Hash, Eq, PartialEq, Clone)]
+        pub(crate) enum PkgType {
+            $($variant,)+
+        }
 
-impl PkgType {
-    pub(crate) fn from_component(component: &str) -> Self {
-        match component {
-            "rust" => PkgType::Rust,
-            "rust-src" => PkgType::RustSrc,
-            "rustc" => PkgType::Rustc,
-            "cargo" => PkgType::Cargo,
-            "rls" | "rls-preview" => PkgType::Rls,
-            "rust-analyzer" | "rust-analyzer-preview" => PkgType::RustAnalyzer,
-            "clippy" | "clippy-preview" => PkgType::Clippy,
-            "rustfmt" | "rustfmt-preview" => PkgType::Rustfmt,
-            "llvm-tools" | "llvm-tools-preview" => PkgType::LlvmTools,
-            "miri" | "miri-preview" => PkgType::Miri,
-            "rust-docs-json" | "rust-docs-json-preview" => PkgType::JsonDocs,
-            other => PkgType::Other(other.into()),
+        impl PkgType {
+            pub(crate) fn is_preview(&self) -> bool {
+                match self {
+                    $( $( $($is_preview)? PkgType::$variant => true, )? )+
+                    _ => false,
+                }
+            }
+
+            /// First part of the tarball name.
+            pub(crate) fn tarball_component_name(&self) -> &str {
+                match self {
+                    $( PkgType::$variant => $component,)+
+                }
+            }
+
+            pub(crate) fn all() -> &'static [PkgType] {
+                &[ $(PkgType::$variant),+ ]
+            }
         }
     }
+}
 
-    /// First part of the tarball name.
-    fn tarball_component_name(&self) -> &str {
-        match self {
-            PkgType::Rust => "rust",
-            PkgType::RustSrc => "rust-src",
-            PkgType::Rustc => "rustc",
-            PkgType::Cargo => "cargo",
-            PkgType::Rls => "rls",
-            PkgType::RustAnalyzer => "rust-analyzer",
-            PkgType::Clippy => "clippy",
-            PkgType::Rustfmt => "rustfmt",
-            PkgType::LlvmTools => "llvm-tools",
-            PkgType::Miri => "miri",
-            PkgType::JsonDocs => "rust-docs-json",
-            PkgType::Other(component) => component,
+pkg_type! {
+    Rust = "rust",
+    RustSrc = "rust-src",
+    Rustc = "rustc",
+    RustcDev = "rustc-dev",
+    RustcDocs = "rustc-docs",
+    ReproducibleArtifacts = "reproducible-artifacts",
+    RustMingw = "rust-mingw",
+    RustStd = "rust-std",
+    Cargo = "cargo",
+    HtmlDocs = "rust-docs",
+    RustAnalysis = "rust-analysis",
+    Rls = "rls"; preview = true,
+    RustAnalyzer = "rust-analyzer"; preview = true,
+    Clippy = "clippy"; preview = true,
+    Rustfmt = "rustfmt"; preview = true,
+    LlvmTools = "llvm-tools"; preview = true,
+    Miri = "miri"; preview = true,
+    JsonDocs = "rust-docs-json"; preview = true,
+}
+
+impl PkgType {
+    /// Component name in the manifest. In particular, this includes the `-preview` suffix where appropriate.
+    pub(crate) fn manifest_component_name(&self) -> String {
+        if self.is_preview() {
+            format!("{}-preview", self.tarball_component_name())
+        } else {
+            self.tarball_component_name().to_string()
         }
     }
 
@@ -73,10 +81,42 @@ impl PkgType {
             PkgType::Miri => false,
 
             PkgType::Rust => true,
+            PkgType::RustStd => true,
             PkgType::RustSrc => true,
             PkgType::Rustc => true,
             PkgType::JsonDocs => true,
-            PkgType::Other(_) => true,
+            PkgType::HtmlDocs => true,
+            PkgType::RustcDev => true,
+            PkgType::RustcDocs => true,
+            PkgType::ReproducibleArtifacts => true,
+            PkgType::RustMingw => true,
+            PkgType::RustAnalysis => true,
+        }
+    }
+
+    pub(crate) fn targets(&self) -> &[&str] {
+        use crate::{HOSTS, MINGW, TARGETS};
+        use PkgType::*;
+
+        match self {
+            Rust => HOSTS, // doesn't matter in practice, but return something to avoid panicking
+            Rustc => HOSTS,
+            RustcDev => HOSTS,
+            ReproducibleArtifacts => HOSTS,
+            RustcDocs => HOSTS,
+            Cargo => HOSTS,
+            RustMingw => MINGW,
+            RustStd => TARGETS,
+            HtmlDocs => HOSTS,
+            JsonDocs => HOSTS,
+            RustSrc => &["*"],
+            Rls => HOSTS,
+            RustAnalyzer => HOSTS,
+            Clippy => HOSTS,
+            Miri => HOSTS,
+            Rustfmt => HOSTS,
+            RustAnalysis => TARGETS,
+            LlvmTools => TARGETS,
         }
     }
 
@@ -84,6 +124,14 @@ impl PkgType {
     fn target_independent(&self) -> bool {
         *self == PkgType::RustSrc
     }
+
+    /// Whether to package these target-specific docs for another similar target.
+    pub(crate) fn use_docs_fallback(&self) -> bool {
+        match self {
+            PkgType::JsonDocs | PkgType::HtmlDocs => true,
+            _ => false,
+        }
+    }
 }
 
 #[derive(Debug, Default, Clone)]
diff --git a/src/tools/clippy/tests/ui/crashes/ice-6250.stderr b/src/tools/clippy/tests/ui/crashes/ice-6250.stderr
index 878897c410c..4506d1550bd 100644
--- a/src/tools/clippy/tests/ui/crashes/ice-6250.stderr
+++ b/src/tools/clippy/tests/ui/crashes/ice-6250.stderr
@@ -23,6 +23,11 @@ error[E0308]: mismatched types
    |
 LL |         Some(reference) = cache.data.get(key) {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found `()`
+   |
+help: consider adding `let`
+   |
+LL |         let Some(reference) = cache.data.get(key) {
+   |         +++
 
 error: aborting due to 3 previous errors
 
diff --git a/src/tools/linkchecker/main.rs b/src/tools/linkchecker/main.rs
index 7842611bd4f..4170c32f1fe 100644
--- a/src/tools/linkchecker/main.rs
+++ b/src/tools/linkchecker/main.rs
@@ -55,30 +55,6 @@ const LINKCHECK_EXCEPTIONS: &[(&str, &[&str])] = &[
 
 #[rustfmt::skip]
 const INTRA_DOC_LINK_EXCEPTIONS: &[(&str, &[&str])] = &[
-    // This will never have links that are not in other pages.
-    // To avoid repeating the exceptions twice, an empty list means all broken links are allowed.
-    ("reference/print.html", &[]),
-    // All the reference 'links' are actually ENBF highlighted as code
-    ("reference/comments.html", &[
-         "/</code> <code>!",
-         "*</code> <code>!",
-    ]),
-    ("reference/identifiers.html", &[
-         "a</code>-<code>z</code> <code>A</code>-<code>Z",
-         "a</code>-<code>z</code> <code>A</code>-<code>Z</code> <code>0</code>-<code>9</code> <code>_",
-         "a</code>-<code>z</code> <code>A</code>-<code>Z</code>] [<code>a</code>-<code>z</code> <code>A</code>-<code>Z</code> <code>0</code>-<code>9</code> <code>_",
-    ]),
-    ("reference/tokens.html", &[
-         "0</code>-<code>1",
-         "0</code>-<code>7",
-         "0</code>-<code>9",
-         "0</code>-<code>9",
-         "0</code>-<code>9</code> <code>a</code>-<code>f</code> <code>A</code>-<code>F",
-    ]),
-    ("reference/notation.html", &[
-         "b</code> <code>B",
-         "a</code>-<code>z",
-    ]),
     // This is being used in the sense of 'inclusive range', not a markdown link
     ("core/ops/struct.RangeInclusive.html", &["begin</code>, <code>end"]),
     ("std/ops/struct.RangeInclusive.html", &["begin</code>, <code>end"]),
@@ -365,6 +341,33 @@ impl Checker {
             }
         });
 
+        self.check_intra_doc_links(file, &pretty_path, &source, report);
+
+        // we don't need the source anymore,
+        // so drop to reduce memory-usage
+        match self.cache.get_mut(&pretty_path).unwrap() {
+            FileEntry::HtmlFile { source, .. } => *source = Rc::new(String::new()),
+            _ => unreachable!("must be html file"),
+        }
+    }
+
+    fn check_intra_doc_links(
+        &mut self,
+        file: &Path,
+        pretty_path: &str,
+        source: &str,
+        report: &mut Report,
+    ) {
+        let relative = file.strip_prefix(&self.root).expect("should always be relative to root");
+        // Don't check the reference. It has several legitimate things that
+        // look like [<code>…</code>]. The reference has its own broken link
+        // checker in its CI which handles this using pulldown_cmark.
+        //
+        // This checks both the end of the root (when checking just the
+        // reference directory) or the beginning (when checking all docs).
+        if self.root.ends_with("reference") || relative.starts_with("reference") {
+            return;
+        }
         // Search for intra-doc links that rustdoc didn't warn about
         // FIXME(#77199, 77200) Rustdoc should just warn about these directly.
         // NOTE: only looks at one line at a time; in practice this should find most links
@@ -379,12 +382,6 @@ impl Checker {
                 }
             }
         }
-        // we don't need the source anymore,
-        // so drop to reduce memory-usage
-        match self.cache.get_mut(&pretty_path).unwrap() {
-            FileEntry::HtmlFile { source, .. } => *source = Rc::new(String::new()),
-            _ => unreachable!("must be html file"),
-        }
     }
 
     /// Load a file from disk, or from the cache if available.
diff --git a/src/tools/miri/src/lib.rs b/src/tools/miri/src/lib.rs
index 3b73d05907b..8028ce75354 100644
--- a/src/tools/miri/src/lib.rs
+++ b/src/tools/miri/src/lib.rs
@@ -3,7 +3,6 @@
 #![feature(never_type)]
 #![feature(try_blocks)]
 #![feature(io_error_more)]
-#![feature(int_log)]
 #![feature(variant_count)]
 #![feature(yeet_expr)]
 #![feature(is_some_and)]
diff --git a/src/tools/miri/tests/pass/integer-ops.rs b/src/tools/miri/tests/pass/integer-ops.rs
index 724be9efc9f..0ec1f8e9c69 100644
--- a/src/tools/miri/tests/pass/integer-ops.rs
+++ b/src/tools/miri/tests/pass/integer-ops.rs
@@ -1,5 +1,4 @@
 //@compile-flags: -Coverflow-checks=off
-#![feature(int_log)]
 #![allow(arithmetic_overflow)]
 
 pub fn main() {
diff --git a/src/tools/rust-analyzer/crates/syntax/src/validation.rs b/src/tools/rust-analyzer/crates/syntax/src/validation.rs
index b9f2b513235..1eea2346451 100644
--- a/src/tools/rust-analyzer/crates/syntax/src/validation.rs
+++ b/src/tools/rust-analyzer/crates/syntax/src/validation.rs
@@ -5,9 +5,7 @@
 mod block;
 
 use rowan::Direction;
-use rustc_lexer::unescape::{
-    self, unescape_byte, unescape_byte_literal, unescape_char, unescape_literal, Mode,
-};
+use rustc_lexer::unescape::{self, unescape_byte, unescape_char, unescape_literal, Mode};
 
 use crate::{
     algo,
@@ -143,7 +141,7 @@ fn validate_literal(literal: ast::Literal, acc: &mut Vec<SyntaxError>) {
         ast::LiteralKind::ByteString(s) => {
             if !s.is_raw() {
                 if let Some(without_quotes) = unquote(text, 2, '"') {
-                    unescape_byte_literal(without_quotes, Mode::ByteStr, &mut |range, char| {
+                    unescape_literal(without_quotes, Mode::ByteStr, &mut |range, char| {
                         if let Err(err) = char {
                             push_err(2, (range.start, err));
                         }
diff --git a/src/tools/rustdoc-js/tester.js b/src/tools/rustdoc-js/tester.js
index df3185758bf..3da4fed33e1 100644
--- a/src/tools/rustdoc-js/tester.js
+++ b/src/tools/rustdoc-js/tester.js
@@ -307,10 +307,13 @@ function runChecks(testFile, doSearch, parseQuery) {
  *   `parseQuery` function exported from the search module.
  */
 function loadSearchJS(doc_folder, resource_suffix) {
-    const searchJs = path.join(doc_folder, "search" + resource_suffix + ".js");
     const searchIndexJs = path.join(doc_folder, "search-index" + resource_suffix + ".js");
     const searchIndex = require(searchIndexJs);
-    const searchModule = require(searchJs);
+
+    const staticFiles = path.join(doc_folder, "static.files");
+    const searchJs = fs.readdirSync(staticFiles).find(
+        f => f.match(/search.*\.js$/));
+    const searchModule = require(path.join(staticFiles, searchJs));
     const searchWords = searchModule.initSearch(searchIndex.searchIndex);
 
     return {
diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs
index aee36f061c5..2b82e9b3f99 100644
--- a/src/tools/tidy/src/ui_tests.rs
+++ b/src/tools/tidy/src/ui_tests.rs
@@ -9,8 +9,8 @@ use std::path::Path;
 
 const ENTRY_LIMIT: usize = 1000;
 // FIXME: The following limits should be reduced eventually.
-const ROOT_ENTRY_LIMIT: usize = 941;
-const ISSUES_ENTRY_LIMIT: usize = 2117;
+const ROOT_ENTRY_LIMIT: usize = 939;
+const ISSUES_ENTRY_LIMIT: usize = 2105;
 
 fn check_entries(path: &Path, bad: &mut bool) {
     for dir in Walk::new(&path.join("test/ui")) {
diff --git a/triagebot.toml b/triagebot.toml
index 202f9cad57a..d3f9efcc41c 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -12,6 +12,7 @@ allow-unauthenticated = [
     "T-*",
     "WG-*",
     "const-hack",
+    "llvm-main",
     "needs-fcp",
     "relnotes",
     "requires-nightly",