about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock539
-rw-r--r--Cargo.toml1
-rw-r--r--compiler/rustc_ast/src/ast.rs6
-rw-r--r--compiler/rustc_ast/src/ast_traits.rs4
-rw-r--r--compiler/rustc_ast/src/attr/mod.rs2
-rw-r--r--compiler/rustc_ast/src/expand/allocator.rs4
-rw-r--r--compiler/rustc_ast/src/token.rs14
-rw-r--r--compiler/rustc_ast/src/tokenstream.rs3
-rw-r--r--compiler/rustc_ast/src/util/literal.rs10
-rw-r--r--compiler/rustc_ast_lowering/src/asm.rs4
-rw-r--r--compiler/rustc_ast_lowering/src/item.rs2
-rw-r--r--compiler/rustc_ast_lowering/src/lib.rs8
-rw-r--r--compiler/rustc_ast_pretty/src/pprust/state.rs16
-rw-r--r--compiler/rustc_ast_pretty/src/pprust/state/item.rs4
-rw-r--r--compiler/rustc_attr/src/builtin.rs4
-rw-r--r--compiler/rustc_attr/src/session_diagnostics.rs2
-rw-r--r--compiler/rustc_borrowck/src/borrowck_errors.rs7
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs68
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs12
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs29
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/region_errors.rs82
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/region_name.rs2
-rw-r--r--compiler/rustc_borrowck/src/lib.rs48
-rw-r--r--compiler/rustc_builtin_macros/src/format.rs2
-rw-r--r--compiler/rustc_codegen_gcc/src/builder.rs2
-rw-r--r--compiler/rustc_codegen_gcc/src/context.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/abi.rs10
-rw-r--r--compiler/rustc_codegen_llvm/src/intrinsic.rs549
-rw-r--r--compiler/rustc_codegen_ssa/Cargo.toml1
-rw-r--r--compiler/rustc_codegen_ssa/src/back/link.rs181
-rw-r--r--compiler/rustc_codegen_ssa/src/back/write.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/base.rs16
-rw-r--r--compiler/rustc_codegen_ssa/src/common.rs6
-rw-r--r--compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs1
-rw-r--r--compiler/rustc_codegen_ssa/src/errors.rs437
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/constant.rs11
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/intrinsic.rs64
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/mod.rs2
-rw-r--r--compiler/rustc_data_structures/src/graph/dominators/mod.rs4
-rw-r--r--compiler/rustc_data_structures/src/graph/scc/mod.rs14
-rw-r--r--compiler/rustc_data_structures/src/obligation_forest/graphviz.rs4
-rw-r--r--compiler/rustc_data_structures/src/profiling.rs2
-rw-r--r--compiler/rustc_data_structures/src/small_c_str.rs6
-rw-r--r--compiler/rustc_data_structures/src/vec_map.rs3
-rw-r--r--compiler/rustc_driver/src/args.rs6
-rw-r--r--compiler/rustc_driver/src/lib.rs41
-rw-r--r--compiler/rustc_driver/src/pretty.rs6
-rw-r--r--compiler/rustc_error_codes/src/error_codes.rs3
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0015.md23
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0588.md2
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0729.md2
-rw-r--r--compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl101
-rw-r--r--compiler/rustc_error_messages/locales/en-US/infer.ftl139
-rw-r--r--compiler/rustc_error_messages/locales/en-US/session.ftl1
-rw-r--r--compiler/rustc_errors/Cargo.toml1
-rw-r--r--compiler/rustc_errors/src/diagnostic_builder.rs55
-rw-r--r--compiler/rustc_errors/src/diagnostic_impls.rs7
-rw-r--r--compiler/rustc_errors/src/lib.rs16
-rw-r--r--compiler/rustc_expand/src/mbe/diagnostics.rs25
-rw-r--r--compiler/rustc_expand/src/mbe/macro_parser.rs26
-rw-r--r--compiler/rustc_expand/src/mbe/macro_rules.rs60
-rw-r--r--compiler/rustc_feature/src/builtin_attrs.rs2
-rw-r--r--compiler/rustc_feature/src/lib.rs2
-rw-r--r--compiler/rustc_graphviz/src/lib.rs12
-rw-r--r--compiler/rustc_hir/src/def.rs3
-rw-r--r--compiler/rustc_hir/src/definitions.rs11
-rw-r--r--compiler/rustc_hir/src/hir.rs2
-rw-r--r--compiler/rustc_hir/src/hir_id.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/mod.rs124
-rw-r--r--compiler/rustc_hir_analysis/src/bounds.rs93
-rw-r--r--compiler/rustc_hir_analysis/src/check/compare_impl_item.rs36
-rw-r--r--compiler/rustc_hir_analysis/src/check/wfcheck.rs67
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/unsafety.rs6
-rw-r--r--compiler/rustc_hir_analysis/src/collect.rs151
-rw-r--r--compiler/rustc_hir_analysis/src/collect/generics_of.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/collect/item_bounds.rs10
-rw-r--r--compiler/rustc_hir_analysis/src/collect/lifetimes.rs8
-rw-r--r--compiler/rustc_hir_analysis/src/collect/predicates_of.rs11
-rw-r--r--compiler/rustc_hir_analysis/src/collect/type_of.rs8
-rw-r--r--compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs22
-rw-r--r--compiler/rustc_hir_pretty/src/lib.rs8
-rw-r--r--compiler/rustc_hir_typeck/src/_match.rs27
-rw-r--r--compiler/rustc_hir_typeck/src/callee.rs6
-rw-r--r--compiler/rustc_hir_typeck/src/closure.rs38
-rw-r--r--compiler/rustc_hir_typeck/src/coercion.rs6
-rw-r--r--compiler/rustc_hir_typeck/src/demand.rs301
-rw-r--r--compiler/rustc_hir_typeck/src/expr.rs17
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs4
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs37
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs34
-rw-r--r--compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/record_consumed_borrow.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/lib.rs11
-rw-r--r--compiler/rustc_hir_typeck/src/method/mod.rs11
-rw-r--r--compiler/rustc_hir_typeck/src/method/prelude2021.rs3
-rw-r--r--compiler/rustc_hir_typeck/src/method/probe.rs3
-rw-r--r--compiler/rustc_hir_typeck/src/method/suggest.rs1843
-rw-r--r--compiler/rustc_hir_typeck/src/pat.rs7
-rw-r--r--compiler/rustc_index/src/bit_set.rs2
-rw-r--r--compiler/rustc_index/src/interval.rs5
-rw-r--r--compiler/rustc_infer/src/errors/mod.rs421
-rw-r--r--compiler/rustc_infer/src/infer/at.rs12
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/mod.rs22
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mod.rs2
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/named_anon_conflict.rs43
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs311
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs396
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs74
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/note.rs37
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/suggest.rs71
-rw-r--r--compiler/rustc_infer/src/infer/mod.rs5
-rw-r--r--compiler/rustc_infer/src/infer/opaque_types.rs2
-rw-r--r--compiler/rustc_interface/src/interface.rs6
-rw-r--r--compiler/rustc_interface/src/passes.rs6
-rw-r--r--compiler/rustc_interface/src/tests.rs15
-rw-r--r--compiler/rustc_interface/src/util.rs13
-rw-r--r--compiler/rustc_lint/src/builtin.rs4
-rw-r--r--compiler/rustc_lint/src/early.rs2
-rw-r--r--compiler/rustc_lint/src/internal.rs2
-rw-r--r--compiler/rustc_lint/src/late.rs2
-rw-r--r--compiler/rustc_lint/src/nonstandard_style.rs3
-rw-r--r--compiler/rustc_lint/src/types.rs7
-rw-r--r--compiler/rustc_lint/src/unused.rs27
-rw-r--r--compiler/rustc_llvm/build.rs28
-rw-r--r--compiler/rustc_log/src/lib.rs3
-rw-r--r--compiler/rustc_macros/src/diagnostics/error.rs16
-rw-r--r--compiler/rustc_macros/src/diagnostics/fluent.rs4
-rw-r--r--compiler/rustc_macros/src/diagnostics/subdiagnostic.rs3
-rw-r--r--compiler/rustc_macros/src/diagnostics/utils.rs8
-rw-r--r--compiler/rustc_macros/src/newtype.rs4
-rw-r--r--compiler/rustc_macros/src/query.rs2
-rw-r--r--compiler/rustc_macros/src/symbols.rs6
-rw-r--r--compiler/rustc_macros/src/symbols/tests.rs3
-rw-r--r--compiler/rustc_metadata/src/creader.rs4
-rw-r--r--compiler/rustc_metadata/src/native_libs.rs2
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder.rs6
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs2
-rw-r--r--compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs2
-rw-r--r--compiler/rustc_metadata/src/rmeta/encoder.rs18
-rw-r--r--compiler/rustc_middle/src/hir/map/mod.rs38
-rw-r--r--compiler/rustc_middle/src/lint.rs2
-rw-r--r--compiler/rustc_middle/src/macros.rs18
-rw-r--r--compiler/rustc_middle/src/mir/mod.rs2
-rw-r--r--compiler/rustc_middle/src/mir/visit.rs8
-rw-r--r--compiler/rustc_middle/src/ty/erase_regions.rs2
-rw-r--r--compiler/rustc_middle/src/ty/error.rs2
-rw-r--r--compiler/rustc_middle/src/ty/flags.rs16
-rw-r--r--compiler/rustc_middle/src/ty/layout.rs65
-rw-r--r--compiler/rustc_middle/src/ty/visit.rs8
-rw-r--r--compiler/rustc_middle/src/util/bug.rs3
-rw-r--r--compiler/rustc_mir_build/src/check_unsafety.rs23
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/check_match.rs12
-rw-r--r--compiler/rustc_mir_dataflow/src/framework/direction.rs2
-rw-r--r--compiler/rustc_mir_dataflow/src/framework/fmt.rs4
-rw-r--r--compiler/rustc_mir_dataflow/src/framework/graphviz.rs18
-rw-r--r--compiler/rustc_mir_dataflow/src/move_paths/mod.rs6
-rw-r--r--compiler/rustc_mir_dataflow/src/value_analysis.rs2
-rw-r--r--compiler/rustc_mir_transform/src/dead_store_elimination.rs2
-rw-r--r--compiler/rustc_mir_transform/src/lib.rs10
-rw-r--r--compiler/rustc_mir_transform/src/simplify.rs15
-rw-r--r--compiler/rustc_monomorphize/Cargo.toml2
-rw-r--r--compiler/rustc_monomorphize/src/collector.rs2
-rw-r--r--compiler/rustc_monomorphize/src/errors.rs2
-rw-r--r--compiler/rustc_monomorphize/src/partitioning/mod.rs65
-rw-r--r--compiler/rustc_monomorphize/src/util.rs8
-rw-r--r--compiler/rustc_parse/src/parser/diagnostics.rs12
-rw-r--r--compiler/rustc_parse/src/parser/expr.rs13
-rw-r--r--compiler/rustc_parse_format/src/lib.rs8
-rw-r--r--compiler/rustc_privacy/src/lib.rs33
-rw-r--r--compiler/rustc_query_impl/Cargo.toml2
-rw-r--r--compiler/rustc_query_impl/src/on_disk_cache.rs2
-rw-r--r--compiler/rustc_query_impl/src/plumbing.rs2
-rw-r--r--compiler/rustc_query_impl/src/profiling_support.rs2
-rw-r--r--compiler/rustc_query_system/src/dep_graph/debug.rs4
-rw-r--r--compiler/rustc_query_system/src/dep_graph/dep_node.rs2
-rw-r--r--compiler/rustc_query_system/src/dep_graph/graph.rs22
-rw-r--r--compiler/rustc_query_system/src/dep_graph/serialized.rs13
-rw-r--r--compiler/rustc_query_system/src/query/plumbing.rs12
-rw-r--r--compiler/rustc_resolve/src/ident.rs9
-rw-r--r--compiler/rustc_resolve/src/late.rs27
-rw-r--r--compiler/rustc_save_analysis/src/lib.rs2
-rw-r--r--compiler/rustc_session/src/config.rs41
-rw-r--r--compiler/rustc_session/src/errors.rs13
-rw-r--r--compiler/rustc_session/src/options.rs38
-rw-r--r--compiler/rustc_session/src/session.rs14
-rw-r--r--compiler/rustc_span/src/def_id.rs2
-rw-r--r--compiler/rustc_span/src/edition.rs2
-rw-r--r--compiler/rustc_span/src/hygiene.rs16
-rw-r--r--compiler/rustc_span/src/lib.rs4
-rw-r--r--compiler/rustc_span/src/profiling.rs2
-rw-r--r--compiler/rustc_span/src/symbol.rs1
-rw-r--r--compiler/rustc_symbol_mangling/src/legacy.rs4
-rw-r--r--compiler/rustc_symbol_mangling/src/lib.rs3
-rw-r--r--compiler/rustc_symbol_mangling/src/test.rs2
-rw-r--r--compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs4
-rw-r--r--compiler/rustc_symbol_mangling/src/v0.rs5
-rw-r--r--compiler/rustc_target/src/abi/call/mod.rs15
-rw-r--r--compiler/rustc_target/src/asm/aarch64.rs2
-rw-r--r--compiler/rustc_target/src/asm/arm.rs2
-rw-r--r--compiler/rustc_target/src/asm/mod.rs14
-rw-r--r--compiler/rustc_target/src/asm/x86.rs30
-rw-r--r--compiler/rustc_target/src/spec/aarch64_unknown_fuchsia.rs (renamed from compiler/rustc_target/src/spec/aarch64_fuchsia.rs)2
-rw-r--r--compiler/rustc_target/src/spec/apple_base.rs10
-rw-r--r--compiler/rustc_target/src/spec/armv7_sony_vita_newlibeabihf.rs40
-rw-r--r--compiler/rustc_target/src/spec/mod.rs18
-rw-r--r--compiler/rustc_target/src/spec/solid_base.rs2
-rw-r--r--compiler/rustc_target/src/spec/x86_64_unknown_fuchsia.rs (renamed from compiler/rustc_target/src/spec/x86_64_fuchsia.rs)2
-rw-r--r--compiler/rustc_trait_selection/src/solve/overflow.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/engine.rs18
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs86
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs166
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/confirmation.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/mod.rs7
-rw-r--r--compiler/rustc_traits/src/dropck_outlives.rs4
-rw-r--r--compiler/rustc_traits/src/normalize_erasing_regions.rs2
-rw-r--r--compiler/rustc_transmute/src/layout/mod.rs2
-rw-r--r--compiler/rustc_ty_utils/src/abi.rs19
-rw-r--r--compiler/rustc_ty_utils/src/layout.rs36
-rw-r--r--compiler/rustc_ty_utils/src/ty.rs5
-rw-r--r--compiler/rustc_type_ir/src/lib.rs32
-rw-r--r--compiler/rustc_type_ir/src/sty.rs6
-rw-r--r--library/alloc/Cargo.toml4
-rw-r--r--library/alloc/benches/slice.rs4
-rw-r--r--library/alloc/src/alloc.rs15
-rw-r--r--library/alloc/src/boxed/thin.rs47
-rw-r--r--library/alloc/src/collections/binary_heap/tests.rs4
-rw-r--r--library/alloc/src/collections/linked_list/tests.rs13
-rw-r--r--library/alloc/src/collections/vec_deque/mod.rs10
-rw-r--r--library/alloc/src/lib.rs19
-rw-r--r--library/alloc/src/rc.rs2
-rw-r--r--library/alloc/src/slice.rs3
-rw-r--r--library/alloc/src/slice/tests.rs359
-rw-r--r--library/alloc/src/sync.rs2
-rw-r--r--library/alloc/src/vec/mod.rs5
-rw-r--r--library/alloc/tests/slice.rs349
-rw-r--r--library/core/Cargo.toml4
-rw-r--r--library/core/benches/num/int_log/mod.rs4
-rw-r--r--library/core/src/future/future.rs1
-rw-r--r--library/core/src/iter/sources/once_with.rs14
-rw-r--r--library/core/src/iter/sources/repeat_n.rs2
-rw-r--r--library/core/src/iter/sources/repeat_with.rs10
-rw-r--r--library/core/src/lib.rs3
-rw-r--r--library/core/src/macros/mod.rs43
-rw-r--r--library/core/src/marker.rs6
-rw-r--r--library/core/src/panicking.rs23
-rw-r--r--library/core/src/str/iter.rs185
-rw-r--r--library/core/tests/lib.rs13
-rw-r--r--library/core/tests/num/flt2dec/random.rs6
-rw-r--r--library/core/tests/slice.rs9
-rw-r--r--library/std/Cargo.toml3
-rw-r--r--library/std/src/alloc.rs2
-rw-r--r--library/std/src/collections/hash/map/tests.rs9
-rw-r--r--library/std/src/collections/hash/set.rs2
-rw-r--r--library/std/src/fs/tests.rs6
-rw-r--r--library/std/src/lib.rs29
-rw-r--r--library/std/src/macros.rs1
-rw-r--r--library/std/src/path.rs2
-rw-r--r--library/std/src/sync/rwlock/tests.rs4
-rw-r--r--library/std/src/sys_common/io.rs3
-rw-r--r--library/std/tests/env.rs20
-rw-r--r--library/test/src/console.rs6
-rw-r--r--library/test/src/formatters/json.rs18
-rw-r--r--library/test/src/formatters/junit.rs16
-rw-r--r--library/test/src/formatters/pretty.rs16
-rw-r--r--library/test/src/formatters/terse.rs20
-rw-r--r--library/test/src/lib.rs2
-rw-r--r--library/test/src/term/terminfo/mod.rs6
-rw-r--r--library/test/src/term/terminfo/parm.rs8
-rw-r--r--library/test/src/term/terminfo/searcher.rs4
-rw-r--r--library/test/src/test_result.rs4
-rw-r--r--library/test/src/types.rs2
-rw-r--r--src/bootstrap/Cargo.lock5
-rw-r--r--src/bootstrap/Cargo.toml1
-rw-r--r--src/bootstrap/bootstrap.py3
-rw-r--r--src/bootstrap/dist.rs3
-rw-r--r--src/bootstrap/download-ci-llvm-stamp2
-rw-r--r--src/bootstrap/format.rs78
-rw-r--r--src/bootstrap/lib.rs3
-rw-r--r--src/bootstrap/native.rs39
-rw-r--r--src/bootstrap/run.rs1
-rw-r--r--src/bootstrap/setup.rs4
-rw-r--r--src/bootstrap/util.rs46
-rw-r--r--src/ci/docker/host-x86_64/dist-various-2/Dockerfile36
-rwxr-xr-xsrc/ci/docker/host-x86_64/dist-various-2/build-fuchsia-toolchain.sh4
-rw-r--r--src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version2
-rwxr-xr-xsrc/ci/docker/scripts/fuchsia-test-runner.py6
-rw-r--r--src/doc/rustc/src/SUMMARY.md3
-rw-r--r--src/doc/rustc/src/platform-support.md5
-rw-r--r--src/doc/rustc/src/platform-support/armv7-sony-vita-eabihf.md127
-rw-r--r--src/doc/rustc/src/platform-support/fuchsia.md97
-rw-r--r--src/doc/unstable-book/src/compiler-flags/dump-mono-stats-format.md6
-rw-r--r--src/doc/unstable-book/src/compiler-flags/dump-mono-stats.md14
-rw-r--r--src/doc/unstable-book/src/compiler-flags/sanitizer.md4
-rwxr-xr-xsrc/etc/pre-push.sh2
-rw-r--r--src/librustdoc/clean/mod.rs2
-rw-r--r--src/librustdoc/clean/types.rs12
-rw-r--r--src/librustdoc/html/render/context.rs22
-rw-r--r--src/librustdoc/html/render/print_item.rs11
-rw-r--r--src/librustdoc/html/render/write_shared.rs62
-rw-r--r--src/librustdoc/html/sources.rs60
-rw-r--r--src/librustdoc/html/static/css/rustdoc.css25
-rw-r--r--src/librustdoc/html/static/js/main.js5
-rw-r--r--src/librustdoc/html/templates/page.html28
-rw-r--r--src/librustdoc/json/conversions.rs31
-rw-r--r--src/librustdoc/passes/check_doc_test_visibility.rs2
-rw-r--r--src/librustdoc/passes/stripper.rs1
-rw-r--r--src/librustdoc/visit_ast.rs2
-rw-r--r--src/test/assembly/stack-protector/stack-protector-target-support.rs4
-rw-r--r--src/test/codegen/box-maybe-uninit-llvm14.rs14
-rw-r--r--src/test/codegen/box-maybe-uninit.rs14
-rw-r--r--src/test/codegen/issue-86106.rs62
-rw-r--r--src/test/codegen/noalias-flag.rs23
-rw-r--r--src/test/codegen/zst-offset.rs9
-rw-r--r--src/test/incremental/hashes/closure_expressions.rs4
-rw-r--r--src/test/mir-opt/const_allocation.main.ConstProp.after.32bit.mir4
-rw-r--r--src/test/mir-opt/const_allocation.main.ConstProp.after.64bit.mir4
-rw-r--r--src/test/mir-opt/const_allocation.rs1
-rw-r--r--src/test/mir-opt/const_allocation2.main.ConstProp.after.32bit.mir4
-rw-r--r--src/test/mir-opt/const_allocation2.main.ConstProp.after.64bit.mir4
-rw-r--r--src/test/mir-opt/const_allocation2.rs1
-rw-r--r--src/test/mir-opt/const_allocation3.main.ConstProp.after.32bit.mir4
-rw-r--r--src/test/mir-opt/const_allocation3.main.ConstProp.after.64bit.mir4
-rw-r--r--src/test/mir-opt/const_allocation3.rs1
-rw-r--r--src/test/mir-opt/const_debuginfo.main.ConstDebugInfo.diff91
-rw-r--r--src/test/mir-opt/const_prop/bad_op_mod_by_zero.main.ConstProp.diff1
-rw-r--r--src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.32bit.diff40
-rw-r--r--src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.64bit.diff40
-rw-r--r--src/test/mir-opt/const_prop/control_flow_simplification.hello.ConstProp.diff1
-rw-r--r--src/test/mir-opt/const_prop/invalid_constant.main.ConstProp.diff19
-rw-r--r--src/test/mir-opt/const_prop/issue_66971.main.ConstProp.diff6
-rw-r--r--src/test/mir-opt/const_prop/issue_67019.main.ConstProp.diff1
-rw-r--r--src/test/mir-opt/const_prop/large_array_index.main.ConstProp.32bit.diff1
-rw-r--r--src/test/mir-opt/const_prop/large_array_index.main.ConstProp.64bit.diff1
-rw-r--r--src/test/mir-opt/const_prop/mutable_variable.main.ConstProp.diff1
-rw-r--r--src/test/mir-opt/const_prop/mutable_variable_aggregate.main.ConstProp.diff1
-rw-r--r--src/test/mir-opt/const_prop/mutable_variable_aggregate_mut_ref.main.ConstProp.diff1
-rw-r--r--src/test/mir-opt/const_prop/mutable_variable_aggregate_partial_read.main.ConstProp.diff1
-rw-r--r--src/test/mir-opt/const_prop/mutable_variable_no_prop.main.ConstProp.diff31
-rw-r--r--src/test/mir-opt/const_prop/mutable_variable_unprop_assign.main.ConstProp.diff48
-rw-r--r--src/test/mir-opt/const_prop/optimizes_into_variable.main.ConstProp.32bit.diff19
-rw-r--r--src/test/mir-opt/const_prop/optimizes_into_variable.main.ConstProp.64bit.diff19
-rw-r--r--src/test/mir-opt/const_prop/optimizes_into_variable.main.SimplifyLocals-final.after.32bit.mir (renamed from src/test/mir-opt/const_prop/optimizes_into_variable.main.SimplifyLocals.after.32bit.mir)2
-rw-r--r--src/test/mir-opt/const_prop/optimizes_into_variable.main.SimplifyLocals-final.after.64bit.mir (renamed from src/test/mir-opt/const_prop/optimizes_into_variable.main.SimplifyLocals.after.64bit.mir)2
-rw-r--r--src/test/mir-opt/const_prop/optimizes_into_variable.rs2
-rw-r--r--src/test/mir-opt/const_prop/read_immutable_static.main.ConstProp.diff1
-rw-r--r--src/test/mir-opt/const_prop/ref_deref.main.ConstProp.diff2
-rw-r--r--src/test/mir-opt/const_prop/ref_deref.main.PromoteTemps.diff2
-rw-r--r--src/test/mir-opt/const_prop/ref_deref.rs1
-rw-r--r--src/test/mir-opt/const_prop/ref_deref_project.rs2
-rw-r--r--src/test/mir-opt/const_prop/reify_fn_ptr.main.ConstProp.diff21
-rw-r--r--src/test/mir-opt/const_prop/repeat.main.ConstProp.32bit.diff1
-rw-r--r--src/test/mir-opt/const_prop/repeat.main.ConstProp.64bit.diff1
-rw-r--r--src/test/mir-opt/const_prop/scalar_literal_propagation.main.ConstProp.diff1
-rw-r--r--src/test/mir-opt/const_prop/slice_len.main.ConstProp.32bit.diff2
-rw-r--r--src/test/mir-opt/const_prop/slice_len.main.ConstProp.64bit.diff2
-rw-r--r--src/test/mir-opt/const_prop/slice_len.rs1
-rw-r--r--src/test/mir-opt/const_prop/tuple_literal_propagation.main.ConstProp.diff1
-rw-r--r--src/test/mir-opt/const_prop_miscompile.bar.ConstProp.diff33
-rw-r--r--src/test/mir-opt/const_prop_miscompile.foo.ConstProp.diff1
-rw-r--r--src/test/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.diff32
-rw-r--r--src/test/mir-opt/dead-store-elimination/cycle.cycle.DeadStoreElimination.diff8
-rw-r--r--src/test/mir-opt/dest-prop/dead_stores_better.f.DestinationPropagation.after.mir1
-rw-r--r--src/test/mir-opt/dest-prop/union.main.DestinationPropagation.diff3
-rw-r--r--src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.diff176
-rw-r--r--src/test/mir-opt/issue_76432.test.SimplifyComparisonIntegral.diff75
-rw-r--r--src/test/mir-opt/simplify_if.main.SimplifyConstCondition-after-const-prop.diff2
-rw-r--r--src/test/mir-opt/simplify_locals.c.SimplifyLocals-before-const-prop.diff (renamed from src/test/mir-opt/simplify_locals.c.SimplifyLocals.diff)4
-rw-r--r--src/test/mir-opt/simplify_locals.d1.SimplifyLocals-before-const-prop.diff (renamed from src/test/mir-opt/simplify_locals.d1.SimplifyLocals.diff)4
-rw-r--r--src/test/mir-opt/simplify_locals.d2.SimplifyLocals-before-const-prop.diff (renamed from src/test/mir-opt/simplify_locals.d2.SimplifyLocals.diff)4
-rw-r--r--src/test/mir-opt/simplify_locals.expose_addr.SimplifyLocals-before-const-prop.diff (renamed from src/test/mir-opt/simplify_locals.expose_addr.SimplifyLocals.diff)4
-rw-r--r--src/test/mir-opt/simplify_locals.r.SimplifyLocals-before-const-prop.diff (renamed from src/test/mir-opt/simplify_locals.r.SimplifyLocals.diff)4
-rw-r--r--src/test/mir-opt/simplify_locals.rs20
-rw-r--r--src/test/mir-opt/simplify_locals.t1.SimplifyLocals-before-const-prop.diff (renamed from src/test/mir-opt/simplify_locals.t1.SimplifyLocals.diff)4
-rw-r--r--src/test/mir-opt/simplify_locals.t2.SimplifyLocals-before-const-prop.diff (renamed from src/test/mir-opt/simplify_locals.t2.SimplifyLocals.diff)4
-rw-r--r--src/test/mir-opt/simplify_locals.t3.SimplifyLocals-before-const-prop.diff (renamed from src/test/mir-opt/simplify_locals.t3.SimplifyLocals.diff)4
-rw-r--r--src/test/mir-opt/simplify_locals.t4.SimplifyLocals-before-const-prop.diff (renamed from src/test/mir-opt/simplify_locals.t4.SimplifyLocals.diff)4
-rw-r--r--src/test/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.diff (renamed from src/test/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals.diff)4
-rw-r--r--src/test/mir-opt/simplify_locals_fixedpoint.rs2
-rw-r--r--src/test/mir-opt/simplify_locals_removes_unused_consts.main.SimplifyLocals-before-const-prop.diff (renamed from src/test/mir-opt/simplify_locals_removes_unused_consts.main.SimplifyLocals.diff)4
-rw-r--r--src/test/mir-opt/simplify_locals_removes_unused_consts.rs4
-rw-r--r--src/test/mir-opt/simplify_locals_removes_unused_discriminant_reads.map.SimplifyLocals-before-const-prop.diff (renamed from src/test/mir-opt/simplify_locals_removes_unused_discriminant_reads.map.SimplifyLocals.diff)4
-rw-r--r--src/test/mir-opt/simplify_locals_removes_unused_discriminant_reads.rs4
-rw-r--r--src/test/mir-opt/simplify_match.main.ConstProp.diff1
-rw-r--r--src/test/mir-opt/uninhabited_enum.process_never.SimplifyLocals-final.after.mir (renamed from src/test/mir-opt/uninhabited_enum.process_never.SimplifyLocals.after.mir)2
-rw-r--r--src/test/mir-opt/uninhabited_enum.process_void.SimplifyLocals-final.after.mir (renamed from src/test/mir-opt/uninhabited_enum.process_void.SimplifyLocals.after.mir)2
-rw-r--r--src/test/mir-opt/uninhabited_enum.rs4
-rw-r--r--src/test/mir-opt/while_let_loops.change_loop_body.ConstProp.diff29
-rw-r--r--src/test/mir-opt/while_storage.while_loop.PreCodegen.after.mir6
-rw-r--r--src/test/run-make/dump-mono-stats/Makefile5
-rw-r--r--src/test/run-make/dump-mono-stats/foo.rs1
-rw-r--r--src/test/rustdoc-gui/anchors.goml80
-rw-r--r--src/test/rustdoc-gui/code-color.goml12
-rw-r--r--src/test/rustdoc-gui/codeblock-tooltip.goml86
-rw-r--r--src/test/rustdoc-gui/docblock-code-block-line-number.goml16
-rw-r--r--src/test/rustdoc-gui/docblock-table.goml32
-rw-r--r--src/test/rustdoc-gui/escape-key.goml2
-rw-r--r--src/test/rustdoc-gui/headers-color.goml40
-rw-r--r--src/test/rustdoc-gui/headings.goml46
-rw-r--r--src/test/rustdoc-gui/help-page.goml23
-rw-r--r--src/test/rustdoc-gui/highlight-colors.goml36
-rw-r--r--src/test/rustdoc-gui/impl-doc.goml6
-rw-r--r--src/test/rustdoc-gui/implementors.goml6
-rw-r--r--src/test/rustdoc-gui/item-decl-colors.goml31
-rw-r--r--src/test/rustdoc-gui/jump-to-def-background.goml12
-rw-r--r--src/test/rustdoc-gui/links-color.goml36
-rw-r--r--src/test/rustdoc-gui/mobile.goml6
-rw-r--r--src/test/rustdoc-gui/notable-trait.goml32
-rw-r--r--src/test/rustdoc-gui/run-on-hover.goml22
-rw-r--r--src/test/rustdoc-gui/rust-logo.goml51
-rw-r--r--src/test/rustdoc-gui/scrape-examples-button-focus.goml10
-rw-r--r--src/test/rustdoc-gui/scrape-examples-color.goml30
-rw-r--r--src/test/rustdoc-gui/scrape-examples-toggle.goml24
-rw-r--r--src/test/rustdoc-gui/search-filter.goml2
-rw-r--r--src/test/rustdoc-gui/search-no-result.goml20
-rw-r--r--src/test/rustdoc-gui/search-result-color.goml91
-rw-r--r--src/test/rustdoc-gui/search-result-display.goml22
-rw-r--r--src/test/rustdoc-gui/search-tab.goml30
-rw-r--r--src/test/rustdoc-gui/sidebar-links-color.goml78
-rw-r--r--src/test/rustdoc-gui/sidebar-mobile.goml14
-rw-r--r--src/test/rustdoc-gui/sidebar-source-code-display.goml90
-rw-r--r--src/test/rustdoc-gui/sidebar-source-code.goml62
-rw-r--r--src/test/rustdoc-gui/sidebar.goml56
-rw-r--r--src/test/rustdoc-gui/source-code-page.goml42
-rw-r--r--src/test/rustdoc-gui/src/lib2/Cargo.lock8
-rw-r--r--src/test/rustdoc-gui/src/lib2/Cargo.toml1
-rw-r--r--src/test/rustdoc-gui/src/lib2/http/Cargo.toml7
-rw-r--r--src/test/rustdoc-gui/src/lib2/http/lib.rs1
-rw-r--r--src/test/rustdoc-gui/src/lib2/implementors/Cargo.toml3
-rw-r--r--src/test/rustdoc-gui/src/lib2/implementors/lib.rs2
-rw-r--r--src/test/rustdoc-gui/stab-badge.goml58
-rw-r--r--src/test/rustdoc-gui/target.goml12
-rw-r--r--src/test/rustdoc-gui/toggle-docs.goml20
-rw-r--r--src/test/rustdoc-gui/type-declation-overflow.goml1
-rw-r--r--src/test/rustdoc-gui/unsafe-fn.goml10
-rw-r--r--src/test/rustdoc-json/doc_hidden_failure.rs3
-rw-r--r--src/test/rustdoc-json/primitives/local_primitive.rs21
-rw-r--r--src/test/rustdoc-json/reexport/pub_use_doc_hidden.rs15
-rw-r--r--src/test/rustdoc-ui/issue-105742.stderr44
-rw-r--r--src/test/rustdoc-ui/z-help.stdout5
-rw-r--r--src/test/rustdoc/src-links.rs5
-rw-r--r--src/test/rustdoc/src-links/fizz.rs1
-rw-r--r--src/test/ui/alloc-error/alloc-error-handler-bad-signature-3.rs2
-rw-r--r--src/test/ui/argument-suggestions/basic.rs6
-rw-r--r--src/test/ui/argument-suggestions/display-is-suggestable.rs2
-rw-r--r--src/test/ui/argument-suggestions/exotic-calls.rs8
-rw-r--r--src/test/ui/argument-suggestions/extern-fn-arg-names.rs2
-rw-r--r--src/test/ui/argument-suggestions/extra_arguments.rs28
-rw-r--r--src/test/ui/argument-suggestions/issue-100154.rs2
-rw-r--r--src/test/ui/argument-suggestions/issue-100478.rs2
-rw-r--r--src/test/ui/argument-suggestions/issue-101097.rs2
-rw-r--r--src/test/ui/argument-suggestions/issue-96638.rs2
-rw-r--r--src/test/ui/argument-suggestions/issue-97197.rs2
-rw-r--r--src/test/ui/argument-suggestions/issue-97484.rs2
-rw-r--r--src/test/ui/argument-suggestions/issue-98894.rs2
-rw-r--r--src/test/ui/argument-suggestions/issue-98897.rs2
-rw-r--r--src/test/ui/argument-suggestions/issue-99482.rs2
-rw-r--r--src/test/ui/argument-suggestions/missing_arguments.rs38
-rw-r--r--src/test/ui/argument-suggestions/mixed_cases.rs8
-rw-r--r--src/test/ui/argument-suggestions/too-long.stderr2
-rw-r--r--src/test/ui/associated-consts/issue-105330.rs (renamed from src/test/ui/issues/issue-105330.rs)0
-rw-r--r--src/test/ui/associated-consts/issue-105330.stderr (renamed from src/test/ui/issues/issue-105330.stderr)0
-rw-r--r--src/test/ui/associated-types/associated-type-projection-from-supertrait.stderr4
-rw-r--r--src/test/ui/associated-types/associated-types-for-unimpl-trait.stderr4
-rw-r--r--src/test/ui/associated-types/associated-types-no-suitable-bound.stderr4
-rw-r--r--src/test/ui/associated-types/associated-types-no-suitable-supertrait-2.stderr4
-rw-r--r--src/test/ui/associated-types/associated-types-no-suitable-supertrait.stderr8
-rw-r--r--src/test/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.stderr4
-rw-r--r--src/test/ui/associated-types/defaults-specialization.stderr8
-rw-r--r--src/test/ui/associated-types/issue-25700-1.rs (renamed from src/test/ui/issues/issue-25700-1.rs)0
-rw-r--r--src/test/ui/associated-types/issue-25700-2.rs (renamed from src/test/ui/issues/issue-25700-2.rs)0
-rw-r--r--src/test/ui/associated-types/issue-25700.rs (renamed from src/test/ui/issues/issue-25700.rs)0
-rw-r--r--src/test/ui/associated-types/issue-25700.stderr (renamed from src/test/ui/issues/issue-25700.stderr)0
-rw-r--r--src/test/ui/associated-types/issue-59324.rs2
-rw-r--r--src/test/ui/associated-types/issue-59324.stderr17
-rw-r--r--src/test/ui/async-await/in-trait/async-example-desugared-boxed-in-trait.stderr4
-rw-r--r--src/test/ui/borrowck/borrowck-drop-from-guard.rs9
-rw-r--r--src/test/ui/borrowck/borrowck-drop-from-guard.stderr21
-rw-r--r--src/test/ui/borrowck/borrowck-mutate-in-guard.rs19
-rw-r--r--src/test/ui/borrowck/borrowck-mutate-in-guard.stderr23
-rw-r--r--src/test/ui/borrowck/issue-31287-drop-in-guard.rs9
-rw-r--r--src/test/ui/borrowck/issue-31287-drop-in-guard.stderr20
-rw-r--r--src/test/ui/borrowck/issue-93078.rs15
-rw-r--r--src/test/ui/borrowck/issue-93078.stderr12
-rw-r--r--src/test/ui/borrowck/regions-bound-missing-bound-in-impl.stderr8
-rw-r--r--src/test/ui/c-variadic/variadic-ffi-1.rs4
-rw-r--r--src/test/ui/chalkify/arithmetic.rs2
-rw-r--r--src/test/ui/chalkify/assert.rs2
-rw-r--r--src/test/ui/chalkify/basic.rs2
-rw-r--r--src/test/ui/chalkify/bugs/async.rs2
-rw-r--r--src/test/ui/chalkify/builtin-copy-clone.rs2
-rw-r--r--src/test/ui/chalkify/chalk_initial_program.rs2
-rw-r--r--src/test/ui/chalkify/closure.rs2
-rw-r--r--src/test/ui/chalkify/generic_impls.rs2
-rw-r--r--src/test/ui/chalkify/impl_wf.rs2
-rw-r--r--src/test/ui/chalkify/impl_wf_2.rs2
-rw-r--r--src/test/ui/chalkify/inherent_impl.rs2
-rw-r--r--src/test/ui/chalkify/inherent_impl_min.rs2
-rw-r--r--src/test/ui/chalkify/lower_env1.rs2
-rw-r--r--src/test/ui/chalkify/lower_env2.rs2
-rw-r--r--src/test/ui/chalkify/lower_env3.rs2
-rw-r--r--src/test/ui/chalkify/lower_impl.rs2
-rw-r--r--src/test/ui/chalkify/lower_struct.rs2
-rw-r--r--src/test/ui/chalkify/lower_trait.rs2
-rw-r--r--src/test/ui/chalkify/lower_trait_higher_rank.rs2
-rw-r--r--src/test/ui/chalkify/lower_trait_where_clause.rs2
-rw-r--r--src/test/ui/chalkify/println.rs2
-rw-r--r--src/test/ui/chalkify/projection.rs2
-rw-r--r--src/test/ui/chalkify/recursive_where_clause_on_type.rs6
-rw-r--r--src/test/ui/chalkify/recursive_where_clause_on_type.stderr4
-rw-r--r--src/test/ui/chalkify/super_trait.rs2
-rw-r--r--src/test/ui/chalkify/trait-objects.rs2
-rw-r--r--src/test/ui/chalkify/trait_implied_bound.rs2
-rw-r--r--src/test/ui/chalkify/type_implied_bound.rs2
-rw-r--r--src/test/ui/chalkify/type_inference.rs2
-rw-r--r--src/test/ui/chalkify/type_wf.rs2
-rw-r--r--src/test/ui/check-cfg/well-known-values.stderr2
-rw-r--r--src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-3.rs3
-rw-r--r--src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-3.stderr26
-rw-r--r--src/test/ui/closures/supertrait-hint-cycle-2.rs18
-rw-r--r--src/test/ui/closures/supertrait-hint-cycle-3.rs16
-rw-r--r--src/test/ui/closures/supertrait-hint-cycle.rs65
-rw-r--r--src/test/ui/codegen/issue-82859-slice-miscompile.rs (renamed from src/test/ui/issues/issue-82859-slice-miscompile.rs)0
-rw-r--r--src/test/ui/coherence/coherence-default-trait-impl.stderr4
-rw-r--r--src/test/ui/command/issue-10626.rs (renamed from src/test/ui/issues/issue-10626.rs)0
-rw-r--r--src/test/ui/compare-method/bad-self-type.stderr12
-rw-r--r--src/test/ui/compare-method/issue-90444.stderr8
-rw-r--r--src/test/ui/compare-method/reordered-type-param.stderr4
-rw-r--r--src/test/ui/const-generics/assoc_const_eq_diagnostic.rs18
-rw-r--r--src/test/ui/const-generics/assoc_const_eq_diagnostic.stderr33
-rw-r--r--src/test/ui/const-generics/generic_const_exprs/issue-76595.rs2
-rw-r--r--src/test/ui/const-generics/incorrect-number-of-const-args.rs4
-rw-r--r--src/test/ui/consts/invalid-union.32bit.stderr6
-rw-r--r--src/test/ui/consts/invalid-union.64bit.stderr6
-rw-r--r--src/test/ui/consts/issue-103790.stderr2
-rw-r--r--src/test/ui/drop/issue-2734.rs (renamed from src/test/ui/issues/issue-2734.rs)0
-rw-r--r--src/test/ui/dropck/dropck-eyepatch-implies-unsafe-impl.stderr18
-rw-r--r--src/test/ui/dropck/issue-34053.rs (renamed from src/test/ui/issues/issue-34053.rs)0
-rw-r--r--src/test/ui/enum-discriminant/issue-72554.rs (renamed from src/test/ui/issues/issue-72554.rs)0
-rw-r--r--src/test/ui/enum-discriminant/issue-72554.stderr (renamed from src/test/ui/issues/issue-72554.stderr)0
-rw-r--r--src/test/ui/error-codes/E0013.rs4
-rw-r--r--src/test/ui/error-codes/E0013.stderr11
-rw-r--r--src/test/ui/error-codes/E0015.rs8
-rw-r--r--src/test/ui/error-codes/E0015.stderr11
-rw-r--r--src/test/ui/error-codes/E0199.stderr2
-rw-r--r--src/test/ui/error-codes/E0200.stderr2
-rw-r--r--src/test/ui/error-codes/E0637.stderr6
-rw-r--r--src/test/ui/extern/issue-13655.rs (renamed from src/test/ui/issues/issue-13655.rs)0
-rw-r--r--src/test/ui/fmt/ifmt-bad-arg.stderr2
-rw-r--r--src/test/ui/fmt/issue-89173.rs2
-rw-r--r--src/test/ui/fmt/issue-89173.stderr2
-rw-r--r--src/test/ui/fn/issue-3044.rs2
-rw-r--r--src/test/ui/fn/issue-3044.stderr2
-rw-r--r--src/test/ui/fn/issue-80179.rs6
-rw-r--r--src/test/ui/fn/issue-80179.stderr6
-rw-r--r--src/test/ui/fn/suggest-return-closure.rs34
-rw-r--r--src/test/ui/fn/suggest-return-closure.stderr36
-rw-r--r--src/test/ui/fn/suggest-return-future.rs23
-rw-r--r--src/test/ui/fn/suggest-return-future.stderr21
-rw-r--r--src/test/ui/generator/issue-102645.rs2
-rw-r--r--src/test/ui/generator/issue-102645.stderr2
-rw-r--r--src/test/ui/generic-associated-types/elided-in-expr-position.stderr4
-rw-r--r--src/test/ui/generic-associated-types/gat-trait-path-missing-lifetime.stderr4
-rw-r--r--src/test/ui/generic-associated-types/issue-71176.stderr2
-rw-r--r--src/test/ui/generic-associated-types/issue-76535.base.stderr2
-rw-r--r--src/test/ui/generic-associated-types/issue-76535.extended.stderr2
-rw-r--r--src/test/ui/generic-associated-types/issue-78671.base.stderr2
-rw-r--r--src/test/ui/generic-associated-types/issue-78671.extended.stderr2
-rw-r--r--src/test/ui/generic-associated-types/issue-79422.base.stderr2
-rw-r--r--src/test/ui/generic-associated-types/issue-79422.extended.stderr2
-rw-r--r--src/test/ui/generic-associated-types/issue-79636-1.stderr2
-rw-r--r--src/test/ui/generic-associated-types/issue-79636-2.stderr2
-rw-r--r--src/test/ui/generic-associated-types/issue-80433.stderr2
-rw-r--r--src/test/ui/generic-associated-types/issue-81712-cyclic-traits.stderr2
-rw-r--r--src/test/ui/generic-associated-types/issue-81862.stderr2
-rw-r--r--src/test/ui/generic-associated-types/missing_lifetime_args.stderr2
-rw-r--r--src/test/ui/generics/generic-type-less-params-with-defaults.stderr2
-rw-r--r--src/test/ui/generics/issue-65285-incorrect-explicit-lifetime-name-needed.stderr6
-rw-r--r--src/test/ui/generics/wrong-number-of-args.stderr12
-rw-r--r--src/test/ui/higher-rank-trait-bounds/issue-58451.rs2
-rw-r--r--src/test/ui/illegal-sized-bound/mutability-mismatch-arg.fixed9
-rw-r--r--src/test/ui/illegal-sized-bound/mutability-mismatch-arg.rs9
-rw-r--r--src/test/ui/illegal-sized-bound/mutability-mismatch-arg.stderr13
-rw-r--r--src/test/ui/illegal-sized-bound/mutability-mismatch.rs10
-rw-r--r--src/test/ui/illegal-sized-bound/mutability-mismatch.stderr18
-rw-r--r--src/test/ui/impl-trait/explicit-generic-args-with-impl-trait/not-enough-args.rs2
-rw-r--r--src/test/ui/impl-trait/impl-generic-mismatch-ab.stderr4
-rw-r--r--src/test/ui/impl-trait/in-trait/box-coerce-span-in-default.rs49
-rw-r--r--src/test/ui/impl-trait/in-trait/box-coerce-span-in-default.stderr11
-rw-r--r--src/test/ui/impl-trait/in-trait/method-signature-matches.stderr12
-rw-r--r--src/test/ui/impl-trait/in-trait/signature-mismatch.stderr4
-rw-r--r--src/test/ui/impl-trait/in-trait/specialization-broken.stderr4
-rw-r--r--src/test/ui/impl-trait/issues/issue-92305.stderr2
-rw-r--r--src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr8
-rw-r--r--src/test/ui/impl-trait/static-return-lifetime-infered.rs2
-rw-r--r--src/test/ui/impl-trait/static-return-lifetime-infered.stderr32
-rw-r--r--src/test/ui/impl-trait/trait_type.stderr4
-rw-r--r--src/test/ui/implied-bounds/hrlt-implied-trait-bounds-guard.rs2
-rw-r--r--src/test/ui/issues/issue-11374.stderr2
-rw-r--r--src/test/ui/issues/issue-13033.rs4
-rw-r--r--src/test/ui/issues/issue-13033.stderr4
-rw-r--r--src/test/ui/issues/issue-14092.stderr2
-rw-r--r--src/test/ui/issues/issue-15094.rs4
-rw-r--r--src/test/ui/issues/issue-15094.stderr4
-rw-r--r--src/test/ui/issues/issue-18611.stderr8
-rw-r--r--src/test/ui/issues/issue-20225.stderr12
-rw-r--r--src/test/ui/issues/issue-20831-debruijn.stderr24
-rw-r--r--src/test/ui/issues/issue-21332.stderr4
-rw-r--r--src/test/ui/issues/issue-23024.stderr2
-rw-r--r--src/test/ui/issues/issue-25386.rs1
-rw-r--r--src/test/ui/issues/issue-25386.stderr8
-rw-r--r--src/test/ui/issues/issue-25439.stderr7
-rw-r--r--src/test/ui/issues/issue-26094.rs2
-rw-r--r--src/test/ui/issues/issue-29723.rs8
-rw-r--r--src/test/ui/issues/issue-29723.stderr20
-rw-r--r--src/test/ui/issues/issue-35570.stderr12
-rw-r--r--src/test/ui/issues/issue-37884.stderr4
-rw-r--r--src/test/ui/issues/issue-48364.stderr2
-rw-r--r--src/test/ui/issues/issue-4935.rs2
-rw-r--r--src/test/ui/issues/issue-86756.stderr2
-rw-r--r--src/test/ui/layout/thin-meta-implies-thin-ptr.rs11
-rw-r--r--src/test/ui/lexer/error-stage.stderr2
-rw-r--r--src/test/ui/lexer/lex-bad-numeric-literals.rs8
-rw-r--r--src/test/ui/lexer/lex-bad-numeric-literals.stderr76
-rw-r--r--src/test/ui/lifetimes/issue-105227.fixed26
-rw-r--r--src/test/ui/lifetimes/issue-105227.rs26
-rw-r--r--src/test/ui/lifetimes/issue-105227.stderr47
-rw-r--r--src/test/ui/lifetimes/issue-26638.rs2
-rw-r--r--src/test/ui/lifetimes/lifetime-mismatch-between-trait-and-impl.stderr4
-rw-r--r--src/test/ui/lifetimes/missing-lifetime-in-alias.stderr2
-rw-r--r--src/test/ui/macros/format-foreign.stderr10
-rw-r--r--src/test/ui/macros/format-unused-lables.stderr2
-rw-r--r--src/test/ui/macros/issue-104769-concat_bytes-invalid-literal.stderr2
-rw-r--r--src/test/ui/macros/issue-10536.rs (renamed from src/test/ui/issues/issue-10536.rs)0
-rw-r--r--src/test/ui/macros/issue-10536.stderr (renamed from src/test/ui/issues/issue-10536.stderr)0
-rw-r--r--src/test/ui/macros/issue-92267.stderr2
-rw-r--r--src/test/ui/methods/issues/issue-61525.stderr2
-rw-r--r--src/test/ui/methods/method-call-err-msg.rs8
-rw-r--r--src/test/ui/methods/method-call-err-msg.stderr8
-rw-r--r--src/test/ui/mismatched_types/E0053.stderr8
-rw-r--r--src/test/ui/mismatched_types/issue-74918-missing-lifetime.stderr4
-rw-r--r--src/test/ui/mismatched_types/issue-75361-mismatched-impl.stderr4
-rw-r--r--src/test/ui/mismatched_types/overloaded-calls-bad.rs4
-rw-r--r--src/test/ui/mismatched_types/trait-impl-fn-incompatibility.stderr8
-rw-r--r--src/test/ui/nll/issue-24535-allow-mutable-borrow-in-match-guard.rs8
-rw-r--r--src/test/ui/nll/issue-27282-move-match-input-into-guard.rs14
-rw-r--r--src/test/ui/nll/issue-27282-move-match-input-into-guard.stderr17
-rw-r--r--src/test/ui/nll/issue-27282-move-ref-mut-into-guard.rs10
-rw-r--r--src/test/ui/nll/issue-27282-move-ref-mut-into-guard.stderr14
-rw-r--r--src/test/ui/nll/issue-27282-mutation-in-guard.rs13
-rw-r--r--src/test/ui/nll/issue-27282-mutation-in-guard.stderr14
-rw-r--r--src/test/ui/nll/issue-27282-reborrow-ref-mut-in-guard.rs14
-rw-r--r--src/test/ui/nll/issue-27282-reborrow-ref-mut-in-guard.stderr14
-rw-r--r--src/test/ui/nll/issue-54189.rs (renamed from src/test/ui/issues/issue-54189.rs)0
-rw-r--r--src/test/ui/nll/issue-54189.stderr (renamed from src/test/ui/issues/issue-54189.stderr)0
-rw-r--r--src/test/ui/nll/match-cfg-fake-edges.rs28
-rw-r--r--src/test/ui/nll/match-cfg-fake-edges.stderr40
-rw-r--r--src/test/ui/nll/match-guards-always-borrow.rs27
-rw-r--r--src/test/ui/nll/match-guards-always-borrow.stderr14
-rw-r--r--src/test/ui/nll/match-guards-partially-borrow.rs193
-rw-r--r--src/test/ui/nll/match-guards-partially-borrow.stderr103
-rw-r--r--src/test/ui/nll/normalization-bounds-error.stderr8
-rw-r--r--src/test/ui/not-enough-arguments.rs4
-rw-r--r--src/test/ui/parser/int-literal-too-large-span.stderr2
-rw-r--r--src/test/ui/parser/issues/issue-5544-a.stderr2
-rw-r--r--src/test/ui/parser/issues/issue-5544-b.stderr2
-rw-r--r--src/test/ui/parser/nested-bad-turbofish.rs3
-rw-r--r--src/test/ui/parser/nested-bad-turbofish.stderr11
-rw-r--r--src/test/ui/privacy/private-field-ty-err.rs20
-rw-r--r--src/test/ui/privacy/private-field-ty-err.stderr14
-rw-r--r--src/test/ui/process/process-panic-after-fork.rs77
-rw-r--r--src/test/ui/regions/regions-implied-bounds-projection-gap-hr-1.stderr20
-rw-r--r--src/test/ui/resolve/resolve-primitive-fallback.rs2
-rw-r--r--src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-across-arms.rs15
-rw-r--r--src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-across-arms.stderr12
-rw-r--r--src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-in-first-arm.rs16
-rw-r--r--src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-in-first-arm.stderr12
-rw-r--r--src/test/ui/span/issue-34264.rs4
-rw-r--r--src/test/ui/span/missing-unit-argument.rs10
-rw-r--r--src/test/ui/span/missing-unit-argument.stderr4
-rw-r--r--src/test/ui/specialization/min_specialization/issue-79224.rs6
-rw-r--r--src/test/ui/specialization/min_specialization/issue-79224.stderr18
-rw-r--r--src/test/ui/suggestions/args-instead-of-tuple-errors.rs2
-rw-r--r--src/test/ui/suggestions/args-instead-of-tuple.fixed12
-rw-r--r--src/test/ui/suggestions/args-instead-of-tuple.rs12
-rw-r--r--src/test/ui/suggestions/args-instead-of-tuple.stderr10
-rw-r--r--src/test/ui/suggestions/imm-ref-trait-object.rs2
-rw-r--r--src/test/ui/suggestions/imm-ref-trait-object.stderr8
-rw-r--r--src/test/ui/suggestions/impl-trait-missing-lifetime-gated.rs5
-rw-r--r--src/test/ui/suggestions/issue-106443-sugg-clone-for-arg.rs23
-rw-r--r--src/test/ui/suggestions/issue-106443-sugg-clone-for-arg.stderr35
-rw-r--r--src/test/ui/suggestions/issue-106443-sugg-clone-for-bound.rs20
-rw-r--r--src/test/ui/suggestions/issue-106443-sugg-clone-for-bound.stderr29
-rw-r--r--src/test/ui/suggestions/missing-type-param-used-in-param.fixed2
-rw-r--r--src/test/ui/suggestions/missing-type-param-used-in-param.rs2
-rw-r--r--src/test/ui/suggestions/sugg-else-for-closure.stderr2
-rw-r--r--src/test/ui/suggestions/trait-with-missing-associated-type-restriction.stderr2
-rw-r--r--src/test/ui/tag-type-args.stderr2
-rw-r--r--src/test/ui/traits/impl-method-mismatch.rs4
-rw-r--r--src/test/ui/traits/impl-method-mismatch.stderr4
-rw-r--r--src/test/ui/traits/issue-35869.stderr16
-rw-r--r--src/test/ui/traits/issue-52893.stderr2
-rw-r--r--src/test/ui/traits/issue-91594.stderr4
-rw-r--r--src/test/ui/traits/issue-99875.rs (renamed from src/test/ui/issues/issue-99875.rs)0
-rw-r--r--src/test/ui/traits/issue-99875.stderr (renamed from src/test/ui/issues/issue-99875.stderr)0
-rw-r--r--src/test/ui/traits/matching-lifetimes.stderr8
-rw-r--r--src/test/ui/traits/param-without-lifetime-constraint.stderr4
-rw-r--r--src/test/ui/traits/safety-trait-impl-cc.stderr8
-rw-r--r--src/test/ui/traits/safety-trait-impl.stderr4
-rw-r--r--src/test/ui/traits/self-without-lifetime-constraint.stderr4
-rw-r--r--src/test/ui/tuple/add-tuple-within-arguments.rs2
-rw-r--r--src/test/ui/tuple/add-tuple-within-arguments.stderr2
-rw-r--r--src/test/ui/tuple/wrong_argument_ice-2.rs2
-rw-r--r--src/test/ui/tuple/wrong_argument_ice-2.stderr2
-rw-r--r--src/test/ui/tuple/wrong_argument_ice-3.rs2
-rw-r--r--src/test/ui/tuple/wrong_argument_ice-3.stderr2
-rw-r--r--src/test/ui/tuple/wrong_argument_ice-4.rs2
-rw-r--r--src/test/ui/tuple/wrong_argument_ice.rs2
-rw-r--r--src/test/ui/tuple/wrong_argument_ice.stderr2
-rw-r--r--src/test/ui/type/ascription/issue-34255-1.stderr2
-rw-r--r--src/test/ui/type/binding-assigned-block-without-tail-expression.rs22
-rw-r--r--src/test/ui/type/binding-assigned-block-without-tail-expression.stderr109
-rw-r--r--src/test/ui/type/closure-with-wrong-borrows.rs10
-rw-r--r--src/test/ui/type/closure-with-wrong-borrows.stderr19
-rw-r--r--src/test/ui/type/issue-58355.rs7
-rw-r--r--src/test/ui/type/issue-58355.stderr13
-rw-r--r--src/test/ui/type/type-ascription-instead-of-initializer.rs2
-rw-r--r--src/test/ui/type/type-check/assignment-in-if.stderr9
-rw-r--r--src/test/ui/type/type-check/point-at-inference-2.rs13
-rw-r--r--src/test/ui/type/type-check/point-at-inference-2.stderr56
-rw-r--r--src/test/ui/type/type-check/point-at-inference-3.fixed12
-rw-r--r--src/test/ui/type/type-check/point-at-inference-3.rs12
-rw-r--r--src/test/ui/type/type-check/point-at-inference-3.stderr21
-rw-r--r--src/test/ui/type/type-check/point-at-inference.fixed13
-rw-r--r--src/test/ui/type/type-check/point-at-inference.rs13
-rw-r--r--src/test/ui/type/type-check/point-at-inference.stderr26
-rw-r--r--src/test/ui/typeck/issue-105946.rs12
-rw-r--r--src/test/ui/typeck/issue-105946.stderr49
-rw-r--r--src/test/ui/typeck/issue-18937-1.rs (renamed from src/test/ui/issues/issue-18937-1.rs)0
-rw-r--r--src/test/ui/typeck/issue-18937.rs (renamed from src/test/ui/issues/issue-18937.rs)0
-rw-r--r--src/test/ui/typeck/issue-18937.stderr (renamed from src/test/ui/issues/issue-18937.stderr)0
-rw-r--r--src/test/ui/typeck/issue-31173.rs (renamed from src/test/ui/issues/issue-31173.rs)0
-rw-r--r--src/test/ui/typeck/issue-31173.stderr (renamed from src/test/ui/issues/issue-31173.stderr)0
-rw-r--r--src/test/ui/typeck/remove-extra-argument.fixed2
-rw-r--r--src/test/ui/typeck/remove-extra-argument.rs2
-rw-r--r--src/test/ui/ufcs/ufcs-qpath-missing-params.stderr4
-rw-r--r--src/test/ui/unboxed-closures/unboxed-closure-no-cyclic-sig.stderr7
-rw-r--r--src/test/ui/unboxed-closures/unboxed-closure-region.rs2
-rw-r--r--src/test/ui/unboxed-closures/unboxed-closure-region.stderr25
-rw-r--r--src/test/ui/underscore-lifetime/where-clause-inherent-impl-ampersand.rust2015.stderr6
-rw-r--r--src/test/ui/underscore-lifetime/where-clause-inherent-impl-ampersand.rust2018.stderr6
-rw-r--r--src/test/ui/underscore-lifetime/where-clause-trait-impl-region.rust2015.stderr6
-rw-r--r--src/test/ui/underscore-lifetime/where-clause-trait-impl-region.rust2018.stderr6
-rw-r--r--src/test/ui/unsafe/auxiliary/issue-106126.rs9
-rw-r--r--src/test/ui/unsafe/issue-106126-good-path-bug.rs12
-rw-r--r--src/test/ui/unsafe/unsafe-trait-impl.rs4
-rw-r--r--src/test/ui/unsafe/unsafe-trait-impl.stderr4
-rw-r--r--src/test/ui/wf/issue-103573.stderr4
-rw-r--r--src/test/ui/wf/wf-foreign-fn-decl-ret.stderr4
-rw-r--r--src/test/ui/wrong-mul-method-signature.stderr12
-rw-r--r--src/tools/build-manifest/src/main.rs4
-rw-r--r--src/tools/build_helper/Cargo.toml8
-rw-r--r--src/tools/build_helper/src/ci.rs40
-rw-r--r--src/tools/build_helper/src/git.rs75
-rw-r--r--src/tools/build_helper/src/lib.rs2
-rw-r--r--src/tools/bump-stage0/src/main.rs27
m---------src/tools/cargo0
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/cast_slice_different_sizes.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/escape.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/index_refutable_slice.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/same_item_push.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_rem_euclid.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/match_single_binding.rs7
-rw-r--r--src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/non_copy_const.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/unit_types/unit_arg.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs2
-rw-r--r--src/tools/clippy/clippy_utils/src/lib.rs6
-rw-r--r--src/tools/compiletest/src/runtest.rs2
-rw-r--r--src/tools/compiletest/src/util.rs8
-rw-r--r--src/tools/error_index_generator/book_config.toml1
-rw-r--r--src/tools/error_index_generator/main.rs14
-rw-r--r--src/tools/error_index_generator/redirect.js10
-rw-r--r--src/tools/jsondoclint/Cargo.toml2
-rw-r--r--src/tools/jsondoclint/src/json_find.rs3
-rw-r--r--src/tools/jsondoclint/src/main.rs98
-rw-r--r--src/tools/jsondoclint/src/validator.rs42
-rw-r--r--src/tools/jsondoclint/src/validator/tests.rs120
-rw-r--r--src/tools/rustc-workspace-hack/Cargo.toml2
-rw-r--r--src/tools/rustdoc-gui/tester.js122
-rw-r--r--src/tools/rustfmt/tests/target/issue_4110.rs1
-rw-r--r--src/tools/tidy/Cargo.toml1
-rw-r--r--src/tools/tidy/src/deps.rs13
-rw-r--r--src/tools/tidy/src/error_codes.rs384
-rw-r--r--src/tools/tidy/src/error_codes_check.rs305
-rw-r--r--src/tools/tidy/src/errors.rs77
-rw-r--r--src/tools/tidy/src/lib.rs4
-rw-r--r--src/tools/tidy/src/main.rs8
-rw-r--r--src/tools/tidy/src/style.rs30
-rw-r--r--src/tools/tidy/src/ui_tests.rs2
-rw-r--r--src/tools/tidy/src/x_version.rs65
-rw-r--r--src/tools/x/src/main.rs8
-rw-r--r--triagebot.toml1
806 files changed, 11162 insertions, 6252 deletions
diff --git a/Cargo.lock b/Cargo.lock
index f99e58e59b8..da47b08c7df 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -30,7 +30,7 @@ version = "0.7.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "43bb833f0bf979d8475d38fbf09ed3b8a55e1885fe93ad3f93239fc6a4f17b98"
 dependencies = [
- "getrandom 0.2.8",
+ "getrandom",
  "once_cell",
  "version_check",
 ]
@@ -50,7 +50,7 @@ version = "0.0.0"
 dependencies = [
  "compiler_builtins",
  "core",
- "rand 0.7.3",
+ "rand",
  "rand_xorshift",
 ]
 
@@ -198,6 +198,18 @@ dependencies = [
 ]
 
 [[package]]
+name = "base16ct"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "349a06037c7bf932dd7e7d1f653678b2038b9ad46a74102f1fc7bd7872678cce"
+
+[[package]]
+name = "base64ct"
+version = "1.5.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b645a089122eccb6111b4f81cbc1a49f5900ac4666bb93ac027feaecf15607bf"
+
+[[package]]
 name = "bitflags"
 version = "1.3.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -260,6 +272,10 @@ dependencies = [
 ]
 
 [[package]]
+name = "build_helper"
+version = "0.1.0"
+
+[[package]]
 name = "bump-stage0"
 version = "0.1.0"
 dependencies = [
@@ -272,6 +288,12 @@ dependencies = [
 ]
 
 [[package]]
+name = "bumpalo"
+version = "3.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba"
+
+[[package]]
 name = "bytecount"
 version = "0.6.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -341,6 +363,7 @@ dependencies = [
  "opener",
  "openssl",
  "os_info",
+ "pasetors",
  "pathdiff",
  "percent-encoding",
  "pretty_env_logger",
@@ -358,6 +381,7 @@ dependencies = [
  "tar",
  "tempfile",
  "termcolor",
+ "time 0.3.17",
  "toml_edit",
  "unicode-width",
  "unicode-xid",
@@ -443,10 +467,13 @@ dependencies = [
  "glob",
  "itertools",
  "lazy_static",
+ "pasetors",
+ "serde",
  "serde_json",
  "snapbox",
  "tar",
  "termcolor",
+ "time 0.3.17",
  "toml_edit",
  "url",
  "winapi",
@@ -585,7 +612,7 @@ dependencies = [
  "num-integer",
  "num-traits",
  "serde",
- "time",
+ "time 0.1.43",
  "winapi",
 ]
 
@@ -597,7 +624,7 @@ checksum = "23b71c3ce99b7611011217b366d923f1d0a7e07a92bb2dbf1e84508c673ca3bd"
 dependencies = [
  "atty",
  "bitflags",
- "clap_derive",
+ "clap_derive 3.2.18",
  "clap_lex 0.2.2",
  "indexmap",
  "once_cell",
@@ -614,7 +641,9 @@ checksum = "6bf8832993da70a4c6d13c581f4463c2bdda27b9bf1c5498dc4365543abe6d6f"
 dependencies = [
  "atty",
  "bitflags",
+ "clap_derive 4.0.13",
  "clap_lex 0.3.0",
+ "once_cell",
  "strsim",
  "termcolor",
 ]
@@ -642,6 +671,19 @@ dependencies = [
 ]
 
 [[package]]
+name = "clap_derive"
+version = "4.0.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c42f169caba89a7d512b5418b09864543eeb4d497416c917d7137863bd2076ad"
+dependencies = [
+ "heck",
+ "proc-macro-error",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
 name = "clap_lex"
 version = "0.2.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -885,6 +927,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "82a90734b3d5dcf656e7624cca6bce9c3a90ee11f900e80141a7427ccfb3d317"
 
 [[package]]
+name = "const-oid"
+version = "0.9.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cec318a675afcb6a1ea1d4340e2d377e56e47c266f28043ceccbf4412ddfdd3b"
+
+[[package]]
 name = "content_inspector"
 version = "0.2.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -903,7 +951,7 @@ checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e"
 name = "core"
 version = "0.0.0"
 dependencies = [
- "rand 0.7.3",
+ "rand",
  "rand_xorshift",
 ]
 
@@ -938,7 +986,7 @@ dependencies = [
 
 [[package]]
 name = "crates-io"
-version = "0.35.0"
+version = "0.35.1"
 dependencies = [
  "anyhow",
  "curl",
@@ -1001,12 +1049,25 @@ dependencies = [
 ]
 
 [[package]]
+name = "crypto-bigint"
+version = "0.4.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ef2b4b23cddf68b89b8f8069890e8c270d54e2d5fe1b143820234805e4cb17ef"
+dependencies = [
+ "generic-array",
+ "rand_core",
+ "subtle",
+ "zeroize",
+]
+
+[[package]]
 name = "crypto-common"
-version = "0.1.2"
+version = "0.1.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a4600d695eb3f6ce1cd44e6e291adceb2cc3ab12f20a33777ecd0bf6eba34e06"
+checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
 dependencies = [
  "generic-array",
+ "typenum",
 ]
 
 [[package]]
@@ -1032,6 +1093,12 @@ dependencies = [
 ]
 
 [[package]]
+name = "ct-codecs"
+version = "1.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f3b7eb4404b8195a9abb6356f4ac07d8ba267045c8d6d220ac4dc992e6cc75df"
+
+[[package]]
 name = "ctor"
 version = "0.1.26"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1088,6 +1155,17 @@ dependencies = [
 ]
 
 [[package]]
+name = "der"
+version = "0.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f1a467a65c5e759bce6e65eaf91cc29f466cdc57cb65777bd646872a8a1fd4de"
+dependencies = [
+ "const-oid",
+ "pem-rfc7468",
+ "zeroize",
+]
+
+[[package]]
 name = "derive-new"
 version = "0.5.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1125,12 +1203,13 @@ checksum = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198"
 
 [[package]]
 name = "digest"
-version = "0.10.2"
+version = "0.10.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8cb780dce4f9a8f5c087362b3a4595936b2019e7c8b30f2c3e9a7e94e6ae9837"
+checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f"
 dependencies = [
  "block-buffer",
  "crypto-common",
+ "subtle",
 ]
 
 [[package]]
@@ -1218,6 +1297,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "453440c271cf5577fd2a40e4942540cb7d0d2f85e27c8d07dd0023c925a67541"
 
 [[package]]
+name = "ecdsa"
+version = "0.14.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "413301934810f597c1d19ca71c8710e99a3f1ba28a0d2ebc01551a2daeea3c5c"
+dependencies = [
+ "der",
+ "elliptic-curve",
+ "rfc6979",
+ "signature",
+]
+
+[[package]]
+name = "ed25519-compact"
+version = "2.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6a3d382e8464107391c8706b4c14b087808ecb909f6c15c34114bc42e53a9e4c"
+dependencies = [
+ "getrandom",
+]
+
+[[package]]
 name = "either"
 version = "1.6.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1236,6 +1336,28 @@ dependencies = [
 ]
 
 [[package]]
+name = "elliptic-curve"
+version = "0.12.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e7bb888ab5300a19b8e5bceef25ac745ad065f3c9f7efc6de1b91958110891d3"
+dependencies = [
+ "base16ct",
+ "crypto-bigint",
+ "der",
+ "digest",
+ "ff",
+ "generic-array",
+ "group",
+ "hkdf",
+ "pem-rfc7468",
+ "pkcs8",
+ "rand_core",
+ "sec1",
+ "subtle",
+ "zeroize",
+]
+
+[[package]]
 name = "ena"
 version = "0.14.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1355,6 +1477,22 @@ dependencies = [
 ]
 
 [[package]]
+name = "ff"
+version = "0.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d013fc25338cc558c5c2cfbad646908fb23591e2404481826742b651c9af7160"
+dependencies = [
+ "rand_core",
+ "subtle",
+]
+
+[[package]]
+name = "fiat-crypto"
+version = "0.1.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a214f5bb88731d436478f3ae1f8a277b62124089ba9fb67f4f93fb100ef73c90"
+
+[[package]]
 name = "filetime"
 version = "0.2.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1613,24 +1751,15 @@ dependencies = [
 
 [[package]]
 name = "getrandom"
-version = "0.1.16"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce"
-dependencies = [
- "cfg-if",
- "libc",
- "wasi 0.9.0+wasi-snapshot-preview1",
-]
-
-[[package]]
-name = "getrandom"
 version = "0.2.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31"
 dependencies = [
  "cfg-if",
+ "js-sys",
  "libc",
- "wasi 0.11.0+wasi-snapshot-preview1",
+ "wasi",
+ "wasm-bindgen",
 ]
 
 [[package]]
@@ -1694,6 +1823,17 @@ dependencies = [
 ]
 
 [[package]]
+name = "group"
+version = "0.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5dfbfb3a6cfbd390d5c9564ab283a0349b9b9fcd46a706c1eb10e0db70bfbac7"
+dependencies = [
+ "ff",
+ "rand_core",
+ "subtle",
+]
+
+[[package]]
 name = "gsgdt"
 version = "0.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1783,6 +1923,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "644f9158b2f133fd50f5fb3242878846d9eb792e445c893805ff0e3824006e35"
 
 [[package]]
+name = "hkdf"
+version = "0.12.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "791a029f6b9fc27657f6f188ec6e5e43f6911f6f878e0dc5501396e09809d437"
+dependencies = [
+ "hmac",
+]
+
+[[package]]
+name = "hmac"
+version = "0.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e"
+dependencies = [
+ "digest",
+]
+
+[[package]]
 name = "home"
 version = "0.5.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1946,7 +2104,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "af1955a75fa080c677d3972822ec4bad316169ab1cfc6c257a942c2265dbe5fe"
 dependencies = [
  "bitmaps",
- "rand_core 0.6.2",
+ "rand_core",
  "rand_xoshiro",
  "sized-chunks",
  "typenum",
@@ -2080,6 +2238,15 @@ dependencies = [
 ]
 
 [[package]]
+name = "js-sys"
+version = "0.3.60"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47"
+dependencies = [
+ "wasm-bindgen",
+]
+
+[[package]]
 name = "jsondocck"
 version = "0.1.0"
 dependencies = [
@@ -2097,8 +2264,10 @@ name = "jsondoclint"
 version = "0.1.0"
 dependencies = [
  "anyhow",
+ "clap 4.0.15",
  "fs-err",
  "rustdoc-json-types",
+ "serde",
  "serde_json",
 ]
 
@@ -2480,14 +2649,14 @@ version = "0.1.0"
 dependencies = [
  "colored",
  "env_logger 0.9.0",
- "getrandom 0.2.8",
+ "getrandom",
  "lazy_static",
  "libc",
  "libffi",
  "libloading",
  "log",
  "measureme",
- "rand 0.8.5",
+ "rand",
  "regex",
  "rustc-workspace-hack",
  "rustc_version",
@@ -2648,6 +2817,17 @@ dependencies = [
 ]
 
 [[package]]
+name = "orion"
+version = "0.17.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f2baf7fd2e326e3895c681176788dd227fcd8369350e53c570592d8563fecbb6"
+dependencies = [
+ "fiat-crypto",
+ "subtle",
+ "zeroize",
+]
+
+[[package]]
 name = "os_info"
 version = "3.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2680,6 +2860,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f"
 
 [[package]]
+name = "p384"
+version = "0.11.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dfc8c5bf642dde52bb9e87c0ecd8ca5a76faac2eeed98dedb7c717997e1080aa"
+dependencies = [
+ "ecdsa",
+ "elliptic-curve",
+ "sha2",
+]
+
+[[package]]
 name = "packed_simd_2"
 version = "0.3.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2761,12 +2952,42 @@ dependencies = [
 ]
 
 [[package]]
+name = "pasetors"
+version = "0.6.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ed20c4c21d893414f42e0cbfebe8a8036b5ae9b0264611fb6504e395eda6ceec"
+dependencies = [
+ "ct-codecs",
+ "ed25519-compact",
+ "getrandom",
+ "orion",
+ "p384",
+ "rand_core",
+ "regex",
+ "serde",
+ "serde_json",
+ "sha2",
+ "subtle",
+ "time 0.3.17",
+ "zeroize",
+]
+
+[[package]]
 name = "pathdiff"
 version = "0.2.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd"
 
 [[package]]
+name = "pem-rfc7468"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "24d159833a9105500e0398934e205e0773f0b27529557134ecfc51c27646adac"
+dependencies = [
+ "base64ct",
+]
+
+[[package]]
 name = "percent-encoding"
 version = "2.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2861,7 +3082,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "5d5285893bb5eb82e6aaf5d59ee909a06a16737a8970984dd7746ba9283498d6"
 dependencies = [
  "phf_shared",
- "rand 0.8.5",
+ "rand",
 ]
 
 [[package]]
@@ -2886,6 +3107,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
 
 [[package]]
+name = "pkcs8"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9eca2c590a5f85da82668fa685c09ce2888b9430e83299debf1f34b65fd4a4ba"
+dependencies = [
+ "der",
+ "spki",
+]
+
+[[package]]
 name = "pkg-config"
 version = "0.3.25"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3058,36 +3289,13 @@ dependencies = [
 
 [[package]]
 name = "rand"
-version = "0.7.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03"
-dependencies = [
- "getrandom 0.1.16",
- "libc",
- "rand_chacha 0.2.2",
- "rand_core 0.5.1",
- "rand_hc",
-]
-
-[[package]]
-name = "rand"
 version = "0.8.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
 dependencies = [
  "libc",
- "rand_chacha 0.3.0",
- "rand_core 0.6.2",
-]
-
-[[package]]
-name = "rand_chacha"
-version = "0.2.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402"
-dependencies = [
- "ppv-lite86",
- "rand_core 0.5.1",
+ "rand_chacha",
+ "rand_core",
 ]
 
 [[package]]
@@ -3097,43 +3305,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "e12735cf05c9e10bf21534da50a147b924d555dc7a547c42e6bb2d5b6017ae0d"
 dependencies = [
  "ppv-lite86",
- "rand_core 0.6.2",
+ "rand_core",
 ]
 
 [[package]]
 name = "rand_core"
-version = "0.5.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19"
-dependencies = [
- "getrandom 0.1.16",
-]
-
-[[package]]
-name = "rand_core"
-version = "0.6.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "34cf66eb183df1c5876e2dcf6b13d57340741e8dc255b48e40a26de954d06ae7"
-dependencies = [
- "getrandom 0.2.8",
-]
-
-[[package]]
-name = "rand_hc"
-version = "0.2.0"
+version = "0.6.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c"
+checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
 dependencies = [
- "rand_core 0.5.1",
+ "getrandom",
 ]
 
 [[package]]
 name = "rand_xorshift"
-version = "0.2.0"
+version = "0.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "77d416b86801d23dde1aa643023b775c3a462efc0ed96443add11546cdf1dca8"
+checksum = "d25bf25ec5ae4a3f1b92f929810509a2f53d7dca2f50b794ff57e3face536c8f"
 dependencies = [
- "rand_core 0.5.1",
+ "rand_core",
 ]
 
 [[package]]
@@ -3142,7 +3332,7 @@ version = "0.6.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "6f97cdb2a36ed4183de61b2f824cc45c9f1037f28afe0a322e9fff4c108b5aaa"
 dependencies = [
- "rand_core 0.6.2",
+ "rand_core",
 ]
 
 [[package]]
@@ -3184,7 +3374,7 @@ version = "0.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "528532f3d801c87aec9def2add9ca802fe569e44a544afe633765267840abe64"
 dependencies = [
- "getrandom 0.2.8",
+ "getrandom",
  "redox_syscall",
 ]
 
@@ -3249,6 +3439,17 @@ dependencies = [
 ]
 
 [[package]]
+name = "rfc6979"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7743f17af12fa0b03b803ba12cd6a8d9483a587e89c69445e3909655c0b9fabb"
+dependencies = [
+ "crypto-bigint",
+ "hmac",
+ "zeroize",
+]
+
+[[package]]
 name = "rls"
 version = "2.0.0"
 dependencies = [
@@ -3387,9 +3588,10 @@ version = "1.0.0"
 dependencies = [
  "bstr 0.2.17",
  "clap 3.2.20",
+ "getrandom",
  "libc",
  "libz-sys",
- "rand 0.8.5",
+ "rand",
  "regex",
  "serde_json",
  "syn",
@@ -3402,7 +3604,7 @@ name = "rustc_abi"
 version = "0.0.0"
 dependencies = [
  "bitflags",
- "rand 0.8.5",
+ "rand",
  "rand_xoshiro",
  "rustc_data_structures",
  "rustc_index",
@@ -3636,6 +3838,7 @@ dependencies = [
  "rustc_span",
  "rustc_symbol_mangling",
  "rustc_target",
+ "rustc_type_ir",
  "serde_json",
  "smallvec",
  "snap",
@@ -3770,6 +3973,7 @@ dependencies = [
  "rustc_serialize",
  "rustc_span",
  "rustc_target",
+ "rustc_type_ir",
  "serde",
  "serde_json",
  "termcolor",
@@ -3906,7 +4110,7 @@ dependencies = [
 name = "rustc_incremental"
 version = "0.0.0"
 dependencies = [
- "rand 0.8.5",
+ "rand",
  "rustc_ast",
  "rustc_data_structures",
  "rustc_errors",
@@ -4226,6 +4430,8 @@ dependencies = [
  "rustc_session",
  "rustc_span",
  "rustc_target",
+ "serde",
+ "serde_json",
  "smallvec",
  "tracing",
 ]
@@ -4775,6 +4981,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
 
 [[package]]
+name = "sec1"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3be24c1842290c45df0a7bf069e0c268a747ad05a192f2fd7dcfdbc1cba40928"
+dependencies = [
+ "base16ct",
+ "der",
+ "generic-array",
+ "pkcs8",
+ "subtle",
+ "zeroize",
+]
+
+[[package]]
 name = "security-framework"
 version = "2.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -4805,18 +5025,18 @@ checksum = "1ef965a420fe14fdac7dd018862966a4c14094f900e1650bbc71ddd7d580c8af"
 
 [[package]]
 name = "semver"
-version = "1.0.12"
+version = "1.0.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a2333e6df6d6598f2b1974829f853c2b4c5f4a6e503c10af918081aa6f8564e1"
+checksum = "e25dfac463d778e353db5be2449d1cce89bd6fd23c9f1ea21310ce6e5a1b29c4"
 dependencies = [
  "serde",
 ]
 
 [[package]]
 name = "serde"
-version = "1.0.147"
+version = "1.0.152"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d193d69bae983fc11a79df82342761dfbf28a99fc8d203dca4c3c1b590948965"
+checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb"
 dependencies = [
  "serde_derive",
 ]
@@ -4833,9 +5053,9 @@ dependencies = [
 
 [[package]]
 name = "serde_derive"
-version = "1.0.147"
+version = "1.0.152"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4f1d362ca8fc9c3e3a7484440752472d68a6caa98f1ab81d99b5dfe517cec852"
+checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -4853,9 +5073,9 @@ dependencies = [
 
 [[package]]
 name = "serde_json"
-version = "1.0.85"
+version = "1.0.91"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e55a28e3aaef9d5ce0506d0a14dbba8054ddc7e499ef522dd8b26859ec9d4a44"
+checksum = "877c235533714907a8c2464236f5c4b2a17262ef1bd71f38f35ea592c8da6883"
 dependencies = [
  "indexmap",
  "itoa",
@@ -4876,9 +5096,9 @@ dependencies = [
 
 [[package]]
 name = "sha2"
-version = "0.10.1"
+version = "0.10.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "99c3bd8169c58782adad9290a9af5939994036b76187f7b4f0e6de91dbbfc0ec"
+checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0"
 dependencies = [
  "cfg-if",
  "cpufeatures",
@@ -4907,6 +5127,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "42a568c8f2cd051a4d283bd6eb0343ac214c1b0f1ac19f93e1175b2dee38c73d"
 
 [[package]]
+name = "signature"
+version = "1.6.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c"
+dependencies = [
+ "digest",
+ "rand_core",
+]
+
+[[package]]
 name = "similar"
 version = "2.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -5010,6 +5240,16 @@ dependencies = [
 ]
 
 [[package]]
+name = "spki"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "67cf02bbac7a337dc36e4f5a693db6c21e7863f45070f7064577eb4367a3212b"
+dependencies = [
+ "base64ct",
+ "der",
+]
+
+[[package]]
 name = "stable_deref_trait"
 version = "1.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -5053,11 +5293,12 @@ dependencies = [
  "panic_abort",
  "panic_unwind",
  "profiler_builtins",
- "rand 0.7.3",
+ "rand",
+ "rand_xorshift",
  "rustc-demangle",
  "std_detect",
  "unwind",
- "wasi 0.11.0+wasi-snapshot-preview1",
+ "wasi",
 ]
 
 [[package]]
@@ -5132,10 +5373,16 @@ dependencies = [
 ]
 
 [[package]]
+name = "subtle"
+version = "2.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601"
+
+[[package]]
 name = "syn"
-version = "1.0.102"
+version = "1.0.107"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3fcd952facd492f9be3ef0d0b7032a6e442ee9b361d4acc2b1d0c4aaa5f613a1"
+checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -5309,6 +5556,7 @@ dependencies = [
  "lazy_static",
  "miropt-test-tools",
  "regex",
+ "semver",
  "termcolor",
  "walkdir",
 ]
@@ -5328,6 +5576,33 @@ dependencies = [
 ]
 
 [[package]]
+name = "time"
+version = "0.3.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a561bf4617eebd33bca6434b988f39ed798e527f51a1e797d0ee4f61c0a38376"
+dependencies = [
+ "itoa",
+ "serde",
+ "time-core",
+ "time-macros",
+]
+
+[[package]]
+name = "time-core"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2e153e1f1acaef8acc537e68b44906d2db6436e2b35ac2c6b42640fff91f00fd"
+
+[[package]]
+name = "time-macros"
+version = "0.2.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d967f99f534ca7e495c575c62638eebc2898a8c84c119b89e250477bc4ba16b2"
+dependencies = [
+ "time-core",
+]
+
+[[package]]
 name = "tinystr"
 version = "0.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -5495,7 +5770,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675"
 dependencies = [
  "cfg-if",
- "rand 0.8.5",
+ "rand",
  "static_assertions",
 ]
 
@@ -5510,9 +5785,9 @@ dependencies = [
 
 [[package]]
 name = "typenum"
-version = "1.12.0"
+version = "1.16.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33"
+checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba"
 
 [[package]]
 name = "ucd-parse"
@@ -5778,7 +6053,7 @@ version = "0.8.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7"
 dependencies = [
- "getrandom 0.2.8",
+ "getrandom",
 ]
 
 [[package]]
@@ -5821,12 +6096,6 @@ dependencies = [
 
 [[package]]
 name = "wasi"
-version = "0.9.0+wasi-snapshot-preview1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
-
-[[package]]
-name = "wasi"
 version = "0.11.0+wasi-snapshot-preview1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
@@ -5837,6 +6106,60 @@ dependencies = [
 ]
 
 [[package]]
+name = "wasm-bindgen"
+version = "0.2.83"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268"
+dependencies = [
+ "cfg-if",
+ "wasm-bindgen-macro",
+]
+
+[[package]]
+name = "wasm-bindgen-backend"
+version = "0.2.83"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142"
+dependencies = [
+ "bumpalo",
+ "log",
+ "once_cell",
+ "proc-macro2",
+ "quote",
+ "syn",
+ "wasm-bindgen-shared",
+]
+
+[[package]]
+name = "wasm-bindgen-macro"
+version = "0.2.83"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810"
+dependencies = [
+ "quote",
+ "wasm-bindgen-macro-support",
+]
+
+[[package]]
+name = "wasm-bindgen-macro-support"
+version = "0.2.83"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+ "wasm-bindgen-backend",
+ "wasm-bindgen-shared",
+]
+
+[[package]]
+name = "wasm-bindgen-shared"
+version = "0.2.83"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f"
+
+[[package]]
 name = "winapi"
 version = "0.3.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -6029,6 +6352,12 @@ dependencies = [
 ]
 
 [[package]]
+name = "zeroize"
+version = "1.5.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c394b5bd0c6f669e7275d9c20aa90ae064cb22e75a1cad54e1b34088034b149f"
+
+[[package]]
 name = "zerovec"
 version = "0.9.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/Cargo.toml b/Cargo.toml
index 1cec4a84480..ce08d4edb56 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -4,6 +4,7 @@ members = [
   "library/std",
   "library/test",
   "src/rustdoc-json-types",
+  "src/tools/build_helper",
   "src/tools/cargotest",
   "src/tools/clippy",
   "src/tools/clippy/clippy_dev",
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs
index c1b26ca0925..e656fb3740b 100644
--- a/compiler/rustc_ast/src/ast.rs
+++ b/compiler/rustc_ast/src/ast.rs
@@ -2170,10 +2170,10 @@ impl fmt::Display for InlineAsmTemplatePiece {
                 Ok(())
             }
             Self::Placeholder { operand_idx, modifier: Some(modifier), .. } => {
-                write!(f, "{{{}:{}}}", operand_idx, modifier)
+                write!(f, "{{{operand_idx}:{modifier}}}")
             }
             Self::Placeholder { operand_idx, modifier: None, .. } => {
-                write!(f, "{{{}}}", operand_idx)
+                write!(f, "{{{operand_idx}}}")
             }
         }
     }
@@ -2185,7 +2185,7 @@ impl InlineAsmTemplatePiece {
         use fmt::Write;
         let mut out = String::new();
         for p in s.iter() {
-            let _ = write!(out, "{}", p);
+            let _ = write!(out, "{p}");
         }
         out
     }
diff --git a/compiler/rustc_ast/src/ast_traits.rs b/compiler/rustc_ast/src/ast_traits.rs
index 1b31be07f7a..4dc9c30a2c8 100644
--- a/compiler/rustc_ast/src/ast_traits.rs
+++ b/compiler/rustc_ast/src/ast_traits.rs
@@ -214,7 +214,7 @@ impl HasTokens for Attribute {
         match &self.kind {
             AttrKind::Normal(normal) => normal.tokens.as_ref(),
             kind @ AttrKind::DocComment(..) => {
-                panic!("Called tokens on doc comment attr {:?}", kind)
+                panic!("Called tokens on doc comment attr {kind:?}")
             }
         }
     }
@@ -222,7 +222,7 @@ impl HasTokens for Attribute {
         Some(match &mut self.kind {
             AttrKind::Normal(normal) => &mut normal.tokens,
             kind @ AttrKind::DocComment(..) => {
-                panic!("Called tokens_mut on doc comment attr {:?}", kind)
+                panic!("Called tokens_mut on doc comment attr {kind:?}")
             }
         })
     }
diff --git a/compiler/rustc_ast/src/attr/mod.rs b/compiler/rustc_ast/src/attr/mod.rs
index d99f6ed2c1c..c6b6207b318 100644
--- a/compiler/rustc_ast/src/attr/mod.rs
+++ b/compiler/rustc_ast/src/attr/mod.rs
@@ -310,7 +310,7 @@ impl Attribute {
             AttrKind::Normal(normal) => normal
                 .tokens
                 .as_ref()
-                .unwrap_or_else(|| panic!("attribute is missing tokens: {:?}", self))
+                .unwrap_or_else(|| panic!("attribute is missing tokens: {self:?}"))
                 .to_attr_token_stream()
                 .to_tokenstream(),
             &AttrKind::DocComment(comment_kind, data) => TokenStream::new(vec![TokenTree::Token(
diff --git a/compiler/rustc_ast/src/expand/allocator.rs b/compiler/rustc_ast/src/expand/allocator.rs
index 1976e4ad3c9..35939496348 100644
--- a/compiler/rustc_ast/src/expand/allocator.rs
+++ b/compiler/rustc_ast/src/expand/allocator.rs
@@ -9,8 +9,8 @@ pub enum AllocatorKind {
 impl AllocatorKind {
     pub fn fn_name(&self, base: Symbol) -> String {
         match *self {
-            AllocatorKind::Global => format!("__rg_{}", base),
-            AllocatorKind::Default => format!("__rdl_{}", base),
+            AllocatorKind::Global => format!("__rg_{base}"),
+            AllocatorKind::Default => format!("__rdl_{base}"),
         }
     }
 }
diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs
index 5b6cf30fa96..f947ae4d057 100644
--- a/compiler/rustc_ast/src/token.rs
+++ b/compiler/rustc_ast/src/token.rs
@@ -125,27 +125,27 @@ impl fmt::Display for Lit {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         let Lit { kind, symbol, suffix } = *self;
         match kind {
-            Byte => write!(f, "b'{}'", symbol)?,
-            Char => write!(f, "'{}'", symbol)?,
-            Str => write!(f, "\"{}\"", symbol)?,
+            Byte => write!(f, "b'{symbol}'")?,
+            Char => write!(f, "'{symbol}'")?,
+            Str => write!(f, "\"{symbol}\"")?,
             StrRaw(n) => write!(
                 f,
                 "r{delim}\"{string}\"{delim}",
                 delim = "#".repeat(n as usize),
                 string = symbol
             )?,
-            ByteStr => write!(f, "b\"{}\"", symbol)?,
+            ByteStr => write!(f, "b\"{symbol}\"")?,
             ByteStrRaw(n) => write!(
                 f,
                 "br{delim}\"{string}\"{delim}",
                 delim = "#".repeat(n as usize),
                 string = symbol
             )?,
-            Integer | Float | Bool | Err => write!(f, "{}", symbol)?,
+            Integer | Float | Bool | Err => write!(f, "{symbol}")?,
         }
 
         if let Some(suffix) = suffix {
-            write!(f, "{}", suffix)?;
+            write!(f, "{suffix}")?;
         }
 
         Ok(())
@@ -756,7 +756,7 @@ impl Token {
                 _ => return None,
             },
             SingleQuote => match joint.kind {
-                Ident(name, false) => Lifetime(Symbol::intern(&format!("'{}", name))),
+                Ident(name, false) => Lifetime(Symbol::intern(&format!("'{name}"))),
                 _ => return None,
             },
 
diff --git a/compiler/rustc_ast/src/tokenstream.rs b/compiler/rustc_ast/src/tokenstream.rs
index 29a5eb4b7c5..fabd43a1618 100644
--- a/compiler/rustc_ast/src/tokenstream.rs
+++ b/compiler/rustc_ast/src/tokenstream.rs
@@ -258,8 +258,7 @@ impl AttrTokenStream {
 
                         assert!(
                             found,
-                            "Failed to find trailing delimited group in: {:?}",
-                            target_tokens
+                            "Failed to find trailing delimited group in: {target_tokens:?}"
                         );
                     }
                     let mut flat: SmallVec<[_; 1]> = SmallVec::new();
diff --git a/compiler/rustc_ast/src/util/literal.rs b/compiler/rustc_ast/src/util/literal.rs
index 0daeecb53a8..74b842ac96e 100644
--- a/compiler/rustc_ast/src/util/literal.rs
+++ b/compiler/rustc_ast/src/util/literal.rs
@@ -34,7 +34,7 @@ pub enum LitError {
     InvalidIntSuffix,
     InvalidFloatSuffix,
     NonDecimalFloat(u32),
-    IntTooLarge,
+    IntTooLarge(u32),
 }
 
 impl LitKind {
@@ -168,7 +168,7 @@ impl fmt::Display for LitKind {
         match *self {
             LitKind::Byte(b) => {
                 let b: String = ascii::escape_default(b).map(Into::<char>::into).collect();
-                write!(f, "b'{}'", b)?;
+                write!(f, "b'{b}'")?;
             }
             LitKind::Char(ch) => write!(f, "'{}'", escape_char_symbol(ch))?,
             LitKind::Str(sym, StrStyle::Cooked) => write!(f, "\"{}\"", escape_string_symbol(sym))?,
@@ -192,7 +192,7 @@ impl fmt::Display for LitKind {
                 )?;
             }
             LitKind::Int(n, ty) => {
-                write!(f, "{}", n)?;
+                write!(f, "{n}")?;
                 match ty {
                     ast::LitIntType::Unsigned(ty) => write!(f, "{}", ty.name())?,
                     ast::LitIntType::Signed(ty) => write!(f, "{}", ty.name())?,
@@ -200,7 +200,7 @@ impl fmt::Display for LitKind {
                 }
             }
             LitKind::Float(symbol, ty) => {
-                write!(f, "{}", symbol)?;
+                write!(f, "{symbol}")?;
                 match ty {
                     ast::LitFloatType::Suffixed(ty) => write!(f, "{}", ty.name())?,
                     ast::LitFloatType::Unsuffixed => {}
@@ -333,6 +333,6 @@ fn integer_lit(symbol: Symbol, suffix: Option<Symbol>) -> Result<LitKind, LitErr
         // but these kinds of errors are already reported by the lexer.
         let from_lexer =
             base < 10 && s.chars().any(|c| c.to_digit(10).map_or(false, |d| d >= base));
-        if from_lexer { LitError::LexerError } else { LitError::IntTooLarge }
+        if from_lexer { LitError::LexerError } else { LitError::IntTooLarge(base) }
     })
 }
diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs
index dfef6ec70fc..941d3179587 100644
--- a/compiler/rustc_ast_lowering/src/asm.rs
+++ b/compiler/rustc_ast_lowering/src/asm.rs
@@ -104,7 +104,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                     Err(supported_abis) => {
                         let mut abis = format!("`{}`", supported_abis[0]);
                         for m in &supported_abis[1..] {
-                            let _ = write!(abis, ", `{}`", m);
+                            let _ = write!(abis, ", `{m}`");
                         }
                         self.tcx.sess.emit_err(InvalidAbiClobberAbi {
                             abi_span: *abi_span,
@@ -262,7 +262,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                             let sub = if !valid_modifiers.is_empty() {
                                 let mut mods = format!("`{}`", valid_modifiers[0]);
                                 for m in &valid_modifiers[1..] {
-                                    let _ = write!(mods, ", `{}`", m);
+                                    let _ = write!(mods, ", `{m}`");
                                 }
                                 InvalidAsmTemplateModifierRegClassSub::SupportModifier {
                                     class_name: class.name(),
diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs
index b6b242bfc27..ea30bed5ace 100644
--- a/compiler/rustc_ast_lowering/src/item.rs
+++ b/compiler/rustc_ast_lowering/src/item.rs
@@ -1051,7 +1051,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                     }
                     _ => {
                         // Replace the ident for bindings that aren't simple.
-                        let name = format!("__arg{}", index);
+                        let name = format!("__arg{index}");
                         let ident = Ident::from_str(&name);
 
                         (ident, false)
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index 83174afdb12..2e135aafb1e 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -296,7 +296,7 @@ impl std::fmt::Display for ImplTraitPosition {
             ImplTraitPosition::ImplReturn => "`impl` method return",
         };
 
-        write!(f, "{}", name)
+        write!(f, "{name}")
     }
 }
 
@@ -503,7 +503,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
 
     fn orig_local_def_id(&self, node: NodeId) -> LocalDefId {
         self.orig_opt_local_def_id(node)
-            .unwrap_or_else(|| panic!("no entry for node id: `{:?}`", node))
+            .unwrap_or_else(|| panic!("no entry for node id: `{node:?}`"))
     }
 
     /// Given the id of some node in the AST, finds the `LocalDefId` associated with it by the name
@@ -524,7 +524,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
     }
 
     fn local_def_id(&self, node: NodeId) -> LocalDefId {
-        self.opt_local_def_id(node).unwrap_or_else(|| panic!("no entry for node id: `{:?}`", node))
+        self.opt_local_def_id(node).unwrap_or_else(|| panic!("no entry for node id: `{node:?}`"))
     }
 
     /// Get the previously recorded `to` local def id given the `from` local def id, obtained using
@@ -2197,7 +2197,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
     fn lower_trait_ref(&mut self, p: &TraitRef, itctx: &ImplTraitContext) -> hir::TraitRef<'hir> {
         let path = match self.lower_qpath(p.ref_id, &None, &p.path, ParamMode::Explicit, itctx) {
             hir::QPath::Resolved(None, path) => path,
-            qpath => panic!("lower_trait_ref: unexpected QPath `{:?}`", qpath),
+            qpath => panic!("lower_trait_ref: unexpected QPath `{qpath:?}`"),
         };
         hir::TraitRef { path, hir_ref_id: self.lower_node_id(p.ref_id) }
     }
diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs
index 104cdd3a8e1..6a8064b0e87 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state.rs
@@ -191,23 +191,23 @@ fn doc_comment_to_string(
     data: Symbol,
 ) -> String {
     match (comment_kind, attr_style) {
-        (CommentKind::Line, ast::AttrStyle::Outer) => format!("///{}", data),
-        (CommentKind::Line, ast::AttrStyle::Inner) => format!("//!{}", data),
-        (CommentKind::Block, ast::AttrStyle::Outer) => format!("/**{}*/", data),
-        (CommentKind::Block, ast::AttrStyle::Inner) => format!("/*!{}*/", data),
+        (CommentKind::Line, ast::AttrStyle::Outer) => format!("///{data}"),
+        (CommentKind::Line, ast::AttrStyle::Inner) => format!("//!{data}"),
+        (CommentKind::Block, ast::AttrStyle::Outer) => format!("/**{data}*/"),
+        (CommentKind::Block, ast::AttrStyle::Inner) => format!("/*!{data}*/"),
     }
 }
 
 pub fn literal_to_string(lit: token::Lit) -> String {
     let token::Lit { kind, symbol, suffix } = lit;
     let mut out = match kind {
-        token::Byte => format!("b'{}'", symbol),
-        token::Char => format!("'{}'", symbol),
-        token::Str => format!("\"{}\"", symbol),
+        token::Byte => format!("b'{symbol}'"),
+        token::Char => format!("'{symbol}'"),
+        token::Str => format!("\"{symbol}\""),
         token::StrRaw(n) => {
             format!("r{delim}\"{string}\"{delim}", delim = "#".repeat(n as usize), string = symbol)
         }
-        token::ByteStr => format!("b\"{}\"", symbol),
+        token::ByteStr => format!("b\"{symbol}\""),
         token::ByteStrRaw(n) => {
             format!("br{delim}\"{string}\"{delim}", delim = "#".repeat(n as usize), string = symbol)
         }
diff --git a/compiler/rustc_ast_pretty/src/pprust/state/item.rs b/compiler/rustc_ast_pretty/src/pprust/state/item.rs
index 5b6a07721e2..bf2c73a66a2 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state/item.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state/item.rs
@@ -411,9 +411,9 @@ impl<'a> State<'a> {
             ast::VisibilityKind::Restricted { path, shorthand, .. } => {
                 let path = Self::to_string(|s| s.print_path(path, false, 0));
                 if *shorthand && (path == "crate" || path == "self" || path == "super") {
-                    self.word_nbsp(format!("pub({})", path))
+                    self.word_nbsp(format!("pub({path})"))
                 } else {
-                    self.word_nbsp(format!("pub(in {})", path))
+                    self.word_nbsp(format!("pub(in {path})"))
                 }
             }
             ast::VisibilityKind::Inherited => {}
diff --git a/compiler/rustc_attr/src/builtin.rs b/compiler/rustc_attr/src/builtin.rs
index ab5e19050ea..40531c1c164 100644
--- a/compiler/rustc_attr/src/builtin.rs
+++ b/compiler/rustc_attr/src/builtin.rs
@@ -619,7 +619,7 @@ fn try_gate_cfg(name: Symbol, span: Span, sess: &ParseSess, features: Option<&Fe
 fn gate_cfg(gated_cfg: &GatedCfg, cfg_span: Span, sess: &ParseSess, features: &Features) {
     let (cfg, feature, has_feature) = gated_cfg;
     if !has_feature(features) && !cfg_span.allows_unstable(*feature) {
-        let explain = format!("`cfg({})` is experimental and subject to change", cfg);
+        let explain = format!("`cfg({cfg})` is experimental and subject to change");
         feature_err(sess, *feature, cfg_span, &explain).emit();
     }
 }
@@ -975,7 +975,7 @@ pub fn find_repr_attrs(sess: &Session, attr: &Attribute) -> Vec<ReprAttr> {
 }
 
 pub fn parse_repr_attr(sess: &Session, attr: &Attribute) -> Vec<ReprAttr> {
-    assert!(attr.has_name(sym::repr), "expected `#[repr(..)]`, found: {:?}", attr);
+    assert!(attr.has_name(sym::repr), "expected `#[repr(..)]`, found: {attr:?}");
     use ReprAttr::*;
     let mut acc = Vec::new();
     let diagnostic = &sess.parse_sess.span_diagnostic;
diff --git a/compiler/rustc_attr/src/session_diagnostics.rs b/compiler/rustc_attr/src/session_diagnostics.rs
index 91c6bcb08a0..3ba7a3c5336 100644
--- a/compiler/rustc_attr/src/session_diagnostics.rs
+++ b/compiler/rustc_attr/src/session_diagnostics.rs
@@ -51,7 +51,7 @@ pub(crate) struct UnknownMetaItem<'a> {
 // Manual implementation to be able to format `expected` items correctly.
 impl<'a> IntoDiagnostic<'a> for UnknownMetaItem<'_> {
     fn into_diagnostic(self, handler: &'a Handler) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
-        let expected = self.expected.iter().map(|name| format!("`{}`", name)).collect::<Vec<_>>();
+        let expected = self.expected.iter().map(|name| format!("`{name}`")).collect::<Vec<_>>();
         let mut diag = handler.struct_span_err_with_code(
             self.span,
             fluent::attr_unknown_meta_item,
diff --git a/compiler/rustc_borrowck/src/borrowck_errors.rs b/compiler/rustc_borrowck/src/borrowck_errors.rs
index e4942f9b666..a4943d11204 100644
--- a/compiler/rustc_borrowck/src/borrowck_errors.rs
+++ b/compiler/rustc_borrowck/src/borrowck_errors.rs
@@ -440,15 +440,14 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
         closure_kind: &str,
         borrowed_path: &str,
         capture_span: Span,
+        scope: &str,
     ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
         let mut err = struct_span_err!(
             self,
             closure_span,
             E0373,
-            "{} may outlive the current function, but it borrows {}, which is owned by the current \
-             function",
-            closure_kind,
-            borrowed_path,
+            "{closure_kind} may outlive the current {scope}, but it borrows {borrowed_path}, \
+             which is owned by the current {scope}",
         );
         err.span_label(capture_span, format!("{} is borrowed here", borrowed_path))
             .span_label(closure_span, format!("may outlive borrowed value {}", borrowed_path));
diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index 3c3cb8c6b9c..d99bfc01a42 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -394,7 +394,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                     }
                 }
                 let typeck = self.infcx.tcx.typeck(self.mir_def_id());
-                let hir_id = hir.get_parent_node(expr.hir_id);
+                let hir_id = hir.parent_id(expr.hir_id);
                 if let Some(parent) = hir.find(hir_id) {
                     let (def_id, args, offset) = if let hir::Node::Expr(parent_expr) = parent
                         && let hir::ExprKind::MethodCall(_, _, args, _) = parent_expr.kind
@@ -527,26 +527,21 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             // that are *partially* initialized by assigning to a field of an uninitialized
             // binding. We differentiate between them for more accurate wording here.
             "isn't fully initialized"
-        } else if spans
-            .iter()
-            .filter(|i| {
-                // We filter these to avoid misleading wording in cases like the following,
-                // where `x` has an `init`, but it is in the same place we're looking at:
-                // ```
-                // let x;
-                // x += 1;
-                // ```
-                !i.contains(span)
-                    // We filter these to avoid incorrect main message on `match-cfg-fake-edges.rs`
-                        && !visitor
-                            .errors
-                            .iter()
-                            .map(|(sp, _)| *sp)
-                            .any(|sp| span < sp && !sp.contains(span))
-            })
-            .count()
-            == 0
-        {
+        } else if !spans.iter().any(|i| {
+            // We filter these to avoid misleading wording in cases like the following,
+            // where `x` has an `init`, but it is in the same place we're looking at:
+            // ```
+            // let x;
+            // x += 1;
+            // ```
+            !i.contains(span)
+            // We filter these to avoid incorrect main message on `match-cfg-fake-edges.rs`
+            && !visitor
+                .errors
+                .iter()
+                .map(|(sp, _)| *sp)
+                .any(|sp| span < sp && !sp.contains(span))
+        }) {
             show_assign_sugg = true;
             "isn't initialized"
         } else {
@@ -1430,6 +1425,21 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             // and `move` will not help here.
             (
                 Some(name),
+                BorrowExplanation::UsedLater(LaterUseKind::ClosureCapture, var_or_use_span, _),
+            ) => self.report_escaping_closure_capture(
+                borrow_spans,
+                borrow_span,
+                &RegionName {
+                    name: self.synthesize_region_name(),
+                    source: RegionNameSource::Static,
+                },
+                ConstraintCategory::CallArgument(None),
+                var_or_use_span,
+                &format!("`{}`", name),
+                "block",
+            ),
+            (
+                Some(name),
                 BorrowExplanation::MustBeValidFor {
                     category:
                         category @ (ConstraintCategory::Return(_)
@@ -1448,6 +1458,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                     category,
                     span,
                     &format!("`{}`", name),
+                    "function",
                 ),
             (
                 name,
@@ -1900,6 +1911,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         Some(err)
     }
 
+    #[instrument(level = "debug", skip(self))]
     fn report_escaping_closure_capture(
         &mut self,
         use_span: UseSpans<'tcx>,
@@ -1908,6 +1920,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         category: ConstraintCategory<'tcx>,
         constraint_span: Span,
         captured_var: &str,
+        scope: &str,
     ) -> DiagnosticBuilder<'cx, ErrorGuaranteed> {
         let tcx = self.infcx.tcx;
         let args_span = use_span.args_or_use();
@@ -1938,8 +1951,13 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             None => "closure",
         };
 
-        let mut err =
-            self.cannot_capture_in_long_lived_closure(args_span, kind, captured_var, var_span);
+        let mut err = self.cannot_capture_in_long_lived_closure(
+            args_span,
+            kind,
+            captured_var,
+            var_span,
+            scope,
+        );
         err.span_suggestion_verbose(
             sugg_span,
             &format!(
@@ -1961,10 +1979,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                 if matches!(use_span.generator_kind(), Some(GeneratorKind::Async(_))) {
                     err.note(
                         "async blocks are not executed immediately and must either take a \
-                    reference or ownership of outside variables they use",
+                         reference or ownership of outside variables they use",
                     );
                 } else {
-                    let msg = format!("function requires argument type to outlive `{}`", fr_name);
+                    let msg = format!("{scope} requires argument type to outlive `{fr_name}`");
                     err.span_note(constraint_span, &msg);
                 }
             }
diff --git a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
index 00f5e8a8397..c4ae30151c4 100644
--- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
@@ -444,6 +444,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
     /// First span returned points to the location of the conflicting use
     /// Second span if `Some` is returned in the case of closures and points
     /// to the use of the path
+    #[instrument(level = "debug", skip(self))]
     fn later_use_kind(
         &self,
         borrow: &BorrowData<'tcx>,
@@ -461,11 +462,18 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                 let block = &self.body.basic_blocks[location.block];
 
                 let kind = if let Some(&Statement {
-                    kind: StatementKind::FakeRead(box (FakeReadCause::ForLet(_), _)),
+                    kind: StatementKind::FakeRead(box (FakeReadCause::ForLet(_), place)),
                     ..
                 }) = block.statements.get(location.statement_index)
                 {
-                    LaterUseKind::FakeLetRead
+                    if let Some(l) = place.as_local()
+                        && let local_decl = &self.body.local_decls[l]
+                        && local_decl.ty.is_closure()
+                    {
+                        LaterUseKind::ClosureCapture
+                    } else {
+                        LaterUseKind::FakeLetRead
+                    }
                 } else if self.was_captured_by_trait_object(borrow) {
                     LaterUseKind::TraitCapture
                 } else if location.statement_index == block.statements.len() {
diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
index 6f6d1b01bd4..09ef84f7cbb 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
@@ -344,20 +344,25 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
                     } else {
                         err.span_help(source_info.span, "try removing `&mut` here");
                     }
-                } else if decl.mutability == Mutability::Not
-                    && !matches!(
+                } else if decl.mutability == Mutability::Not {
+                    if matches!(
                         decl.local_info,
                         Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::ImplicitSelf(
                             hir::ImplicitSelfKind::MutRef
-                        ))))
-                    )
-                {
-                    err.span_suggestion_verbose(
-                        decl.source_info.span.shrink_to_lo(),
-                        "consider making the binding mutable",
-                        "mut ",
-                        Applicability::MachineApplicable,
-                    );
+                        ),)))
+                    ) {
+                        err.note(
+                            "as `Self` may be unsized, this call attempts to take `&mut &mut self`",
+                        );
+                        err.note("however, `&mut self` expands to `self: &mut Self`, therefore `self` cannot be borrowed mutably");
+                    } else {
+                        err.span_suggestion_verbose(
+                            decl.source_info.span.shrink_to_lo(),
+                            "consider making the binding mutable",
+                            "mut ",
+                            Applicability::MachineApplicable,
+                        );
+                    };
                 }
             }
 
@@ -1004,7 +1009,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
         let hir = self.infcx.tcx.hir();
         let closure_id = self.mir_hir_id();
         let closure_span = self.infcx.tcx.def_span(self.mir_def_id());
-        let fn_call_id = hir.get_parent_node(closure_id);
+        let fn_call_id = hir.parent_id(closure_id);
         let node = hir.get(fn_call_id);
         let def_id = hir.enclosing_body_owner(fn_call_id);
         let mut look_at_return = true;
diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
index bcc8afbfd95..cc33ef14756 100644
--- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
@@ -4,9 +4,9 @@
 
 use rustc_data_structures::fx::FxIndexSet;
 use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, MultiSpan};
+use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_hir::intravisit::Visitor;
-use rustc_hir::{self as hir, Item, ItemKind, Node};
 use rustc_infer::infer::{
     error_reporting::nice_region_error::{
         self, find_anon_type, find_param_with_region, suggest_adding_lifetime_params,
@@ -192,6 +192,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
         // buffered in the `MirBorrowckCtxt`.
 
         let mut outlives_suggestion = OutlivesSuggestionBuilder::default();
+        let mut last_unexpected_hidden_region: Option<(Span, Ty<'_>, ty::OpaqueTypeKey<'tcx>)> =
+            None;
 
         for nll_error in nll_errors.into_iter() {
             match nll_error {
@@ -234,13 +236,19 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
                     let named_ty = self.regioncx.name_regions(self.infcx.tcx, hidden_ty);
                     let named_key = self.regioncx.name_regions(self.infcx.tcx, key);
                     let named_region = self.regioncx.name_regions(self.infcx.tcx, member_region);
-                    self.buffer_error(unexpected_hidden_region_diagnostic(
+                    let mut diag = unexpected_hidden_region_diagnostic(
                         self.infcx.tcx,
                         span,
                         named_ty,
                         named_region,
                         named_key,
-                    ));
+                    );
+                    if last_unexpected_hidden_region != Some((span, named_ty, named_key)) {
+                        self.buffer_error(diag);
+                        last_unexpected_hidden_region = Some((span, named_ty, named_key));
+                    } else {
+                        diag.delay_as_bug();
+                    }
                 }
 
                 RegionErrorKind::BoundUniversalRegionError {
@@ -291,71 +299,6 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
         outlives_suggestion.add_suggestion(self);
     }
 
-    fn get_impl_ident_and_self_ty_from_trait(
-        &self,
-        def_id: DefId,
-        trait_objects: &FxIndexSet<DefId>,
-    ) -> Option<(Ident, &'tcx hir::Ty<'tcx>)> {
-        let tcx = self.infcx.tcx;
-        match tcx.hir().get_if_local(def_id) {
-            Some(Node::ImplItem(impl_item)) => {
-                match tcx.hir().find_by_def_id(tcx.hir().get_parent_item(impl_item.hir_id()).def_id)
-                {
-                    Some(Node::Item(Item {
-                        kind: ItemKind::Impl(hir::Impl { self_ty, .. }),
-                        ..
-                    })) => Some((impl_item.ident, self_ty)),
-                    _ => None,
-                }
-            }
-            Some(Node::TraitItem(trait_item)) => {
-                let trait_did = tcx.hir().get_parent_item(trait_item.hir_id());
-                match tcx.hir().find_by_def_id(trait_did.def_id) {
-                    Some(Node::Item(Item { kind: ItemKind::Trait(..), .. })) => {
-                        // The method being called is defined in the `trait`, but the `'static`
-                        // obligation comes from the `impl`. Find that `impl` so that we can point
-                        // at it in the suggestion.
-                        let trait_did = trait_did.to_def_id();
-                        match tcx
-                            .hir()
-                            .trait_impls(trait_did)
-                            .iter()
-                            .filter_map(|&impl_did| {
-                                match tcx.hir().get_if_local(impl_did.to_def_id()) {
-                                    Some(Node::Item(Item {
-                                        kind: ItemKind::Impl(hir::Impl { self_ty, .. }),
-                                        ..
-                                    })) if trait_objects.iter().all(|did| {
-                                        // FIXME: we should check `self_ty` against the receiver
-                                        // type in the `UnifyReceiver` context, but for now, use
-                                        // this imperfect proxy. This will fail if there are
-                                        // multiple `impl`s for the same trait like
-                                        // `impl Foo for Box<dyn Bar>` and `impl Foo for dyn Bar`.
-                                        // In that case, only the first one will get suggestions.
-                                        let mut traits = vec![];
-                                        let mut hir_v = HirTraitObjectVisitor(&mut traits, *did);
-                                        hir_v.visit_ty(self_ty);
-                                        !traits.is_empty()
-                                    }) =>
-                                    {
-                                        Some(self_ty)
-                                    }
-                                    _ => None,
-                                }
-                            })
-                            .next()
-                        {
-                            Some(self_ty) => Some((trait_item.ident, self_ty)),
-                            _ => None,
-                        }
-                    }
-                    _ => None,
-                }
-            }
-            _ => None,
-        }
-    }
-
     /// Report an error because the universal region `fr` was required to outlive
     /// `outlived_fr` but it is not known to do so. For example:
     ///
@@ -795,6 +738,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
                 Some(arg),
                 captures,
                 Some((param.param_ty_span, param.param_ty.to_string())),
+                self.infcx.tcx.is_suitable_region(f).map(|r| r.def_id),
             );
         }
     }
@@ -850,7 +794,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
         visitor.visit_ty(param.param_ty);
 
         let Some((ident, self_ty)) =
-            self.get_impl_ident_and_self_ty_from_trait(instance.def_id(), &visitor.0) else {return};
+            NiceRegionError::get_impl_ident_and_self_ty_from_trait(tcx, instance.def_id(), &visitor.0) else { return; };
 
         self.suggest_constrain_dyn_trait_in_impl(diag, &visitor.0, ident, self_ty);
     }
diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs
index dbd4cac7b14..579ce90a760 100644
--- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs
@@ -200,7 +200,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
     /// increment the counter.
     ///
     /// This is _not_ idempotent. Call `give_region_a_name` when possible.
-    fn synthesize_region_name(&self) -> Symbol {
+    pub(crate) fn synthesize_region_name(&self) -> Symbol {
         let c = self.next_region_name.replace_with(|counter| *counter + 1);
         Symbol::intern(&format!("'{:?}", c))
     }
diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs
index ae1bea008b6..278ffed0747 100644
--- a/compiler/rustc_borrowck/src/lib.rs
+++ b/compiler/rustc_borrowck/src/lib.rs
@@ -863,7 +863,6 @@ enum WriteKind {
 /// local place can be mutated.
 //
 // FIXME: @nikomatsakis suggested that this flag could be removed with the following modifications:
-// - Merge `check_access_permissions()` and `check_if_reassignment_to_immutable_state()`.
 // - Split `is_mutable()` into `is_assignable()` (can be directly assigned) and
 //   `is_declared_mutable()`.
 // - Take flow state into consideration in `is_assignable()` for local variables.
@@ -1132,20 +1131,6 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         // Write of P[i] or *P requires P init'd.
         self.check_if_assigned_path_is_moved(location, place_span, flow_state);
 
-        // Special case: you can assign an immutable local variable
-        // (e.g., `x = ...`) so long as it has never been initialized
-        // before (at this point in the flow).
-        if let Some(local) = place_span.0.as_local() {
-            if let Mutability::Not = self.body.local_decls[local].mutability {
-                // check for reassignments to immutable local variables
-                self.check_if_reassignment_to_immutable_state(
-                    location, local, place_span, flow_state,
-                );
-                return;
-            }
-        }
-
-        // Otherwise, use the normal access permission rules.
         self.access_place(
             location,
             place_span,
@@ -1554,24 +1539,6 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         }
     }
 
-    fn check_if_reassignment_to_immutable_state(
-        &mut self,
-        location: Location,
-        local: Local,
-        place_span: (Place<'tcx>, Span),
-        flow_state: &Flows<'cx, 'tcx>,
-    ) {
-        debug!("check_if_reassignment_to_immutable_state({:?})", local);
-
-        // Check if any of the initializations of `local` have happened yet:
-        if let Some(init_index) = self.is_local_ever_initialized(local, flow_state) {
-            // And, if so, report an error.
-            let init = &self.move_data.inits[init_index];
-            let span = init.span(&self.body);
-            self.report_illegal_reassignment(location, place_span, span, place_span.0);
-        }
-    }
-
     fn check_if_full_path_is_moved(
         &mut self,
         location: Location,
@@ -2037,12 +2004,19 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         // partial initialization, do not complain about mutability
         // errors except for actual mutation (as opposed to an attempt
         // to do a partial initialization).
-        let previously_initialized =
-            self.is_local_ever_initialized(place.local, flow_state).is_some();
+        let previously_initialized = self.is_local_ever_initialized(place.local, flow_state);
 
         // at this point, we have set up the error reporting state.
-        if previously_initialized {
-            self.report_mutability_error(place, span, the_place_err, error_access, location);
+        if let Some(init_index) = previously_initialized {
+            if let (AccessKind::Mutate, Some(_)) = (error_access, place.as_local()) {
+                // If this is a mutate access to an immutable local variable with no projections
+                // report the error as an illegal reassignment
+                let init = &self.move_data.inits[init_index];
+                let assigned_span = init.span(&self.body);
+                self.report_illegal_reassignment(location, (place, span), assigned_span, place);
+            } else {
+                self.report_mutability_error(place, span, the_place_err, error_access, location)
+            }
             true
         } else {
             false
diff --git a/compiler/rustc_builtin_macros/src/format.rs b/compiler/rustc_builtin_macros/src/format.rs
index 63bc0d552c1..b2b7b9d75bd 100644
--- a/compiler/rustc_builtin_macros/src/format.rs
+++ b/compiler/rustc_builtin_macros/src/format.rs
@@ -638,7 +638,7 @@ fn report_missing_placeholders(
                 if show_doc_note {
                     diag.note(concat!(
                         stringify!($kind),
-                        " formatting not supported; see the documentation for `std::fmt`",
+                        " formatting is not supported; see the documentation for `std::fmt`",
                     ));
                 }
                 if suggestions.len() > 0 {
diff --git a/compiler/rustc_codegen_gcc/src/builder.rs b/compiler/rustc_codegen_gcc/src/builder.rs
index effb2de4827..a92242b2615 100644
--- a/compiler/rustc_codegen_gcc/src/builder.rs
+++ b/compiler/rustc_codegen_gcc/src/builder.rs
@@ -1244,7 +1244,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
     ) -> RValue<'gcc> {
         // FIXME(antoyo): remove when having a proper API.
         let gcc_func = unsafe { std::mem::transmute(func) };
-        let call = if self.functions.borrow().values().find(|value| **value == gcc_func).is_some() {
+        let call = if self.functions.borrow().values().any(|value| *value == gcc_func) {
             self.function_call(func, args, funclet)
         }
         else {
diff --git a/compiler/rustc_codegen_gcc/src/context.rs b/compiler/rustc_codegen_gcc/src/context.rs
index 837708aeb0e..4424b31c054 100644
--- a/compiler/rustc_codegen_gcc/src/context.rs
+++ b/compiler/rustc_codegen_gcc/src/context.rs
@@ -253,7 +253,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
 
     pub fn rvalue_as_function(&self, value: RValue<'gcc>) -> Function<'gcc> {
         let function: Function<'gcc> = unsafe { std::mem::transmute(value) };
-        debug_assert!(self.functions.borrow().values().find(|value| **value == function).is_some(),
+        debug_assert!(self.functions.borrow().values().any(|value| *value == function),
             "{:?} ({:?}) is not a function", value, value.get_type());
         function
     }
diff --git a/compiler/rustc_codegen_llvm/src/abi.rs b/compiler/rustc_codegen_llvm/src/abi.rs
index a6fd2a7de6b..546540dfd76 100644
--- a/compiler/rustc_codegen_llvm/src/abi.rs
+++ b/compiler/rustc_codegen_llvm/src/abi.rs
@@ -34,13 +34,6 @@ pub trait ArgAttributesExt {
     );
 }
 
-fn should_use_mutable_noalias(cx: &CodegenCx<'_, '_>) -> bool {
-    // LLVM prior to version 12 had known miscompiles in the presence of
-    // noalias attributes (see #54878), but we don't support earlier
-    // versions at all anymore. We now enable mutable noalias by default.
-    cx.tcx.sess.opts.unstable_opts.mutable_noalias.unwrap_or(true)
-}
-
 const ABI_AFFECTING_ATTRIBUTES: [(ArgAttribute, llvm::AttributeKind); 1] =
     [(ArgAttribute::InReg, llvm::AttributeKind::InReg)];
 
@@ -88,9 +81,6 @@ fn get_attrs<'ll>(this: &ArgAttributes, cx: &CodegenCx<'ll, '_>) -> SmallVec<[&'
                 attrs.push(llattr.create_attr(cx.llcx));
             }
         }
-        if regular.contains(ArgAttribute::NoAliasMutRef) && should_use_mutable_noalias(cx) {
-            attrs.push(llvm::AttributeKind::NoAlias.create_attr(cx.llcx));
-        }
     } else if cx.tcx.sess.opts.unstable_opts.sanitizer.contains(SanitizerSet::MEMORY) {
         // If we're not optimising, *but* memory sanitizer is on, emit noundef, since it affects
         // memory sanitizer's behavior.
diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs
index 1ce48f82e1c..680d810f78e 100644
--- a/compiler/rustc_codegen_llvm/src/intrinsic.rs
+++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs
@@ -8,8 +8,8 @@ use crate::va_arg::emit_va_arg;
 use crate::value::Value;
 
 use rustc_codegen_ssa::base::{compare_simd_types, wants_msvc_seh};
-use rustc_codegen_ssa::common::span_invalid_monomorphization_error;
 use rustc_codegen_ssa::common::{IntPredicate, TypeKind};
+use rustc_codegen_ssa::errors::{ExpectedPointerMutability, InvalidMonomorphization};
 use rustc_codegen_ssa::mir::operand::OperandRef;
 use rustc_codegen_ssa::mir::place::PlaceRef;
 use rustc_codegen_ssa::traits::*;
@@ -284,15 +284,11 @@ impl<'ll, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'_, 'll, 'tcx> {
                         _ => bug!(),
                     },
                     None => {
-                        span_invalid_monomorphization_error(
-                            tcx.sess,
+                        tcx.sess.emit_err(InvalidMonomorphization::BasicIntegerType {
                             span,
-                            &format!(
-                                "invalid monomorphization of `{}` intrinsic: \
-                                      expected basic integer type, found `{}`",
-                                name, ty
-                            ),
-                        );
+                            name,
+                            ty,
+                        });
                         return;
                     }
                 }
@@ -838,40 +834,24 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
     llret_ty: &'ll Type,
     span: Span,
 ) -> Result<&'ll Value, ()> {
-    // macros for error handling:
-    #[allow(unused_macro_rules)]
-    macro_rules! emit_error {
-        ($msg: tt) => {
-            emit_error!($msg, )
-        };
-        ($msg: tt, $($fmt: tt)*) => {
-            span_invalid_monomorphization_error(
-                bx.sess(), span,
-                &format!(concat!("invalid monomorphization of `{}` intrinsic: ", $msg),
-                         name, $($fmt)*));
-        }
-    }
-
     macro_rules! return_error {
-        ($($fmt: tt)*) => {
-            {
-                emit_error!($($fmt)*);
-                return Err(());
-            }
-        }
+        ($diag: expr) => {{
+            bx.sess().emit_err($diag);
+            return Err(());
+        }};
     }
 
     macro_rules! require {
-        ($cond: expr, $($fmt: tt)*) => {
+        ($cond: expr, $diag: expr) => {
             if !$cond {
-                return_error!($($fmt)*);
+                return_error!($diag);
             }
         };
     }
 
     macro_rules! require_simd {
-        ($ty: expr, $position: expr) => {
-            require!($ty.is_simd(), "expected SIMD {} type, found non-SIMD `{}`", $position, $ty)
+        ($ty: expr, $diag: expr) => {
+            require!($ty.is_simd(), $diag)
         };
     }
 
@@ -881,7 +861,11 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
     let arg_tys = sig.inputs();
 
     if name == sym::simd_select_bitmask {
-        require_simd!(arg_tys[1], "argument");
+        require_simd!(
+            arg_tys[1],
+            InvalidMonomorphization::SimdArgument { span, name, ty: arg_tys[1] }
+        );
+
         let (len, _) = arg_tys[1].simd_size_and_type(bx.tcx());
 
         let expected_int_bits = (len.max(8) - 1).next_power_of_two();
@@ -902,12 +886,13 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
                 let ptr = bx.pointercast(place.llval, bx.cx.type_ptr_to(int_ty));
                 bx.load(int_ty, ptr, Align::ONE)
             }
-            _ => return_error!(
-                "invalid bitmask `{}`, expected `u{}` or `[u8; {}]`",
+            _ => return_error!(InvalidMonomorphization::InvalidBitmask {
+                span,
+                name,
                 mask_ty,
                 expected_int_bits,
                 expected_bytes
-            ),
+            }),
         };
 
         let i1 = bx.type_i1();
@@ -919,7 +904,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
     }
 
     // every intrinsic below takes a SIMD vector as its first argument
-    require_simd!(arg_tys[0], "input");
+    require_simd!(arg_tys[0], InvalidMonomorphization::SimdInput { span, name, ty: arg_tys[0] });
     let in_ty = arg_tys[0];
 
     let comparison = match name {
@@ -934,23 +919,24 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
 
     let (in_len, in_elem) = arg_tys[0].simd_size_and_type(bx.tcx());
     if let Some(cmp_op) = comparison {
-        require_simd!(ret_ty, "return");
+        require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty });
 
         let (out_len, out_ty) = ret_ty.simd_size_and_type(bx.tcx());
+
         require!(
             in_len == out_len,
-            "expected return type with length {} (same as input type `{}`), \
-             found `{}` with length {}",
-            in_len,
-            in_ty,
-            ret_ty,
-            out_len
+            InvalidMonomorphization::ReturnLengthInputType {
+                span,
+                name,
+                in_len,
+                in_ty,
+                ret_ty,
+                out_len
+            }
         );
         require!(
             bx.type_kind(bx.element_type(llret_ty)) == TypeKind::Integer,
-            "expected return type with integer elements, found `{}` with non-integer `{}`",
-            ret_ty,
-            out_ty
+            InvalidMonomorphization::ReturnIntegerType { span, name, ret_ty, out_ty }
         );
 
         return Ok(compare_simd_types(
@@ -975,10 +961,11 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
                         span_bug!(span, "could not evaluate shuffle index array length")
                     })
                 }
-                _ => return_error!(
-                    "simd_shuffle index must be an array of `u32`, got `{}`",
-                    args[2].layout.ty
-                ),
+                _ => return_error!(InvalidMonomorphization::SimdShuffle {
+                    span,
+                    name,
+                    ty: args[2].layout.ty
+                }),
             }
         } else {
             stripped.parse().unwrap_or_else(|_| {
@@ -986,23 +973,15 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
             })
         };
 
-        require_simd!(ret_ty, "return");
+        require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty });
         let (out_len, out_ty) = ret_ty.simd_size_and_type(bx.tcx());
         require!(
             out_len == n,
-            "expected return type of length {}, found `{}` with length {}",
-            n,
-            ret_ty,
-            out_len
+            InvalidMonomorphization::ReturnLength { span, name, in_len: n, ret_ty, out_len }
         );
         require!(
             in_elem == out_ty,
-            "expected return element type `{}` (element of input `{}`), \
-             found `{}` with element type `{}`",
-            in_elem,
-            in_ty,
-            ret_ty,
-            out_ty
+            InvalidMonomorphization::ReturnElement { span, name, in_elem, in_ty, ret_ty, out_ty }
         );
 
         let total_len = u128::from(in_len) * 2;
@@ -1015,15 +994,20 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
                 let val = bx.const_get_elt(vector, i as u64);
                 match bx.const_to_opt_u128(val, true) {
                     None => {
-                        emit_error!("shuffle index #{} is not a constant", arg_idx);
+                        bx.sess().emit_err(InvalidMonomorphization::ShuffleIndexNotConstant {
+                            span,
+                            name,
+                            arg_idx,
+                        });
                         None
                     }
                     Some(idx) if idx >= total_len => {
-                        emit_error!(
-                            "shuffle index #{} is out of bounds (limit {})",
+                        bx.sess().emit_err(InvalidMonomorphization::ShuffleIndexOutOfBounds {
+                            span,
+                            name,
                             arg_idx,
-                            total_len
-                        );
+                            total_len,
+                        });
                         None
                     }
                     Some(idx) => Some(bx.const_i32(idx as i32)),
@@ -1044,10 +1028,13 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
     if name == sym::simd_insert {
         require!(
             in_elem == arg_tys[2],
-            "expected inserted type `{}` (element of input `{}`), found `{}`",
-            in_elem,
-            in_ty,
-            arg_tys[2]
+            InvalidMonomorphization::InsertedType {
+                span,
+                name,
+                in_elem,
+                in_ty,
+                out_ty: arg_tys[2]
+            }
         );
         return Ok(bx.insert_element(
             args[0].immediate(),
@@ -1058,10 +1045,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
     if name == sym::simd_extract {
         require!(
             ret_ty == in_elem,
-            "expected return type `{}` (element of input `{}`), found `{}`",
-            in_elem,
-            in_ty,
-            ret_ty
+            InvalidMonomorphization::ReturnType { span, name, in_elem, in_ty, ret_ty }
         );
         return Ok(bx.extract_element(args[0].immediate(), args[1].immediate()));
     }
@@ -1069,17 +1053,18 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
     if name == sym::simd_select {
         let m_elem_ty = in_elem;
         let m_len = in_len;
-        require_simd!(arg_tys[1], "argument");
+        require_simd!(
+            arg_tys[1],
+            InvalidMonomorphization::SimdArgument { span, name, ty: arg_tys[1] }
+        );
         let (v_len, _) = arg_tys[1].simd_size_and_type(bx.tcx());
         require!(
             m_len == v_len,
-            "mismatched lengths: mask length `{}` != other vector length `{}`",
-            m_len,
-            v_len
+            InvalidMonomorphization::MismatchedLengths { span, name, m_len, v_len }
         );
         match m_elem_ty.kind() {
             ty::Int(_) => {}
-            _ => return_error!("mask element type is `{}`, expected `i_`", m_elem_ty),
+            _ => return_error!(InvalidMonomorphization::MaskType { span, name, ty: m_elem_ty }),
         }
         // truncate the mask to a vector of i1s
         let i1 = bx.type_i1();
@@ -1111,11 +1096,12 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
                 args[0].immediate(),
                 i.bit_width().unwrap_or_else(|| bx.data_layout().pointer_size.bits()),
             ),
-            _ => return_error!(
-                "vector argument `{}`'s element type `{}`, expected integer element type",
+            _ => return_error!(InvalidMonomorphization::VectorArgument {
+                span,
+                name,
                 in_ty,
                 in_elem
-            ),
+            }),
         };
 
         // Shift the MSB to the right by "in_elem_bitwidth - 1" into the first bit position.
@@ -1150,12 +1136,13 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
                 let ptr = bx.pointercast(ptr, bx.cx.type_ptr_to(array_ty));
                 return Ok(bx.load(array_ty, ptr, Align::ONE));
             }
-            _ => return_error!(
-                "cannot return `{}`, expected `u{}` or `[u8; {}]`",
+            _ => return_error!(InvalidMonomorphization::CannotReturn {
+                span,
+                name,
                 ret_ty,
                 expected_int_bits,
                 expected_bytes
-            ),
+            }),
         }
     }
 
@@ -1168,25 +1155,11 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
         span: Span,
         args: &[OperandRef<'tcx, &'ll Value>],
     ) -> Result<&'ll Value, ()> {
-        #[allow(unused_macro_rules)]
-        macro_rules! emit_error {
-            ($msg: tt) => {
-                emit_error!($msg, )
-            };
-            ($msg: tt, $($fmt: tt)*) => {
-                span_invalid_monomorphization_error(
-                    bx.sess(), span,
-                    &format!(concat!("invalid monomorphization of `{}` intrinsic: ", $msg),
-                             name, $($fmt)*));
-            }
-        }
         macro_rules! return_error {
-            ($($fmt: tt)*) => {
-                {
-                    emit_error!($($fmt)*);
-                    return Err(());
-                }
-            }
+            ($diag: expr) => {{
+                bx.sess().emit_err($diag);
+                return Err(());
+            }};
         }
 
         let (elem_ty_str, elem_ty) = if let ty::Float(f) = in_elem.kind() {
@@ -1194,16 +1167,15 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
             match f.bit_width() {
                 32 => ("f32", elem_ty),
                 64 => ("f64", elem_ty),
-                _ => {
-                    return_error!(
-                        "unsupported element type `{}` of floating-point vector `{}`",
-                        f.name_str(),
-                        in_ty
-                    );
-                }
+                _ => return_error!(InvalidMonomorphization::FloatingPointVector {
+                    span,
+                    name,
+                    f_ty: *f,
+                    in_ty,
+                }),
             }
         } else {
-            return_error!("`{}` is not a floating-point type", in_ty);
+            return_error!(InvalidMonomorphization::FloatingPointType { span, name, in_ty });
         };
 
         let vec_ty = bx.type_vector(elem_ty, in_len);
@@ -1225,7 +1197,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
             sym::simd_fsqrt => ("sqrt", bx.type_func(&[vec_ty], vec_ty)),
             sym::simd_round => ("round", bx.type_func(&[vec_ty], vec_ty)),
             sym::simd_trunc => ("trunc", bx.type_func(&[vec_ty], vec_ty)),
-            _ => return_error!("unrecognized intrinsic `{}`", name),
+            _ => return_error!(InvalidMonomorphization::UnrecognizedIntrinsic { span, name }),
         };
         let llvm_name = &format!("llvm.{0}.v{1}{2}", intr_name, in_len, elem_ty_str);
         let f = bx.declare_cfn(llvm_name, llvm::UnnamedAddr::No, fn_ty);
@@ -1319,37 +1291,48 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
         // * M: any integer width is supported, will be truncated to i1
 
         // All types must be simd vector types
-        require_simd!(in_ty, "first");
-        require_simd!(arg_tys[1], "second");
-        require_simd!(arg_tys[2], "third");
-        require_simd!(ret_ty, "return");
+        require_simd!(in_ty, InvalidMonomorphization::SimdFirst { span, name, ty: in_ty });
+        require_simd!(
+            arg_tys[1],
+            InvalidMonomorphization::SimdSecond { span, name, ty: arg_tys[1] }
+        );
+        require_simd!(
+            arg_tys[2],
+            InvalidMonomorphization::SimdThird { span, name, ty: arg_tys[2] }
+        );
+        require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty });
 
         // Of the same length:
         let (out_len, _) = arg_tys[1].simd_size_and_type(bx.tcx());
         let (out_len2, _) = arg_tys[2].simd_size_and_type(bx.tcx());
         require!(
             in_len == out_len,
-            "expected {} argument with length {} (same as input type `{}`), \
-             found `{}` with length {}",
-            "second",
-            in_len,
-            in_ty,
-            arg_tys[1],
-            out_len
+            InvalidMonomorphization::SecondArgumentLength {
+                span,
+                name,
+                in_len,
+                in_ty,
+                arg_ty: arg_tys[1],
+                out_len
+            }
         );
         require!(
             in_len == out_len2,
-            "expected {} argument with length {} (same as input type `{}`), \
-             found `{}` with length {}",
-            "third",
-            in_len,
-            in_ty,
-            arg_tys[2],
-            out_len2
+            InvalidMonomorphization::ThirdArgumentLength {
+                span,
+                name,
+                in_len,
+                in_ty,
+                arg_ty: arg_tys[2],
+                out_len: out_len2
+            }
         );
 
         // The return type must match the first argument type
-        require!(ret_ty == in_ty, "expected return type `{}`, found `{}`", in_ty, ret_ty);
+        require!(
+            ret_ty == in_ty,
+            InvalidMonomorphization::ExpectedReturnType { span, name, in_ty, ret_ty }
+        );
 
         // This counts how many pointers
         fn ptr_count(t: Ty<'_>) -> usize {
@@ -1376,15 +1359,15 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
             _ => {
                 require!(
                     false,
-                    "expected element type `{}` of second argument `{}` \
-                        to be a pointer to the element type `{}` of the first \
-                        argument `{}`, found `{}` != `*_ {}`",
-                    element_ty1,
-                    arg_tys[1],
-                    in_elem,
-                    in_ty,
-                    element_ty1,
-                    in_elem
+                    InvalidMonomorphization::ExpectedElementType {
+                        span,
+                        name,
+                        expected_element: element_ty1,
+                        second_arg: arg_tys[1],
+                        in_elem,
+                        in_ty,
+                        mutability: ExpectedPointerMutability::Not,
+                    }
                 );
                 unreachable!();
             }
@@ -1400,10 +1383,12 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
             _ => {
                 require!(
                     false,
-                    "expected element type `{}` of third argument `{}` \
-                                 to be a signed integer type",
-                    element_ty2,
-                    arg_tys[2]
+                    InvalidMonomorphization::ThirdArgElementType {
+                        span,
+                        name,
+                        expected_element: element_ty2,
+                        third_arg: arg_tys[2]
+                    }
                 );
             }
         }
@@ -1452,32 +1437,40 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
         // * M: any integer width is supported, will be truncated to i1
 
         // All types must be simd vector types
-        require_simd!(in_ty, "first");
-        require_simd!(arg_tys[1], "second");
-        require_simd!(arg_tys[2], "third");
+        require_simd!(in_ty, InvalidMonomorphization::SimdFirst { span, name, ty: in_ty });
+        require_simd!(
+            arg_tys[1],
+            InvalidMonomorphization::SimdSecond { span, name, ty: arg_tys[1] }
+        );
+        require_simd!(
+            arg_tys[2],
+            InvalidMonomorphization::SimdThird { span, name, ty: arg_tys[2] }
+        );
 
         // Of the same length:
         let (element_len1, _) = arg_tys[1].simd_size_and_type(bx.tcx());
         let (element_len2, _) = arg_tys[2].simd_size_and_type(bx.tcx());
         require!(
             in_len == element_len1,
-            "expected {} argument with length {} (same as input type `{}`), \
-            found `{}` with length {}",
-            "second",
-            in_len,
-            in_ty,
-            arg_tys[1],
-            element_len1
+            InvalidMonomorphization::SecondArgumentLength {
+                span,
+                name,
+                in_len,
+                in_ty,
+                arg_ty: arg_tys[1],
+                out_len: element_len1
+            }
         );
         require!(
             in_len == element_len2,
-            "expected {} argument with length {} (same as input type `{}`), \
-            found `{}` with length {}",
-            "third",
-            in_len,
-            in_ty,
-            arg_tys[2],
-            element_len2
+            InvalidMonomorphization::ThirdArgumentLength {
+                span,
+                name,
+                in_len,
+                in_ty,
+                arg_ty: arg_tys[2],
+                out_len: element_len2
+            }
         );
 
         // This counts how many pointers
@@ -1508,15 +1501,15 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
             _ => {
                 require!(
                     false,
-                    "expected element type `{}` of second argument `{}` \
-                        to be a pointer to the element type `{}` of the first \
-                        argument `{}`, found `{}` != `*mut {}`",
-                    element_ty1,
-                    arg_tys[1],
-                    in_elem,
-                    in_ty,
-                    element_ty1,
-                    in_elem
+                    InvalidMonomorphization::ExpectedElementType {
+                        span,
+                        name,
+                        expected_element: element_ty1,
+                        second_arg: arg_tys[1],
+                        in_elem,
+                        in_ty,
+                        mutability: ExpectedPointerMutability::Mut,
+                    }
                 );
                 unreachable!();
             }
@@ -1531,10 +1524,12 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
             _ => {
                 require!(
                     false,
-                    "expected element type `{}` of third argument `{}` \
-                         be a signed integer type",
-                    element_ty2,
-                    arg_tys[2]
+                    InvalidMonomorphization::ThirdArgElementType {
+                        span,
+                        name,
+                        expected_element: element_ty2,
+                        third_arg: arg_tys[2]
+                    }
                 );
             }
         }
@@ -1581,10 +1576,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
             if name == sym::$name {
                 require!(
                     ret_ty == in_elem,
-                    "expected return type `{}` (element of input `{}`), found `{}`",
-                    in_elem,
-                    in_ty,
-                    ret_ty
+                    InvalidMonomorphization::ReturnType { span, name, in_elem, in_ty, ret_ty }
                 );
                 return match in_elem.kind() {
                     ty::Int(_) | ty::Uint(_) => {
@@ -1607,25 +1599,28 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
                                 32 => bx.const_real(bx.type_f32(), $identity),
                                 64 => bx.const_real(bx.type_f64(), $identity),
                                 v => return_error!(
-                                    r#"
-unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#,
-                                    sym::$name,
-                                    in_ty,
-                                    in_elem,
-                                    v,
-                                    ret_ty
+                                    InvalidMonomorphization::UnsupportedSymbolOfSize {
+                                        span,
+                                        name,
+                                        symbol: sym::$name,
+                                        in_ty,
+                                        in_elem,
+                                        size: v,
+                                        ret_ty
+                                    }
                                 ),
                             }
                         };
                         Ok(bx.$float_reduce(acc, args[0].immediate()))
                     }
-                    _ => return_error!(
-                        "unsupported {} from `{}` with element `{}` to `{}`",
-                        sym::$name,
+                    _ => return_error!(InvalidMonomorphization::UnsupportedSymbol {
+                        span,
+                        name,
+                        symbol: sym::$name,
                         in_ty,
                         in_elem,
                         ret_ty
-                    ),
+                    }),
                 };
             }
         };
@@ -1653,22 +1648,20 @@ unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#,
             if name == sym::$name {
                 require!(
                     ret_ty == in_elem,
-                    "expected return type `{}` (element of input `{}`), found `{}`",
-                    in_elem,
-                    in_ty,
-                    ret_ty
+                    InvalidMonomorphization::ReturnType { span, name, in_elem, in_ty, ret_ty }
                 );
                 return match in_elem.kind() {
                     ty::Int(_i) => Ok(bx.$int_red(args[0].immediate(), true)),
                     ty::Uint(_u) => Ok(bx.$int_red(args[0].immediate(), false)),
                     ty::Float(_f) => Ok(bx.$float_red(args[0].immediate())),
-                    _ => return_error!(
-                        "unsupported {} from `{}` with element `{}` to `{}`",
-                        sym::$name,
+                    _ => return_error!(InvalidMonomorphization::UnsupportedSymbol {
+                        span,
+                        name,
+                        symbol: sym::$name,
                         in_ty,
                         in_elem,
                         ret_ty
-                    ),
+                    }),
                 };
             }
         };
@@ -1686,22 +1679,20 @@ unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#,
                 let input = if !$boolean {
                     require!(
                         ret_ty == in_elem,
-                        "expected return type `{}` (element of input `{}`), found `{}`",
-                        in_elem,
-                        in_ty,
-                        ret_ty
+                        InvalidMonomorphization::ReturnType { span, name, in_elem, in_ty, ret_ty }
                     );
                     args[0].immediate()
                 } else {
                     match in_elem.kind() {
                         ty::Int(_) | ty::Uint(_) => {}
-                        _ => return_error!(
-                            "unsupported {} from `{}` with element `{}` to `{}`",
-                            sym::$name,
+                        _ => return_error!(InvalidMonomorphization::UnsupportedSymbol {
+                            span,
+                            name,
+                            symbol: sym::$name,
                             in_ty,
                             in_elem,
                             ret_ty
-                        ),
+                        }),
                     }
 
                     // boolean reductions operate on vectors of i1s:
@@ -1714,13 +1705,14 @@ unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#,
                         let r = bx.$red(input);
                         Ok(if !$boolean { r } else { bx.zext(r, bx.type_bool()) })
                     }
-                    _ => return_error!(
-                        "unsupported {} from `{}` with element `{}` to `{}`",
-                        sym::$name,
+                    _ => return_error!(InvalidMonomorphization::UnsupportedSymbol {
+                        span,
+                        name,
+                        symbol: sym::$name,
                         in_ty,
                         in_elem,
                         ret_ty
-                    ),
+                    }),
                 };
             }
         };
@@ -1733,16 +1725,18 @@ unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#,
     bitwise_red!(simd_reduce_any: vector_reduce_or, true);
 
     if name == sym::simd_cast_ptr {
-        require_simd!(ret_ty, "return");
+        require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty });
         let (out_len, out_elem) = ret_ty.simd_size_and_type(bx.tcx());
         require!(
             in_len == out_len,
-            "expected return type with length {} (same as input type `{}`), \
-                  found `{}` with length {}",
-            in_len,
-            in_ty,
-            ret_ty,
-            out_len
+            InvalidMonomorphization::ReturnLengthInputType {
+                span,
+                name,
+                in_len,
+                in_ty,
+                ret_ty,
+                out_len
+            }
         );
 
         match in_elem.kind() {
@@ -1751,9 +1745,14 @@ unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#,
                     bx.tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), ty)
                 });
                 assert!(!check_sized); // we are in codegen, so we shouldn't see these types
-                require!(metadata.is_unit(), "cannot cast fat pointer `{}`", in_elem)
+                require!(
+                    metadata.is_unit(),
+                    InvalidMonomorphization::CastFatPointer { span, name, ty: in_elem }
+                );
+            }
+            _ => {
+                return_error!(InvalidMonomorphization::ExpectedPointer { span, name, ty: in_elem })
             }
-            _ => return_error!("expected pointer, got `{}`", in_elem),
         }
         match out_elem.kind() {
             ty::RawPtr(p) => {
@@ -1761,9 +1760,14 @@ unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#,
                     bx.tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), ty)
                 });
                 assert!(!check_sized); // we are in codegen, so we shouldn't see these types
-                require!(metadata.is_unit(), "cannot cast to fat pointer `{}`", out_elem)
+                require!(
+                    metadata.is_unit(),
+                    InvalidMonomorphization::CastFatPointer { span, name, ty: out_elem }
+                );
+            }
+            _ => {
+                return_error!(InvalidMonomorphization::ExpectedPointer { span, name, ty: out_elem })
             }
-            _ => return_error!("expected pointer, got `{}`", out_elem),
         }
 
         if in_elem == out_elem {
@@ -1774,66 +1778,76 @@ unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#,
     }
 
     if name == sym::simd_expose_addr {
-        require_simd!(ret_ty, "return");
+        require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty });
         let (out_len, out_elem) = ret_ty.simd_size_and_type(bx.tcx());
         require!(
             in_len == out_len,
-            "expected return type with length {} (same as input type `{}`), \
-                  found `{}` with length {}",
-            in_len,
-            in_ty,
-            ret_ty,
-            out_len
+            InvalidMonomorphization::ReturnLengthInputType {
+                span,
+                name,
+                in_len,
+                in_ty,
+                ret_ty,
+                out_len
+            }
         );
 
         match in_elem.kind() {
             ty::RawPtr(_) => {}
-            _ => return_error!("expected pointer, got `{}`", in_elem),
+            _ => {
+                return_error!(InvalidMonomorphization::ExpectedPointer { span, name, ty: in_elem })
+            }
         }
         match out_elem.kind() {
             ty::Uint(ty::UintTy::Usize) => {}
-            _ => return_error!("expected `usize`, got `{}`", out_elem),
+            _ => return_error!(InvalidMonomorphization::ExpectedUsize { span, name, ty: out_elem }),
         }
 
         return Ok(bx.ptrtoint(args[0].immediate(), llret_ty));
     }
 
     if name == sym::simd_from_exposed_addr {
-        require_simd!(ret_ty, "return");
+        require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty });
         let (out_len, out_elem) = ret_ty.simd_size_and_type(bx.tcx());
         require!(
             in_len == out_len,
-            "expected return type with length {} (same as input type `{}`), \
-                  found `{}` with length {}",
-            in_len,
-            in_ty,
-            ret_ty,
-            out_len
+            InvalidMonomorphization::ReturnLengthInputType {
+                span,
+                name,
+                in_len,
+                in_ty,
+                ret_ty,
+                out_len
+            }
         );
 
         match in_elem.kind() {
             ty::Uint(ty::UintTy::Usize) => {}
-            _ => return_error!("expected `usize`, got `{}`", in_elem),
+            _ => return_error!(InvalidMonomorphization::ExpectedUsize { span, name, ty: in_elem }),
         }
         match out_elem.kind() {
             ty::RawPtr(_) => {}
-            _ => return_error!("expected pointer, got `{}`", out_elem),
+            _ => {
+                return_error!(InvalidMonomorphization::ExpectedPointer { span, name, ty: out_elem })
+            }
         }
 
         return Ok(bx.inttoptr(args[0].immediate(), llret_ty));
     }
 
     if name == sym::simd_cast || name == sym::simd_as {
-        require_simd!(ret_ty, "return");
+        require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty });
         let (out_len, out_elem) = ret_ty.simd_size_and_type(bx.tcx());
         require!(
             in_len == out_len,
-            "expected return type with length {} (same as input type `{}`), \
-                  found `{}` with length {}",
-            in_len,
-            in_ty,
-            ret_ty,
-            out_len
+            InvalidMonomorphization::ReturnLengthInputType {
+                span,
+                name,
+                in_len,
+                in_ty,
+                ret_ty,
+                out_len
+            }
         );
         // casting cares about nominal type, not just structural type
         if in_elem == out_elem {
@@ -1912,11 +1926,14 @@ unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#,
         }
         require!(
             false,
-            "unsupported cast from `{}` with element `{}` to `{}` with element `{}`",
-            in_ty,
-            in_elem,
-            ret_ty,
-            out_elem
+            InvalidMonomorphization::UnsupportedCast {
+                span,
+                name,
+                in_ty,
+                in_elem,
+                ret_ty,
+                out_elem
+            }
         );
     }
     macro_rules! arith_binary {
@@ -1928,10 +1945,10 @@ unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#,
                     })*
                     _ => {},
                 }
-                require!(false,
-                         "unsupported operation on `{}` with element `{}`",
-                         in_ty,
-                         in_elem)
+                require!(
+                    false,
+                    InvalidMonomorphization::UnsupportedOperation { span, name, in_ty, in_elem }
+                );
             })*
         }
     }
@@ -1959,10 +1976,10 @@ unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#,
                     })*
                     _ => {},
                 }
-                require!(false,
-                         "unsupported operation on `{}` with element `{}`",
-                         in_ty,
-                         in_elem)
+                require!(
+                    false,
+                    InvalidMonomorphization::UnsupportedOperation { span, name, in_ty, in_elem }
+                );
             })*
         }
     }
@@ -2000,12 +2017,12 @@ unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#,
             ty::Int(i) => (true, i.bit_width().unwrap_or(ptr_bits), bx.cx.type_int_from_ty(i)),
             ty::Uint(i) => (false, i.bit_width().unwrap_or(ptr_bits), bx.cx.type_uint_from_ty(i)),
             _ => {
-                return_error!(
-                    "expected element type `{}` of vector type `{}` \
-                     to be a signed or unsigned integer type",
-                    arg_tys[0].simd_size_and_type(bx.tcx()).1,
-                    arg_tys[0]
-                );
+                return_error!(InvalidMonomorphization::ExpectedVectorElementType {
+                    span,
+                    name,
+                    expected_element: arg_tys[0].simd_size_and_type(bx.tcx()).1,
+                    vector_type: arg_tys[0]
+                });
             }
         };
         let llvm_intrinsic = &format!(
diff --git a/compiler/rustc_codegen_ssa/Cargo.toml b/compiler/rustc_codegen_ssa/Cargo.toml
index 345174fb595..d1ad687e6ae 100644
--- a/compiler/rustc_codegen_ssa/Cargo.toml
+++ b/compiler/rustc_codegen_ssa/Cargo.toml
@@ -27,6 +27,7 @@ rustc_arena = { path = "../rustc_arena" }
 rustc_ast = { path = "../rustc_ast" }
 rustc_span = { path = "../rustc_span" }
 rustc_middle = { path = "../rustc_middle" }
+rustc_type_ir = { path = "../rustc_type_ir" }
 rustc_attr = { path = "../rustc_attr" }
 rustc_symbol_mangling = { path = "../rustc_symbol_mangling" }
 rustc_data_structures = { path = "../rustc_data_structures" }
diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs
index edde1537b81..8ca7103ed48 100644
--- a/compiler/rustc_codegen_ssa/src/back/link.rs
+++ b/compiler/rustc_codegen_ssa/src/back/link.rs
@@ -11,7 +11,7 @@ use rustc_metadata::find_native_static_library;
 use rustc_metadata::fs::{emit_wrapper_file, METADATA_FILENAME};
 use rustc_middle::middle::dependency_format::Linkage;
 use rustc_middle::middle::exported_symbols::SymbolExportKind;
-use rustc_session::config::{self, CFGuard, CrateType, DebugInfo, LdImpl, Lto, Strip};
+use rustc_session::config::{self, CFGuard, CrateType, DebugInfo, LdImpl, Strip};
 use rustc_session::config::{OutputFilenames, OutputType, PrintRequest, SplitDwarfKind};
 use rustc_session::cstore::DllImport;
 use rustc_session::output::{check_file_is_writeable, invalid_output_for_target, out_filename};
@@ -208,16 +208,16 @@ pub fn link_binary<'a>(
     Ok(())
 }
 
+// Crate type is not passed when calculating the dylibs to include for LTO. In that case all
+// crate types must use the same dependency formats.
 pub fn each_linked_rlib(
-    sess: &Session,
     info: &CrateInfo,
+    crate_type: Option<CrateType>,
     f: &mut dyn FnMut(CrateNum, &Path),
 ) -> Result<(), errors::LinkRlibError> {
     let crates = info.used_crates.iter();
-    let mut fmts = None;
 
-    let lto_active = matches!(sess.lto(), Lto::Fat | Lto::Thin);
-    if lto_active {
+    let fmts = if crate_type.is_none() {
         for combination in info.dependency_formats.iter().combinations(2) {
             let (ty1, list1) = &combination[0];
             let (ty2, list2) = &combination[1];
@@ -230,27 +230,23 @@ pub fn each_linked_rlib(
                 });
             }
         }
-    }
-
-    for (ty, list) in info.dependency_formats.iter() {
-        match ty {
-            CrateType::Executable
-            | CrateType::Staticlib
-            | CrateType::Cdylib
-            | CrateType::ProcMacro => {
-                fmts = Some(list);
-                break;
-            }
-            CrateType::Dylib if lto_active => {
-                fmts = Some(list);
-                break;
-            }
-            _ => {}
+        if info.dependency_formats.is_empty() {
+            return Err(errors::LinkRlibError::MissingFormat);
         }
-    }
-    let Some(fmts) = fmts else {
-        return Err(errors::LinkRlibError::MissingFormat);
+        &info.dependency_formats[0].1
+    } else {
+        let fmts = info
+            .dependency_formats
+            .iter()
+            .find_map(|&(ty, ref list)| if Some(ty) == crate_type { Some(list) } else { None });
+
+        let Some(fmts) = fmts else {
+            return Err(errors::LinkRlibError::MissingFormat);
+        };
+
+        fmts
     };
+
     for &cnum in crates {
         match fmts.get(cnum.as_usize() - 1) {
             Some(&Linkage::NotLinked | &Linkage::Dynamic | &Linkage::IncludedFromDylib) => continue,
@@ -516,64 +512,71 @@ fn link_staticlib<'a>(
     )?;
     let mut all_native_libs = vec![];
 
-    let res = each_linked_rlib(sess, &codegen_results.crate_info, &mut |cnum, path| {
-        let name = codegen_results.crate_info.crate_name[&cnum];
-        let native_libs = &codegen_results.crate_info.native_libraries[&cnum];
-
-        // Here when we include the rlib into our staticlib we need to make a
-        // decision whether to include the extra object files along the way.
-        // These extra object files come from statically included native
-        // libraries, but they may be cfg'd away with #[link(cfg(..))].
-        //
-        // This unstable feature, though, only needs liblibc to work. The only
-        // use case there is where musl is statically included in liblibc.rlib,
-        // so if we don't want the included version we just need to skip it. As
-        // a result the logic here is that if *any* linked library is cfg'd away
-        // we just skip all object files.
-        //
-        // Clearly this is not sufficient for a general purpose feature, and
-        // we'd want to read from the library's metadata to determine which
-        // object files come from where and selectively skip them.
-        let skip_object_files = native_libs.iter().any(|lib| {
-            matches!(lib.kind, NativeLibKind::Static { bundle: None | Some(true), .. })
-                && !relevant_lib(sess, lib)
-        });
+    let res = each_linked_rlib(
+        &codegen_results.crate_info,
+        Some(CrateType::Staticlib),
+        &mut |cnum, path| {
+            let name = codegen_results.crate_info.crate_name[&cnum];
+            let native_libs = &codegen_results.crate_info.native_libraries[&cnum];
+
+            // Here when we include the rlib into our staticlib we need to make a
+            // decision whether to include the extra object files along the way.
+            // These extra object files come from statically included native
+            // libraries, but they may be cfg'd away with #[link(cfg(..))].
+            //
+            // This unstable feature, though, only needs liblibc to work. The only
+            // use case there is where musl is statically included in liblibc.rlib,
+            // so if we don't want the included version we just need to skip it. As
+            // a result the logic here is that if *any* linked library is cfg'd away
+            // we just skip all object files.
+            //
+            // Clearly this is not sufficient for a general purpose feature, and
+            // we'd want to read from the library's metadata to determine which
+            // object files come from where and selectively skip them.
+            let skip_object_files = native_libs.iter().any(|lib| {
+                matches!(lib.kind, NativeLibKind::Static { bundle: None | Some(true), .. })
+                    && !relevant_lib(sess, lib)
+            });
 
-        let lto = are_upstream_rust_objects_already_included(sess)
-            && !ignored_for_lto(sess, &codegen_results.crate_info, cnum);
+            let lto = are_upstream_rust_objects_already_included(sess)
+                && !ignored_for_lto(sess, &codegen_results.crate_info, cnum);
 
-        // Ignoring obj file starting with the crate name
-        // as simple comparison is not enough - there
-        // might be also an extra name suffix
-        let obj_start = name.as_str().to_owned();
+            // Ignoring obj file starting with the crate name
+            // as simple comparison is not enough - there
+            // might be also an extra name suffix
+            let obj_start = name.as_str().to_owned();
 
-        ab.add_archive(
-            path,
-            Box::new(move |fname: &str| {
-                // Ignore metadata files, no matter the name.
-                if fname == METADATA_FILENAME {
-                    return true;
-                }
+            ab.add_archive(
+                path,
+                Box::new(move |fname: &str| {
+                    // Ignore metadata files, no matter the name.
+                    if fname == METADATA_FILENAME {
+                        return true;
+                    }
 
-                // Don't include Rust objects if LTO is enabled
-                if lto && looks_like_rust_object_file(fname) {
-                    return true;
-                }
+                    // Don't include Rust objects if LTO is enabled
+                    if lto && looks_like_rust_object_file(fname) {
+                        return true;
+                    }
 
-                // Otherwise if this is *not* a rust object and we're skipping
-                // objects then skip this file
-                if skip_object_files && (!fname.starts_with(&obj_start) || !fname.ends_with(".o")) {
-                    return true;
-                }
+                    // Otherwise if this is *not* a rust object and we're skipping
+                    // objects then skip this file
+                    if skip_object_files
+                        && (!fname.starts_with(&obj_start) || !fname.ends_with(".o"))
+                    {
+                        return true;
+                    }
 
-                // ok, don't skip this
-                false
-            }),
-        )
-        .unwrap();
+                    // ok, don't skip this
+                    false
+                }),
+            )
+            .unwrap();
 
-        all_native_libs.extend(codegen_results.crate_info.native_libraries[&cnum].iter().cloned());
-    });
+            all_native_libs
+                .extend(codegen_results.crate_info.native_libraries[&cnum].iter().cloned());
+        },
+    );
     if let Err(e) = res {
         sess.emit_fatal(e);
     }
@@ -1354,7 +1357,8 @@ fn print_native_static_libs(sess: &Session, all_native_libs: &[NativeLib]) {
     if !lib_args.is_empty() {
         sess.emit_note(errors::StaticLibraryNativeArtifacts);
         // Prefix for greppability
-        sess.emit_note(errors::NativeStaticLibs { arguments: lib_args.join(" ") });
+        // Note: This must not be translated as tools are allowed to depend on this exact string.
+        sess.note_without_error(&format!("native-static-libs: {}", &lib_args.join(" ")));
     }
 }
 
@@ -2612,7 +2616,7 @@ fn add_static_crate<'a>(
             sess.target.no_builtins || !codegen_results.crate_info.is_no_builtins.contains(&cnum);
 
         let mut archive = archive_builder_builder.new_archive_builder(sess);
-        if let Err(e) = archive.add_archive(
+        if let Err(error) = archive.add_archive(
             cratepath,
             Box::new(move |f| {
                 if f == METADATA_FILENAME {
@@ -2652,7 +2656,7 @@ fn add_static_crate<'a>(
                 false
             }),
         ) {
-            sess.fatal(&format!("failed to build archive from rlib: {}", e));
+            sess.emit_fatal(errors::RlibArchiveBuildFailure { error });
         }
         if archive.build(&dst) {
             link_upstream(&dst);
@@ -2822,11 +2826,30 @@ fn add_gcc_ld_path(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) {
                     // Implement the "linker flavor" part of -Zgcc-ld
                     // by asking cc to use some kind of lld.
                     cmd.arg("-fuse-ld=lld");
+
                     if !flavor.is_gnu() {
                         // Tell clang to use a non-default LLD flavor.
                         // Gcc doesn't understand the target option, but we currently assume
                         // that gcc is not used for Apple and Wasm targets (#97402).
-                        cmd.arg(format!("--target={}", sess.target.llvm_target));
+                        //
+                        // Note that we don't want to do that by default on macOS: e.g. passing a
+                        // 10.7 target to LLVM works, but not to recent versions of clang/macOS, as
+                        // shown in issue #101653 and the discussion in PR #101792.
+                        //
+                        // It could be required in some cases of cross-compiling with
+                        // `-Zgcc-ld=lld`, but this is generally unspecified, and we don't know
+                        // which specific versions of clang, macOS SDK, host and target OS
+                        // combinations impact us here.
+                        //
+                        // So we do a simple first-approximation until we know more of what the
+                        // Apple targets require (and which would be handled prior to hitting this
+                        // `-Zgcc-ld=lld` codepath anyway), but the expectation is that until then
+                        // this should be manually passed if needed. We specify the target when
+                        // targeting a different linker flavor on macOS, and that's also always
+                        // the case when targeting WASM.
+                        if sess.target.linker_flavor != sess.host.linker_flavor {
+                            cmd.arg(format!("--target={}", sess.target.llvm_target));
+                        }
                     }
                 }
             }
diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs
index 1a7de1a184a..7aadcdd2228 100644
--- a/compiler/rustc_codegen_ssa/src/back/write.rs
+++ b/compiler/rustc_codegen_ssa/src/back/write.rs
@@ -1002,7 +1002,7 @@ fn start_executing_work<B: ExtraBackendMethods>(
     let sess = tcx.sess;
 
     let mut each_linked_rlib_for_lto = Vec::new();
-    drop(link::each_linked_rlib(sess, crate_info, &mut |cnum, path| {
+    drop(link::each_linked_rlib(crate_info, None, &mut |cnum, path| {
         if link::ignored_for_lto(sess, crate_info, cnum) {
             return;
         }
diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs
index 8b34be38580..d318c15d342 100644
--- a/compiler/rustc_codegen_ssa/src/base.rs
+++ b/compiler/rustc_codegen_ssa/src/base.rs
@@ -5,6 +5,7 @@ use crate::back::write::{
     submit_post_lto_module_to_llvm, submit_pre_lto_module_to_llvm, ComputedLtoType, OngoingCodegen,
 };
 use crate::common::{IntPredicate, RealPredicate, TypeKind};
+use crate::errors;
 use crate::meth;
 use crate::mir;
 use crate::mir::operand::OperandValue;
@@ -451,10 +452,7 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
         let Some(llfn) = cx.declare_c_main(llfty) else {
             // FIXME: We should be smart and show a better diagnostic here.
             let span = cx.tcx().def_span(rust_main_def_id);
-            cx.sess()
-                .struct_span_err(span, "entry symbol `main` declared multiple times")
-                .help("did you use `#[no_mangle]` on `fn main`? Use `#[start]` instead")
-                .emit();
+            cx.sess().emit_err(errors::MultipleMainFunctions { span });
             cx.sess().abort_if_errors();
             bug!();
         };
@@ -595,8 +593,8 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
                 &metadata,
                 &exported_symbols::metadata_symbol_name(tcx),
             );
-            if let Err(err) = std::fs::write(&file_name, data) {
-                tcx.sess.fatal(&format!("error writing metadata object file: {}", err));
+            if let Err(error) = std::fs::write(&file_name, data) {
+                tcx.sess.emit_fatal(errors::MetadataObjectFileWrite { error });
             }
             Some(CompiledModule {
                 name: metadata_cgu_name,
@@ -815,11 +813,7 @@ impl CrateInfo {
         let subsystem = tcx.sess.first_attr_value_str_by_name(crate_attrs, sym::windows_subsystem);
         let windows_subsystem = subsystem.map(|subsystem| {
             if subsystem != sym::windows && subsystem != sym::console {
-                tcx.sess.fatal(&format!(
-                    "invalid windows subsystem `{}`, only \
-                                     `windows` and `console` are allowed",
-                    subsystem
-                ));
+                tcx.sess.emit_fatal(errors::InvalidWindowsSubsystem { subsystem });
             }
             subsystem.to_string()
         });
diff --git a/compiler/rustc_codegen_ssa/src/common.rs b/compiler/rustc_codegen_ssa/src/common.rs
index 71f9179d02c..e1abb73a504 100644
--- a/compiler/rustc_codegen_ssa/src/common.rs
+++ b/compiler/rustc_codegen_ssa/src/common.rs
@@ -1,10 +1,8 @@
 #![allow(non_camel_case_types)]
 
-use rustc_errors::struct_span_err;
 use rustc_hir::LangItem;
 use rustc_middle::mir::interpret::ConstValue;
 use rustc_middle::ty::{self, layout::TyAndLayout, Ty, TyCtxt};
-use rustc_session::Session;
 use rustc_span::Span;
 
 use crate::base;
@@ -193,10 +191,6 @@ pub fn shift_mask_val<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
     }
 }
 
-pub fn span_invalid_monomorphization_error(a: &Session, b: Span, c: &str) {
-    struct_span_err!(a, b, E0511, "{}", c).emit();
-}
-
 pub fn asm_const_to_str<'tcx>(
     tcx: TyCtxt<'tcx>,
     sp: Span,
diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
index 3ae6c531b44..1599ccbb259 100644
--- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
+++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
@@ -93,6 +93,7 @@ fn push_debuginfo_type_name<'tcx>(
                     Err(e) => {
                         // Computing the layout can still fail here, e.g. if the target architecture
                         // cannot represent the type. See https://github.com/rust-lang/rust/issues/94961.
+                        // FIXME: migrate once `rustc_middle::mir::interpret::InterpError` is translatable.
                         tcx.sess.fatal(&format!("{}", e));
                     }
                 }
diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs
index 0620000201f..d81252653df 100644
--- a/compiler/rustc_codegen_ssa/src/errors.rs
+++ b/compiler/rustc_codegen_ssa/src/errors.rs
@@ -6,7 +6,9 @@ use rustc_errors::{
     IntoDiagnosticArg,
 };
 use rustc_macros::Diagnostic;
+use rustc_middle::ty::Ty;
 use rustc_span::{Span, Symbol};
+use rustc_type_ir::FloatTy;
 use std::borrow::Cow;
 use std::io::Error;
 use std::path::{Path, PathBuf};
@@ -445,12 +447,6 @@ pub struct LinkerFileStem;
 pub struct StaticLibraryNativeArtifacts;
 
 #[derive(Diagnostic)]
-#[diag(codegen_ssa_native_static_libs)]
-pub struct NativeStaticLibs {
-    pub arguments: String,
-}
-
-#[derive(Diagnostic)]
 #[diag(codegen_ssa_link_script_unavailable)]
 pub struct LinkScriptUnavailable;
 
@@ -555,3 +551,432 @@ pub struct ExpectedUsedSymbol {
     #[primary_span]
     pub span: Span,
 }
+
+#[derive(Diagnostic)]
+#[diag(codegen_ssa_multiple_main_functions)]
+#[help]
+pub struct MultipleMainFunctions {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(codegen_ssa_metadata_object_file_write)]
+pub struct MetadataObjectFileWrite {
+    pub error: Error,
+}
+
+#[derive(Diagnostic)]
+#[diag(codegen_ssa_invalid_windows_subsystem)]
+pub struct InvalidWindowsSubsystem {
+    pub subsystem: Symbol,
+}
+
+#[derive(Diagnostic)]
+#[diag(codegen_ssa_erroneous_constant)]
+pub struct ErroneousConstant {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(codegen_ssa_polymorphic_constant_too_generic)]
+pub struct PolymorphicConstantTooGeneric {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(codegen_ssa_shuffle_indices_evaluation)]
+pub struct ShuffleIndicesEvaluation {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(codegen_ssa_missing_memory_ordering)]
+pub struct MissingMemoryOrdering;
+
+#[derive(Diagnostic)]
+#[diag(codegen_ssa_unknown_atomic_ordering)]
+pub struct UnknownAtomicOrdering;
+
+#[derive(Diagnostic)]
+#[diag(codegen_ssa_atomic_compare_exchange)]
+pub struct AtomicCompareExchange;
+
+#[derive(Diagnostic)]
+#[diag(codegen_ssa_unknown_atomic_operation)]
+pub struct UnknownAtomicOperation;
+
+#[derive(Diagnostic)]
+pub enum InvalidMonomorphization<'tcx> {
+    #[diag(codegen_ssa_invalid_monomorphization_basic_integer_type, code = "E0511")]
+    BasicIntegerType {
+        #[primary_span]
+        span: Span,
+        name: Symbol,
+        ty: Ty<'tcx>,
+    },
+
+    #[diag(codegen_ssa_invalid_monomorphization_basic_float_type, code = "E0511")]
+    BasicFloatType {
+        #[primary_span]
+        span: Span,
+        name: Symbol,
+        ty: Ty<'tcx>,
+    },
+
+    #[diag(codegen_ssa_invalid_monomorphization_float_to_int_unchecked, code = "E0511")]
+    FloatToIntUnchecked {
+        #[primary_span]
+        span: Span,
+        ty: Ty<'tcx>,
+    },
+
+    #[diag(codegen_ssa_invalid_monomorphization_floating_point_vector, code = "E0511")]
+    FloatingPointVector {
+        #[primary_span]
+        span: Span,
+        name: Symbol,
+        f_ty: FloatTy,
+        in_ty: Ty<'tcx>,
+    },
+
+    #[diag(codegen_ssa_invalid_monomorphization_floating_point_type, code = "E0511")]
+    FloatingPointType {
+        #[primary_span]
+        span: Span,
+        name: Symbol,
+        in_ty: Ty<'tcx>,
+    },
+
+    #[diag(codegen_ssa_invalid_monomorphization_unrecognized_intrinsic, code = "E0511")]
+    UnrecognizedIntrinsic {
+        #[primary_span]
+        span: Span,
+        name: Symbol,
+    },
+
+    #[diag(codegen_ssa_invalid_monomorphization_simd_argument, code = "E0511")]
+    SimdArgument {
+        #[primary_span]
+        span: Span,
+        name: Symbol,
+        ty: Ty<'tcx>,
+    },
+
+    #[diag(codegen_ssa_invalid_monomorphization_simd_input, code = "E0511")]
+    SimdInput {
+        #[primary_span]
+        span: Span,
+        name: Symbol,
+        ty: Ty<'tcx>,
+    },
+
+    #[diag(codegen_ssa_invalid_monomorphization_simd_first, code = "E0511")]
+    SimdFirst {
+        #[primary_span]
+        span: Span,
+        name: Symbol,
+        ty: Ty<'tcx>,
+    },
+
+    #[diag(codegen_ssa_invalid_monomorphization_simd_second, code = "E0511")]
+    SimdSecond {
+        #[primary_span]
+        span: Span,
+        name: Symbol,
+        ty: Ty<'tcx>,
+    },
+
+    #[diag(codegen_ssa_invalid_monomorphization_simd_third, code = "E0511")]
+    SimdThird {
+        #[primary_span]
+        span: Span,
+        name: Symbol,
+        ty: Ty<'tcx>,
+    },
+
+    #[diag(codegen_ssa_invalid_monomorphization_simd_return, code = "E0511")]
+    SimdReturn {
+        #[primary_span]
+        span: Span,
+        name: Symbol,
+        ty: Ty<'tcx>,
+    },
+
+    #[diag(codegen_ssa_invalid_monomorphization_invalid_bitmask, code = "E0511")]
+    InvalidBitmask {
+        #[primary_span]
+        span: Span,
+        name: Symbol,
+        mask_ty: Ty<'tcx>,
+        expected_int_bits: u64,
+        expected_bytes: u64,
+    },
+
+    #[diag(codegen_ssa_invalid_monomorphization_return_length_input_type, code = "E0511")]
+    ReturnLengthInputType {
+        #[primary_span]
+        span: Span,
+        name: Symbol,
+        in_len: u64,
+        in_ty: Ty<'tcx>,
+        ret_ty: Ty<'tcx>,
+        out_len: u64,
+    },
+
+    #[diag(codegen_ssa_invalid_monomorphization_second_argument_length, code = "E0511")]
+    SecondArgumentLength {
+        #[primary_span]
+        span: Span,
+        name: Symbol,
+        in_len: u64,
+        in_ty: Ty<'tcx>,
+        arg_ty: Ty<'tcx>,
+        out_len: u64,
+    },
+
+    #[diag(codegen_ssa_invalid_monomorphization_third_argument_length, code = "E0511")]
+    ThirdArgumentLength {
+        #[primary_span]
+        span: Span,
+        name: Symbol,
+        in_len: u64,
+        in_ty: Ty<'tcx>,
+        arg_ty: Ty<'tcx>,
+        out_len: u64,
+    },
+
+    #[diag(codegen_ssa_invalid_monomorphization_return_integer_type, code = "E0511")]
+    ReturnIntegerType {
+        #[primary_span]
+        span: Span,
+        name: Symbol,
+        ret_ty: Ty<'tcx>,
+        out_ty: Ty<'tcx>,
+    },
+
+    #[diag(codegen_ssa_invalid_monomorphization_simd_shuffle, code = "E0511")]
+    SimdShuffle {
+        #[primary_span]
+        span: Span,
+        name: Symbol,
+        ty: Ty<'tcx>,
+    },
+
+    #[diag(codegen_ssa_invalid_monomorphization_return_length, code = "E0511")]
+    ReturnLength {
+        #[primary_span]
+        span: Span,
+        name: Symbol,
+        in_len: u64,
+        ret_ty: Ty<'tcx>,
+        out_len: u64,
+    },
+
+    #[diag(codegen_ssa_invalid_monomorphization_return_element, code = "E0511")]
+    ReturnElement {
+        #[primary_span]
+        span: Span,
+        name: Symbol,
+        in_elem: Ty<'tcx>,
+        in_ty: Ty<'tcx>,
+        ret_ty: Ty<'tcx>,
+        out_ty: Ty<'tcx>,
+    },
+
+    #[diag(codegen_ssa_invalid_monomorphization_shuffle_index_not_constant, code = "E0511")]
+    ShuffleIndexNotConstant {
+        #[primary_span]
+        span: Span,
+        name: Symbol,
+        arg_idx: u64,
+    },
+
+    #[diag(codegen_ssa_invalid_monomorphization_shuffle_index_out_of_bounds, code = "E0511")]
+    ShuffleIndexOutOfBounds {
+        #[primary_span]
+        span: Span,
+        name: Symbol,
+        arg_idx: u64,
+        total_len: u128,
+    },
+
+    #[diag(codegen_ssa_invalid_monomorphization_inserted_type, code = "E0511")]
+    InsertedType {
+        #[primary_span]
+        span: Span,
+        name: Symbol,
+        in_elem: Ty<'tcx>,
+        in_ty: Ty<'tcx>,
+        out_ty: Ty<'tcx>,
+    },
+
+    #[diag(codegen_ssa_invalid_monomorphization_return_type, code = "E0511")]
+    ReturnType {
+        #[primary_span]
+        span: Span,
+        name: Symbol,
+        in_elem: Ty<'tcx>,
+        in_ty: Ty<'tcx>,
+        ret_ty: Ty<'tcx>,
+    },
+
+    #[diag(codegen_ssa_invalid_monomorphization_expected_return_type, code = "E0511")]
+    ExpectedReturnType {
+        #[primary_span]
+        span: Span,
+        name: Symbol,
+        in_ty: Ty<'tcx>,
+        ret_ty: Ty<'tcx>,
+    },
+
+    #[diag(codegen_ssa_invalid_monomorphization_mismatched_lengths, code = "E0511")]
+    MismatchedLengths {
+        #[primary_span]
+        span: Span,
+        name: Symbol,
+        m_len: u64,
+        v_len: u64,
+    },
+
+    #[diag(codegen_ssa_invalid_monomorphization_mask_type, code = "E0511")]
+    MaskType {
+        #[primary_span]
+        span: Span,
+        name: Symbol,
+        ty: Ty<'tcx>,
+    },
+
+    #[diag(codegen_ssa_invalid_monomorphization_vector_argument, code = "E0511")]
+    VectorArgument {
+        #[primary_span]
+        span: Span,
+        name: Symbol,
+        in_ty: Ty<'tcx>,
+        in_elem: Ty<'tcx>,
+    },
+
+    #[diag(codegen_ssa_invalid_monomorphization_cannot_return, code = "E0511")]
+    CannotReturn {
+        #[primary_span]
+        span: Span,
+        name: Symbol,
+        ret_ty: Ty<'tcx>,
+        expected_int_bits: u64,
+        expected_bytes: u64,
+    },
+
+    #[diag(codegen_ssa_invalid_monomorphization_expected_element_type, code = "E0511")]
+    ExpectedElementType {
+        #[primary_span]
+        span: Span,
+        name: Symbol,
+        expected_element: Ty<'tcx>,
+        second_arg: Ty<'tcx>,
+        in_elem: Ty<'tcx>,
+        in_ty: Ty<'tcx>,
+        mutability: ExpectedPointerMutability,
+    },
+
+    #[diag(codegen_ssa_invalid_monomorphization_third_arg_element_type, code = "E0511")]
+    ThirdArgElementType {
+        #[primary_span]
+        span: Span,
+        name: Symbol,
+        expected_element: Ty<'tcx>,
+        third_arg: Ty<'tcx>,
+    },
+
+    #[diag(codegen_ssa_invalid_monomorphization_unsupported_symbol_of_size, code = "E0511")]
+    UnsupportedSymbolOfSize {
+        #[primary_span]
+        span: Span,
+        name: Symbol,
+        symbol: Symbol,
+        in_ty: Ty<'tcx>,
+        in_elem: Ty<'tcx>,
+        size: u64,
+        ret_ty: Ty<'tcx>,
+    },
+
+    #[diag(codegen_ssa_invalid_monomorphization_unsupported_symbol, code = "E0511")]
+    UnsupportedSymbol {
+        #[primary_span]
+        span: Span,
+        name: Symbol,
+        symbol: Symbol,
+        in_ty: Ty<'tcx>,
+        in_elem: Ty<'tcx>,
+        ret_ty: Ty<'tcx>,
+    },
+
+    #[diag(codegen_ssa_invalid_monomorphization_cast_fat_pointer, code = "E0511")]
+    CastFatPointer {
+        #[primary_span]
+        span: Span,
+        name: Symbol,
+        ty: Ty<'tcx>,
+    },
+
+    #[diag(codegen_ssa_invalid_monomorphization_expected_pointer, code = "E0511")]
+    ExpectedPointer {
+        #[primary_span]
+        span: Span,
+        name: Symbol,
+        ty: Ty<'tcx>,
+    },
+
+    #[diag(codegen_ssa_invalid_monomorphization_expected_usize, code = "E0511")]
+    ExpectedUsize {
+        #[primary_span]
+        span: Span,
+        name: Symbol,
+        ty: Ty<'tcx>,
+    },
+
+    #[diag(codegen_ssa_invalid_monomorphization_unsupported_cast, code = "E0511")]
+    UnsupportedCast {
+        #[primary_span]
+        span: Span,
+        name: Symbol,
+        in_ty: Ty<'tcx>,
+        in_elem: Ty<'tcx>,
+        ret_ty: Ty<'tcx>,
+        out_elem: Ty<'tcx>,
+    },
+
+    #[diag(codegen_ssa_invalid_monomorphization_unsupported_operation, code = "E0511")]
+    UnsupportedOperation {
+        #[primary_span]
+        span: Span,
+        name: Symbol,
+        in_ty: Ty<'tcx>,
+        in_elem: Ty<'tcx>,
+    },
+
+    #[diag(codegen_ssa_invalid_monomorphization_expected_vector_element_type, code = "E0511")]
+    ExpectedVectorElementType {
+        #[primary_span]
+        span: Span,
+        name: Symbol,
+        expected_element: Ty<'tcx>,
+        vector_type: Ty<'tcx>,
+    },
+}
+
+pub enum ExpectedPointerMutability {
+    Mut,
+    Not,
+}
+
+impl IntoDiagnosticArg for ExpectedPointerMutability {
+    fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
+        match self {
+            ExpectedPointerMutability::Mut => DiagnosticArgValue::Str(Cow::Borrowed("*mut")),
+            ExpectedPointerMutability::Not => DiagnosticArgValue::Str(Cow::Borrowed("*_")),
+        }
+    }
+}
diff --git a/compiler/rustc_codegen_ssa/src/mir/constant.rs b/compiler/rustc_codegen_ssa/src/mir/constant.rs
index 53ff3c24096..14fe84a146d 100644
--- a/compiler/rustc_codegen_ssa/src/mir/constant.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/constant.rs
@@ -1,3 +1,4 @@
+use crate::errors;
 use crate::mir::operand::OperandRef;
 use crate::traits::*;
 use rustc_middle::mir;
@@ -44,10 +45,14 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         self.cx.tcx().const_eval_resolve(ty::ParamEnv::reveal_all(), uv, None).map_err(|err| {
             match err {
                 ErrorHandled::Reported(_) => {
-                    self.cx.tcx().sess.span_err(constant.span, "erroneous constant encountered");
+                    self.cx.tcx().sess.emit_err(errors::ErroneousConstant { span: constant.span });
                 }
                 ErrorHandled::TooGeneric => {
-                    span_bug!(constant.span, "codegen encountered polymorphic constant: {:?}", err);
+                    self.cx
+                        .tcx()
+                        .sess
+                        .diagnostic()
+                        .emit_bug(errors::PolymorphicConstantTooGeneric { span: constant.span });
                 }
             }
             err
@@ -87,7 +92,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 (llval, c.ty())
             })
             .unwrap_or_else(|_| {
-                bx.tcx().sess.span_err(span, "could not evaluate shuffle_indices at compile time");
+                bx.tcx().sess.emit_err(errors::ShuffleIndicesEvaluation { span });
                 // We've errored, so we don't have to produce working code.
                 let ty = self.monomorphize(ty);
                 let llty = bx.backend_type(bx.layout_of(ty));
diff --git a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs
index a75609260ed..766dc74cbbb 100644
--- a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs
@@ -1,7 +1,9 @@
 use super::operand::{OperandRef, OperandValue};
 use super::place::PlaceRef;
 use super::FunctionCx;
-use crate::common::{span_invalid_monomorphization_error, IntPredicate};
+use crate::common::IntPredicate;
+use crate::errors;
+use crate::errors::InvalidMonomorphization;
 use crate::glue;
 use crate::meth;
 use crate::traits::*;
@@ -305,15 +307,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                         _ => bug!(),
                     },
                     None => {
-                        span_invalid_monomorphization_error(
-                            bx.tcx().sess,
-                            span,
-                            &format!(
-                                "invalid monomorphization of `{}` intrinsic: \
-                                      expected basic integer type, found `{}`",
-                                name, ty
-                            ),
-                        );
+                        bx.tcx().sess.emit_err(InvalidMonomorphization::BasicIntegerType { span, name, ty });
                         return;
                     }
                 }
@@ -329,15 +323,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                         _ => bug!(),
                     },
                     None => {
-                        span_invalid_monomorphization_error(
-                            bx.tcx().sess,
-                            span,
-                            &format!(
-                                "invalid monomorphization of `{}` intrinsic: \
-                                      expected basic float type, found `{}`",
-                                name, arg_tys[0]
-                            ),
-                        );
+                        bx.tcx().sess.emit_err(InvalidMonomorphization::BasicFloatType { span, name, ty: arg_tys[0] });
                         return;
                     }
                 }
@@ -345,29 +331,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
 
             sym::float_to_int_unchecked => {
                 if float_type_width(arg_tys[0]).is_none() {
-                    span_invalid_monomorphization_error(
-                        bx.tcx().sess,
-                        span,
-                        &format!(
-                            "invalid monomorphization of `float_to_int_unchecked` \
-                                  intrinsic: expected basic float type, \
-                                  found `{}`",
-                            arg_tys[0]
-                        ),
-                    );
+                    bx.tcx().sess.emit_err(InvalidMonomorphization::FloatToIntUnchecked { span, ty: arg_tys[0] });
                     return;
                 }
                 let Some((_width, signed)) = int_type_width_signed(ret_ty, bx.tcx()) else {
-                    span_invalid_monomorphization_error(
-                        bx.tcx().sess,
-                        span,
-                        &format!(
-                            "invalid monomorphization of `float_to_int_unchecked` \
-                                    intrinsic:  expected basic integer type, \
-                                    found `{}`",
-                            ret_ty
-                        ),
-                    );
+                    bx.tcx().sess.emit_err(InvalidMonomorphization::FloatToIntUnchecked { span, ty: ret_ty });
                     return;
                 };
                 if signed {
@@ -402,7 +370,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 use crate::common::{AtomicRmwBinOp, SynchronizationScope};
 
                 let Some((instruction, ordering)) = atomic.split_once('_') else {
-                    bx.sess().fatal("Atomic intrinsic missing memory ordering");
+                    bx.sess().emit_fatal(errors::MissingMemoryOrdering);
                 };
 
                 let parse_ordering = |bx: &Bx, s| match s {
@@ -412,25 +380,17 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                     "release" => Release,
                     "acqrel" => AcquireRelease,
                     "seqcst" => SequentiallyConsistent,
-                    _ => bx.sess().fatal("unknown ordering in atomic intrinsic"),
+                    _ => bx.sess().emit_fatal(errors::UnknownAtomicOrdering),
                 };
 
                 let invalid_monomorphization = |ty| {
-                    span_invalid_monomorphization_error(
-                        bx.tcx().sess,
-                        span,
-                        &format!(
-                            "invalid monomorphization of `{}` intrinsic: \
-                                  expected basic integer type, found `{}`",
-                            name, ty
-                        ),
-                    );
+                    bx.tcx().sess.emit_err(InvalidMonomorphization::BasicIntegerType { span, name, ty });
                 };
 
                 match instruction {
                     "cxchg" | "cxchgweak" => {
                         let Some((success, failure)) = ordering.split_once('_') else {
-                            bx.sess().fatal("Atomic compare-exchange intrinsic missing failure memory ordering");
+                            bx.sess().emit_fatal(errors::AtomicCompareExchange);
                         };
                         let ty = substs.type_at(0);
                         if int_type_width_signed(ty, bx.tcx()).is_some() || ty.is_unsafe_ptr() {
@@ -529,7 +489,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                             "min" => AtomicRmwBinOp::AtomicMin,
                             "umax" => AtomicRmwBinOp::AtomicUMax,
                             "umin" => AtomicRmwBinOp::AtomicUMin,
-                            _ => bx.sess().fatal("unknown atomic operation"),
+                            _ => bx.sess().emit_fatal(errors::UnknownAtomicOperation),
                         };
 
                         let ty = substs.type_at(0);
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/mod.rs b/compiler/rustc_const_eval/src/transform/check_consts/mod.rs
index 655ec345ed3..0a90572d39e 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/mod.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/mod.rs
@@ -115,7 +115,7 @@ fn is_parent_const_stable_trait(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
     let local_def_id = def_id.expect_local();
     let hir_id = tcx.local_def_id_to_hir_id(local_def_id);
 
-    let Some(parent) = tcx.hir().find_parent_node(hir_id) else { return false };
+    let Some(parent) = tcx.hir().opt_parent_id(hir_id) else { return false };
     let parent_def = tcx.hir().get(parent);
 
     if !matches!(
diff --git a/compiler/rustc_data_structures/src/graph/dominators/mod.rs b/compiler/rustc_data_structures/src/graph/dominators/mod.rs
index 94a8c1fc051..ea2a4388b92 100644
--- a/compiler/rustc_data_structures/src/graph/dominators/mod.rs
+++ b/compiler/rustc_data_structures/src/graph/dominators/mod.rs
@@ -277,12 +277,12 @@ impl<Node: Idx> Dominators<Node> {
     }
 
     pub fn immediate_dominator(&self, node: Node) -> Node {
-        assert!(self.is_reachable(node), "node {:?} is not reachable", node);
+        assert!(self.is_reachable(node), "node {node:?} is not reachable");
         self.immediate_dominators[node].unwrap()
     }
 
     pub fn dominators(&self, node: Node) -> Iter<'_, Node> {
-        assert!(self.is_reachable(node), "node {:?} is not reachable", node);
+        assert!(self.is_reachable(node), "node {node:?} is not reachable");
         Iter { dominators: self, node: Some(node) }
     }
 
diff --git a/compiler/rustc_data_structures/src/graph/scc/mod.rs b/compiler/rustc_data_structures/src/graph/scc/mod.rs
index b31092eca98..c8e66eb672c 100644
--- a/compiler/rustc_data_structures/src/graph/scc/mod.rs
+++ b/compiler/rustc_data_structures/src/graph/scc/mod.rs
@@ -233,10 +233,9 @@ where
             .map(G::Node::new)
             .map(|node| match this.start_walk_from(node) {
                 WalkReturn::Complete { scc_index } => scc_index,
-                WalkReturn::Cycle { min_depth } => panic!(
-                    "`start_walk_node({:?})` returned cycle with depth {:?}",
-                    node, min_depth
-                ),
+                WalkReturn::Cycle { min_depth } => {
+                    panic!("`start_walk_node({node:?})` returned cycle with depth {min_depth:?}")
+                }
             })
             .collect();
 
@@ -272,8 +271,7 @@ where
             NodeState::NotVisited => return None,
 
             NodeState::InCycleWith { parent } => panic!(
-                "`find_state` returned `InCycleWith({:?})`, which ought to be impossible",
-                parent
+                "`find_state` returned `InCycleWith({parent:?})`, which ought to be impossible"
             ),
         })
     }
@@ -369,7 +367,7 @@ where
                     previous_node = previous;
                 }
                 // Only InCycleWith nodes were added to the reverse linked list.
-                other => panic!("Invalid previous link while compressing cycle: {:?}", other),
+                other => panic!("Invalid previous link while compressing cycle: {other:?}"),
             }
 
             debug!("find_state: parent_state = {:?}", node_state);
@@ -394,7 +392,7 @@ where
                 // NotVisited can not be part of a cycle since it should
                 // have instead gotten explored.
                 NodeState::NotVisited | NodeState::InCycleWith { .. } => {
-                    panic!("invalid parent state: {:?}", node_state)
+                    panic!("invalid parent state: {node_state:?}")
                 }
             }
         }
diff --git a/compiler/rustc_data_structures/src/obligation_forest/graphviz.rs b/compiler/rustc_data_structures/src/obligation_forest/graphviz.rs
index 3a268e4b4f4..4b6aa116520 100644
--- a/compiler/rustc_data_structures/src/obligation_forest/graphviz.rs
+++ b/compiler/rustc_data_structures/src/obligation_forest/graphviz.rs
@@ -30,7 +30,7 @@ impl<O: ForestObligation> ObligationForest<O> {
 
         let counter = COUNTER.fetch_add(1, Ordering::AcqRel);
 
-        let file_path = dir.as_ref().join(format!("{:010}_{}.gv", counter, description));
+        let file_path = dir.as_ref().join(format!("{counter:010}_{description}.gv"));
 
         let mut gv_file = BufWriter::new(File::create(file_path).unwrap());
 
@@ -47,7 +47,7 @@ impl<'a, O: ForestObligation + 'a> dot::Labeller<'a> for &'a ObligationForest<O>
     }
 
     fn node_id(&self, index: &Self::Node) -> dot::Id<'_> {
-        dot::Id::new(format!("obligation_{}", index)).unwrap()
+        dot::Id::new(format!("obligation_{index}")).unwrap()
     }
 
     fn node_label(&self, index: &Self::Node) -> dot::LabelText<'_> {
diff --git a/compiler/rustc_data_structures/src/profiling.rs b/compiler/rustc_data_structures/src/profiling.rs
index 16296b22489..393f1739081 100644
--- a/compiler/rustc_data_structures/src/profiling.rs
+++ b/compiler/rustc_data_structures/src/profiling.rs
@@ -545,7 +545,7 @@ impl SelfProfiler {
         // length can behave as a source of entropy for heap addresses, when
         // ASLR is disabled and the heap is otherwise determinic.
         let pid: u32 = process::id();
-        let filename = format!("{}-{:07}.rustc_profile", crate_name, pid);
+        let filename = format!("{crate_name}-{pid:07}.rustc_profile");
         let path = output_directory.join(&filename);
         let profiler =
             Profiler::with_counter(&path, measureme::counters::Counter::by_name(counter_name)?)?;
diff --git a/compiler/rustc_data_structures/src/small_c_str.rs b/compiler/rustc_data_structures/src/small_c_str.rs
index 3a8ab8ff991..719e4e3d974 100644
--- a/compiler/rustc_data_structures/src/small_c_str.rs
+++ b/compiler/rustc_data_structures/src/small_c_str.rs
@@ -30,7 +30,7 @@ impl SmallCStr {
             SmallVec::from_vec(data)
         };
         if let Err(e) = ffi::CStr::from_bytes_with_nul(&data) {
-            panic!("The string \"{}\" cannot be converted into a CStr: {}", s, e);
+            panic!("The string \"{s}\" cannot be converted into a CStr: {e}");
         }
         SmallCStr { data }
     }
@@ -39,7 +39,7 @@ impl SmallCStr {
     pub fn new_with_nul(s: &str) -> SmallCStr {
         let b = s.as_bytes();
         if let Err(e) = ffi::CStr::from_bytes_with_nul(b) {
-            panic!("The string \"{}\" cannot be converted into a CStr: {}", s, e);
+            panic!("The string \"{s}\" cannot be converted into a CStr: {e}");
         }
         SmallCStr { data: SmallVec::from_slice(s.as_bytes()) }
     }
@@ -74,7 +74,7 @@ impl<'a> FromIterator<&'a str> for SmallCStr {
             iter.into_iter().flat_map(|s| s.as_bytes()).copied().collect::<SmallVec<_>>();
         data.push(0);
         if let Err(e) = ffi::CStr::from_bytes_with_nul(&data) {
-            panic!("The iterator {:?} cannot be converted into a CStr: {}", data, e);
+            panic!("The iterator {data:?} cannot be converted into a CStr: {e}");
         }
         Self { data }
     }
diff --git a/compiler/rustc_data_structures/src/vec_map.rs b/compiler/rustc_data_structures/src/vec_map.rs
index 2417df66bb9..d1a99bcaeb7 100644
--- a/compiler/rustc_data_structures/src/vec_map.rs
+++ b/compiler/rustc_data_structures/src/vec_map.rs
@@ -71,8 +71,7 @@ where
         // This should return just one element, otherwise it's a bug
         assert!(
             filter.next().is_none(),
-            "Collection {:#?} should have just one matching element",
-            self
+            "Collection {self:#?} should have just one matching element"
         );
         Some(value)
     }
diff --git a/compiler/rustc_driver/src/args.rs b/compiler/rustc_driver/src/args.rs
index 01338359f1a..42c97cc6a9d 100644
--- a/compiler/rustc_driver/src/args.rs
+++ b/compiler/rustc_driver/src/args.rs
@@ -25,7 +25,7 @@ pub fn arg_expand_all(at_args: &[String]) -> Vec<String> {
             Ok(arg) => args.extend(arg),
             Err(err) => rustc_session::early_error(
                 rustc_session::config::ErrorOutputType::default(),
-                &format!("Failed to load argument file: {}", err),
+                &format!("Failed to load argument file: {err}"),
             ),
         }
     }
@@ -42,8 +42,8 @@ impl fmt::Display for Error {
     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
         match self {
             Error::Utf8Error(None) => write!(fmt, "Utf8 error"),
-            Error::Utf8Error(Some(path)) => write!(fmt, "Utf8 error in {}", path),
-            Error::IOError(path, err) => write!(fmt, "IO Error: {}: {}", path, err),
+            Error::Utf8Error(Some(path)) => write!(fmt, "Utf8 error in {path}"),
+            Error::IOError(path, err) => write!(fmt, "IO Error: {path}: {err}"),
         }
     }
 }
diff --git a/compiler/rustc_driver/src/lib.rs b/compiler/rustc_driver/src/lib.rs
index 30179e97872..3cbe0052359 100644
--- a/compiler/rustc_driver/src/lib.rs
+++ b/compiler/rustc_driver/src/lib.rs
@@ -486,11 +486,8 @@ impl Compilation {
 
 fn handle_explain(registry: Registry, code: &str, output: ErrorOutputType) {
     let upper_cased_code = code.to_ascii_uppercase();
-    let normalised = if upper_cased_code.starts_with('E') {
-        upper_cased_code
-    } else {
-        format!("E{0:0>4}", code)
-    };
+    let normalised =
+        if upper_cased_code.starts_with('E') { upper_cased_code } else { format!("E{code:0>4}") };
     match registry.try_find_description(&normalised) {
         Ok(Some(description)) => {
             let mut is_in_code_block = false;
@@ -513,14 +510,14 @@ fn handle_explain(registry: Registry, code: &str, output: ErrorOutputType) {
             if io::stdout().is_terminal() {
                 show_content_with_pager(&text);
             } else {
-                print!("{}", text);
+                print!("{text}");
             }
         }
         Ok(None) => {
-            early_error(output, &format!("no extended information for {}", code));
+            early_error(output, &format!("no extended information for {code}"));
         }
         Err(InvalidErrorCode) => {
-            early_error(output, &format!("{} is not a valid error code", code));
+            early_error(output, &format!("{code} is not a valid error code"));
         }
     }
 }
@@ -552,7 +549,7 @@ fn show_content_with_pager(content: &str) {
     // If pager fails for whatever reason, we should still print the content
     // to standard output
     if fallback_to_println {
-        print!("{}", content);
+        print!("{content}");
     }
 }
 
@@ -672,7 +669,7 @@ fn print_crate_info(
                 );
                 let id = rustc_session::output::find_crate_name(sess, attrs, input);
                 if *req == PrintRequest::CrateName {
-                    println!("{}", id);
+                    println!("{id}");
                     continue;
                 }
                 let crate_types = collect_crate_types(sess, attrs);
@@ -704,7 +701,7 @@ fn print_crate_info(
                         }
 
                         if let Some(value) = value {
-                            Some(format!("{}=\"{}\"", name, value))
+                            Some(format!("{name}=\"{value}\""))
                         } else {
                             Some(name.to_string())
                         }
@@ -713,7 +710,7 @@ fn print_crate_info(
 
                 cfgs.sort();
                 for cfg in cfgs {
-                    println!("{}", cfg);
+                    println!("{cfg}");
                 }
             }
             CallingConventions => {
@@ -739,7 +736,7 @@ fn print_crate_info(
                     let stable = sess.target.options.supported_split_debuginfo.contains(split);
                     let unstable_ok = sess.unstable_options();
                     if stable || unstable_ok {
-                        println!("{}", split);
+                        println!("{split}");
                     }
                 }
             }
@@ -776,14 +773,14 @@ pub fn version_at_macro_invocation(
 ) {
     let verbose = matches.opt_present("verbose");
 
-    println!("{} {}", binary, version);
+    println!("{binary} {version}");
 
     if verbose {
-        println!("binary: {}", binary);
-        println!("commit-hash: {}", commit_hash);
-        println!("commit-date: {}", commit_date);
+        println!("binary: {binary}");
+        println!("commit-hash: {commit_hash}");
+        println!("commit-date: {commit_date}");
         println!("host: {}", config::host_triple());
-        println!("release: {}", release);
+        println!("release: {release}");
 
         let debug_flags = matches.opt_strs("Z");
         let backend_name = debug_flags.iter().find_map(|x| x.strip_prefix("codegen-backend="));
@@ -1037,7 +1034,7 @@ pub fn handle_options(args: &[String]) -> Option<getopts::Matches> {
                 .map(|&(name, ..)| ('C', name))
                 .chain(Z_OPTIONS.iter().map(|&(name, ..)| ('Z', name)))
                 .find(|&(_, name)| *opt == name.replace('_', "-"))
-                .map(|(flag, _)| format!("{}. Did you mean `-{} {}`?", e, flag, opt)),
+                .map(|(flag, _)| format!("{e}. Did you mean `-{flag} {opt}`?")),
             _ => None,
         };
         early_error(ErrorOutputType::default(), &msg.unwrap_or_else(|| e.to_string()));
@@ -1148,7 +1145,7 @@ fn extra_compiler_flags() -> Option<(Vec<String>, bool)> {
             } else {
                 result.push(a.to_string());
                 match ICE_REPORT_COMPILER_FLAGS_STRIP_VALUE.iter().find(|s| option == **s) {
-                    Some(s) => result.push(format!("{}=[REDACTED]", s)),
+                    Some(s) => result.push(format!("{s}=[REDACTED]")),
                     None => result.push(content),
                 }
             }
@@ -1246,7 +1243,7 @@ pub fn report_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str) {
 
     let mut xs: Vec<Cow<'static, str>> = vec![
         "the compiler unexpectedly panicked. this is a bug.".into(),
-        format!("we would appreciate a bug report: {}", bug_report_url).into(),
+        format!("we would appreciate a bug report: {bug_report_url}").into(),
         format!(
             "rustc {} running on {}",
             util::version_str!().unwrap_or("unknown_version"),
@@ -1379,7 +1376,7 @@ pub fn main() -> ! {
                 arg.into_string().unwrap_or_else(|arg| {
                     early_error(
                         ErrorOutputType::default(),
-                        &format!("argument {} is not valid Unicode: {:?}", i, arg),
+                        &format!("argument {i} is not valid Unicode: {arg:?}"),
                     )
                 })
             })
diff --git a/compiler/rustc_driver/src/pretty.rs b/compiler/rustc_driver/src/pretty.rs
index f9b1316d2eb..b2451bc730f 100644
--- a/compiler/rustc_driver/src/pretty.rs
+++ b/compiler/rustc_driver/src/pretty.rs
@@ -360,7 +360,7 @@ fn get_source(input: &Input, sess: &Session) -> (String, FileName) {
 
 fn write_or_print(out: &str, ofile: Option<&Path>, sess: &Session) {
     match ofile {
-        None => print!("{}", out),
+        None => print!("{out}"),
         Some(p) => {
             if let Err(e) = std::fs::write(p, out) {
                 sess.emit_fatal(UnprettyDumpFail {
@@ -402,7 +402,7 @@ pub fn print_after_parsing(
         }
         AstTree(PpAstTreeMode::Normal) => {
             debug!("pretty printing AST tree");
-            format!("{:#?}", krate)
+            format!("{krate:#?}")
         }
         _ => unreachable!(),
     };
@@ -446,7 +446,7 @@ pub fn print_after_hir_lowering<'tcx>(
 
         AstTree(PpAstTreeMode::Expanded) => {
             debug!("pretty-printing expanded AST");
-            format!("{:#?}", krate)
+            format!("{krate:#?}")
         }
 
         Hir(s) => call_with_pp_support_hir(&s, tcx, move |annotation, hir_map| {
diff --git a/compiler/rustc_error_codes/src/error_codes.rs b/compiler/rustc_error_codes/src/error_codes.rs
index 3fba2cf5749..76d5da19399 100644
--- a/compiler/rustc_error_codes/src/error_codes.rs
+++ b/compiler/rustc_error_codes/src/error_codes.rs
@@ -579,8 +579,7 @@ E0791: include_str!("./error_codes/E0791.md"),
 //  E0300, // unexpanded macro
 //  E0304, // expected signed integer constant
 //  E0305, // expected constant
-    E0313, // lifetime of borrowed pointer outlives lifetime of captured
-           // variable
+//  E0313, // removed: found unreachable
 //  E0314, // closure outlives stack frame
 //  E0315, // cannot invoke closure outside of its lifetime
 //  E0319, // trait impls for defaulted traits allowed just for structs/enums
diff --git a/compiler/rustc_error_codes/src/error_codes/E0015.md b/compiler/rustc_error_codes/src/error_codes/E0015.md
index 021a0219d13..ac78f66adad 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0015.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0015.md
@@ -1,5 +1,4 @@
-A constant item was initialized with something that is not a constant
-expression.
+A non-`const` function was called in a `const` context.
 
 Erroneous code example:
 
@@ -8,26 +7,20 @@ fn create_some() -> Option<u8> {
     Some(1)
 }
 
-const FOO: Option<u8> = create_some(); // error!
+// error: cannot call non-const fn `create_some` in constants
+const FOO: Option<u8> = create_some();
 ```
 
-The only functions that can be called in static or constant expressions are
-`const` functions, and struct/enum constructors.
+All functions used in a `const` context (constant or static expression) must
+be marked `const`.
 
 To fix this error, you can declare `create_some` as a constant function:
 
 ```
-const fn create_some() -> Option<u8> { // declared as a const function
+// declared as a `const` function:
+const fn create_some() -> Option<u8> {
     Some(1)
 }
 
-const FOO: Option<u8> = create_some(); // ok!
-
-// These are also working:
-struct Bar {
-    x: u8,
-}
-
-const OTHER_FOO: Option<u8> = Some(1);
-const BAR: Bar = Bar {x: 1};
+const FOO: Option<u8> = create_some(); // no error!
 ```
diff --git a/compiler/rustc_error_codes/src/error_codes/E0588.md b/compiler/rustc_error_codes/src/error_codes/E0588.md
index 040c7a02ef4..995d945f158 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0588.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0588.md
@@ -11,7 +11,7 @@ struct Aligned(i32);
 struct Packed(Aligned);
 ```
 
-Just like you cannot have both `align` and `packed` representation hints on a
+Just like you cannot have both `align` and `packed` representation hints on the
 same type, a `packed` type cannot contain another type with the `align`
 representation hint. However, you can do the opposite:
 
diff --git a/compiler/rustc_error_codes/src/error_codes/E0729.md b/compiler/rustc_error_codes/src/error_codes/E0729.md
index 74f89080b91..3891745b500 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0729.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0729.md
@@ -1,3 +1,5 @@
+#### Note: this error code is no longer emitted by the compiler
+
 Support for Non-Lexical Lifetimes (NLL) has been included in the Rust compiler
 since 1.31, and has been enabled on the 2015 edition since 1.36. The new borrow
 checker for NLL uncovered some bugs in the old borrow checker, which in some
diff --git a/compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl b/compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl
index db4c82b35c7..c8c7afb5f91 100644
--- a/compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl
+++ b/compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl
@@ -157,8 +157,6 @@ codegen_ssa_linker_file_stem = couldn't extract file stem from specified linker
 
 codegen_ssa_static_library_native_artifacts = Link against the following native artifacts when linking against this static library. The order and any duplication can be significant on some platforms.
 
-codegen_ssa_native_static_libs = native-static-libs: {$arguments}
-
 codegen_ssa_link_script_unavailable = can only use link script when linking with GNU-like linker
 
 codegen_ssa_link_script_write_failure = failed to write link script to {$path}: {$error}
@@ -194,3 +192,102 @@ codegen_ssa_unknown_archive_kind =
     Don't know how to build archive of type: {$kind}
 
 codegen_ssa_expected_used_symbol = expected `used`, `used(compiler)` or `used(linker)`
+
+codegen_ssa_multiple_main_functions = entry symbol `main` declared multiple times
+    .help = did you use `#[no_mangle]` on `fn main`? Use `#[start]` instead
+
+codegen_ssa_metadata_object_file_write = error writing metadata object file: {$error}
+
+codegen_ssa_invalid_windows_subsystem = invalid windows subsystem `{$subsystem}`, only `windows` and `console` are allowed
+
+codegen_ssa_erroneous_constant = erroneous constant encountered
+
+codegen_ssa_shuffle_indices_evaluation = could not evaluate shuffle_indices at compile time
+
+codegen_ssa_missing_memory_ordering = Atomic intrinsic missing memory ordering
+
+codegen_ssa_unknown_atomic_ordering = unknown ordering in atomic intrinsic
+
+codegen_ssa_atomic_compare_exchange = Atomic compare-exchange intrinsic missing failure memory ordering
+
+codegen_ssa_unknown_atomic_operation = unknown atomic operation
+
+codegen_ssa_invalid_monomorphization_basic_integer_type = invalid monomorphization of `{$name}` intrinsic: expected basic integer type, found `{$ty}`
+
+codegen_ssa_invalid_monomorphization_basic_float_type = invalid monomorphization of `{$name}` intrinsic: expected basic float type, found `{$ty}`
+
+codegen_ssa_invalid_monomorphization_float_to_int_unchecked = invalid monomorphization of `float_to_int_unchecked` intrinsic: expected basic float type, found `{$ty}`
+
+codegen_ssa_invalid_monomorphization_floating_point_vector = invalid monomorphization of `{$name}` intrinsic: unsupported element type `{$f_ty}` of floating-point vector `{$in_ty}`
+
+codegen_ssa_invalid_monomorphization_floating_point_type = invalid monomorphization of `{$name}` intrinsic: `{$in_ty}` is not a floating-point type
+
+codegen_ssa_invalid_monomorphization_unrecognized_intrinsic = invalid monomorphization of `{$name}` intrinsic: unrecognized intrinsic `{$name}`
+
+codegen_ssa_invalid_monomorphization_simd_argument = invalid monomorphization of `{$name}` intrinsic: expected SIMD argument type, found non-SIMD `{$ty}`
+
+codegen_ssa_invalid_monomorphization_simd_input = invalid monomorphization of `{$name}` intrinsic: expected SIMD input type, found non-SIMD `{$ty}`
+
+codegen_ssa_invalid_monomorphization_simd_first = invalid monomorphization of `{$name}` intrinsic: expected SIMD first type, found non-SIMD `{$ty}`
+
+codegen_ssa_invalid_monomorphization_simd_second = invalid monomorphization of `{$name}` intrinsic: expected SIMD second type, found non-SIMD `{$ty}`
+
+codegen_ssa_invalid_monomorphization_simd_third = invalid monomorphization of `{$name}` intrinsic: expected SIMD third type, found non-SIMD `{$ty}`
+
+codegen_ssa_invalid_monomorphization_simd_return = invalid monomorphization of `{$name}` intrinsic: expected SIMD return type, found non-SIMD `{$ty}`
+
+codegen_ssa_invalid_monomorphization_invalid_bitmask = invalid monomorphization of `{$name}` intrinsic: invalid bitmask `{$mask_ty}`, expected `u{$expected_int_bits}` or `[u8; {$expected_bytes}]`
+
+codegen_ssa_polymorphic_constant_too_generic = codegen encountered polymorphic constant: TooGeneric
+
+codegen_ssa_invalid_monomorphization_return_length_input_type = invalid monomorphization of `{$name}` intrinsic: expected return type with length {$in_len} (same as input type `{$in_ty}`), found `{$ret_ty}` with length {$out_len}
+
+codegen_ssa_invalid_monomorphization_second_argument_length = invalid monomorphization of `{$name}` intrinsic: expected second argument with length {$in_len} (same as input type `{$in_ty}`), found `{$arg_ty}` with length {$out_len}
+
+codegen_ssa_invalid_monomorphization_third_argument_length = invalid monomorphization of `{$name}` intrinsic: expected third argument with length {$in_len} (same as input type `{$in_ty}`), found `{$arg_ty}` with length {$out_len}
+
+codegen_ssa_invalid_monomorphization_return_integer_type = invalid monomorphization of `{$name}` intrinsic: expected return type with integer elements, found `{$ret_ty}` with non-integer `{$out_ty}`
+
+codegen_ssa_invalid_monomorphization_simd_shuffle = invalid monomorphization of `{$name}` intrinsic: simd_shuffle index must be an array of `u32`, got `{$ty}`
+
+codegen_ssa_invalid_monomorphization_return_length = invalid monomorphization of `{$name}` intrinsic: expected return type of length {$in_len}, found `{$ret_ty}` with length {$out_len}
+
+codegen_ssa_invalid_monomorphization_return_element = invalid monomorphization of `{$name}` intrinsic: expected return element type `{$in_elem}` (element of input `{$in_ty}`), found `{$ret_ty}` with element type `{$out_ty}`
+
+codegen_ssa_invalid_monomorphization_shuffle_index_not_constant = invalid monomorphization of `{$name}` intrinsic: shuffle index #{$arg_idx} is not a constant
+
+codegen_ssa_invalid_monomorphization_shuffle_index_out_of_bounds = invalid monomorphization of `{$name}` intrinsic: shuffle index #{$arg_idx} is out of bounds (limit {$total_len})
+
+codegen_ssa_invalid_monomorphization_inserted_type = invalid monomorphization of `{$name}` intrinsic: expected inserted type `{$in_elem}` (element of input `{$in_ty}`), found `{$out_ty}`
+
+codegen_ssa_invalid_monomorphization_return_type = invalid monomorphization of `{$name}` intrinsic: expected return type `{$in_elem}` (element of input `{$in_ty}`), found `{$ret_ty}`
+
+codegen_ssa_invalid_monomorphization_expected_return_type = invalid monomorphization of `{$name}` intrinsic: expected return type `{$in_ty}`, found `{$ret_ty}`
+
+codegen_ssa_invalid_monomorphization_mismatched_lengths = invalid monomorphization of `{$name}` intrinsic: mismatched lengths: mask length `{$m_len}` != other vector length `{$v_len}`
+
+codegen_ssa_invalid_monomorphization_mask_type = invalid monomorphization of `{$name}` intrinsic: mask element type is `{$ty}`, expected `i_`
+
+codegen_ssa_invalid_monomorphization_vector_argument = invalid monomorphization of `{$name}` intrinsic: vector argument `{$in_ty}`'s element type `{$in_elem}`, expected integer element type
+
+codegen_ssa_invalid_monomorphization_cannot_return = invalid monomorphization of `{$name}` intrinsic: cannot return `{$ret_ty}`, expected `u{$expected_int_bits}` or `[u8; {$expected_bytes}]`
+
+codegen_ssa_invalid_monomorphization_expected_element_type = invalid monomorphization of `{$name}` intrinsic: expected element type `{$expected_element}` of second argument `{$second_arg}` to be a pointer to the element type `{$in_elem}` of the first argument `{$in_ty}`, found `{$expected_element}` != `{$mutability} {$in_elem}`
+
+codegen_ssa_invalid_monomorphization_third_arg_element_type = invalid monomorphization of `{$name}` intrinsic: expected element type `{$expected_element}` of third argument `{$third_arg}` to be a signed integer type
+
+codegen_ssa_invalid_monomorphization_unsupported_symbol_of_size = invalid monomorphization of `{$name}` intrinsic: unsupported {$symbol} from `{$in_ty}` with element `{$in_elem}` of size `{$size}` to `{$ret_ty}`
+
+codegen_ssa_invalid_monomorphization_unsupported_symbol = invalid monomorphization of `{$name}` intrinsic: unsupported {$symbol} from `{$in_ty}` with element `{$in_elem}` to `{$ret_ty}`
+
+codegen_ssa_invalid_monomorphization_cast_fat_pointer = invalid monomorphization of `{$name}` intrinsic: cannot cast fat pointer `{$ty}`
+
+codegen_ssa_invalid_monomorphization_expected_pointer = invalid monomorphization of `{$name}` intrinsic: expected pointer, got `{$ty}`
+
+codegen_ssa_invalid_monomorphization_expected_usize = invalid monomorphization of `{$name}` intrinsic: expected `usize`, got `{$ty}`
+
+codegen_ssa_invalid_monomorphization_unsupported_cast = invalid monomorphization of `{$name}` intrinsic: unsupported cast from `{$in_ty}` with element `{$in_elem}` to `{$ret_ty}` with element `{$out_elem}`
+
+codegen_ssa_invalid_monomorphization_unsupported_operation = invalid monomorphization of `{$name}` intrinsic: unsupported operation on `{$in_ty}` with element `{$in_elem}`
+
+codegen_ssa_invalid_monomorphization_expected_vector_element_type = invalid monomorphization of `{$name}` intrinsic: expected element type `{$expected_element}` of vector type `{$vector_type}` to be a signed or unsigned integer type
diff --git a/compiler/rustc_error_messages/locales/en-US/infer.ftl b/compiler/rustc_error_messages/locales/en-US/infer.ftl
index c9d83746d54..c1cb07cf0df 100644
--- a/compiler/rustc_error_messages/locales/en-US/infer.ftl
+++ b/compiler/rustc_error_messages/locales/en-US/infer.ftl
@@ -172,3 +172,142 @@ 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`
+
+infer_explicit_lifetime_required_with_ident = explicit lifetime required in the type of `{$simple_ident}`
+    .label = lifetime `{$named}` required
+
+infer_explicit_lifetime_required_with_param_type = explicit lifetime required in parameter type
+    .label = lifetime `{$named}` required
+
+infer_explicit_lifetime_required_sugg_with_ident = add explicit lifetime `{$named}` to the type of `{$simple_ident}`
+
+infer_explicit_lifetime_required_sugg_with_param_type = add explicit lifetime `{$named}` to type
+
+infer_actual_impl_expl_expected_signature_two = {$leading_ellipsis ->
+    [true] ...
+    *[false] {""}
+}closure with signature `{$ty_or_sig}` must implement `{$trait_path}`, for any two lifetimes `'{$lifetime_1}` and `'{$lifetime_2}`...
+infer_actual_impl_expl_expected_signature_any = {$leading_ellipsis ->
+    [true] ...
+    *[false] {""}
+}closure with signature `{$ty_or_sig}` must implement `{$trait_path}`, for any lifetime `'{$lifetime_1}`...
+infer_actual_impl_expl_expected_signature_some = {$leading_ellipsis ->
+    [true] ...
+    *[false] {""}
+}closure with signature `{$ty_or_sig}` must implement `{$trait_path}`, for some specific lifetime `'{lifetime_1}`...
+infer_actual_impl_expl_expected_signature_nothing = {$leading_ellipsis ->
+    [true] ...
+    *[false] {""}
+}closure with signature `{$ty_or_sig}` must implement `{$trait_path}`
+infer_actual_impl_expl_expected_passive_two = {$leading_ellipsis ->
+    [true] ...
+    *[false] {""}
+}`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`, for any two lifetimes `'{$lifetime_1}` and `'{$lifetime_2}`...
+infer_actual_impl_expl_expected_passive_any = {$leading_ellipsis ->
+    [true] ...
+    *[false] {""}
+}`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`, for any lifetime `'{$lifetime_1}`...
+infer_actual_impl_expl_expected_passive_some = {$leading_ellipsis ->
+    [true] ...
+    *[false] {""}
+}`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`, for some specific lifetime `'{lifetime_1}`...
+infer_actual_impl_expl_expected_passive_nothing = {$leading_ellipsis ->
+    [true] ...
+    *[false] {""}
+}`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`
+infer_actual_impl_expl_expected_other_two = {$leading_ellipsis ->
+    [true] ...
+    *[false] {""}
+}`{$ty_or_sig}` must implement `{$trait_path}`, for any two lifetimes `'{$lifetime_1}` and `'{$lifetime_2}`...
+infer_actual_impl_expl_expected_other_any = {$leading_ellipsis ->
+    [true] ...
+    *[false] {""}
+}`{$ty_or_sig}` must implement `{$trait_path}`, for any lifetime `'{$lifetime_1}`...
+infer_actual_impl_expl_expected_other_some = {$leading_ellipsis ->
+    [true] ...
+    *[false] {""}
+}`{$ty_or_sig}` must implement `{$trait_path}`, for some specific lifetime `'{lifetime_1}`...
+infer_actual_impl_expl_expected_other_nothing = {$leading_ellipsis ->
+    [true] ...
+    *[false] {""}
+}`{$ty_or_sig}` must implement `{$trait_path}`
+
+infer_actual_impl_expl_but_actually_implements_trait = ...but it actually implements `{$trait_path}`{$has_lifetime ->
+    [true] , for some specific lifetime `'{$lifetime}`
+    *[false] {""}
+}
+infer_actual_impl_expl_but_actually_implemented_for_ty = ...but `{$trait_path}` is actually implemented for the type `{$ty}`{$has_lifetime ->
+    [true] , for some specific lifetime `'{$lifetime}`
+    *[false] {""}
+}
+infer_actual_impl_expl_but_actually_ty_implements = ...but `{$ty}` actually implements `{$trait_path}`{$has_lifetime ->
+    [true] , for some specific lifetime `'{$lifetime}`
+    *[false] {""}
+}
+
+infer_trait_placeholder_mismatch = implementation of `{$trait_def_id}` is not general enough
+    .label_satisfy = doesn't satisfy where-clause
+    .label_where = due to a where-clause on `{$def_id}`...
+    .label_dup = implementation of `{$trait_def_id}` is not general enough
+
+infer_trait_impl_diff = `impl` item signature doesn't match `trait` item signature
+    .found = found `{$found}`
+    .expected = expected `{$expected}`
+    .expected_found = expected signature `{$expected}`
+               {"   "}found signature `{$found}`
+
+infer_tid_rel_help = verify the lifetime relationships in the `trait` and `impl` between the `self` argument, the other inputs and its output
+infer_tid_consider_borrowing = consider borrowing this type parameter in the trait
+infer_tid_param_help = the lifetime requirements from the `impl` do not correspond to the requirements in the `trait`
+
+infer_dtcs_has_lifetime_req_label = this has an implicit `'static` lifetime requirement
+infer_dtcs_introduces_requirement = calling this method introduces the `impl`'s 'static` requirement
+infer_dtcs_has_req_note = the used `impl` has a `'static` requirement
+infer_dtcs_suggestion = consider relaxing the implicit `'static` requirement
+
+infer_but_calling_introduces = {$has_param_name ->
+    [true] `{$param_name}`
+    *[false] `fn` parameter
+} has {$lifetime_kind ->
+    [named] lifetime `{lifetime}`
+    *[anon] an anonymous lifetime `'_`
+} but calling `{assoc_item}` introduces an implicit `'static` lifetime requirement
+    .label1 = {$has_lifetime ->
+        [named] lifetime `{lifetime}`
+        *[anon] an anonymous lifetime `'_`
+    }
+    .label2 = ...is used and required to live as long as `'static` here because of an implicit lifetime bound on the {$has_impl_path ->
+        [named] `impl` of `{$impl_path}`
+        *[anon] inherent `impl`
+    }
+
+infer_but_needs_to_satisfy = {$has_param_name ->
+    [true] `{$param_name}`
+    *[false] `fn` parameter
+} has {$has_lifetime ->
+    [named] lifetime `{lifetime}`
+    *[anon] an anonymous lifetime `'_`
+} but it needs to satisfy a `'static` lifetime requirement
+    .influencer = this data with {$has_lifetime ->
+        [named] lifetime `{lifetime}`
+        *[anon] an anonymous lifetime `'_`
+    }...
+    .require = {$spans_empty ->
+        *[true] ...is used and required to live as long as `'static` here
+        [false] ...and is required to live as long as `'static` here
+    }
+    .used_here = ...is used here...
+    .introduced_by_bound = 'static` lifetime requirement introduced by this bound
+
+infer_more_targeted = {$has_param_name ->
+    [true] `{$param_name}`
+    *[false] `fn` parameter
+} has {$has_lifetime ->
+    [named] lifetime `{lifetime}`
+    *[anon] an anonymous lifetime `'_`
+} but calling `{$ident}` introduces an implicit `'static` lifetime requirement
+
+infer_ril_introduced_here = `'static` requirement introduced here
+infer_ril_introduced_by = requirement introduced by this return type
+infer_ril_because_of = because of this returned expression
+infer_ril_static_introduced_by = "`'static` lifetime requirement introduced by the return type
diff --git a/compiler/rustc_error_messages/locales/en-US/session.ftl b/compiler/rustc_error_messages/locales/en-US/session.ftl
index ab9e8b6baae..bc37d91a7c6 100644
--- a/compiler/rustc_error_messages/locales/en-US/session.ftl
+++ b/compiler/rustc_error_messages/locales/en-US/session.ftl
@@ -85,6 +85,7 @@ session_invalid_float_literal_suffix = invalid suffix `{$suffix}` for float lite
     .help = valid suffixes are `f32` and `f64`
 
 session_int_literal_too_large = integer literal is too large
+    .note = value exceeds limit of `{$limit}`
 
 session_invalid_int_literal_width = invalid width `{$width}` for integer literal
     .help = valid widths are 8, 16, 32, 64 and 128
diff --git a/compiler/rustc_errors/Cargo.toml b/compiler/rustc_errors/Cargo.toml
index dee7a31ec20..cadd53fbd83 100644
--- a/compiler/rustc_errors/Cargo.toml
+++ b/compiler/rustc_errors/Cargo.toml
@@ -17,6 +17,7 @@ rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_target = { path = "../rustc_target" }
 rustc_hir = { path = "../rustc_hir" }
 rustc_lint_defs = { path = "../rustc_lint_defs" }
+rustc_type_ir = { path = "../rustc_type_ir" }
 unicode-width = "0.1.4"
 termcolor = "1.0"
 annotate-snippets = "0.9"
diff --git a/compiler/rustc_errors/src/diagnostic_builder.rs b/compiler/rustc_errors/src/diagnostic_builder.rs
index a2ed988643f..cbfee582d87 100644
--- a/compiler/rustc_errors/src/diagnostic_builder.rs
+++ b/compiler/rustc_errors/src/diagnostic_builder.rs
@@ -1,7 +1,7 @@
 use crate::diagnostic::IntoDiagnosticArg;
 use crate::{
     Diagnostic, DiagnosticId, DiagnosticMessage, DiagnosticStyledString, ErrorGuaranteed,
-    SubdiagnosticMessage,
+    ExplicitBug, SubdiagnosticMessage,
 };
 use crate::{Handler, Level, MultiSpan, StashKey};
 use rustc_lint_defs::Applicability;
@@ -12,6 +12,7 @@ use std::borrow::Cow;
 use std::fmt::{self, Debug};
 use std::marker::PhantomData;
 use std::ops::{Deref, DerefMut};
+use std::panic;
 use std::thread::panicking;
 
 /// Trait implemented by error types. This should not be implemented manually. Instead, use
@@ -308,6 +309,58 @@ impl EmissionGuarantee for Noted {
     }
 }
 
+/// Marker type which enables implementation of `create_bug` and `emit_bug` functions for
+/// bug struct diagnostics.
+#[derive(Copy, Clone)]
+pub struct Bug;
+
+impl<'a> DiagnosticBuilder<'a, Bug> {
+    /// Convenience function for internal use, clients should use one of the
+    /// `struct_*` methods on [`Handler`].
+    #[track_caller]
+    pub(crate) fn new_bug(handler: &'a Handler, message: impl Into<DiagnosticMessage>) -> Self {
+        let diagnostic = Diagnostic::new_with_code(Level::Bug, None, message);
+        Self::new_diagnostic_bug(handler, diagnostic)
+    }
+
+    /// Creates a new `DiagnosticBuilder` with an already constructed
+    /// diagnostic.
+    pub(crate) fn new_diagnostic_bug(handler: &'a Handler, diagnostic: Diagnostic) -> Self {
+        debug!("Created new diagnostic bug");
+        Self {
+            inner: DiagnosticBuilderInner {
+                state: DiagnosticBuilderState::Emittable(handler),
+                diagnostic: Box::new(diagnostic),
+            },
+            _marker: PhantomData,
+        }
+    }
+}
+
+impl EmissionGuarantee for Bug {
+    fn diagnostic_builder_emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self {
+        match db.inner.state {
+            // First `.emit()` call, the `&Handler` is still available.
+            DiagnosticBuilderState::Emittable(handler) => {
+                db.inner.state = DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation;
+
+                handler.emit_diagnostic(&mut db.inner.diagnostic);
+            }
+            // `.emit()` was previously called, disallowed from repeating it.
+            DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation => {}
+        }
+        // Then panic. No need to return the marker type.
+        panic::panic_any(ExplicitBug);
+    }
+
+    fn make_diagnostic_builder(
+        handler: &Handler,
+        msg: impl Into<DiagnosticMessage>,
+    ) -> DiagnosticBuilder<'_, Self> {
+        DiagnosticBuilder::new_bug(handler, msg)
+    }
+}
+
 impl<'a> DiagnosticBuilder<'a, !> {
     /// Convenience function for internal use, clients should use one of the
     /// `struct_*` methods on [`Handler`].
diff --git a/compiler/rustc_errors/src/diagnostic_impls.rs b/compiler/rustc_errors/src/diagnostic_impls.rs
index 628cb90903f..794b6efcc2b 100644
--- a/compiler/rustc_errors/src/diagnostic_impls.rs
+++ b/compiler/rustc_errors/src/diagnostic_impls.rs
@@ -9,6 +9,7 @@ use rustc_span::edition::Edition;
 use rustc_span::symbol::{Ident, MacroRulesNormalizedIdent, Symbol};
 use rustc_target::abi::TargetDataLayoutErrors;
 use rustc_target::spec::{PanicStrategy, SplitDebuginfo, StackProtector, TargetTriple};
+use rustc_type_ir as type_ir;
 use std::borrow::Cow;
 use std::fmt;
 use std::num::ParseIntError;
@@ -170,6 +171,12 @@ impl IntoDiagnosticArg for ast::token::TokenKind {
     }
 }
 
+impl IntoDiagnosticArg for type_ir::FloatTy {
+    fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
+        DiagnosticArgValue::Str(Cow::Borrowed(self.name_str()))
+    }
+}
+
 impl IntoDiagnosticArg for Level {
     fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
         DiagnosticArgValue::Str(Cow::Borrowed(match self {
diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs
index 136c360201e..b4d23e96f8f 100644
--- a/compiler/rustc_errors/src/lib.rs
+++ b/compiler/rustc_errors/src/lib.rs
@@ -978,6 +978,7 @@ impl Handler {
         self.inner.borrow_mut().span_bug(span, msg)
     }
 
+    /// For documentation on this, see `Session::delay_span_bug`.
     #[track_caller]
     pub fn delay_span_bug(
         &self,
@@ -1132,6 +1133,20 @@ impl Handler {
         self.create_fatal(fatal).emit()
     }
 
+    pub fn create_bug<'a>(
+        &'a self,
+        bug: impl IntoDiagnostic<'a, diagnostic_builder::Bug>,
+    ) -> DiagnosticBuilder<'a, diagnostic_builder::Bug> {
+        bug.into_diagnostic(self)
+    }
+
+    pub fn emit_bug<'a>(
+        &'a self,
+        bug: impl IntoDiagnostic<'a, diagnostic_builder::Bug>,
+    ) -> diagnostic_builder::Bug {
+        self.create_bug(bug).emit()
+    }
+
     fn emit_diag_at_span(
         &self,
         mut diag: Diagnostic,
@@ -1529,6 +1544,7 @@ impl HandlerInner {
         self.emit_diagnostic(diag.set_span(sp));
     }
 
+    /// For documentation on this, see `Session::delay_span_bug`.
     #[track_caller]
     fn delay_span_bug(
         &mut self,
diff --git a/compiler/rustc_expand/src/mbe/diagnostics.rs b/compiler/rustc_expand/src/mbe/diagnostics.rs
index 3a38d7a9669..f469b2daef5 100644
--- a/compiler/rustc_expand/src/mbe/diagnostics.rs
+++ b/compiler/rustc_expand/src/mbe/diagnostics.rs
@@ -114,6 +114,12 @@ impl BestFailure {
 }
 
 impl<'a, 'cx, 'matcher> Tracker<'matcher> for CollectTrackerAndEmitter<'a, 'cx, 'matcher> {
+    type Failure = (Token, usize, &'static str);
+
+    fn build_failure(tok: Token, position: usize, msg: &'static str) -> Self::Failure {
+        (tok, position, msg)
+    }
+
     fn before_match_loc(&mut self, parser: &TtParser, matcher: &'matcher MatcherLoc) {
         if self.remaining_matcher.is_none()
             || (parser.has_no_remaining_items_for_step() && *matcher != MatcherLoc::Eof)
@@ -122,7 +128,7 @@ impl<'a, 'cx, 'matcher> Tracker<'matcher> for CollectTrackerAndEmitter<'a, 'cx,
         }
     }
 
-    fn after_arm(&mut self, result: &NamedParseResult) {
+    fn after_arm(&mut self, result: &NamedParseResult<Self::Failure>) {
         match result {
             Success(_) => {
                 // Nonterminal parser recovery might turn failed matches into successful ones,
@@ -132,7 +138,7 @@ impl<'a, 'cx, 'matcher> Tracker<'matcher> for CollectTrackerAndEmitter<'a, 'cx,
                     "should not collect detailed info for successful macro match",
                 );
             }
-            Failure(token, approx_position, msg) => {
+            Failure((token, approx_position, msg)) => {
                 debug!(?token, ?msg, "a new failure of an arm");
 
                 if self
@@ -175,6 +181,21 @@ impl<'a, 'cx> CollectTrackerAndEmitter<'a, 'cx, '_> {
     }
 }
 
+/// Currently used by macro_rules! compilation to extract a little information from the `Failure` case.
+pub struct FailureForwarder;
+
+impl<'matcher> Tracker<'matcher> for FailureForwarder {
+    type Failure = (Token, usize, &'static str);
+
+    fn build_failure(tok: Token, position: usize, msg: &'static str) -> Self::Failure {
+        (tok, position, msg)
+    }
+
+    fn description() -> &'static str {
+        "failure-forwarder"
+    }
+}
+
 pub(super) fn emit_frag_parse_err(
     mut e: DiagnosticBuilder<'_, rustc_errors::ErrorGuaranteed>,
     parser: &Parser<'_>,
diff --git a/compiler/rustc_expand/src/mbe/macro_parser.rs b/compiler/rustc_expand/src/mbe/macro_parser.rs
index df1c1834c1d..2e199541b92 100644
--- a/compiler/rustc_expand/src/mbe/macro_parser.rs
+++ b/compiler/rustc_expand/src/mbe/macro_parser.rs
@@ -305,13 +305,13 @@ enum EofMatcherPositions {
 }
 
 /// Represents the possible results of an attempted parse.
-pub(crate) enum ParseResult<T> {
+pub(crate) enum ParseResult<T, F> {
     /// Parsed successfully.
     Success(T),
     /// Arm failed to match. If the second parameter is `token::Eof`, it indicates an unexpected
     /// end of macro invocation. Otherwise, it indicates that no rules expected the given token.
     /// The usize is the approximate position of the token in the input token stream.
-    Failure(Token, usize, &'static str),
+    Failure(F),
     /// Fatal error (malformed macro?). Abort compilation.
     Error(rustc_span::Span, String),
     ErrorReported(ErrorGuaranteed),
@@ -320,7 +320,7 @@ pub(crate) enum ParseResult<T> {
 /// A `ParseResult` where the `Success` variant contains a mapping of
 /// `MacroRulesNormalizedIdent`s to `NamedMatch`es. This represents the mapping
 /// of metavars to the token trees they bind to.
-pub(crate) type NamedParseResult = ParseResult<NamedMatches>;
+pub(crate) type NamedParseResult<F> = ParseResult<NamedMatches, F>;
 
 /// Contains a mapping of `MacroRulesNormalizedIdent`s to `NamedMatch`es.
 /// This represents the mapping of metavars to the token trees they bind to.
@@ -458,7 +458,7 @@ impl TtParser {
         token: &Token,
         approx_position: usize,
         track: &mut T,
-    ) -> Option<NamedParseResult> {
+    ) -> Option<NamedParseResult<T::Failure>> {
         // Matcher positions that would be valid if the macro invocation was over now. Only
         // modified if `token == Eof`.
         let mut eof_mps = EofMatcherPositions::None;
@@ -595,14 +595,14 @@ impl TtParser {
                 EofMatcherPositions::Multiple => {
                     Error(token.span, "ambiguity: multiple successful parses".to_string())
                 }
-                EofMatcherPositions::None => Failure(
+                EofMatcherPositions::None => Failure(T::build_failure(
                     Token::new(
                         token::Eof,
                         if token.span.is_dummy() { token.span } else { token.span.shrink_to_hi() },
                     ),
                     approx_position,
                     "missing tokens in macro arguments",
-                ),
+                )),
             })
         } else {
             None
@@ -615,7 +615,7 @@ impl TtParser {
         parser: &mut Cow<'_, Parser<'_>>,
         matcher: &'matcher [MatcherLoc],
         track: &mut T,
-    ) -> NamedParseResult {
+    ) -> NamedParseResult<T::Failure> {
         // A queue of possible matcher positions. We initialize it with the matcher position in
         // which the "dot" is before the first token of the first token tree in `matcher`.
         // `parse_tt_inner` then processes all of these possible matcher positions and produces
@@ -648,11 +648,11 @@ impl TtParser {
                 (0, 0) => {
                     // There are no possible next positions AND we aren't waiting for the black-box
                     // parser: syntax error.
-                    return Failure(
+                    return Failure(T::build_failure(
                         parser.token.clone(),
                         parser.approx_token_stream_pos(),
                         "no rules expected this token in macro call",
-                    );
+                    ));
                 }
 
                 (_, 0) => {
@@ -711,11 +711,11 @@ impl TtParser {
         }
     }
 
-    fn ambiguity_error(
+    fn ambiguity_error<F>(
         &self,
         matcher: &[MatcherLoc],
         token_span: rustc_span::Span,
-    ) -> NamedParseResult {
+    ) -> NamedParseResult<F> {
         let nts = self
             .bb_mps
             .iter()
@@ -741,11 +741,11 @@ impl TtParser {
         )
     }
 
-    fn nameize<I: Iterator<Item = NamedMatch>>(
+    fn nameize<I: Iterator<Item = NamedMatch>, F>(
         &self,
         matcher: &[MatcherLoc],
         mut res: I,
-    ) -> NamedParseResult {
+    ) -> NamedParseResult<F> {
         // Make that each metavar has _exactly one_ binding. If so, insert the binding into the
         // `NamedParseResult`. Otherwise, it's an error.
         let mut ret_val = FxHashMap::default();
diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs
index fbb806fe81b..c0489f68633 100644
--- a/compiler/rustc_expand/src/mbe/macro_rules.rs
+++ b/compiler/rustc_expand/src/mbe/macro_rules.rs
@@ -141,31 +141,40 @@ fn trace_macros_note(cx_expansions: &mut FxIndexMap<Span, Vec<String>>, sp: Span
 }
 
 pub(super) trait Tracker<'matcher> {
+    /// The contents of `ParseResult::Failure`.
+    type Failure;
+
+    /// Arm failed to match. If the token is `token::Eof`, it indicates an unexpected
+    /// end of macro invocation. Otherwise, it indicates that no rules expected the given token.
+    /// The usize is the approximate position of the token in the input token stream.
+    fn build_failure(tok: Token, position: usize, msg: &'static str) -> Self::Failure;
+
     /// This is called before trying to match next MatcherLoc on the current token.
-    fn before_match_loc(&mut self, parser: &TtParser, matcher: &'matcher MatcherLoc);
+    fn before_match_loc(&mut self, _parser: &TtParser, _matcher: &'matcher MatcherLoc) {}
 
     /// This is called after an arm has been parsed, either successfully or unsuccessfully. When this is called,
     /// `before_match_loc` was called at least once (with a `MatcherLoc::Eof`).
-    fn after_arm(&mut self, result: &NamedParseResult);
+    fn after_arm(&mut self, _result: &NamedParseResult<Self::Failure>) {}
 
     /// For tracing.
     fn description() -> &'static str;
 
-    fn recovery() -> Recovery;
+    fn recovery() -> Recovery {
+        Recovery::Forbidden
+    }
 }
 
 /// A noop tracker that is used in the hot path of the expansion, has zero overhead thanks to monomorphization.
 pub(super) struct NoopTracker;
 
 impl<'matcher> Tracker<'matcher> for NoopTracker {
-    fn before_match_loc(&mut self, _: &TtParser, _: &'matcher MatcherLoc) {}
-    fn after_arm(&mut self, _: &NamedParseResult) {}
+    type Failure = ();
+
+    fn build_failure(_tok: Token, _position: usize, _msg: &'static str) -> Self::Failure {}
+
     fn description() -> &'static str {
         "none"
     }
-    fn recovery() -> Recovery {
-        Recovery::Forbidden
-    }
 }
 
 /// Expands the rules based macro defined by `lhses` and `rhses` for a given
@@ -326,8 +335,8 @@ pub(super) fn try_match_macro<'matcher, T: Tracker<'matcher>>(
 
                 return Ok((i, named_matches));
             }
-            Failure(_, reached_position, _) => {
-                trace!(%reached_position, "Failed to match arm, trying the next one");
+            Failure(_) => {
+                trace!("Failed to match arm, trying the next one");
                 // Try the next arm.
             }
             Error(_, _) => {
@@ -381,11 +390,13 @@ pub fn compile_declarative_macro(
     let rhs_nm = Ident::new(sym::rhs, def.span);
     let tt_spec = Some(NonterminalKind::TT);
 
-    // Parse the macro_rules! invocation
-    let (macro_rules, body) = match &def.kind {
-        ast::ItemKind::MacroDef(def) => (def.macro_rules, def.body.tokens.clone()),
+    let macro_def = match &def.kind {
+        ast::ItemKind::MacroDef(def) => def,
         _ => unreachable!(),
     };
+    let macro_rules = macro_def.macro_rules;
+
+    // Parse the macro_rules! invocation
 
     // The pattern that macro_rules matches.
     // The grammar for macro_rules! is:
@@ -426,13 +437,32 @@ pub fn compile_declarative_macro(
     // Convert it into `MatcherLoc` form.
     let argument_gram = mbe::macro_parser::compute_locs(&argument_gram);
 
-    let parser = Parser::new(&sess.parse_sess, body, true, rustc_parse::MACRO_ARGUMENTS);
+    let create_parser = || {
+        let body = macro_def.body.tokens.clone();
+        Parser::new(&sess.parse_sess, body, true, rustc_parse::MACRO_ARGUMENTS)
+    };
+
+    let parser = create_parser();
     let mut tt_parser =
         TtParser::new(Ident::with_dummy_span(if macro_rules { kw::MacroRules } else { kw::Macro }));
     let argument_map =
         match tt_parser.parse_tt(&mut Cow::Owned(parser), &argument_gram, &mut NoopTracker) {
             Success(m) => m,
-            Failure(token, _, msg) => {
+            Failure(()) => {
+                // The fast `NoopTracker` doesn't have any info on failure, so we need to retry it with another one
+                // that gives us the information we need.
+                // For this we need to reclone the macro body as the previous parser consumed it.
+                let retry_parser = create_parser();
+
+                let parse_result = tt_parser.parse_tt(
+                    &mut Cow::Owned(retry_parser),
+                    &argument_gram,
+                    &mut diagnostics::FailureForwarder,
+                );
+                let Failure((token, _, msg)) = parse_result else {
+                    unreachable!("matcher returned something other than Failure after retry");
+                };
+
                 let s = parse_failure_msg(&token);
                 let sp = token.span.substitute_dummy(def.span);
                 let mut err = sess.parse_sess.span_diagnostic.struct_span_err(sp, &s);
diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs
index 6d8e78a0f18..ad85231860d 100644
--- a/compiler/rustc_feature/src/builtin_attrs.rs
+++ b/compiler/rustc_feature/src/builtin_attrs.rs
@@ -70,7 +70,7 @@ impl std::fmt::Debug for AttributeGate {
     fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         match *self {
             Self::Gated(ref stab, name, expl, _) => {
-                write!(fmt, "Gated({:?}, {}, {})", stab, name, expl)
+                write!(fmt, "Gated({stab:?}, {name}, {expl})")
             }
             Self::Ungated => write!(fmt, "Ungated"),
         }
diff --git a/compiler/rustc_feature/src/lib.rs b/compiler/rustc_feature/src/lib.rs
index bdaa0ee88eb..8e2a13a6c0a 100644
--- a/compiler/rustc_feature/src/lib.rs
+++ b/compiler/rustc_feature/src/lib.rs
@@ -120,7 +120,7 @@ fn find_lang_feature_issue(feature: Symbol) -> Option<NonZeroU32> {
             .find(|t| t.name == feature);
         match found {
             Some(found) => found.issue,
-            None => panic!("feature `{}` is not declared anywhere", feature),
+            None => panic!("feature `{feature}` is not declared anywhere"),
         }
     }
 }
diff --git a/compiler/rustc_graphviz/src/lib.rs b/compiler/rustc_graphviz/src/lib.rs
index 434f0a53b78..b70a55e8953 100644
--- a/compiler/rustc_graphviz/src/lib.rs
+++ b/compiler/rustc_graphviz/src/lib.rs
@@ -516,7 +516,7 @@ impl<'a> LabelText<'a> {
         match *self {
             LabelStr(ref s) => format!("\"{}\"", s.escape_default()),
             EscStr(ref s) => format!("\"{}\"", LabelText::escape_str(s)),
-            HtmlStr(ref s) => format!("<{}>", s),
+            HtmlStr(ref s) => format!("<{s}>"),
         }
     }
 
@@ -622,7 +622,7 @@ where
     if let Some(fontname) = options.iter().find_map(|option| {
         if let RenderOption::Fontname(fontname) = option { Some(fontname) } else { None }
     }) {
-        font = format!(r#"fontname="{}""#, fontname);
+        font = format!(r#"fontname="{fontname}""#);
         graph_attrs.push(&font[..]);
         content_attrs.push(&font[..]);
     }
@@ -635,8 +635,8 @@ where
     if !(graph_attrs.is_empty() && content_attrs.is_empty()) {
         writeln!(w, r#"    graph[{}];"#, graph_attrs.join(" "))?;
         let content_attrs_str = content_attrs.join(" ");
-        writeln!(w, r#"    node[{}];"#, content_attrs_str)?;
-        writeln!(w, r#"    edge[{}];"#, content_attrs_str)?;
+        writeln!(w, r#"    node[{content_attrs_str}];"#)?;
+        writeln!(w, r#"    edge[{content_attrs_str}];"#)?;
     }
 
     let mut text = Vec::new();
@@ -649,7 +649,7 @@ where
         write!(text, "{}", id.as_slice()).unwrap();
 
         if !options.contains(&RenderOption::NoNodeLabels) {
-            write!(text, "[label={}]", escaped).unwrap();
+            write!(text, "[label={escaped}]").unwrap();
         }
 
         let style = g.node_style(n);
@@ -678,7 +678,7 @@ where
         write!(text, "{} -> {}", source_id.as_slice(), target_id.as_slice()).unwrap();
 
         if !options.contains(&RenderOption::NoEdgeLabels) {
-            write!(text, "[label={}]", escaped_label).unwrap();
+            write!(text, "[label={escaped_label}]").unwrap();
         }
 
         let style = g.edge_style(e);
diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs
index 149cf4ece37..92103979786 100644
--- a/compiler/rustc_hir/src/def.rs
+++ b/compiler/rustc_hir/src/def.rs
@@ -597,8 +597,7 @@ impl<Id> Res<Id> {
     where
         Id: Debug,
     {
-        self.opt_def_id()
-            .unwrap_or_else(|| panic!("attempted .def_id() on invalid res: {:?}", self))
+        self.opt_def_id().unwrap_or_else(|| panic!("attempted .def_id() on invalid res: {self:?}"))
     }
 
     /// Return `Some(..)` with the `DefId` of this `Res` if it has a ID, else `None`.
diff --git a/compiler/rustc_hir/src/definitions.rs b/compiler/rustc_hir/src/definitions.rs
index dd37efb6983..21cf214e47c 100644
--- a/compiler/rustc_hir/src/definitions.rs
+++ b/compiler/rustc_hir/src/definitions.rs
@@ -53,9 +53,8 @@ impl DefPathTable {
             //
             // See the documentation for DefPathHash for more information.
             panic!(
-                "found DefPathHash collision between {:?} and {:?}. \
-                    Compilation cannot continue.",
-                def_path1, def_path2
+                "found DefPathHash collision between {def_path1:?} and {def_path2:?}. \
+                    Compilation cannot continue."
             );
         }
 
@@ -224,7 +223,7 @@ impl DefPath {
         let mut s = String::with_capacity(self.data.len() * 16);
 
         for component in &self.data {
-            write!(s, "::{}", component).unwrap();
+            write!(s, "::{component}").unwrap();
         }
 
         s
@@ -240,7 +239,7 @@ impl DefPath {
         for component in &self.data {
             s.extend(opt_delimiter);
             opt_delimiter = Some('-');
-            write!(s, "{}", component).unwrap();
+            write!(s, "{component}").unwrap();
         }
 
         s
@@ -433,7 +432,7 @@ impl fmt::Display for DefPathData {
         match self.name() {
             DefPathDataName::Named(name) => f.write_str(name.as_str()),
             // FIXME(#70334): this will generate legacy {{closure}}, {{impl}}, etc
-            DefPathDataName::Anon { namespace } => write!(f, "{{{{{}}}}}", namespace),
+            DefPathDataName::Anon { namespace } => write!(f, "{{{{{namespace}}}}}"),
         }
     }
 }
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index 034f06bb889..bc897ed8112 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -3460,7 +3460,7 @@ impl<'hir> Node<'hir> {
     /// ```ignore (illustrative)
     /// ctor
     ///     .ctor_hir_id()
-    ///     .and_then(|ctor_id| tcx.hir().find(tcx.hir().get_parent_node(ctor_id)))
+    ///     .and_then(|ctor_id| tcx.hir().find_parent(ctor_id))
     ///     .and_then(|parent| parent.ident())
     /// ```
     pub fn ident(&self) -> Option<Ident> {
diff --git a/compiler/rustc_hir/src/hir_id.rs b/compiler/rustc_hir/src/hir_id.rs
index 5d05adfb556..3b4add0cf4d 100644
--- a/compiler/rustc_hir/src/hir_id.rs
+++ b/compiler/rustc_hir/src/hir_id.rs
@@ -119,7 +119,7 @@ impl HirId {
 
 impl fmt::Display for HirId {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(f, "{:?}", self)
+        write!(f, "{self:?}")
     }
 }
 
diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs
index d7ab942665b..9a111cb8609 100644
--- a/compiler/rustc_hir_analysis/src/astconv/mod.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs
@@ -682,7 +682,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             ty::Binder::bind_with_vars(tcx.mk_trait_ref(trait_def_id, substs), bound_vars);
 
         debug!(?poly_trait_ref, ?assoc_bindings);
-        bounds.trait_bounds.push((poly_trait_ref, span, constness));
+        bounds.push_trait_bound(tcx, poly_trait_ref, span, constness);
 
         let mut dup_bindings = FxHashMap::default();
         for binding in &assoc_bindings {
@@ -853,18 +853,19 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
     }
 
     /// Sets `implicitly_sized` to true on `Bounds` if necessary
-    pub(crate) fn add_implicitly_sized<'hir>(
+    pub(crate) fn add_implicitly_sized(
         &self,
-        bounds: &mut Bounds<'hir>,
-        ast_bounds: &'hir [hir::GenericBound<'hir>],
-        self_ty_where_predicates: Option<(LocalDefId, &'hir [hir::WherePredicate<'hir>])>,
+        bounds: &mut Bounds<'tcx>,
+        self_ty: Ty<'tcx>,
+        ast_bounds: &'tcx [hir::GenericBound<'tcx>],
+        self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>,
         span: Span,
     ) {
         let tcx = self.tcx();
 
         // Try to find an unbound in bounds.
         let mut unbound = None;
-        let mut search_bounds = |ast_bounds: &'hir [hir::GenericBound<'hir>]| {
+        let mut search_bounds = |ast_bounds: &'tcx [hir::GenericBound<'tcx>]| {
             for ab in ast_bounds {
                 if let hir::GenericBound::Trait(ptr, hir::TraitBoundModifier::Maybe) = ab {
                     if unbound.is_none() {
@@ -912,7 +913,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             // No lang item for `Sized`, so we can't add it as a bound.
             return;
         }
-        bounds.implicitly_sized = Some(span);
+        bounds.push_sized(tcx, self_ty, span);
     }
 
     /// This helper takes a *converted* parameter type (`param_ty`)
@@ -963,10 +964,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 }
                 hir::GenericBound::Outlives(lifetime) => {
                     let region = self.ast_region_to_region(lifetime, None);
-                    bounds.region_bounds.push((
-                        ty::Binder::bind_with_vars(region, bound_vars),
+                    bounds.push_region_bound(
+                        self.tcx(),
+                        ty::Binder::bind_with_vars(
+                            ty::OutlivesPredicate(param_ty, region),
+                            bound_vars,
+                        ),
                         lifetime.ident.span,
-                    ));
+                    );
                 }
             }
         }
@@ -1199,17 +1204,26 @@ 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);
-                        let reported = tcx
-                            .sess
-                            .struct_span_err(
+                        let mut err = tcx.sess.struct_span_err(
+                            binding.span,
+                            &format!("expected {expected} bound, found {got}"),
+                        );
+                        err.span_note(
+                            tcx.def_span(assoc_item_def_id),
+                            &format!("{expected} defined here"),
+                        );
+
+                        if let hir::def::DefKind::AssocConst = def_kind
+                          && let Some(t) = term.ty() && (t.is_enum() || t.references_error())
+                          && tcx.features().associated_const_equality {
+                            err.span_suggestion(
                                 binding.span,
-                                &format!("expected {expected} bound, found {got}"),
-                            )
-                            .span_note(
-                                tcx.def_span(assoc_item_def_id),
-                                &format!("{expected} defined here"),
-                            )
-                            .emit();
+                                "if equating a const, try wrapping with braces",
+                                format!("{} = {{ const }}", binding.item_name),
+                                Applicability::HasPlaceholders,
+                            );
+                        }
+                        let reported = err.emit();
                         term = match def_kind {
                             hir::def::DefKind::AssocTy => {
                                 tcx.ty_error_with_guaranteed(reported).into()
@@ -1225,13 +1239,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                         };
                     }
                 }
-                bounds.projection_bounds.push((
-                    projection_ty.map_bound(|projection_ty| ty::ProjectionPredicate {
-                        projection_ty,
-                        term: term,
-                    }),
+                bounds.push_projection_bound(
+                    tcx,
+                    projection_ty
+                        .map_bound(|projection_ty| ty::ProjectionPredicate { projection_ty, term }),
                     binding.span,
-                ));
+                );
             }
             ConvertedBindingKind::Constraint(ast_bounds) => {
                 // "Desugar" a constraint like `T: Iterator<Item: Debug>` to
@@ -1260,7 +1273,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
     fn conv_object_ty_poly_trait_ref(
         &self,
         span: Span,
-        trait_bounds: &[hir::PolyTraitRef<'_>],
+        hir_trait_bounds: &[hir::PolyTraitRef<'_>],
         lifetime: &hir::Lifetime,
         borrowed: bool,
         representation: DynKind,
@@ -1270,7 +1283,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         let mut bounds = Bounds::default();
         let mut potential_assoc_types = Vec::new();
         let dummy_self = self.tcx().types.trait_object_dummy_self;
-        for trait_bound in trait_bounds.iter().rev() {
+        for trait_bound in hir_trait_bounds.iter().rev() {
             if let GenericArgCountResult {
                 correct:
                     Err(GenericArgCountMismatch { invalid_args: cur_potential_assoc_types, .. }),
@@ -1287,10 +1300,45 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             }
         }
 
+        let mut trait_bounds = vec![];
+        let mut projection_bounds = vec![];
+        for (pred, span) in bounds.predicates() {
+            let bound_pred = pred.kind();
+            match bound_pred.skip_binder() {
+                ty::PredicateKind::Clause(clause) => match clause {
+                    ty::Clause::Trait(trait_pred) => {
+                        assert_eq!(trait_pred.polarity, ty::ImplPolarity::Positive);
+                        trait_bounds.push((
+                            bound_pred.rebind(trait_pred.trait_ref),
+                            span,
+                            trait_pred.constness,
+                        ));
+                    }
+                    ty::Clause::Projection(proj) => {
+                        projection_bounds.push((bound_pred.rebind(proj), span));
+                    }
+                    ty::Clause::TypeOutlives(_) => {
+                        // Do nothing, we deal with regions separately
+                    }
+                    ty::Clause::RegionOutlives(_) => bug!(),
+                },
+                ty::PredicateKind::WellFormed(_)
+                | ty::PredicateKind::ObjectSafe(_)
+                | ty::PredicateKind::ClosureKind(_, _, _)
+                | ty::PredicateKind::Subtype(_)
+                | ty::PredicateKind::Coerce(_)
+                | ty::PredicateKind::ConstEvaluatable(_)
+                | ty::PredicateKind::ConstEquate(_, _)
+                | ty::PredicateKind::TypeWellFormedFromEnv(_)
+                | ty::PredicateKind::Ambiguous => bug!(),
+            }
+        }
+
         // Expand trait aliases recursively and check that only one regular (non-auto) trait
         // is used and no 'maybe' bounds are used.
         let expanded_traits =
-            traits::expand_trait_aliases(tcx, bounds.trait_bounds.iter().map(|&(a, b, _)| (a, b)));
+            traits::expand_trait_aliases(tcx, trait_bounds.iter().map(|&(a, b, _)| (a, b)));
+
         let (mut auto_traits, regular_traits): (Vec<_>, Vec<_>) = expanded_traits
             .filter(|i| i.trait_ref().self_ty().skip_binder() == dummy_self)
             .partition(|i| tcx.trait_is_auto(i.trait_ref().def_id()));
@@ -1327,8 +1375,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         }
 
         if regular_traits.is_empty() && auto_traits.is_empty() {
-            let trait_alias_span = bounds
-                .trait_bounds
+            let trait_alias_span = trait_bounds
                 .iter()
                 .map(|&(trait_ref, _, _)| trait_ref.def_id())
                 .find(|&trait_ref| tcx.is_trait_alias(trait_ref))
@@ -1359,8 +1406,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         // Use a `BTreeSet` to keep output in a more consistent order.
         let mut associated_types: FxHashMap<Span, BTreeSet<DefId>> = FxHashMap::default();
 
-        let regular_traits_refs_spans = bounds
-            .trait_bounds
+        let regular_traits_refs_spans = trait_bounds
             .into_iter()
             .filter(|(trait_ref, _, _)| !tcx.trait_is_auto(trait_ref.def_id()));
 
@@ -1414,7 +1460,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                         // the discussion in #56288 for alternatives.
                         if !references_self {
                             // Include projections defined on supertraits.
-                            bounds.projection_bounds.push((pred, span));
+                            projection_bounds.push((pred, span));
                         }
                     }
                     _ => (),
@@ -1422,7 +1468,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             }
         }
 
-        for (projection_bound, _) in &bounds.projection_bounds {
+        for (projection_bound, _) in &projection_bounds {
             for def_ids in associated_types.values_mut() {
                 def_ids.remove(&projection_bound.projection_def_id());
             }
@@ -1431,7 +1477,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         self.complain_about_missing_associated_types(
             associated_types,
             potential_assoc_types,
-            trait_bounds,
+            hir_trait_bounds,
         );
 
         // De-duplicate auto traits so that, e.g., `dyn Trait + Send + Send` is the same as
@@ -1473,7 +1519,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 let substs = tcx.intern_substs(&substs[..]);
 
                 let span = i.bottom().1;
-                let empty_generic_args = trait_bounds.iter().any(|hir_bound| {
+                let empty_generic_args = hir_trait_bounds.iter().any(|hir_bound| {
                     hir_bound.trait_ref.path.res == Res::Def(DefKind::Trait, trait_ref.def_id)
                         && hir_bound.span.contains(span)
                 });
@@ -1505,7 +1551,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             })
         });
 
-        let existential_projections = bounds.projection_bounds.iter().map(|(bound, _)| {
+        let existential_projections = projection_bounds.iter().map(|(bound, _)| {
             bound.map_bound(|mut b| {
                 assert_eq!(b.projection_ty.self_ty(), dummy_self);
 
@@ -2936,7 +2982,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         let hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Fn(..), ident, .. }) =
             hir.get(fn_hir_id) else { return None };
         let hir::Node::Item(hir::Item { kind: hir::ItemKind::Impl(i), .. }) =
-                hir.get(hir.get_parent_node(fn_hir_id)) else { bug!("ImplItem should have Impl parent") };
+                hir.get_parent(fn_hir_id) else { bug!("ImplItem should have Impl parent") };
 
         let trait_ref = self.instantiate_mono_trait_ref(
             i.of_trait.as_ref()?,
diff --git a/compiler/rustc_hir_analysis/src/bounds.rs b/compiler/rustc_hir_analysis/src/bounds.rs
index 3e3544ce666..0880c8c15f2 100644
--- a/compiler/rustc_hir_analysis/src/bounds.rs
+++ b/compiler/rustc_hir_analysis/src/bounds.rs
@@ -1,6 +1,7 @@
 //! Bounds are restrictions applied to some types after they've been converted into the
 //! `ty` form from the HIR.
 
+use rustc_hir::LangItem;
 use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt};
 use rustc_span::Span;
 
@@ -15,73 +16,53 @@ use rustc_span::Span;
 ///           ^^^^^^^^^ bounding the type parameter `T`
 ///
 /// impl dyn Bar + Baz
-///          ^^^^^^^^^ bounding the forgotten dynamic type
+///          ^^^^^^^^^ bounding the type-erased dynamic type
 /// ```
 ///
 /// Our representation is a bit mixed here -- in some cases, we
 /// include the self type (e.g., `trait_bounds`) but in others we do not
 #[derive(Default, PartialEq, Eq, Clone, Debug)]
 pub struct Bounds<'tcx> {
-    /// A list of region bounds on the (implicit) self type. So if you
-    /// had `T: 'a + 'b` this might would be a list `['a, 'b]` (but
-    /// the `T` is not explicitly included).
-    pub region_bounds: Vec<(ty::Binder<'tcx, ty::Region<'tcx>>, Span)>,
-
-    /// A list of trait bounds. So if you had `T: Debug` this would be
-    /// `T: Debug`. Note that the self-type is explicit here.
-    pub trait_bounds: Vec<(ty::PolyTraitRef<'tcx>, Span, ty::BoundConstness)>,
-
-    /// A list of projection equality bounds. So if you had `T:
-    /// Iterator<Item = u32>` this would include `<T as
-    /// Iterator>::Item => u32`. Note that the self-type is explicit
-    /// here.
-    pub projection_bounds: Vec<(ty::PolyProjectionPredicate<'tcx>, Span)>,
-
-    /// `Some` if there is *no* `?Sized` predicate. The `span`
-    /// is the location in the source of the `T` declaration which can
-    /// be cited as the source of the `T: Sized` requirement.
-    pub implicitly_sized: Option<Span>,
+    pub predicates: Vec<(ty::Predicate<'tcx>, Span)>,
 }
 
 impl<'tcx> Bounds<'tcx> {
-    /// Converts a bounds list into a flat set of predicates (like
-    /// where-clauses). Because some of our bounds listings (e.g.,
-    /// regions) don't include the self-type, you must supply the
-    /// self-type here (the `param_ty` parameter).
-    pub fn predicates<'out, 's>(
-        &'s self,
+    pub fn push_region_bound(
+        &mut self,
         tcx: TyCtxt<'tcx>,
-        param_ty: Ty<'tcx>,
-        // the output must live shorter than the duration of the borrow of self and 'tcx.
-    ) -> impl Iterator<Item = (ty::Predicate<'tcx>, Span)> + 'out
-    where
-        'tcx: 'out,
-        's: 'out,
-    {
-        // If it could be sized, and is, add the `Sized` predicate.
-        let sized_predicate = self.implicitly_sized.and_then(|span| {
-            // FIXME: use tcx.at(span).mk_trait_ref(LangItem::Sized) here? This may make no-core code harder to write.
-            let sized = tcx.lang_items().sized_trait()?;
-            let trait_ref = ty::Binder::dummy(tcx.mk_trait_ref(sized, [param_ty]));
-            Some((trait_ref.without_const().to_predicate(tcx), span))
-        });
+        region: ty::PolyTypeOutlivesPredicate<'tcx>,
+        span: Span,
+    ) {
+        self.predicates.push((region.to_predicate(tcx), span));
+    }
 
-        let region_preds = self.region_bounds.iter().map(move |&(region_bound, span)| {
-            let pred = region_bound
-                .map_bound(|region_bound| ty::OutlivesPredicate(param_ty, region_bound))
-                .to_predicate(tcx);
-            (pred, span)
-        });
-        let trait_bounds =
-            self.trait_bounds.iter().map(move |&(bound_trait_ref, span, constness)| {
-                let predicate = bound_trait_ref.with_constness(constness).to_predicate(tcx);
-                (predicate, span)
-            });
-        let projection_bounds = self
-            .projection_bounds
-            .iter()
-            .map(move |&(projection, span)| (projection.to_predicate(tcx), span));
+    pub fn push_trait_bound(
+        &mut self,
+        tcx: TyCtxt<'tcx>,
+        trait_ref: ty::PolyTraitRef<'tcx>,
+        span: Span,
+        constness: ty::BoundConstness,
+    ) {
+        self.predicates.push((trait_ref.with_constness(constness).to_predicate(tcx), span));
+    }
+
+    pub fn push_projection_bound(
+        &mut self,
+        tcx: TyCtxt<'tcx>,
+        projection: ty::PolyProjectionPredicate<'tcx>,
+        span: Span,
+    ) {
+        self.predicates.push((projection.to_predicate(tcx), span));
+    }
+
+    pub fn push_sized(&mut self, tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, span: Span) {
+        let sized_def_id = tcx.require_lang_item(LangItem::Sized, Some(span));
+        let trait_ref = ty::Binder::dummy(tcx.mk_trait_ref(sized_def_id, [ty]));
+        // Preferrable to put this obligation first, since we report better errors for sized ambiguity.
+        self.predicates.insert(0, (trait_ref.without_const().to_predicate(tcx), span));
+    }
 
-        sized_predicate.into_iter().chain(region_preds).chain(trait_bounds).chain(projection_bounds)
+    pub fn predicates(&self) -> impl Iterator<Item = (ty::Predicate<'tcx>, Span)> + '_ {
+        self.predicates.iter().cloned()
     }
 }
diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
index a767338ab85..0d3391bbc1e 100644
--- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
@@ -270,8 +270,8 @@ fn compare_method_predicate_entailment<'tcx>(
     let unnormalized_impl_fty = tcx.mk_fn_ptr(ty::Binder::dummy(unnormalized_impl_sig));
 
     let norm_cause = ObligationCause::misc(impl_m_span, impl_m_hir_id);
-    let impl_fty = ocx.normalize(&norm_cause, param_env, unnormalized_impl_fty);
-    debug!("compare_impl_method: impl_fty={:?}", impl_fty);
+    let impl_sig = ocx.normalize(&norm_cause, param_env, unnormalized_impl_sig);
+    debug!("compare_impl_method: impl_fty={:?}", impl_sig);
 
     let trait_sig = tcx.bound_fn_sig(trait_m.def_id).subst(tcx, trait_to_placeholder_substs);
     let trait_sig = tcx.liberate_late_bound_regions(impl_m.def_id, trait_sig);
@@ -294,18 +294,17 @@ fn compare_method_predicate_entailment<'tcx>(
     // type would be more appropriate. In other places we have a `Vec<Span>`
     // corresponding to their `Vec<Predicate>`, but we don't have that here.
     // Fixing this would improve the output of test `issue-83765.rs`.
-    let result = ocx.sup(&cause, param_env, trait_fty, impl_fty);
+    let result = ocx.sup(&cause, param_env, trait_sig, impl_sig);
 
     if let Err(terr) = result {
-        debug!(?terr, "sub_types failed: impl ty {:?}, trait ty {:?}", impl_fty, trait_fty);
+        debug!(?impl_sig, ?trait_sig, ?terr, "sub_types failed");
 
         let emitted = report_trait_method_mismatch(
             &infcx,
             cause,
             terr,
-            (trait_m, trait_fty),
-            (impl_m, impl_fty),
-            trait_sig,
+            (trait_m, trait_sig),
+            (impl_m, impl_sig),
             impl_trait_ref,
         );
         return Err(emitted);
@@ -484,7 +483,8 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
     let impl_trait_ref = tcx.impl_trait_ref(impl_m.impl_container(tcx).unwrap()).unwrap();
     let param_env = tcx.param_env(def_id);
 
-    // First, check a few of the same thing as `compare_impl_method`, just so we don't ICE during substitutions later.
+    // First, check a few of the same things as `compare_impl_method`,
+    // just so we don't ICE during substitution later.
     compare_number_of_generics(tcx, impl_m, trait_m, tcx.hir().span_if_local(impl_m.def_id), true)?;
     compare_generic_param_kinds(tcx, impl_m, trait_m, true)?;
     check_region_bounds_on_impl_item(tcx, impl_m, trait_m, true)?;
@@ -577,14 +577,11 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
 
     debug!(?trait_sig, ?impl_sig, "equating function signatures");
 
-    let trait_fty = tcx.mk_fn_ptr(ty::Binder::dummy(trait_sig));
-    let impl_fty = tcx.mk_fn_ptr(ty::Binder::dummy(impl_sig));
-
     // Unify the whole function signature. We need to do this to fully infer
     // the lifetimes of the return type, but do this after unifying just the
     // return types, since we want to avoid duplicating errors from
     // `compare_method_predicate_entailment`.
-    match ocx.eq(&cause, param_env, trait_fty, impl_fty) {
+    match ocx.eq(&cause, param_env, trait_sig, impl_sig) {
         Ok(()) => {}
         Err(terr) => {
             // This function gets called during `compare_method_predicate_entailment` when normalizing a
@@ -595,9 +592,8 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
                 infcx,
                 cause,
                 terr,
-                (trait_m, trait_fty),
-                (impl_m, impl_fty),
-                trait_sig,
+                (trait_m, trait_sig),
+                (impl_m, impl_sig),
                 impl_trait_ref,
             );
             return Err(emitted);
@@ -771,9 +767,8 @@ fn report_trait_method_mismatch<'tcx>(
     infcx: &InferCtxt<'tcx>,
     mut cause: ObligationCause<'tcx>,
     terr: TypeError<'tcx>,
-    (trait_m, trait_fty): (&ty::AssocItem, Ty<'tcx>),
-    (impl_m, impl_fty): (&ty::AssocItem, Ty<'tcx>),
-    trait_sig: ty::FnSig<'tcx>,
+    (trait_m, trait_sig): (&ty::AssocItem, ty::FnSig<'tcx>),
+    (impl_m, impl_sig): (&ty::AssocItem, ty::FnSig<'tcx>),
     impl_trait_ref: ty::TraitRef<'tcx>,
 ) -> ErrorGuaranteed {
     let tcx = infcx.tcx;
@@ -858,10 +853,7 @@ fn report_trait_method_mismatch<'tcx>(
         &mut diag,
         &cause,
         trait_err_span.map(|sp| (sp, "type in trait".to_owned())),
-        Some(infer::ValuePairs::Terms(ExpectedFound {
-            expected: trait_fty.into(),
-            found: impl_fty.into(),
-        })),
+        Some(infer::ValuePairs::Sigs(ExpectedFound { expected: trait_sig, found: impl_sig })),
         terr,
         false,
         false,
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index 0d1aa39c5d9..969f7de51ce 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -97,21 +97,22 @@ pub(super) fn enter_wf_checking_ctxt<'tcx, F>(
     let infcx = &tcx.infer_ctxt().build();
     let ocx = ObligationCtxt::new(infcx);
 
-    let assumed_wf_types = ocx.assumed_wf_types(param_env, span, body_def_id);
-
     let mut wfcx = WfCheckingCtxt { ocx, span, body_id, param_env };
 
     if !tcx.features().trivial_bounds {
         wfcx.check_false_global_bounds()
     }
     f(&mut wfcx);
+
+    let assumed_wf_types = wfcx.ocx.assumed_wf_types(param_env, span, body_def_id);
+    let implied_bounds = infcx.implied_bounds_tys(param_env, body_id, assumed_wf_types);
+
     let errors = wfcx.select_all_or_error();
     if !errors.is_empty() {
         infcx.err_ctxt().report_fulfillment_errors(&errors, None);
         return;
     }
 
-    let implied_bounds = infcx.implied_bounds_tys(param_env, body_id, assumed_wf_types);
     let outlives_environment =
         OutlivesEnvironment::with_bounds(param_env, Some(infcx), implied_bounds);
 
@@ -1489,54 +1490,38 @@ fn check_fn_or_method<'tcx>(
     def_id: LocalDefId,
 ) {
     let tcx = wfcx.tcx();
-    let sig = tcx.liberate_late_bound_regions(def_id.to_def_id(), sig);
+    let mut sig = tcx.liberate_late_bound_regions(def_id.to_def_id(), sig);
 
     // Normalize the input and output types one at a time, using a different
     // `WellFormedLoc` for each. We cannot call `normalize_associated_types`
     // on the entire `FnSig`, since this would use the same `WellFormedLoc`
     // for each type, preventing the HIR wf check from generating
     // a nice error message.
-    let ty::FnSig { mut inputs_and_output, c_variadic, unsafety, abi } = sig;
-    inputs_and_output = tcx.mk_type_list(inputs_and_output.iter().enumerate().map(|(i, ty)| {
-        wfcx.normalize(
-            span,
-            Some(WellFormedLoc::Param {
-                function: def_id,
-                // Note that the `param_idx` of the output type is
-                // one greater than the index of the last input type.
-                param_idx: i.try_into().unwrap(),
-            }),
-            ty,
-        )
-    }));
-    // Manually call `normalize_associated_types_in` on the other types
-    // in `FnSig`. This ensures that if the types of these fields
-    // ever change to include projections, we will start normalizing
-    // them automatically.
-    let sig = ty::FnSig {
-        inputs_and_output,
-        c_variadic: wfcx.normalize(span, None, c_variadic),
-        unsafety: wfcx.normalize(span, None, unsafety),
-        abi: wfcx.normalize(span, None, abi),
-    };
+    let arg_span =
+        |idx| hir_decl.inputs.get(idx).map_or(hir_decl.output.span(), |arg: &hir::Ty<'_>| arg.span);
+
+    sig.inputs_and_output =
+        tcx.mk_type_list(sig.inputs_and_output.iter().enumerate().map(|(idx, ty)| {
+            wfcx.normalize(
+                arg_span(idx),
+                Some(WellFormedLoc::Param {
+                    function: def_id,
+                    // Note that the `param_idx` of the output type is
+                    // one greater than the index of the last input type.
+                    param_idx: idx.try_into().unwrap(),
+                }),
+                ty,
+            )
+        }));
 
-    for (i, (&input_ty, ty)) in iter::zip(sig.inputs(), hir_decl.inputs).enumerate() {
+    for (idx, ty) in sig.inputs_and_output.iter().enumerate() {
         wfcx.register_wf_obligation(
-            ty.span,
-            Some(WellFormedLoc::Param { function: def_id, param_idx: i.try_into().unwrap() }),
-            input_ty.into(),
+            arg_span(idx),
+            Some(WellFormedLoc::Param { function: def_id, param_idx: idx.try_into().unwrap() }),
+            ty.into(),
         );
     }
 
-    wfcx.register_wf_obligation(
-        hir_decl.output.span(),
-        Some(WellFormedLoc::Param {
-            function: def_id,
-            param_idx: sig.inputs().len().try_into().unwrap(),
-        }),
-        sig.output().into(),
-    );
-
     check_where_clauses(wfcx, span, def_id);
 
     check_return_position_impl_trait_in_trait_bounds(
@@ -1912,7 +1897,7 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> {
             }
             let pred = obligation.predicate;
             // Match the existing behavior.
-            if pred.is_global() && !pred.has_late_bound_regions() {
+            if pred.is_global() && !pred.has_late_bound_vars() {
                 let pred = self.normalize(span, None, pred);
                 let hir_node = tcx.hir().find(self.body_id);
 
diff --git a/compiler/rustc_hir_analysis/src/coherence/unsafety.rs b/compiler/rustc_hir_analysis/src/coherence/unsafety.rs
index a34815b45b3..70cc15b2f8c 100644
--- a/compiler/rustc_hir_analysis/src/coherence/unsafety.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/unsafety.rs
@@ -21,7 +21,7 @@ pub(super) fn check_item(tcx: TyCtxt<'_>, def_id: LocalDefId) {
             (Unsafety::Normal, None, Unsafety::Unsafe, hir::ImplPolarity::Positive) => {
                 struct_span_err!(
                     tcx.sess,
-                    item.span,
+                    tcx.def_span(def_id),
                     E0199,
                     "implementing the trait `{}` is not unsafe",
                     trait_ref.print_only_trait_path()
@@ -38,7 +38,7 @@ pub(super) fn check_item(tcx: TyCtxt<'_>, def_id: LocalDefId) {
             (Unsafety::Unsafe, _, Unsafety::Normal, hir::ImplPolarity::Positive) => {
                 struct_span_err!(
                     tcx.sess,
-                    item.span,
+                    tcx.def_span(def_id),
                     E0200,
                     "the trait `{}` requires an `unsafe impl` declaration",
                     trait_ref.print_only_trait_path()
@@ -61,7 +61,7 @@ pub(super) fn check_item(tcx: TyCtxt<'_>, def_id: LocalDefId) {
             (Unsafety::Normal, Some(attr_name), Unsafety::Normal, hir::ImplPolarity::Positive) => {
                 struct_span_err!(
                     tcx.sess,
-                    item.span,
+                    tcx.def_span(def_id),
                     E0569,
                     "requires an `unsafe impl` declaration due to `#[{}]` attribute",
                     attr_name
diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs
index 1ff7429e415..7afde550b42 100644
--- a/compiler/rustc_hir_analysis/src/collect.rs
+++ b/compiler/rustc_hir_analysis/src/collect.rs
@@ -17,6 +17,7 @@
 use crate::astconv::AstConv;
 use crate::check::intrinsic::intrinsic_operation_unsafety;
 use crate::errors;
+use hir::def::DefKind;
 use rustc_data_structures::captures::Captures;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed, StashKey};
@@ -24,8 +25,8 @@ use rustc_hir as hir;
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::intravisit::{self, Visitor};
 use rustc_hir::{GenericParamKind, Node};
-use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use rustc_infer::infer::TyCtxtInferExt;
+use rustc_infer::traits::ObligationCause;
 use rustc_middle::hir::nested_filter;
 use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::util::{Discr, IntTypeExt};
@@ -212,7 +213,7 @@ pub(crate) fn placeholder_type_error_diag<'tcx>(
             is_fn = true;
 
             // Check if parent is const or static
-            let parent_id = tcx.hir().get_parent_node(hir_ty.hir_id);
+            let parent_id = tcx.hir().parent_id(hir_ty.hir_id);
             let parent_node = tcx.hir().get(parent_id);
 
             is_const_or_static = matches!(
@@ -1108,7 +1109,7 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> {
         ImplItem(hir::ImplItem { kind: ImplItemKind::Fn(sig, _), generics, .. }) => {
             // Do not try to infer the return type for a impl method coming from a trait
             if let Item(hir::Item { kind: ItemKind::Impl(i), .. }) =
-                tcx.hir().get(tcx.hir().get_parent_node(hir_id))
+                tcx.hir().get_parent(hir_id)
                 && i.of_trait.is_some()
             {
                 <dyn AstConv<'_>>::ty_of_fn(
@@ -1195,12 +1196,11 @@ fn infer_return_ty_for_fn_sig<'tcx>(
                 ty::ReErased => tcx.lifetimes.re_static,
                 _ => r,
             });
-            let fn_sig = ty::Binder::dummy(fn_sig);
 
             let mut visitor = HirPlaceholderCollector::default();
             visitor.visit_ty(ty);
             let mut diag = bad_placeholder(tcx, visitor.0, "return type");
-            let ret_ty = fn_sig.skip_binder().output();
+            let ret_ty = fn_sig.output();
             if ret_ty.is_suggestable(tcx, false) {
                 diag.span_suggestion(
                     ty.span,
@@ -1223,26 +1223,26 @@ fn infer_return_ty_for_fn_sig<'tcx>(
                         Applicability::MachineApplicable,
                     );
                 }
+            } else if let Some(sugg) = suggest_impl_trait(tcx, ret_ty, ty.span, hir_id, def_id) {
+                diag.span_suggestion(
+                    ty.span,
+                    "replace with an appropriate return type",
+                    sugg,
+                    Applicability::MachineApplicable,
+                );
             } else if ret_ty.is_closure() {
-                // We're dealing with a closure, so we should suggest using `impl Fn` or trait bounds
-                // to prevent the user from getting a papercut while trying to use the unique closure
-                // syntax (e.g. `[closure@src/lib.rs:2:5: 2:9]`).
                 diag.help("consider using an `Fn`, `FnMut`, or `FnOnce` trait bound");
+            }
+            // Also note how `Fn` traits work just in case!
+            if ret_ty.is_closure() {
                 diag.note(
                     "for more information on `Fn` traits and closure types, see \
                      https://doc.rust-lang.org/book/ch13-01-closures.html",
                 );
-            } else if let Some(i_ty) = suggest_impl_iterator(tcx, ret_ty, ty.span, hir_id, def_id) {
-                diag.span_suggestion(
-                    ty.span,
-                    "replace with an appropriate return type",
-                    format!("impl Iterator<Item = {}>", i_ty),
-                    Applicability::MachineApplicable,
-                );
             }
             diag.emit();
 
-            fn_sig
+            ty::Binder::dummy(fn_sig)
         }
         None => <dyn AstConv<'_>>::ty_of_fn(
             icx,
@@ -1256,47 +1256,94 @@ fn infer_return_ty_for_fn_sig<'tcx>(
     }
 }
 
-fn suggest_impl_iterator<'tcx>(
+fn suggest_impl_trait<'tcx>(
     tcx: TyCtxt<'tcx>,
     ret_ty: Ty<'tcx>,
     span: Span,
     hir_id: hir::HirId,
     def_id: LocalDefId,
-) -> Option<Ty<'tcx>> {
-    let Some(iter_trait) = tcx.get_diagnostic_item(sym::Iterator) else { return None; };
-    let Some(iterator_item) = tcx.get_diagnostic_item(sym::IteratorItem) else { return None; };
-    if !tcx
-        .infer_ctxt()
-        .build()
-        .type_implements_trait(iter_trait, [ret_ty], tcx.param_env(def_id))
-        .must_apply_modulo_regions()
-    {
-        return None;
-    }
-    let infcx = tcx.infer_ctxt().build();
-    let ocx = ObligationCtxt::new_in_snapshot(&infcx);
-    // Find the type of `Iterator::Item`.
-    let origin = TypeVariableOrigin { kind: TypeVariableOriginKind::TypeInference, span };
-    let ty_var = infcx.next_ty_var(origin);
-    let projection = ty::Binder::dummy(ty::PredicateKind::Clause(ty::Clause::Projection(
-        ty::ProjectionPredicate {
-            projection_ty: tcx.mk_alias_ty(iterator_item, tcx.mk_substs([ret_ty.into()].iter())),
-            term: ty_var.into(),
-        },
-    )));
-    // Add `<ret_ty as Iterator>::Item = _` obligation.
-    ocx.register_obligation(crate::traits::Obligation::misc(
-        tcx,
-        span,
-        hir_id,
-        tcx.param_env(def_id),
-        projection,
-    ));
-    if ocx.select_where_possible().is_empty()
-        && let item_ty = infcx.resolve_vars_if_possible(ty_var)
-        && item_ty.is_suggestable(tcx, false)
-    {
-        return Some(item_ty);
+) -> Option<String> {
+    let format_as_assoc: fn(_, _, _, _, _) -> _ =
+        |tcx: TyCtxt<'tcx>,
+         _: ty::SubstsRef<'tcx>,
+         trait_def_id: DefId,
+         assoc_item_def_id: DefId,
+         item_ty: Ty<'tcx>| {
+            let trait_name = tcx.item_name(trait_def_id);
+            let assoc_name = tcx.item_name(assoc_item_def_id);
+            Some(format!("impl {trait_name}<{assoc_name} = {item_ty}>"))
+        };
+    let format_as_parenthesized: fn(_, _, _, _, _) -> _ =
+        |tcx: TyCtxt<'tcx>,
+         substs: ty::SubstsRef<'tcx>,
+         trait_def_id: DefId,
+         _: DefId,
+         item_ty: Ty<'tcx>| {
+            let trait_name = tcx.item_name(trait_def_id);
+            let args_tuple = substs.type_at(1);
+            let ty::Tuple(types) = *args_tuple.kind() else { return None; };
+            if !types.is_suggestable(tcx, false) {
+                return None;
+            }
+            let maybe_ret =
+                if item_ty.is_unit() { String::new() } else { format!(" -> {item_ty}") };
+            Some(format!(
+                "impl {trait_name}({}){maybe_ret}",
+                types.iter().map(|ty| ty.to_string()).collect::<Vec<_>>().join(", ")
+            ))
+        };
+
+    for (trait_def_id, assoc_item_def_id, formatter) in [
+        (
+            tcx.get_diagnostic_item(sym::Iterator),
+            tcx.get_diagnostic_item(sym::IteratorItem),
+            format_as_assoc,
+        ),
+        (
+            tcx.lang_items().future_trait(),
+            tcx.get_diagnostic_item(sym::FutureOutput),
+            format_as_assoc,
+        ),
+        (tcx.lang_items().fn_trait(), tcx.lang_items().fn_once_output(), format_as_parenthesized),
+        (
+            tcx.lang_items().fn_mut_trait(),
+            tcx.lang_items().fn_once_output(),
+            format_as_parenthesized,
+        ),
+        (
+            tcx.lang_items().fn_once_trait(),
+            tcx.lang_items().fn_once_output(),
+            format_as_parenthesized,
+        ),
+    ] {
+        let Some(trait_def_id) = trait_def_id else { continue; };
+        let Some(assoc_item_def_id) = assoc_item_def_id else { continue; };
+        if tcx.def_kind(assoc_item_def_id) != DefKind::AssocTy {
+            continue;
+        }
+        let param_env = tcx.param_env(def_id);
+        let infcx = tcx.infer_ctxt().build();
+        let substs = ty::InternalSubsts::for_item(tcx, trait_def_id, |param, _| {
+            if param.index == 0 { ret_ty.into() } else { infcx.var_for_def(span, param) }
+        });
+        if !infcx.type_implements_trait(trait_def_id, substs, param_env).must_apply_modulo_regions()
+        {
+            continue;
+        }
+        let ocx = ObligationCtxt::new_in_snapshot(&infcx);
+        let item_ty = ocx.normalize(
+            &ObligationCause::misc(span, hir_id),
+            param_env,
+            tcx.mk_projection(assoc_item_def_id, substs),
+        );
+        // FIXME(compiler-errors): We may benefit from resolving regions here.
+        if ocx.select_where_possible().is_empty()
+            && let item_ty = infcx.resolve_vars_if_possible(item_ty)
+            && item_ty.is_suggestable(tcx, false)
+            && let Some(sugg) = formatter(tcx, infcx.resolve_vars_if_possible(substs), trait_def_id, assoc_item_def_id, item_ty)
+        {
+            return Some(sugg);
+        }
     }
     None
 }
diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs
index cb4c35c0ce1..96221c3e3d8 100644
--- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs
@@ -103,7 +103,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
                 // `min_const_generics`.
                 Some(parent_def_id.to_def_id())
             } else {
-                let parent_node = tcx.hir().get(tcx.hir().get_parent_node(hir_id));
+                let parent_node = tcx.hir().get_parent(hir_id);
                 match parent_node {
                     // HACK(eddyb) this provides the correct generics for repeat
                     // expressions' count (i.e. `N` in `[x; N]`), and explicit
@@ -320,7 +320,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
 
     // provide junk type parameter defs for const blocks.
     if let Node::AnonConst(_) = node {
-        let parent_node = tcx.hir().get(tcx.hir().get_parent_node(hir_id));
+        let parent_node = tcx.hir().get_parent(hir_id);
         if let Node::Expr(&Expr { kind: ExprKind::ConstBlock(_), .. }) = parent_node {
             params.push(ty::GenericParamDef {
                 index: next_index(),
diff --git a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
index 0542e2c8f50..093e9560ccd 100644
--- a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
+++ b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
@@ -28,7 +28,7 @@ fn associated_type_bounds<'tcx>(
     let icx = ItemCtxt::new(tcx, assoc_item_def_id);
     let mut bounds = <dyn AstConv<'_>>::compute_bounds(&icx, item_ty, ast_bounds);
     // Associated types are implicitly sized unless a `?Sized` bound is found
-    <dyn AstConv<'_>>::add_implicitly_sized(&icx, &mut bounds, ast_bounds, None, span);
+    <dyn AstConv<'_>>::add_implicitly_sized(&icx, &mut bounds, item_ty, ast_bounds, None, span);
 
     let trait_def_id = tcx.parent(assoc_item_def_id);
     let trait_predicates = tcx.trait_explicit_predicates_and_bounds(trait_def_id.expect_local());
@@ -44,9 +44,7 @@ fn associated_type_bounds<'tcx>(
         }
     });
 
-    let all_bounds = tcx
-        .arena
-        .alloc_from_iter(bounds.predicates(tcx, item_ty).into_iter().chain(bounds_from_parent));
+    let all_bounds = tcx.arena.alloc_from_iter(bounds.predicates().chain(bounds_from_parent));
     debug!("associated_type_bounds({}) = {:?}", tcx.def_path_str(assoc_item_def_id), all_bounds);
     all_bounds
 }
@@ -74,10 +72,10 @@ fn opaque_type_bounds<'tcx>(
         let icx = ItemCtxt::new(tcx, opaque_def_id);
         let mut bounds = <dyn AstConv<'_>>::compute_bounds(&icx, item_ty, ast_bounds);
         // Opaque types are implicitly sized unless a `?Sized` bound is found
-        <dyn AstConv<'_>>::add_implicitly_sized(&icx, &mut bounds, ast_bounds, None, span);
+        <dyn AstConv<'_>>::add_implicitly_sized(&icx, &mut bounds, item_ty, ast_bounds, None, span);
         debug!(?bounds);
 
-        tcx.arena.alloc_from_iter(bounds.predicates(tcx, item_ty))
+        tcx.arena.alloc_from_iter(bounds.predicates())
     })
 }
 
diff --git a/compiler/rustc_hir_analysis/src/collect/lifetimes.rs b/compiler/rustc_hir_analysis/src/collect/lifetimes.rs
index fb519d6731d..35f10dc8737 100644
--- a/compiler/rustc_hir_analysis/src/collect/lifetimes.rs
+++ b/compiler/rustc_hir_analysis/src/collect/lifetimes.rs
@@ -682,7 +682,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
                     };
                     let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id);
                     // Ensure that the parent of the def is an item, not HRTB
-                    let parent_id = self.tcx.hir().get_parent_node(hir_id);
+                    let parent_id = self.tcx.hir().parent_id(hir_id);
                     if !parent_id.is_owner() {
                         struct_span_err!(
                             self.tcx.sess,
@@ -1195,8 +1195,10 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
                     // Fresh lifetimes in APIT used to be allowed in async fns and forbidden in
                     // regular fns.
                     if let Some(hir::PredicateOrigin::ImplTrait) = where_bound_origin
-                        && let hir::LifetimeName::Param(_) = lifetime_ref.res
-                        && lifetime_ref.is_anonymous()
+                        && let hir::LifetimeName::Param(param_id) = lifetime_ref.res
+                        && let Some(generics) = self.tcx.hir().get_generics(self.tcx.local_parent(param_id))
+                        && let Some(param) = generics.params.iter().find(|p| p.def_id == param_id)
+                        && param.is_elided_lifetime()
                         && let hir::IsAsync::NotAsync = self.tcx.asyncness(lifetime_ref.hir_id.owner.def_id)
                         && !self.tcx.features().anonymous_lifetime_in_impl_trait
                     {
diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
index 0943350e2d4..18fc43ce15c 100644
--- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
@@ -165,12 +165,13 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
                 <dyn AstConv<'_>>::add_implicitly_sized(
                     &icx,
                     &mut bounds,
+                    param_ty,
                     &[],
                     Some((param.def_id, ast_generics.predicates)),
                     param.span,
                 );
                 trace!(?bounds);
-                predicates.extend(bounds.predicates(tcx, param_ty));
+                predicates.extend(bounds.predicates());
                 trace!(?predicates);
             }
             GenericParamKind::Const { .. } => {
@@ -217,7 +218,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
                     &mut bounds,
                     bound_vars,
                 );
-                predicates.extend(bounds.predicates(tcx, ty));
+                predicates.extend(bounds.predicates());
             }
 
             hir::WherePredicate::RegionPredicate(region_pred) => {
@@ -270,7 +271,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
     // We create bi-directional Outlives predicates between the original
     // and the duplicated parameter, to ensure that they do not get out of sync.
     if let Node::Item(&Item { kind: ItemKind::OpaqueTy(..), .. }) = node {
-        let opaque_ty_id = tcx.hir().get_parent_node(hir_id);
+        let opaque_ty_id = tcx.hir().parent_id(hir_id);
         let opaque_ty_node = tcx.hir().get(opaque_ty_id);
         let Node::Ty(&Ty { kind: TyKind::OpaqueDef(_, lifetimes, _), .. }) = opaque_ty_node else {
             bug!("unexpected {opaque_ty_node:?}")
@@ -536,7 +537,7 @@ pub(super) fn super_predicates_that_define_assoc_type(
             <dyn AstConv<'_>>::compute_bounds(&icx, self_param_ty, bounds)
         };
 
-        let superbounds1 = superbounds1.predicates(tcx, self_param_ty);
+        let superbounds1 = superbounds1.predicates();
 
         // Convert any explicit superbounds in the where-clause,
         // e.g., `trait Foo where Self: Bar`.
@@ -745,5 +746,5 @@ fn predicates_from_bound<'tcx>(
 ) -> Vec<(ty::Predicate<'tcx>, Span)> {
     let mut bounds = Bounds::default();
     astconv.add_bounds(param_ty, [bound].into_iter(), &mut bounds, bound_vars);
-    bounds.predicates(astconv.tcx(), param_ty).collect()
+    bounds.predicates().collect()
 }
diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs
index 4bd55a54831..1f9a9f80302 100644
--- a/compiler/rustc_hir_analysis/src/collect/type_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs
@@ -28,7 +28,7 @@ pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<
         _ => return None,
     };
 
-    let parent_node_id = tcx.hir().get_parent_node(hir_id);
+    let parent_node_id = tcx.hir().parent_id(hir_id);
     let parent_node = tcx.hir().get(parent_node_id);
 
     let (generics, arg_idx) = match parent_node {
@@ -402,7 +402,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
         }
 
         Node::AnonConst(_) => {
-            let parent_node = tcx.hir().get(tcx.hir().get_parent_node(hir_id));
+            let parent_node = tcx.hir().get_parent(hir_id);
             match parent_node {
                 Node::Ty(&Ty { kind: TyKind::Array(_, ref constant), .. })
                 | Node::Expr(&Expr { kind: ExprKind::Repeat(_, ref constant), .. })
@@ -445,7 +445,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
                         ..
                     },
                 ) if let Node::TraitRef(trait_ref) =
-                    tcx.hir().get(tcx.hir().get_parent_node(binding_id))
+                    tcx.hir().get_parent(binding_id)
                     && e.hir_id == hir_id =>
                 {
                     let Some(trait_def_id) = trait_ref.trait_def_id() else {
@@ -472,7 +472,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
                 Node::TypeBinding(
                     binding @ &TypeBinding { hir_id: binding_id, gen_args, ref kind, .. },
                 ) if let Node::TraitRef(trait_ref) =
-                    tcx.hir().get(tcx.hir().get_parent_node(binding_id))
+                    tcx.hir().get_parent(binding_id)
                     && let Some((idx, _)) =
                         gen_args.args.iter().enumerate().find(|(_, arg)| {
                             if let GenericArg::Const(ct) = arg {
diff --git a/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs b/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs
index 4451db19f5c..574b1e8b485 100644
--- a/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs
+++ b/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs
@@ -597,11 +597,15 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
                 let span = self.path_segment.ident.span;
 
                 // insert a suggestion of the form "Y<'a, 'b>"
-                let ident = self.path_segment.ident.name.to_ident_string();
-                let sugg = format!("{}<{}>", ident, suggested_args);
+                let sugg = format!("<{}>", suggested_args);
                 debug!("sugg: {:?}", sugg);
 
-                err.span_suggestion_verbose(span, &msg, sugg, Applicability::HasPlaceholders);
+                err.span_suggestion_verbose(
+                    span.shrink_to_hi(),
+                    &msg,
+                    sugg,
+                    Applicability::HasPlaceholders,
+                );
             }
 
             AngleBrackets::Available => {
@@ -643,11 +647,15 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
                 let span = self.path_segment.ident.span;
 
                 // insert a suggestion of the form "Y<T, U>"
-                let ident = self.path_segment.ident.name.to_ident_string();
-                let sugg = format!("{}<{}>", ident, suggested_args);
+                let sugg = format!("<{}>", suggested_args);
                 debug!("sugg: {:?}", sugg);
 
-                err.span_suggestion_verbose(span, &msg, sugg, Applicability::HasPlaceholders);
+                err.span_suggestion_verbose(
+                    span.shrink_to_hi(),
+                    &msg,
+                    sugg,
+                    Applicability::HasPlaceholders,
+                );
             }
             AngleBrackets::Available => {
                 let gen_args_span = self.gen_args.span().unwrap();
@@ -716,7 +724,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
             num = num_trait_generics_except_self,
         );
 
-        if let Some(parent_node) = self.tcx.hir().find_parent_node(self.path_segment.hir_id)
+        if let Some(parent_node) = self.tcx.hir().opt_parent_id(self.path_segment.hir_id)
         && let Some(parent_node) = self.tcx.hir().find(parent_node)
         && let hir::Node::Expr(expr) = parent_node {
             match expr.kind {
diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs
index 24a67cc14c4..3e3af8395a1 100644
--- a/compiler/rustc_hir_pretty/src/lib.rs
+++ b/compiler/rustc_hir_pretty/src/lib.rs
@@ -1268,7 +1268,7 @@ impl<'a> State<'a> {
                 hir::InlineAsmOperand::In { reg, ref expr } => {
                     s.word("in");
                     s.popen();
-                    s.word(format!("{}", reg));
+                    s.word(format!("{reg}"));
                     s.pclose();
                     s.space();
                     s.print_expr(expr);
@@ -1276,7 +1276,7 @@ impl<'a> State<'a> {
                 hir::InlineAsmOperand::Out { reg, late, ref expr } => {
                     s.word(if late { "lateout" } else { "out" });
                     s.popen();
-                    s.word(format!("{}", reg));
+                    s.word(format!("{reg}"));
                     s.pclose();
                     s.space();
                     match expr {
@@ -1287,7 +1287,7 @@ impl<'a> State<'a> {
                 hir::InlineAsmOperand::InOut { reg, late, ref expr } => {
                     s.word(if late { "inlateout" } else { "inout" });
                     s.popen();
-                    s.word(format!("{}", reg));
+                    s.word(format!("{reg}"));
                     s.pclose();
                     s.space();
                     s.print_expr(expr);
@@ -1295,7 +1295,7 @@ impl<'a> State<'a> {
                 hir::InlineAsmOperand::SplitInOut { reg, late, ref in_expr, ref out_expr } => {
                     s.word(if late { "inlateout" } else { "inout" });
                     s.popen();
-                    s.word(format!("{}", reg));
+                    s.word(format!("{reg}"));
                     s.pclose();
                     s.space();
                     s.print_expr(in_expr);
diff --git a/compiler/rustc_hir_typeck/src/_match.rs b/compiler/rustc_hir_typeck/src/_match.rs
index ab12cae4e2b..b6f19d3cc68 100644
--- a/compiler/rustc_hir_typeck/src/_match.rs
+++ b/compiler/rustc_hir_typeck/src/_match.rs
@@ -224,14 +224,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         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",
+            "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",
+            "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(
@@ -289,15 +287,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
     fn maybe_get_coercion_reason(&self, hir_id: hir::HirId, sp: Span) -> Option<(Span, String)> {
         let node = {
-            let rslt = self.tcx.hir().get_parent_node(self.tcx.hir().get_parent_node(hir_id));
+            let rslt = self.tcx.hir().parent_id(self.tcx.hir().parent_id(hir_id));
             self.tcx.hir().get(rslt)
         };
         if let hir::Node::Block(block) = node {
             // check that the body's parent is an fn
-            let parent = self
-                .tcx
-                .hir()
-                .get(self.tcx.hir().get_parent_node(self.tcx.hir().get_parent_node(block.hir_id)));
+            let parent = self.tcx.hir().get_parent(self.tcx.hir().parent_id(block.hir_id));
             if let (Some(expr), hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(..), .. })) =
                 (&block.expr, parent)
             {
@@ -526,7 +521,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         None
                     }
                 })?;
-                let opaque_ty = self.tcx.mk_opaque(rpit_def_id, substs);
 
                 if !self.can_coerce(first_ty, expected) || !self.can_coerce(second_ty, expected) {
                     return None;
@@ -540,13 +534,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     {
                         let pred = pred.kind().rebind(match pred.kind().skip_binder() {
                             ty::PredicateKind::Clause(ty::Clause::Trait(trait_pred)) => {
-                                assert_eq!(trait_pred.trait_ref.self_ty(), opaque_ty);
+                                // FIXME(rpitit): This will need to be fixed when we move to associated types
+                                assert!(matches!(
+                                    *trait_pred.trait_ref.self_ty().kind(),
+                                    ty::Alias(_, ty::AliasTy { def_id, substs, .. })
+                                    if def_id == rpit_def_id && substs == substs
+                                ));
                                 ty::PredicateKind::Clause(ty::Clause::Trait(
                                     trait_pred.with_self_ty(self.tcx, ty),
                                 ))
                             }
                             ty::PredicateKind::Clause(ty::Clause::Projection(mut proj_pred)) => {
-                                assert_eq!(proj_pred.projection_ty.self_ty(), opaque_ty);
+                                assert!(matches!(
+                                    *proj_pred.projection_ty.self_ty().kind(),
+                                    ty::Alias(_, ty::AliasTy { def_id, substs, .. })
+                                    if def_id == rpit_def_id && substs == substs
+                                ));
                                 proj_pred = proj_pred.with_self_ty(self.tcx, ty);
                                 ty::PredicateKind::Clause(ty::Clause::Projection(proj_pred))
                             }
diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs
index 829913d278d..2cb976f718c 100644
--- a/compiler/rustc_hir_typeck/src/callee.rs
+++ b/compiler/rustc_hir_typeck/src/callee.rs
@@ -288,7 +288,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         callee_span: Span,
     ) {
         let hir = self.tcx.hir();
-        let parent_hir_id = hir.get_parent_node(hir_id);
+        let parent_hir_id = hir.parent_id(hir_id);
         let parent_node = hir.get(parent_hir_id);
         if let (
             hir::Node::Expr(hir::Expr {
@@ -303,7 +303,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             {
                 // Actually need to unwrap a few more layers of HIR to get to
                 // the _real_ closure...
-                let async_closure = hir.get_parent_node(hir.get_parent_node(parent_hir_id));
+                let async_closure = hir.parent_id(hir.parent_id(parent_hir_id));
                 if let hir::Node::Expr(hir::Expr {
                     kind: hir::ExprKind::Closure(&hir::Closure { fn_decl_span, .. }),
                     ..
@@ -336,7 +336,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         call_expr: &'tcx hir::Expr<'tcx>,
         callee_expr: &'tcx hir::Expr<'tcx>,
     ) -> bool {
-        let hir_id = self.tcx.hir().get_parent_node(call_expr.hir_id);
+        let hir_id = self.tcx.hir().parent_id(call_expr.hir_id);
         let parent_node = self.tcx.hir().get(hir_id);
         if let (
             hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Array(_), .. }),
diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs
index 5bd02dff73b..3453da500b9 100644
--- a/compiler/rustc_hir_typeck/src/closure.rs
+++ b/compiler/rustc_hir_typeck/src/closure.rs
@@ -13,7 +13,7 @@ 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};
+use rustc_middle::ty::{self, Ty, TypeSuperVisitable, TypeVisitor};
 use rustc_span::source_map::Span;
 use rustc_target::spec::abi::Abi;
 use rustc_trait_selection::traits;
@@ -21,6 +21,7 @@ use rustc_trait_selection::traits::error_reporting::ArgKind;
 use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _;
 use std::cmp;
 use std::iter;
+use std::ops::ControlFlow;
 
 /// What signature do we *expect* the closure to have from context?
 #[derive(Debug, Clone, TypeFoldable, TypeVisitable)]
@@ -54,7 +55,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         // closure sooner rather than later, so first examine the expected
         // type, and see if can glean a closure kind from there.
         let (expected_sig, expected_kind) = match expected.to_option(self) {
-            Some(ty) => self.deduce_expectations_from_expected_type(ty),
+            Some(ty) => self.deduce_closure_signature(ty),
             None => (None, None),
         };
         let body = self.tcx.hir().body(closure.body);
@@ -162,13 +163,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     /// Given the expected type, figures out what it can about this closure we
     /// are about to type check:
     #[instrument(skip(self), level = "debug")]
-    fn deduce_expectations_from_expected_type(
+    fn deduce_closure_signature(
         &self,
         expected_ty: Ty<'tcx>,
     ) -> (Option<ExpectedSig<'tcx>>, Option<ty::ClosureKind>) {
         match *expected_ty.kind() {
             ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => self
-                .deduce_signature_from_predicates(
+                .deduce_closure_signature_from_predicates(
+                    expected_ty,
                     self.tcx.bound_explicit_item_bounds(def_id).subst_iter_copied(self.tcx, substs),
                 ),
             ty::Dynamic(ref object_type, ..) => {
@@ -181,7 +183,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     .and_then(|did| self.tcx.fn_trait_kind_from_def_id(did));
                 (sig, kind)
             }
-            ty::Infer(ty::TyVar(vid)) => self.deduce_signature_from_predicates(
+            ty::Infer(ty::TyVar(vid)) => self.deduce_closure_signature_from_predicates(
+                self.tcx.mk_ty_var(self.root_var(vid)),
                 self.obligations_for_self_ty(vid).map(|obl| (obl.predicate, obl.cause.span)),
             ),
             ty::FnPtr(sig) => {
@@ -192,8 +195,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         }
     }
 
-    fn deduce_signature_from_predicates(
+    fn deduce_closure_signature_from_predicates(
         &self,
+        expected_ty: Ty<'tcx>,
         predicates: impl DoubleEndedIterator<Item = (ty::Predicate<'tcx>, Span)>,
     ) -> (Option<ExpectedSig<'tcx>>, Option<ty::ClosureKind>) {
         let mut expected_sig = None;
@@ -214,13 +218,33 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             if expected_sig.is_none()
                 && let ty::PredicateKind::Clause(ty::Clause::Projection(proj_predicate)) = bound_predicate.skip_binder()
             {
-                expected_sig = self.normalize(
+                let inferred_sig = self.normalize(
                     obligation.cause.span,
                     self.deduce_sig_from_projection(
                     Some(obligation.cause.span),
                         bound_predicate.rebind(proj_predicate),
                     ),
                 );
+                // Make sure that we didn't infer a signature that mentions itself.
+                // This can happen when we elaborate certain supertrait bounds that
+                // mention projections containing the `Self` type. See #105401.
+                struct MentionsTy<'tcx> {
+                    expected_ty: Ty<'tcx>,
+                }
+                impl<'tcx> TypeVisitor<'tcx> for MentionsTy<'tcx> {
+                    type BreakTy = ();
+
+                    fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
+                        if t == self.expected_ty {
+                            ControlFlow::BREAK
+                        } else {
+                            t.super_visit_with(self)
+                        }
+                    }
+                }
+                if inferred_sig.visit_with(&mut MentionsTy { expected_ty }).is_continue() {
+                    expected_sig = inferred_sig;
+                }
             }
 
             // Even if we can't infer the full signature, we may be able to
diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs
index 3fb14e31ea1..9e91a3f9076 100644
--- a/compiler/rustc_hir_typeck/src/coercion.rs
+++ b/compiler/rustc_hir_typeck/src/coercion.rs
@@ -1547,7 +1547,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
                         err.span_label(cause.span, "return type is not `()`");
                     }
                     ObligationCauseCode::BlockTailExpression(blk_id) => {
-                        let parent_id = fcx.tcx.hir().get_parent_node(blk_id);
+                        let parent_id = fcx.tcx.hir().parent_id(blk_id);
                         err = self.report_return_mismatched_types(
                             cause,
                             expected,
@@ -1578,7 +1578,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
                             None,
                         );
                         if !fcx.tcx.features().unsized_locals {
-                            let id = fcx.tcx.hir().get_parent_node(id);
+                            let id = fcx.tcx.hir().parent_id(id);
                             unsized_return = self.is_return_ty_unsized(fcx, id);
                         }
                     }
@@ -1668,7 +1668,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
         let mut pointing_at_return_type = false;
         let mut fn_output = None;
 
-        let parent_id = fcx.tcx.hir().get_parent_node(id);
+        let parent_id = fcx.tcx.hir().parent_id(id);
         let parent = fcx.tcx.hir().get(parent_id);
         if let Some(expr) = expression
             && let hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Closure(&hir::Closure { body, .. }), .. }) = parent
diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs
index 1360383a75a..f68a428d09a 100644
--- a/compiler/rustc_hir_typeck/src/demand.rs
+++ b/compiler/rustc_hir_typeck/src/demand.rs
@@ -1,9 +1,11 @@
 use crate::FnCtxt;
 use rustc_ast::util::parser::PREC_POSTFIX;
+use rustc_data_structures::fx::FxHashMap;
 use rustc_errors::MultiSpan;
 use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed};
 use rustc_hir as hir;
 use rustc_hir::def::CtorKind;
+use rustc_hir::intravisit::Visitor;
 use rustc_hir::lang_items::LangItem;
 use rustc_hir::{is_range_literal, Node};
 use rustc_infer::infer::InferOk;
@@ -11,11 +13,14 @@ use rustc_middle::lint::in_external_macro;
 use rustc_middle::middle::stability::EvalResult;
 use rustc_middle::ty::adjustment::AllowTwoPhase;
 use rustc_middle::ty::error::{ExpectedFound, TypeError};
-use rustc_middle::ty::print::with_no_trimmed_paths;
-use rustc_middle::ty::{self, Article, AssocItem, Ty, TypeAndMut};
+use rustc_middle::ty::fold::{BottomUpFolder, TypeFolder};
+use rustc_middle::ty::print::{with_forced_trimmed_paths, with_no_trimmed_paths};
+use rustc_middle::ty::relate::TypeRelation;
+use rustc_middle::ty::{self, Article, AssocItem, Ty, TypeAndMut, TypeVisitable};
 use rustc_span::symbol::{sym, Symbol};
 use rustc_span::{BytePos, Span};
 use rustc_trait_selection::infer::InferCtxtExt as _;
+use rustc_trait_selection::traits::error_reporting::method_chain::CollectAllMismatches;
 use rustc_trait_selection::traits::ObligationCause;
 
 use super::method::probe;
@@ -40,7 +45,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         self.annotate_alternative_method_deref(err, expr, error);
 
         // Use `||` to give these suggestions a precedence
-        let _ = self.suggest_missing_parentheses(err, expr)
+        let suggested = self.suggest_missing_parentheses(err, expr)
             || self.suggest_remove_last_method_call(err, expr, expected)
             || self.suggest_associated_const(err, expr, expected)
             || self.suggest_deref_ref_or_into(err, expr, expected, expr_ty, expected_ty_expr)
@@ -52,8 +57,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             || self.suggest_boxing_when_appropriate(err, expr, expected, expr_ty)
             || self.suggest_block_to_brackets_peeling_refs(err, expr, expr_ty, expected)
             || self.suggest_copied_or_cloned(err, expr, expr_ty, expected)
+            || self.suggest_clone_for_ref(err, expr, expr_ty, expected)
             || self.suggest_into(err, expr, expr_ty, expected)
             || self.suggest_floating_point_literal(err, expr, expected);
+        if !suggested {
+            self.point_at_expr_source_of_inferred_type(err, expr, expr_ty, expected);
+        }
     }
 
     pub fn emit_coerce_suggestions(
@@ -75,6 +84,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         self.note_need_for_fn_pointer(err, expected, expr_ty);
         self.note_internal_mutation_in_method(err, expr, expected, expr_ty);
         self.check_for_range_as_method_call(err, expr, expr_ty, expected);
+        self.check_for_binding_assigned_block_without_tail_expression(err, expr, expr_ty, expected);
     }
 
     /// Requires that the two types unify, and prints an error message if
@@ -205,13 +215,222 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         (expected, Some(err))
     }
 
+    pub fn point_at_expr_source_of_inferred_type(
+        &self,
+        err: &mut Diagnostic,
+        expr: &hir::Expr<'_>,
+        found: Ty<'tcx>,
+        expected: Ty<'tcx>,
+    ) -> bool {
+        let map = self.tcx.hir();
+
+        let hir::ExprKind::Path(hir::QPath::Resolved(None, p)) = expr.kind else { return false; };
+        let [hir::PathSegment { ident, args: None, .. }] = p.segments else { return false; };
+        let hir::def::Res::Local(hir_id) = p.res else { return false; };
+        let Some(hir::Node::Pat(pat)) = map.find(hir_id) else { return false; };
+        let Some(hir::Node::Local(hir::Local {
+            ty: None,
+            init: Some(init),
+            ..
+        })) = map.find_parent(pat.hir_id) else { return false; };
+        let Some(ty) = self.node_ty_opt(init.hir_id) else { return false; };
+        if ty.is_closure() || init.span.overlaps(expr.span) || pat.span.from_expansion() {
+            return false;
+        }
+
+        // Locate all the usages of the relevant binding.
+        struct FindExprs<'hir> {
+            hir_id: hir::HirId,
+            uses: Vec<&'hir hir::Expr<'hir>>,
+        }
+        impl<'v> Visitor<'v> for FindExprs<'v> {
+            fn visit_expr(&mut self, ex: &'v hir::Expr<'v>) {
+                if let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = ex.kind
+                    && let hir::def::Res::Local(hir_id) = path.res
+                    && hir_id == self.hir_id
+                {
+                    self.uses.push(ex);
+                }
+                hir::intravisit::walk_expr(self, ex);
+            }
+        }
+
+        let mut expr_finder = FindExprs { hir_id, uses: vec![] };
+        let id = map.get_parent_item(hir_id);
+        let hir_id: hir::HirId = id.into();
+
+        let Some(node) = map.find(hir_id) else { return false; };
+        let Some(body_id) = node.body_id() else { return false; };
+        let body = map.body(body_id);
+        expr_finder.visit_expr(body.value);
+        // Hack to make equality checks on types with inference variables and regions useful.
+        let mut eraser = BottomUpFolder {
+            tcx: self.tcx,
+            lt_op: |_| self.tcx.lifetimes.re_erased,
+            ct_op: |c| c,
+            ty_op: |t| match *t.kind() {
+                ty::Infer(ty::TyVar(vid)) => self.tcx.mk_ty_infer(ty::TyVar(self.root_var(vid))),
+                ty::Infer(ty::IntVar(_)) => {
+                    self.tcx.mk_ty_infer(ty::IntVar(ty::IntVid { index: 0 }))
+                }
+                ty::Infer(ty::FloatVar(_)) => {
+                    self.tcx.mk_ty_infer(ty::FloatVar(ty::FloatVid { index: 0 }))
+                }
+                _ => t,
+            },
+        };
+        let mut prev = eraser.fold_ty(ty);
+        let mut prev_span = None;
+
+        for binding in expr_finder.uses {
+            // In every expression where the binding is referenced, we will look at that
+            // expression's type and see if it is where the incorrect found type was fully
+            // "materialized" and point at it. We will also try to provide a suggestion there.
+            if let Some(hir::Node::Expr(expr)
+            | hir::Node::Stmt(hir::Stmt {
+                kind: hir::StmtKind::Expr(expr) | hir::StmtKind::Semi(expr),
+                ..
+            })) = &map.find_parent(binding.hir_id)
+                && let hir::ExprKind::MethodCall(segment, rcvr, args, _span) = expr.kind
+                && rcvr.hir_id == binding.hir_id
+                && let Some(def_id) = self.typeck_results.borrow().type_dependent_def_id(expr.hir_id)
+            {
+                // We special case methods, because they can influence inference through the
+                // call's arguments and we can provide a more explicit span.
+                let sig = self.tcx.fn_sig(def_id);
+                let def_self_ty = sig.input(0).skip_binder();
+                let rcvr_ty = self.node_ty(rcvr.hir_id);
+                // Get the evaluated type *after* calling the method call, so that the influence
+                // of the arguments can be reflected in the receiver type. The receiver
+                // expression has the type *before* theis analysis is done.
+                let ty = match self.lookup_probe(
+                    segment.ident,
+                    rcvr_ty,
+                    expr,
+                    probe::ProbeScope::TraitsInScope,
+                ) {
+                    Ok(pick) => pick.self_ty,
+                    Err(_) => rcvr_ty,
+                };
+                // Remove one layer of references to account for `&mut self` and
+                // `&self`, so that we can compare it against the binding.
+                let (ty, def_self_ty) = match (ty.kind(), def_self_ty.kind()) {
+                    (ty::Ref(_, ty, a), ty::Ref(_, self_ty, b)) if a == b => (*ty, *self_ty),
+                    _ => (ty, def_self_ty),
+                };
+                let mut param_args = FxHashMap::default();
+                let mut param_expected = FxHashMap::default();
+                let mut param_found = FxHashMap::default();
+                if self.can_eq(self.param_env, ty, found).is_ok() {
+                    // We only point at the first place where the found type was inferred.
+                    for (i, param_ty) in sig.inputs().skip_binder().iter().skip(1).enumerate() {
+                        if def_self_ty.contains(*param_ty) && let ty::Param(_) = param_ty.kind() {
+                            // We found an argument that references a type parameter in `Self`,
+                            // so we assume that this is the argument that caused the found
+                            // type, which we know already because of `can_eq` above was first
+                            // inferred in this method call.
+                            let arg = &args[i];
+                            let arg_ty = self.node_ty(arg.hir_id);
+                            err.span_label(
+                                arg.span,
+                                &format!(
+                                    "this is of type `{arg_ty}`, which causes `{ident}` to be \
+                                     inferred as `{ty}`",
+                                ),
+                            );
+                            param_args.insert(param_ty, (arg, arg_ty));
+                        }
+                    }
+                }
+
+                // Here we find, for a type param `T`, the type that `T` is in the current
+                // method call *and* in the original expected type. That way, we can see if we
+                // can give any structured suggestion for the function argument.
+                let mut c = CollectAllMismatches {
+                    infcx: &self.infcx,
+                    param_env: self.param_env,
+                    errors: vec![],
+                };
+                let _ = c.relate(def_self_ty, ty);
+                for error in c.errors {
+                    if let TypeError::Sorts(error) = error {
+                        param_found.insert(error.expected, error.found);
+                    }
+                }
+                c.errors = vec![];
+                let _ = c.relate(def_self_ty, expected);
+                for error in c.errors {
+                    if let TypeError::Sorts(error) = error {
+                        param_expected.insert(error.expected, error.found);
+                    }
+                }
+                for (param, (arg, arg_ty)) in param_args.iter() {
+                    let Some(expected) = param_expected.get(param) else { continue; };
+                    let Some(found) = param_found.get(param) else { continue; };
+                    if self.can_eq(self.param_env, *arg_ty, *found).is_err() { continue; }
+                    self.emit_coerce_suggestions(err, arg, *found, *expected, None, None);
+                }
+
+                let ty = eraser.fold_ty(ty);
+                if ty.references_error() {
+                    break;
+                }
+                if ty != prev
+                    && param_args.is_empty()
+                    && self.can_eq(self.param_env, ty, found).is_ok()
+                {
+                    // We only point at the first place where the found type was inferred.
+                    err.span_label(
+                        segment.ident.span,
+                        with_forced_trimmed_paths!(format!(
+                            "here the type of `{ident}` is inferred to be `{ty}`",
+                        )),
+                    );
+                    break;
+                } else if !param_args.is_empty() {
+                    break;
+                }
+                prev = ty;
+            } else {
+                let ty = eraser.fold_ty(self.node_ty(binding.hir_id));
+                if ty.references_error() {
+                    break;
+                }
+                if ty != prev
+                    && let Some(span) = prev_span
+                    && self.can_eq(self.param_env, ty, found).is_ok()
+                {
+                    // We only point at the first place where the found type was inferred.
+                    // We use the *previous* span because if the type is known *here* it means
+                    // it was *evaluated earlier*. We don't do this for method calls because we
+                    // evaluate the method's self type eagerly, but not in any other case.
+                    err.span_label(
+                        span,
+                        with_forced_trimmed_paths!(format!(
+                            "here the type of `{ident}` is inferred to be `{ty}`",
+                        )),
+                    );
+                    break;
+                }
+                prev = ty;
+            }
+            if binding.hir_id == expr.hir_id {
+                // Do not look at expressions that come after the expression we were originally
+                // evaluating and had a type error.
+                break;
+            }
+            prev_span = Some(binding.span);
+        }
+        true
+    }
+
     fn annotate_expected_due_to_let_ty(
         &self,
         err: &mut Diagnostic,
         expr: &hir::Expr<'_>,
         error: Option<TypeError<'tcx>>,
     ) {
-        let parent = self.tcx.hir().get_parent_node(expr.hir_id);
+        let parent = self.tcx.hir().parent_id(expr.hir_id);
         match (self.tcx.hir().find(parent), error) {
             (Some(hir::Node::Local(hir::Local { ty: Some(ty), init: Some(init), .. })), _)
                 if init.hir_id == expr.hir_id =>
@@ -258,10 +477,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         hir::Path { res: hir::def::Res::Local(hir_id), .. },
                     )) => {
                         if let Some(hir::Node::Pat(pat)) = self.tcx.hir().find(*hir_id) {
-                            let parent = self.tcx.hir().get_parent_node(pat.hir_id);
                             primary_span = pat.span;
                             secondary_span = pat.span;
-                            match self.tcx.hir().find(parent) {
+                            match self.tcx.hir().find_parent(pat.hir_id) {
                                 Some(hir::Node::Local(hir::Local { ty: Some(ty), .. })) => {
                                     primary_span = ty.span;
                                     post_message = " type";
@@ -326,7 +544,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         expr: &hir::Expr<'_>,
         error: Option<TypeError<'tcx>>,
     ) {
-        let parent = self.tcx.hir().get_parent_node(expr.hir_id);
+        let parent = self.tcx.hir().parent_id(expr.hir_id);
         let Some(TypeError::Sorts(ExpectedFound { expected, .. })) = error else {return;};
         let Some(hir::Node::Expr(hir::Expr {
                     kind: hir::ExprKind::Assign(lhs, rhs, _), ..
@@ -510,7 +728,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
                 // Unroll desugaring, to make sure this works for `for` loops etc.
                 loop {
-                    parent = self.tcx.hir().get_parent_node(id);
+                    parent = self.tcx.hir().parent_id(id);
                     if let Some(parent_span) = self.tcx.hir().opt_span(parent) {
                         if parent_span.find_ancestor_inside(expr.span).is_some() {
                             // The parent node is part of the same span, so is the result of the
@@ -790,12 +1008,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             return None;
         };
 
-        let local_parent = self.tcx.hir().get_parent_node(local_id);
+        let local_parent = self.tcx.hir().parent_id(local_id);
         let Some(Node::Param(hir::Param { hir_id: param_hir_id, .. })) = self.tcx.hir().find(local_parent) else {
             return None;
         };
 
-        let param_parent = self.tcx.hir().get_parent_node(*param_hir_id);
+        let param_parent = self.tcx.hir().parent_id(*param_hir_id);
         let Some(Node::Expr(hir::Expr {
             hir_id: expr_hir_id,
             kind: hir::ExprKind::Closure(hir::Closure { fn_decl: closure_fn_decl, .. }),
@@ -804,7 +1022,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             return None;
         };
 
-        let expr_parent = self.tcx.hir().get_parent_node(*expr_hir_id);
+        let expr_parent = self.tcx.hir().parent_id(*expr_hir_id);
         let hir = self.tcx.hir().find(expr_parent);
         let closure_params_len = closure_fn_decl.inputs.len();
         let (
@@ -857,7 +1075,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             _ => None,
         }?;
 
-        match hir.find(hir.get_parent_node(expr.hir_id))? {
+        match hir.find_parent(expr.hir_id)? {
             Node::ExprField(field) => {
                 if field.ident.name == local.name && field.is_shorthand {
                     return Some(local.name);
@@ -883,7 +1101,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     /// Returns whether the given expression is an `else if`.
     pub(crate) fn is_else_if_block(&self, expr: &hir::Expr<'_>) -> bool {
         if let hir::ExprKind::If(..) = expr.kind {
-            let parent_id = self.tcx.hir().get_parent_node(expr.hir_id);
+            let parent_id = self.tcx.hir().parent_id(expr.hir_id);
             if let Some(Node::Expr(hir::Expr {
                 kind: hir::ExprKind::If(_, _, Some(else_expr)),
                 ..
@@ -1040,7 +1258,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         if let Some(hir::Node::Expr(hir::Expr {
                             kind: hir::ExprKind::Assign(..),
                             ..
-                        })) = self.tcx.hir().find(self.tcx.hir().get_parent_node(expr.hir_id))
+                        })) = self.tcx.hir().find_parent(expr.hir_id)
                         {
                             if mutability.is_mut() {
                                 // Suppressing this diagnostic, we'll properly print it in `check_expr_assign`
@@ -1162,7 +1380,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         }
                     }
                     // If we've reached our target type with just removing `&`, then just print now.
-                    if steps == 0 {
+                    if steps == 0 && !remove.trim().is_empty() {
                         return Some((
                             prefix_span,
                             format!("consider removing the `{}`", remove.trim()),
@@ -1221,6 +1439,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         } else {
                             (prefix_span, format!("{}{}", prefix, "*".repeat(steps)))
                         };
+                        if suggestion.trim().is_empty() {
+                            return None;
+                        }
 
                         return Some((
                             span,
@@ -1267,9 +1488,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         let mut sugg = vec![];
 
-        if let Some(hir::Node::ExprField(field)) =
-            self.tcx.hir().find(self.tcx.hir().get_parent_node(expr.hir_id))
-        {
+        if let Some(hir::Node::ExprField(field)) = self.tcx.hir().find_parent(expr.hir_id) {
             // `expr` is a literal field for a struct, only suggest if appropriate
             if field.is_shorthand {
                 // This is a field literal
@@ -1625,7 +1844,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             [start, end],
             _,
         ) = expr.kind else { return; };
-        let parent = self.tcx.hir().get_parent_node(expr.hir_id);
+        let parent = self.tcx.hir().parent_id(expr.hir_id);
         if let Some(hir::Node::ExprField(_)) = self.tcx.hir().find(parent) {
             // Ignore `Foo { field: a..Default::default() }`
             return;
@@ -1673,4 +1892,48 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             Applicability::MachineApplicable,
         );
     }
+
+    /// Identify when the type error is because `()` is found in a binding that was assigned a
+    /// block without a tail expression.
+    fn check_for_binding_assigned_block_without_tail_expression(
+        &self,
+        err: &mut Diagnostic,
+        expr: &hir::Expr<'_>,
+        checked_ty: Ty<'tcx>,
+        expected_ty: Ty<'tcx>,
+    ) {
+        if !checked_ty.is_unit() {
+            return;
+        }
+        let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = expr.kind else { return; };
+        let hir::def::Res::Local(hir_id) = path.res else { return; };
+        let Some(hir::Node::Pat(pat)) = self.tcx.hir().find(hir_id) else {
+            return;
+        };
+        let Some(hir::Node::Local(hir::Local {
+            ty: None,
+            init: Some(init),
+            ..
+        })) = self.tcx.hir().find_parent(pat.hir_id) else { return; };
+        let hir::ExprKind::Block(block, None) = init.kind else { return; };
+        if block.expr.is_some() {
+            return;
+        }
+        let [.., stmt] = block.stmts else {
+            err.span_label(block.span, "this empty block is missing a tail expression");
+            return;
+        };
+        let hir::StmtKind::Semi(tail_expr) = stmt.kind else { return; };
+        let Some(ty) = self.node_ty_opt(tail_expr.hir_id) else { return; };
+        if self.can_eq(self.param_env, expected_ty, ty).is_ok() {
+            err.span_suggestion_short(
+                stmt.span.with_lo(tail_expr.span.hi()),
+                "remove this semicolon",
+                "",
+                Applicability::MachineApplicable,
+            );
+        } else {
+            err.span_label(block.span, "this block is missing a tail expression");
+        }
+    }
 }
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index b8b4e873663..b08b22108c8 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -234,6 +234,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             ) => self.check_expr_path(qpath, expr, args),
             _ => self.check_expr_kind(expr, expected),
         });
+        let ty = self.resolve_vars_if_possible(ty);
 
         // Warn for non-block expressions with diverging children.
         match expr.kind {
@@ -920,7 +921,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         original_expr_id: HirId,
         then: impl FnOnce(&hir::Expr<'_>),
     ) {
-        let mut parent = self.tcx.hir().get_parent_node(original_expr_id);
+        let mut parent = self.tcx.hir().parent_id(original_expr_id);
         while let Some(node) = self.tcx.hir().find(parent) {
             match node {
                 hir::Node::Expr(hir::Expr {
@@ -943,7 +944,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 }) => {
                     // Check if our original expression is a child of the condition of a while loop
                     let expr_is_ancestor = std::iter::successors(Some(original_expr_id), |id| {
-                        self.tcx.hir().find_parent_node(*id)
+                        self.tcx.hir().opt_parent_id(*id)
                     })
                     .take_while(|id| *id != parent)
                     .any(|id| id == expr.hir_id);
@@ -959,7 +960,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 | hir::Node::TraitItem(_)
                 | hir::Node::Crate(_) => break,
                 _ => {
-                    parent = self.tcx.hir().get_parent_node(parent);
+                    parent = self.tcx.hir().parent_id(parent);
                 }
             }
         }
@@ -1083,7 +1084,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 // Do not suggest `if let x = y` as `==` is way more likely to be the intention.
                 let hir = self.tcx.hir();
                 if let hir::Node::Expr(hir::Expr { kind: ExprKind::If { .. }, .. }) =
-                    hir.get(hir.get_parent_node(hir.get_parent_node(expr.hir_id)))
+                    hir.get_parent(hir.parent_id(expr.hir_id))
                 {
                     err.span_suggestion_verbose(
                         expr.span.shrink_to_lo(),
@@ -2216,7 +2217,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             self.tcx.check_stability(field.did, Some(expr.hir_id), expr.span, None);
                             return field_ty;
                         }
-                        private_candidate = Some((adjustments, base_def.did(), field_ty));
+                        private_candidate = Some((adjustments, base_def.did()));
                     }
                 }
                 ty::Tuple(tys) => {
@@ -2239,12 +2240,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         }
         self.structurally_resolved_type(autoderef.span(), autoderef.final_ty(false));
 
-        if let Some((adjustments, did, field_ty)) = private_candidate {
+        if let Some((adjustments, did)) = private_candidate {
             // (#90483) apply adjustments to avoid ExprUseVisitor from
             // creating erroneous projection.
             self.apply_adjustments(base, adjustments);
             self.ban_private_field_access(expr, base_ty, field, did);
-            return field_ty;
+            return self.tcx().ty_error();
         }
 
         if field.name == kw::Empty {
@@ -2462,7 +2463,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         err.span_label(field.span, "method, not a field");
         let expr_is_call =
             if let hir::Node::Expr(hir::Expr { kind: ExprKind::Call(callee, _args), .. }) =
-                self.tcx.hir().get(self.tcx.hir().get_parent_node(expr.hir_id))
+                self.tcx.hir().get_parent(expr.hir_id)
             {
                 expr.hir_id == callee.hir_id
             } else {
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
index 150e917c739..634688de01a 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
@@ -1435,9 +1435,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     pub(in super::super) fn expr_in_place(&self, mut expr_id: hir::HirId) -> bool {
         let mut contained_in_place = false;
 
-        while let hir::Node::Expr(parent_expr) =
-            self.tcx.hir().get(self.tcx.hir().get_parent_node(expr_id))
-        {
+        while let hir::Node::Expr(parent_expr) = self.tcx.hir().get_parent(expr_id) {
             match &parent_expr.kind {
                 hir::ExprKind::Assign(lhs, ..) | hir::ExprKind::AssignOp(_, lhs, ..) => {
                     if lhs.hir_id == expr_id {
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
index d342d96a10f..7d6b4aaebf4 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
@@ -473,7 +473,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         call_expr: &hir::Expr<'tcx>,
     ) {
         // Next, let's construct the error
-        let (error_span, full_call_span, ctor_of, is_method) = match &call_expr.kind {
+        let (error_span, full_call_span, call_name, is_method) = match &call_expr.kind {
             hir::ExprKind::Call(
                 hir::Expr { hir_id, span, kind: hir::ExprKind::Path(qpath), .. },
                 _,
@@ -481,12 +481,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 if let Res::Def(DefKind::Ctor(of, _), _) =
                     self.typeck_results.borrow().qpath_res(qpath, *hir_id)
                 {
-                    (call_span, *span, Some(of), false)
+                    let name = match of {
+                        CtorOf::Struct => "struct",
+                        CtorOf::Variant => "enum variant",
+                    };
+                    (call_span, *span, name, false)
                 } else {
-                    (call_span, *span, None, false)
+                    (call_span, *span, "function", false)
                 }
             }
-            hir::ExprKind::Call(hir::Expr { span, .. }, _) => (call_span, *span, None, false),
+            hir::ExprKind::Call(hir::Expr { span, .. }, _) => (call_span, *span, "function", false),
             hir::ExprKind::MethodCall(path_segment, _, _, span) => {
                 let ident_span = path_segment.ident.span;
                 let ident_span = if let Some(args) = path_segment.args {
@@ -494,17 +498,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 } else {
                     ident_span
                 };
-                // methods are never ctors
-                (*span, ident_span, None, true)
+                (*span, ident_span, "method", true)
             }
             k => span_bug!(call_span, "checking argument types on a non-call: `{:?}`", k),
         };
         let args_span = error_span.trim_start(full_call_span).unwrap_or(error_span);
-        let call_name = match ctor_of {
-            Some(CtorOf::Struct) => "struct",
-            Some(CtorOf::Variant) => "enum variant",
-            None => "function",
-        };
 
         // Don't print if it has error types or is just plain `_`
         fn has_error_or_infer<'tcx>(tys: impl IntoIterator<Item = Ty<'tcx>>) -> bool {
@@ -690,8 +688,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         err = tcx.sess.struct_span_err_with_code(
                             full_call_span,
                             &format!(
-                                "this {} takes {}{} but {} {} supplied",
-                                call_name,
+                                "{call_name} takes {}{} but {} {} supplied",
                                 if c_variadic { "at least " } else { "" },
                                 potentially_plural_count(
                                     formal_and_expected_inputs.len(),
@@ -801,6 +798,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 full_call_span,
                 format!("arguments to this {} are incorrect", call_name),
             );
+            if let (Some(callee_ty), hir::ExprKind::MethodCall(_, rcvr, _, _)) =
+                (callee_ty, &call_expr.kind)
+            {
+                // Type that would have accepted this argument if it hadn't been inferred earlier.
+                // FIXME: We leave an inference variable for now, but it'd be nice to get a more
+                // specific type to increase the accuracy of the diagnostic.
+                let expected = self.infcx.next_ty_var(TypeVariableOrigin {
+                    kind: TypeVariableOriginKind::MiscVariable,
+                    span: full_call_span,
+                });
+                self.point_at_expr_source_of_inferred_type(&mut err, rcvr, expected, callee_ty);
+            }
             // Call out where the function is defined
             self.label_fn_like(
                 &mut err,
@@ -1803,7 +1812,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     hir_id: call_hir_id,
                     span: call_span,
                     ..
-                }) = hir.get(hir.get_parent_node(expr.hir_id))
+                }) = hir.get_parent(expr.hir_id)
                     && callee.hir_id == expr.hir_id
                 {
                     if self.closure_span_overlaps_error(error, *call_span) {
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
index 322e11c978f..236bdc60e67 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
@@ -32,7 +32,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         self.typeck_results
             .borrow()
             .liberated_fn_sigs()
-            .get(self.tcx.hir().get_parent_node(self.body_id))
+            .get(self.tcx.hir().parent_id(self.body_id))
             .copied()
     }
 
@@ -642,7 +642,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 // Check if the parent expression is a call to Pin::new.  If it
                 // is and we were expecting a Box, ergo Pin<Box<expected>>, we
                 // can suggest Box::pin.
-                let parent = self.tcx.hir().get_parent_node(expr.hir_id);
+                let parent = self.tcx.hir().parent_id(expr.hir_id);
                 let Some(Node::Expr(Expr { kind: ExprKind::Call(fn_name, _), .. })) = self.tcx.hir().find(parent) else {
                     return false;
                 };
@@ -1014,6 +1014,36 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         }
     }
 
+    pub(crate) fn suggest_clone_for_ref(
+        &self,
+        diag: &mut Diagnostic,
+        expr: &hir::Expr<'_>,
+        expr_ty: Ty<'tcx>,
+        expected_ty: Ty<'tcx>,
+    ) -> bool {
+        if let ty::Ref(_, inner_ty, hir::Mutability::Not) = expr_ty.kind()
+            && let Some(clone_trait_def) = self.tcx.lang_items().clone_trait()
+            && expected_ty == *inner_ty
+            && self
+                .infcx
+                .type_implements_trait(
+                    clone_trait_def,
+                    [self.tcx.erase_regions(expected_ty)],
+                    self.param_env
+                )
+                .must_apply_modulo_regions()
+          {
+              diag.span_suggestion_verbose(
+                  expr.span.shrink_to_hi(),
+                  "consider using clone here",
+                  ".clone()",
+                  Applicability::MachineApplicable,
+              );
+              return true;
+          }
+        false
+    }
+
     pub(crate) fn suggest_copied_or_cloned(
         &self,
         diag: &mut Diagnostic,
diff --git a/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/record_consumed_borrow.rs b/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/record_consumed_borrow.rs
index bfe95852aa7..472205be7b5 100644
--- a/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/record_consumed_borrow.rs
+++ b/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/record_consumed_borrow.rs
@@ -140,7 +140,7 @@ impl<'tcx> expr_use_visitor::Delegate<'tcx> for ExprUseDelegate<'tcx> {
         diag_expr_id: HirId,
     ) {
         let hir = self.tcx.hir();
-        let parent = match hir.find_parent_node(place_with_id.hir_id) {
+        let parent = match hir.opt_parent_id(place_with_id.hir_id) {
             Some(parent) => parent,
             None => place_with_id.hir_id,
         };
diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs
index b06927f9662..99e09b86a23 100644
--- a/compiler/rustc_hir_typeck/src/lib.rs
+++ b/compiler/rustc_hir_typeck/src/lib.rs
@@ -224,7 +224,7 @@ fn typeck_with_fallback<'tcx>(
                     _ => None,
                 })
                 .unwrap_or_else(|| match tcx.hir().get(id) {
-                    Node::AnonConst(_) => match tcx.hir().get(tcx.hir().get_parent_node(id)) {
+                    Node::AnonConst(_) => match tcx.hir().get(tcx.hir().parent_id(id)) {
                         Node::Expr(&hir::Expr {
                             kind: hir::ExprKind::ConstBlock(ref anon_const),
                             ..
@@ -240,10 +240,8 @@ fn typeck_with_fallback<'tcx>(
                         }),
                         Node::Expr(&hir::Expr { kind: hir::ExprKind::InlineAsm(asm), .. })
                         | Node::Item(&hir::Item { kind: hir::ItemKind::GlobalAsm(asm), .. }) => {
-                            let operand_ty = asm
-                                .operands
-                                .iter()
-                                .filter_map(|(op, _op_sp)| match op {
+                            let operand_ty =
+                                asm.operands.iter().find_map(|(op, _op_sp)| match op {
                                     hir::InlineAsmOperand::Const { anon_const }
                                         if anon_const.hir_id == id =>
                                     {
@@ -259,8 +257,7 @@ fn typeck_with_fallback<'tcx>(
                                         }))
                                     }
                                     _ => None,
-                                })
-                                .next();
+                                });
                             operand_ty.unwrap_or_else(fallback)
                         }
                         _ => fallback(),
diff --git a/compiler/rustc_hir_typeck/src/method/mod.rs b/compiler/rustc_hir_typeck/src/method/mod.rs
index b9b27e8627a..d276bcdb81e 100644
--- a/compiler/rustc_hir_typeck/src/method/mod.rs
+++ b/compiler/rustc_hir_typeck/src/method/mod.rs
@@ -57,7 +57,12 @@ pub enum MethodError<'tcx> {
     PrivateMatch(DefKind, DefId, Vec<DefId>),
 
     // Found a `Self: Sized` bound where `Self` is a trait object.
-    IllegalSizedBound(Vec<DefId>, bool, Span),
+    IllegalSizedBound {
+        candidates: Vec<DefId>,
+        needs_mut: bool,
+        bound_span: Span,
+        self_expr: &'tcx hir::Expr<'tcx>,
+    },
 
     // Found a match, but the return type is wrong
     BadReturnType,
@@ -112,7 +117,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             Err(NoMatch(..)) => false,
             Err(Ambiguity(..)) => true,
             Err(PrivateMatch(..)) => allow_private,
-            Err(IllegalSizedBound(..)) => true,
+            Err(IllegalSizedBound { .. }) => true,
             Err(BadReturnType) => bug!("no return type expectations but got BadReturnType"),
         }
     }
@@ -236,7 +241,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     _ => Vec::new(),
                 };
 
-            return Err(IllegalSizedBound(candidates, needs_mut, span));
+            return Err(IllegalSizedBound { candidates, needs_mut, bound_span: span, self_expr });
         }
 
         Ok(result.callee)
diff --git a/compiler/rustc_hir_typeck/src/method/prelude2021.rs b/compiler/rustc_hir_typeck/src/method/prelude2021.rs
index dea14dd93d6..3d6c2119bea 100644
--- a/compiler/rustc_hir_typeck/src/method/prelude2021.rs
+++ b/compiler/rustc_hir_typeck/src/method/prelude2021.rs
@@ -341,8 +341,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         // Find an identifier with which this trait was imported (note that `_` doesn't count).
         let any_id = import_items
             .iter()
-            .filter_map(|item| if item.ident.name != Underscore { Some(item.ident) } else { None })
-            .next();
+            .find_map(|item| if item.ident.name != Underscore { Some(item.ident) } else { None });
         if let Some(any_id) = any_id {
             if any_id.name == Empty {
                 // Glob import, so just use its name.
diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs
index 1afaae0e020..2daf1979ee5 100644
--- a/compiler/rustc_hir_typeck/src/method/probe.rs
+++ b/compiler/rustc_hir_typeck/src/method/probe.rs
@@ -1111,7 +1111,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
                 // a raw pointer
                 !step.self_ty.references_error() && !step.from_unsafe_deref
             })
-            .flat_map(|step| {
+            .find_map(|step| {
                 let InferOk { value: self_ty, obligations: _ } = self
                     .fcx
                     .probe_instantiate_query_response(
@@ -1147,7 +1147,6 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
                         })
                     })
             })
-            .next()
     }
 
     /// For each type `T` in the step list, this attempts to find a method where
diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs
index 7053c180685..536c4270659 100644
--- a/compiler/rustc_hir_typeck/src/method/suggest.rs
+++ b/compiler/rustc_hir_typeck/src/method/suggest.rs
@@ -102,7 +102,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
     pub fn report_method_error(
         &self,
-        mut span: Span,
+        span: Span,
         rcvr_ty: Ty<'tcx>,
         item_name: Ident,
         source: SelfSource<'tcx>,
@@ -114,989 +114,1024 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             return None;
         }
 
-        let report_candidates = |span: Span,
-                                 err: &mut Diagnostic,
-                                 sources: &mut Vec<CandidateSource>,
-                                 sugg_span: Option<Span>| {
-            sources.sort();
-            sources.dedup();
-            // Dynamic limit to avoid hiding just one candidate, which is silly.
-            let limit = if sources.len() == 5 { 5 } else { 4 };
-
-            for (idx, source) in sources.iter().take(limit).enumerate() {
-                match *source {
-                    CandidateSource::Impl(impl_did) => {
-                        // Provide the best span we can. Use the item, if local to crate, else
-                        // the impl, if local to crate (item may be defaulted), else nothing.
-                        let Some(item) = self.associated_value(impl_did, item_name).or_else(|| {
-                            let impl_trait_ref = self.tcx.impl_trait_ref(impl_did)?;
-                            self.associated_value(impl_trait_ref.def_id, item_name)
-                        }) else {
-                            continue;
-                        };
+        let sugg_span = if let SelfSource::MethodCall(expr) = source {
+            // Given `foo.bar(baz)`, `expr` is `bar`, but we want to point to the whole thing.
+            self.tcx.hir().expect_expr(self.tcx.hir().parent_id(expr.hir_id)).span
+        } else {
+            span
+        };
 
-                        let note_span = if item.def_id.is_local() {
-                            Some(self.tcx.def_span(item.def_id))
-                        } else if impl_did.is_local() {
-                            Some(self.tcx.def_span(impl_did))
-                        } else {
-                            None
-                        };
+        match error {
+            MethodError::NoMatch(mut no_match_data) => {
+                return self.report_no_match_method_error(
+                    span,
+                    rcvr_ty,
+                    item_name,
+                    source,
+                    args,
+                    sugg_span,
+                    &mut no_match_data,
+                );
+            }
 
-                        let impl_ty = self.tcx.at(span).type_of(impl_did);
+            MethodError::Ambiguity(mut sources) => {
+                let mut err = struct_span_err!(
+                    self.sess(),
+                    item_name.span,
+                    E0034,
+                    "multiple applicable items in scope"
+                );
+                err.span_label(item_name.span, format!("multiple `{}` found", item_name));
 
-                        let insertion = match self.tcx.impl_trait_ref(impl_did) {
-                            None => String::new(),
-                            Some(trait_ref) => format!(
-                                " of the trait `{}`",
-                                self.tcx.def_path_str(trait_ref.def_id)
-                            ),
-                        };
+                self.note_candidates_on_method_error(
+                    rcvr_ty,
+                    item_name,
+                    args,
+                    span,
+                    &mut err,
+                    &mut sources,
+                    Some(sugg_span),
+                );
+                err.emit();
+            }
 
-                        let (note_str, idx) = if sources.len() > 1 {
-                            (
-                                format!(
-                                    "candidate #{} is defined in an impl{} for the type `{}`",
-                                    idx + 1,
-                                    insertion,
-                                    impl_ty,
-                                ),
-                                Some(idx + 1),
-                            )
-                        } else {
-                            (
-                                format!(
-                                    "the candidate is defined in an impl{} for the type `{}`",
-                                    insertion, impl_ty,
-                                ),
-                                None,
-                            )
-                        };
-                        if let Some(note_span) = note_span {
-                            // We have a span pointing to the method. Show note with snippet.
-                            err.span_note(note_span, &note_str);
-                        } else {
-                            err.note(&note_str);
-                        }
-                        if let Some(sugg_span) = sugg_span
-                            && let Some(trait_ref) = self.tcx.impl_trait_ref(impl_did) {
-                            let path = self.tcx.def_path_str(trait_ref.def_id);
-
-                            let ty = match item.kind {
-                                ty::AssocKind::Const | ty::AssocKind::Type => rcvr_ty,
-                                ty::AssocKind::Fn => self
-                                    .tcx
-                                    .fn_sig(item.def_id)
-                                    .inputs()
-                                    .skip_binder()
-                                    .get(0)
-                                    .filter(|ty| ty.is_region_ptr() && !rcvr_ty.is_region_ptr())
-                                    .copied()
-                                    .unwrap_or(rcvr_ty),
-                            };
-                            print_disambiguation_help(
-                                item_name,
-                                args,
-                                err,
-                                path,
-                                ty,
-                                item.kind,
-                                item.def_id,
-                                sugg_span,
-                                idx,
-                                self.tcx.sess.source_map(),
-                                item.fn_has_self_parameter,
-                            );
+            MethodError::PrivateMatch(kind, def_id, out_of_scope_traits) => {
+                let kind = kind.descr(def_id);
+                let mut err = struct_span_err!(
+                    self.tcx.sess,
+                    item_name.span,
+                    E0624,
+                    "{} `{}` is private",
+                    kind,
+                    item_name
+                );
+                err.span_label(item_name.span, &format!("private {}", kind));
+                let sp = self
+                    .tcx
+                    .hir()
+                    .span_if_local(def_id)
+                    .unwrap_or_else(|| self.tcx.def_span(def_id));
+                err.span_label(sp, &format!("private {} defined here", kind));
+                self.suggest_valid_traits(&mut err, out_of_scope_traits);
+                err.emit();
+            }
+
+            MethodError::IllegalSizedBound { candidates, needs_mut, bound_span, self_expr } => {
+                let msg = if needs_mut {
+                    with_forced_trimmed_paths!(format!(
+                        "the `{item_name}` method cannot be invoked on `{rcvr_ty}`"
+                    ))
+                } else {
+                    format!("the `{item_name}` method cannot be invoked on a trait object")
+                };
+                let mut err = self.sess().struct_span_err(span, &msg);
+                if !needs_mut {
+                    err.span_label(bound_span, "this has a `Sized` requirement");
+                }
+                if !candidates.is_empty() {
+                    let help = format!(
+                        "{an}other candidate{s} {were} found in the following trait{s}, perhaps \
+                         add a `use` for {one_of_them}:",
+                        an = if candidates.len() == 1 { "an" } else { "" },
+                        s = pluralize!(candidates.len()),
+                        were = pluralize!("was", candidates.len()),
+                        one_of_them = if candidates.len() == 1 { "it" } else { "one_of_them" },
+                    );
+                    self.suggest_use_candidates(&mut err, help, candidates);
+                }
+                if let ty::Ref(region, t_type, mutability) = rcvr_ty.kind() {
+                    if needs_mut {
+                        let trait_type = self.tcx.mk_ref(
+                            *region,
+                            ty::TypeAndMut { ty: *t_type, mutbl: mutability.invert() },
+                        );
+                        let msg = format!("you need `{}` instead of `{}`", trait_type, rcvr_ty);
+                        let mut kind = &self_expr.kind;
+                        while let hir::ExprKind::AddrOf(_, _, expr)
+                        | hir::ExprKind::Unary(hir::UnOp::Deref, expr) = kind
+                        {
+                            kind = &expr.kind;
                         }
-                    }
-                    CandidateSource::Trait(trait_did) => {
-                        let Some(item) = self.associated_value(trait_did, item_name) else { continue };
-                        let item_span = self.tcx.def_span(item.def_id);
-                        let idx = if sources.len() > 1 {
-                            let msg = &format!(
-                                "candidate #{} is defined in the trait `{}`",
-                                idx + 1,
-                                self.tcx.def_path_str(trait_did)
+                        if let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = kind
+                            && let hir::def::Res::Local(hir_id) = path.res
+                            && let Some(hir::Node::Pat(b)) = self.tcx.hir().find(hir_id)
+                            && let Some(hir::Node::Param(p)) = self.tcx.hir().find_parent(b.hir_id)
+                            && let Some(node) = self.tcx.hir().find_parent(p.hir_id)
+                            && let Some(decl) = node.fn_decl()
+                            && let Some(ty) = decl.inputs.iter().find(|ty| ty.span == p.ty_span)
+                            && let hir::TyKind::Ref(_, mut_ty) = &ty.kind
+                            && let hir::Mutability::Not = mut_ty.mutbl
+                        {
+                            err.span_suggestion_verbose(
+                                mut_ty.ty.span.shrink_to_lo(),
+                                &msg,
+                                "mut ",
+                                Applicability::MachineApplicable,
                             );
-                            err.span_note(item_span, msg);
-                            Some(idx + 1)
                         } else {
-                            let msg = &format!(
-                                "the candidate is defined in the trait `{}`",
-                                self.tcx.def_path_str(trait_did)
-                            );
-                            err.span_note(item_span, msg);
-                            None
-                        };
-                        if let Some(sugg_span) = sugg_span {
-                            let path = self.tcx.def_path_str(trait_did);
-                            print_disambiguation_help(
-                                item_name,
-                                args,
-                                err,
-                                path,
-                                rcvr_ty,
-                                item.kind,
-                                item.def_id,
-                                sugg_span,
-                                idx,
-                                self.tcx.sess.source_map(),
-                                item.fn_has_self_parameter,
-                            );
+                            err.help(&msg);
                         }
                     }
                 }
+                err.emit();
             }
-            if sources.len() > limit {
-                err.note(&format!("and {} others", sources.len() - limit));
-            }
-        };
 
-        let sugg_span = if let SelfSource::MethodCall(expr) = source {
-            // Given `foo.bar(baz)`, `expr` is `bar`, but we want to point to the whole thing.
-            self.tcx.hir().expect_expr(self.tcx.hir().get_parent_node(expr.hir_id)).span
+            MethodError::BadReturnType => bug!("no return type expectations but got BadReturnType"),
+        }
+        None
+    }
+
+    pub fn report_no_match_method_error(
+        &self,
+        mut span: Span,
+        rcvr_ty: Ty<'tcx>,
+        item_name: Ident,
+        source: SelfSource<'tcx>,
+        args: Option<(&'tcx hir::Expr<'tcx>, &'tcx [hir::Expr<'tcx>])>,
+        sugg_span: Span,
+        no_match_data: &mut NoMatchData<'tcx>,
+    ) -> Option<DiagnosticBuilder<'_, ErrorGuaranteed>> {
+        let mode = no_match_data.mode;
+        let tcx = self.tcx;
+        let rcvr_ty = self.resolve_vars_if_possible(rcvr_ty);
+        let ty_str = with_forced_trimmed_paths!(self.ty_to_string(rcvr_ty));
+        let is_method = mode == Mode::MethodCall;
+        let unsatisfied_predicates = &no_match_data.unsatisfied_predicates;
+        let lev_candidate = no_match_data.lev_candidate;
+        let item_kind = if is_method {
+            "method"
+        } else if rcvr_ty.is_enum() {
+            "variant or associated item"
         } else {
-            span
+            match (item_name.as_str().chars().next(), rcvr_ty.is_fresh_ty()) {
+                (Some(name), false) if name.is_lowercase() => "function or associated item",
+                (Some(_), false) => "associated item",
+                (Some(_), true) | (None, false) => "variant or associated item",
+                (None, true) => "variant",
+            }
         };
 
-        match error {
-            MethodError::NoMatch(NoMatchData {
-                mut static_candidates,
-                unsatisfied_predicates,
-                out_of_scope_traits,
-                lev_candidate,
-                mode,
-            }) => {
-                let tcx = self.tcx;
-
-                let rcvr_ty = self.resolve_vars_if_possible(rcvr_ty);
-                let ty_str = with_forced_trimmed_paths!(self.ty_to_string(rcvr_ty));
-                let is_method = mode == Mode::MethodCall;
-                let item_kind = if is_method {
-                    "method"
-                } else if rcvr_ty.is_enum() {
-                    "variant or associated item"
-                } else {
-                    match (item_name.as_str().chars().next(), rcvr_ty.is_fresh_ty()) {
-                        (Some(name), false) if name.is_lowercase() => "function or associated item",
-                        (Some(_), false) => "associated item",
-                        (Some(_), true) | (None, false) => "variant or associated item",
-                        (None, true) => "variant",
+        if self.suggest_wrapping_range_with_parens(tcx, rcvr_ty, source, span, item_name, &ty_str)
+            || self.suggest_constraining_numerical_ty(
+                tcx, rcvr_ty, source, span, item_kind, item_name, &ty_str,
+            )
+        {
+            return None;
+        }
+        span = item_name.span;
+
+        // Don't show generic arguments when the method can't be found in any implementation (#81576).
+        let mut ty_str_reported = ty_str.clone();
+        if let ty::Adt(_, generics) = rcvr_ty.kind() {
+            if generics.len() > 0 {
+                let mut autoderef = self.autoderef(span, rcvr_ty);
+                let candidate_found = autoderef.any(|(ty, _)| {
+                    if let ty::Adt(adt_def, _) = ty.kind() {
+                        self.tcx
+                            .inherent_impls(adt_def.did())
+                            .iter()
+                            .any(|def_id| self.associated_value(*def_id, item_name).is_some())
+                    } else {
+                        false
                     }
-                };
-
-                if self.suggest_wrapping_range_with_parens(
-                    tcx, rcvr_ty, source, span, item_name, &ty_str,
-                ) || self.suggest_constraining_numerical_ty(
-                    tcx, rcvr_ty, source, span, item_kind, item_name, &ty_str,
-                ) {
-                    return None;
-                }
-                span = item_name.span;
-
-                // Don't show generic arguments when the method can't be found in any implementation (#81576).
-                let mut ty_str_reported = ty_str.clone();
-                if let ty::Adt(_, generics) = rcvr_ty.kind() {
-                    if generics.len() > 0 {
-                        let mut autoderef = self.autoderef(span, rcvr_ty);
-                        let candidate_found = autoderef.any(|(ty, _)| {
-                            if let ty::Adt(adt_def, _) = ty.kind() {
-                                self.tcx
-                                    .inherent_impls(adt_def.did())
-                                    .iter()
-                                    .filter_map(|def_id| self.associated_value(*def_id, item_name))
-                                    .count()
-                                    >= 1
-                            } else {
-                                false
-                            }
-                        });
-                        let has_deref = autoderef.step_count() > 0;
-                        if !candidate_found && !has_deref && unsatisfied_predicates.is_empty() {
-                            if let Some((path_string, _)) = ty_str.split_once('<') {
-                                ty_str_reported = path_string.to_string();
-                            }
-                        }
+                });
+                let has_deref = autoderef.step_count() > 0;
+                if !candidate_found && !has_deref && unsatisfied_predicates.is_empty() {
+                    if let Some((path_string, _)) = ty_str.split_once('<') {
+                        ty_str_reported = path_string.to_string();
                     }
                 }
+            }
+        }
 
-                let mut err = struct_span_err!(
-                    tcx.sess,
-                    span,
-                    E0599,
-                    "no {} named `{}` found for {} `{}` in the current scope",
-                    item_kind,
-                    item_name,
-                    rcvr_ty.prefix_string(self.tcx),
-                    ty_str_reported,
-                );
-                if rcvr_ty.references_error() {
-                    err.downgrade_to_delayed_bug();
-                }
+        let mut err = struct_span_err!(
+            tcx.sess,
+            span,
+            E0599,
+            "no {} named `{}` found for {} `{}` in the current scope",
+            item_kind,
+            item_name,
+            rcvr_ty.prefix_string(self.tcx),
+            ty_str_reported,
+        );
+        if rcvr_ty.references_error() {
+            err.downgrade_to_delayed_bug();
+        }
 
-                if let Mode::MethodCall = mode && let SelfSource::MethodCall(cal) = source {
-                    self.suggest_await_before_method(
-                        &mut err, item_name, rcvr_ty, cal, span,
-                    );
-                }
-                if let Some(span) =
-                    tcx.resolutions(()).confused_type_with_std_module.get(&span.with_parent(None))
-                {
-                    err.span_suggestion(
-                        span.shrink_to_lo(),
-                        "you are looking for the module in `std`, not the primitive type",
-                        "std::",
-                        Applicability::MachineApplicable,
-                    );
-                }
-                if let ty::RawPtr(_) = &rcvr_ty.kind() {
-                    err.note(
-                        "try using `<*const T>::as_ref()` to get a reference to the \
-                         type behind the pointer: https://doc.rust-lang.org/std/\
-                         primitive.pointer.html#method.as_ref",
-                    );
-                    err.note(
-                        "using `<*const T>::as_ref()` on a pointer which is unaligned or points \
-                         to invalid or uninitialized memory is undefined behavior",
-                    );
-                }
+        if let Mode::MethodCall = mode && let SelfSource::MethodCall(cal) = source {
+            self.suggest_await_before_method(
+                &mut err, item_name, rcvr_ty, cal, span,
+            );
+        }
+        if let Some(span) =
+            tcx.resolutions(()).confused_type_with_std_module.get(&span.with_parent(None))
+        {
+            err.span_suggestion(
+                span.shrink_to_lo(),
+                "you are looking for the module in `std`, not the primitive type",
+                "std::",
+                Applicability::MachineApplicable,
+            );
+        }
+        if let ty::RawPtr(_) = &rcvr_ty.kind() {
+            err.note(
+                "try using `<*const T>::as_ref()` to get a reference to the \
+                 type behind the pointer: https://doc.rust-lang.org/std/\
+                 primitive.pointer.html#method.as_ref",
+            );
+            err.note(
+                "using `<*const T>::as_ref()` on a pointer which is unaligned or points \
+                 to invalid or uninitialized memory is undefined behavior",
+            );
+        }
 
-                let ty_span = match rcvr_ty.kind() {
-                    ty::Param(param_type) => Some(
-                        param_type.span_from_generics(self.tcx, self.body_id.owner.to_def_id()),
-                    ),
-                    ty::Adt(def, _) if def.did().is_local() => Some(tcx.def_span(def.did())),
-                    _ => None,
-                };
-                if let Some(span) = ty_span {
-                    err.span_label(
-                        span,
-                        format!(
-                            "{item_kind} `{item_name}` not found for this {}",
-                            rcvr_ty.prefix_string(self.tcx)
-                        ),
-                    );
-                }
+        let ty_span = match rcvr_ty.kind() {
+            ty::Param(param_type) => {
+                Some(param_type.span_from_generics(self.tcx, self.body_id.owner.to_def_id()))
+            }
+            ty::Adt(def, _) if def.did().is_local() => Some(tcx.def_span(def.did())),
+            _ => None,
+        };
+        if let Some(span) = ty_span {
+            err.span_label(
+                span,
+                format!(
+                    "{item_kind} `{item_name}` not found for this {}",
+                    rcvr_ty.prefix_string(self.tcx)
+                ),
+            );
+        }
 
-                if let SelfSource::MethodCall(rcvr_expr) = source {
-                    self.suggest_fn_call(&mut err, rcvr_expr, rcvr_ty, |output_ty| {
-                        let call_expr = self
-                            .tcx
-                            .hir()
-                            .expect_expr(self.tcx.hir().get_parent_node(rcvr_expr.hir_id));
-                        let probe = self.lookup_probe(
-                            item_name,
-                            output_ty,
-                            call_expr,
-                            ProbeScope::AllTraits,
-                        );
-                        probe.is_ok()
-                    });
-                }
+        if let SelfSource::MethodCall(rcvr_expr) = source {
+            self.suggest_fn_call(&mut err, rcvr_expr, rcvr_ty, |output_ty| {
+                let call_expr =
+                    self.tcx.hir().expect_expr(self.tcx.hir().parent_id(rcvr_expr.hir_id));
+                let probe =
+                    self.lookup_probe(item_name, output_ty, call_expr, ProbeScope::AllTraits);
+                probe.is_ok()
+            });
+        }
 
-                let mut custom_span_label = false;
+        let mut custom_span_label = false;
 
-                if !static_candidates.is_empty() {
-                    err.note(
-                        "found the following associated functions; to be used as methods, \
-                         functions must have a `self` parameter",
-                    );
-                    err.span_label(span, "this is an associated function, not a method");
-                    custom_span_label = true;
-                }
-                if static_candidates.len() == 1 {
-                    self.suggest_associated_call_syntax(
-                        &mut err,
-                        &static_candidates,
-                        rcvr_ty,
-                        source,
-                        item_name,
-                        args,
-                        sugg_span,
-                    );
+        let static_candidates = &mut no_match_data.static_candidates;
+        if !static_candidates.is_empty() {
+            err.note(
+                "found the following associated functions; to be used as methods, \
+                 functions must have a `self` parameter",
+            );
+            err.span_label(span, "this is an associated function, not a method");
+            custom_span_label = true;
+        }
+        if static_candidates.len() == 1 {
+            self.suggest_associated_call_syntax(
+                &mut err,
+                &static_candidates,
+                rcvr_ty,
+                source,
+                item_name,
+                args,
+                sugg_span,
+            );
 
-                    report_candidates(span, &mut err, &mut static_candidates, None);
-                } else if static_candidates.len() > 1 {
-                    report_candidates(span, &mut err, &mut static_candidates, Some(sugg_span));
-                }
+            self.note_candidates_on_method_error(
+                rcvr_ty,
+                item_name,
+                args,
+                span,
+                &mut err,
+                static_candidates,
+                None,
+            );
+        } else if static_candidates.len() > 1 {
+            self.note_candidates_on_method_error(
+                rcvr_ty,
+                item_name,
+                args,
+                span,
+                &mut err,
+                static_candidates,
+                Some(sugg_span),
+            );
+        }
 
-                let mut bound_spans = vec![];
-                let mut restrict_type_params = false;
-                let mut unsatisfied_bounds = false;
-                if item_name.name == sym::count && self.is_slice_ty(rcvr_ty, span) {
-                    let msg = "consider using `len` instead";
-                    if let SelfSource::MethodCall(_expr) = source {
-                        err.span_suggestion_short(
-                            span,
-                            msg,
-                            "len",
-                            Applicability::MachineApplicable,
-                        );
-                    } else {
-                        err.span_label(span, msg);
-                    }
-                    if let Some(iterator_trait) = self.tcx.get_diagnostic_item(sym::Iterator) {
-                        let iterator_trait = self.tcx.def_path_str(iterator_trait);
-                        err.note(&format!("`count` is defined on `{iterator_trait}`, which `{rcvr_ty}` does not implement"));
-                    }
-                } else if !unsatisfied_predicates.is_empty() {
-                    let mut type_params = FxHashMap::default();
-
-                    // Pick out the list of unimplemented traits on the receiver.
-                    // This is used for custom error messages with the `#[rustc_on_unimplemented]` attribute.
-                    let mut unimplemented_traits = FxHashMap::default();
-                    let mut unimplemented_traits_only = true;
-                    for (predicate, _parent_pred, cause) in &unsatisfied_predicates {
-                        if let (ty::PredicateKind::Clause(ty::Clause::Trait(p)), Some(cause)) =
-                            (predicate.kind().skip_binder(), cause.as_ref())
-                        {
-                            if p.trait_ref.self_ty() != rcvr_ty {
-                                // This is necessary, not just to keep the errors clean, but also
-                                // because our derived obligations can wind up with a trait ref that
-                                // requires a different param_env to be correctly compared.
-                                continue;
-                            }
-                            unimplemented_traits.entry(p.trait_ref.def_id).or_insert((
-                                predicate.kind().rebind(p.trait_ref),
-                                Obligation {
-                                    cause: cause.clone(),
-                                    param_env: self.param_env,
-                                    predicate: *predicate,
-                                    recursion_depth: 0,
-                                },
-                            ));
-                        }
+        let mut bound_spans = vec![];
+        let mut restrict_type_params = false;
+        let mut unsatisfied_bounds = false;
+        if item_name.name == sym::count && self.is_slice_ty(rcvr_ty, span) {
+            let msg = "consider using `len` instead";
+            if let SelfSource::MethodCall(_expr) = source {
+                err.span_suggestion_short(span, msg, "len", Applicability::MachineApplicable);
+            } else {
+                err.span_label(span, msg);
+            }
+            if let Some(iterator_trait) = self.tcx.get_diagnostic_item(sym::Iterator) {
+                let iterator_trait = self.tcx.def_path_str(iterator_trait);
+                err.note(&format!(
+                    "`count` is defined on `{iterator_trait}`, which `{rcvr_ty}` does not implement"
+                ));
+            }
+        } else if !unsatisfied_predicates.is_empty() {
+            let mut type_params = FxHashMap::default();
+
+            // Pick out the list of unimplemented traits on the receiver.
+            // This is used for custom error messages with the `#[rustc_on_unimplemented]` attribute.
+            let mut unimplemented_traits = FxHashMap::default();
+            let mut unimplemented_traits_only = true;
+            for (predicate, _parent_pred, cause) in unsatisfied_predicates {
+                if let (ty::PredicateKind::Clause(ty::Clause::Trait(p)), Some(cause)) =
+                    (predicate.kind().skip_binder(), cause.as_ref())
+                {
+                    if p.trait_ref.self_ty() != rcvr_ty {
+                        // This is necessary, not just to keep the errors clean, but also
+                        // because our derived obligations can wind up with a trait ref that
+                        // requires a different param_env to be correctly compared.
+                        continue;
                     }
+                    unimplemented_traits.entry(p.trait_ref.def_id).or_insert((
+                        predicate.kind().rebind(p.trait_ref),
+                        Obligation {
+                            cause: cause.clone(),
+                            param_env: self.param_env,
+                            predicate: *predicate,
+                            recursion_depth: 0,
+                        },
+                    ));
+                }
+            }
 
-                    // Make sure that, if any traits other than the found ones were involved,
-                    // we don't don't report an unimplemented trait.
-                    // We don't want to say that `iter::Cloned` is not an iterator, just
-                    // because of some non-Clone item being iterated over.
-                    for (predicate, _parent_pred, _cause) in &unsatisfied_predicates {
-                        match predicate.kind().skip_binder() {
-                            ty::PredicateKind::Clause(ty::Clause::Trait(p))
-                                if unimplemented_traits.contains_key(&p.trait_ref.def_id) => {}
-                            _ => {
-                                unimplemented_traits_only = false;
-                                break;
-                            }
-                        }
+            // Make sure that, if any traits other than the found ones were involved,
+            // we don't don't report an unimplemented trait.
+            // We don't want to say that `iter::Cloned` is not an iterator, just
+            // because of some non-Clone item being iterated over.
+            for (predicate, _parent_pred, _cause) in unsatisfied_predicates {
+                match predicate.kind().skip_binder() {
+                    ty::PredicateKind::Clause(ty::Clause::Trait(p))
+                        if unimplemented_traits.contains_key(&p.trait_ref.def_id) => {}
+                    _ => {
+                        unimplemented_traits_only = false;
+                        break;
                     }
+                }
+            }
 
-                    let mut collect_type_param_suggestions =
-                        |self_ty: Ty<'tcx>, parent_pred: ty::Predicate<'tcx>, obligation: &str| {
-                            // We don't care about regions here, so it's fine to skip the binder here.
-                            if let (ty::Param(_), ty::PredicateKind::Clause(ty::Clause::Trait(p))) =
-                                (self_ty.kind(), parent_pred.kind().skip_binder())
-                            {
-                                let hir = self.tcx.hir();
-                                let node = match p.trait_ref.self_ty().kind() {
-                                    ty::Param(_) => {
-                                        // Account for `fn` items like in `issue-35677.rs` to
-                                        // suggest restricting its type params.
-                                        let parent_body =
-                                            hir.body_owner(hir::BodyId { hir_id: self.body_id });
-                                        Some(hir.get(parent_body))
-                                    }
-                                    ty::Adt(def, _) => {
-                                        def.did().as_local().map(|def_id| hir.get_by_def_id(def_id))
-                                    }
-                                    _ => None,
-                                };
-                                if let Some(hir::Node::Item(hir::Item { kind, .. })) = node {
-                                    if let Some(g) = kind.generics() {
-                                        let key = (
-                                            g.tail_span_for_predicate_suggestion(),
-                                            g.add_where_or_trailing_comma(),
-                                        );
-                                        type_params
-                                            .entry(key)
-                                            .or_insert_with(FxHashSet::default)
-                                            .insert(obligation.to_owned());
-                                    }
-                                }
+            let mut collect_type_param_suggestions =
+                |self_ty: Ty<'tcx>, parent_pred: ty::Predicate<'tcx>, obligation: &str| {
+                    // We don't care about regions here, so it's fine to skip the binder here.
+                    if let (ty::Param(_), ty::PredicateKind::Clause(ty::Clause::Trait(p))) =
+                        (self_ty.kind(), parent_pred.kind().skip_binder())
+                    {
+                        let hir = self.tcx.hir();
+                        let node = match p.trait_ref.self_ty().kind() {
+                            ty::Param(_) => {
+                                // Account for `fn` items like in `issue-35677.rs` to
+                                // suggest restricting its type params.
+                                let parent_body =
+                                    hir.body_owner(hir::BodyId { hir_id: self.body_id });
+                                Some(hir.get(parent_body))
                             }
-                        };
-                    let mut bound_span_label = |self_ty: Ty<'_>, obligation: &str, quiet: &str| {
-                        let msg = format!(
-                            "doesn't satisfy `{}`",
-                            if obligation.len() > 50 { quiet } else { obligation }
-                        );
-                        match &self_ty.kind() {
-                            // Point at the type that couldn't satisfy the bound.
                             ty::Adt(def, _) => {
-                                bound_spans.push((self.tcx.def_span(def.did()), msg))
+                                def.did().as_local().map(|def_id| hir.get_by_def_id(def_id))
                             }
-                            // Point at the trait object that couldn't satisfy the bound.
-                            ty::Dynamic(preds, _, _) => {
-                                for pred in preds.iter() {
-                                    match pred.skip_binder() {
-                                        ty::ExistentialPredicate::Trait(tr) => bound_spans
-                                            .push((self.tcx.def_span(tr.def_id), msg.clone())),
-                                        ty::ExistentialPredicate::Projection(_)
-                                        | ty::ExistentialPredicate::AutoTrait(_) => {}
-                                    }
+                            _ => None,
+                        };
+                        if let Some(hir::Node::Item(hir::Item { kind, .. })) = node {
+                            if let Some(g) = kind.generics() {
+                                let key = (
+                                    g.tail_span_for_predicate_suggestion(),
+                                    g.add_where_or_trailing_comma(),
+                                );
+                                type_params
+                                    .entry(key)
+                                    .or_insert_with(FxHashSet::default)
+                                    .insert(obligation.to_owned());
+                            }
+                        }
+                    }
+                };
+            let mut bound_span_label = |self_ty: Ty<'_>, obligation: &str, quiet: &str| {
+                let msg = format!(
+                    "doesn't satisfy `{}`",
+                    if obligation.len() > 50 { quiet } else { obligation }
+                );
+                match &self_ty.kind() {
+                    // Point at the type that couldn't satisfy the bound.
+                    ty::Adt(def, _) => bound_spans.push((self.tcx.def_span(def.did()), msg)),
+                    // Point at the trait object that couldn't satisfy the bound.
+                    ty::Dynamic(preds, _, _) => {
+                        for pred in preds.iter() {
+                            match pred.skip_binder() {
+                                ty::ExistentialPredicate::Trait(tr) => {
+                                    bound_spans.push((self.tcx.def_span(tr.def_id), msg.clone()))
                                 }
+                                ty::ExistentialPredicate::Projection(_)
+                                | ty::ExistentialPredicate::AutoTrait(_) => {}
                             }
-                            // Point at the closure that couldn't satisfy the bound.
-                            ty::Closure(def_id, _) => bound_spans.push((
-                                tcx.def_span(*def_id),
-                                format!("doesn't satisfy `{}`", quiet),
-                            )),
-                            _ => {}
                         }
-                    };
-                    let mut format_pred = |pred: ty::Predicate<'tcx>| {
-                        let bound_predicate = pred.kind();
-                        match bound_predicate.skip_binder() {
-                            ty::PredicateKind::Clause(ty::Clause::Projection(pred)) => {
-                                let pred = bound_predicate.rebind(pred);
-                                // `<Foo as Iterator>::Item = String`.
-                                let projection_ty = pred.skip_binder().projection_ty;
-
-                                let substs_with_infer_self = tcx.mk_substs(
-                                    iter::once(tcx.mk_ty_var(ty::TyVid::from_u32(0)).into())
-                                        .chain(projection_ty.substs.iter().skip(1)),
-                                );
+                    }
+                    // Point at the closure that couldn't satisfy the bound.
+                    ty::Closure(def_id, _) => bound_spans
+                        .push((tcx.def_span(*def_id), format!("doesn't satisfy `{}`", quiet))),
+                    _ => {}
+                }
+            };
+            let mut format_pred = |pred: ty::Predicate<'tcx>| {
+                let bound_predicate = pred.kind();
+                match bound_predicate.skip_binder() {
+                    ty::PredicateKind::Clause(ty::Clause::Projection(pred)) => {
+                        let pred = bound_predicate.rebind(pred);
+                        // `<Foo as Iterator>::Item = String`.
+                        let projection_ty = pred.skip_binder().projection_ty;
+
+                        let substs_with_infer_self = tcx.mk_substs(
+                            iter::once(tcx.mk_ty_var(ty::TyVid::from_u32(0)).into())
+                                .chain(projection_ty.substs.iter().skip(1)),
+                        );
 
-                                let quiet_projection_ty =
-                                    tcx.mk_alias_ty(projection_ty.def_id, substs_with_infer_self);
+                        let quiet_projection_ty =
+                            tcx.mk_alias_ty(projection_ty.def_id, substs_with_infer_self);
 
-                                let term = pred.skip_binder().term;
+                        let term = pred.skip_binder().term;
 
-                                let obligation = format!("{} = {}", projection_ty, term);
-                                let quiet = with_forced_trimmed_paths!(format!(
-                                    "{} = {}",
-                                    quiet_projection_ty, term
-                                ));
+                        let obligation = format!("{} = {}", projection_ty, term);
+                        let quiet = with_forced_trimmed_paths!(format!(
+                            "{} = {}",
+                            quiet_projection_ty, term
+                        ));
 
-                                bound_span_label(projection_ty.self_ty(), &obligation, &quiet);
-                                Some((obligation, projection_ty.self_ty()))
-                            }
-                            ty::PredicateKind::Clause(ty::Clause::Trait(poly_trait_ref)) => {
-                                let p = poly_trait_ref.trait_ref;
-                                let self_ty = p.self_ty();
-                                let path = p.print_only_trait_path();
-                                let obligation = format!("{}: {}", self_ty, path);
-                                let quiet = with_forced_trimmed_paths!(format!("_: {}", path));
-                                bound_span_label(self_ty, &obligation, &quiet);
-                                Some((obligation, self_ty))
-                            }
-                            _ => None,
-                        }
-                    };
+                        bound_span_label(projection_ty.self_ty(), &obligation, &quiet);
+                        Some((obligation, projection_ty.self_ty()))
+                    }
+                    ty::PredicateKind::Clause(ty::Clause::Trait(poly_trait_ref)) => {
+                        let p = poly_trait_ref.trait_ref;
+                        let self_ty = p.self_ty();
+                        let path = p.print_only_trait_path();
+                        let obligation = format!("{}: {}", self_ty, path);
+                        let quiet = with_forced_trimmed_paths!(format!("_: {}", path));
+                        bound_span_label(self_ty, &obligation, &quiet);
+                        Some((obligation, self_ty))
+                    }
+                    _ => None,
+                }
+            };
 
-                    // Find all the requirements that come from a local `impl` block.
-                    let mut skip_list: FxHashSet<_> = Default::default();
-                    let mut spanned_predicates: FxHashMap<MultiSpan, _> = Default::default();
-                    for (data, p, parent_p, impl_def_id, cause) in unsatisfied_predicates
-                        .iter()
-                        .filter_map(|(p, parent, c)| c.as_ref().map(|c| (p, parent, c)))
-                        .filter_map(|(p, parent, c)| match c.code() {
-                            ObligationCauseCode::ImplDerivedObligation(data) => {
-                                Some((&data.derived, p, parent, data.impl_def_id, data))
-                            }
-                            _ => None,
-                        })
+            // Find all the requirements that come from a local `impl` block.
+            let mut skip_list: FxHashSet<_> = Default::default();
+            let mut spanned_predicates: FxHashMap<MultiSpan, _> = Default::default();
+            for (data, p, parent_p, impl_def_id, cause) in unsatisfied_predicates
+                .iter()
+                .filter_map(|(p, parent, c)| c.as_ref().map(|c| (p, parent, c)))
+                .filter_map(|(p, parent, c)| match c.code() {
+                    ObligationCauseCode::ImplDerivedObligation(data) => {
+                        Some((&data.derived, p, parent, data.impl_def_id, data))
+                    }
+                    _ => None,
+                })
+            {
+                let parent_trait_ref = data.parent_trait_pred;
+                let path = parent_trait_ref.print_modifiers_and_trait_path();
+                let tr_self_ty = parent_trait_ref.skip_binder().self_ty();
+                let unsatisfied_msg = "unsatisfied trait bound introduced here";
+                let derive_msg = "unsatisfied trait bound introduced in this `derive` macro";
+                match self.tcx.hir().get_if_local(impl_def_id) {
+                    // Unmet obligation comes from a `derive` macro, point at it once to
+                    // avoid multiple span labels pointing at the same place.
+                    Some(Node::Item(hir::Item {
+                        kind: hir::ItemKind::Impl(hir::Impl { of_trait, self_ty, .. }),
+                        ..
+                    })) if matches!(
+                        self_ty.span.ctxt().outer_expn_data().kind,
+                        ExpnKind::Macro(MacroKind::Derive, _)
+                    ) || matches!(
+                        of_trait.as_ref().map(|t| t.path.span.ctxt().outer_expn_data().kind),
+                        Some(ExpnKind::Macro(MacroKind::Derive, _))
+                    ) =>
                     {
-                        let parent_trait_ref = data.parent_trait_pred;
-                        let path = parent_trait_ref.print_modifiers_and_trait_path();
-                        let tr_self_ty = parent_trait_ref.skip_binder().self_ty();
-                        let unsatisfied_msg = "unsatisfied trait bound introduced here";
-                        let derive_msg =
-                            "unsatisfied trait bound introduced in this `derive` macro";
-                        match self.tcx.hir().get_if_local(impl_def_id) {
-                            // Unmet obligation comes from a `derive` macro, point at it once to
-                            // avoid multiple span labels pointing at the same place.
-                            Some(Node::Item(hir::Item {
-                                kind: hir::ItemKind::Impl(hir::Impl { of_trait, self_ty, .. }),
-                                ..
-                            })) if matches!(
-                                self_ty.span.ctxt().outer_expn_data().kind,
-                                ExpnKind::Macro(MacroKind::Derive, _)
-                            ) || matches!(
-                                of_trait.as_ref().map(|t| t
-                                    .path
-                                    .span
-                                    .ctxt()
-                                    .outer_expn_data()
-                                    .kind),
-                                Some(ExpnKind::Macro(MacroKind::Derive, _))
-                            ) =>
-                            {
-                                let span = self_ty.span.ctxt().outer_expn_data().call_site;
-                                let mut spans: MultiSpan = span.into();
-                                spans.push_span_label(span, derive_msg);
-                                let entry = spanned_predicates.entry(spans);
-                                entry.or_insert_with(|| (path, tr_self_ty, Vec::new())).2.push(p);
-                            }
+                        let span = self_ty.span.ctxt().outer_expn_data().call_site;
+                        let mut spans: MultiSpan = span.into();
+                        spans.push_span_label(span, derive_msg);
+                        let entry = spanned_predicates.entry(spans);
+                        entry.or_insert_with(|| (path, tr_self_ty, Vec::new())).2.push(p);
+                    }
 
-                            // Unmet obligation coming from an `impl`.
-                            Some(Node::Item(hir::Item {
-                                kind:
-                                    hir::ItemKind::Impl(hir::Impl {
-                                        of_trait, self_ty, generics, ..
-                                    }),
-                                span: item_span,
-                                ..
-                            })) => {
-                                let sized_pred =
-                                    unsatisfied_predicates.iter().any(|(pred, _, _)| {
-                                        match pred.kind().skip_binder() {
-                                            ty::PredicateKind::Clause(ty::Clause::Trait(pred)) => {
-                                                Some(pred.def_id())
-                                                    == self.tcx.lang_items().sized_trait()
-                                                    && pred.polarity == ty::ImplPolarity::Positive
-                                            }
-                                            _ => false,
-                                        }
-                                    });
-                                for param in generics.params {
-                                    if param.span == cause.span && sized_pred {
-                                        let (sp, sugg) = match param.colon_span {
-                                            Some(sp) => (sp.shrink_to_hi(), " ?Sized +"),
-                                            None => (param.span.shrink_to_hi(), ": ?Sized"),
-                                        };
-                                        err.span_suggestion_verbose(
-                                            sp,
-                                            "consider relaxing the type parameter's implicit \
-                                             `Sized` bound",
-                                            sugg,
-                                            Applicability::MachineApplicable,
-                                        );
+                    // Unmet obligation coming from an `impl`.
+                    Some(Node::Item(hir::Item {
+                        kind: hir::ItemKind::Impl(hir::Impl { of_trait, self_ty, generics, .. }),
+                        span: item_span,
+                        ..
+                    })) => {
+                        let sized_pred =
+                            unsatisfied_predicates.iter().any(|(pred, _, _)| {
+                                match pred.kind().skip_binder() {
+                                    ty::PredicateKind::Clause(ty::Clause::Trait(pred)) => {
+                                        Some(pred.def_id()) == self.tcx.lang_items().sized_trait()
+                                            && pred.polarity == ty::ImplPolarity::Positive
                                     }
+                                    _ => false,
                                 }
-                                if let Some(pred) = parent_p {
-                                    // Done to add the "doesn't satisfy" `span_label`.
-                                    let _ = format_pred(*pred);
-                                }
-                                skip_list.insert(p);
-                                let mut spans = if cause.span != *item_span {
-                                    let mut spans: MultiSpan = cause.span.into();
-                                    spans.push_span_label(cause.span, unsatisfied_msg);
-                                    spans
-                                } else {
-                                    let mut spans = Vec::with_capacity(2);
-                                    if let Some(trait_ref) = of_trait {
-                                        spans.push(trait_ref.path.span);
-                                    }
-                                    spans.push(self_ty.span);
-                                    spans.into()
+                            });
+                        for param in generics.params {
+                            if param.span == cause.span && sized_pred {
+                                let (sp, sugg) = match param.colon_span {
+                                    Some(sp) => (sp.shrink_to_hi(), " ?Sized +"),
+                                    None => (param.span.shrink_to_hi(), ": ?Sized"),
                                 };
-                                if let Some(trait_ref) = of_trait {
-                                    spans.push_span_label(trait_ref.path.span, "");
-                                }
-                                spans.push_span_label(self_ty.span, "");
-
-                                let entry = spanned_predicates.entry(spans);
-                                entry.or_insert_with(|| (path, tr_self_ty, Vec::new())).2.push(p);
-                            }
-                            Some(Node::Item(hir::Item {
-                                kind: hir::ItemKind::Trait(rustc_ast::ast::IsAuto::Yes, ..),
-                                span: item_span,
-                                ..
-                            })) => {
-                                tcx.sess.delay_span_bug(
-                                        *item_span,
-                                        "auto trait is invoked with no method error, but no error reported?",
-                                    );
+                                err.span_suggestion_verbose(
+                                    sp,
+                                    "consider relaxing the type parameter's implicit \
+                                     `Sized` bound",
+                                    sugg,
+                                    Applicability::MachineApplicable,
+                                );
                             }
-                            Some(_) => unreachable!(),
-                            None => (),
                         }
-                    }
-                    let mut spanned_predicates: Vec<_> = spanned_predicates.into_iter().collect();
-                    spanned_predicates.sort_by_key(|(span, (_, _, _))| span.primary_span());
-                    for (span, (_path, _self_ty, preds)) in spanned_predicates {
-                        let mut preds: Vec<_> = preds
-                            .into_iter()
-                            .filter_map(|pred| format_pred(*pred))
-                            .map(|(p, _)| format!("`{}`", p))
-                            .collect();
-                        preds.sort();
-                        preds.dedup();
-                        let msg = if let [pred] = &preds[..] {
-                            format!("trait bound {} was not satisfied", pred)
+                        if let Some(pred) = parent_p {
+                            // Done to add the "doesn't satisfy" `span_label`.
+                            let _ = format_pred(*pred);
+                        }
+                        skip_list.insert(p);
+                        let mut spans = if cause.span != *item_span {
+                            let mut spans: MultiSpan = cause.span.into();
+                            spans.push_span_label(cause.span, unsatisfied_msg);
+                            spans
                         } else {
-                            format!(
-                                "the following trait bounds were not satisfied:\n{}",
-                                preds.join("\n"),
-                            )
+                            let mut spans = Vec::with_capacity(2);
+                            if let Some(trait_ref) = of_trait {
+                                spans.push(trait_ref.path.span);
+                            }
+                            spans.push(self_ty.span);
+                            spans.into()
                         };
-                        err.span_note(span, &msg);
-                        unsatisfied_bounds = true;
-                    }
+                        if let Some(trait_ref) = of_trait {
+                            spans.push_span_label(trait_ref.path.span, "");
+                        }
+                        spans.push_span_label(self_ty.span, "");
 
-                    // The requirements that didn't have an `impl` span to show.
-                    let mut bound_list = unsatisfied_predicates
-                        .iter()
-                        .filter_map(|(pred, parent_pred, _cause)| {
-                            format_pred(*pred).map(|(p, self_ty)| {
-                                collect_type_param_suggestions(self_ty, *pred, &p);
-                                (
-                                    match parent_pred {
-                                        None => format!("`{}`", &p),
-                                        Some(parent_pred) => match format_pred(*parent_pred) {
-                                            None => format!("`{}`", &p),
-                                            Some((parent_p, _)) => {
-                                                collect_type_param_suggestions(
-                                                    self_ty,
-                                                    *parent_pred,
-                                                    &p,
-                                                );
-                                                format!(
-                                                    "`{}`\nwhich is required by `{}`",
-                                                    p, parent_p
-                                                )
-                                            }
-                                        },
-                                    },
-                                    *pred,
-                                )
-                            })
-                        })
-                        .filter(|(_, pred)| !skip_list.contains(&pred))
-                        .map(|(t, _)| t)
-                        .enumerate()
-                        .collect::<Vec<(usize, String)>>();
-
-                    for ((span, add_where_or_comma), obligations) in type_params.into_iter() {
-                        restrict_type_params = true;
-                        // #74886: Sort here so that the output is always the same.
-                        let mut obligations = obligations.into_iter().collect::<Vec<_>>();
-                        obligations.sort();
-                        err.span_suggestion_verbose(
-                            span,
-                            &format!(
-                                "consider restricting the type parameter{s} to satisfy the \
-                                 trait bound{s}",
-                                s = pluralize!(obligations.len())
-                            ),
-                            format!("{} {}", add_where_or_comma, obligations.join(", ")),
-                            Applicability::MaybeIncorrect,
+                        let entry = spanned_predicates.entry(spans);
+                        entry.or_insert_with(|| (path, tr_self_ty, Vec::new())).2.push(p);
+                    }
+                    Some(Node::Item(hir::Item {
+                        kind: hir::ItemKind::Trait(rustc_ast::ast::IsAuto::Yes, ..),
+                        span: item_span,
+                        ..
+                    })) => {
+                        tcx.sess.delay_span_bug(
+                            *item_span,
+                            "auto trait is invoked with no method error, but no error reported?",
                         );
                     }
+                    Some(_) => unreachable!(),
+                    None => (),
+                }
+            }
+            let mut spanned_predicates: Vec<_> = spanned_predicates.into_iter().collect();
+            spanned_predicates.sort_by_key(|(span, (_, _, _))| span.primary_span());
+            for (span, (_path, _self_ty, preds)) in spanned_predicates {
+                let mut preds: Vec<_> = preds
+                    .into_iter()
+                    .filter_map(|pred| format_pred(*pred))
+                    .map(|(p, _)| format!("`{}`", p))
+                    .collect();
+                preds.sort();
+                preds.dedup();
+                let msg = if let [pred] = &preds[..] {
+                    format!("trait bound {} was not satisfied", pred)
+                } else {
+                    format!("the following trait bounds were not satisfied:\n{}", preds.join("\n"),)
+                };
+                err.span_note(span, &msg);
+                unsatisfied_bounds = true;
+            }
 
-                    bound_list.sort_by(|(_, a), (_, b)| a.cmp(b)); // Sort alphabetically.
-                    bound_list.dedup_by(|(_, a), (_, b)| a == b); // #35677
-                    bound_list.sort_by_key(|(pos, _)| *pos); // Keep the original predicate order.
+            // The requirements that didn't have an `impl` span to show.
+            let mut bound_list = unsatisfied_predicates
+                .iter()
+                .filter_map(|(pred, parent_pred, _cause)| {
+                    format_pred(*pred).map(|(p, self_ty)| {
+                        collect_type_param_suggestions(self_ty, *pred, &p);
+                        (
+                            match parent_pred {
+                                None => format!("`{}`", &p),
+                                Some(parent_pred) => match format_pred(*parent_pred) {
+                                    None => format!("`{}`", &p),
+                                    Some((parent_p, _)) => {
+                                        collect_type_param_suggestions(self_ty, *parent_pred, &p);
+                                        format!("`{}`\nwhich is required by `{}`", p, parent_p)
+                                    }
+                                },
+                            },
+                            *pred,
+                        )
+                    })
+                })
+                .filter(|(_, pred)| !skip_list.contains(&pred))
+                .map(|(t, _)| t)
+                .enumerate()
+                .collect::<Vec<(usize, String)>>();
+
+            for ((span, add_where_or_comma), obligations) in type_params.into_iter() {
+                restrict_type_params = true;
+                // #74886: Sort here so that the output is always the same.
+                let mut obligations = obligations.into_iter().collect::<Vec<_>>();
+                obligations.sort();
+                err.span_suggestion_verbose(
+                    span,
+                    &format!(
+                        "consider restricting the type parameter{s} to satisfy the \
+                         trait bound{s}",
+                        s = pluralize!(obligations.len())
+                    ),
+                    format!("{} {}", add_where_or_comma, obligations.join(", ")),
+                    Applicability::MaybeIncorrect,
+                );
+            }
 
-                    if !bound_list.is_empty() || !skip_list.is_empty() {
-                        let bound_list = bound_list
-                            .into_iter()
-                            .map(|(_, path)| path)
-                            .collect::<Vec<_>>()
-                            .join("\n");
-                        let actual_prefix = rcvr_ty.prefix_string(self.tcx);
-                        info!("unimplemented_traits.len() == {}", unimplemented_traits.len());
-                        let (primary_message, label) =
-                            if unimplemented_traits.len() == 1 && unimplemented_traits_only {
-                                unimplemented_traits
-                                    .into_iter()
-                                    .next()
-                                    .map(|(_, (trait_ref, obligation))| {
-                                        if trait_ref.self_ty().references_error()
-                                            || rcvr_ty.references_error()
-                                        {
-                                            // Avoid crashing.
-                                            return (None, None);
-                                        }
-                                        let OnUnimplementedNote { message, label, .. } = self
-                                            .err_ctxt()
-                                            .on_unimplemented_note(trait_ref, &obligation);
-                                        (message, label)
-                                    })
-                                    .unwrap()
-                            } else {
-                                (None, None)
-                            };
-                        let primary_message = primary_message.unwrap_or_else(|| format!(
-                            "the {item_kind} `{item_name}` exists for {actual_prefix} `{ty_str}`, \
-                             but its trait bounds were not satisfied"
-                        ));
-                        err.set_primary_message(&primary_message);
-                        if let Some(label) = label {
-                            custom_span_label = true;
-                            err.span_label(span, label);
-                        }
-                        if !bound_list.is_empty() {
-                            err.note(&format!(
-                                "the following trait bounds were not satisfied:\n{bound_list}"
-                            ));
-                        }
-                        self.suggest_derive(&mut err, &unsatisfied_predicates);
+            bound_list.sort_by(|(_, a), (_, b)| a.cmp(b)); // Sort alphabetically.
+            bound_list.dedup_by(|(_, a), (_, b)| a == b); // #35677
+            bound_list.sort_by_key(|(pos, _)| *pos); // Keep the original predicate order.
+
+            if !bound_list.is_empty() || !skip_list.is_empty() {
+                let bound_list =
+                    bound_list.into_iter().map(|(_, path)| path).collect::<Vec<_>>().join("\n");
+                let actual_prefix = rcvr_ty.prefix_string(self.tcx);
+                info!("unimplemented_traits.len() == {}", unimplemented_traits.len());
+                let (primary_message, label) = if unimplemented_traits.len() == 1
+                    && unimplemented_traits_only
+                {
+                    unimplemented_traits
+                        .into_iter()
+                        .next()
+                        .map(|(_, (trait_ref, obligation))| {
+                            if trait_ref.self_ty().references_error() || rcvr_ty.references_error()
+                            {
+                                // Avoid crashing.
+                                return (None, None);
+                            }
+                            let OnUnimplementedNote { message, label, .. } =
+                                self.err_ctxt().on_unimplemented_note(trait_ref, &obligation);
+                            (message, label)
+                        })
+                        .unwrap()
+                } else {
+                    (None, None)
+                };
+                let primary_message = primary_message.unwrap_or_else(|| {
+                    format!(
+                        "the {item_kind} `{item_name}` exists for {actual_prefix} `{ty_str}`, \
+                    but its trait bounds were not satisfied"
+                    )
+                });
+                err.set_primary_message(&primary_message);
+                if let Some(label) = label {
+                    custom_span_label = true;
+                    err.span_label(span, label);
+                }
+                if !bound_list.is_empty() {
+                    err.note(&format!(
+                        "the following trait bounds were not satisfied:\n{bound_list}"
+                    ));
+                }
+                self.suggest_derive(&mut err, &unsatisfied_predicates);
+
+                unsatisfied_bounds = true;
+            }
+        }
 
-                        unsatisfied_bounds = true;
+        let label_span_not_found = |err: &mut Diagnostic| {
+            if unsatisfied_predicates.is_empty() {
+                err.span_label(span, format!("{item_kind} not found in `{ty_str}`"));
+                let is_string_or_ref_str = match rcvr_ty.kind() {
+                    ty::Ref(_, ty, _) => {
+                        ty.is_str()
+                            || matches!(
+                                ty.kind(),
+                                ty::Adt(adt, _) if Some(adt.did()) == self.tcx.lang_items().string()
+                            )
                     }
+                    ty::Adt(adt, _) => Some(adt.did()) == self.tcx.lang_items().string(),
+                    _ => false,
+                };
+                if is_string_or_ref_str && item_name.name == sym::iter {
+                    err.span_suggestion_verbose(
+                        item_name.span,
+                        "because of the in-memory representation of `&str`, to obtain \
+                         an `Iterator` over each of its codepoint use method `chars`",
+                        "chars",
+                        Applicability::MachineApplicable,
+                    );
                 }
-
-                let label_span_not_found = |err: &mut Diagnostic| {
-                    if unsatisfied_predicates.is_empty() {
-                        err.span_label(span, format!("{item_kind} not found in `{ty_str}`"));
-                        let is_string_or_ref_str = match rcvr_ty.kind() {
-                            ty::Ref(_, ty, _) => {
-                                ty.is_str()
-                                    || matches!(
-                                        ty.kind(),
-                                        ty::Adt(adt, _) if Some(adt.did()) == self.tcx.lang_items().string()
-                                    )
-                            }
-                            ty::Adt(adt, _) => Some(adt.did()) == self.tcx.lang_items().string(),
-                            _ => false,
-                        };
-                        if is_string_or_ref_str && item_name.name == sym::iter {
-                            err.span_suggestion_verbose(
-                                item_name.span,
-                                "because of the in-memory representation of `&str`, to obtain \
-                                 an `Iterator` over each of its codepoint use method `chars`",
-                                "chars",
-                                Applicability::MachineApplicable,
-                            );
-                        }
-                        if let ty::Adt(adt, _) = rcvr_ty.kind() {
-                            let mut inherent_impls_candidate = self
-                                .tcx
-                                .inherent_impls(adt.did())
-                                .iter()
-                                .copied()
-                                .filter(|def_id| {
-                                    if let Some(assoc) = self.associated_value(*def_id, item_name) {
-                                        // Check for both mode is the same so we avoid suggesting
-                                        // incorrect associated item.
-                                        match (mode, assoc.fn_has_self_parameter, source) {
-                                            (Mode::MethodCall, true, SelfSource::MethodCall(_)) => {
-                                                // We check that the suggest type is actually
-                                                // different from the received one
-                                                // So we avoid suggestion method with Box<Self>
-                                                // for instance
-                                                self.tcx.at(span).type_of(*def_id) != rcvr_ty
-                                                    && self.tcx.at(span).type_of(*def_id) != rcvr_ty
-                                            }
-                                            (Mode::Path, false, _) => true,
-                                            _ => false,
-                                        }
-                                    } else {
-                                        false
+                if let ty::Adt(adt, _) = rcvr_ty.kind() {
+                    let mut inherent_impls_candidate = self
+                        .tcx
+                        .inherent_impls(adt.did())
+                        .iter()
+                        .copied()
+                        .filter(|def_id| {
+                            if let Some(assoc) = self.associated_value(*def_id, item_name) {
+                                // Check for both mode is the same so we avoid suggesting
+                                // incorrect associated item.
+                                match (mode, assoc.fn_has_self_parameter, source) {
+                                    (Mode::MethodCall, true, SelfSource::MethodCall(_)) => {
+                                        // We check that the suggest type is actually
+                                        // different from the received one
+                                        // So we avoid suggestion method with Box<Self>
+                                        // for instance
+                                        self.tcx.at(span).type_of(*def_id) != rcvr_ty
+                                            && self.tcx.at(span).type_of(*def_id) != rcvr_ty
                                     }
-                                })
-                                .collect::<Vec<_>>();
-                            if !inherent_impls_candidate.is_empty() {
-                                inherent_impls_candidate.sort();
-                                inherent_impls_candidate.dedup();
-
-                                // number of type to shows at most.
-                                let limit = if inherent_impls_candidate.len() == 5 { 5 } else { 4 };
-                                let type_candidates = inherent_impls_candidate
-                                    .iter()
-                                    .take(limit)
-                                    .map(|impl_item| {
-                                        format!("- `{}`", self.tcx.at(span).type_of(*impl_item))
-                                    })
-                                    .collect::<Vec<_>>()
-                                    .join("\n");
-                                let additional_types = if inherent_impls_candidate.len() > limit {
-                                    format!(
-                                        "\nand {} more types",
-                                        inherent_impls_candidate.len() - limit
-                                    )
-                                } else {
-                                    "".to_string()
-                                };
-                                err.note(&format!(
-                                    "the {item_kind} was found for\n{}{}",
-                                    type_candidates, additional_types
-                                ));
+                                    (Mode::Path, false, _) => true,
+                                    _ => false,
+                                }
+                            } else {
+                                false
                             }
-                        }
-                    } else {
-                        let ty_str = if ty_str.len() > 50 {
-                            String::new()
+                        })
+                        .collect::<Vec<_>>();
+                    if !inherent_impls_candidate.is_empty() {
+                        inherent_impls_candidate.sort();
+                        inherent_impls_candidate.dedup();
+
+                        // number of type to shows at most.
+                        let limit = if inherent_impls_candidate.len() == 5 { 5 } else { 4 };
+                        let type_candidates = inherent_impls_candidate
+                            .iter()
+                            .take(limit)
+                            .map(|impl_item| {
+                                format!("- `{}`", self.tcx.at(span).type_of(*impl_item))
+                            })
+                            .collect::<Vec<_>>()
+                            .join("\n");
+                        let additional_types = if inherent_impls_candidate.len() > limit {
+                            format!("\nand {} more types", inherent_impls_candidate.len() - limit)
                         } else {
-                            format!("on `{ty_str}` ")
+                            "".to_string()
                         };
-                        err.span_label(span, format!(
-                            "{item_kind} cannot be called {ty_str}due to unsatisfied trait bounds"
+                        err.note(&format!(
+                            "the {item_kind} was found for\n{}{}",
+                            type_candidates, additional_types
                         ));
                     }
-                };
-
-                // If the method name is the name of a field with a function or closure type,
-                // give a helping note that it has to be called as `(x.f)(...)`.
-                if let SelfSource::MethodCall(expr) = source {
-                    if !self.suggest_calling_field_as_fn(span, rcvr_ty, expr, item_name, &mut err)
-                        && lev_candidate.is_none()
-                        && !custom_span_label
-                    {
-                        label_span_not_found(&mut err);
-                    }
-                } else if !custom_span_label {
-                    label_span_not_found(&mut err);
                 }
+            } else {
+                let ty_str =
+                    if ty_str.len() > 50 { String::new() } else { format!("on `{ty_str}` ") };
+                err.span_label(
+                    span,
+                    format!("{item_kind} cannot be called {ty_str}due to unsatisfied trait bounds"),
+                );
+            }
+        };
 
-                // Don't suggest (for example) `expr.field.clone()` if `expr.clone()`
-                // can't be called due to `typeof(expr): Clone` not holding.
-                if unsatisfied_predicates.is_empty() {
-                    self.suggest_calling_method_on_field(
-                        &mut err, source, span, rcvr_ty, item_name,
-                    );
-                }
+        // If the method name is the name of a field with a function or closure type,
+        // give a helping note that it has to be called as `(x.f)(...)`.
+        if let SelfSource::MethodCall(expr) = source {
+            if !self.suggest_calling_field_as_fn(span, rcvr_ty, expr, item_name, &mut err)
+                && lev_candidate.is_none()
+                && !custom_span_label
+            {
+                label_span_not_found(&mut err);
+            }
+        } else if !custom_span_label {
+            label_span_not_found(&mut err);
+        }
 
-                self.check_for_inner_self(&mut err, source, rcvr_ty, item_name);
+        // Don't suggest (for example) `expr.field.clone()` if `expr.clone()`
+        // can't be called due to `typeof(expr): Clone` not holding.
+        if unsatisfied_predicates.is_empty() {
+            self.suggest_calling_method_on_field(&mut err, source, span, rcvr_ty, item_name);
+        }
 
-                bound_spans.sort();
-                bound_spans.dedup();
-                for (span, msg) in bound_spans.into_iter() {
-                    err.span_label(span, &msg);
-                }
+        self.check_for_inner_self(&mut err, source, rcvr_ty, item_name);
+
+        bound_spans.sort();
+        bound_spans.dedup();
+        for (span, msg) in bound_spans.into_iter() {
+            err.span_label(span, &msg);
+        }
 
-                if rcvr_ty.is_numeric() && rcvr_ty.is_fresh() || restrict_type_params {
+        if rcvr_ty.is_numeric() && rcvr_ty.is_fresh() || restrict_type_params {
+        } else {
+            self.suggest_traits_to_import(
+                &mut err,
+                span,
+                rcvr_ty,
+                item_name,
+                args.map(|(_, args)| args.len() + 1),
+                source,
+                no_match_data.out_of_scope_traits.clone(),
+                &unsatisfied_predicates,
+                &static_candidates,
+                unsatisfied_bounds,
+            );
+        }
+
+        // Don't emit a suggestion if we found an actual method
+        // that had unsatisfied trait bounds
+        if unsatisfied_predicates.is_empty() && rcvr_ty.is_enum() {
+            let adt_def = rcvr_ty.ty_adt_def().expect("enum is not an ADT");
+            if let Some(suggestion) = lev_distance::find_best_match_for_name(
+                &adt_def.variants().iter().map(|s| s.name).collect::<Vec<_>>(),
+                item_name.name,
+                None,
+            ) {
+                err.span_suggestion(
+                    span,
+                    "there is a variant with a similar name",
+                    suggestion,
+                    Applicability::MaybeIncorrect,
+                );
+            }
+        }
+
+        if item_name.name == sym::as_str && rcvr_ty.peel_refs().is_str() {
+            let msg = "remove this method call";
+            let mut fallback_span = true;
+            if let SelfSource::MethodCall(expr) = source {
+                let call_expr = self.tcx.hir().expect_expr(self.tcx.hir().parent_id(expr.hir_id));
+                if let Some(span) = call_expr.span.trim_start(expr.span) {
+                    err.span_suggestion(span, msg, "", Applicability::MachineApplicable);
+                    fallback_span = false;
+                }
+            }
+            if fallback_span {
+                err.span_label(span, msg);
+            }
+        } else if let Some(lev_candidate) = lev_candidate {
+            // Don't emit a suggestion if we found an actual method
+            // that had unsatisfied trait bounds
+            if unsatisfied_predicates.is_empty() {
+                let def_kind = lev_candidate.kind.as_def_kind();
+                // Methods are defined within the context of a struct and their first parameter is always self,
+                // which represents the instance of the struct the method is being called on
+                // Associated functions don’t take self as a parameter and
+                // they are not methods because they don’t have an instance of the struct to work with.
+                if def_kind == DefKind::AssocFn && lev_candidate.fn_has_self_parameter {
+                    err.span_suggestion(
+                        span,
+                        "there is a method with a similar name",
+                        lev_candidate.name,
+                        Applicability::MaybeIncorrect,
+                    );
                 } else {
-                    self.suggest_traits_to_import(
-                        &mut err,
+                    err.span_suggestion(
                         span,
-                        rcvr_ty,
-                        item_name,
-                        args.map(|(_, args)| args.len() + 1),
-                        source,
-                        out_of_scope_traits,
-                        &unsatisfied_predicates,
-                        &static_candidates,
-                        unsatisfied_bounds,
+                        &format!(
+                            "there is {} {} with a similar name",
+                            def_kind.article(),
+                            def_kind.descr(lev_candidate.def_id),
+                        ),
+                        lev_candidate.name,
+                        Applicability::MaybeIncorrect,
                     );
                 }
+            }
+        }
 
-                // Don't emit a suggestion if we found an actual method
-                // that had unsatisfied trait bounds
-                if unsatisfied_predicates.is_empty() && rcvr_ty.is_enum() {
-                    let adt_def = rcvr_ty.ty_adt_def().expect("enum is not an ADT");
-                    if let Some(suggestion) = lev_distance::find_best_match_for_name(
-                        &adt_def.variants().iter().map(|s| s.name).collect::<Vec<_>>(),
-                        item_name.name,
-                        None,
-                    ) {
-                        err.span_suggestion(
-                            span,
-                            "there is a variant with a similar name",
-                            suggestion,
-                            Applicability::MaybeIncorrect,
-                        );
-                    }
-                }
-
-                if item_name.name == sym::as_str && rcvr_ty.peel_refs().is_str() {
-                    let msg = "remove this method call";
-                    let mut fallback_span = true;
-                    if let SelfSource::MethodCall(expr) = source {
-                        let call_expr =
-                            self.tcx.hir().expect_expr(self.tcx.hir().get_parent_node(expr.hir_id));
-                        if let Some(span) = call_expr.span.trim_start(expr.span) {
-                            err.span_suggestion(span, msg, "", Applicability::MachineApplicable);
-                            fallback_span = false;
-                        }
-                    }
-                    if fallback_span {
-                        err.span_label(span, msg);
-                    }
-                } else if let Some(lev_candidate) = lev_candidate {
-                    // Don't emit a suggestion if we found an actual method
-                    // that had unsatisfied trait bounds
-                    if unsatisfied_predicates.is_empty() {
-                        let def_kind = lev_candidate.kind.as_def_kind();
-                        // Methods are defined within the context of a struct and their first parameter is always self,
-                        // which represents the instance of the struct the method is being called on
-                        // Associated functions don’t take self as a parameter and
-                        // they are not methods because they don’t have an instance of the struct to work with.
-                        if def_kind == DefKind::AssocFn && lev_candidate.fn_has_self_parameter {
-                            err.span_suggestion(
-                                span,
-                                "there is a method with a similar name",
-                                lev_candidate.name,
-                                Applicability::MaybeIncorrect,
-                            );
-                        } else {
-                            err.span_suggestion(
-                                span,
-                                &format!(
-                                    "there is {} {} with a similar name",
-                                    def_kind.article(),
-                                    def_kind.descr(lev_candidate.def_id),
-                                ),
-                                lev_candidate.name,
-                                Applicability::MaybeIncorrect,
-                            );
-                        }
-                    }
-                }
+        self.check_for_deref_method(&mut err, source, rcvr_ty, item_name);
+        return Some(err);
+    }
 
-                self.check_for_deref_method(&mut err, source, rcvr_ty, item_name);
+    fn note_candidates_on_method_error(
+        &self,
+        rcvr_ty: Ty<'tcx>,
+        item_name: Ident,
+        args: Option<(&'tcx hir::Expr<'tcx>, &'tcx [hir::Expr<'tcx>])>,
+        span: Span,
+        err: &mut Diagnostic,
+        sources: &mut Vec<CandidateSource>,
+        sugg_span: Option<Span>,
+    ) {
+        sources.sort();
+        sources.dedup();
+        // Dynamic limit to avoid hiding just one candidate, which is silly.
+        let limit = if sources.len() == 5 { 5 } else { 4 };
+
+        for (idx, source) in sources.iter().take(limit).enumerate() {
+            match *source {
+                CandidateSource::Impl(impl_did) => {
+                    // Provide the best span we can. Use the item, if local to crate, else
+                    // the impl, if local to crate (item may be defaulted), else nothing.
+                    let Some(item) = self.associated_value(impl_did, item_name).or_else(|| {
+                        let impl_trait_ref = self.tcx.impl_trait_ref(impl_did)?;
+                        self.associated_value(impl_trait_ref.def_id, item_name)
+                    }) else {
+                        continue;
+                    };
 
-                return Some(err);
-            }
+                    let note_span = if item.def_id.is_local() {
+                        Some(self.tcx.def_span(item.def_id))
+                    } else if impl_did.is_local() {
+                        Some(self.tcx.def_span(impl_did))
+                    } else {
+                        None
+                    };
 
-            MethodError::Ambiguity(mut sources) => {
-                let mut err = struct_span_err!(
-                    self.sess(),
-                    item_name.span,
-                    E0034,
-                    "multiple applicable items in scope"
-                );
-                err.span_label(item_name.span, format!("multiple `{}` found", item_name));
+                    let impl_ty = self.tcx.at(span).type_of(impl_did);
 
-                report_candidates(span, &mut err, &mut sources, Some(sugg_span));
-                err.emit();
-            }
+                    let insertion = match self.tcx.impl_trait_ref(impl_did) {
+                        None => String::new(),
+                        Some(trait_ref) => {
+                            format!(" of the trait `{}`", self.tcx.def_path_str(trait_ref.def_id))
+                        }
+                    };
 
-            MethodError::PrivateMatch(kind, def_id, out_of_scope_traits) => {
-                let kind = kind.descr(def_id);
-                let mut err = struct_span_err!(
-                    self.tcx.sess,
-                    item_name.span,
-                    E0624,
-                    "{} `{}` is private",
-                    kind,
-                    item_name
-                );
-                err.span_label(item_name.span, &format!("private {}", kind));
-                let sp = self
-                    .tcx
-                    .hir()
-                    .span_if_local(def_id)
-                    .unwrap_or_else(|| self.tcx.def_span(def_id));
-                err.span_label(sp, &format!("private {} defined here", kind));
-                self.suggest_valid_traits(&mut err, out_of_scope_traits);
-                err.emit();
-            }
+                    let (note_str, idx) = if sources.len() > 1 {
+                        (
+                            format!(
+                                "candidate #{} is defined in an impl{} for the type `{}`",
+                                idx + 1,
+                                insertion,
+                                impl_ty,
+                            ),
+                            Some(idx + 1),
+                        )
+                    } else {
+                        (
+                            format!(
+                                "the candidate is defined in an impl{} for the type `{}`",
+                                insertion, impl_ty,
+                            ),
+                            None,
+                        )
+                    };
+                    if let Some(note_span) = note_span {
+                        // We have a span pointing to the method. Show note with snippet.
+                        err.span_note(note_span, &note_str);
+                    } else {
+                        err.note(&note_str);
+                    }
+                    if let Some(sugg_span) = sugg_span
+                        && let Some(trait_ref) = self.tcx.impl_trait_ref(impl_did) {
+                        let path = self.tcx.def_path_str(trait_ref.def_id);
 
-            MethodError::IllegalSizedBound(candidates, needs_mut, bound_span) => {
-                let msg = format!("the `{}` method cannot be invoked on a trait object", item_name);
-                let mut err = self.sess().struct_span_err(span, &msg);
-                err.span_label(bound_span, "this has a `Sized` requirement");
-                if !candidates.is_empty() {
-                    let help = format!(
-                        "{an}other candidate{s} {were} found in the following trait{s}, perhaps \
-                         add a `use` for {one_of_them}:",
-                        an = if candidates.len() == 1 { "an" } else { "" },
-                        s = pluralize!(candidates.len()),
-                        were = pluralize!("was", candidates.len()),
-                        one_of_them = if candidates.len() == 1 { "it" } else { "one_of_them" },
-                    );
-                    self.suggest_use_candidates(&mut err, help, candidates);
+                        let ty = match item.kind {
+                            ty::AssocKind::Const | ty::AssocKind::Type => rcvr_ty,
+                            ty::AssocKind::Fn => self
+                                .tcx
+                                .fn_sig(item.def_id)
+                                .inputs()
+                                .skip_binder()
+                                .get(0)
+                                .filter(|ty| ty.is_region_ptr() && !rcvr_ty.is_region_ptr())
+                                .copied()
+                                .unwrap_or(rcvr_ty),
+                        };
+                        print_disambiguation_help(
+                            item_name,
+                            args,
+                            err,
+                            path,
+                            ty,
+                            item.kind,
+                            item.def_id,
+                            sugg_span,
+                            idx,
+                            self.tcx.sess.source_map(),
+                            item.fn_has_self_parameter,
+                        );
+                    }
                 }
-                if let ty::Ref(region, t_type, mutability) = rcvr_ty.kind() {
-                    if needs_mut {
-                        let trait_type = self.tcx.mk_ref(
-                            *region,
-                            ty::TypeAndMut { ty: *t_type, mutbl: mutability.invert() },
+                CandidateSource::Trait(trait_did) => {
+                    let Some(item) = self.associated_value(trait_did, item_name) else { continue };
+                    let item_span = self.tcx.def_span(item.def_id);
+                    let idx = if sources.len() > 1 {
+                        let msg = &format!(
+                            "candidate #{} is defined in the trait `{}`",
+                            idx + 1,
+                            self.tcx.def_path_str(trait_did)
+                        );
+                        err.span_note(item_span, msg);
+                        Some(idx + 1)
+                    } else {
+                        let msg = &format!(
+                            "the candidate is defined in the trait `{}`",
+                            self.tcx.def_path_str(trait_did)
+                        );
+                        err.span_note(item_span, msg);
+                        None
+                    };
+                    if let Some(sugg_span) = sugg_span {
+                        let path = self.tcx.def_path_str(trait_did);
+                        print_disambiguation_help(
+                            item_name,
+                            args,
+                            err,
+                            path,
+                            rcvr_ty,
+                            item.kind,
+                            item.def_id,
+                            sugg_span,
+                            idx,
+                            self.tcx.sess.source_map(),
+                            item.fn_has_self_parameter,
                         );
-                        err.note(&format!("you need `{}` instead of `{}`", trait_type, rcvr_ty));
                     }
                 }
-                err.emit();
             }
-
-            MethodError::BadReturnType => bug!("no return type expectations but got BadReturnType"),
         }
-        None
+        if sources.len() > limit {
+            err.note(&format!("and {} others", sources.len() - limit));
+        }
     }
 
     /// Suggest calling `Ty::method` if `.method()` isn't found because the method
@@ -1265,7 +1300,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         Applicability::MachineApplicable,
                     );
                 } else {
-                    let call_expr = tcx.hir().expect_expr(tcx.hir().get_parent_node(expr.hir_id));
+                    let call_expr = tcx.hir().expect_expr(tcx.hir().parent_id(expr.hir_id));
 
                     if let Some(span) = call_expr.span.trim_start(item_name.span) {
                         err.span_suggestion(
@@ -1447,7 +1482,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         let filename = tcx.sess.source_map().span_to_filename(span);
 
                         let parent_node =
-                            self.tcx.hir().get(self.tcx.hir().get_parent_node(hir_id));
+                            self.tcx.hir().get_parent(hir_id);
                         let msg = format!(
                             "you must specify a type for this binding, like `{}`",
                             concrete_type,
@@ -1520,7 +1555,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let mut visitor = LetVisitor { result: None, ident_name: seg1.ident.name };
         visitor.visit_body(&body);
 
-        let parent = self.tcx.hir().get_parent_node(seg1.hir_id);
+        let parent = self.tcx.hir().parent_id(seg1.hir_id);
         if let Some(Node::Expr(call_expr)) = self.tcx.hir().find(parent)
             && let Some(expr) = visitor.result
             && let Some(self_ty) = self.node_ty_opt(expr.hir_id)
@@ -1558,7 +1593,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         && let Some((fields, substs)) =
             self.get_field_candidates_considering_privacy(span, actual, mod_id)
         {
-            let call_expr = self.tcx.hir().expect_expr(self.tcx.hir().get_parent_node(expr.hir_id));
+            let call_expr = self.tcx.hir().expect_expr(self.tcx.hir().parent_id(expr.hir_id));
 
             let lang_items = self.tcx.lang_items();
             let never_mention_traits = [
@@ -1628,7 +1663,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     ) {
         let tcx = self.tcx;
         let SelfSource::MethodCall(expr) = source else { return; };
-        let call_expr = tcx.hir().expect_expr(tcx.hir().get_parent_node(expr.hir_id));
+        let call_expr = tcx.hir().expect_expr(tcx.hir().parent_id(expr.hir_id));
 
         let ty::Adt(kind, substs) = actual.kind() else { return; };
         match kind.adt_kind() {
@@ -2589,7 +2624,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             return false;
         }
 
-        let parent = self.tcx.hir().get_parent_node(expr.hir_id);
+        let parent = self.tcx.hir().parent_id(expr.hir_id);
         if  let Some(Node::Expr(call_expr)) = self.tcx.hir().find(parent) &&
             let hir::ExprKind::MethodCall(
                 hir::PathSegment { ident: method_name, .. },
diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs
index 28e959b7c6a..e0304fa2d3b 100644
--- a/compiler/rustc_hir_typeck/src/pat.rs
+++ b/compiler/rustc_hir_typeck/src/pat.rs
@@ -553,6 +553,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             (lhs, Some((true, rhs_ty, rhs_sp))) => one_side_err(rhs_sp, rhs_ty, lhs),
             _ => span_bug!(span, "Impossible, verified above."),
         }
+        if (lhs, rhs).references_error() {
+            err.downgrade_to_delayed_bug();
+        }
         if self.tcx.sess.teach(&err.get_code().unwrap()) {
             err.note(
                 "In a match expression, only numbers and characters can be matched \
@@ -692,7 +695,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let tcx = self.tcx;
         if let PatKind::Ref(inner, mutbl) = pat.kind
         && let PatKind::Binding(_, _, binding, ..) = inner.kind {
-            let binding_parent_id = tcx.hir().get_parent_node(pat.hir_id);
+            let binding_parent_id = tcx.hir().parent_id(pat.hir_id);
             let binding_parent = tcx.hir().get(binding_parent_id);
             debug!(?inner, ?pat, ?binding_parent);
 
@@ -936,7 +939,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         res.descr(),
                     ),
                 );
-                match self.tcx.hir().get(self.tcx.hir().get_parent_node(pat.hir_id)) {
+                match self.tcx.hir().get_parent(pat.hir_id) {
                     hir::Node::PatField(..) => {
                         e.span_suggestion_verbose(
                             ident.span.shrink_to_hi(),
diff --git a/compiler/rustc_index/src/bit_set.rs b/compiler/rustc_index/src/bit_set.rs
index 686cb6dac49..15179392c88 100644
--- a/compiler/rustc_index/src/bit_set.rs
+++ b/compiler/rustc_index/src/bit_set.rs
@@ -1091,7 +1091,7 @@ impl<T: Idx> ToString for BitSet<T> {
                 assert!(mask <= 0xFF);
                 let byte = word & mask;
 
-                result.push_str(&format!("{}{:02x}", sep, byte));
+                result.push_str(&format!("{sep}{byte:02x}"));
 
                 if remain <= 8 {
                     break;
diff --git a/compiler/rustc_index/src/interval.rs b/compiler/rustc_index/src/interval.rs
index 3592fb33077..d809740c6ab 100644
--- a/compiler/rustc_index/src/interval.rs
+++ b/compiler/rustc_index/src/interval.rs
@@ -135,10 +135,7 @@ impl<I: Idx> IntervalSet<I> {
         };
         debug_assert!(
             self.check_invariants(),
-            "wrong intervals after insert {:?}..={:?} to {:?}",
-            start,
-            end,
-            self
+            "wrong intervals after insert {start:?}..={end:?} to {self:?}"
         );
         result
     }
diff --git a/compiler/rustc_infer/src/errors/mod.rs b/compiler/rustc_infer/src/errors/mod.rs
index 4430acf34db..033a1842edb 100644
--- a/compiler/rustc_infer/src/errors/mod.rs
+++ b/compiler/rustc_infer/src/errors/mod.rs
@@ -1,15 +1,18 @@
 use hir::GenericParamKind;
 use rustc_errors::{
     fluent, AddToDiagnostic, Applicability, Diagnostic, DiagnosticMessage, DiagnosticStyledString,
-    MultiSpan, SubdiagnosticMessage,
+    IntoDiagnosticArg, MultiSpan, SubdiagnosticMessage,
 };
 use rustc_hir as hir;
-use rustc_hir::{FnRetTy, Ty};
+use rustc_hir::FnRetTy;
 use rustc_macros::{Diagnostic, Subdiagnostic};
-use rustc_middle::ty::{Region, TyCtxt};
+use rustc_middle::ty::print::TraitRefPrintOnlyTraitPath;
+use rustc_middle::ty::{Binder, FnSig, Region, Ty, TyCtxt};
 use rustc_span::symbol::kw;
+use rustc_span::Symbol;
 use rustc_span::{symbol::Ident, BytePos, Span};
 
+use crate::infer::error_reporting::nice_region_error::placeholder_error::Highlighted;
 use crate::infer::error_reporting::{
     need_type_info::{GeneratorKindAsDiagArg, UnderspecifiedArgKind},
     ObligationCauseAsDiagArg,
@@ -357,8 +360,8 @@ impl AddToDiagnostic for LifetimeMismatchLabels {
 pub struct AddLifetimeParamsSuggestion<'a> {
     pub tcx: TyCtxt<'a>,
     pub sub: Region<'a>,
-    pub ty_sup: &'a Ty<'a>,
-    pub ty_sub: &'a Ty<'a>,
+    pub ty_sup: &'a hir::Ty<'a>,
+    pub ty_sub: &'a hir::Ty<'a>,
     pub add_note: bool,
 }
 
@@ -520,3 +523,411 @@ pub struct MismatchedStaticLifetime<'a> {
     #[subdiagnostic]
     pub implicit_static_lifetimes: Vec<ImplicitStaticLifetimeSubdiag>,
 }
+
+#[derive(Diagnostic)]
+pub enum ExplicitLifetimeRequired<'a> {
+    #[diag(infer_explicit_lifetime_required_with_ident, code = "E0621")]
+    WithIdent {
+        #[primary_span]
+        #[label]
+        span: Span,
+        simple_ident: Ident,
+        named: String,
+        #[suggestion(
+            infer_explicit_lifetime_required_sugg_with_ident,
+            code = "{new_ty}",
+            applicability = "unspecified"
+        )]
+        new_ty_span: Span,
+        #[skip_arg]
+        new_ty: Ty<'a>,
+    },
+    #[diag(infer_explicit_lifetime_required_with_param_type, code = "E0621")]
+    WithParamType {
+        #[primary_span]
+        #[label]
+        span: Span,
+        named: String,
+        #[suggestion(
+            infer_explicit_lifetime_required_sugg_with_param_type,
+            code = "{new_ty}",
+            applicability = "unspecified"
+        )]
+        new_ty_span: Span,
+        #[skip_arg]
+        new_ty: Ty<'a>,
+    },
+}
+
+pub enum TyOrSig<'tcx> {
+    Ty(Highlighted<'tcx, Ty<'tcx>>),
+    ClosureSig(Highlighted<'tcx, Binder<'tcx, FnSig<'tcx>>>),
+}
+
+impl IntoDiagnosticArg for TyOrSig<'_> {
+    fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> {
+        match self {
+            TyOrSig::Ty(ty) => ty.into_diagnostic_arg(),
+            TyOrSig::ClosureSig(sig) => sig.into_diagnostic_arg(),
+        }
+    }
+}
+
+#[derive(Subdiagnostic)]
+pub enum ActualImplExplNotes<'tcx> {
+    #[note(infer_actual_impl_expl_expected_signature_two)]
+    ExpectedSignatureTwo {
+        leading_ellipsis: bool,
+        ty_or_sig: TyOrSig<'tcx>,
+        trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
+        lifetime_1: usize,
+        lifetime_2: usize,
+    },
+    #[note(infer_actual_impl_expl_expected_signature_any)]
+    ExpectedSignatureAny {
+        leading_ellipsis: bool,
+        ty_or_sig: TyOrSig<'tcx>,
+        trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
+        lifetime_1: usize,
+    },
+    #[note(infer_actual_impl_expl_expected_signature_some)]
+    ExpectedSignatureSome {
+        leading_ellipsis: bool,
+        ty_or_sig: TyOrSig<'tcx>,
+        trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
+        lifetime_1: usize,
+    },
+    #[note(infer_actual_impl_expl_expected_signature_nothing)]
+    ExpectedSignatureNothing {
+        leading_ellipsis: bool,
+        ty_or_sig: TyOrSig<'tcx>,
+        trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
+    },
+    #[note(infer_actual_impl_expl_expected_passive_two)]
+    ExpectedPassiveTwo {
+        leading_ellipsis: bool,
+        ty_or_sig: TyOrSig<'tcx>,
+        trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
+        lifetime_1: usize,
+        lifetime_2: usize,
+    },
+    #[note(infer_actual_impl_expl_expected_passive_any)]
+    ExpectedPassiveAny {
+        leading_ellipsis: bool,
+        ty_or_sig: TyOrSig<'tcx>,
+        trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
+        lifetime_1: usize,
+    },
+    #[note(infer_actual_impl_expl_expected_passive_some)]
+    ExpectedPassiveSome {
+        leading_ellipsis: bool,
+        ty_or_sig: TyOrSig<'tcx>,
+        trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
+        lifetime_1: usize,
+    },
+    #[note(infer_actual_impl_expl_expected_passive_nothing)]
+    ExpectedPassiveNothing {
+        leading_ellipsis: bool,
+        ty_or_sig: TyOrSig<'tcx>,
+        trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
+    },
+    #[note(infer_actual_impl_expl_expected_other_two)]
+    ExpectedOtherTwo {
+        leading_ellipsis: bool,
+        ty_or_sig: TyOrSig<'tcx>,
+        trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
+        lifetime_1: usize,
+        lifetime_2: usize,
+    },
+    #[note(infer_actual_impl_expl_expected_other_any)]
+    ExpectedOtherAny {
+        leading_ellipsis: bool,
+        ty_or_sig: TyOrSig<'tcx>,
+        trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
+        lifetime_1: usize,
+    },
+    #[note(infer_actual_impl_expl_expected_other_some)]
+    ExpectedOtherSome {
+        leading_ellipsis: bool,
+        ty_or_sig: TyOrSig<'tcx>,
+        trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
+        lifetime_1: usize,
+    },
+    #[note(infer_actual_impl_expl_expected_other_nothing)]
+    ExpectedOtherNothing {
+        leading_ellipsis: bool,
+        ty_or_sig: TyOrSig<'tcx>,
+        trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
+    },
+    #[note(infer_actual_impl_expl_but_actually_implements_trait)]
+    ButActuallyImplementsTrait {
+        trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
+        has_lifetime: bool,
+        lifetime: usize,
+    },
+    #[note(infer_actual_impl_expl_but_actually_implemented_for_ty)]
+    ButActuallyImplementedForTy {
+        trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
+        has_lifetime: bool,
+        lifetime: usize,
+        ty: String,
+    },
+    #[note(infer_actual_impl_expl_but_actually_ty_implements)]
+    ButActuallyTyImplements {
+        trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
+        has_lifetime: bool,
+        lifetime: usize,
+        ty: String,
+    },
+}
+
+pub enum ActualImplExpectedKind {
+    Signature,
+    Passive,
+    Other,
+}
+
+pub enum ActualImplExpectedLifetimeKind {
+    Two,
+    Any,
+    Some,
+    Nothing,
+}
+
+impl<'tcx> ActualImplExplNotes<'tcx> {
+    pub fn new_expected(
+        kind: ActualImplExpectedKind,
+        lt_kind: ActualImplExpectedLifetimeKind,
+        leading_ellipsis: bool,
+        ty_or_sig: TyOrSig<'tcx>,
+        trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
+        lifetime_1: usize,
+        lifetime_2: usize,
+    ) -> Self {
+        match (kind, lt_kind) {
+            (ActualImplExpectedKind::Signature, ActualImplExpectedLifetimeKind::Two) => {
+                Self::ExpectedSignatureTwo {
+                    leading_ellipsis,
+                    ty_or_sig,
+                    trait_path,
+                    lifetime_1,
+                    lifetime_2,
+                }
+            }
+            (ActualImplExpectedKind::Signature, ActualImplExpectedLifetimeKind::Any) => {
+                Self::ExpectedSignatureAny { leading_ellipsis, ty_or_sig, trait_path, lifetime_1 }
+            }
+            (ActualImplExpectedKind::Signature, ActualImplExpectedLifetimeKind::Some) => {
+                Self::ExpectedSignatureSome { leading_ellipsis, ty_or_sig, trait_path, lifetime_1 }
+            }
+            (ActualImplExpectedKind::Signature, ActualImplExpectedLifetimeKind::Nothing) => {
+                Self::ExpectedSignatureNothing { leading_ellipsis, ty_or_sig, trait_path }
+            }
+            (ActualImplExpectedKind::Passive, ActualImplExpectedLifetimeKind::Two) => {
+                Self::ExpectedPassiveTwo {
+                    leading_ellipsis,
+                    ty_or_sig,
+                    trait_path,
+                    lifetime_1,
+                    lifetime_2,
+                }
+            }
+            (ActualImplExpectedKind::Passive, ActualImplExpectedLifetimeKind::Any) => {
+                Self::ExpectedPassiveAny { leading_ellipsis, ty_or_sig, trait_path, lifetime_1 }
+            }
+            (ActualImplExpectedKind::Passive, ActualImplExpectedLifetimeKind::Some) => {
+                Self::ExpectedPassiveSome { leading_ellipsis, ty_or_sig, trait_path, lifetime_1 }
+            }
+            (ActualImplExpectedKind::Passive, ActualImplExpectedLifetimeKind::Nothing) => {
+                Self::ExpectedPassiveNothing { leading_ellipsis, ty_or_sig, trait_path }
+            }
+            (ActualImplExpectedKind::Other, ActualImplExpectedLifetimeKind::Two) => {
+                Self::ExpectedOtherTwo {
+                    leading_ellipsis,
+                    ty_or_sig,
+                    trait_path,
+                    lifetime_1,
+                    lifetime_2,
+                }
+            }
+            (ActualImplExpectedKind::Other, ActualImplExpectedLifetimeKind::Any) => {
+                Self::ExpectedOtherAny { leading_ellipsis, ty_or_sig, trait_path, lifetime_1 }
+            }
+            (ActualImplExpectedKind::Other, ActualImplExpectedLifetimeKind::Some) => {
+                Self::ExpectedOtherSome { leading_ellipsis, ty_or_sig, trait_path, lifetime_1 }
+            }
+            (ActualImplExpectedKind::Other, ActualImplExpectedLifetimeKind::Nothing) => {
+                Self::ExpectedOtherNothing { leading_ellipsis, ty_or_sig, trait_path }
+            }
+        }
+    }
+}
+
+#[derive(Diagnostic)]
+#[diag(infer_trait_placeholder_mismatch)]
+pub struct TraitPlaceholderMismatch<'tcx> {
+    #[primary_span]
+    pub span: Span,
+    #[label(label_satisfy)]
+    pub satisfy_span: Option<Span>,
+    #[label(label_where)]
+    pub where_span: Option<Span>,
+    #[label(label_dup)]
+    pub dup_span: Option<Span>,
+    pub def_id: String,
+    pub trait_def_id: String,
+
+    #[subdiagnostic]
+    pub actual_impl_expl_notes: Vec<ActualImplExplNotes<'tcx>>,
+}
+
+pub struct ConsiderBorrowingParamHelp {
+    pub spans: Vec<Span>,
+}
+
+impl AddToDiagnostic for ConsiderBorrowingParamHelp {
+    fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, f: F)
+    where
+        F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
+    {
+        let mut type_param_span: MultiSpan = self.spans.clone().into();
+        for &span in &self.spans {
+            // Seems like we can't call f() here as Into<DiagnosticMessage> is required
+            type_param_span.push_span_label(span, fluent::infer_tid_consider_borrowing);
+        }
+        let msg = f(diag, fluent::infer_tid_param_help.into());
+        diag.span_help(type_param_span, msg);
+    }
+}
+
+#[derive(Subdiagnostic)]
+#[help(infer_tid_rel_help)]
+pub struct RelationshipHelp;
+
+#[derive(Diagnostic)]
+#[diag(infer_trait_impl_diff)]
+pub struct TraitImplDiff {
+    #[primary_span]
+    #[label(found)]
+    pub sp: Span,
+    #[label(expected)]
+    pub trait_sp: Span,
+    #[note(expected_found)]
+    pub note: (),
+    #[subdiagnostic]
+    pub param_help: ConsiderBorrowingParamHelp,
+    #[subdiagnostic]
+    // Seems like subdiagnostics are always pushed to the end, so this one
+    // also has to be a subdiagnostic to maintain order.
+    pub rel_help: Option<RelationshipHelp>,
+    pub expected: String,
+    pub found: String,
+}
+
+pub struct DynTraitConstraintSuggestion {
+    pub span: Span,
+    pub ident: Ident,
+}
+
+impl AddToDiagnostic for DynTraitConstraintSuggestion {
+    fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, f: F)
+    where
+        F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
+    {
+        let mut multi_span: MultiSpan = vec![self.span].into();
+        multi_span.push_span_label(self.span, fluent::infer_dtcs_has_lifetime_req_label);
+        multi_span.push_span_label(self.ident.span, fluent::infer_dtcs_introduces_requirement);
+        let msg = f(diag, fluent::infer_dtcs_has_req_note.into());
+        diag.span_note(multi_span, msg);
+        let msg = f(diag, fluent::infer_dtcs_suggestion.into());
+        diag.span_suggestion_verbose(
+            self.span.shrink_to_hi(),
+            msg,
+            " + '_",
+            Applicability::MaybeIncorrect,
+        );
+    }
+}
+
+#[derive(Diagnostic)]
+#[diag(infer_but_calling_introduces, code = "E0772")]
+pub struct ButCallingIntroduces {
+    #[label(label1)]
+    pub param_ty_span: Span,
+    #[primary_span]
+    #[label(label2)]
+    pub cause_span: Span,
+
+    pub has_param_name: bool,
+    pub param_name: String,
+    pub has_lifetime: bool,
+    pub lifetime: String,
+    pub assoc_item: Symbol,
+    pub has_impl_path: bool,
+    pub impl_path: String,
+}
+
+pub struct ReqIntroducedLocations {
+    pub span: MultiSpan,
+    pub spans: Vec<Span>,
+    pub fn_decl_span: Span,
+    pub cause_span: Span,
+    pub add_label: bool,
+}
+
+impl AddToDiagnostic for ReqIntroducedLocations {
+    fn add_to_diagnostic_with<F>(mut self, diag: &mut Diagnostic, f: F)
+    where
+        F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
+    {
+        for sp in self.spans {
+            self.span.push_span_label(sp, fluent::infer_ril_introduced_here);
+        }
+
+        if self.add_label {
+            self.span.push_span_label(self.fn_decl_span, fluent::infer_ril_introduced_by);
+        }
+        self.span.push_span_label(self.cause_span, fluent::infer_ril_because_of);
+        let msg = f(diag, fluent::infer_ril_static_introduced_by.into());
+        diag.span_note(self.span, msg);
+    }
+}
+
+pub struct MoreTargeted {
+    pub ident: Symbol,
+}
+
+impl AddToDiagnostic for MoreTargeted {
+    fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _f: F)
+    where
+        F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
+    {
+        diag.code(rustc_errors::error_code!(E0772));
+        diag.set_primary_message(fluent::infer_more_targeted);
+        diag.set_arg("ident", self.ident);
+    }
+}
+
+#[derive(Diagnostic)]
+#[diag(infer_but_needs_to_satisfy, code = "E0759")]
+pub struct ButNeedsToSatisfy {
+    #[primary_span]
+    pub sp: Span,
+    #[label(influencer)]
+    pub influencer_point: Span,
+    #[label(used_here)]
+    pub spans: Vec<Span>,
+    #[label(require)]
+    pub require_span_as_label: Option<Span>,
+    #[note(require)]
+    pub require_span_as_note: Option<Span>,
+    #[note(introduced_by_bound)]
+    pub bound: Option<Span>,
+
+    #[subdiagnostic]
+    pub req_introduces_loc: Option<ReqIntroducedLocations>,
+
+    pub spans_empty: bool,
+    pub has_lifetime: bool,
+    pub lifetime: String,
+}
diff --git a/compiler/rustc_infer/src/infer/at.rs b/compiler/rustc_infer/src/infer/at.rs
index e9186540a7b..d816a9ed3d7 100644
--- a/compiler/rustc_infer/src/infer/at.rs
+++ b/compiler/rustc_infer/src/infer/at.rs
@@ -427,3 +427,15 @@ impl<'tcx> ToTrace<'tcx> for ty::AliasTy<'tcx> {
         }
     }
 }
+
+impl<'tcx> ToTrace<'tcx> for ty::FnSig<'tcx> {
+    fn to_trace(
+        _: TyCtxt<'tcx>,
+        cause: &ObligationCause<'tcx>,
+        a_is_expected: bool,
+        a: Self,
+        b: Self,
+    ) -> TypeTrace<'tcx> {
+        TypeTrace { cause: cause.clone(), values: Sigs(ExpectedFound::new(a_is_expected, a, b)) }
+    }
+}
diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
index 7222eb77682..5c3e9a2d5cc 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
@@ -1,4 +1,3 @@
-// ignore-tidy-filelength
 //! Error Reporting Code for the inference engine
 //!
 //! Because of the way inference, and in particular region inference,
@@ -303,6 +302,7 @@ pub fn unexpected_hidden_region_diagnostic<'tcx>(
                     None,
                     format!("captures `{}`", hidden_region),
                     None,
+                    Some(reg_info.def_id),
                 )
             }
         }
@@ -1428,8 +1428,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
         impl<'tcx> OpaqueTypesVisitor<'tcx> {
             fn visit_expected_found(
                 tcx: TyCtxt<'tcx>,
-                expected: Ty<'tcx>,
-                found: Ty<'tcx>,
+                expected: impl TypeVisitable<'tcx>,
+                found: impl TypeVisitable<'tcx>,
                 ignore_span: Span,
             ) -> Self {
                 let mut types_visitor = OpaqueTypesVisitor {
@@ -1569,6 +1569,11 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                             _ => (false, Mismatch::Fixed("type")),
                         }
                     }
+                    ValuePairs::Sigs(infer::ExpectedFound { expected, found }) => {
+                        OpaqueTypesVisitor::visit_expected_found(self.tcx, expected, found, span)
+                            .report(diag);
+                        (false, Mismatch::Fixed("signature"))
+                    }
                     ValuePairs::TraitRefs(_) | ValuePairs::PolyTraitRefs(_) => {
                         (false, Mismatch::Fixed("trait"))
                     }
@@ -2040,6 +2045,17 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                     ret => ret,
                 }
             }
+            infer::Sigs(exp_found) => {
+                let exp_found = self.resolve_vars_if_possible(exp_found);
+                if exp_found.references_error() {
+                    return None;
+                }
+                let (exp, fnd) = self.cmp_fn_sig(
+                    &ty::Binder::dummy(exp_found.expected),
+                    &ty::Binder::dummy(exp_found.found),
+                );
+                Some((exp, fnd, None, None))
+            }
         }
     }
 
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 8a0e332f9c7..59fb74eb543 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
@@ -9,7 +9,7 @@ mod different_lifetimes;
 pub mod find_anon_type;
 mod mismatched_static_lifetime;
 mod named_anon_conflict;
-mod placeholder_error;
+pub(crate) mod placeholder_error;
 mod placeholder_relation;
 mod static_impl_trait;
 mod trait_impl_difference;
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 3fe7c1598fc..4e13ec90228 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
@@ -1,8 +1,11 @@
 //! Error Reporting for Anonymous Region Lifetime Errors
 //! where one region is named and the other is anonymous.
-use crate::infer::error_reporting::nice_region_error::find_anon_type::find_anon_type;
 use crate::infer::error_reporting::nice_region_error::NiceRegionError;
-use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed};
+use crate::{
+    errors::ExplicitLifetimeRequired,
+    infer::error_reporting::nice_region_error::find_anon_type::find_anon_type,
+};
+use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed};
 use rustc_middle::ty;
 use rustc_span::symbol::kw;
 
@@ -86,31 +89,17 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
         {
             return None;
         }
-
-        let (error_var, span_label_var) = match param.pat.simple_ident() {
-            Some(simple_ident) => (
-                format!("the type of `{}`", simple_ident),
-                format!("the type of `{}`", simple_ident),
-            ),
-            None => ("parameter type".to_owned(), "type".to_owned()),
+        let named = named.to_string();
+        let err = match param.pat.simple_ident() {
+            Some(simple_ident) => ExplicitLifetimeRequired::WithIdent {
+                span,
+                simple_ident,
+                named,
+                new_ty_span,
+                new_ty,
+            },
+            None => ExplicitLifetimeRequired::WithParamType { span, named, new_ty_span, new_ty },
         };
-
-        let mut diag = struct_span_err!(
-            self.tcx().sess,
-            span,
-            E0621,
-            "explicit lifetime required in {}",
-            error_var
-        );
-
-        diag.span_label(span, format!("lifetime `{}` required", named));
-        diag.span_suggestion(
-            new_ty_span,
-            &format!("add explicit lifetime `{}` to {}", named, span_label_var),
-            new_ty,
-            Applicability::Unspecified,
-        );
-
-        Some(diag)
+        Some(self.tcx().sess.parse_sess.create_err(err))
     }
 }
diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs
index fed9fda74bf..202f39521e9 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs
@@ -1,10 +1,14 @@
+use crate::errors::{
+    ActualImplExpectedKind, ActualImplExpectedLifetimeKind, ActualImplExplNotes,
+    TraitPlaceholderMismatch, TyOrSig,
+};
 use crate::infer::error_reporting::nice_region_error::NiceRegionError;
 use crate::infer::lexical_region_resolve::RegionResolutionError;
 use crate::infer::ValuePairs;
 use crate::infer::{SubregionOrigin, TypeTrace};
 use crate::traits::{ObligationCause, ObligationCauseCode};
 use rustc_data_structures::intern::Interned;
-use rustc_errors::{Diagnostic, DiagnosticBuilder, ErrorGuaranteed};
+use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed, IntoDiagnosticArg};
 use rustc_hir::def::Namespace;
 use rustc_hir::def_id::DefId;
 use rustc_middle::ty::error::ExpectedFound;
@@ -12,7 +16,43 @@ use rustc_middle::ty::print::{FmtPrinter, Print, RegionHighlightMode};
 use rustc_middle::ty::subst::SubstsRef;
 use rustc_middle::ty::{self, RePlaceholder, ReVar, Region, TyCtxt};
 
-use std::fmt::{self, Write};
+use std::fmt;
+
+// HACK(eddyb) maybe move this in a more central location.
+#[derive(Copy, Clone)]
+pub struct Highlighted<'tcx, T> {
+    tcx: TyCtxt<'tcx>,
+    highlight: RegionHighlightMode<'tcx>,
+    value: T,
+}
+
+impl<'tcx, T> IntoDiagnosticArg for Highlighted<'tcx, T>
+where
+    T: for<'a> Print<'tcx, FmtPrinter<'a, 'tcx>, Error = fmt::Error, Output = FmtPrinter<'a, 'tcx>>,
+{
+    fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> {
+        rustc_errors::DiagnosticArgValue::Str(self.to_string().into())
+    }
+}
+
+impl<'tcx, T> Highlighted<'tcx, T> {
+    fn map<U>(self, f: impl FnOnce(T) -> U) -> Highlighted<'tcx, U> {
+        Highlighted { tcx: self.tcx, highlight: self.highlight, value: f(self.value) }
+    }
+}
+
+impl<'tcx, T> fmt::Display for Highlighted<'tcx, T>
+where
+    T: for<'a> Print<'tcx, FmtPrinter<'a, 'tcx>, Error = fmt::Error, Output = FmtPrinter<'a, 'tcx>>,
+{
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        let mut printer = ty::print::FmtPrinter::new(self.tcx, Namespace::TypeNS);
+        printer.region_highlight_mode = self.highlight;
+
+        let s = self.value.print(printer)?.into_buffer();
+        f.write_str(&s)
+    }
+}
 
 impl<'tcx> NiceRegionError<'_, 'tcx> {
     /// When given a `ConcreteFailure` for a function with arguments containing a named region and
@@ -205,26 +245,21 @@ impl<'tcx> NiceRegionError<'_, 'tcx> {
         actual_substs: SubstsRef<'tcx>,
     ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
         let span = cause.span();
-        let msg = format!(
-            "implementation of `{}` is not general enough",
-            self.tcx().def_path_str(trait_def_id),
-        );
-        let mut err = self.tcx().sess.struct_span_err(span, &msg);
-
-        let leading_ellipsis = if let ObligationCauseCode::ItemObligation(def_id)
-        | ObligationCauseCode::ExprItemObligation(def_id, ..) =
-            *cause.code()
-        {
-            err.span_label(span, "doesn't satisfy where-clause");
-            err.span_label(
-                self.tcx().def_span(def_id),
-                &format!("due to a where-clause on `{}`...", self.tcx().def_path_str(def_id)),
-            );
-            true
-        } else {
-            err.span_label(span, &msg);
-            false
-        };
+
+        let (leading_ellipsis, satisfy_span, where_span, dup_span, def_id) =
+            if let ObligationCauseCode::ItemObligation(def_id)
+            | ObligationCauseCode::ExprItemObligation(def_id, ..) = *cause.code()
+            {
+                (
+                    true,
+                    Some(span),
+                    Some(self.tcx().def_span(def_id)),
+                    None,
+                    self.tcx().def_path_str(def_id),
+                )
+            } else {
+                (false, None, None, Some(span), String::new())
+            };
 
         let expected_trait_ref = self
             .cx
@@ -284,8 +319,7 @@ impl<'tcx> NiceRegionError<'_, 'tcx> {
             ?expected_self_ty_has_vid,
         );
 
-        self.explain_actual_impl_that_was_found(
-            &mut err,
+        let actual_impl_expl_notes = self.explain_actual_impl_that_was_found(
             sub_placeholder,
             sup_placeholder,
             has_sub,
@@ -299,7 +333,15 @@ impl<'tcx> NiceRegionError<'_, 'tcx> {
             leading_ellipsis,
         );
 
-        err
+        self.tcx().sess.create_err(TraitPlaceholderMismatch {
+            span,
+            satisfy_span,
+            where_span,
+            dup_span,
+            def_id,
+            trait_def_id: self.tcx().def_path_str(trait_def_id),
+            actual_impl_expl_notes,
+        })
     }
 
     /// Add notes with details about the expected and actual trait refs, with attention to cases
@@ -309,7 +351,6 @@ impl<'tcx> NiceRegionError<'_, 'tcx> {
     /// due to the number of combinations we have to deal with.
     fn explain_actual_impl_that_was_found(
         &self,
-        err: &mut Diagnostic,
         sub_placeholder: Option<Region<'tcx>>,
         sup_placeholder: Option<Region<'tcx>>,
         has_sub: Option<usize>,
@@ -321,39 +362,7 @@ impl<'tcx> NiceRegionError<'_, 'tcx> {
         actual_has_vid: Option<usize>,
         any_self_ty_has_vid: bool,
         leading_ellipsis: bool,
-    ) {
-        // HACK(eddyb) maybe move this in a more central location.
-        #[derive(Copy, Clone)]
-        struct Highlighted<'tcx, T> {
-            tcx: TyCtxt<'tcx>,
-            highlight: RegionHighlightMode<'tcx>,
-            value: T,
-        }
-
-        impl<'tcx, T> Highlighted<'tcx, T> {
-            fn map<U>(self, f: impl FnOnce(T) -> U) -> Highlighted<'tcx, U> {
-                Highlighted { tcx: self.tcx, highlight: self.highlight, value: f(self.value) }
-            }
-        }
-
-        impl<'tcx, T> fmt::Display for Highlighted<'tcx, T>
-        where
-            T: for<'a> Print<
-                'tcx,
-                FmtPrinter<'a, 'tcx>,
-                Error = fmt::Error,
-                Output = FmtPrinter<'a, 'tcx>,
-            >,
-        {
-            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-                let mut printer = ty::print::FmtPrinter::new(self.tcx, Namespace::TypeNS);
-                printer.region_highlight_mode = self.highlight;
-
-                let s = self.value.print(printer)?.into_buffer();
-                f.write_str(&s)
-            }
-        }
-
+    ) -> Vec<ActualImplExplNotes<'tcx>> {
         // The weird thing here with the `maybe_highlighting_region` calls and the
         // the match inside is meant to be like this:
         //
@@ -380,120 +389,110 @@ impl<'tcx> NiceRegionError<'_, 'tcx> {
         let mut expected_trait_ref = highlight_trait_ref(expected_trait_ref);
         expected_trait_ref.highlight.maybe_highlighting_region(sub_placeholder, has_sub);
         expected_trait_ref.highlight.maybe_highlighting_region(sup_placeholder, has_sup);
-        err.note(&{
-            let passive_voice = match (has_sub, has_sup) {
-                (Some(_), _) | (_, Some(_)) => any_self_ty_has_vid,
-                (None, None) => {
-                    expected_trait_ref.highlight.maybe_highlighting_region(vid, expected_has_vid);
-                    match expected_has_vid {
-                        Some(_) => true,
-                        None => any_self_ty_has_vid,
-                    }
-                }
-            };
 
-            let mut note = if same_self_type {
-                let mut self_ty = expected_trait_ref.map(|tr| tr.self_ty());
-                self_ty.highlight.maybe_highlighting_region(vid, actual_has_vid);
-
-                if self_ty.value.is_closure()
-                    && self.tcx().is_fn_trait(expected_trait_ref.value.def_id)
-                {
-                    let closure_sig = self_ty.map(|closure| {
-                        if let ty::Closure(_, substs) = closure.kind() {
-                            self.tcx().signature_unclosure(
-                                substs.as_closure().sig(),
-                                rustc_hir::Unsafety::Normal,
-                            )
-                        } else {
-                            bug!("type is not longer closure");
-                        }
-                    });
-
-                    format!(
-                        "{}closure with signature `{}` must implement `{}`",
-                        if leading_ellipsis { "..." } else { "" },
-                        closure_sig,
-                        expected_trait_ref.map(|tr| tr.print_only_trait_path()),
-                    )
-                } else {
-                    format!(
-                        "{}`{}` must implement `{}`",
-                        if leading_ellipsis { "..." } else { "" },
-                        self_ty,
-                        expected_trait_ref.map(|tr| tr.print_only_trait_path()),
-                    )
+        let passive_voice = match (has_sub, has_sup) {
+            (Some(_), _) | (_, Some(_)) => any_self_ty_has_vid,
+            (None, None) => {
+                expected_trait_ref.highlight.maybe_highlighting_region(vid, expected_has_vid);
+                match expected_has_vid {
+                    Some(_) => true,
+                    None => any_self_ty_has_vid,
                 }
-            } else if passive_voice {
-                format!(
-                    "{}`{}` would have to be implemented for the type `{}`",
-                    if leading_ellipsis { "..." } else { "" },
+            }
+        };
+
+        let (kind, ty_or_sig, trait_path) = if same_self_type {
+            let mut self_ty = expected_trait_ref.map(|tr| tr.self_ty());
+            self_ty.highlight.maybe_highlighting_region(vid, actual_has_vid);
+
+            if self_ty.value.is_closure() && self.tcx().is_fn_trait(expected_trait_ref.value.def_id)
+            {
+                let closure_sig = self_ty.map(|closure| {
+                    if let ty::Closure(_, substs) = closure.kind() {
+                        self.tcx().signature_unclosure(
+                            substs.as_closure().sig(),
+                            rustc_hir::Unsafety::Normal,
+                        )
+                    } else {
+                        bug!("type is not longer closure");
+                    }
+                });
+                (
+                    ActualImplExpectedKind::Signature,
+                    TyOrSig::ClosureSig(closure_sig),
                     expected_trait_ref.map(|tr| tr.print_only_trait_path()),
-                    expected_trait_ref.map(|tr| tr.self_ty()),
                 )
             } else {
-                format!(
-                    "{}`{}` must implement `{}`",
-                    if leading_ellipsis { "..." } else { "" },
-                    expected_trait_ref.map(|tr| tr.self_ty()),
+                (
+                    ActualImplExpectedKind::Other,
+                    TyOrSig::Ty(self_ty),
                     expected_trait_ref.map(|tr| tr.print_only_trait_path()),
                 )
-            };
+            }
+        } else if passive_voice {
+            (
+                ActualImplExpectedKind::Passive,
+                TyOrSig::Ty(expected_trait_ref.map(|tr| tr.self_ty())),
+                expected_trait_ref.map(|tr| tr.print_only_trait_path()),
+            )
+        } else {
+            (
+                ActualImplExpectedKind::Other,
+                TyOrSig::Ty(expected_trait_ref.map(|tr| tr.self_ty())),
+                expected_trait_ref.map(|tr| tr.print_only_trait_path()),
+            )
+        };
 
-            match (has_sub, has_sup) {
-                (Some(n1), Some(n2)) => {
-                    let _ = write!(
-                        note,
-                        ", for any two lifetimes `'{}` and `'{}`...",
-                        std::cmp::min(n1, n2),
-                        std::cmp::max(n1, n2),
-                    );
-                }
-                (Some(n), _) | (_, Some(n)) => {
-                    let _ = write!(note, ", for any lifetime `'{}`...", n,);
-                }
-                (None, None) => {
-                    if let Some(n) = expected_has_vid {
-                        let _ = write!(note, ", for some specific lifetime `'{}`...", n,);
-                    }
+        let (lt_kind, lifetime_1, lifetime_2) = match (has_sub, has_sup) {
+            (Some(n1), Some(n2)) => {
+                (ActualImplExpectedLifetimeKind::Two, std::cmp::min(n1, n2), std::cmp::max(n1, n2))
+            }
+            (Some(n), _) | (_, Some(n)) => (ActualImplExpectedLifetimeKind::Any, n, 0),
+            (None, None) => {
+                if let Some(n) = expected_has_vid {
+                    (ActualImplExpectedLifetimeKind::Some, n, 0)
+                } else {
+                    (ActualImplExpectedLifetimeKind::Nothing, 0, 0)
                 }
             }
+        };
 
-            note
-        });
+        let note_1 = ActualImplExplNotes::new_expected(
+            kind,
+            lt_kind,
+            leading_ellipsis,
+            ty_or_sig,
+            trait_path,
+            lifetime_1,
+            lifetime_2,
+        );
 
         let mut actual_trait_ref = highlight_trait_ref(actual_trait_ref);
         actual_trait_ref.highlight.maybe_highlighting_region(vid, actual_has_vid);
-        err.note(&{
-            let passive_voice = match actual_has_vid {
-                Some(_) => any_self_ty_has_vid,
-                None => true,
-            };
 
-            let mut note = if same_self_type {
-                format!(
-                    "...but it actually implements `{}`",
-                    actual_trait_ref.map(|tr| tr.print_only_trait_path()),
-                )
-            } else if passive_voice {
-                format!(
-                    "...but `{}` is actually implemented for the type `{}`",
-                    actual_trait_ref.map(|tr| tr.print_only_trait_path()),
-                    actual_trait_ref.map(|tr| tr.self_ty()),
-                )
-            } else {
-                format!(
-                    "...but `{}` actually implements `{}`",
-                    actual_trait_ref.map(|tr| tr.self_ty()),
-                    actual_trait_ref.map(|tr| tr.print_only_trait_path()),
-                )
-            };
+        let passive_voice = match actual_has_vid {
+            Some(_) => any_self_ty_has_vid,
+            None => true,
+        };
 
-            if let Some(n) = actual_has_vid {
-                let _ = write!(note, ", for some specific lifetime `'{}`", n);
+        let trait_path = actual_trait_ref.map(|tr| tr.print_only_trait_path());
+        let ty = actual_trait_ref.map(|tr| tr.self_ty()).to_string();
+        let has_lifetime = actual_has_vid.is_some();
+        let lifetime = actual_has_vid.unwrap_or_default();
+
+        let note_2 = if same_self_type {
+            ActualImplExplNotes::ButActuallyImplementsTrait { trait_path, has_lifetime, lifetime }
+        } else if passive_voice {
+            ActualImplExplNotes::ButActuallyImplementedForTy {
+                trait_path,
+                ty,
+                has_lifetime,
+                lifetime,
             }
+        } else {
+            ActualImplExplNotes::ButActuallyTyImplements { trait_path, ty, has_lifetime, lifetime }
+        };
 
-            note
-        });
+        vec![note_1, note_2]
     }
 }
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 9bd2202d260..fb0f09198cc 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
@@ -1,20 +1,28 @@
 //! Error Reporting for static impl Traits.
 
+use crate::errors::{
+    ButCallingIntroduces, ButNeedsToSatisfy, DynTraitConstraintSuggestion, MoreTargeted,
+    ReqIntroducedLocations,
+};
 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::FxIndexSet;
-use rustc_errors::{struct_span_err, Applicability, Diagnostic, ErrorGuaranteed, MultiSpan};
+use rustc_errors::{AddToDiagnostic, Applicability, Diagnostic, ErrorGuaranteed, MultiSpan};
 use rustc_hir::def_id::DefId;
 use rustc_hir::intravisit::{walk_ty, Visitor};
-use rustc_hir::{self as hir, GenericBound, Item, ItemKind, Lifetime, LifetimeName, Node, TyKind};
+use rustc_hir::{
+    self as hir, GenericBound, GenericParamKind, Item, ItemKind, Lifetime, LifetimeName, Node,
+    TyKind,
+};
 use rustc_middle::ty::{
     self, AssocItemContainer, StaticLifetimeVisitor, Ty, TyCtxt, TypeSuperVisitable, TypeVisitor,
 };
 use rustc_span::symbol::Ident;
 use rustc_span::Span;
 
+use rustc_span::def_id::LocalDefId;
 use std::ops::ControlFlow;
 
 impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
@@ -49,46 +57,32 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
                     }
 
                     let param = self.find_param_with_region(*sup_r, *sub_r)?;
-                    let lifetime = if sup_r.has_name() {
-                        format!("lifetime `{}`", sup_r)
-                    } else {
-                        "an anonymous lifetime `'_`".to_string()
+                    let simple_ident = param.param.pat.simple_ident();
+
+                    let (has_impl_path, impl_path) = match ctxt.assoc_item.container {
+                        AssocItemContainer::TraitContainer => {
+                            let id = ctxt.assoc_item.container_id(tcx);
+                            (true, tcx.def_path_str(id))
+                        }
+                        AssocItemContainer::ImplContainer => (false, String::new()),
                     };
-                    let mut err = struct_span_err!(
-                        tcx.sess,
-                        cause.span,
-                        E0772,
-                        "{} has {} but calling `{}` introduces an implicit `'static` lifetime \
-                         requirement",
-                        param
-                            .param
-                            .pat
-                            .simple_ident()
-                            .map(|s| format!("`{}`", s))
-                            .unwrap_or_else(|| "`fn` parameter".to_string()),
-                        lifetime,
-                        ctxt.assoc_item.name,
-                    );
-                    err.span_label(param.param_ty_span, &format!("this data with {}...", lifetime));
-                    err.span_label(
-                        cause.span,
-                        &format!(
-                            "...is used and required to live as long as `'static` here \
-                             because of an implicit lifetime bound on the {}",
-                            match ctxt.assoc_item.container {
-                                AssocItemContainer::TraitContainer => {
-                                    let id = ctxt.assoc_item.container_id(tcx);
-                                    format!("`impl` of `{}`", tcx.def_path_str(id))
-                                }
-                                AssocItemContainer::ImplContainer => "inherent `impl`".to_string(),
-                            },
-                        ),
-                    );
+
+                    let mut err = self.tcx().sess.create_err(ButCallingIntroduces {
+                        param_ty_span: param.param_ty_span,
+                        cause_span: cause.span,
+                        has_param_name: simple_ident.is_some(),
+                        param_name: simple_ident.map(|x| x.to_string()).unwrap_or_default(),
+                        has_lifetime: sup_r.has_name(),
+                        lifetime: sup_r.to_string(),
+                        assoc_item: ctxt.assoc_item.name,
+                        has_impl_path,
+                        impl_path,
+                    });
                     if self.find_impl_on_dyn_trait(&mut err, param.param_ty, &ctxt) {
                         let reported = err.emit();
                         return Some(reported);
                     } else {
-                        err.cancel();
+                        err.cancel()
                     }
                 }
                 return None;
@@ -104,25 +98,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
         let sp = var_origin.span();
         let return_sp = sub_origin.span();
         let param = self.find_param_with_region(*sup_r, *sub_r)?;
-        let (lifetime_name, lifetime) = if sup_r.has_name() {
-            (sup_r.to_string(), format!("lifetime `{}`", sup_r))
-        } else {
-            ("'_".to_owned(), "an anonymous lifetime `'_`".to_string())
-        };
-        let param_name = param
-            .param
-            .pat
-            .simple_ident()
-            .map(|s| format!("`{}`", s))
-            .unwrap_or_else(|| "`fn` parameter".to_string());
-        let mut err = struct_span_err!(
-            tcx.sess,
-            sp,
-            E0759,
-            "{} has {} but it needs to satisfy a `'static` lifetime requirement",
-            param_name,
-            lifetime,
-        );
+        let lifetime_name = if sup_r.has_name() { sup_r.to_string() } else { "'_".to_owned() };
 
         let (mention_influencer, influencer_point) =
             if sup_origin.span().overlaps(param.param_ty_span) {
@@ -141,7 +117,6 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
             } else {
                 (!sup_origin.span().overlaps(return_sp), param.param_ty_span)
             };
-        err.span_label(influencer_point, &format!("this data with {}...", lifetime));
 
         debug!("try_report_static_impl_trait: param_info={:?}", param);
 
@@ -155,31 +130,19 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
         spans.dedup_by_key(|span| (span.lo(), span.hi()));
 
         // We try to make the output have fewer overlapping spans if possible.
-        let require_msg = if spans.is_empty() {
-            "...is used and required to live as long as `'static` here"
-        } else {
-            "...and is required to live as long as `'static` here"
-        };
         let require_span =
             if sup_origin.span().overlaps(return_sp) { sup_origin.span() } else { return_sp };
 
-        for span in &spans {
-            err.span_label(*span, "...is used here...");
-        }
-
-        if spans.iter().any(|sp| sp.overlaps(return_sp) || *sp > return_sp) {
-            // If any of the "captured here" labels appears on the same line or after
-            // `require_span`, we put it on a note to ensure the text flows by appearing
-            // always at the end.
-            err.span_note(require_span, require_msg);
+        let spans_empty = spans.is_empty();
+        let require_as_note = spans.iter().any(|sp| sp.overlaps(return_sp) || *sp > return_sp);
+        let bound = if let SubregionOrigin::RelateParamBound(_, _, Some(bound)) = sub_origin {
+            Some(*bound)
         } else {
-            // We don't need a note, it's already at the end, it can be shown as a `span_label`.
-            err.span_label(require_span, require_msg);
-        }
+            None
+        };
+
+        let mut subdiag = None;
 
-        if let SubregionOrigin::RelateParamBound(_, _, Some(bound)) = sub_origin {
-            err.span_note(*bound, "`'static` lifetime requirement introduced by this bound");
-        }
         if let SubregionOrigin::Subtype(box TypeTrace { cause, .. }) = sub_origin {
             if let ObligationCauseCode::ReturnValue(hir_id)
             | ObligationCauseCode::BlockTailExpression(hir_id) = cause.code()
@@ -187,33 +150,50 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
                 let parent_id = tcx.hir().get_parent_item(*hir_id);
                 if let Some(fn_decl) = tcx.hir().fn_decl_by_hir_id(parent_id.into()) {
                     let mut span: MultiSpan = fn_decl.output.span().into();
+                    let mut spans = Vec::new();
                     let mut add_label = true;
                     if let hir::FnRetTy::Return(ty) = fn_decl.output {
                         let mut v = StaticLifetimeVisitor(vec![], tcx.hir());
                         v.visit_ty(ty);
                         if !v.0.is_empty() {
                             span = v.0.clone().into();
-                            for sp in v.0 {
-                                span.push_span_label(sp, "`'static` requirement introduced here");
-                            }
+                            spans = v.0;
                             add_label = false;
                         }
                     }
-                    if add_label {
-                        span.push_span_label(
-                            fn_decl.output.span(),
-                            "requirement introduced by this return type",
-                        );
-                    }
-                    span.push_span_label(cause.span, "because of this returned expression");
-                    err.span_note(
+                    let fn_decl_span = fn_decl.output.span();
+
+                    subdiag = Some(ReqIntroducedLocations {
                         span,
-                        "`'static` lifetime requirement introduced by the return type",
-                    );
+                        spans,
+                        fn_decl_span,
+                        cause_span: cause.span,
+                        add_label,
+                    });
                 }
             }
         }
 
+        let diag = ButNeedsToSatisfy {
+            sp,
+            influencer_point,
+            spans: spans.clone(),
+            // If any of the "captured here" labels appears on the same line or after
+            // `require_span`, we put it on a note to ensure the text flows by appearing
+            // always at the end.
+            require_span_as_note: require_as_note.then_some(require_span),
+            // We don't need a note, it's already at the end, it can be shown as a `span_label`.
+            require_span_as_label: (!require_as_note).then_some(require_span),
+            req_introduces_loc: subdiag,
+
+            has_lifetime: sup_r.has_name(),
+            lifetime: sup_r.to_string(),
+            spans_empty,
+            bound,
+        };
+
+        let mut err = self.tcx().sess.create_err(diag);
+
         let fn_returns = tcx.return_type_impl_or_dyn_traits(anon_reg_sup.def_id);
 
         let mut override_error_code = None;
@@ -239,7 +219,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
             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)
+                NiceRegionError::get_impl_ident_and_self_ty_from_trait(tcx, item_def_id, &v.0)
                 && self.suggest_constrain_dyn_trait_in_impl(&mut err, &v.0, ident, self_ty)
             {
                 override_error_code = Some(ident.name);
@@ -247,12 +227,8 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
         }
         if let (Some(ident), true) = (override_error_code, fn_returns.is_empty()) {
             // Provide a more targeted error code and description.
-            err.code(rustc_errors::error_code!(E0772));
-            err.set_primary_message(&format!(
-                "{} has {} but calling `{}` introduces an implicit `'static` lifetime \
-                requirement",
-                param_name, lifetime, ident,
-            ));
+            let retarget_subdiag = MoreTargeted { ident };
+            retarget_subdiag.add_to_diagnostic(&mut err);
         }
 
         let arg = match param.param.pat.simple_ident() {
@@ -268,6 +244,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
             Some(arg),
             captures,
             Some((param.param_ty_span, param.param_ty.to_string())),
+            Some(anon_reg_sup.def_id),
         );
 
         let reported = err.emit();
@@ -283,6 +260,7 @@ pub fn suggest_new_region_bound(
     arg: Option<String>,
     captures: String,
     param: Option<(Span, String)>,
+    scope_def_id: Option<LocalDefId>,
 ) {
     debug!("try_report_static_impl_trait: fn_return={:?}", fn_returns);
     // FIXME: account for the need of parens in `&(dyn Trait + '_)`
@@ -309,19 +287,12 @@ pub fn suggest_new_region_bound(
                 let did = item_id.owner_id.to_def_id();
                 let ty = tcx.mk_opaque(did, ty::InternalSubsts::identity_for_item(tcx, did));
 
-                if let Some(span) = opaque
-                    .bounds
-                    .iter()
-                    .filter_map(|arg| match arg {
-                        GenericBound::Outlives(Lifetime {
-                            res: LifetimeName::Static,
-                            ident,
-                            ..
-                        }) => Some(ident.span),
-                        _ => None,
-                    })
-                    .next()
-                {
+                if let Some(span) = opaque.bounds.iter().find_map(|arg| match arg {
+                    GenericBound::Outlives(Lifetime {
+                        res: LifetimeName::Static, ident, ..
+                    }) => Some(ident.span),
+                    _ => None,
+                }) {
                     if let Some(explicit_static) = &explicit_static {
                         err.span_suggestion_verbose(
                             span,
@@ -338,27 +309,78 @@ pub fn suggest_new_region_bound(
                             Applicability::MaybeIncorrect,
                         );
                     }
-                } else if opaque
-                    .bounds
-                    .iter()
-                    .filter_map(|arg| match arg {
-                        GenericBound::Outlives(Lifetime { ident, .. })
-                            if ident.name.to_string() == lifetime_name =>
-                        {
-                            Some(ident.span)
-                        }
-                        _ => None,
-                    })
-                    .next()
-                    .is_some()
-                {
+                } else if opaque.bounds.iter().any(|arg| match arg {
+                    GenericBound::Outlives(Lifetime { ident, .. })
+                        if ident.name.to_string() == lifetime_name =>
+                    {
+                        true
+                    }
+                    _ => false,
+                }) {
                 } else {
-                    err.span_suggestion_verbose(
-                        fn_return.span.shrink_to_hi(),
-                        &format!("{declare} `{ty}` {captures}, {explicit}",),
-                        &plus_lt,
-                        Applicability::MaybeIncorrect,
-                    );
+                    // get a lifetime name of existing named lifetimes if any
+                    let existing_lt_name = if let Some(id) = scope_def_id
+                        && let Some(generics) = tcx.hir().get_generics(id)
+                        && let named_lifetimes = generics
+                        .params
+                        .iter()
+                        .filter(|p| matches!(p.kind, GenericParamKind::Lifetime { kind: hir::LifetimeParamKind::Explicit }))
+                        .map(|p| { if let hir::ParamName::Plain(name) = p.name {Some(name.to_string())} else {None}})
+                        .filter(|n| ! matches!(n, None))
+                        .collect::<Vec<_>>()
+                        && named_lifetimes.len() > 0 {
+                        named_lifetimes[0].clone()
+                    } else {
+                        None
+                    };
+                    let name = if let Some(name) = &existing_lt_name {
+                        format!("{}", name)
+                    } else {
+                        format!("'a")
+                    };
+                    // if there are more than one elided lifetimes in inputs, the explicit `'_` lifetime cannot be used.
+                    // introducing a new lifetime `'a` or making use of one from existing named lifetimes if any
+                    if let Some(id) = scope_def_id
+                        && let Some(generics) = tcx.hir().get_generics(id)
+                        && let mut spans_suggs = generics
+                            .params
+                            .iter()
+                            .filter(|p| p.is_elided_lifetime())
+                            .map(|p|
+                                  if p.span.hi() - p.span.lo() == rustc_span::BytePos(1) { // Ampersand (elided without '_)
+                                      (p.span.shrink_to_hi(),format!("{name} "))
+                                  } else { // Underscore (elided with '_)
+                                      (p.span, format!("{name}"))
+                                  }
+                            )
+                            .collect::<Vec<_>>()
+                        && spans_suggs.len() > 1
+                    {
+                        let use_lt =
+                        if existing_lt_name == None {
+                            spans_suggs.push((generics.span.shrink_to_hi(), format!("<{name}>")));
+                            format!("you can introduce a named lifetime parameter `{name}`")
+                        } else {
+                            // make use the existing named lifetime
+                            format!("you can use the named lifetime parameter `{name}`")
+                        };
+                        spans_suggs
+                            .push((fn_return.span.shrink_to_hi(), format!(" + {name} ")));
+                        err.multipart_suggestion_verbose(
+                            &format!(
+                                "{declare} `{ty}` {captures}, {use_lt}",
+                            ),
+                            spans_suggs,
+                            Applicability::MaybeIncorrect,
+                        );
+                    } else {
+                        err.span_suggestion_verbose(
+                            fn_return.span.shrink_to_hi(),
+                            &format!("{declare} `{ty}` {captures}, {explicit}",),
+                            &plus_lt,
+                            Applicability::MaybeIncorrect,
+                        );
+                    }
                 }
             }
             TyKind::TraitObject(_, lt, _) => {
@@ -403,66 +425,54 @@ pub fn suggest_new_region_bound(
 }
 
 impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
-    fn get_impl_ident_and_self_ty_from_trait(
-        &self,
+    pub fn get_impl_ident_and_self_ty_from_trait(
+        tcx: TyCtxt<'tcx>,
         def_id: DefId,
         trait_objects: &FxIndexSet<DefId>,
     ) -> Option<(Ident, &'tcx hir::Ty<'tcx>)> {
-        let tcx = self.tcx();
-        match tcx.hir().get_if_local(def_id) {
-            Some(Node::ImplItem(impl_item)) => {
-                match tcx.hir().find_by_def_id(tcx.hir().get_parent_item(impl_item.hir_id()).def_id)
+        match tcx.hir().get_if_local(def_id)? {
+            Node::ImplItem(impl_item) => {
+                let impl_did = tcx.hir().get_parent_item(impl_item.hir_id());
+                if let hir::OwnerNode::Item(Item {
+                    kind: ItemKind::Impl(hir::Impl { self_ty, .. }),
+                    ..
+                }) = tcx.hir().owner(impl_did)
                 {
-                    Some(Node::Item(Item {
-                        kind: ItemKind::Impl(hir::Impl { self_ty, .. }),
-                        ..
-                    })) => Some((impl_item.ident, self_ty)),
-                    _ => None,
+                    Some((impl_item.ident, self_ty))
+                } else {
+                    None
                 }
             }
-            Some(Node::TraitItem(trait_item)) => {
-                let trait_did = tcx.hir().get_parent_item(trait_item.hir_id());
-                match tcx.hir().find_by_def_id(trait_did.def_id) {
-                    Some(Node::Item(Item { kind: ItemKind::Trait(..), .. })) => {
-                        // The method being called is defined in the `trait`, but the `'static`
-                        // obligation comes from the `impl`. Find that `impl` so that we can point
-                        // at it in the suggestion.
-                        let trait_did = trait_did.to_def_id();
-                        match tcx
-                            .hir()
-                            .trait_impls(trait_did)
-                            .iter()
-                            .filter_map(|&impl_did| {
-                                match tcx.hir().get_if_local(impl_did.to_def_id()) {
-                                    Some(Node::Item(Item {
-                                        kind: ItemKind::Impl(hir::Impl { self_ty, .. }),
-                                        ..
-                                    })) if trait_objects.iter().all(|did| {
-                                        // FIXME: we should check `self_ty` against the receiver
-                                        // type in the `UnifyReceiver` context, but for now, use
-                                        // this imperfect proxy. This will fail if there are
-                                        // multiple `impl`s for the same trait like
-                                        // `impl Foo for Box<dyn Bar>` and `impl Foo for dyn Bar`.
-                                        // In that case, only the first one will get suggestions.
-                                        let mut traits = vec![];
-                                        let mut hir_v = HirTraitObjectVisitor(&mut traits, *did);
-                                        hir_v.visit_ty(self_ty);
-                                        !traits.is_empty()
-                                    }) =>
-                                    {
-                                        Some(self_ty)
-                                    }
-                                    _ => None,
-                                }
-                            })
-                            .next()
-                        {
-                            Some(self_ty) => Some((trait_item.ident, self_ty)),
-                            _ => None,
-                        }
+            Node::TraitItem(trait_item) => {
+                let trait_id = tcx.hir().get_parent_item(trait_item.hir_id());
+                debug_assert_eq!(tcx.def_kind(trait_id.def_id), hir::def::DefKind::Trait);
+                // The method being called is defined in the `trait`, but the `'static`
+                // obligation comes from the `impl`. Find that `impl` so that we can point
+                // at it in the suggestion.
+                let trait_did = trait_id.to_def_id();
+                tcx.hir().trait_impls(trait_did).iter().find_map(|&impl_did| {
+                    if let Node::Item(Item {
+                        kind: ItemKind::Impl(hir::Impl { self_ty, .. }),
+                        ..
+                    }) = tcx.hir().find_by_def_id(impl_did)?
+                        && trait_objects.iter().all(|did| {
+                            // FIXME: we should check `self_ty` against the receiver
+                            // type in the `UnifyReceiver` context, but for now, use
+                            // this imperfect proxy. This will fail if there are
+                            // multiple `impl`s for the same trait like
+                            // `impl Foo for Box<dyn Bar>` and `impl Foo for dyn Bar`.
+                            // In that case, only the first one will get suggestions.
+                            let mut traits = vec![];
+                            let mut hir_v = HirTraitObjectVisitor(&mut traits, *did);
+                            hir_v.visit_ty(self_ty);
+                            !traits.is_empty()
+                        })
+                    {
+                        Some((trait_item.ident, *self_ty))
+                    } else {
+                        None
                     }
-                    _ => None,
-                }
+                })
             }
             _ => None,
         }
@@ -493,7 +503,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
 
         // Get the `Ident` of the method being called and the corresponding `impl` (to point at
         // `Bar` in `impl Foo for dyn Bar {}` and the definition of the method being called).
-        let Some((ident, self_ty)) = self.get_impl_ident_and_self_ty_from_trait(instance.def_id(), &v.0) else {
+        let Some((ident, self_ty)) = NiceRegionError::get_impl_ident_and_self_ty_from_trait(tcx, instance.def_id(), &v.0) else {
             return false;
         };
 
@@ -513,21 +523,9 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
             let mut traits = vec![];
             let mut hir_v = HirTraitObjectVisitor(&mut traits, *found_did);
             hir_v.visit_ty(&self_ty);
-            for span in &traits {
-                let mut multi_span: MultiSpan = vec![*span].into();
-                multi_span
-                    .push_span_label(*span, "this has an implicit `'static` lifetime requirement");
-                multi_span.push_span_label(
-                    ident.span,
-                    "calling this method introduces the `impl`'s 'static` requirement",
-                );
-                err.span_note(multi_span, "the used `impl` has a `'static` requirement");
-                err.span_suggestion_verbose(
-                    span.shrink_to_hi(),
-                    "consider relaxing the implicit `'static` requirement",
-                    " + '_",
-                    Applicability::MaybeIncorrect,
-                );
+            for &span in &traits {
+                let subdiag = DynTraitConstraintSuggestion { span, ident };
+                subdiag.add_to_diagnostic(err);
                 suggested = true;
             }
         }
diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs
index dc1dc898922..40c0c806e1f 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs
@@ -1,15 +1,17 @@
 //! Error Reporting for `impl` items that do not match the obligations from their `trait`.
 
+use crate::errors::{ConsiderBorrowingParamHelp, RelationshipHelp, TraitImplDiff};
 use crate::infer::error_reporting::nice_region_error::NiceRegionError;
 use crate::infer::lexical_region_resolve::RegionResolutionError;
-use crate::infer::Subtype;
+use crate::infer::{Subtype, ValuePairs};
 use crate::traits::ObligationCauseCode::CompareImplItemObligation;
-use rustc_errors::{ErrorGuaranteed, MultiSpan};
+use rustc_errors::ErrorGuaranteed;
 use rustc_hir as hir;
 use rustc_hir::def::Res;
 use rustc_hir::def_id::DefId;
 use rustc_hir::intravisit::Visitor;
 use rustc_middle::hir::nested_filter;
+use rustc_middle::ty::error::ExpectedFound;
 use rustc_middle::ty::print::RegionHighlightMode;
 use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitor};
 use rustc_span::Span;
@@ -22,22 +24,27 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
         let error = self.error.as_ref()?;
         debug!("try_report_impl_not_conforming_to_trait {:?}", error);
         if let RegionResolutionError::SubSupConflict(
-                _,
-                var_origin,
-                sub_origin,
-                _sub,
-                sup_origin,
-                _sup,
-                _,
-            ) = error.clone()
+            _,
+            var_origin,
+            sub_origin,
+            _sub,
+            sup_origin,
+            _sup,
+            _,
+        ) = error.clone()
             && let (Subtype(sup_trace), Subtype(sub_trace)) = (&sup_origin, &sub_origin)
-            && let sub_expected_found @ Some((sub_expected, sub_found)) = sub_trace.values.ty()
-            && let sup_expected_found @ Some(_) = sup_trace.values.ty()
             && let CompareImplItemObligation { trait_item_def_id, .. } = sub_trace.cause.code()
-            && sup_expected_found == sub_expected_found
+            && sub_trace.values == sup_trace.values
+            && let ValuePairs::Sigs(ExpectedFound { expected, found }) = sub_trace.values
         {
-            let guar =
-                self.emit_err(var_origin.span(), sub_expected, sub_found, *trait_item_def_id);
+            // FIXME(compiler-errors): Don't like that this needs `Ty`s, but
+            // all of the region highlighting machinery only deals with those.
+            let guar = self.emit_err(
+                var_origin.span(),
+                self.cx.tcx.mk_fn_ptr(ty::Binder::dummy(expected)),
+                self.cx.tcx.mk_fn_ptr(ty::Binder::dummy(found)),
+                *trait_item_def_id,
+            );
             return Some(guar);
         }
         None
@@ -51,10 +58,6 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
         trait_def_id: DefId,
     ) -> ErrorGuaranteed {
         let trait_sp = self.tcx().def_span(trait_def_id);
-        let mut err = self
-            .tcx()
-            .sess
-            .struct_span_err(sp, "`impl` item signature doesn't match `trait` item signature");
 
         // Mark all unnamed regions in the type with a number.
         // This diagnostic is called in response to lifetime errors, so be informative.
@@ -91,9 +94,6 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
         let found =
             self.cx.extract_inference_diagnostics_data(found.into(), Some(found_highlight)).name;
 
-        err.span_label(sp, &format!("found `{}`", found));
-        err.span_label(trait_sp, &format!("expected `{}`", expected));
-
         // Get the span of all the used type parameters in the method.
         let assoc_item = self.tcx().associated_item(trait_def_id);
         let mut visitor = TypeParamSpanVisitor { tcx: self.tcx(), types: vec![] };
@@ -110,26 +110,18 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
             }
             _ => {}
         }
-        let mut type_param_span: MultiSpan = visitor.types.to_vec().into();
-        for &span in &visitor.types {
-            type_param_span
-                .push_span_label(span, "consider borrowing this type parameter in the trait");
-        }
 
-        err.note(&format!("expected `{}`\n   found `{}`", expected, found));
-
-        err.span_help(
-            type_param_span,
-            "the lifetime requirements from the `impl` do not correspond to the requirements in \
-             the `trait`",
-        );
-        if visitor.types.is_empty() {
-            err.help(
-                "verify the lifetime relationships in the `trait` and `impl` between the `self` \
-                 argument, the other inputs and its output",
-            );
-        }
-        err.emit()
+        let diag = TraitImplDiff {
+            sp,
+            trait_sp,
+            note: (),
+            param_help: ConsiderBorrowingParamHelp { spans: visitor.types.to_vec() },
+            rel_help: visitor.types.is_empty().then_some(RelationshipHelp),
+            expected,
+            found,
+        };
+
+        self.tcx().sess.emit_err(diag)
     }
 }
 
diff --git a/compiler/rustc_infer/src/infer/error_reporting/note.rs b/compiler/rustc_infer/src/infer/error_reporting/note.rs
index d91ef882bc4..7bb79d7bda8 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/note.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/note.rs
@@ -25,16 +25,6 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
             infer::Reborrow(span) => {
                 RegionOriginNote::Plain { span, msg: fluent::infer_reborrow }.add_to_diagnostic(err)
             }
-            infer::ReborrowUpvar(span, ref upvar_id) => {
-                let var_name = self.tcx.hir().name(upvar_id.var_path.hir_id);
-                RegionOriginNote::WithName {
-                    span,
-                    msg: fluent::infer_reborrow,
-                    name: &var_name.to_string(),
-                    continues: false,
-                }
-                .add_to_diagnostic(err);
-            }
             infer::RelateObjectBound(span) => {
                 RegionOriginNote::Plain { span, msg: fluent::infer_relate_object_bound }
                     .add_to_diagnostic(err);
@@ -162,33 +152,6 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                 );
                 err
             }
-            infer::ReborrowUpvar(span, ref upvar_id) => {
-                let var_name = self.tcx.hir().name(upvar_id.var_path.hir_id);
-                let mut err = struct_span_err!(
-                    self.tcx.sess,
-                    span,
-                    E0313,
-                    "lifetime of borrowed pointer outlives lifetime of captured variable `{}`...",
-                    var_name
-                );
-                note_and_explain_region(
-                    self.tcx,
-                    &mut err,
-                    "...the borrowed pointer is valid for ",
-                    sub,
-                    "...",
-                    None,
-                );
-                note_and_explain_region(
-                    self.tcx,
-                    &mut err,
-                    &format!("...but `{}` is only valid for ", var_name),
-                    sup,
-                    "",
-                    None,
-                );
-                err
-            }
             infer::RelateObjectBound(span) => {
                 let mut err = struct_span_err!(
                     self.tcx.sess,
diff --git a/compiler/rustc_infer/src/infer/error_reporting/suggest.rs b/compiler/rustc_infer/src/infer/error_reporting/suggest.rs
index 30ca9f41d6e..5b02956a106 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/suggest.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/suggest.rs
@@ -411,7 +411,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
         span: Span,
     ) {
         let hir = self.tcx.hir();
-        let fn_hir_id = hir.get_parent_node(cause.body_id);
+        let fn_hir_id = hir.parent_id(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), ..
@@ -585,45 +585,42 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
             let hir::StmtKind::Local(local) = &stmt.kind else { continue; };
             local.pat.walk(&mut find_compatible_candidates);
         }
-        match hir.find(hir.get_parent_node(blk.hir_id)) {
-            Some(hir::Node::Expr(hir::Expr { hir_id, .. })) => {
-                match hir.find(hir.get_parent_node(*hir_id)) {
-                    Some(hir::Node::Arm(hir::Arm { pat, .. })) => {
-                        pat.walk(&mut find_compatible_candidates);
-                    }
-                    Some(
-                        hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, _, body), .. })
-                        | hir::Node::ImplItem(hir::ImplItem {
-                            kind: hir::ImplItemKind::Fn(_, body),
-                            ..
-                        })
-                        | hir::Node::TraitItem(hir::TraitItem {
-                            kind: hir::TraitItemKind::Fn(_, hir::TraitFn::Provided(body)),
-                            ..
-                        })
-                        | hir::Node::Expr(hir::Expr {
-                            kind: hir::ExprKind::Closure(hir::Closure { body, .. }),
-                            ..
-                        }),
-                    ) => {
-                        for param in hir.body(*body).params {
-                            param.pat.walk(&mut find_compatible_candidates);
-                        }
-                    }
-                    Some(hir::Node::Expr(hir::Expr {
-                        kind:
-                            hir::ExprKind::If(
-                                hir::Expr { kind: hir::ExprKind::Let(let_), .. },
-                                then_block,
-                                _,
-                            ),
+        match hir.find_parent(blk.hir_id) {
+            Some(hir::Node::Expr(hir::Expr { hir_id, .. })) => match hir.find_parent(*hir_id) {
+                Some(hir::Node::Arm(hir::Arm { pat, .. })) => {
+                    pat.walk(&mut find_compatible_candidates);
+                }
+                Some(
+                    hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, _, body), .. })
+                    | hir::Node::ImplItem(hir::ImplItem {
+                        kind: hir::ImplItemKind::Fn(_, body), ..
+                    })
+                    | hir::Node::TraitItem(hir::TraitItem {
+                        kind: hir::TraitItemKind::Fn(_, hir::TraitFn::Provided(body)),
+                        ..
+                    })
+                    | hir::Node::Expr(hir::Expr {
+                        kind: hir::ExprKind::Closure(hir::Closure { body, .. }),
                         ..
-                    })) if then_block.hir_id == *hir_id => {
-                        let_.pat.walk(&mut find_compatible_candidates);
+                    }),
+                ) => {
+                    for param in hir.body(*body).params {
+                        param.pat.walk(&mut find_compatible_candidates);
                     }
-                    _ => {}
                 }
-            }
+                Some(hir::Node::Expr(hir::Expr {
+                    kind:
+                        hir::ExprKind::If(
+                            hir::Expr { kind: hir::ExprKind::Let(let_), .. },
+                            then_block,
+                            _,
+                        ),
+                    ..
+                })) if then_block.hir_id == *hir_id => {
+                    let_.pat.walk(&mut find_compatible_candidates);
+                }
+                _ => {}
+            },
             _ => {}
         }
 
diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs
index b17a465eb38..a9de74d78cb 100644
--- a/compiler/rustc_infer/src/infer/mod.rs
+++ b/compiler/rustc_infer/src/infer/mod.rs
@@ -361,6 +361,7 @@ pub enum ValuePairs<'tcx> {
     Terms(ExpectedFound<ty::Term<'tcx>>),
     TraitRefs(ExpectedFound<ty::TraitRef<'tcx>>),
     PolyTraitRefs(ExpectedFound<ty::PolyTraitRef<'tcx>>),
+    Sigs(ExpectedFound<ty::FnSig<'tcx>>),
 }
 
 impl<'tcx> ValuePairs<'tcx> {
@@ -409,9 +410,6 @@ pub enum SubregionOrigin<'tcx> {
     /// Creating a pointer `b` to contents of another reference
     Reborrow(Span),
 
-    /// Creating a pointer `b` to contents of an upvar
-    ReborrowUpvar(Span, ty::UpvarId),
-
     /// Data with type `Ty<'tcx>` was borrowed
     DataBorrowed(Ty<'tcx>, Span),
 
@@ -1954,7 +1952,6 @@ impl<'tcx> SubregionOrigin<'tcx> {
             RelateParamBound(a, ..) => a,
             RelateRegionParamBound(a) => a,
             Reborrow(a) => a,
-            ReborrowUpvar(a, _) => a,
             DataBorrowed(_, a) => a,
             ReferenceOutlivesReferent(_, a) => a,
             CompareImplItemObligation { span, .. } => span,
diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs
index a130fde47ed..749e960bfd0 100644
--- a/compiler/rustc_infer/src/infer/opaque_types.rs
+++ b/compiler/rustc_infer/src/infer/opaque_types.rs
@@ -61,7 +61,7 @@ impl<'tcx> InferCtxt<'tcx> {
                 .as_local()
                 .map_or(false, |def_id| self.opaque_type_origin(def_id, span).is_some())
         };
-        let value = value.fold_with(&mut ty::fold::BottomUpFolder {
+        let value = value.fold_with(&mut BottomUpFolder {
             tcx: self.tcx,
             lt_op: |lt| lt,
             ct_op: |ct| ct,
diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs
index 4c22ab68a56..7f761b005ed 100644
--- a/compiler/rustc_interface/src/interface.rs
+++ b/compiler/rustc_interface/src/interface.rs
@@ -90,8 +90,7 @@ pub fn parse_cfgspecs(cfgspecs: Vec<String>) -> FxHashSet<(String, Option<String
             .into_iter()
             .map(|s| {
                 let sess = ParseSess::with_silent_emitter(Some(format!(
-                    "this error occurred on the command line: `--cfg={}`",
-                    s
+                    "this error occurred on the command line: `--cfg={s}`"
                 )));
                 let filename = FileName::cfg_spec_source_code(&s);
 
@@ -150,8 +149,7 @@ pub fn parse_check_cfg(specs: Vec<String>) -> CheckCfg {
 
         'specs: for s in specs {
             let sess = ParseSess::with_silent_emitter(Some(format!(
-                "this error occurred on the command line: `--check-cfg={}`",
-                s
+                "this error occurred on the command line: `--check-cfg={s}`"
             )));
             let filename = FileName::cfg_spec_source_code(&s);
 
diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs
index 89d9450cf4e..86d56385bc9 100644
--- a/compiler/rustc_interface/src/passes.rs
+++ b/compiler/rustc_interface/src/passes.rs
@@ -620,7 +620,7 @@ fn write_out_deps(
         // prevents `make` from spitting out an error if a file is later
         // deleted. For more info see #28735
         for path in files {
-            writeln!(file, "{}:", path)?;
+            writeln!(file, "{path}:")?;
         }
 
         // Emit special comments with information about accessed environment variables.
@@ -633,9 +633,9 @@ fn write_out_deps(
             envs.sort_unstable();
             writeln!(file)?;
             for (k, v) in envs {
-                write!(file, "# env-dep:{}", k)?;
+                write!(file, "# env-dep:{k}")?;
                 if let Some(v) = v {
-                    write!(file, "={}", v)?;
+                    write!(file, "={v}")?;
                 }
                 writeln!(file)?;
             }
diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs
index eb3baba999b..316e2e29cd8 100644
--- a/compiler/rustc_interface/src/tests.rs
+++ b/compiler/rustc_interface/src/tests.rs
@@ -3,17 +3,17 @@ use crate::interface::parse_cfgspecs;
 
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::{emitter::HumanReadableErrorType, registry, ColorConfig};
-use rustc_session::config::InstrumentCoverage;
-use rustc_session::config::Strip;
+use rustc_session::config::rustc_optgroups;
+use rustc_session::config::TraitSolver;
 use rustc_session::config::{build_configuration, build_session_options, to_crate_config};
 use rustc_session::config::{
-    rustc_optgroups, ErrorOutputType, ExternLocation, LocationDetail, Options, Passes,
-};
-use rustc_session::config::{
     BranchProtection, Externs, OomStrategy, OutputType, OutputTypes, PAuthKey, PacRet,
     ProcMacroExecutionStrategy, SymbolManglingVersion, WasiExecModel,
 };
 use rustc_session::config::{CFGuard, ExternEntry, LinkerPluginLto, LtoCli, SwitchWithOptPath};
+use rustc_session::config::{DumpMonoStatsFormat, MirSpanview};
+use rustc_session::config::{ErrorOutputType, ExternLocation, LocationDetail, Options, Strip};
+use rustc_session::config::{InstrumentCoverage, Passes};
 use rustc_session::lint::Level;
 use rustc_session::search_paths::SearchPath;
 use rustc_session::utils::{CanonicalizedPath, NativeLib, NativeLibKind};
@@ -647,6 +647,9 @@ fn test_unstable_options_tracking_hash() {
     untracked!(dump_mir_dir, String::from("abc"));
     untracked!(dump_mir_exclude_pass_number, true);
     untracked!(dump_mir_graphviz, true);
+    untracked!(dump_mir_spanview, Some(MirSpanview::Statement));
+    untracked!(dump_mono_stats, SwitchWithOptPath::Enabled(Some("mono-items-dir/".into())));
+    untracked!(dump_mono_stats_format, DumpMonoStatsFormat::Json);
     untracked!(dylib_lto, true);
     untracked!(emit_stack_sizes, true);
     untracked!(future_incompat_test, true);
@@ -720,7 +723,6 @@ fn test_unstable_options_tracking_hash() {
             pac_ret: Some(PacRet { leaf: true, key: PAuthKey::B })
         })
     );
-    tracked!(chalk, true);
     tracked!(codegen_backend, Some("abc".to_string()));
     tracked!(crate_attr, vec!["abc".to_string()]);
     tracked!(debug_info_for_profiling, true);
@@ -790,6 +792,7 @@ fn test_unstable_options_tracking_hash() {
     tracked!(thinlto, Some(true));
     tracked!(thir_unsafeck, true);
     tracked!(tls_model, Some(TlsModel::GeneralDynamic));
+    tracked!(trait_solver, TraitSolver::Chalk);
     tracked!(translate_remapped_path_to_local_path, false);
     tracked!(trap_unreachable, Some(false));
     tracked!(treat_err_as_bug, NonZeroUsize::new(1));
diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs
index 4142964a0da..02a7756c8d4 100644
--- a/compiler/rustc_interface/src/util.rs
+++ b/compiler/rustc_interface/src/util.rs
@@ -205,13 +205,13 @@ pub(crate) fn run_in_thread_pool_with_globals<F: FnOnce() -> R + Send, R: Send>(
 
 fn load_backend_from_dylib(path: &Path) -> MakeBackendFn {
     let lib = unsafe { Library::new(path) }.unwrap_or_else(|err| {
-        let err = format!("couldn't load codegen backend {:?}: {}", path, err);
+        let err = format!("couldn't load codegen backend {path:?}: {err}");
         early_error(ErrorOutputType::default(), &err);
     });
 
     let backend_sym = unsafe { lib.get::<MakeBackendFn>(b"__rustc_codegen_backend") }
         .unwrap_or_else(|e| {
-            let err = format!("couldn't load codegen backend: {}", e);
+            let err = format!("couldn't load codegen backend: {e}");
             early_error(ErrorOutputType::default(), &err);
         });
 
@@ -304,8 +304,7 @@ fn get_codegen_sysroot(maybe_sysroot: &Option<PathBuf>, backend_name: &str) -> M
             .join("\n* ");
         let err = format!(
             "failed to find a `codegen-backends` folder \
-                           in the sysroot candidates:\n* {}",
-            candidates
+                           in the sysroot candidates:\n* {candidates}"
         );
         early_error(ErrorOutputType::default(), &err);
     });
@@ -325,7 +324,7 @@ fn get_codegen_sysroot(maybe_sysroot: &Option<PathBuf>, backend_name: &str) -> M
 
     let expected_names = &[
         format!("rustc_codegen_{}-{}", backend_name, env!("CFG_RELEASE")),
-        format!("rustc_codegen_{}", backend_name),
+        format!("rustc_codegen_{backend_name}"),
     ];
     for entry in d.filter_map(|e| e.ok()) {
         let path = entry.path();
@@ -354,7 +353,7 @@ fn get_codegen_sysroot(maybe_sysroot: &Option<PathBuf>, backend_name: &str) -> M
     match file {
         Some(ref s) => load_backend_from_dylib(s),
         None => {
-            let err = format!("unsupported builtin codegen backend `{}`", backend_name);
+            let err = format!("unsupported builtin codegen backend `{backend_name}`");
             early_error(ErrorOutputType::default(), &err);
         }
     }
@@ -389,7 +388,7 @@ pub(crate) fn check_attr_crate_type(
                             BuiltinLintDiagnostics::UnknownCrateTypes(
                                 span,
                                 "did you mean".to_string(),
-                                format!("\"{}\"", candidate),
+                                format!("\"{candidate}\""),
                             ),
                         );
                     } else {
diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index cdb901b7f86..d58168ff377 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -1392,7 +1392,7 @@ declare_lint! {
     ///
     /// The attribute must be used in conjunction with the
     /// [`closure_track_caller` feature flag]. Otherwise, the `#[track_caller]`
-    /// annotation will function as as no-op.
+    /// annotation will function as a no-op.
     ///
     /// [`closure_track_caller` feature flag]: https://doc.rust-lang.org/beta/unstable-book/language-features/closure-track-caller.html
     UNGATED_ASYNC_FN_TRACK_CALLER,
@@ -1526,7 +1526,7 @@ impl<'tcx> LateLintPass<'tcx> for UnreachablePub {
 
     fn check_field_def(&mut self, cx: &LateContext<'_>, field: &hir::FieldDef<'_>) {
         let map = cx.tcx.hir();
-        if matches!(map.get(map.get_parent_node(field.hir_id)), Node::Variant(_)) {
+        if matches!(map.get_parent(field.hir_id), Node::Variant(_)) {
             return;
         }
         self.perform_lint(cx, "field", field.def_id, field.vis_span, false);
diff --git a/compiler/rustc_lint/src/early.rs b/compiler/rustc_lint/src/early.rs
index 5f84d5c8b94..c18abaef8e2 100644
--- a/compiler/rustc_lint/src/early.rs
+++ b/compiler/rustc_lint/src/early.rs
@@ -29,7 +29,7 @@ macro_rules! lint_callback { ($cx:expr, $f:ident, $($args:expr),*) => ({
     $cx.pass.$f(&$cx.context, $($args),*);
 }) }
 
-/// Implements the AST traversal for early lint passes. `T` provides the the
+/// Implements the AST traversal for early lint passes. `T` provides the
 /// `check_*` methods.
 pub struct EarlyContextAndPass<'a, T: EarlyLintPass> {
     context: EarlyContext<'a>,
diff --git a/compiler/rustc_lint/src/internal.rs b/compiler/rustc_lint/src/internal.rs
index 4f92661dbd3..48902cd0569 100644
--- a/compiler/rustc_lint/src/internal.rs
+++ b/compiler/rustc_lint/src/internal.rs
@@ -143,7 +143,7 @@ impl<'tcx> LateLintPass<'tcx> for TyTyKind {
             TyKind::Path(QPath::Resolved(_, path)) => {
                 if lint_ty_kind_usage(cx, &path.res) {
                     let hir = cx.tcx.hir();
-                    let span = match hir.find(hir.get_parent_node(ty.hir_id)) {
+                    let span = match hir.find_parent(ty.hir_id) {
                         Some(Node::Pat(Pat {
                             kind:
                                 PatKind::Path(qpath)
diff --git a/compiler/rustc_lint/src/late.rs b/compiler/rustc_lint/src/late.rs
index e2876938d70..b2a2656746e 100644
--- a/compiler/rustc_lint/src/late.rs
+++ b/compiler/rustc_lint/src/late.rs
@@ -40,7 +40,7 @@ macro_rules! lint_callback { ($cx:expr, $f:ident, $($args:expr),*) => ({
     $cx.pass.$f(&$cx.context, $($args),*);
 }) }
 
-/// Implements the AST traversal for late lint passes. `T` provides the the
+/// Implements the AST traversal for late lint passes. `T` provides the
 /// `check_*` methods.
 pub struct LateContextAndPass<'tcx, T: LateLintPass<'tcx>> {
     context: LateContext<'tcx>,
diff --git a/compiler/rustc_lint/src/nonstandard_style.rs b/compiler/rustc_lint/src/nonstandard_style.rs
index 91fcd6d690e..f37d6e9a63d 100644
--- a/compiler/rustc_lint/src/nonstandard_style.rs
+++ b/compiler/rustc_lint/src/nonstandard_style.rs
@@ -444,8 +444,7 @@ impl<'tcx> LateLintPass<'tcx> for NonSnakeCase {
 
     fn check_pat(&mut self, cx: &LateContext<'_>, p: &hir::Pat<'_>) {
         if let PatKind::Binding(_, hid, ident, _) = p.kind {
-            if let hir::Node::PatField(field) = cx.tcx.hir().get(cx.tcx.hir().get_parent_node(hid))
-            {
+            if let hir::Node::PatField(field) = cx.tcx.hir().get_parent(hid) {
                 if !field.is_shorthand {
                     // Only check if a new name has been introduced, to avoid warning
                     // on both the struct definition and this pattern.
diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs
index 8e27bc03c48..fa415243ba0 100644
--- a/compiler/rustc_lint/src/types.rs
+++ b/compiler/rustc_lint/src/types.rs
@@ -127,10 +127,9 @@ fn lint_overflowing_range_endpoint<'tcx>(
 ) -> bool {
     // We only want to handle exclusive (`..`) ranges,
     // which are represented as `ExprKind::Struct`.
-    let par_id = cx.tcx.hir().get_parent_node(expr.hir_id);
+    let par_id = cx.tcx.hir().parent_id(expr.hir_id);
     let Node::ExprField(field) = cx.tcx.hir().get(par_id) else { return false };
-    let field_par_id = cx.tcx.hir().get_parent_node(field.hir_id);
-    let Node::Expr(struct_expr) = cx.tcx.hir().get(field_par_id) else { return false };
+    let Node::Expr(struct_expr) = cx.tcx.hir().get_parent(field.hir_id) else { return false };
     if !is_range_literal(struct_expr) {
         return false;
     };
@@ -404,7 +403,7 @@ fn lint_uint_literal<'tcx>(
         _ => bug!(),
     };
     if lit_val < min || lit_val > max {
-        let parent_id = cx.tcx.hir().get_parent_node(e.hir_id);
+        let parent_id = cx.tcx.hir().parent_id(e.hir_id);
         if let Node::Expr(par_e) = cx.tcx.hir().get(parent_id) {
             match par_e.kind {
                 hir::ExprKind::Cast(..) => {
diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs
index a7a5234049f..525079681ca 100644
--- a/compiler/rustc_lint/src/unused.rs
+++ b/compiler/rustc_lint/src/unused.rs
@@ -256,7 +256,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
                         cx.tcx,
                         cx.tcx.explicit_item_bounds(def).iter().cloned(),
                     )
-                    .filter_map(|obligation| {
+                    .find_map(|obligation| {
                         // We only look at the `DefId`, so it is safe to skip the binder here.
                         if let ty::PredicateKind::Clause(ty::Clause::Trait(
                             ref poly_trait_predicate,
@@ -270,22 +270,17 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
                         }
                     })
                     .map(|inner| MustUsePath::Opaque(Box::new(inner)))
-                    .next()
                 }
-                ty::Dynamic(binders, _, _) => binders
-                    .iter()
-                    .filter_map(|predicate| {
-                        if let ty::ExistentialPredicate::Trait(ref trait_ref) =
-                            predicate.skip_binder()
-                        {
-                            let def_id = trait_ref.def_id;
-                            is_def_must_use(cx, def_id, span)
-                        } else {
-                            None
-                        }
-                        .map(|inner| MustUsePath::TraitObject(Box::new(inner)))
-                    })
-                    .next(),
+                ty::Dynamic(binders, _, _) => binders.iter().find_map(|predicate| {
+                    if let ty::ExistentialPredicate::Trait(ref trait_ref) = predicate.skip_binder()
+                    {
+                        let def_id = trait_ref.def_id;
+                        is_def_must_use(cx, def_id, span)
+                            .map(|inner| MustUsePath::TraitObject(Box::new(inner)))
+                    } else {
+                        None
+                    }
+                }),
                 ty::Tuple(tys) => {
                     let elem_exprs = if let hir::ExprKind::Tup(elem_exprs) = expr.kind {
                         debug_assert_eq!(elem_exprs.len(), tys.len());
diff --git a/compiler/rustc_llvm/build.rs b/compiler/rustc_llvm/build.rs
index 0b3c057345a..9fe59a1d826 100644
--- a/compiler/rustc_llvm/build.rs
+++ b/compiler/rustc_llvm/build.rs
@@ -58,7 +58,7 @@ fn restore_library_path() {
 /// Supposed to be used for all variables except those set for build scripts by cargo
 /// <https://doc.rust-lang.org/cargo/reference/environment-variables.html#environment-variables-cargo-sets-for-build-scripts>
 fn tracked_env_var_os<K: AsRef<OsStr> + Display>(key: K) -> Option<OsString> {
-    println!("cargo:rerun-if-env-changed={}", key);
+    println!("cargo:rerun-if-env-changed={key}");
     env::var_os(key)
 }
 
@@ -84,7 +84,7 @@ fn output(cmd: &mut Command) -> String {
     let output = match cmd.stderr(Stdio::inherit()).output() {
         Ok(status) => status,
         Err(e) => {
-            println!("\n\nfailed to execute command: {:?}\nerror: {}\n\n", cmd, e);
+            println!("\n\nfailed to execute command: {cmd:?}\nerror: {e}\n\n");
             std::process::exit(1);
         }
     };
@@ -100,7 +100,7 @@ fn output(cmd: &mut Command) -> String {
 
 fn main() {
     for component in REQUIRED_COMPONENTS.iter().chain(OPTIONAL_COMPONENTS.iter()) {
-        println!("cargo:rustc-check-cfg=values(llvm_component,\"{}\")", component);
+        println!("cargo:rustc-check-cfg=values(llvm_component,\"{component}\")");
     }
 
     if tracked_env_var_os("RUST_CHECK").is_some() {
@@ -164,12 +164,12 @@ fn main() {
 
     for component in REQUIRED_COMPONENTS {
         if !components.contains(component) {
-            panic!("require llvm component {} but wasn't found", component);
+            panic!("require llvm component {component} but wasn't found");
         }
     }
 
     for component in components.iter() {
-        println!("cargo:rustc-cfg=llvm_component=\"{}\"", component);
+        println!("cargo:rustc-cfg=llvm_component=\"{component}\"");
     }
 
     // Link in our own LLVM shims, compiled with the same flags as LLVM
@@ -283,7 +283,7 @@ fn main() {
         }
 
         let kind = if name.starts_with("LLVM") { llvm_kind } else { "dylib" };
-        println!("cargo:rustc-link-lib={}={}", kind, name);
+        println!("cargo:rustc-link-lib={kind}={name}");
     }
 
     // LLVM ldflags
@@ -302,11 +302,11 @@ fn main() {
                 println!("cargo:rustc-link-search=native={}", stripped.replace(&host, &target));
             }
         } else if let Some(stripped) = lib.strip_prefix("-LIBPATH:") {
-            println!("cargo:rustc-link-search=native={}", stripped);
+            println!("cargo:rustc-link-search=native={stripped}");
         } else if let Some(stripped) = lib.strip_prefix("-l") {
-            println!("cargo:rustc-link-lib={}", stripped);
+            println!("cargo:rustc-link-lib={stripped}");
         } else if let Some(stripped) = lib.strip_prefix("-L") {
-            println!("cargo:rustc-link-search=native={}", stripped);
+            println!("cargo:rustc-link-search=native={stripped}");
         }
     }
 
@@ -318,9 +318,9 @@ fn main() {
     if let Some(s) = llvm_linker_flags {
         for lib in s.into_string().unwrap().split_whitespace() {
             if let Some(stripped) = lib.strip_prefix("-l") {
-                println!("cargo:rustc-link-lib={}", stripped);
+                println!("cargo:rustc-link-lib={stripped}");
             } else if let Some(stripped) = lib.strip_prefix("-L") {
-                println!("cargo:rustc-link-search=native={}", stripped);
+                println!("cargo:rustc-link-search=native={stripped}");
             }
         }
     }
@@ -359,14 +359,14 @@ fn main() {
             let path = PathBuf::from(s);
             println!("cargo:rustc-link-search=native={}", path.parent().unwrap().display());
             if target.contains("windows") {
-                println!("cargo:rustc-link-lib=static:-bundle={}", stdcppname);
+                println!("cargo:rustc-link-lib=static:-bundle={stdcppname}");
             } else {
-                println!("cargo:rustc-link-lib=static={}", stdcppname);
+                println!("cargo:rustc-link-lib=static={stdcppname}");
             }
         } else if cxxflags.contains("stdlib=libc++") {
             println!("cargo:rustc-link-lib=c++");
         } else {
-            println!("cargo:rustc-link-lib={}", stdcppname);
+            println!("cargo:rustc-link-lib={stdcppname}");
         }
     }
 
diff --git a/compiler/rustc_log/src/lib.rs b/compiler/rustc_log/src/lib.rs
index ddf29c488c9..4cac88aff64 100644
--- a/compiler/rustc_log/src/lib.rs
+++ b/compiler/rustc_log/src/lib.rs
@@ -114,8 +114,7 @@ impl Display for Error {
         match self {
             Error::InvalidColorValue(value) => write!(
                 formatter,
-                "invalid log color value '{}': expected one of always, never, or auto",
-                value,
+                "invalid log color value '{value}': expected one of always, never, or auto",
             ),
             Error::NonUnicodeColorValue => write!(
                 formatter,
diff --git a/compiler/rustc_macros/src/diagnostics/error.rs b/compiler/rustc_macros/src/diagnostics/error.rs
index 4612f54e4b1..2d62d593163 100644
--- a/compiler/rustc_macros/src/diagnostics/error.rs
+++ b/compiler/rustc_macros/src/diagnostics/error.rs
@@ -76,11 +76,11 @@ pub(crate) fn invalid_attr(attr: &Attribute, meta: &Meta) -> Diagnostic {
     let span = attr.span().unwrap();
     let path = path_to_string(&attr.path);
     match meta {
-        Meta::Path(_) => span_err(span, &format!("`#[{}]` is not a valid attribute", path)),
+        Meta::Path(_) => span_err(span, &format!("`#[{path}]` is not a valid attribute")),
         Meta::NameValue(_) => {
-            span_err(span, &format!("`#[{} = ...]` is not a valid attribute", path))
+            span_err(span, &format!("`#[{path} = ...]` is not a valid attribute"))
         }
-        Meta::List(_) => span_err(span, &format!("`#[{}(...)]` is not a valid attribute", path)),
+        Meta::List(_) => span_err(span, &format!("`#[{path}(...)]` is not a valid attribute")),
     }
 }
 
@@ -107,7 +107,7 @@ pub(crate) fn invalid_nested_attr(attr: &Attribute, nested: &NestedMeta) -> Diag
     let meta = match nested {
         syn::NestedMeta::Meta(meta) => meta,
         syn::NestedMeta::Lit(_) => {
-            return span_err(span, &format!("`#[{}(\"...\")]` is not a valid attribute", name));
+            return span_err(span, &format!("`#[{name}(\"...\")]` is not a valid attribute"));
         }
     };
 
@@ -115,13 +115,11 @@ pub(crate) fn invalid_nested_attr(attr: &Attribute, nested: &NestedMeta) -> Diag
     let path = path_to_string(meta.path());
     match meta {
         Meta::NameValue(..) => {
-            span_err(span, &format!("`#[{}({} = ...)]` is not a valid attribute", name, path))
-        }
-        Meta::Path(..) => {
-            span_err(span, &format!("`#[{}({})]` is not a valid attribute", name, path))
+            span_err(span, &format!("`#[{name}({path} = ...)]` is not a valid attribute"))
         }
+        Meta::Path(..) => span_err(span, &format!("`#[{name}({path})]` is not a valid attribute")),
         Meta::List(..) => {
-            span_err(span, &format!("`#[{}({}(...))]` is not a valid attribute", name, path))
+            span_err(span, &format!("`#[{name}({path}(...))]` is not a valid attribute"))
         }
     }
 }
diff --git a/compiler/rustc_macros/src/diagnostics/fluent.rs b/compiler/rustc_macros/src/diagnostics/fluent.rs
index 3e447c94ef1..32338f9dfc5 100644
--- a/compiler/rustc_macros/src/diagnostics/fluent.rs
+++ b/compiler/rustc_macros/src/diagnostics/fluent.rs
@@ -178,7 +178,7 @@ pub(crate) fn fluent_messages(input: proc_macro::TokenStream) -> proc_macro::Tok
                         opt: Default::default(),
                     };
                     let dl = DisplayList::from(snippet);
-                    eprintln!("{}\n", dl);
+                    eprintln!("{dl}\n");
                 }
                 continue;
             }
@@ -265,7 +265,7 @@ pub(crate) fn fluent_messages(input: proc_macro::TokenStream) -> proc_macro::Tok
                         Diagnostic::spanned(
                             path_span,
                             Level::Error,
-                            format!("overrides existing {}: `{}`", kind, id),
+                            format!("overrides existing {kind}: `{id}`"),
                         )
                         .span_help(previous_defns[&id], "previously defined in this resource")
                         .emit();
diff --git a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs
index 767db367322..baffd3cec9c 100644
--- a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs
+++ b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs
@@ -198,8 +198,7 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> {
                 throw_span_err!(
                     attr.span().unwrap(),
                     &format!(
-                        "diagnostic slug must be first argument of a `#[{}(...)]` attribute",
-                        name
+                        "diagnostic slug must be first argument of a `#[{name}(...)]` attribute"
                     )
                 );
             };
diff --git a/compiler/rustc_macros/src/diagnostics/utils.rs b/compiler/rustc_macros/src/diagnostics/utils.rs
index 4ff9c777ad8..6f52a3de1b1 100644
--- a/compiler/rustc_macros/src/diagnostics/utils.rs
+++ b/compiler/rustc_macros/src/diagnostics/utils.rs
@@ -322,7 +322,7 @@ pub(crate) trait HasFieldMap {
                 None => {
                     span_err(
                         span.unwrap(),
-                        &format!("`{}` doesn't refer to a field on this type", field),
+                        &format!("`{field}` doesn't refer to a field on this type"),
                     )
                     .emit();
                     quote! {
@@ -603,8 +603,7 @@ impl SubdiagnosticKind {
                     if suggestion_kind != SuggestionKind::Normal {
                         invalid_attr(attr, &meta)
                             .help(format!(
-                                r#"Use `#[suggestion(..., style = "{}")]` instead"#,
-                                suggestion_kind
+                                r#"Use `#[suggestion(..., style = "{suggestion_kind}")]` instead"#
                             ))
                             .emit();
                     }
@@ -621,8 +620,7 @@ impl SubdiagnosticKind {
                     if suggestion_kind != SuggestionKind::Normal {
                         invalid_attr(attr, &meta)
                             .help(format!(
-                                r#"Use `#[multipart_suggestion(..., style = "{}")]` instead"#,
-                                suggestion_kind
+                                r#"Use `#[multipart_suggestion(..., style = "{suggestion_kind}")]` instead"#
                             ))
                             .emit();
                     }
diff --git a/compiler/rustc_macros/src/newtype.rs b/compiler/rustc_macros/src/newtype.rs
index 153473de624..89ea89cf502 100644
--- a/compiler/rustc_macros/src/newtype.rs
+++ b/compiler/rustc_macros/src/newtype.rs
@@ -41,7 +41,7 @@ impl Parse for Newtype {
                     };
 
                     if let Some(old) = max.replace(literal.lit) {
-                        panic!("Specified multiple max: {:?}", old);
+                        panic!("Specified multiple max: {old:?}");
                     }
 
                     false
@@ -52,7 +52,7 @@ impl Parse for Newtype {
                     };
 
                     if let Some(old) = debug_format.replace(literal.lit) {
-                        panic!("Specified multiple debug format options: {:?}", old);
+                        panic!("Specified multiple debug format options: {old:?}");
                     }
 
                     false
diff --git a/compiler/rustc_macros/src/query.rs b/compiler/rustc_macros/src/query.rs
index 789d83a0dd0..08e42a8a08f 100644
--- a/compiler/rustc_macros/src/query.rs
+++ b/compiler/rustc_macros/src/query.rs
@@ -239,7 +239,7 @@ fn doc_comment_from_desc(list: &Punctuated<Expr, token::Comma>) -> Result<Attrib
             .unwrap();
         },
     );
-    let doc_string = format!("[query description - consider adding a doc-comment!] {}", doc_string);
+    let doc_string = format!("[query description - consider adding a doc-comment!] {doc_string}");
     Ok(parse_quote! { #[doc = #doc_string] })
 }
 
diff --git a/compiler/rustc_macros/src/symbols.rs b/compiler/rustc_macros/src/symbols.rs
index 92590c33b9d..04facbf657d 100644
--- a/compiler/rustc_macros/src/symbols.rs
+++ b/compiler/rustc_macros/src/symbols.rs
@@ -134,7 +134,7 @@ fn symbols_with_errors(input: TokenStream) -> (TokenStream, Vec<syn::Error>) {
 
     let mut check_dup = |span: Span, str: &str, errors: &mut Errors| {
         if let Some(prev_span) = keys.get(str) {
-            errors.error(span, format!("Symbol `{}` is duplicated", str));
+            errors.error(span, format!("Symbol `{str}` is duplicated"));
             errors.error(*prev_span, "location of previous definition".to_string());
         } else {
             keys.insert(str.to_string(), span);
@@ -144,8 +144,8 @@ fn symbols_with_errors(input: TokenStream) -> (TokenStream, Vec<syn::Error>) {
     let mut check_order = |span: Span, str: &str, errors: &mut Errors| {
         if let Some((prev_span, ref prev_str)) = prev_key {
             if str < prev_str {
-                errors.error(span, format!("Symbol `{}` must precede `{}`", str, prev_str));
-                errors.error(prev_span, format!("location of previous symbol `{}`", prev_str));
+                errors.error(span, format!("Symbol `{str}` must precede `{prev_str}`"));
+                errors.error(prev_span, format!("location of previous symbol `{prev_str}`"));
             }
         }
         prev_key = Some((span, str.to_string()));
diff --git a/compiler/rustc_macros/src/symbols/tests.rs b/compiler/rustc_macros/src/symbols/tests.rs
index 842d2a97718..bd0c08a53c4 100644
--- a/compiler/rustc_macros/src/symbols/tests.rs
+++ b/compiler/rustc_macros/src/symbols/tests.rs
@@ -16,14 +16,13 @@ fn test_symbols() {
     let m: &syn::ItemMacro = file
         .items
         .iter()
-        .filter_map(|i| {
+        .find_map(|i| {
             if let syn::Item::Macro(m) = i {
                 if m.mac.path == symbols_path { Some(m) } else { None }
             } else {
                 None
             }
         })
-        .next()
         .expect("did not find `symbols!` macro invocation.");
 
     let body_tokens = m.mac.tokens.clone();
diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs
index b34dc0df1e2..653f2b39d3e 100644
--- a/compiler/rustc_metadata/src/creader.rs
+++ b/compiler/rustc_metadata/src/creader.rs
@@ -112,7 +112,7 @@ impl<'a> std::fmt::Debug for CrateDump<'a> {
         writeln!(fmt, "resolved crates:")?;
         for (cnum, data) in self.0.iter_crate_data() {
             writeln!(fmt, "  name: {}", data.name())?;
-            writeln!(fmt, "  cnum: {}", cnum)?;
+            writeln!(fmt, "  cnum: {cnum}")?;
             writeln!(fmt, "  hash: {}", data.hash())?;
             writeln!(fmt, "  reqd: {:?}", data.dep_kind())?;
             let CrateSource { dylib, rlib, rmeta } = data.source();
@@ -150,7 +150,7 @@ impl CStore {
     pub(crate) fn get_crate_data(&self, cnum: CrateNum) -> CrateMetadataRef<'_> {
         let cdata = self.metas[cnum]
             .as_ref()
-            .unwrap_or_else(|| panic!("Failed to get crate data for {:?}", cnum));
+            .unwrap_or_else(|| panic!("Failed to get crate data for {cnum:?}"));
         CrateMetadataRef { cdata, cstore: self }
     }
 
diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs
index 1fd35adf1bd..59869ee4173 100644
--- a/compiler/rustc_metadata/src/native_libs.rs
+++ b/compiler/rustc_metadata/src/native_libs.rs
@@ -45,7 +45,7 @@ pub fn find_native_static_library(
 
     for path in search_paths {
         for (prefix, suffix) in &formats {
-            let test = path.join(format!("{}{}{}", prefix, name, suffix));
+            let test = path.join(format!("{prefix}{name}{suffix}"));
             if test.exists() {
                 return test;
             }
diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs
index 99d8225a4c3..143d8f2f1e1 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder.rs
@@ -462,7 +462,7 @@ impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for SyntaxContext {
                 .root
                 .syntax_contexts
                 .get(cdata, id)
-                .unwrap_or_else(|| panic!("Missing SyntaxContext {:?} for crate {:?}", id, cname))
+                .unwrap_or_else(|| panic!("Missing SyntaxContext {id:?} for crate {cname:?}"))
                 .decode((cdata, sess))
         })
     }
@@ -806,7 +806,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
             .tables
             .def_span
             .get(self, index)
-            .unwrap_or_else(|| panic!("Missing span for {:?}", index))
+            .unwrap_or_else(|| panic!("Missing span for {index:?}"))
             .decode((self, sess))
     }
 
@@ -1249,7 +1249,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
             .tables
             .proc_macro_quoted_spans
             .get(self, index)
-            .unwrap_or_else(|| panic!("Missing proc macro quoted span: {:?}", index))
+            .unwrap_or_else(|| panic!("Missing proc macro quoted span: {index:?}"))
             .decode((self, sess))
     }
 
diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
index e167bbf57e6..cb451931dfe 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
@@ -230,7 +230,7 @@ provide! { tcx, def_id, other, cdata,
             .trait_impl_trait_tys
             .get(cdata, def_id.index)
             .map(|lazy| lazy.decode((cdata, tcx)))
-            .process_decoded(tcx, || panic!("{:?} does not have trait_impl_trait_tys", def_id)))
+            .process_decoded(tcx, || panic!("{def_id:?} does not have trait_impl_trait_tys")))
      }
 
     visibility => { cdata.get_visibility(def_id.index) }
diff --git a/compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs b/compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs
index 40c94b372bb..a6133f1b417 100644
--- a/compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs
+++ b/compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs
@@ -58,7 +58,7 @@ impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for DefPathHashMapRef<'static>
         let _ = d.read_raw_bytes(len);
 
         let inner = odht::HashTable::from_raw_bytes(o).unwrap_or_else(|e| {
-            panic!("decode error: {}", e);
+            panic!("decode error: {e}");
         });
         DefPathHashMapRef::OwnedFromMetadata(inner)
     }
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index 214a5842233..0d9f216700f 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -145,7 +145,7 @@ impl<'a, 'tcx, I, T> Encodable<EncodeContext<'a, 'tcx>> for LazyTable<I, T> {
 impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for CrateNum {
     fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) {
         if *self != LOCAL_CRATE && s.is_proc_macro {
-            panic!("Attempted to encode non-local CrateNum {:?} for proc-macro crate", self);
+            panic!("Attempted to encode non-local CrateNum {self:?} for proc-macro crate");
         }
         s.emit_u32(self.as_u32());
     }
@@ -276,7 +276,7 @@ impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for Span {
                 // Introduce a new scope so that we drop the 'lock()' temporary
                 match &*source_file.external_src.lock() {
                     ExternalSource::Foreign { metadata_index, .. } => *metadata_index,
-                    src => panic!("Unexpected external source {:?}", src),
+                    src => panic!("Unexpected external source {src:?}"),
                 }
             };
 
@@ -733,12 +733,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
             let prefix = "meta-stats";
             let perc = |bytes| (bytes * 100) as f64 / total_bytes as f64;
 
-            eprintln!("{} METADATA STATS", prefix);
+            eprintln!("{prefix} METADATA STATS");
             eprintln!("{} {:<23}{:>10}", prefix, "Section", "Size");
-            eprintln!(
-                "{} ----------------------------------------------------------------",
-                prefix
-            );
+            eprintln!("{prefix} ----------------------------------------------------------------");
             for (label, size) in stats {
                 eprintln!(
                     "{} {:<23}{:>10} ({:4.1}%)",
@@ -748,10 +745,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
                     perc(size)
                 );
             }
-            eprintln!(
-                "{} ----------------------------------------------------------------",
-                prefix
-            );
+            eprintln!("{prefix} ----------------------------------------------------------------");
             eprintln!(
                 "{} {:<23}{:>10} (of which {:.1}% are zero bytes)",
                 prefix,
@@ -759,7 +753,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
                 to_readable_str(total_bytes),
                 perc(zero_bytes)
             );
-            eprintln!("{}", prefix);
+            eprintln!("{prefix}");
         }
 
         root
diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs
index d799d3a5ad7..883554f959c 100644
--- a/compiler/rustc_middle/src/hir/map/mod.rs
+++ b/compiler/rustc_middle/src/hir/map/mod.rs
@@ -69,7 +69,7 @@ impl<'hir> Iterator for ParentHirIterator<'hir> {
         }
         loop {
             // There are nodes that do not have entries, so we need to skip them.
-            let parent_id = self.map.get_parent_node(self.current_id);
+            let parent_id = self.map.parent_id(self.current_id);
 
             if parent_id == self.current_id {
                 self.current_id = CRATE_HIR_ID;
@@ -246,7 +246,7 @@ impl<'hir> Map<'hir> {
             },
             Node::Variant(_) => DefKind::Variant,
             Node::Ctor(variant_data) => {
-                let ctor_of = match self.find(self.get_parent_node(hir_id)) {
+                let ctor_of = match self.find_parent(hir_id) {
                     Some(Node::Item(..)) => def::CtorOf::Struct,
                     Some(Node::Variant(..)) => def::CtorOf::Variant,
                     _ => unreachable!(),
@@ -257,7 +257,7 @@ impl<'hir> Map<'hir> {
                 }
             }
             Node::AnonConst(_) => {
-                let inline = match self.find(self.get_parent_node(hir_id)) {
+                let inline = match self.find_parent(hir_id) {
                     Some(Node::Expr(&Expr {
                         kind: ExprKind::ConstBlock(ref anon_const), ..
                     })) if anon_const.hir_id == hir_id => true,
@@ -298,7 +298,7 @@ impl<'hir> Map<'hir> {
     /// Finds the id of the parent node to this one.
     ///
     /// If calling repeatedly and iterating over parents, prefer [`Map::parent_iter`].
-    pub fn find_parent_node(self, id: HirId) -> Option<HirId> {
+    pub fn opt_parent_id(self, id: HirId) -> Option<HirId> {
         if id.local_id == ItemLocalId::from_u32(0) {
             Some(self.tcx.hir_owner_parent(id.owner))
         } else {
@@ -312,11 +312,19 @@ impl<'hir> Map<'hir> {
     }
 
     #[track_caller]
-    pub fn get_parent_node(self, hir_id: HirId) -> HirId {
-        self.find_parent_node(hir_id)
+    pub fn parent_id(self, hir_id: HirId) -> HirId {
+        self.opt_parent_id(hir_id)
             .unwrap_or_else(|| bug!("No parent for node {:?}", self.node_to_string(hir_id)))
     }
 
+    pub fn get_parent(self, hir_id: HirId) -> Node<'hir> {
+        self.get(self.parent_id(hir_id))
+    }
+
+    pub fn find_parent(self, hir_id: HirId) -> Option<Node<'hir>> {
+        self.find(self.opt_parent_id(hir_id)?)
+    }
+
     /// Retrieves the `Node` corresponding to `id`, returning `None` if cannot be found.
     pub fn find(self, id: HirId) -> Option<Node<'hir>> {
         if id.local_id == ItemLocalId::from_u32(0) {
@@ -414,7 +422,7 @@ impl<'hir> Map<'hir> {
     /// which this is the body of, i.e., a `fn`, `const` or `static`
     /// item (possibly associated), a closure, or a `hir::AnonConst`.
     pub fn body_owner(self, BodyId { hir_id }: BodyId) -> HirId {
-        let parent = self.get_parent_node(hir_id);
+        let parent = self.parent_id(hir_id);
         assert!(self.find(parent).map_or(false, |n| is_body_owner(n, hir_id)), "{hir_id:?}");
         parent
     }
@@ -642,21 +650,21 @@ impl<'hir> Map<'hir> {
     }
 
     /// Returns an iterator for the nodes in the ancestor tree of the `current_id`
-    /// until the crate root is reached. Prefer this over your own loop using `get_parent_node`.
+    /// until the crate root is reached. Prefer this over your own loop using `parent_id`.
     #[inline]
     pub fn parent_id_iter(self, current_id: HirId) -> impl Iterator<Item = HirId> + 'hir {
         ParentHirIterator { current_id, map: self }
     }
 
     /// Returns an iterator for the nodes in the ancestor tree of the `current_id`
-    /// until the crate root is reached. Prefer this over your own loop using `get_parent_node`.
+    /// until the crate root is reached. Prefer this over your own loop using `parent_id`.
     #[inline]
     pub fn parent_iter(self, current_id: HirId) -> impl Iterator<Item = (HirId, Node<'hir>)> {
         self.parent_id_iter(current_id).filter_map(move |id| Some((id, self.find(id)?)))
     }
 
     /// Returns an iterator for the nodes in the ancestor tree of the `current_id`
-    /// until the crate root is reached. Prefer this over your own loop using `get_parent_node`.
+    /// until the crate root is reached. Prefer this over your own loop using `parent_id`.
     #[inline]
     pub fn parent_owner_iter(self, current_id: HirId) -> ParentOwnerIterator<'hir> {
         ParentOwnerIterator { current_id, map: self }
@@ -664,7 +672,7 @@ impl<'hir> Map<'hir> {
 
     /// Checks if the node is left-hand side of an assignment.
     pub fn is_lhs(self, id: HirId) -> bool {
-        match self.find(self.get_parent_node(id)) {
+        match self.find_parent(id) {
             Some(Node::Expr(expr)) => match expr.kind {
                 ExprKind::Assign(lhs, _rhs, _span) => lhs.hir_id == id,
                 _ => false,
@@ -892,7 +900,7 @@ impl<'hir> Map<'hir> {
             Node::Pat(&Pat { kind: PatKind::Binding(_, _, ident, _), .. }) => Some(ident),
             // A `Ctor` doesn't have an identifier itself, but its parent
             // struct/variant does. Compare with `hir::Map::opt_span`.
-            Node::Ctor(..) => match self.find(self.get_parent_node(id))? {
+            Node::Ctor(..) => match self.find_parent(id)? {
                 Node::Item(item) => Some(item.ident),
                 Node::Variant(variant) => Some(variant.ident),
                 _ => unreachable!(),
@@ -1021,7 +1029,7 @@ impl<'hir> Map<'hir> {
                 ForeignItemKind::Fn(decl, _, _) => until_within(item.span, decl.output.span()),
                 _ => named_span(item.span, item.ident, None),
             },
-            Node::Ctor(_) => return self.opt_span(self.get_parent_node(hir_id)),
+            Node::Ctor(_) => return self.opt_span(self.parent_id(hir_id)),
             Node::Expr(Expr {
                 kind: ExprKind::Closure(Closure { fn_decl_span, .. }),
                 span,
@@ -1063,7 +1071,7 @@ impl<'hir> Map<'hir> {
             Node::PatField(field) => field.span,
             Node::Arm(arm) => arm.span,
             Node::Block(block) => block.span,
-            Node::Ctor(..) => self.span_with_body(self.get_parent_node(hir_id)),
+            Node::Ctor(..) => self.span_with_body(self.parent_id(hir_id)),
             Node::Lifetime(lifetime) => lifetime.ident.span,
             Node::GenericParam(param) => param.span,
             Node::Infer(i) => i.span,
@@ -1093,7 +1101,7 @@ impl<'hir> Map<'hir> {
     /// Returns the HirId of `N` in `struct Foo<const N: usize = { ... }>` when
     /// called with the HirId for the `{ ... }` anon const
     pub fn opt_const_param_default_param_def_id(self, anon_const: HirId) -> Option<LocalDefId> {
-        match self.get(self.get_parent_node(anon_const)) {
+        match self.get_parent(anon_const) {
             Node::GenericParam(GenericParam {
                 def_id: param_id,
                 kind: GenericParamKind::Const { .. },
diff --git a/compiler/rustc_middle/src/lint.rs b/compiler/rustc_middle/src/lint.rs
index 51df42f6d14..eb48b325e84 100644
--- a/compiler/rustc_middle/src/lint.rs
+++ b/compiler/rustc_middle/src/lint.rs
@@ -182,7 +182,7 @@ impl TyCtxt<'_> {
             if hir.attrs(id).iter().any(|attr| Level::from_attr(attr).is_some()) {
                 return id;
             }
-            let next = hir.get_parent_node(id);
+            let next = hir.parent_id(id);
             if next == id {
                 bug!("lint traversal reached the root of the crate");
             }
diff --git a/compiler/rustc_middle/src/macros.rs b/compiler/rustc_middle/src/macros.rs
index 01fe72de612..5ca4d260179 100644
--- a/compiler/rustc_middle/src/macros.rs
+++ b/compiler/rustc_middle/src/macros.rs
@@ -1,3 +1,13 @@
+/// A macro for triggering an ICE.
+/// Calling `bug` instead of panicking will result in a nicer error message and should
+/// therefore be prefered over `panic`/`unreachable` or others.
+///
+/// If you have a span available, you should use [`span_bug`] instead.
+///
+/// If the bug should only be emitted when compilation didn't fail, [`Session::delay_span_bug`] may be useful.
+///
+/// [`Session::delay_span_bug`]: rustc_session::Session::delay_span_bug
+/// [`span_bug`]: crate::span_bug
 #[macro_export]
 macro_rules! bug {
     () => ( $crate::bug!("impossible case reached") );
@@ -8,6 +18,14 @@ macro_rules! bug {
     });
 }
 
+/// A macro for triggering an ICE with a span.
+/// Calling `span_bug!` instead of panicking will result in a nicer error message and point
+/// at the code the compiler was compiling when it ICEd. This is the preferred way to trigger
+/// ICEs.
+///
+/// If the bug should only be emitted when compilation didn't fail, [`Session::delay_span_bug`] may be useful.
+///
+/// [`Session::delay_span_bug`]: rustc_session::Session::delay_span_bug
 #[macro_export]
 macro_rules! span_bug {
     ($span:expr, $msg:expr) => ({ $crate::util::bug::span_bug_fmt($span, ::std::format_args!($msg)) });
diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs
index a89e6566d56..14bdff4568f 100644
--- a/compiler/rustc_middle/src/mir/mod.rs
+++ b/compiler/rustc_middle/src/mir/mod.rs
@@ -2506,7 +2506,7 @@ impl<'tcx> ConstantKind<'tcx> {
         }
 
         let hir_id = tcx.hir().local_def_id_to_hir_id(def.did);
-        let parent_substs = if let Some(parent_hir_id) = tcx.hir().find_parent_node(hir_id) {
+        let parent_substs = if let Some(parent_hir_id) = tcx.hir().opt_parent_id(hir_id) {
             if let Some(parent_did) = tcx.hir().opt_local_def_id(parent_hir_id) {
                 InternalSubsts::identity_for_item(tcx, parent_did.to_def_id())
             } else {
diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs
index 2ee3f551529..1a264d2d5af 100644
--- a/compiler/rustc_middle/src/mir/visit.rs
+++ b/compiler/rustc_middle/src/mir/visit.rs
@@ -3,15 +3,15 @@
 //! ## Overview
 //!
 //! There are two visitors, one for immutable and one for mutable references,
-//! but both are generated by the following macro. The code is written according
-//! to the following conventions:
+//! but both are generated by the `make_mir_visitor` macro.
+//! The code is written according to the following conventions:
 //!
 //! - introduce a `visit_foo` and a `super_foo` method for every MIR type
 //! - `visit_foo`, by default, calls `super_foo`
 //! - `super_foo`, by default, destructures the `foo` and calls `visit_foo`
 //!
-//! This allows you as a user to override `visit_foo` for types are
-//! interested in, and invoke (within that method) call
+//! This allows you to override `visit_foo` for types you are
+//! interested in, and invoke (within that method call)
 //! `self.super_foo` to get the default behavior. Just as in an OO
 //! language, you should never call `super` methods ordinarily except
 //! in that circumstance.
diff --git a/compiler/rustc_middle/src/ty/erase_regions.rs b/compiler/rustc_middle/src/ty/erase_regions.rs
index ffdac93bcd0..9e4f90caab0 100644
--- a/compiler/rustc_middle/src/ty/erase_regions.rs
+++ b/compiler/rustc_middle/src/ty/erase_regions.rs
@@ -21,7 +21,7 @@ impl<'tcx> TyCtxt<'tcx> {
         T: TypeFoldable<'tcx>,
     {
         // If there's nothing to erase avoid performing the query at all
-        if !value.has_type_flags(TypeFlags::HAS_RE_LATE_BOUND | TypeFlags::HAS_FREE_REGIONS) {
+        if !value.has_type_flags(TypeFlags::HAS_LATE_BOUND | TypeFlags::HAS_FREE_REGIONS) {
             return value;
         }
         debug!("erase_regions({:?})", value);
diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs
index 14d07608a78..50554cf9a82 100644
--- a/compiler/rustc_middle/src/ty/error.rs
+++ b/compiler/rustc_middle/src/ty/error.rs
@@ -457,7 +457,7 @@ impl<'tcx> TyCtxt<'tcx> {
                             .def_id
                             .as_local()
                             .map(|id| hir.local_def_id_to_hir_id(id))
-                            .and_then(|id| self.hir().find(self.hir().get_parent_node(id)))
+                            .and_then(|id| self.hir().find_parent(id))
                             .as_ref()
                             .and_then(|node| node.generics())
                         {
diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs
index 8306d670a65..b7eafc4b437 100644
--- a/compiler/rustc_middle/src/ty/flags.rs
+++ b/compiler/rustc_middle/src/ty/flags.rs
@@ -59,8 +59,18 @@ impl FlagComputation {
     {
         let mut computation = FlagComputation::new();
 
-        if !value.bound_vars().is_empty() {
-            computation.flags = computation.flags | TypeFlags::HAS_RE_LATE_BOUND;
+        for bv in value.bound_vars() {
+            match bv {
+                ty::BoundVariableKind::Ty(_) => {
+                    computation.flags |= TypeFlags::HAS_TY_LATE_BOUND;
+                }
+                ty::BoundVariableKind::Region(_) => {
+                    computation.flags |= TypeFlags::HAS_RE_LATE_BOUND;
+                }
+                ty::BoundVariableKind::Const => {
+                    computation.flags |= TypeFlags::HAS_CT_LATE_BOUND;
+                }
+            }
         }
 
         f(&mut computation, value.skip_binder());
@@ -131,6 +141,7 @@ impl FlagComputation {
 
             &ty::Bound(debruijn, _) => {
                 self.add_bound_var(debruijn);
+                self.add_flags(TypeFlags::HAS_TY_LATE_BOUND);
             }
 
             &ty::Placeholder(..) => {
@@ -303,6 +314,7 @@ impl FlagComputation {
             }
             ty::ConstKind::Bound(debruijn, _) => {
                 self.add_bound_var(debruijn);
+                self.add_flags(TypeFlags::HAS_CT_LATE_BOUND);
             }
             ty::ConstKind::Param(_) => {
                 self.add_flags(TypeFlags::HAS_CT_PARAM);
diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs
index 9e0ca44d098..00f53afd663 100644
--- a/compiler/rustc_middle/src/ty/layout.rs
+++ b/compiler/rustc_middle/src/ty/layout.rs
@@ -670,29 +670,50 @@ where
                         });
                     }
 
-                    match tcx.struct_tail_erasing_lifetimes(pointee, cx.param_env()).kind() {
-                        ty::Slice(_) | ty::Str => TyMaybeWithLayout::Ty(tcx.types.usize),
-                        ty::Dynamic(_, _, ty::Dyn) => {
-                            TyMaybeWithLayout::Ty(tcx.mk_imm_ref(
-                                tcx.lifetimes.re_static,
-                                tcx.mk_array(tcx.types.usize, 3),
-                            ))
-                            /* FIXME: use actual fn pointers
-                            Warning: naively computing the number of entries in the
-                            vtable by counting the methods on the trait + methods on
-                            all parent traits does not work, because some methods can
-                            be not object safe and thus excluded from the vtable.
-                            Increase this counter if you tried to implement this but
-                            failed to do it without duplicating a lot of code from
-                            other places in the compiler: 2
-                            tcx.mk_tup(&[
-                                tcx.mk_array(tcx.types.usize, 3),
-                                tcx.mk_array(Option<fn()>),
-                            ])
-                            */
+                    let mk_dyn_vtable = || {
+                        tcx.mk_imm_ref(tcx.lifetimes.re_static, tcx.mk_array(tcx.types.usize, 3))
+                        /* FIXME: use actual fn pointers
+                        Warning: naively computing the number of entries in the
+                        vtable by counting the methods on the trait + methods on
+                        all parent traits does not work, because some methods can
+                        be not object safe and thus excluded from the vtable.
+                        Increase this counter if you tried to implement this but
+                        failed to do it without duplicating a lot of code from
+                        other places in the compiler: 2
+                        tcx.mk_tup(&[
+                            tcx.mk_array(tcx.types.usize, 3),
+                            tcx.mk_array(Option<fn()>),
+                        ])
+                        */
+                    };
+
+                    let metadata = if let Some(metadata_def_id) = tcx.lang_items().metadata_type() {
+                        let metadata = tcx.normalize_erasing_regions(
+                            cx.param_env(),
+                            tcx.mk_projection(metadata_def_id, [pointee]),
+                        );
+
+                        // Map `Metadata = DynMetadata<dyn Trait>` back to a vtable, since it
+                        // offers better information than `std::ptr::metadata::VTable`,
+                        // and we rely on this layout information to trigger a panic in
+                        // `std::mem::uninitialized::<&dyn Trait>()`, for example.
+                        if let ty::Adt(def, substs) = metadata.kind()
+                            && Some(def.did()) == tcx.lang_items().dyn_metadata()
+                            && substs.type_at(0).is_trait()
+                        {
+                            mk_dyn_vtable()
+                        } else {
+                            metadata
                         }
-                        _ => bug!("TyAndLayout::field({:?}): not applicable", this),
-                    }
+                    } else {
+                        match tcx.struct_tail_erasing_lifetimes(pointee, cx.param_env()).kind() {
+                            ty::Slice(_) | ty::Str => tcx.types.usize,
+                            ty::Dynamic(_, _, ty::Dyn) => mk_dyn_vtable(),
+                            _ => bug!("TyAndLayout::field({:?}): not applicable", this),
+                        }
+                    };
+
+                    TyMaybeWithLayout::Ty(metadata)
                 }
 
                 // Arrays and slices.
diff --git a/compiler/rustc_middle/src/ty/visit.rs b/compiler/rustc_middle/src/ty/visit.rs
index d5553f84f75..ca445558131 100644
--- a/compiler/rustc_middle/src/ty/visit.rs
+++ b/compiler/rustc_middle/src/ty/visit.rs
@@ -165,6 +165,14 @@ pub trait TypeVisitable<'tcx>: fmt::Debug + Clone {
     fn has_late_bound_regions(&self) -> bool {
         self.has_type_flags(TypeFlags::HAS_RE_LATE_BOUND)
     }
+    /// True if there are any late-bound non-region variables
+    fn has_non_region_late_bound(&self) -> bool {
+        self.has_type_flags(TypeFlags::HAS_LATE_BOUND - TypeFlags::HAS_RE_LATE_BOUND)
+    }
+    /// True if there are any late-bound variables
+    fn has_late_bound_vars(&self) -> bool {
+        self.has_type_flags(TypeFlags::HAS_LATE_BOUND)
+    }
 
     /// Indicates whether this value still has parameters/placeholders/inference variables
     /// which could be replaced later, in a way that would change the results of `impl`
diff --git a/compiler/rustc_middle/src/util/bug.rs b/compiler/rustc_middle/src/util/bug.rs
index fd7045d6a03..b73ae593905 100644
--- a/compiler/rustc_middle/src/util/bug.rs
+++ b/compiler/rustc_middle/src/util/bug.rs
@@ -35,8 +35,7 @@ fn opt_span_bug_fmt<S: Into<MultiSpan>>(
             (Some(tcx), None) => tcx.sess.diagnostic().bug(&msg),
             (None, _) => panic_any(msg),
         }
-    });
-    unreachable!();
+    })
 }
 
 /// A query to trigger a `delay_span_bug`. Clearly, if one has a `tcx` one can already trigger a
diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs
index 3c311729a52..03a7f2d70fa 100644
--- a/compiler/rustc_mir_build/src/check_unsafety.rs
+++ b/compiler/rustc_mir_build/src/check_unsafety.rs
@@ -5,6 +5,7 @@ use rustc_middle::thir::visit::{self, Visitor};
 use rustc_hir as hir;
 use rustc_middle::mir::BorrowKind;
 use rustc_middle::thir::*;
+use rustc_middle::ty::print::with_no_trimmed_paths;
 use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt};
 use rustc_session::lint::builtin::{UNSAFE_OP_IN_UNSAFE_FN, UNUSED_UNSAFE};
 use rustc_session::lint::Level;
@@ -524,17 +525,19 @@ impl UnsafeOpKind {
         hir_id: hir::HirId,
         span: Span,
     ) {
+        // FIXME: ideally we would want to trim the def paths, but this is not
+        // feasible with the current lint emission API (see issue #106126).
         match self {
-            CallToUnsafeFunction(did) if did.is_some() => tcx.emit_spanned_lint(
+            CallToUnsafeFunction(Some(did)) => tcx.emit_spanned_lint(
                 UNSAFE_OP_IN_UNSAFE_FN,
                 hir_id,
                 span,
                 UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafe {
                     span,
-                    function: &tcx.def_path_str(did.unwrap()),
+                    function: &with_no_trimmed_paths!(tcx.def_path_str(*did)),
                 },
             ),
-            CallToUnsafeFunction(..) => tcx.emit_spanned_lint(
+            CallToUnsafeFunction(None) => tcx.emit_spanned_lint(
                 UNSAFE_OP_IN_UNSAFE_FN,
                 hir_id,
                 span,
@@ -594,7 +597,7 @@ impl UnsafeOpKind {
                 span,
                 UnsafeOpInUnsafeFnCallToFunctionWithRequiresUnsafe {
                     span,
-                    function: &tcx.def_path_str(*did),
+                    function: &with_no_trimmed_paths!(tcx.def_path_str(*did)),
                 },
             ),
         }
@@ -607,24 +610,24 @@ impl UnsafeOpKind {
         unsafe_op_in_unsafe_fn_allowed: bool,
     ) {
         match self {
-            CallToUnsafeFunction(did) if did.is_some() && unsafe_op_in_unsafe_fn_allowed => {
+            CallToUnsafeFunction(Some(did)) if unsafe_op_in_unsafe_fn_allowed => {
                 tcx.sess.emit_err(CallToUnsafeFunctionRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
                     span,
-                    function: &tcx.def_path_str(did.unwrap()),
+                    function: &tcx.def_path_str(*did),
                 });
             }
-            CallToUnsafeFunction(did) if did.is_some() => {
+            CallToUnsafeFunction(Some(did)) => {
                 tcx.sess.emit_err(CallToUnsafeFunctionRequiresUnsafe {
                     span,
-                    function: &tcx.def_path_str(did.unwrap()),
+                    function: &tcx.def_path_str(*did),
                 });
             }
-            CallToUnsafeFunction(..) if unsafe_op_in_unsafe_fn_allowed => {
+            CallToUnsafeFunction(None) if unsafe_op_in_unsafe_fn_allowed => {
                 tcx.sess.emit_err(
                     CallToUnsafeFunctionRequiresUnsafeNamelessUnsafeOpInUnsafeFnAllowed { span },
                 );
             }
-            CallToUnsafeFunction(..) => {
+            CallToUnsafeFunction(None) => {
                 tcx.sess.emit_err(CallToUnsafeFunctionRequiresUnsafeNameless { span });
             }
             UseOfInlineAssembly if unsafe_op_in_unsafe_fn_allowed => {
diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
index a94d8d6c643..e7ee0d9e908 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
@@ -247,14 +247,14 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
 
     fn check_let_chain(&mut self, cx: &mut MatchCheckCtxt<'p, 'tcx>, pat_id: HirId) -> bool {
         let hir = self.tcx.hir();
-        let parent = hir.get_parent_node(pat_id);
+        let parent = hir.parent_id(pat_id);
 
         // First, figure out if the given pattern is part of a let chain,
         // and if so, obtain the top node of the chain.
         let mut top = parent;
         let mut part_of_chain = false;
         loop {
-            let new_top = hir.get_parent_node(top);
+            let new_top = hir.parent_id(top);
             if let hir::Node::Expr(
                 hir::Expr {
                     kind: hir::ExprKind::Binary(Spanned { node: hir::BinOpKind::And, .. }, lhs, rhs),
@@ -1054,7 +1054,7 @@ pub enum LetSource {
 fn let_source(tcx: TyCtxt<'_>, pat_id: HirId) -> LetSource {
     let hir = tcx.hir();
 
-    let parent = hir.get_parent_node(pat_id);
+    let parent = hir.parent_id(pat_id);
     let_source_parent(tcx, parent, Some(pat_id))
 }
 
@@ -1073,7 +1073,7 @@ fn let_source_parent(tcx: TyCtxt<'_>, parent: HirId, pat_id: Option<HirId>) -> L
         _ => {}
     }
 
-    let parent_parent = hir.get_parent_node(parent);
+    let parent_parent = hir.parent_id(parent);
     let parent_parent_node = hir.get(parent_parent);
     match parent_parent_node {
         hir::Node::Stmt(hir::Stmt { kind: hir::StmtKind::Local(_), .. }) => {
@@ -1085,8 +1085,8 @@ fn let_source_parent(tcx: TyCtxt<'_>, parent: HirId, pat_id: Option<HirId>) -> L
         _ => {}
     }
 
-    let parent_parent_parent = hir.get_parent_node(parent_parent);
-    let parent_parent_parent_parent = hir.get_parent_node(parent_parent_parent);
+    let parent_parent_parent = hir.parent_id(parent_parent);
+    let parent_parent_parent_parent = hir.parent_id(parent_parent_parent);
     let parent_parent_parent_parent_node = hir.get(parent_parent_parent_parent);
 
     if let hir::Node::Expr(hir::Expr {
diff --git a/compiler/rustc_mir_dataflow/src/framework/direction.rs b/compiler/rustc_mir_dataflow/src/framework/direction.rs
index 5ff6b9e7e69..077a21fc8af 100644
--- a/compiler/rustc_mir_dataflow/src/framework/direction.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/direction.rs
@@ -287,7 +287,7 @@ impl Direction for Backward {
                 | mir::TerminatorKind::InlineAsm { cleanup: Some(unwind), .. }
                     if unwind == bb =>
                 {
-                    if dead_unwinds.map_or(true, |dead| !dead.contains(bb)) {
+                    if dead_unwinds.map_or(true, |dead| !dead.contains(pred)) {
                         propagate(pred, exit_state);
                     }
                 }
diff --git a/compiler/rustc_mir_dataflow/src/framework/fmt.rs b/compiler/rustc_mir_dataflow/src/framework/fmt.rs
index 209e6f7ac9f..490be166a91 100644
--- a/compiler/rustc_mir_dataflow/src/framework/fmt.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/fmt.rs
@@ -143,7 +143,7 @@ where
             ", "
         };
 
-        write!(f, "{}", delim)?;
+        write!(f, "{delim}")?;
         idx.fmt_with(ctxt, f)?;
         first = false;
     }
@@ -164,7 +164,7 @@ where
             ", "
         };
 
-        write!(f, "{}", delim)?;
+        write!(f, "{delim}")?;
         idx.fmt_with(ctxt, f)?;
         first = false;
     }
diff --git a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs
index c9d5601f207..96c42894b69 100644
--- a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs
@@ -71,7 +71,7 @@ where
 
     fn graph_id(&self) -> dot::Id<'_> {
         let name = graphviz_safe_def_name(self.body.source.def_id());
-        dot::Id::new(format!("graph_for_def_id_{}", name)).unwrap()
+        dot::Id::new(format!("graph_for_def_id_{name}")).unwrap()
     }
 
     fn node_id(&self, n: &Self::Node) -> dot::Id<'_> {
@@ -190,7 +190,7 @@ where
             " cellpadding=\"3\"",
             " sides=\"rb\"",
         );
-        write!(w, r#"<table{fmt}>"#, fmt = table_fmt)?;
+        write!(w, r#"<table{table_fmt}>"#)?;
 
         // A + B: Block header
         match self.style {
@@ -372,7 +372,7 @@ where
         write!(w, concat!("<tr>", r#"<td colspan="2" {fmt}>MIR</td>"#,), fmt = fmt,)?;
 
         for name in state_column_names {
-            write!(w, "<td {fmt}>{name}</td>", fmt = fmt, name = name)?;
+            write!(w, "<td {fmt}>{name}</td>")?;
         }
 
         write!(w, "</tr>")
@@ -394,18 +394,18 @@ where
         };
 
         for (i, statement) in body[block].statements.iter().enumerate() {
-            let statement_str = format!("{:?}", statement);
-            let index_str = format!("{}", i);
+            let statement_str = format!("{statement:?}");
+            let index_str = format!("{i}");
 
             let after = next_in_dataflow_order(&mut afters);
             let before = befores.as_mut().map(next_in_dataflow_order);
 
             self.write_row(w, &index_str, &statement_str, |_this, w, fmt| {
                 if let Some(before) = before {
-                    write!(w, r#"<td {fmt} align="left">{diff}</td>"#, fmt = fmt, diff = before)?;
+                    write!(w, r#"<td {fmt} align="left">{before}</td>"#)?;
                 }
 
-                write!(w, r#"<td {fmt} align="left">{diff}</td>"#, fmt = fmt, diff = after)
+                write!(w, r#"<td {fmt} align="left">{after}</td>"#)
             })?;
         }
 
@@ -421,10 +421,10 @@ where
 
         self.write_row(w, "T", &terminator_str, |_this, w, fmt| {
             if let Some(before) = before {
-                write!(w, r#"<td {fmt} align="left">{diff}</td>"#, fmt = fmt, diff = before)?;
+                write!(w, r#"<td {fmt} align="left">{before}</td>"#)?;
             }
 
-            write!(w, r#"<td {fmt} align="left">{diff}</td>"#, fmt = fmt, diff = after)
+            write!(w, r#"<td {fmt} align="left">{after}</td>"#)
         })
     }
 
diff --git a/compiler/rustc_mir_dataflow/src/move_paths/mod.rs b/compiler/rustc_mir_dataflow/src/move_paths/mod.rs
index 9b053985bed..5f22a418de8 100644
--- a/compiler/rustc_mir_dataflow/src/move_paths/mod.rs
+++ b/compiler/rustc_mir_dataflow/src/move_paths/mod.rs
@@ -129,13 +129,13 @@ impl<'tcx> fmt::Debug for MovePath<'tcx> {
     fn fmt(&self, w: &mut fmt::Formatter<'_>) -> fmt::Result {
         write!(w, "MovePath {{")?;
         if let Some(parent) = self.parent {
-            write!(w, " parent: {:?},", parent)?;
+            write!(w, " parent: {parent:?},")?;
         }
         if let Some(first_child) = self.first_child {
-            write!(w, " first_child: {:?},", first_child)?;
+            write!(w, " first_child: {first_child:?},")?;
         }
         if let Some(next_sibling) = self.next_sibling {
-            write!(w, " next_sibling: {:?}", next_sibling)?;
+            write!(w, " next_sibling: {next_sibling:?}")?;
         }
         write!(w, " place: {:?} }}", self.place)
     }
diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs
index fe5ee4011ab..0522c657939 100644
--- a/compiler/rustc_mir_dataflow/src/value_analysis.rs
+++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs
@@ -920,7 +920,7 @@ fn debug_with_context<V: Debug + Eq>(
 ) -> std::fmt::Result {
     for (local, place) in map.locals.iter_enumerated() {
         if let Some(place) = place {
-            debug_with_context_rec(*place, &format!("{:?}", local), new, old, map, f)?;
+            debug_with_context_rec(*place, &format!("{local:?}"), new, old, map, f)?;
         }
     }
     Ok(())
diff --git a/compiler/rustc_mir_transform/src/dead_store_elimination.rs b/compiler/rustc_mir_transform/src/dead_store_elimination.rs
index 42c580c63f0..09546330cec 100644
--- a/compiler/rustc_mir_transform/src/dead_store_elimination.rs
+++ b/compiler/rustc_mir_transform/src/dead_store_elimination.rs
@@ -71,7 +71,7 @@ pub fn eliminate<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, borrowed: &BitS
         bbs[block].statements[statement_index].make_nop();
     }
 
-    crate::simplify::SimplifyLocals.run_pass(tcx, body)
+    crate::simplify::simplify_locals(body, tcx)
 }
 
 pub struct DeadStoreElimination;
diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs
index ae79c2290f6..16b8a901f36 100644
--- a/compiler/rustc_mir_transform/src/lib.rs
+++ b/compiler/rustc_mir_transform/src/lib.rs
@@ -524,11 +524,8 @@ fn run_runtime_lowering_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
 
 /// Returns the sequence of passes that do the initial cleanup of runtime MIR.
 fn run_runtime_cleanup_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
-    let passes: &[&dyn MirPass<'tcx>] = &[
-        &elaborate_box_derefs::ElaborateBoxDerefs,
-        &lower_intrinsics::LowerIntrinsics,
-        &simplify::SimplifyCfg::new("elaborate-drops"),
-    ];
+    let passes: &[&dyn MirPass<'tcx>] =
+        &[&lower_intrinsics::LowerIntrinsics, &simplify::SimplifyCfg::new("elaborate-drops")];
 
     pm::run_passes(tcx, body, passes, Some(MirPhase::Runtime(RuntimePhase::PostCleanup)));
 }
@@ -560,6 +557,7 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
             &multiple_return_terminators::MultipleReturnTerminators,
             &instcombine::InstCombine,
             &separate_const_switch::SeparateConstSwitch,
+            &simplify::SimplifyLocals::new("before-const-prop"),
             //
             // FIXME(#70073): This pass is responsible for both optimization as well as some lints.
             &const_prop::ConstProp,
@@ -578,7 +576,7 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
             &o1(remove_noop_landing_pads::RemoveNoopLandingPads),
             &o1(simplify::SimplifyCfg::new("final")),
             &nrvo::RenameReturnPlace,
-            &simplify::SimplifyLocals,
+            &simplify::SimplifyLocals::new("final"),
             &multiple_return_terminators::MultipleReturnTerminators,
             &deduplicate_blocks::DeduplicateBlocks,
             // Some cleanup necessary at least for LLVM and potentially other codegen backends.
diff --git a/compiler/rustc_mir_transform/src/simplify.rs b/compiler/rustc_mir_transform/src/simplify.rs
index 8212a7b523b..8f6abe7a912 100644
--- a/compiler/rustc_mir_transform/src/simplify.rs
+++ b/compiler/rustc_mir_transform/src/simplify.rs
@@ -379,9 +379,21 @@ fn save_unreachable_coverage(
     ));
 }
 
-pub struct SimplifyLocals;
+pub struct SimplifyLocals {
+    label: String,
+}
+
+impl SimplifyLocals {
+    pub fn new(label: &str) -> SimplifyLocals {
+        SimplifyLocals { label: format!("SimplifyLocals-{}", label) }
+    }
+}
 
 impl<'tcx> MirPass<'tcx> for SimplifyLocals {
+    fn name(&self) -> &str {
+        &self.label
+    }
+
     fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
         sess.mir_opt_level() > 0
     }
@@ -557,6 +569,7 @@ fn remove_unused_definitions(used_locals: &mut UsedLocals, body: &mut Body<'_>)
 
                     StatementKind::SetDiscriminant { ref place, .. }
                     | StatementKind::Deinit(ref place) => used_locals.is_used(place.local),
+                    StatementKind::Nop => false,
                     _ => true,
                 };
 
diff --git a/compiler/rustc_monomorphize/Cargo.toml b/compiler/rustc_monomorphize/Cargo.toml
index 6ee5330b63f..c8af10576b4 100644
--- a/compiler/rustc_monomorphize/Cargo.toml
+++ b/compiler/rustc_monomorphize/Cargo.toml
@@ -6,6 +6,8 @@ edition = "2021"
 [lib]
 
 [dependencies]
+serde = "1"
+serde_json = "1"
 smallvec = { version = "1.8.1", features = [ "union", "may_dangle" ] }
 tracing = "0.1"
 rustc_data_structures = { path = "../rustc_data_structures" }
diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs
index 59cc500a99d..b573df43250 100644
--- a/compiler/rustc_monomorphize/src/collector.rs
+++ b/compiler/rustc_monomorphize/src/collector.rs
@@ -526,7 +526,7 @@ fn collect_items_rec<'tcx>(
         let formatted_item = with_no_trimmed_paths!(starting_point.node.to_string());
         tcx.sess.span_note_without_error(
             starting_point.span,
-            &format!("the above error was encountered while instantiating `{}`", formatted_item),
+            &format!("the above error was encountered while instantiating `{formatted_item}`"),
         );
     }
     inlining_map.lock_mut().record_accesses(starting_point.node, &neighbors.items);
diff --git a/compiler/rustc_monomorphize/src/errors.rs b/compiler/rustc_monomorphize/src/errors.rs
index f15cf54718e..aa3227cac2d 100644
--- a/compiler/rustc_monomorphize/src/errors.rs
+++ b/compiler/rustc_monomorphize/src/errors.rs
@@ -50,7 +50,7 @@ impl IntoDiagnostic<'_> for UnusedGenericParams {
             // FIXME: I can figure out how to do a label with a fluent string with a fixed message,
             // or a label with a dynamic value in a hard-coded string, but I haven't figured out
             // how to combine the two. 😢
-            diag.span_label(span, format!("generic parameter `{}` is unused", name));
+            diag.span_label(span, format!("generic parameter `{name}` is unused"));
         }
         diag
     }
diff --git a/compiler/rustc_monomorphize/src/partitioning/mod.rs b/compiler/rustc_monomorphize/src/partitioning/mod.rs
index 4f25fc71314..fd6bcad1898 100644
--- a/compiler/rustc_monomorphize/src/partitioning/mod.rs
+++ b/compiler/rustc_monomorphize/src/partitioning/mod.rs
@@ -102,14 +102,14 @@ use std::path::{Path, PathBuf};
 
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::sync;
-use rustc_hir::def_id::DefIdSet;
+use rustc_hir::def_id::{DefIdSet, LOCAL_CRATE};
 use rustc_middle::mir;
 use rustc_middle::mir::mono::MonoItem;
 use rustc_middle::mir::mono::{CodegenUnit, Linkage};
 use rustc_middle::ty::print::with_no_trimmed_paths;
 use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::TyCtxt;
-use rustc_session::config::SwitchWithOptPath;
+use rustc_session::config::{DumpMonoStatsFormat, SwitchWithOptPath};
 use rustc_span::symbol::Symbol;
 
 use crate::collector::InliningMap;
@@ -285,7 +285,7 @@ where
         use std::fmt::Write;
 
         let s = &mut String::new();
-        let _ = writeln!(s, "{}", label);
+        let _ = writeln!(s, "{label}");
         for cgu in cgus {
             let _ =
                 writeln!(s, "CodegenUnit {} estimated size {} :", cgu.name(), cgu.size_estimate());
@@ -355,9 +355,8 @@ fn collect_and_partition_mono_items(tcx: TyCtxt<'_>, (): ()) -> (&DefIdSet, &[Co
             } else {
                 if mode_string != "lazy" {
                     let message = format!(
-                        "Unknown codegen-item collection mode '{}'. \
-                                           Falling back to 'lazy' mode.",
-                        mode_string
+                        "Unknown codegen-item collection mode '{mode_string}'. \
+                                           Falling back to 'lazy' mode."
                     );
                     tcx.sess.warn(&message);
                 }
@@ -417,7 +416,7 @@ fn collect_and_partition_mono_items(tcx: TyCtxt<'_>, (): ()) -> (&DefIdSet, &[Co
     // Output monomorphization stats per def_id
     if let SwitchWithOptPath::Enabled(ref path) = tcx.sess.opts.unstable_opts.dump_mono_stats {
         if let Err(err) =
-            dump_mono_items_stats(tcx, &codegen_units, path, tcx.sess.opts.crate_name.as_deref())
+            dump_mono_items_stats(tcx, &codegen_units, path, tcx.crate_name(LOCAL_CRATE))
         {
             tcx.sess.emit_fatal(CouldntDumpMonoStats { error: err.to_string() });
         }
@@ -470,7 +469,7 @@ fn collect_and_partition_mono_items(tcx: TyCtxt<'_>, (): ()) -> (&DefIdSet, &[Co
         item_keys.sort();
 
         for item in item_keys {
-            println!("MONO_ITEM {}", item);
+            println!("MONO_ITEM {item}");
         }
     }
 
@@ -483,7 +482,7 @@ fn dump_mono_items_stats<'tcx>(
     tcx: TyCtxt<'tcx>,
     codegen_units: &[CodegenUnit<'tcx>],
     output_directory: &Option<PathBuf>,
-    crate_name: Option<&str>,
+    crate_name: Symbol,
 ) -> Result<(), Box<dyn std::error::Error>> {
     let output_directory = if let Some(ref directory) = output_directory {
         fs::create_dir_all(directory)?;
@@ -492,9 +491,11 @@ fn dump_mono_items_stats<'tcx>(
         Path::new(".")
     };
 
-    let filename = format!("{}.mono_items.md", crate_name.unwrap_or("unknown-crate"));
+    let format = tcx.sess.opts.unstable_opts.dump_mono_stats_format;
+    let ext = format.extension();
+    let filename = format!("{crate_name}.mono_items.{ext}");
     let output_path = output_directory.join(&filename);
-    let file = File::create(output_path)?;
+    let file = File::create(&output_path)?;
     let mut file = BufWriter::new(file);
 
     // Gather instantiated mono items grouped by def_id
@@ -508,30 +509,44 @@ fn dump_mono_items_stats<'tcx>(
         }
     }
 
+    #[derive(serde::Serialize)]
+    struct MonoItem {
+        name: String,
+        instantiation_count: usize,
+        size_estimate: usize,
+        total_estimate: usize,
+    }
+
     // Output stats sorted by total instantiated size, from heaviest to lightest
     let mut stats: Vec<_> = items_per_def_id
         .into_iter()
         .map(|(def_id, items)| {
+            let name = with_no_trimmed_paths!(tcx.def_path_str(def_id));
             let instantiation_count = items.len();
             let size_estimate = items[0].size_estimate(tcx);
             let total_estimate = instantiation_count * size_estimate;
-            (def_id, instantiation_count, size_estimate, total_estimate)
+            MonoItem { name, instantiation_count, size_estimate, total_estimate }
         })
         .collect();
-    stats.sort_unstable_by_key(|(_, _, _, total_estimate)| cmp::Reverse(*total_estimate));
+    stats.sort_unstable_by_key(|item| cmp::Reverse(item.total_estimate));
 
     if !stats.is_empty() {
-        writeln!(
-            file,
-            "| Item | Instantiation count | Estimated Cost Per Instantiation | Total Estimated Cost |"
-        )?;
-        writeln!(file, "| --- | ---: | ---: | ---: |")?;
-        for (def_id, instantiation_count, size_estimate, total_estimate) in stats {
-            let item = with_no_trimmed_paths!(tcx.def_path_str(def_id));
-            writeln!(
-                file,
-                "| {item} | {instantiation_count} | {size_estimate} | {total_estimate} |"
-            )?;
+        match format {
+            DumpMonoStatsFormat::Json => serde_json::to_writer(file, &stats)?,
+            DumpMonoStatsFormat::Markdown => {
+                writeln!(
+                    file,
+                    "| Item | Instantiation count | Estimated Cost Per Instantiation | Total Estimated Cost |"
+                )?;
+                writeln!(file, "| --- | ---: | ---: | ---: |")?;
+
+                for MonoItem { name, instantiation_count, size_estimate, total_estimate } in stats {
+                    writeln!(
+                        file,
+                        "| `{name}` | {instantiation_count} | {size_estimate} | {total_estimate} |"
+                    )?;
+                }
+            }
         }
     }
 
@@ -580,6 +595,6 @@ pub fn provide(providers: &mut Providers) {
         let (_, all) = tcx.collect_and_partition_mono_items(());
         all.iter()
             .find(|cgu| cgu.name() == name)
-            .unwrap_or_else(|| panic!("failed to find cgu with name {:?}", name))
+            .unwrap_or_else(|| panic!("failed to find cgu with name {name:?}"))
     };
 }
diff --git a/compiler/rustc_monomorphize/src/util.rs b/compiler/rustc_monomorphize/src/util.rs
index 6a4d2df1ead..33e1f6ce342 100644
--- a/compiler/rustc_monomorphize/src/util.rs
+++ b/compiler/rustc_monomorphize/src/util.rs
@@ -40,12 +40,12 @@ pub(crate) fn dump_closure_profile<'tcx>(tcx: TyCtxt<'tcx>, closure_instance: In
         let new_size = tcx
             .layout_of(param_env.and(after_feature_tys))
             .map(|l| format!("{:?}", l.size.bytes()))
-            .unwrap_or_else(|e| format!("Failed {:?}", e));
+            .unwrap_or_else(|e| format!("Failed {e:?}"));
 
         let old_size = tcx
             .layout_of(param_env.and(before_feature_tys))
             .map(|l| format!("{:?}", l.size.bytes()))
-            .unwrap_or_else(|e| format!("Failed {:?}", e));
+            .unwrap_or_else(|e| format!("Failed {e:?}"));
 
         let closure_span = tcx.def_span(closure_def_id);
         let src_file = tcx.sess.source_map().span_to_filename(closure_span);
@@ -54,7 +54,7 @@ pub(crate) fn dump_closure_profile<'tcx>(tcx: TyCtxt<'tcx>, closure_instance: In
             .source_map()
             .span_to_lines(closure_span)
             .map(|l| format!("{:?} {:?}", l.lines.first(), l.lines.last()))
-            .unwrap_or_else(|e| format!("{:?}", e));
+            .unwrap_or_else(|e| format!("{e:?}"));
 
         if let Err(e) = writeln!(
             file,
@@ -64,7 +64,7 @@ pub(crate) fn dump_closure_profile<'tcx>(tcx: TyCtxt<'tcx>, closure_instance: In
             src_file.prefer_local(),
             line_nos
         ) {
-            eprintln!("Error writing to file {}", e)
+            eprintln!("Error writing to file {e}")
         }
     }
 }
diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs
index b3231f55bc6..d9fa3e31db9 100644
--- a/compiler/rustc_parse/src/parser/diagnostics.rs
+++ b/compiler/rustc_parse/src/parser/diagnostics.rs
@@ -1104,7 +1104,11 @@ impl<'a> Parser<'a> {
                     return if token::ModSep == self.token.kind {
                         // We have some certainty that this was a bad turbofish at this point.
                         // `foo< bar >::`
-                        err.suggest_turbofish = Some(op.span.shrink_to_lo());
+                        if let ExprKind::Binary(o, ..) = inner_op.kind && o.node == BinOpKind::Lt {
+                            err.suggest_turbofish = Some(op.span.shrink_to_lo());
+                        } else {
+                            err.help_turbofish = Some(());
+                        }
 
                         let snapshot = self.create_snapshot_for_diagnostic();
                         self.bump(); // `::`
@@ -1130,7 +1134,11 @@ impl<'a> Parser<'a> {
                     } else if token::OpenDelim(Delimiter::Parenthesis) == self.token.kind {
                         // We have high certainty that this was a bad turbofish at this point.
                         // `foo< bar >(`
-                        err.suggest_turbofish = Some(op.span.shrink_to_lo());
+                        if let ExprKind::Binary(o, ..) = inner_op.kind && o.node == BinOpKind::Lt {
+                            err.suggest_turbofish = Some(op.span.shrink_to_lo());
+                        } else {
+                            err.help_turbofish = Some(());
+                        }
                         // Consume the fn call arguments.
                         match self.consume_fn_args() {
                             Err(()) => Err(err.into_diagnostic(&self.sess.span_diagnostic)),
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index 1fc1ffd6cb6..9f436783ced 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -1503,12 +1503,13 @@ impl<'a> Parser<'a> {
                 prior_type_ascription: self.last_type_ascription,
             });
             (lo.to(self.prev_token.span), ExprKind::MacCall(mac))
-        } else if self.check(&token::OpenDelim(Delimiter::Brace)) &&
-            let Some(expr) = self.maybe_parse_struct_expr(&qself, &path) {
-                if qself.is_some() {
-                    self.sess.gated_spans.gate(sym::more_qualified_paths, path.span);
-                }
-                return expr;
+        } else if self.check(&token::OpenDelim(Delimiter::Brace))
+            && let Some(expr) = self.maybe_parse_struct_expr(&qself, &path)
+        {
+            if qself.is_some() {
+                self.sess.gated_spans.gate(sym::more_qualified_paths, path.span);
+            }
+            return expr;
         } else {
             (path.span, ExprKind::Path(qself, path))
         };
diff --git a/compiler/rustc_parse_format/src/lib.rs b/compiler/rustc_parse_format/src/lib.rs
index 9f2aaca0acf..1eb227503f2 100644
--- a/compiler/rustc_parse_format/src/lib.rs
+++ b/compiler/rustc_parse_format/src/lib.rs
@@ -447,7 +447,7 @@ impl<'a> Parser<'a> {
                 Some(pos)
             } else {
                 let pos = self.to_span_index(pos);
-                let description = format!("expected `'}}'`, found `{:?}`", maybe);
+                let description = format!("expected `'}}'`, found `{maybe:?}`");
                 let label = "expected `}`".to_owned();
                 let (note, secondary_label) = if c == '}' {
                     (
@@ -471,12 +471,12 @@ impl<'a> Parser<'a> {
                 None
             }
         } else {
-            let description = format!("expected `{:?}` but string was terminated", c);
+            let description = format!("expected `{c:?}` but string was terminated");
             // point at closing `"`
             let pos = self.input.len() - if self.append_newline { 1 } else { 0 };
             let pos = self.to_span_index(pos);
             if c == '}' {
-                let label = format!("expected `{:?}`", c);
+                let label = format!("expected `{c:?}`");
                 let (note, secondary_label) = if c == '}' {
                     (
                         Some(
@@ -497,7 +497,7 @@ impl<'a> Parser<'a> {
                     should_be_replaced_with_positional_argument: false,
                 });
             } else {
-                self.err(description, format!("expected `{:?}`", c), pos.to(pos));
+                self.err(description, format!("expected `{c:?}`"), pos.to(pos));
             }
             None
         }
diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs
index 72d38aeac7a..8fe47d862e7 100644
--- a/compiler/rustc_privacy/src/lib.rs
+++ b/compiler/rustc_privacy/src/lib.rs
@@ -915,7 +915,7 @@ impl<'tcx, 'a> TestReachabilityVisitor<'tcx, 'a> {
                     if level != Level::Direct {
                         error_msg.push_str(", ");
                     }
-                    error_msg.push_str(&format!("{:?}: {}", level, vis_str));
+                    error_msg.push_str(&format!("{level:?}: {vis_str}"));
                 }
             } else {
                 error_msg.push_str("not in the table");
@@ -1223,19 +1223,22 @@ impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> {
                 self.tcx.types.never,
             );
 
-            for (trait_predicate, _, _) in bounds.trait_bounds {
-                if self.visit_trait(trait_predicate.skip_binder()).is_break() {
-                    return;
-                }
-            }
-
-            for (poly_predicate, _) in bounds.projection_bounds {
-                let pred = poly_predicate.skip_binder();
-                let poly_pred_term = self.visit(pred.term);
-                if poly_pred_term.is_break()
-                    || self.visit_projection_ty(pred.projection_ty).is_break()
-                {
-                    return;
+            for (pred, _) in bounds.predicates() {
+                match pred.kind().skip_binder() {
+                    ty::PredicateKind::Clause(ty::Clause::Trait(trait_predicate)) => {
+                        if self.visit_trait(trait_predicate.trait_ref).is_break() {
+                            return;
+                        }
+                    }
+                    ty::PredicateKind::Clause(ty::Clause::Projection(proj_predicate)) => {
+                        let term = self.visit(proj_predicate.term);
+                        if term.is_break()
+                            || self.visit_projection_ty(proj_predicate.projection_ty).is_break()
+                        {
+                            return;
+                        }
+                    }
+                    _ => {}
                 }
             }
         }
@@ -2141,7 +2144,7 @@ fn check_private_in_public(tcx: TyCtxt<'_>, (): ()) {
             if !old_error_set_ancestry.insert(id) {
                 break;
             }
-            let parent = tcx.hir().get_parent_node(id);
+            let parent = tcx.hir().parent_id(id);
             if parent == id {
                 break;
             }
diff --git a/compiler/rustc_query_impl/Cargo.toml b/compiler/rustc_query_impl/Cargo.toml
index b2111a1262a..46e77626479 100644
--- a/compiler/rustc_query_impl/Cargo.toml
+++ b/compiler/rustc_query_impl/Cargo.toml
@@ -4,7 +4,7 @@ version = "0.0.0"
 edition = "2021"
 
 [lib]
-doctest = false
+
 
 [dependencies]
 measureme = "10.0.0"
diff --git a/compiler/rustc_query_impl/src/on_disk_cache.rs b/compiler/rustc_query_impl/src/on_disk_cache.rs
index 2bcfdab03c8..70c481fb0ee 100644
--- a/compiler/rustc_query_impl/src/on_disk_cache.rs
+++ b/compiler/rustc_query_impl/src/on_disk_cache.rs
@@ -787,7 +787,7 @@ impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for DefId {
         // which means that the definition with this hash is guaranteed to
         // still exist in the current compilation session.
         d.tcx.def_path_hash_to_def_id(def_path_hash, &mut || {
-            panic!("Failed to convert DefPathHash {:?}", def_path_hash)
+            panic!("Failed to convert DefPathHash {def_path_hash:?}")
         })
     }
 }
diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs
index 535445e70bc..6125ad4eff1 100644
--- a/compiler/rustc_query_impl/src/plumbing.rs
+++ b/compiler/rustc_query_impl/src/plumbing.rs
@@ -321,7 +321,7 @@ pub(crate) fn create_query_frame<
         ty::print::with_forced_impl_filename_line!(do_describe(tcx.tcx, key))
     );
     let description =
-        if tcx.sess.verbose() { format!("{} [{:?}]", description, name) } else { description };
+        if tcx.sess.verbose() { format!("{description} [{name:?}]") } else { description };
     let span = if kind == dep_graph::DepKind::def_span {
         // The `def_span` query is used to calculate `default_span`,
         // so exit to avoid infinite recursion.
diff --git a/compiler/rustc_query_impl/src/profiling_support.rs b/compiler/rustc_query_impl/src/profiling_support.rs
index 5f54bab9c31..4743170e9bf 100644
--- a/compiler/rustc_query_impl/src/profiling_support.rs
+++ b/compiler/rustc_query_impl/src/profiling_support.rs
@@ -111,7 +111,7 @@ impl<T: Debug> IntoSelfProfilingString for T {
         &self,
         builder: &mut QueryKeyStringBuilder<'_, '_>,
     ) -> StringId {
-        let s = format!("{:?}", self);
+        let s = format!("{self:?}");
         builder.profiler.alloc_string(&s[..])
     }
 }
diff --git a/compiler/rustc_query_system/src/dep_graph/debug.rs b/compiler/rustc_query_system/src/dep_graph/debug.rs
index f9f3169af69..c2c9600f555 100644
--- a/compiler/rustc_query_system/src/dep_graph/debug.rs
+++ b/compiler/rustc_query_system/src/dep_graph/debug.rs
@@ -29,7 +29,7 @@ impl DepNodeFilter {
 
     /// Tests whether `node` meets the filter, returning true if so.
     pub fn test<K: DepKind>(&self, node: &DepNode<K>) -> bool {
-        let debug_str = format!("{:?}", node);
+        let debug_str = format!("{node:?}");
         self.text.split('&').map(|s| s.trim()).all(|f| debug_str.contains(f))
     }
 }
@@ -46,7 +46,7 @@ impl<K: DepKind> EdgeFilter<K> {
     pub fn new(test: &str) -> Result<EdgeFilter<K>, Box<dyn Error>> {
         let parts: Vec<_> = test.split("->").collect();
         if parts.len() != 2 {
-            Err(format!("expected a filter like `a&b -> c&d`, not `{}`", test).into())
+            Err(format!("expected a filter like `a&b -> c&d`, not `{test}`").into())
         } else {
             Ok(EdgeFilter {
                 source: DepNodeFilter::new(parts[0]),
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 d79c5816a9c..9e1ca6ab515 100644
--- a/compiler/rustc_query_system/src/dep_graph/dep_node.rs
+++ b/compiler/rustc_query_system/src/dep_graph/dep_node.rs
@@ -120,7 +120,7 @@ pub trait DepNodeParams<Tcx: DepContext>: fmt::Debug + Sized {
     }
 
     fn to_debug_str(&self, _: Tcx) -> String {
-        format!("{:?}", self)
+        format!("{self:?}")
     }
 
     /// This method tries to recover the query key from the given `DepNode`,
diff --git a/compiler/rustc_query_system/src/dep_graph/graph.rs b/compiler/rustc_query_system/src/dep_graph/graph.rs
index 0b1ff5d709f..53c9da15737 100644
--- a/compiler/rustc_query_system/src/dep_graph/graph.rs
+++ b/compiler/rustc_query_system/src/dep_graph/graph.rs
@@ -316,10 +316,8 @@ impl<K: DepKind> DepGraph<K> {
         assert!(
             !self.dep_node_exists(&key),
             "forcing query with already existing `DepNode`\n\
-                 - query-key: {:?}\n\
-                 - dep-node: {:?}",
-            arg,
-            key
+                 - query-key: {arg:?}\n\
+                 - dep-node: {key:?}"
         );
 
         let task_deps = if cx.dep_context().is_eval_always(key.kind) {
@@ -365,8 +363,7 @@ impl<K: DepKind> DepGraph<K> {
             debug_assert!(
                 data.colors.get(prev_index).is_none(),
                 "DepGraph::with_task() - Duplicate DepNodeColor \
-                            insertion for {:?}",
-                key
+                            insertion for {key:?}"
             );
 
             data.colors.insert(prev_index, color);
@@ -447,7 +444,7 @@ impl<K: DepKind> DepGraph<K> {
                     TaskDepsRef::Allow(deps) => deps.lock(),
                     TaskDepsRef::Ignore => return,
                     TaskDepsRef::Forbid => {
-                        panic!("Illegal read of: {:?}", dep_node_index)
+                        panic!("Illegal read of: {dep_node_index:?}")
                     }
                 };
                 let task_deps = &mut *task_deps;
@@ -824,8 +821,7 @@ impl<K: DepKind> DepGraph<K> {
         debug_assert!(
             data.colors.get(prev_dep_node_index).is_none(),
             "DepGraph::try_mark_previous_green() - Duplicate DepNodeColor \
-                      insertion for {:?}",
-            dep_node
+                      insertion for {dep_node:?}"
         );
 
         if !side_effects.is_empty() {
@@ -1164,7 +1160,7 @@ impl<K: DepKind> CurrentDepGraph<K> {
             if let Some(fingerprint) = fingerprint {
                 if fingerprint == prev_graph.fingerprint_by_index(prev_index) {
                     if print_status {
-                        eprintln!("[task::green] {:?}", key);
+                        eprintln!("[task::green] {key:?}");
                     }
 
                     // This is a green node: it existed in the previous compilation,
@@ -1186,7 +1182,7 @@ impl<K: DepKind> CurrentDepGraph<K> {
                     (dep_node_index, Some((prev_index, DepNodeColor::Green(dep_node_index))))
                 } else {
                     if print_status {
-                        eprintln!("[task::red] {:?}", key);
+                        eprintln!("[task::red] {key:?}");
                     }
 
                     // This is a red node: it existed in the previous compilation, its query
@@ -1209,7 +1205,7 @@ impl<K: DepKind> CurrentDepGraph<K> {
                 }
             } else {
                 if print_status {
-                    eprintln!("[task::unknown] {:?}", key);
+                    eprintln!("[task::unknown] {key:?}");
                 }
 
                 // This is a red node, effectively: it existed in the previous compilation
@@ -1234,7 +1230,7 @@ impl<K: DepKind> CurrentDepGraph<K> {
             }
         } else {
             if print_status {
-                eprintln!("[task::new] {:?}", key);
+                eprintln!("[task::new] {key:?}");
             }
 
             let fingerprint = fingerprint.unwrap_or(Fingerprint::ZERO);
diff --git a/compiler/rustc_query_system/src/dep_graph/serialized.rs b/compiler/rustc_query_system/src/dep_graph/serialized.rs
index a918328d413..dfc1344f85c 100644
--- a/compiler/rustc_query_system/src/dep_graph/serialized.rs
+++ b/compiler/rustc_query_system/src/dep_graph/serialized.rs
@@ -270,17 +270,14 @@ impl<K: DepKind + Encodable<FileEncoder>> GraphEncoder<K> {
 
             eprintln!("[incremental]");
             eprintln!("[incremental] DepGraph Statistics");
-            eprintln!("{}", SEPARATOR);
+            eprintln!("{SEPARATOR}");
             eprintln!("[incremental]");
             eprintln!("[incremental] Total Node Count: {}", status.total_node_count);
             eprintln!("[incremental] Total Edge Count: {}", status.total_edge_count);
 
             if cfg!(debug_assertions) {
-                eprintln!("[incremental] Total Edge Reads: {}", total_read_count);
-                eprintln!(
-                    "[incremental] Total Duplicate Edge Reads: {}",
-                    total_duplicate_read_count
-                );
+                eprintln!("[incremental] Total Edge Reads: {total_read_count}");
+                eprintln!("[incremental] Total Duplicate Edge Reads: {total_duplicate_read_count}");
             }
 
             eprintln!("[incremental]");
@@ -288,7 +285,7 @@ impl<K: DepKind + Encodable<FileEncoder>> GraphEncoder<K> {
                 "[incremental]  {:<36}| {:<17}| {:<12}| {:<17}|",
                 "Node Kind", "Node Frequency", "Node Count", "Avg. Edge Count"
             );
-            eprintln!("{}", SEPARATOR);
+            eprintln!("{SEPARATOR}");
 
             for stat in stats {
                 let node_kind_ratio =
@@ -304,7 +301,7 @@ impl<K: DepKind + Encodable<FileEncoder>> GraphEncoder<K> {
                 );
             }
 
-            eprintln!("{}", SEPARATOR);
+            eprintln!("{SEPARATOR}");
             eprintln!("[incremental]");
         }
     }
diff --git a/compiler/rustc_query_system/src/query/plumbing.rs b/compiler/rustc_query_system/src/query/plumbing.rs
index da1ac6a5fb2..b3b939eae88 100644
--- a/compiler/rustc_query_system/src/query/plumbing.rs
+++ b/compiler/rustc_query_system/src/query/plumbing.rs
@@ -549,8 +549,7 @@ where
         // can be forced from `DepNode`.
         debug_assert!(
             !qcx.dep_context().fingerprint_style(dep_node.kind).reconstructible(),
-            "missing on-disk cache entry for {:?}",
-            dep_node
+            "missing on-disk cache entry for {dep_node:?}"
         );
     }
 
@@ -589,8 +588,7 @@ where
 {
     assert!(
         tcx.dep_graph().is_green(dep_node),
-        "fingerprint for green query instance not loaded from cache: {:?}",
-        dep_node,
+        "fingerprint for green query instance not loaded from cache: {dep_node:?}",
     );
 
     let new_hash = hash_result.map_or(Fingerprint::ZERO, |f| {
@@ -669,16 +667,16 @@ fn incremental_verify_ich_failed(sess: &Session, dep_node: DebugArg<'_>, result:
         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)
+            format!("`cargo clean -p {crate_name}` or `cargo clean`")
         } else {
             "`cargo clean`".to_string()
         };
 
         sess.emit_err(crate::error::IncrementCompilation {
             run_cmd,
-            dep_node: format!("{:?}", dep_node),
+            dep_node: format!("{dep_node:?}"),
         });
-        panic!("Found unstable fingerprints for {:?}: {:?}", dep_node, result);
+        panic!("Found unstable fingerprints for {dep_node:?}: {result:?}");
     }
 
     INSIDE_VERIFY_PANIC.with(|in_panic| in_panic.set(old_in_panic));
diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs
index 0c4b35b8833..e41fe325b81 100644
--- a/compiler/rustc_resolve/src/ident.rs
+++ b/compiler/rustc_resolve/src/ident.rs
@@ -820,13 +820,12 @@ impl<'a> Resolver<'a> {
             // binding if it exists. What we really want here is having two separate scopes in
             // a module - one for non-globs and one for globs, but until that's done use this
             // hack to avoid inconsistent resolution ICEs during import validation.
-            let binding = [resolution.binding, resolution.shadowed_glob]
-                .into_iter()
-                .filter_map(|binding| match (binding, ignore_binding) {
+            let binding = [resolution.binding, resolution.shadowed_glob].into_iter().find_map(
+                |binding| match (binding, ignore_binding) {
                     (Some(binding), Some(ignored)) if ptr::eq(binding, ignored) => None,
                     _ => binding,
-                })
-                .next();
+                },
+            );
             let Some(binding) = binding else {
                 return Err((Determined, Weak::No));
             };
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index c44635b85f8..ca43762aa21 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -1515,7 +1515,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
             count: 1,
         };
         let elision_candidate = LifetimeElisionCandidate::Missing(missing_lifetime);
-        for rib in self.lifetime_ribs.iter().rev() {
+        for (i, rib) in self.lifetime_ribs.iter().enumerate().rev() {
             debug!(?rib.kind);
             match rib.kind {
                 LifetimeRibKind::AnonymousCreateParameter { binder, .. } => {
@@ -1532,16 +1532,31 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
                     } else {
                         ("`'_` cannot be used here", "`'_` is a reserved lifetime name")
                     };
-                    rustc_errors::struct_span_err!(
+                    let mut diag = rustc_errors::struct_span_err!(
                         self.r.session,
                         lifetime.ident.span,
                         E0637,
                         "{}",
                         msg,
-                    )
-                    .span_label(lifetime.ident.span, note)
-                    .emit();
-
+                    );
+                    diag.span_label(lifetime.ident.span, note);
+                    if elided {
+                        for rib in self.lifetime_ribs[i..].iter().rev() {
+                            if let LifetimeRibKind::Generics {
+                                span,
+                                kind: LifetimeBinderKind::PolyTrait | LifetimeBinderKind::WhereBound,
+                                ..
+                            } = &rib.kind
+                            {
+                                diag.span_help(
+                                    *span,
+                                    "consider introducing a higher-ranked lifetime here with `for<'a>`",
+                                );
+                                break;
+                            }
+                        }
+                    }
+                    diag.emit();
                     self.record_lifetime_res(lifetime.id, LifetimeRes::Error, elision_candidate);
                     return;
                 }
diff --git a/compiler/rustc_save_analysis/src/lib.rs b/compiler/rustc_save_analysis/src/lib.rs
index 6afd5fe5a7f..a8d82de02b7 100644
--- a/compiler/rustc_save_analysis/src/lib.rs
+++ b/compiler/rustc_save_analysis/src/lib.rs
@@ -600,7 +600,7 @@ impl<'tcx> SaveContext<'tcx> {
                 if seg.res != Res::Err {
                     seg.res
                 } else {
-                    let parent_node = self.tcx.hir().get_parent_node(hir_id);
+                    let parent_node = self.tcx.hir().parent_id(hir_id);
                     self.get_path_res(parent_node)
                 }
             }
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index 02e3992a6a9..1ccfc59f7a9 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -35,6 +35,7 @@ use std::hash::Hash;
 use std::iter;
 use std::path::{Path, PathBuf};
 use std::str::{self, FromStr};
+use std::sync::LazyLock;
 
 pub mod sigpipe;
 
@@ -554,6 +555,16 @@ pub enum PrintRequest {
     SplitDebuginfo,
 }
 
+#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
+pub enum TraitSolver {
+    /// Classic trait solver in `rustc_trait_selection::traits::select`
+    Classic,
+    /// Chalk trait solver
+    Chalk,
+    /// Experimental trait solver in `rustc_trait_selection::solve`
+    Next,
+}
+
 pub enum Input {
     /// Load source code from a file.
     File(PathBuf),
@@ -1312,7 +1323,12 @@ mod opt {
         unstable(longer(a, b), move |opts| opts.optmulti(a, b, c, d))
     }
 }
-
+static EDITION_STRING: LazyLock<String> = LazyLock::new(|| {
+    format!(
+        "Specify which edition of the compiler to use when compiling code. \
+The default is {DEFAULT_EDITION} and the latest stable edition is {LATEST_STABLE_EDITION}."
+    )
+});
 /// Returns the "short" subset of the rustc command line options,
 /// including metadata for each option, such as whether the option is
 /// part of the stable long-term interface for rustc.
@@ -1345,7 +1361,7 @@ pub fn rustc_short_optgroups() -> Vec<RustcOptGroup> {
         opt::opt_s(
             "",
             "edition",
-            "Specify which edition of the compiler to use when compiling code.",
+            &*EDITION_STRING,
             EDITION_NAME_LIST,
         ),
         opt::multi_s(
@@ -2761,7 +2777,7 @@ pub(crate) mod dep_tracking {
         BranchProtection, CFGuard, CFProtection, CrateType, DebugInfo, ErrorOutputType,
         InstrumentCoverage, LdImpl, LinkerPluginLto, LocationDetail, LtoCli, OomStrategy, OptLevel,
         OutputType, OutputTypes, Passes, SourceFileHashAlgorithm, SplitDwarfKind,
-        SwitchWithOptPath, SymbolManglingVersion, TrimmedDefPaths,
+        SwitchWithOptPath, SymbolManglingVersion, TraitSolver, TrimmedDefPaths,
     };
     use crate::lint;
     use crate::options::WasiExecModel;
@@ -2861,6 +2877,7 @@ pub(crate) mod dep_tracking {
         BranchProtection,
         OomStrategy,
         LanguageIdentifier,
+        TraitSolver,
     );
 
     impl<T1, T2> DepTrackingHash for (T1, T2)
@@ -2981,3 +2998,21 @@ pub enum ProcMacroExecutionStrategy {
     /// Run the proc-macro code on a different thread.
     CrossThread,
 }
+
+/// Which format to use for `-Z dump-mono-stats`
+#[derive(Clone, Copy, PartialEq, Hash, Debug)]
+pub enum DumpMonoStatsFormat {
+    /// Pretty-print a markdown table
+    Markdown,
+    /// Emit structured JSON
+    Json,
+}
+
+impl DumpMonoStatsFormat {
+    pub fn extension(self) -> &'static str {
+        match self {
+            Self::Markdown => "md",
+            Self::Json => "json",
+        }
+    }
+}
diff --git a/compiler/rustc_session/src/errors.rs b/compiler/rustc_session/src/errors.rs
index e72b76cfee9..f5a72573d58 100644
--- a/compiler/rustc_session/src/errors.rs
+++ b/compiler/rustc_session/src/errors.rs
@@ -260,9 +260,11 @@ pub(crate) struct InvalidFloatLiteralSuffix {
 
 #[derive(Diagnostic)]
 #[diag(session_int_literal_too_large)]
+#[note]
 pub(crate) struct IntLiteralTooLarge {
     #[primary_span]
     pub span: Span,
+    pub limit: String,
 }
 
 #[derive(Diagnostic)]
@@ -361,8 +363,15 @@ pub fn report_lit_error(sess: &ParseSess, err: LitError, lit: token::Lit, span:
                 _ => unreachable!(),
             };
         }
-        LitError::IntTooLarge => {
-            sess.emit_err(IntLiteralTooLarge { span });
+        LitError::IntTooLarge(base) => {
+            let max = u128::MAX;
+            let limit = match base {
+                2 => format!("{max:#b}"),
+                8 => format!("{max:#o}"),
+                16 => format!("{max:#x}"),
+                _ => format!("{max}"),
+            };
+            sess.emit_err(IntLiteralTooLarge { span, limit });
         }
     }
 }
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index 9bf581ff73d..043a60a1c53 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -377,10 +377,13 @@ mod desc {
     pub const parse_linker_flavor: &str = ::rustc_target::spec::LinkerFlavorCli::one_of();
     pub const parse_optimization_fuel: &str = "crate=integer";
     pub const parse_mir_spanview: &str = "`statement` (default), `terminator`, or `block`";
+    pub const parse_dump_mono_stats: &str = "`markdown` (default) or `json`";
     pub const parse_instrument_coverage: &str =
         "`all` (default), `except-unused-generics`, `except-unused-functions`, or `off`";
     pub const parse_unpretty: &str = "`string` or `string=string`";
     pub const parse_treat_err_as_bug: &str = "either no value or a number bigger than 0";
+    pub const parse_trait_solver: &str =
+        "one of the supported solver modes (`classic`, `chalk`, or `next`)";
     pub const parse_lto: &str =
         "either a boolean (`yes`, `no`, `on`, `off`, etc), `thin`, `fat`, or omitted";
     pub const parse_linker_plugin_lto: &str =
@@ -820,6 +823,21 @@ mod parse {
         true
     }
 
+    pub(crate) fn parse_dump_mono_stats(slot: &mut DumpMonoStatsFormat, v: Option<&str>) -> bool {
+        match v {
+            None => true,
+            Some("json") => {
+                *slot = DumpMonoStatsFormat::Json;
+                true
+            }
+            Some("markdown") => {
+                *slot = DumpMonoStatsFormat::Markdown;
+                true
+            }
+            Some(_) => false,
+        }
+    }
+
     pub(crate) fn parse_instrument_coverage(
         slot: &mut Option<InstrumentCoverage>,
         v: Option<&str>,
@@ -864,6 +882,18 @@ mod parse {
         }
     }
 
+    pub(crate) fn parse_trait_solver(slot: &mut TraitSolver, v: Option<&str>) -> bool {
+        match v {
+            Some("classic") => *slot = TraitSolver::Classic,
+            Some("chalk") => *slot = TraitSolver::Chalk,
+            Some("next") => *slot = TraitSolver::Next,
+            // default trait solver is subject to change..
+            Some("default") => *slot = TraitSolver::Classic,
+            _ => return false,
+        }
+        true
+    }
+
     pub(crate) fn parse_lto(slot: &mut LtoCli, v: Option<&str>) -> bool {
         if v.is_some() {
             let mut bool_arg = None;
@@ -1233,8 +1263,6 @@ options! {
         "instrument control-flow architecture protection"),
     cgu_partitioning_strategy: Option<String> = (None, parse_opt_string, [TRACKED],
         "the codegen unit partitioning strategy to use"),
-    chalk: bool = (false, parse_bool, [TRACKED],
-        "enable the experimental Chalk-based trait solving engine"),
     codegen_backend: Option<String> = (None, parse_opt_string, [TRACKED],
         "the backend to use"),
     combine_cgu: bool = (false, parse_bool, [TRACKED],
@@ -1295,7 +1323,9 @@ options! {
         an additional `.html` file showing the computed coverage spans."),
     dump_mono_stats: SwitchWithOptPath = (SwitchWithOptPath::Disabled,
         parse_switch_with_opt_path, [UNTRACKED],
-        "output statistics about monomorphization collection (format: markdown)"),
+        "output statistics about monomorphization collection"),
+    dump_mono_stats_format: DumpMonoStatsFormat = (DumpMonoStatsFormat::Markdown, parse_dump_mono_stats, [UNTRACKED],
+        "the format to use for -Z dump-mono-stats (`markdown` (default) or `json`)"),
     dwarf_version: Option<u32> = (None, parse_opt_number, [TRACKED],
         "version of DWARF debug information to emit (default: 2 or 4, depending on platform)"),
     dylib_lto: bool = (false, parse_bool, [UNTRACKED],
@@ -1591,6 +1621,8 @@ options! {
         "for every macro invocation, print its name and arguments (default: no)"),
     track_diagnostics: bool = (false, parse_bool, [UNTRACKED],
         "tracks where in rustc a diagnostic was emitted"),
+    trait_solver: TraitSolver = (TraitSolver::Classic, parse_trait_solver, [TRACKED],
+        "specify the trait solver mode used by rustc (default: classic)"),
     // Diagnostics are considered side-effects of a query (see `QuerySideEffects`) and are saved
     // alongside query results and changes to translation options can affect diagnostics - so
     // translation options should be tracked.
diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs
index 4a3d29414d6..1b2e8d9dc70 100644
--- a/compiler/rustc_session/src/session.rs
+++ b/compiler/rustc_session/src/session.rs
@@ -590,7 +590,19 @@ impl Session {
     pub fn warn(&self, msg: impl Into<DiagnosticMessage>) {
         self.diagnostic().warn(msg)
     }
-    /// Delay a span_bug() call until abort_if_errors()
+
+    /// Ensures that compilation cannot succeed.
+    ///
+    /// If this function has been called but no errors have been emitted and
+    /// compilation succeeds, it will cause an internal compiler error (ICE).
+    ///
+    /// This can be used in code paths that should never run on successful compilations.
+    /// For example, it can be used to create an [`ErrorGuaranteed`]
+    /// (but you should prefer threading through the [`ErrorGuaranteed`] from an error emission directly).
+    ///
+    /// If no span is available, use [`DUMMY_SP`].
+    ///
+    /// [`DUMMY_SP`]: rustc_span::DUMMY_SP
     #[track_caller]
     pub fn delay_span_bug<S: Into<MultiSpan>>(
         &self,
diff --git a/compiler/rustc_span/src/def_id.rs b/compiler/rustc_span/src/def_id.rs
index 221f65b66e6..7c5e1427d1e 100644
--- a/compiler/rustc_span/src/def_id.rs
+++ b/compiler/rustc_span/src/def_id.rs
@@ -303,7 +303,7 @@ impl DefId {
         // i.e. don't use closures.
         match self.as_local() {
             Some(local_def_id) => local_def_id,
-            None => panic!("DefId::expect_local: `{:?}` isn't local", self),
+            None => panic!("DefId::expect_local: `{self:?}` isn't local"),
         }
     }
 
diff --git a/compiler/rustc_span/src/edition.rs b/compiler/rustc_span/src/edition.rs
index 065d3660e50..b43183916bc 100644
--- a/compiler/rustc_span/src/edition.rs
+++ b/compiler/rustc_span/src/edition.rs
@@ -44,7 +44,7 @@ impl fmt::Display for Edition {
             Edition::Edition2021 => "2021",
             Edition::Edition2024 => "2024",
         };
-        write!(f, "{}", s)
+        write!(f, "{s}")
     }
 }
 
diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs
index 4e70dfb6147..a9a9a3fbf9d 100644
--- a/compiler/rustc_span/src/hygiene.rs
+++ b/compiler/rustc_span/src/hygiene.rs
@@ -110,7 +110,7 @@ fn assert_default_hashing_controls<CTX: HashStableContext>(ctx: &CTX, msg: &str)
         // Such configuration must not be used for metadata.
         HashingControls { hash_spans }
             if hash_spans == !ctx.unstable_opts_incremental_ignore_spans() => {}
-        other => panic!("Attempted hashing of {msg} with non-default HashingControls: {:?}", other),
+        other => panic!("Attempted hashing of {msg} with non-default HashingControls: {other:?}"),
     }
 }
 
@@ -629,7 +629,7 @@ pub fn update_dollar_crate_names(mut get_name: impl FnMut(SyntaxContext) -> Symb
 pub fn debug_hygiene_data(verbose: bool) -> String {
     HygieneData::with(|data| {
         if verbose {
-            format!("{:#?}", data)
+            format!("{data:#?}")
         } else {
             let mut s = String::from("Expansions:");
             let mut debug_expn_data = |(id, expn_data): (&ExpnId, &ExpnData)| {
@@ -1067,9 +1067,9 @@ impl ExpnKind {
         match *self {
             ExpnKind::Root => kw::PathRoot.to_string(),
             ExpnKind::Macro(macro_kind, name) => match macro_kind {
-                MacroKind::Bang => format!("{}!", name),
-                MacroKind::Attr => format!("#[{}]", name),
-                MacroKind::Derive => format!("#[derive({})]", name),
+                MacroKind::Bang => format!("{name}!"),
+                MacroKind::Attr => format!("#[{name}]"),
+                MacroKind::Derive => format!("#[derive({name})]"),
             },
             ExpnKind::AstPass(kind) => kind.descr().to_string(),
             ExpnKind::Desugaring(kind) => format!("desugaring of {}", kind.descr()),
@@ -1466,11 +1466,7 @@ impl<D: Decoder> Decodable<D> for SyntaxContext {
 /// collisions are only possible between `ExpnId`s within the same crate.
 fn update_disambiguator(expn_data: &mut ExpnData, mut ctx: impl HashStableContext) -> ExpnHash {
     // This disambiguator should not have been set yet.
-    assert_eq!(
-        expn_data.disambiguator, 0,
-        "Already set disambiguator for ExpnData: {:?}",
-        expn_data
-    );
+    assert_eq!(expn_data.disambiguator, 0, "Already set disambiguator for ExpnData: {expn_data:?}");
     assert_default_hashing_controls(&ctx, "ExpnData (disambiguator)");
     let mut expn_hash = expn_data.hash_expn(&mut ctx);
 
diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs
index bee4b0a2332..7e61f2f9f73 100644
--- a/compiler/rustc_span/src/lib.rs
+++ b/compiler/rustc_span/src/lib.rs
@@ -329,7 +329,7 @@ impl fmt::Display for FileNameDisplay<'_> {
             ProcMacroSourceCode(_) => write!(fmt, "<proc-macro source code>"),
             CfgSpec(_) => write!(fmt, "<cfgspec>"),
             CliCrateAttr(_) => write!(fmt, "<crate attribute>"),
-            Custom(ref s) => write!(fmt, "<{}>", s),
+            Custom(ref s) => write!(fmt, "<{s}>"),
             DocTest(ref path, _) => write!(fmt, "{}", path.display()),
             InlineAsm(_) => write!(fmt, "<inline asm>"),
         }
@@ -1074,7 +1074,7 @@ impl NonNarrowChar {
             0 => NonNarrowChar::ZeroWidth(pos),
             2 => NonNarrowChar::Wide(pos),
             4 => NonNarrowChar::Tab(pos),
-            _ => panic!("width {} given for non-narrow character", width),
+            _ => panic!("width {width} given for non-narrow character"),
         }
     }
 
diff --git a/compiler/rustc_span/src/profiling.rs b/compiler/rustc_span/src/profiling.rs
index f169007fab4..0ab890b9f01 100644
--- a/compiler/rustc_span/src/profiling.rs
+++ b/compiler/rustc_span/src/profiling.rs
@@ -27,7 +27,7 @@ impl SpannedEventArgRecorder for EventArgRecorder<'_> {
             if let Some(source_map) = &*session_globals.source_map.borrow() {
                 source_map.span_to_embeddable_string(span)
             } else {
-                format!("{:?}", span)
+                format!("{span:?}")
             }
         });
         self.record_arg(span_arg);
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 85510fa2c66..5d5f8d6d654 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -193,6 +193,7 @@ symbols! {
         FromIterator,
         FromResidual,
         Future,
+        FutureOutput,
         FxHashMap,
         FxHashSet,
         GlobalAlloc,
diff --git a/compiler/rustc_symbol_mangling/src/legacy.rs b/compiler/rustc_symbol_mangling/src/legacy.rs
index a59c9011ab2..23ff6b333f0 100644
--- a/compiler/rustc_symbol_mangling/src/legacy.rs
+++ b/compiler/rustc_symbol_mangling/src/legacy.rs
@@ -175,7 +175,7 @@ impl SymbolPath {
     fn finish(mut self, hash: u64) -> String {
         self.finalize_pending_component();
         // E = end name-sequence
-        let _ = write!(self.result, "17h{:016x}E", hash);
+        let _ = write!(self.result, "17h{hash:016x}E");
         self.result
     }
 }
@@ -227,7 +227,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolPrinter<'tcx> {
                 self = self.print_type(ty)?;
                 self.write_str("; ")?;
                 if let Some(size) = size.kind().try_to_bits(self.tcx().data_layout.pointer_size) {
-                    write!(self, "{}", size)?
+                    write!(self, "{size}")?
                 } else if let ty::ConstKind::Param(param) = size.kind() {
                     self = param.print(self)?
                 } else {
diff --git a/compiler/rustc_symbol_mangling/src/lib.rs b/compiler/rustc_symbol_mangling/src/lib.rs
index 62f44a48032..547a5907660 100644
--- a/compiler/rustc_symbol_mangling/src/lib.rs
+++ b/compiler/rustc_symbol_mangling/src/lib.rs
@@ -269,8 +269,7 @@ fn compute_symbol_name<'tcx>(
 
     debug_assert!(
         rustc_demangle::try_demangle(&symbol).is_ok(),
-        "compute_symbol_name: `{}` cannot be demangled",
-        symbol
+        "compute_symbol_name: `{symbol}` cannot be demangled"
     );
 
     symbol
diff --git a/compiler/rustc_symbol_mangling/src/test.rs b/compiler/rustc_symbol_mangling/src/test.rs
index 150459ce0f5..c6899f8f244 100644
--- a/compiler/rustc_symbol_mangling/src/test.rs
+++ b/compiler/rustc_symbol_mangling/src/test.rs
@@ -74,7 +74,7 @@ impl SymbolNamesTest<'_> {
                 tcx.sess.emit_err(TestOutput {
                     span: attr.span,
                     kind: Kind::DemanglingAlt,
-                    content: format!("{:#}", demangling),
+                    content: format!("{demangling:#}"),
                 });
             }
         }
diff --git a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs
index e9b85705086..0759b95bd94 100644
--- a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs
+++ b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs
@@ -126,11 +126,11 @@ fn encode_const<'tcx>(
         if value < zero {
             s.push('n')
         };
-        let _ = write!(s, "{}", value);
+        let _ = write!(s, "{value}");
     }
 
     fn push_unsigned_value<T: Display>(s: &mut String, value: T) {
-        let _ = write!(s, "{}", value);
+        let _ = write!(s, "{value}");
     }
 
     if let Some(scalar_int) = c.kind().try_to_scalar_int() {
diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs
index 4285aa62cb9..0d446d654dc 100644
--- a/compiler/rustc_symbol_mangling/src/v0.rs
+++ b/compiler/rustc_symbol_mangling/src/v0.rs
@@ -206,6 +206,7 @@ impl<'tcx> SymbolMangler<'tcx> {
     where
         T: TypeVisitable<'tcx>,
     {
+        // FIXME(non-lifetime-binders): What to do here?
         let regions = if value.has_late_bound_regions() {
             self.tcx.collect_referenced_late_bound_regions(value)
         } else {
@@ -609,7 +610,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> {
                     bits = val.unsigned_abs();
                 }
 
-                let _ = write!(self.out, "{:x}_", bits);
+                let _ = write!(self.out, "{bits:x}_");
             }
 
             // FIXME(valtrees): Remove the special case for `str`
@@ -637,7 +638,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> {
 
                                 // FIXME(eddyb) use a specialized hex-encoding loop.
                                 for byte in s.bytes() {
-                                    let _ = write!(self.out, "{:02x}", byte);
+                                    let _ = write!(self.out, "{byte:02x}");
                                 }
 
                                 self.push("_");
diff --git a/compiler/rustc_target/src/abi/call/mod.rs b/compiler/rustc_target/src/abi/call/mod.rs
index a5ffaebea0b..3b8c867d35b 100644
--- a/compiler/rustc_target/src/abi/call/mod.rs
+++ b/compiler/rustc_target/src/abi/call/mod.rs
@@ -71,12 +71,7 @@ mod attr_impl {
             const NonNull   = 1 << 3;
             const ReadOnly  = 1 << 4;
             const InReg     = 1 << 5;
-            // Due to past miscompiles in LLVM, we use a separate attribute for
-            // &mut arguments, so that the codegen backend can decide whether
-            // or not to actually emit the attribute. It can also be controlled
-            // with the `-Zmutable-noalias` debugging option.
-            const NoAliasMutRef = 1 << 6;
-            const NoUndef = 1 << 7;
+            const NoUndef = 1 << 6;
         }
     }
 }
@@ -177,12 +172,12 @@ impl Reg {
                 17..=32 => dl.i32_align.abi,
                 33..=64 => dl.i64_align.abi,
                 65..=128 => dl.i128_align.abi,
-                _ => panic!("unsupported integer: {:?}", self),
+                _ => panic!("unsupported integer: {self:?}"),
             },
             RegKind::Float => match self.size.bits() {
                 32 => dl.f32_align.abi,
                 64 => dl.f64_align.abi,
-                _ => panic!("unsupported float: {:?}", self),
+                _ => panic!("unsupported float: {self:?}"),
             },
             RegKind::Vector => dl.vector_align(self.size).abi,
         }
@@ -642,7 +637,7 @@ impl fmt::Display for AdjustForForeignAbiError {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match self {
             Self::Unsupported { arch, abi } => {
-                write!(f, "target architecture {:?} does not support `extern {}` ABI", arch, abi)
+                write!(f, "target architecture {arch:?} does not support `extern {abi}` ABI")
             }
         }
     }
@@ -760,7 +755,7 @@ impl FromStr for Conv {
             "AmdGpuKernel" => Ok(Conv::AmdGpuKernel),
             "AvrInterrupt" => Ok(Conv::AvrInterrupt),
             "AvrNonBlockingInterrupt" => Ok(Conv::AvrNonBlockingInterrupt),
-            _ => Err(format!("'{}' is not a valid value for entry function call convetion.", s)),
+            _ => Err(format!("'{s}' is not a valid value for entry function call convetion.")),
         }
     }
 }
diff --git a/compiler/rustc_target/src/asm/aarch64.rs b/compiler/rustc_target/src/asm/aarch64.rs
index 62a0f9fb034..28493c7700f 100644
--- a/compiler/rustc_target/src/asm/aarch64.rs
+++ b/compiler/rustc_target/src/asm/aarch64.rs
@@ -195,6 +195,6 @@ impl AArch64InlineAsmReg {
             (modifier.unwrap_or('v'), self as u32 - Self::v0 as u32)
         };
         assert!(index < 32);
-        write!(out, "{}{}", prefix, index)
+        write!(out, "{prefix}{index}")
     }
 }
diff --git a/compiler/rustc_target/src/asm/arm.rs b/compiler/rustc_target/src/asm/arm.rs
index 0db3eb6fcac..ec7429a3065 100644
--- a/compiler/rustc_target/src/asm/arm.rs
+++ b/compiler/rustc_target/src/asm/arm.rs
@@ -249,7 +249,7 @@ impl ArmInlineAsmReg {
             let index = self as u32 - Self::q0 as u32;
             assert!(index < 16);
             let index = index * 2 + (modifier == 'f') as u32;
-            write!(out, "d{}", index)
+            write!(out, "d{index}")
         } else {
             out.write_str(self.name())
         }
diff --git a/compiler/rustc_target/src/asm/mod.rs b/compiler/rustc_target/src/asm/mod.rs
index 65d2cd64bf6..7f01f33d39c 100644
--- a/compiler/rustc_target/src/asm/mod.rs
+++ b/compiler/rustc_target/src/asm/mod.rs
@@ -679,13 +679,13 @@ impl fmt::Display for InlineAsmType {
             Self::I128 => f.write_str("i128"),
             Self::F32 => f.write_str("f32"),
             Self::F64 => f.write_str("f64"),
-            Self::VecI8(n) => write!(f, "i8x{}", n),
-            Self::VecI16(n) => write!(f, "i16x{}", n),
-            Self::VecI32(n) => write!(f, "i32x{}", n),
-            Self::VecI64(n) => write!(f, "i64x{}", n),
-            Self::VecI128(n) => write!(f, "i128x{}", n),
-            Self::VecF32(n) => write!(f, "f32x{}", n),
-            Self::VecF64(n) => write!(f, "f64x{}", n),
+            Self::VecI8(n) => write!(f, "i8x{n}"),
+            Self::VecI16(n) => write!(f, "i16x{n}"),
+            Self::VecI32(n) => write!(f, "i32x{n}"),
+            Self::VecI64(n) => write!(f, "i64x{n}"),
+            Self::VecI128(n) => write!(f, "i128x{n}"),
+            Self::VecF32(n) => write!(f, "f32x{n}"),
+            Self::VecF64(n) => write!(f, "f64x{n}"),
         }
     }
 }
diff --git a/compiler/rustc_target/src/asm/x86.rs b/compiler/rustc_target/src/asm/x86.rs
index 238c365093f..5eae07f141f 100644
--- a/compiler/rustc_target/src/asm/x86.rs
+++ b/compiler/rustc_target/src/asm/x86.rs
@@ -357,28 +357,28 @@ impl X86InlineAsmReg {
         if self as u32 <= Self::dx as u32 {
             let root = ['a', 'b', 'c', 'd'][self as usize - Self::ax as usize];
             match modifier.unwrap_or(reg_default_modifier) {
-                'l' => write!(out, "{}l", root),
-                'h' => write!(out, "{}h", root),
-                'x' => write!(out, "{}x", root),
-                'e' => write!(out, "e{}x", root),
-                'r' => write!(out, "r{}x", root),
+                'l' => write!(out, "{root}l"),
+                'h' => write!(out, "{root}h"),
+                'x' => write!(out, "{root}x"),
+                'e' => write!(out, "e{root}x"),
+                'r' => write!(out, "r{root}x"),
                 _ => unreachable!(),
             }
         } else if self as u32 <= Self::di as u32 {
             let root = self.name();
             match modifier.unwrap_or(reg_default_modifier) {
-                'l' => write!(out, "{}l", root),
-                'x' => write!(out, "{}", root),
-                'e' => write!(out, "e{}", root),
-                'r' => write!(out, "r{}", root),
+                'l' => write!(out, "{root}l"),
+                'x' => write!(out, "{root}"),
+                'e' => write!(out, "e{root}"),
+                'r' => write!(out, "r{root}"),
                 _ => unreachable!(),
             }
         } else if self as u32 <= Self::r15 as u32 {
             let root = self.name();
             match modifier.unwrap_or(reg_default_modifier) {
-                'l' => write!(out, "{}b", root),
-                'x' => write!(out, "{}w", root),
-                'e' => write!(out, "{}d", root),
+                'l' => write!(out, "{root}b"),
+                'x' => write!(out, "{root}w"),
+                'e' => write!(out, "{root}d"),
                 'r' => out.write_str(root),
                 _ => unreachable!(),
             }
@@ -387,15 +387,15 @@ impl X86InlineAsmReg {
         } else if self as u32 <= Self::xmm15 as u32 {
             let prefix = modifier.unwrap_or('x');
             let index = self as u32 - Self::xmm0 as u32;
-            write!(out, "{}{}", prefix, index)
+            write!(out, "{prefix}{index}")
         } else if self as u32 <= Self::ymm15 as u32 {
             let prefix = modifier.unwrap_or('y');
             let index = self as u32 - Self::ymm0 as u32;
-            write!(out, "{}{}", prefix, index)
+            write!(out, "{prefix}{index}")
         } else if self as u32 <= Self::zmm31 as u32 {
             let prefix = modifier.unwrap_or('z');
             let index = self as u32 - Self::zmm0 as u32;
-            write!(out, "{}{}", prefix, index)
+            write!(out, "{prefix}{index}")
         } else {
             out.write_str(self.name())
         }
diff --git a/compiler/rustc_target/src/spec/aarch64_fuchsia.rs b/compiler/rustc_target/src/spec/aarch64_unknown_fuchsia.rs
index 4634433c4a9..da493f0c260 100644
--- a/compiler/rustc_target/src/spec/aarch64_fuchsia.rs
+++ b/compiler/rustc_target/src/spec/aarch64_unknown_fuchsia.rs
@@ -2,7 +2,7 @@ use crate::spec::{SanitizerSet, Target, TargetOptions};
 
 pub fn target() -> Target {
     Target {
-        llvm_target: "aarch64-fuchsia".into(),
+        llvm_target: "aarch64-unknown-fuchsia".into(),
         pointer_width: 64,
         data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
         arch: "aarch64".into(),
diff --git a/compiler/rustc_target/src/spec/apple_base.rs b/compiler/rustc_target/src/spec/apple_base.rs
index 44644c4733e..5c6dcc0aba9 100644
--- a/compiler/rustc_target/src/spec/apple_base.rs
+++ b/compiler/rustc_target/src/spec/apple_base.rs
@@ -76,7 +76,7 @@ impl Arch {
 
 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(),
+        "sim" => format!("{os}-simulator").into(),
         "macabi" => "mac-catalyst".into(),
         _ => os.into(),
     };
@@ -193,7 +193,7 @@ fn macos_deployment_target(arch: Arch) -> (u32, u32) {
 
 fn macos_lld_platform_version(arch: Arch) -> String {
     let (major, minor) = macos_deployment_target(arch);
-    format!("{}.{}", major, minor)
+    format!("{major}.{minor}")
 }
 
 pub fn macos_llvm_target(arch: Arch) -> String {
@@ -252,7 +252,7 @@ pub fn ios_llvm_target(arch: Arch) -> String {
 
 fn ios_lld_platform_version() -> String {
     let (major, minor) = ios_deployment_target();
-    format!("{}.{}", major, minor)
+    format!("{major}.{minor}")
 }
 
 pub fn ios_sim_llvm_target(arch: Arch) -> String {
@@ -266,7 +266,7 @@ fn tvos_deployment_target() -> (u32, u32) {
 
 fn tvos_lld_platform_version() -> String {
     let (major, minor) = tvos_deployment_target();
-    format!("{}.{}", major, minor)
+    format!("{major}.{minor}")
 }
 
 fn watchos_deployment_target() -> (u32, u32) {
@@ -275,7 +275,7 @@ fn watchos_deployment_target() -> (u32, u32) {
 
 fn watchos_lld_platform_version() -> String {
     let (major, minor) = watchos_deployment_target();
-    format!("{}.{}", major, minor)
+    format!("{major}.{minor}")
 }
 
 pub fn watchos_sim_llvm_target(arch: Arch) -> String {
diff --git a/compiler/rustc_target/src/spec/armv7_sony_vita_newlibeabihf.rs b/compiler/rustc_target/src/spec/armv7_sony_vita_newlibeabihf.rs
new file mode 100644
index 00000000000..ebd2cca25ea
--- /dev/null
+++ b/compiler/rustc_target/src/spec/armv7_sony_vita_newlibeabihf.rs
@@ -0,0 +1,40 @@
+use crate::abi::Endian;
+use crate::spec::{cvs, Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions};
+
+/// A base target for PlayStation Vita devices using the VITASDK toolchain (using newlib).
+///
+/// Requires the VITASDK toolchain on the host system.
+
+pub fn target() -> Target {
+    let pre_link_args = TargetOptions::link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-Wl,-q"]);
+
+    Target {
+        llvm_target: "armv7a-vita-newlibeabihf".into(),
+        pointer_width: 32,
+        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
+        arch: "arm".into(),
+
+        options: TargetOptions {
+            os: "vita".into(),
+            endian: Endian::Little,
+            c_int_width: "32".into(),
+            dynamic_linking: false,
+            env: "newlib".into(),
+            vendor: "sony".into(),
+            abi: "eabihf".into(),
+            linker_flavor: LinkerFlavor::Gnu(Cc::Yes, Lld::No),
+            no_default_libraries: false,
+            cpu: "cortex-a9".into(),
+            executables: true,
+            families: cvs!["unix"],
+            linker: Some("arm-vita-eabi-gcc".into()),
+            relocation_model: RelocModel::Static,
+            features: "+v7,+neon".into(),
+            pre_link_args,
+            exe_suffix: ".elf".into(),
+            panic_strategy: PanicStrategy::Abort,
+            max_atomic_width: Some(32),
+            ..Default::default()
+        },
+    }
+}
diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs
index 4512db49403..0fafa52a45b 100644
--- a/compiler/rustc_target/src/spec/mod.rs
+++ b/compiler/rustc_target/src/spec/mod.rs
@@ -840,7 +840,7 @@ impl fmt::Display for SanitizerSet {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         let mut first = true;
         for s in *self {
-            let name = s.as_str().unwrap_or_else(|| panic!("unrecognized sanitizer {:?}", s));
+            let name = s.as_str().unwrap_or_else(|| panic!("unrecognized sanitizer {s:?}"));
             if !first {
                 f.write_str(", ")?;
             }
@@ -1109,8 +1109,8 @@ supported_targets! {
     ("x86_64-apple-darwin", x86_64_apple_darwin),
     ("i686-apple-darwin", i686_apple_darwin),
 
-    ("aarch64-fuchsia", aarch64_fuchsia),
-    ("x86_64-fuchsia", x86_64_fuchsia),
+    ("aarch64-unknown-fuchsia", aarch64_unknown_fuchsia),
+    ("x86_64-unknown-fuchsia", x86_64_unknown_fuchsia),
 
     ("avr-unknown-gnu-atmega328", avr_unknown_gnu_atmega328),
 
@@ -1241,6 +1241,8 @@ supported_targets! {
 
     ("aarch64-nintendo-switch-freestanding", aarch64_nintendo_switch_freestanding),
 
+    ("armv7-sony-vita-newlibeabihf", armv7_sony_vita_newlibeabihf),
+
     ("armv7-unknown-linux-uclibceabi", armv7_unknown_linux_uclibceabi),
     ("armv7-unknown-linux-uclibceabihf", armv7_unknown_linux_uclibceabihf),
 
@@ -2072,7 +2074,7 @@ impl Target {
         let mut get_req_field = |name: &str| {
             obj.remove(name)
                 .and_then(|j| j.as_str().map(str::to_string))
-                .ok_or_else(|| format!("Field {} in target specification is required", name))
+                .ok_or_else(|| format!("Field {name} in target specification is required"))
         };
 
         let mut base = Target {
@@ -2478,7 +2480,7 @@ impl Target {
             if let Some(s) = fp.as_str() {
                 base.frame_pointer = s
                     .parse()
-                    .map_err(|()| format!("'{}' is not a valid value for frame-pointer", s))?;
+                    .map_err(|()| format!("'{s}' is not a valid value for frame-pointer"))?;
             } else {
                 incorrect_type.push("frame-pointer".into())
             }
@@ -2670,7 +2672,7 @@ impl Target {
                     return load_file(&p);
                 }
 
-                Err(format!("Could not find specification for target {:?}", target_triple))
+                Err(format!("Could not find specification for target {target_triple:?}"))
             }
             TargetTriple::TargetJson { ref contents, .. } => {
                 let obj = serde_json::from_str(contents).map_err(|e| e.to_string())?;
@@ -2934,7 +2936,7 @@ impl TargetTriple {
         let contents = std::fs::read_to_string(&canonicalized_path).map_err(|err| {
             io::Error::new(
                 io::ErrorKind::InvalidInput,
-                format!("target path {:?} is not a valid file: {}", canonicalized_path, err),
+                format!("target path {canonicalized_path:?} is not a valid file: {err}"),
             )
         })?;
         let triple = canonicalized_path
@@ -2969,7 +2971,7 @@ impl TargetTriple {
                 let mut hasher = DefaultHasher::new();
                 content.hash(&mut hasher);
                 let hash = hasher.finish();
-                format!("{}-{}", triple, hash)
+                format!("{triple}-{hash}")
             }
         }
     }
diff --git a/compiler/rustc_target/src/spec/solid_base.rs b/compiler/rustc_target/src/spec/solid_base.rs
index c585a6cd58e..eaf72b7616c 100644
--- a/compiler/rustc_target/src/spec/solid_base.rs
+++ b/compiler/rustc_target/src/spec/solid_base.rs
@@ -3,7 +3,7 @@ use crate::spec::TargetOptions;
 
 pub fn opts(kernel: &str) -> TargetOptions {
     TargetOptions {
-        os: format!("solid_{}", kernel).into(),
+        os: format!("solid_{kernel}").into(),
         vendor: "kmc".into(),
         executables: false,
         frame_pointer: FramePointer::NonLeaf,
diff --git a/compiler/rustc_target/src/spec/x86_64_fuchsia.rs b/compiler/rustc_target/src/spec/x86_64_unknown_fuchsia.rs
index 532dd6d0742..a3231d19f4c 100644
--- a/compiler/rustc_target/src/spec/x86_64_fuchsia.rs
+++ b/compiler/rustc_target/src/spec/x86_64_unknown_fuchsia.rs
@@ -8,7 +8,7 @@ pub fn target() -> Target {
     base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::CFI;
 
     Target {
-        llvm_target: "x86_64-fuchsia".into(),
+        llvm_target: "x86_64-unknown-fuchsia".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(),
diff --git a/compiler/rustc_trait_selection/src/solve/overflow.rs b/compiler/rustc_trait_selection/src/solve/overflow.rs
index 8d73a83aec9..fdd6adb681b 100644
--- a/compiler/rustc_trait_selection/src/solve/overflow.rs
+++ b/compiler/rustc_trait_selection/src/solve/overflow.rs
@@ -36,7 +36,7 @@ impl OverflowData {
 
     #[inline]
     pub(super) fn has_overflow(&self, depth: usize) -> bool {
-        self.current_limit.value_within_limit(depth + self.additional_depth)
+        !self.current_limit.value_within_limit(depth + self.additional_depth)
     }
 
     /// Updating the current limit when hitting overflow.
diff --git a/compiler/rustc_trait_selection/src/traits/engine.rs b/compiler/rustc_trait_selection/src/traits/engine.rs
index c028e89e4ea..bc6d9d4b922 100644
--- a/compiler/rustc_trait_selection/src/traits/engine.rs
+++ b/compiler/rustc_trait_selection/src/traits/engine.rs
@@ -3,6 +3,7 @@ use std::fmt::Debug;
 
 use super::TraitEngine;
 use super::{ChalkFulfillmentContext, FulfillmentContext};
+use crate::solve::FulfillmentCtxt as NextFulfillmentCtxt;
 use crate::traits::NormalizeExt;
 use rustc_data_structures::fx::FxIndexSet;
 use rustc_hir::def_id::{DefId, LocalDefId};
@@ -20,6 +21,7 @@ use rustc_middle::ty::error::TypeError;
 use rustc_middle::ty::ToPredicate;
 use rustc_middle::ty::TypeFoldable;
 use rustc_middle::ty::{self, Ty, TyCtxt};
+use rustc_session::config::TraitSolver;
 use rustc_span::Span;
 
 pub trait TraitEngineExt<'tcx> {
@@ -29,18 +31,18 @@ pub trait TraitEngineExt<'tcx> {
 
 impl<'tcx> TraitEngineExt<'tcx> for dyn TraitEngine<'tcx> {
     fn new(tcx: TyCtxt<'tcx>) -> Box<Self> {
-        if tcx.sess.opts.unstable_opts.chalk {
-            Box::new(ChalkFulfillmentContext::new())
-        } else {
-            Box::new(FulfillmentContext::new())
+        match tcx.sess.opts.unstable_opts.trait_solver {
+            TraitSolver::Classic => Box::new(FulfillmentContext::new()),
+            TraitSolver::Chalk => Box::new(ChalkFulfillmentContext::new()),
+            TraitSolver::Next => Box::new(NextFulfillmentCtxt::new()),
         }
     }
 
     fn new_in_snapshot(tcx: TyCtxt<'tcx>) -> Box<Self> {
-        if tcx.sess.opts.unstable_opts.chalk {
-            Box::new(ChalkFulfillmentContext::new_in_snapshot())
-        } else {
-            Box::new(FulfillmentContext::new_in_snapshot())
+        match tcx.sess.opts.unstable_opts.trait_solver {
+            TraitSolver::Classic => Box::new(FulfillmentContext::new_in_snapshot()),
+            TraitSolver::Chalk => Box::new(ChalkFulfillmentContext::new_in_snapshot()),
+            TraitSolver::Next => Box::new(NextFulfillmentCtxt::new()),
         }
     }
 }
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 8a08c7533aa..9c098e1a2fc 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
@@ -33,13 +33,14 @@ use rustc_infer::infer::error_reporting::TypeErrCtxt;
 use rustc_infer::infer::{InferOk, TypeTrace};
 use rustc_middle::traits::select::OverflowError;
 use rustc_middle::ty::abstract_const::NotConstEvaluatable;
-use rustc_middle::ty::error::ExpectedFound;
+use rustc_middle::ty::error::{ExpectedFound, TypeError};
 use rustc_middle::ty::fold::{TypeFolder, TypeSuperFoldable};
 use rustc_middle::ty::print::{with_forced_trimmed_paths, FmtPrinter, Print};
 use rustc_middle::ty::{
     self, SubtypePredicate, ToPolyTraitRef, ToPredicate, TraitRef, Ty, TyCtxt, TypeFoldable,
     TypeVisitable,
 };
+use rustc_session::config::TraitSolver;
 use rustc_session::Limit;
 use rustc_span::def_id::LOCAL_CRATE;
 use rustc_span::symbol::sym;
@@ -770,7 +771,11 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                                 ),
                             }
                         };
-
+                        self.check_for_binding_assigned_block_without_tail_expression(
+                            &obligation,
+                            &mut err,
+                            trait_predicate,
+                        );
                         if self.suggest_add_reference_to_arg(
                             &obligation,
                             &mut err,
@@ -868,6 +873,11 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                             );
                         }
 
+                        if self.suggest_add_clone_to_arg(&obligation, &mut err, trait_predicate) {
+                            err.emit();
+                            return;
+                        }
+
                         if self.suggest_impl_trait(&mut err, span, &obligation, trait_predicate) {
                             err.emit();
                             return;
@@ -1167,7 +1177,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                     }
 
                     ty::PredicateKind::WellFormed(ty) => {
-                        if !self.tcx.sess.opts.unstable_opts.chalk {
+                        if self.tcx.sess.opts.unstable_opts.trait_solver == TraitSolver::Classic {
                             // WF predicates cannot themselves make
                             // errors. They can only block due to
                             // ambiguity; otherwise, they always
@@ -1179,7 +1189,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                             // which bounds actually failed to hold.
                             self.tcx.sess.struct_span_err(
                                 span,
-                                &format!("the type `{}` is not well-formed (chalk)", ty),
+                                &format!("the type `{}` is not well-formed", ty),
                             )
                         }
                     }
@@ -1215,6 +1225,25 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                 }
             }
 
+            OutputTypeParameterMismatch(
+                found_trait_ref,
+                expected_trait_ref,
+                terr @ TypeError::CyclicTy(_),
+            ) => {
+                let self_ty = found_trait_ref.self_ty().skip_binder();
+                let (cause, terr) = if let ty::Closure(def_id, _) = self_ty.kind() {
+                    (
+                        ObligationCause::dummy_with_span(tcx.def_span(def_id)),
+                        TypeError::CyclicTy(self_ty),
+                    )
+                } else {
+                    (obligation.cause.clone(), terr)
+                };
+                self.report_and_explain_type_error(
+                    TypeTrace::poly_trait_refs(&cause, true, expected_trait_ref, found_trait_ref),
+                    terr,
+                )
+            }
             OutputTypeParameterMismatch(found_trait_ref, expected_trait_ref, _) => {
                 let found_trait_ref = self.resolve_vars_if_possible(found_trait_ref);
                 let expected_trait_ref = self.resolve_vars_if_possible(expected_trait_ref);
@@ -1387,7 +1416,6 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
 
         self.note_obligation_cause(&mut err, &obligation);
         self.point_at_returns_when_relevant(&mut err, &obligation);
-
         err.emit();
     }
 }
@@ -2247,23 +2275,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                 if let (Some(body_id), Some(ty::subst::GenericArgKind::Type(_))) =
                     (body_id, subst.map(|subst| subst.unpack()))
                 {
-                    struct FindExprBySpan<'hir> {
-                        span: Span,
-                        result: Option<&'hir hir::Expr<'hir>>,
-                    }
-
-                    impl<'v> hir::intravisit::Visitor<'v> for FindExprBySpan<'v> {
-                        fn visit_expr(&mut self, ex: &'v hir::Expr<'v>) {
-                            if self.span == ex.span {
-                                self.result = Some(ex);
-                            } else {
-                                hir::intravisit::walk_expr(self, ex);
-                            }
-                        }
-                    }
-
-                    let mut expr_finder = FindExprBySpan { span, result: None };
-
+                    let mut expr_finder = FindExprBySpan::new(span);
                     expr_finder.visit_expr(&self.tcx.hir().body(body_id).value);
 
                     if let Some(hir::Expr {
@@ -2750,6 +2762,36 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
     }
 }
 
+/// Crude way of getting back an `Expr` from a `Span`.
+pub struct FindExprBySpan<'hir> {
+    pub span: Span,
+    pub result: Option<&'hir hir::Expr<'hir>>,
+    pub ty_result: Option<&'hir hir::Ty<'hir>>,
+}
+
+impl<'hir> FindExprBySpan<'hir> {
+    fn new(span: Span) -> Self {
+        Self { span, result: None, ty_result: None }
+    }
+}
+
+impl<'v> Visitor<'v> for FindExprBySpan<'v> {
+    fn visit_expr(&mut self, ex: &'v hir::Expr<'v>) {
+        if self.span == ex.span {
+            self.result = Some(ex);
+        } else {
+            hir::intravisit::walk_expr(self, ex);
+        }
+    }
+    fn visit_ty(&mut self, ty: &'v hir::Ty<'v>) {
+        if self.span == ty.span {
+            self.ty_result = Some(ty);
+        } else {
+            hir::intravisit::walk_ty(self, ty);
+        }
+    }
+}
+
 /// Look for type `param` in an ADT being used only through a reference to confirm that suggesting
 /// `param: ?Sized` would be a valid constraint.
 struct FindTypeParam {
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 9bfe527647d..b0a730c8ad1 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
@@ -117,7 +117,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                 Some(if movability.is_some() { "an async closure" } else { "a closure" })
             }),
             hir::Node::Expr(hir::Expr { .. }) => {
-                let parent_hid = hir.get_parent_node(hir_id);
+                let parent_hid = hir.parent_id(hir_id);
                 if parent_hid != hir_id { self.describe_enclosure(parent_hid) } else { None }
             }
             _ => None,
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
index 7c21a1047bc..c52365ae3b7 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -1,13 +1,16 @@
 // ignore-tidy-filelength
 
-use super::{DefIdOrName, Obligation, ObligationCause, ObligationCauseCode, PredicateObligation};
+use super::{
+    DefIdOrName, FindExprBySpan, Obligation, ObligationCause, ObligationCauseCode,
+    PredicateObligation,
+};
 
 use crate::autoderef::Autoderef;
 use crate::infer::InferCtxt;
 use crate::traits::{NormalizeExt, ObligationCtxt};
 
 use hir::def::CtorOf;
-use hir::HirId;
+use hir::{Expr, HirId};
 use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_errors::{
@@ -196,6 +199,20 @@ pub trait TypeErrCtxtExt<'tcx> {
         trait_pred: ty::PolyTraitPredicate<'tcx>,
     ) -> bool;
 
+    fn check_for_binding_assigned_block_without_tail_expression(
+        &self,
+        obligation: &PredicateObligation<'tcx>,
+        err: &mut Diagnostic,
+        trait_pred: ty::PolyTraitPredicate<'tcx>,
+    );
+
+    fn suggest_add_clone_to_arg(
+        &self,
+        obligation: &PredicateObligation<'tcx>,
+        err: &mut Diagnostic,
+        trait_pred: ty::PolyTraitPredicate<'tcx>,
+    ) -> bool;
+
     fn suggest_add_reference_to_arg(
         &self,
         obligation: &PredicateObligation<'tcx>,
@@ -248,7 +265,7 @@ pub trait TypeErrCtxtExt<'tcx> {
 
     fn point_at_returns_when_relevant(
         &self,
-        err: &mut Diagnostic,
+        err: &mut DiagnosticBuilder<'tcx, ErrorGuaranteed>,
         obligation: &PredicateObligation<'tcx>,
     );
 
@@ -838,8 +855,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
 
         let hir = self.tcx.hir();
         let hir_id = hir.local_def_id_to_hir_id(def_id.as_local()?);
-        let parent_node = hir.get_parent_node(hir_id);
-        match hir.find(parent_node) {
+        match hir.find_parent(hir_id) {
             Some(hir::Node::Stmt(hir::Stmt { kind: hir::StmtKind::Local(local), .. })) => {
                 get_name(err, &local.pat.kind)
             }
@@ -1033,6 +1049,115 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
         true
     }
 
+    fn check_for_binding_assigned_block_without_tail_expression(
+        &self,
+        obligation: &PredicateObligation<'tcx>,
+        err: &mut Diagnostic,
+        trait_pred: ty::PolyTraitPredicate<'tcx>,
+    ) {
+        let mut span = obligation.cause.span;
+        while span.from_expansion() {
+            // Remove all the desugaring and macro contexts.
+            span.remove_mark();
+        }
+        let mut expr_finder = FindExprBySpan::new(span);
+        let Some(hir::Node::Expr(body)) = self.tcx.hir().find(obligation.cause.body_id) else { return; };
+        expr_finder.visit_expr(&body);
+        let Some(expr) = expr_finder.result else { return; };
+        let Some(typeck) = &self.typeck_results else { return; };
+        let Some(ty) = typeck.expr_ty_adjusted_opt(expr) else { return; };
+        if !ty.is_unit() {
+            return;
+        };
+        let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = expr.kind else { return; };
+        let hir::def::Res::Local(hir_id) = path.res else { return; };
+        let Some(hir::Node::Pat(pat)) = self.tcx.hir().find(hir_id) else {
+            return;
+        };
+        let Some(hir::Node::Local(hir::Local {
+            ty: None,
+            init: Some(init),
+            ..
+        })) = self.tcx.hir().find_parent(pat.hir_id) else { return; };
+        let hir::ExprKind::Block(block, None) = init.kind else { return; };
+        if block.expr.is_some() {
+            return;
+        }
+        let [.., stmt] = block.stmts else {
+            err.span_label(block.span, "this empty block is missing a tail expression");
+            return;
+        };
+        let hir::StmtKind::Semi(tail_expr) = stmt.kind else { return; };
+        let Some(ty) = typeck.expr_ty_opt(tail_expr) else {
+            err.span_label(block.span, "this block is missing a tail expression");
+            return;
+        };
+        let ty = self.resolve_numeric_literals_with_default(self.resolve_vars_if_possible(ty));
+        let trait_pred_and_self = trait_pred.map_bound(|trait_pred| (trait_pred, ty));
+
+        let new_obligation =
+            self.mk_trait_obligation_with_new_self_ty(obligation.param_env, trait_pred_and_self);
+        if self.predicate_must_hold_modulo_regions(&new_obligation) {
+            err.span_suggestion_short(
+                stmt.span.with_lo(tail_expr.span.hi()),
+                "remove this semicolon",
+                "",
+                Applicability::MachineApplicable,
+            );
+        } else {
+            err.span_label(block.span, "this block is missing a tail expression");
+        }
+    }
+
+    fn suggest_add_clone_to_arg(
+        &self,
+        obligation: &PredicateObligation<'tcx>,
+        err: &mut Diagnostic,
+        trait_pred: ty::PolyTraitPredicate<'tcx>,
+    ) -> bool {
+        let self_ty = self.resolve_vars_if_possible(trait_pred.self_ty());
+        let ty = self.tcx.erase_late_bound_regions(self_ty);
+        let owner = self.tcx.hir().get_parent_item(obligation.cause.body_id);
+        let Some(generics) = self.tcx.hir().get_generics(owner.def_id) else { return false };
+        let ty::Ref(_, inner_ty, hir::Mutability::Not) = ty.kind() else { return false };
+        let ty::Param(param) = inner_ty.kind() else { return false };
+        let ObligationCauseCode::FunctionArgumentObligation { arg_hir_id, .. } = obligation.cause.code() else { return false };
+        let arg_node = self.tcx.hir().get(*arg_hir_id);
+        let Node::Expr(Expr { kind: hir::ExprKind::Path(_), ..}) = arg_node else { return false };
+
+        let clone_trait = self.tcx.require_lang_item(LangItem::Clone, None);
+        let has_clone = |ty| {
+            self.type_implements_trait(clone_trait, [ty], obligation.param_env)
+                .must_apply_modulo_regions()
+        };
+
+        let new_obligation = self.mk_trait_obligation_with_new_self_ty(
+            obligation.param_env,
+            trait_pred.map_bound(|trait_pred| (trait_pred, *inner_ty)),
+        );
+
+        if self.predicate_may_hold(&new_obligation) && has_clone(ty) {
+            if !has_clone(param.to_ty(self.tcx)) {
+                suggest_constraining_type_param(
+                    self.tcx,
+                    generics,
+                    err,
+                    param.name.as_str(),
+                    "Clone",
+                    Some(clone_trait),
+                );
+            }
+            err.span_suggestion_verbose(
+                obligation.cause.span.shrink_to_hi(),
+                "consider using clone here",
+                ".clone()".to_string(),
+                Applicability::MaybeIncorrect,
+            );
+            return true;
+        }
+        false
+    }
+
     fn suggest_add_reference_to_arg(
         &self,
         obligation: &PredicateObligation<'tcx>,
@@ -1421,7 +1546,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
         trait_pred: ty::PolyTraitPredicate<'tcx>,
     ) -> bool {
         let hir = self.tcx.hir();
-        let parent_node = hir.get_parent_node(obligation.cause.body_id);
+        let parent_node = hir.parent_id(obligation.cause.body_id);
         let node = hir.find(parent_node);
         if let Some(hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(sig, _, body_id), .. })) = node
             && let hir::ExprKind::Block(blk, _) = &hir.body(*body_id).value.kind
@@ -1458,7 +1583,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
 
     fn return_type_span(&self, obligation: &PredicateObligation<'tcx>) -> Option<Span> {
         let hir = self.tcx.hir();
-        let parent_node = hir.get_parent_node(obligation.cause.body_id);
+        let parent_node = hir.parent_id(obligation.cause.body_id);
         let Some(hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(sig, ..), .. })) = hir.find(parent_node) else {
             return None;
         };
@@ -1483,7 +1608,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
         }
 
         let hir = self.tcx.hir();
-        let fn_hir_id = hir.get_parent_node(obligation.cause.body_id);
+        let fn_hir_id = hir.parent_id(obligation.cause.body_id);
         let node = hir.find(fn_hir_id);
         let Some(hir::Node::Item(hir::Item {
             kind: hir::ItemKind::Fn(sig, _, body_id),
@@ -1686,7 +1811,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
 
     fn point_at_returns_when_relevant(
         &self,
-        err: &mut Diagnostic,
+        err: &mut DiagnosticBuilder<'tcx, ErrorGuaranteed>,
         obligation: &PredicateObligation<'tcx>,
     ) {
         match obligation.cause.code().peel_derives() {
@@ -1695,7 +1820,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
         }
 
         let hir = self.tcx.hir();
-        let parent_node = hir.get_parent_node(obligation.cause.body_id);
+        let parent_node = hir.parent_id(obligation.cause.body_id);
         let node = hir.find(parent_node);
         if let Some(hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, _, body_id), .. })) =
             node
@@ -1708,7 +1833,15 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
             for expr in &visitor.returns {
                 if let Some(returned_ty) = typeck_results.node_type_opt(expr.hir_id) {
                     let ty = self.resolve_vars_if_possible(returned_ty);
-                    err.span_label(expr.span, &format!("this returned value is of type `{}`", ty));
+                    if ty.references_error() {
+                        // don't print out the [type error] here
+                        err.delay_as_bug();
+                    } else {
+                        err.span_label(
+                            expr.span,
+                            &format!("this returned value is of type `{}`", ty),
+                        );
+                    }
                 }
             }
         }
@@ -2291,7 +2424,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                         let expr = hir.expect_expr(expr_id);
                         debug!("target_ty evaluated from {:?}", expr);
 
-                        let parent = hir.get_parent_node(expr_id);
+                        let parent = hir.parent_id(expr_id);
                         if let Some(hir::Node::Expr(e)) = hir.find(parent) {
                             let parent_span = hir.span(parent);
                             let parent_did = parent.owner.to_def_id();
@@ -2512,7 +2645,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                 }
             }
             ObligationCauseCode::VariableType(hir_id) => {
-                let parent_node = self.tcx.hir().get_parent_node(hir_id);
+                let parent_node = self.tcx.hir().parent_id(hir_id);
                 match self.tcx.hir().find(parent_node) {
                     Some(Node::Local(hir::Local { ty: Some(ty), .. })) => {
                         err.span_suggestion_verbose(
@@ -2992,7 +3125,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
         span: Span,
     ) {
         let body_hir_id = obligation.cause.body_id;
-        let item_id = self.tcx.hir().get_parent_node(body_hir_id);
+        let item_id = self.tcx.hir().parent_id(body_hir_id);
 
         if let Some(body_id) =
             self.tcx.hir().maybe_body_owned_by(self.tcx.hir().local_def_id(item_id))
@@ -3219,7 +3352,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
             if let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = expr.kind
                 && let hir::Path { res: hir::def::Res::Local(hir_id), .. } = path
                 && let Some(hir::Node::Pat(binding)) = self.tcx.hir().find(*hir_id)
-                && let parent_hir_id = self.tcx.hir().get_parent_node(binding.hir_id)
+                && let parent_hir_id = self.tcx.hir().parent_id(binding.hir_id)
                 && let Some(hir::Node::Local(local)) = self.tcx.hir().find(parent_hir_id)
                 && let Some(binding_expr) = local.init
             {
@@ -3287,8 +3420,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
             if let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = expr.kind
                 && let hir::Path { res: hir::def::Res::Local(hir_id), .. } = path
                 && let Some(hir::Node::Pat(binding)) = self.tcx.hir().find(*hir_id)
-                && let parent_hir_id = self.tcx.hir().get_parent_node(binding.hir_id)
-                && let Some(parent) = self.tcx.hir().find(parent_hir_id)
+                && let Some(parent) = self.tcx.hir().find_parent(binding.hir_id)
             {
                 // We've reached the root of the method call chain...
                 if let hir::Node::Local(local) = parent
diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
index 466641ea6df..15526b34ed2 100644
--- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
@@ -15,6 +15,7 @@ use rustc_middle::ty::{
     self, Binder, GenericArg, GenericArgKind, GenericParamDefKind, InternalSubsts, SubstsRef,
     ToPolyTraitRef, ToPredicate, TraitRef, Ty, TyCtxt,
 };
+use rustc_session::config::TraitSolver;
 use rustc_span::def_id::DefId;
 
 use crate::traits::project::{normalize_with_depth, normalize_with_depth_to};
@@ -767,8 +768,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         debug!(?closure_def_id, ?trait_ref, ?nested, "confirm closure candidate obligations");
 
         // FIXME: Chalk
-
-        if !self.tcx().sess.opts.unstable_opts.chalk {
+        if self.tcx().sess.opts.unstable_opts.trait_solver != TraitSolver::Chalk {
             nested.push(obligation.with(
                 self.tcx(),
                 ty::Binder::dummy(ty::PredicateKind::ClosureKind(closure_def_id, substs, kind)),
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index 760b4585f4e..3f14491f803 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -755,7 +755,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                     // contain the "'static" lifetime (any other lifetime
                     // would either be late-bound or local), so it is guaranteed
                     // to outlive any other lifetime
-                    if pred.0.is_global() && !pred.0.has_late_bound_regions() {
+                    if pred.0.is_global() && !pred.0.has_late_bound_vars() {
                         Ok(EvaluatedToOk)
                     } else {
                         Ok(EvaluatedToOkModuloRegions)
@@ -1785,9 +1785,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         // Check if a bound would previously have been removed when normalizing
         // the param_env so that it can be given the lowest priority. See
         // #50825 for the motivation for this.
-        let is_global = |cand: &ty::PolyTraitPredicate<'tcx>| {
-            cand.is_global() && !cand.has_late_bound_regions()
-        };
+        let is_global =
+            |cand: &ty::PolyTraitPredicate<'tcx>| cand.is_global() && !cand.has_late_bound_vars();
 
         // (*) Prefer `BuiltinCandidate { has_nested: false }`, `PointeeCandidate`,
         // `DiscriminantKindCandidate`, `ConstDestructCandidate`
diff --git a/compiler/rustc_traits/src/dropck_outlives.rs b/compiler/rustc_traits/src/dropck_outlives.rs
index 3f661ce6923..481b56e111e 100644
--- a/compiler/rustc_traits/src/dropck_outlives.rs
+++ b/compiler/rustc_traits/src/dropck_outlives.rs
@@ -189,7 +189,7 @@ fn dtorck_constraint_for_ty<'tcx>(
 
                 tcx.sess.delay_span_bug(
                     span,
-                    &format!("upvar_tys for closure not found. Expected capture information for closure {}", ty,),
+                    &format!("upvar_tys for closure not found. Expected capture information for closure {ty}",),
                 );
                 return Err(NoSolution);
             }
@@ -231,7 +231,7 @@ fn dtorck_constraint_for_ty<'tcx>(
                 // be fully resolved.
                 tcx.sess.delay_span_bug(
                     span,
-                    &format!("upvar_tys for generator not found. Expected capture information for generator {}", ty,),
+                    &format!("upvar_tys for generator not found. Expected capture information for generator {ty}",),
                 );
                 return Err(NoSolution);
             }
diff --git a/compiler/rustc_traits/src/normalize_erasing_regions.rs b/compiler/rustc_traits/src/normalize_erasing_regions.rs
index 6e6bc62a040..5cad2c2ccb0 100644
--- a/compiler/rustc_traits/src/normalize_erasing_regions.rs
+++ b/compiler/rustc_traits/src/normalize_erasing_regions.rs
@@ -47,7 +47,7 @@ fn try_normalize_after_erasing_regions<'tcx, T: TypeFoldable<'tcx> + PartialEq +
             // us a test case.
             debug_assert_eq!(normalized_value, resolved_value);
             let erased = infcx.tcx.erase_regions(resolved_value);
-            debug_assert!(!erased.needs_infer(), "{:?}", erased);
+            debug_assert!(!erased.needs_infer(), "{erased:?}");
             Ok(erased)
         }
         Err(NoSolution) => Err(NoSolution),
diff --git a/compiler/rustc_transmute/src/layout/mod.rs b/compiler/rustc_transmute/src/layout/mod.rs
index 07035ebdfb1..f8d05bc89d2 100644
--- a/compiler/rustc_transmute/src/layout/mod.rs
+++ b/compiler/rustc_transmute/src/layout/mod.rs
@@ -24,7 +24,7 @@ impl fmt::Debug for Byte {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match &self {
             Self::Uninit => f.write_str("??u8"),
-            Self::Init(b) => write!(f, "{:#04x}u8", b),
+            Self::Init(b) => write!(f, "{b:#04x}u8"),
         }
     }
 }
diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs
index 73d2d278f93..f8a5691f29d 100644
--- a/compiler/rustc_ty_utils/src/abi.rs
+++ b/compiler/rustc_ty_utils/src/abi.rs
@@ -256,6 +256,11 @@ fn adjust_for_rust_scalar<'tcx>(
             // See https://github.com/rust-lang/unsafe-code-guidelines/issues/326
             let noalias_for_box = cx.tcx.sess.opts.unstable_opts.box_noalias.unwrap_or(true);
 
+            // LLVM prior to version 12 had known miscompiles in the presence of noalias attributes
+            // (see #54878), so it was conditionally disabled, but we don't support earlier
+            // versions at all anymore. We still support turning it off using -Zmutable-noalias.
+            let noalias_mut_ref = cx.tcx.sess.opts.unstable_opts.mutable_noalias.unwrap_or(true);
+
             // `&mut` pointer parameters never alias other parameters,
             // or mutable global data
             //
@@ -263,15 +268,9 @@ fn adjust_for_rust_scalar<'tcx>(
             // and can be marked as both `readonly` and `noalias`, as
             // LLVM's definition of `noalias` is based solely on memory
             // dependencies rather than pointer equality
-            //
-            // Due to past miscompiles in LLVM, we apply a separate NoAliasMutRef attribute
-            // for UniqueBorrowed arguments, so that the codegen backend can decide whether
-            // or not to actually emit the attribute. It can also be controlled with the
-            // `-Zmutable-noalias` debugging option.
             let no_alias = match kind {
-                PointerKind::SharedMutable
-                | PointerKind::UniqueBorrowed
-                | PointerKind::UniqueBorrowedPinned => false,
+                PointerKind::SharedMutable | PointerKind::UniqueBorrowedPinned => false,
+                PointerKind::UniqueBorrowed => noalias_mut_ref,
                 PointerKind::UniqueOwned => noalias_for_box,
                 PointerKind::Frozen => true,
             };
@@ -284,10 +283,6 @@ fn adjust_for_rust_scalar<'tcx>(
             if kind == PointerKind::Frozen && !is_return {
                 attrs.set(ArgAttribute::ReadOnly);
             }
-
-            if kind == PointerKind::UniqueBorrowed && !is_return {
-                attrs.set(ArgAttribute::NoAliasMutRef);
-            }
         }
     }
 }
diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs
index c8c6acaa453..6aa016133ca 100644
--- a/compiler/rustc_ty_utils/src/layout.rs
+++ b/compiler/rustc_ty_utils/src/layout.rs
@@ -155,17 +155,37 @@ fn layout_of_uncached<'tcx>(
             }
 
             let unsized_part = tcx.struct_tail_erasing_lifetimes(pointee, param_env);
-            let metadata = match unsized_part.kind() {
-                ty::Foreign(..) => {
+
+            let metadata = if let Some(metadata_def_id) = tcx.lang_items().metadata_type() {
+                let metadata_ty = tcx.normalize_erasing_regions(
+                    param_env,
+                    tcx.mk_projection(metadata_def_id, [pointee]),
+                );
+                let metadata_layout = cx.layout_of(metadata_ty)?;
+                // If the metadata is a 1-zst, then the pointer is thin.
+                if metadata_layout.is_zst() && metadata_layout.align.abi.bytes() == 1 {
                     return Ok(tcx.intern_layout(LayoutS::scalar(cx, data_ptr)));
                 }
-                ty::Slice(_) | ty::Str => scalar_unit(Int(dl.ptr_sized_integer(), false)),
-                ty::Dynamic(..) => {
-                    let mut vtable = scalar_unit(Pointer);
-                    vtable.valid_range_mut().start = 1;
-                    vtable
+
+                let Abi::Scalar(metadata) = metadata_layout.abi else {
+                    return Err(LayoutError::Unknown(unsized_part));
+                };
+                metadata
+            } else {
+                match unsized_part.kind() {
+                    ty::Foreign(..) => {
+                        return Ok(tcx.intern_layout(LayoutS::scalar(cx, data_ptr)));
+                    }
+                    ty::Slice(_) | ty::Str => scalar_unit(Int(dl.ptr_sized_integer(), false)),
+                    ty::Dynamic(..) => {
+                        let mut vtable = scalar_unit(Pointer);
+                        vtable.valid_range_mut().start = 1;
+                        vtable
+                    }
+                    _ => {
+                        return Err(LayoutError::Unknown(unsized_part));
+                    }
                 }
-                _ => return Err(LayoutError::Unknown(unsized_part)),
             };
 
             // Effectively a (ptr, meta) tuple.
diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs
index e2d10f550c3..87923ebbe4b 100644
--- a/compiler/rustc_ty_utils/src/ty.rs
+++ b/compiler/rustc_ty_utils/src/ty.rs
@@ -2,6 +2,7 @@ use rustc_data_structures::fx::FxIndexSet;
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_middle::ty::{self, Binder, Predicate, PredicateKind, ToPredicate, Ty, TyCtxt};
+use rustc_session::config::TraitSolver;
 use rustc_trait_selection::traits;
 
 fn sized_constraint_for_ty<'tcx>(
@@ -121,7 +122,7 @@ fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> {
     // are any errors at that point, so outside of type inference you can be
     // sure that this will succeed without errors anyway.
 
-    if tcx.sess.opts.unstable_opts.chalk {
+    if tcx.sess.opts.unstable_opts.trait_solver == TraitSolver::Chalk {
         let environment = well_formed_types_in_env(tcx, def_id);
         predicates.extend(environment);
     }
@@ -161,7 +162,7 @@ fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> {
                 kind: hir::ImplItemKind::Type(..) | hir::ImplItemKind::Fn(..),
                 ..
             }) => {
-                let parent_hir_id = tcx.hir().get_parent_node(hir_id);
+                let parent_hir_id = tcx.hir().parent_id(hir_id);
                 match tcx.hir().get(parent_hir_id) {
                     hir::Node::Item(hir::Item {
                         kind: hir::ItemKind::Impl(hir::Impl { constness, .. }),
diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs
index dd36a5c7a21..44004cb0be1 100644
--- a/compiler/rustc_type_ir/src/lib.rs
+++ b/compiler/rustc_type_ir/src/lib.rs
@@ -241,22 +241,30 @@ bitflags! {
         /// Basically anything but `ReLateBound` and `ReErased`.
         const HAS_FREE_REGIONS            = 1 << 14;
 
-        /// Does this have any `ReLateBound` regions? Used to check
-        /// if a global bound is safe to evaluate.
+        /// Does this have any `ReLateBound` regions?
         const HAS_RE_LATE_BOUND           = 1 << 15;
+        /// Does this have any `Bound` types?
+        const HAS_TY_LATE_BOUND           = 1 << 16;
+        /// Does this have any `ConstKind::Bound` consts?
+        const HAS_CT_LATE_BOUND           = 1 << 17;
+        /// Does this have any bound variables?
+        /// Used to check if a global bound is safe to evaluate.
+        const HAS_LATE_BOUND              = TypeFlags::HAS_RE_LATE_BOUND.bits
+                                          | TypeFlags::HAS_TY_LATE_BOUND.bits
+                                          | TypeFlags::HAS_CT_LATE_BOUND.bits;
 
         /// Does this have any `ReErased` regions?
-        const HAS_RE_ERASED               = 1 << 16;
+        const HAS_RE_ERASED               = 1 << 18;
 
         /// Does this value have parameters/placeholders/inference variables which could be
         /// replaced later, in a way that would change the results of `impl` specialization?
-        const STILL_FURTHER_SPECIALIZABLE = 1 << 17;
+        const STILL_FURTHER_SPECIALIZABLE = 1 << 19;
 
         /// Does this value have `InferTy::FreshTy/FreshIntTy/FreshFloatTy`?
-        const HAS_TY_FRESH                = 1 << 18;
+        const HAS_TY_FRESH                = 1 << 20;
 
         /// Does this value have `InferConst::Fresh`?
-        const HAS_CT_FRESH                = 1 << 19;
+        const HAS_CT_FRESH                = 1 << 21;
     }
 }
 
@@ -718,9 +726,9 @@ impl fmt::Debug for InferTy {
             TyVar(ref v) => v.fmt(f),
             IntVar(ref v) => v.fmt(f),
             FloatVar(ref v) => v.fmt(f),
-            FreshTy(v) => write!(f, "FreshTy({:?})", v),
-            FreshIntTy(v) => write!(f, "FreshIntTy({:?})", v),
-            FreshFloatTy(v) => write!(f, "FreshFloatTy({:?})", v),
+            FreshTy(v) => write!(f, "FreshTy({v:?})"),
+            FreshIntTy(v) => write!(f, "FreshIntTy({v:?})"),
+            FreshFloatTy(v) => write!(f, "FreshFloatTy({v:?})"),
         }
     }
 }
@@ -743,9 +751,9 @@ impl fmt::Display for InferTy {
             TyVar(_) => write!(f, "_"),
             IntVar(_) => write!(f, "{}", "{integer}"),
             FloatVar(_) => write!(f, "{}", "{float}"),
-            FreshTy(v) => write!(f, "FreshTy({})", v),
-            FreshIntTy(v) => write!(f, "FreshIntTy({})", v),
-            FreshFloatTy(v) => write!(f, "FreshFloatTy({})", v),
+            FreshTy(v) => write!(f, "FreshTy({v})"),
+            FreshIntTy(v) => write!(f, "FreshIntTy({v})"),
+            FreshFloatTy(v) => write!(f, "FreshFloatTy({v})"),
         }
     }
 }
diff --git a/compiler/rustc_type_ir/src/sty.rs b/compiler/rustc_type_ir/src/sty.rs
index f30ae82d7cd..b944cbd698d 100644
--- a/compiler/rustc_type_ir/src/sty.rs
+++ b/compiler/rustc_type_ir/src/sty.rs
@@ -1028,10 +1028,10 @@ impl<I: Interner> hash::Hash for RegionKind<I> {
 impl<I: Interner> fmt::Debug for RegionKind<I> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match self {
-            ReEarlyBound(data) => write!(f, "ReEarlyBound({:?})", data),
+            ReEarlyBound(data) => write!(f, "ReEarlyBound({data:?})"),
 
             ReLateBound(binder_id, bound_region) => {
-                write!(f, "ReLateBound({:?}, {:?})", binder_id, bound_region)
+                write!(f, "ReLateBound({binder_id:?}, {bound_region:?})")
             }
 
             ReFree(fr) => fr.fmt(f),
@@ -1040,7 +1040,7 @@ impl<I: Interner> fmt::Debug for RegionKind<I> {
 
             ReVar(vid) => vid.fmt(f),
 
-            RePlaceholder(placeholder) => write!(f, "RePlaceholder({:?})", placeholder),
+            RePlaceholder(placeholder) => write!(f, "RePlaceholder({placeholder:?})"),
 
             ReErased => f.write_str("ReErased"),
         }
diff --git a/library/alloc/Cargo.toml b/library/alloc/Cargo.toml
index 265020209eb..95c07abf731 100644
--- a/library/alloc/Cargo.toml
+++ b/library/alloc/Cargo.toml
@@ -13,8 +13,8 @@ core = { path = "../core" }
 compiler_builtins = { version = "0.1.40", features = ['rustc-dep-of-std'] }
 
 [dev-dependencies]
-rand = "0.7"
-rand_xorshift = "0.2"
+rand = { version = "0.8.5", default-features = false, features = ["alloc"] }
+rand_xorshift = "0.3.0"
 
 [[test]]
 name = "collectionstests"
diff --git a/library/alloc/benches/slice.rs b/library/alloc/benches/slice.rs
index bd6f38f2f10..b62be9d39a1 100644
--- a/library/alloc/benches/slice.rs
+++ b/library/alloc/benches/slice.rs
@@ -1,6 +1,6 @@
 use std::{mem, ptr};
 
-use rand::distributions::{Alphanumeric, Standard};
+use rand::distributions::{Alphanumeric, DistString, Standard};
 use rand::Rng;
 use test::{black_box, Bencher};
 
@@ -218,7 +218,7 @@ fn gen_strings(len: usize) -> Vec<String> {
     let mut v = vec![];
     for _ in 0..len {
         let n = rng.gen::<usize>() % 20 + 1;
-        v.push((&mut rng).sample_iter(&Alphanumeric).take(n).collect());
+        v.push(Alphanumeric.sample_string(&mut rng, n));
     }
     v
 }
diff --git a/library/alloc/src/alloc.rs b/library/alloc/src/alloc.rs
index a2fdec6fbfe..fe6de1cf879 100644
--- a/library/alloc/src/alloc.rs
+++ b/library/alloc/src/alloc.rs
@@ -402,7 +402,20 @@ pub mod __alloc_error_handler {
     // `#[alloc_error_handler]`.
     #[rustc_std_internal_symbol]
     pub unsafe fn __rdl_oom(size: usize, _align: usize) -> ! {
-        panic!("memory allocation of {size} bytes failed")
+        extern "Rust" {
+            // This symbol is emitted by rustc next to __rust_alloc_error_handler.
+            // Its value depends on the -Zoom={panic,abort} compiler option.
+            static __rust_alloc_error_handler_should_panic: u8;
+        }
+
+        #[allow(unused_unsafe)]
+        if unsafe { __rust_alloc_error_handler_should_panic != 0 } {
+            panic!("memory allocation of {size} bytes failed")
+        } else {
+            core::panicking::panic_nounwind_fmt(format_args!(
+                "memory allocation of {size} bytes failed"
+            ))
+        }
     }
 }
 
diff --git a/library/alloc/src/boxed/thin.rs b/library/alloc/src/boxed/thin.rs
index c477c44906c..c1a82e452f6 100644
--- a/library/alloc/src/boxed/thin.rs
+++ b/library/alloc/src/boxed/thin.rs
@@ -226,24 +226,45 @@ impl<H> WithHeader<H> {
     // - Assumes that either `value` can be dereferenced, or is the
     //   `NonNull::dangling()` we use when both `T` and `H` are ZSTs.
     unsafe fn drop<T: ?Sized>(&self, value: *mut T) {
+        struct DropGuard<H> {
+            ptr: NonNull<u8>,
+            value_layout: Layout,
+            _marker: PhantomData<H>,
+        }
+
+        impl<H> Drop for DropGuard<H> {
+            fn drop(&mut self) {
+                unsafe {
+                    // SAFETY: Layout must have been computable if we're in drop
+                    let (layout, value_offset) =
+                        WithHeader::<H>::alloc_layout(self.value_layout).unwrap_unchecked();
+
+                    // Note: Don't deallocate if the layout size is zero, because the pointer
+                    // didn't come from the allocator.
+                    if layout.size() != 0 {
+                        alloc::dealloc(self.ptr.as_ptr().sub(value_offset), layout);
+                    } else {
+                        debug_assert!(
+                            value_offset == 0
+                                && mem::size_of::<H>() == 0
+                                && self.value_layout.size() == 0
+                        );
+                    }
+                }
+            }
+        }
+
         unsafe {
-            let value_layout = Layout::for_value_raw(value);
-            // SAFETY: Layout must have been computable if we're in drop
-            let (layout, value_offset) = Self::alloc_layout(value_layout).unwrap_unchecked();
+            // `_guard` will deallocate the memory when dropped, even if `drop_in_place` unwinds.
+            let _guard = DropGuard {
+                ptr: self.0,
+                value_layout: Layout::for_value_raw(value),
+                _marker: PhantomData::<H>,
+            };
 
             // We only drop the value because the Pointee trait requires that the metadata is copy
             // aka trivially droppable.
             ptr::drop_in_place::<T>(value);
-
-            // Note: Don't deallocate if the layout size is zero, because the pointer
-            // didn't come from the allocator.
-            if layout.size() != 0 {
-                alloc::dealloc(self.0.as_ptr().sub(value_offset), layout);
-            } else {
-                debug_assert!(
-                    value_offset == 0 && mem::size_of::<H>() == 0 && value_layout.size() == 0
-                );
-            }
         }
     }
 
diff --git a/library/alloc/src/collections/binary_heap/tests.rs b/library/alloc/src/collections/binary_heap/tests.rs
index fe08e0e10e8..59c516374c0 100644
--- a/library/alloc/src/collections/binary_heap/tests.rs
+++ b/library/alloc/src/collections/binary_heap/tests.rs
@@ -465,7 +465,7 @@ fn test_retain() {
 #[test]
 #[cfg(not(target_os = "emscripten"))]
 fn panic_safe() {
-    use rand::{seq::SliceRandom, thread_rng};
+    use rand::seq::SliceRandom;
     use std::cmp;
     use std::panic::{self, AssertUnwindSafe};
     use std::sync::atomic::{AtomicUsize, Ordering};
@@ -490,7 +490,7 @@ fn panic_safe() {
             self.0.partial_cmp(&other.0)
         }
     }
-    let mut rng = thread_rng();
+    let mut rng = crate::test_helpers::test_rng();
     const DATASZ: usize = 32;
     // Miri is too slow
     let ntest = if cfg!(miri) { 1 } else { 10 };
diff --git a/library/alloc/src/collections/linked_list/tests.rs b/library/alloc/src/collections/linked_list/tests.rs
index 5d5af22bb29..04594d55b6a 100644
--- a/library/alloc/src/collections/linked_list/tests.rs
+++ b/library/alloc/src/collections/linked_list/tests.rs
@@ -5,7 +5,7 @@ use crate::vec::Vec;
 use std::panic::{catch_unwind, AssertUnwindSafe};
 use std::thread;
 
-use rand::{thread_rng, RngCore};
+use rand::RngCore;
 
 #[test]
 fn test_basic() {
@@ -481,12 +481,12 @@ fn test_split_off_2() {
     }
 }
 
-fn fuzz_test(sz: i32) {
+fn fuzz_test(sz: i32, rng: &mut impl RngCore) {
     let mut m: LinkedList<_> = LinkedList::new();
     let mut v = vec![];
     for i in 0..sz {
         check_links(&m);
-        let r: u8 = thread_rng().next_u32() as u8;
+        let r: u8 = rng.next_u32() as u8;
         match r % 6 {
             0 => {
                 m.pop_back();
@@ -521,11 +521,12 @@ fn fuzz_test(sz: i32) {
 
 #[test]
 fn test_fuzz() {
+    let mut rng = crate::test_helpers::test_rng();
     for _ in 0..25 {
-        fuzz_test(3);
-        fuzz_test(16);
+        fuzz_test(3, &mut rng);
+        fuzz_test(16, &mut rng);
         #[cfg(not(miri))] // Miri is too slow
-        fuzz_test(189);
+        fuzz_test(189, &mut rng);
     }
 }
 
diff --git a/library/alloc/src/collections/vec_deque/mod.rs b/library/alloc/src/collections/vec_deque/mod.rs
index c955db46d29..451e4936bc5 100644
--- a/library/alloc/src/collections/vec_deque/mod.rs
+++ b/library/alloc/src/collections/vec_deque/mod.rs
@@ -636,6 +636,7 @@ impl<T, A: Allocator> VecDeque<T, A> {
     /// buf.push_back(3);
     /// buf.push_back(4);
     /// buf.push_back(5);
+    /// buf.push_back(6);
     /// assert_eq!(buf.get(1), Some(&4));
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -661,10 +662,11 @@ impl<T, A: Allocator> VecDeque<T, A> {
     /// buf.push_back(3);
     /// buf.push_back(4);
     /// buf.push_back(5);
+    /// buf.push_back(6);
+    /// assert_eq!(buf[1], 4);
     /// if let Some(elem) = buf.get_mut(1) {
     ///     *elem = 7;
     /// }
-    ///
     /// assert_eq!(buf[1], 7);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -2821,9 +2823,9 @@ impl<T, A: Allocator> From<Vec<T, A>> for VecDeque<T, A> {
     /// [`Vec<T>`]: crate::vec::Vec
     /// [`VecDeque<T>`]: crate::collections::VecDeque
     ///
-    /// In its current implementation, this is a very cheap
-    /// conversion. This isn't yet a guarantee though, and
-    /// shouldn't be relied on.
+    /// This conversion is guaranteed to run in *O*(1) time
+    /// and to not re-allocate the `Vec`'s buffer or allocate
+    /// any additional memory.
     #[inline]
     fn from(other: Vec<T, A>) -> Self {
         let (ptr, len, cap, alloc) = other.into_raw_parts_with_alloc();
diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs
index 9857f0516ba..4e812529c2c 100644
--- a/library/alloc/src/lib.rs
+++ b/library/alloc/src/lib.rs
@@ -110,6 +110,7 @@
 #![feature(const_maybe_uninit_as_mut_ptr)]
 #![feature(const_refs_to_cell)]
 #![feature(core_intrinsics)]
+#![feature(core_panic)]
 #![feature(const_eval_select)]
 #![feature(const_pin)]
 #![feature(const_waker)]
@@ -191,6 +192,7 @@
 #![feature(unsized_fn_params)]
 #![feature(c_unwind)]
 #![feature(with_negative_coherence)]
+#![cfg_attr(test, feature(panic_update_hook))]
 //
 // Rustdoc features:
 #![feature(doc_cfg)]
@@ -254,3 +256,20 @@ pub mod vec;
 pub mod __export {
     pub use core::format_args;
 }
+
+#[cfg(test)]
+#[allow(dead_code)] // Not used in all configurations
+pub(crate) mod test_helpers {
+    /// Copied from `std::test_helpers::test_rng`, since these tests rely on the
+    /// seed not being the same for every RNG invocation too.
+    pub(crate) fn test_rng() -> rand_xorshift::XorShiftRng {
+        use std::hash::{BuildHasher, Hash, Hasher};
+        let mut hasher = std::collections::hash_map::RandomState::new().build_hasher();
+        std::panic::Location::caller().hash(&mut hasher);
+        let hc64 = hasher.finish();
+        let seed_vec =
+            hc64.to_le_bytes().into_iter().chain(0u8..8).collect::<crate::vec::Vec<u8>>();
+        let seed: [u8; 16] = seed_vec.as_slice().try_into().unwrap();
+        rand::SeedableRng::from_seed(seed)
+    }
+}
diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs
index 80a5913daa6..c1d853ed652 100644
--- a/library/alloc/src/rc.rs
+++ b/library/alloc/src/rc.rs
@@ -2561,7 +2561,7 @@ impl<T: ?Sized> Clone for Weak<T> {
 }
 
 #[stable(feature = "rc_weak", since = "1.4.0")]
-impl<T: ?Sized + fmt::Debug> fmt::Debug for Weak<T> {
+impl<T: ?Sized> fmt::Debug for Weak<T> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         write!(f, "(Weak)")
     }
diff --git a/library/alloc/src/slice.rs b/library/alloc/src/slice.rs
index 4cfb2def098..e9886fc5717 100644
--- a/library/alloc/src/slice.rs
+++ b/library/alloc/src/slice.rs
@@ -28,6 +28,9 @@ use crate::borrow::ToOwned;
 use crate::boxed::Box;
 use crate::vec::Vec;
 
+#[cfg(test)]
+mod tests;
+
 #[unstable(feature = "slice_range", issue = "76393")]
 pub use core::slice::range;
 #[unstable(feature = "array_chunks", issue = "74985")]
diff --git a/library/alloc/src/slice/tests.rs b/library/alloc/src/slice/tests.rs
new file mode 100644
index 00000000000..f674530aaa5
--- /dev/null
+++ b/library/alloc/src/slice/tests.rs
@@ -0,0 +1,359 @@
+use crate::borrow::ToOwned;
+use crate::rc::Rc;
+use crate::string::ToString;
+use crate::test_helpers::test_rng;
+use crate::vec::Vec;
+
+use core::cell::Cell;
+use core::cmp::Ordering::{self, Equal, Greater, Less};
+use core::convert::identity;
+use core::fmt;
+use core::mem;
+use core::sync::atomic::{AtomicUsize, Ordering::Relaxed};
+use rand::{distributions::Standard, prelude::*, Rng, RngCore};
+use std::panic;
+
+macro_rules! do_test {
+    ($input:ident, $func:ident) => {
+        let len = $input.len();
+
+        // Work out the total number of comparisons required to sort
+        // this array...
+        let mut count = 0usize;
+        $input.to_owned().$func(|a, b| {
+            count += 1;
+            a.cmp(b)
+        });
+
+        // ... and then panic on each and every single one.
+        for panic_countdown in 0..count {
+            // Refresh the counters.
+            VERSIONS.store(0, Relaxed);
+            for i in 0..len {
+                DROP_COUNTS[i].store(0, Relaxed);
+            }
+
+            let v = $input.to_owned();
+            let _ = std::panic::catch_unwind(move || {
+                let mut v = v;
+                let mut panic_countdown = panic_countdown;
+                v.$func(|a, b| {
+                    if panic_countdown == 0 {
+                        SILENCE_PANIC.with(|s| s.set(true));
+                        panic!();
+                    }
+                    panic_countdown -= 1;
+                    a.cmp(b)
+                })
+            });
+
+            // Check that the number of things dropped is exactly
+            // what we expect (i.e., the contents of `v`).
+            for (i, c) in DROP_COUNTS.iter().enumerate().take(len) {
+                let count = c.load(Relaxed);
+                assert!(count == 1, "found drop count == {} for i == {}, len == {}", count, i, len);
+            }
+
+            // Check that the most recent versions of values were dropped.
+            assert_eq!(VERSIONS.load(Relaxed), 0);
+        }
+    };
+}
+
+const MAX_LEN: usize = 80;
+
+static DROP_COUNTS: [AtomicUsize; MAX_LEN] = [
+    // FIXME(RFC 1109): AtomicUsize is not Copy.
+    AtomicUsize::new(0),
+    AtomicUsize::new(0),
+    AtomicUsize::new(0),
+    AtomicUsize::new(0),
+    AtomicUsize::new(0),
+    AtomicUsize::new(0),
+    AtomicUsize::new(0),
+    AtomicUsize::new(0),
+    AtomicUsize::new(0),
+    AtomicUsize::new(0),
+    AtomicUsize::new(0),
+    AtomicUsize::new(0),
+    AtomicUsize::new(0),
+    AtomicUsize::new(0),
+    AtomicUsize::new(0),
+    AtomicUsize::new(0),
+    AtomicUsize::new(0),
+    AtomicUsize::new(0),
+    AtomicUsize::new(0),
+    AtomicUsize::new(0),
+    AtomicUsize::new(0),
+    AtomicUsize::new(0),
+    AtomicUsize::new(0),
+    AtomicUsize::new(0),
+    AtomicUsize::new(0),
+    AtomicUsize::new(0),
+    AtomicUsize::new(0),
+    AtomicUsize::new(0),
+    AtomicUsize::new(0),
+    AtomicUsize::new(0),
+    AtomicUsize::new(0),
+    AtomicUsize::new(0),
+    AtomicUsize::new(0),
+    AtomicUsize::new(0),
+    AtomicUsize::new(0),
+    AtomicUsize::new(0),
+    AtomicUsize::new(0),
+    AtomicUsize::new(0),
+    AtomicUsize::new(0),
+    AtomicUsize::new(0),
+    AtomicUsize::new(0),
+    AtomicUsize::new(0),
+    AtomicUsize::new(0),
+    AtomicUsize::new(0),
+    AtomicUsize::new(0),
+    AtomicUsize::new(0),
+    AtomicUsize::new(0),
+    AtomicUsize::new(0),
+    AtomicUsize::new(0),
+    AtomicUsize::new(0),
+    AtomicUsize::new(0),
+    AtomicUsize::new(0),
+    AtomicUsize::new(0),
+    AtomicUsize::new(0),
+    AtomicUsize::new(0),
+    AtomicUsize::new(0),
+    AtomicUsize::new(0),
+    AtomicUsize::new(0),
+    AtomicUsize::new(0),
+    AtomicUsize::new(0),
+    AtomicUsize::new(0),
+    AtomicUsize::new(0),
+    AtomicUsize::new(0),
+    AtomicUsize::new(0),
+    AtomicUsize::new(0),
+    AtomicUsize::new(0),
+    AtomicUsize::new(0),
+    AtomicUsize::new(0),
+    AtomicUsize::new(0),
+    AtomicUsize::new(0),
+    AtomicUsize::new(0),
+    AtomicUsize::new(0),
+    AtomicUsize::new(0),
+    AtomicUsize::new(0),
+    AtomicUsize::new(0),
+    AtomicUsize::new(0),
+    AtomicUsize::new(0),
+    AtomicUsize::new(0),
+    AtomicUsize::new(0),
+    AtomicUsize::new(0),
+];
+
+static VERSIONS: AtomicUsize = AtomicUsize::new(0);
+
+#[derive(Clone, Eq)]
+struct DropCounter {
+    x: u32,
+    id: usize,
+    version: Cell<usize>,
+}
+
+impl PartialEq for DropCounter {
+    fn eq(&self, other: &Self) -> bool {
+        self.partial_cmp(other) == Some(Ordering::Equal)
+    }
+}
+
+impl PartialOrd for DropCounter {
+    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+        self.version.set(self.version.get() + 1);
+        other.version.set(other.version.get() + 1);
+        VERSIONS.fetch_add(2, Relaxed);
+        self.x.partial_cmp(&other.x)
+    }
+}
+
+impl Ord for DropCounter {
+    fn cmp(&self, other: &Self) -> Ordering {
+        self.partial_cmp(other).unwrap()
+    }
+}
+
+impl Drop for DropCounter {
+    fn drop(&mut self) {
+        DROP_COUNTS[self.id].fetch_add(1, Relaxed);
+        VERSIONS.fetch_sub(self.version.get(), Relaxed);
+    }
+}
+
+std::thread_local!(static SILENCE_PANIC: Cell<bool> = Cell::new(false));
+
+#[test]
+#[cfg_attr(target_os = "emscripten", ignore)] // no threads
+fn panic_safe() {
+    panic::update_hook(move |prev, info| {
+        if !SILENCE_PANIC.with(|s| s.get()) {
+            prev(info);
+        }
+    });
+
+    let mut rng = test_rng();
+
+    // Miri is too slow (but still need to `chain` to make the types match)
+    let lens = if cfg!(miri) { (1..10).chain(0..0) } else { (1..20).chain(70..MAX_LEN) };
+    let moduli: &[u32] = if cfg!(miri) { &[5] } else { &[5, 20, 50] };
+
+    for len in lens {
+        for &modulus in moduli {
+            for &has_runs in &[false, true] {
+                let mut input = (0..len)
+                    .map(|id| DropCounter {
+                        x: rng.next_u32() % modulus,
+                        id: id,
+                        version: Cell::new(0),
+                    })
+                    .collect::<Vec<_>>();
+
+                if has_runs {
+                    for c in &mut input {
+                        c.x = c.id as u32;
+                    }
+
+                    for _ in 0..5 {
+                        let a = rng.gen::<usize>() % len;
+                        let b = rng.gen::<usize>() % len;
+                        if a < b {
+                            input[a..b].reverse();
+                        } else {
+                            input.swap(a, b);
+                        }
+                    }
+                }
+
+                do_test!(input, sort_by);
+                do_test!(input, sort_unstable_by);
+            }
+        }
+    }
+
+    // Set default panic hook again.
+    drop(panic::take_hook());
+}
+
+#[test]
+#[cfg_attr(miri, ignore)] // Miri is too slow
+fn test_sort() {
+    let mut rng = test_rng();
+
+    for len in (2..25).chain(500..510) {
+        for &modulus in &[5, 10, 100, 1000] {
+            for _ in 0..10 {
+                let orig: Vec<_> = (&mut rng)
+                    .sample_iter::<i32, _>(&Standard)
+                    .map(|x| x % modulus)
+                    .take(len)
+                    .collect();
+
+                // Sort in default order.
+                let mut v = orig.clone();
+                v.sort();
+                assert!(v.windows(2).all(|w| w[0] <= w[1]));
+
+                // Sort in ascending order.
+                let mut v = orig.clone();
+                v.sort_by(|a, b| a.cmp(b));
+                assert!(v.windows(2).all(|w| w[0] <= w[1]));
+
+                // Sort in descending order.
+                let mut v = orig.clone();
+                v.sort_by(|a, b| b.cmp(a));
+                assert!(v.windows(2).all(|w| w[0] >= w[1]));
+
+                // Sort in lexicographic order.
+                let mut v1 = orig.clone();
+                let mut v2 = orig.clone();
+                v1.sort_by_key(|x| x.to_string());
+                v2.sort_by_cached_key(|x| x.to_string());
+                assert!(v1.windows(2).all(|w| w[0].to_string() <= w[1].to_string()));
+                assert!(v1 == v2);
+
+                // Sort with many pre-sorted runs.
+                let mut v = orig.clone();
+                v.sort();
+                v.reverse();
+                for _ in 0..5 {
+                    let a = rng.gen::<usize>() % len;
+                    let b = rng.gen::<usize>() % len;
+                    if a < b {
+                        v[a..b].reverse();
+                    } else {
+                        v.swap(a, b);
+                    }
+                }
+                v.sort();
+                assert!(v.windows(2).all(|w| w[0] <= w[1]));
+            }
+        }
+    }
+
+    // Sort using a completely random comparison function.
+    // This will reorder the elements *somehow*, but won't panic.
+    let mut v = [0; 500];
+    for i in 0..v.len() {
+        v[i] = i as i32;
+    }
+    v.sort_by(|_, _| *[Less, Equal, Greater].choose(&mut rng).unwrap());
+    v.sort();
+    for i in 0..v.len() {
+        assert_eq!(v[i], i as i32);
+    }
+
+    // Should not panic.
+    [0i32; 0].sort();
+    [(); 10].sort();
+    [(); 100].sort();
+
+    let mut v = [0xDEADBEEFu64];
+    v.sort();
+    assert!(v == [0xDEADBEEF]);
+}
+
+#[test]
+fn test_sort_stability() {
+    // Miri is too slow
+    let large_range = if cfg!(miri) { 0..0 } else { 500..510 };
+    let rounds = if cfg!(miri) { 1 } else { 10 };
+
+    let mut rng = test_rng();
+    for len in (2..25).chain(large_range) {
+        for _ in 0..rounds {
+            let mut counts = [0; 10];
+
+            // create a vector like [(6, 1), (5, 1), (6, 2), ...],
+            // where the first item of each tuple is random, but
+            // the second item represents which occurrence of that
+            // number this element is, i.e., the second elements
+            // will occur in sorted order.
+            let orig: Vec<_> = (0..len)
+                .map(|_| {
+                    let n = rng.gen::<usize>() % 10;
+                    counts[n] += 1;
+                    (n, counts[n])
+                })
+                .collect();
+
+            let mut v = orig.clone();
+            // Only sort on the first element, so an unstable sort
+            // may mix up the counts.
+            v.sort_by(|&(a, _), &(b, _)| a.cmp(&b));
+
+            // This comparison includes the count (the second item
+            // of the tuple), so elements with equal first items
+            // will need to be ordered with increasing
+            // counts... i.e., exactly asserting that this sort is
+            // stable.
+            assert!(v.windows(2).all(|w| w[0] <= w[1]));
+
+            let mut v = orig.clone();
+            v.sort_by_cached_key(|&(x, _)| x);
+            assert!(v.windows(2).all(|w| w[0] <= w[1]));
+        }
+    }
+}
diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs
index ddcd863aa3e..d833d4d1dfb 100644
--- a/library/alloc/src/sync.rs
+++ b/library/alloc/src/sync.rs
@@ -312,7 +312,7 @@ impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Weak<U>> for Weak<T> {}
 impl<T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<Weak<U>> for Weak<T> {}
 
 #[stable(feature = "arc_weak", since = "1.4.0")]
-impl<T: ?Sized + fmt::Debug> fmt::Debug for Weak<T> {
+impl<T: ?Sized> fmt::Debug for Weak<T> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         write!(f, "(Weak)")
     }
diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs
index 1da73862d4a..36cfac8ee9e 100644
--- a/library/alloc/src/vec/mod.rs
+++ b/library/alloc/src/vec/mod.rs
@@ -490,6 +490,8 @@ impl<T> Vec<T> {
     /// This is highly unsafe, due to the number of invariants that aren't
     /// checked:
     ///
+    /// * `ptr` must have been allocated using the global allocator, such as via
+    ///   the [`alloc::alloc`] function.
     /// * `T` needs to have the same alignment as what `ptr` was allocated with.
     ///   (`T` having a less strict alignment is not sufficient, the alignment really
     ///   needs to be equal to satisfy the [`dealloc`] requirement that memory must be
@@ -526,6 +528,7 @@ impl<T> Vec<T> {
     /// function.
     ///
     /// [`String`]: crate::string::String
+    /// [`alloc::alloc`]: crate::alloc::alloc
     /// [`dealloc`]: crate::alloc::GlobalAlloc::dealloc
     ///
     /// # Examples
@@ -681,6 +684,7 @@ impl<T, A: Allocator> Vec<T, A> {
     /// This is highly unsafe, due to the number of invariants that aren't
     /// checked:
     ///
+    /// * `ptr` must be [*currently allocated*] via the given allocator `alloc`.
     /// * `T` needs to have the same alignment as what `ptr` was allocated with.
     ///   (`T` having a less strict alignment is not sufficient, the alignment really
     ///   needs to be equal to satisfy the [`dealloc`] requirement that memory must be
@@ -714,6 +718,7 @@ impl<T, A: Allocator> Vec<T, A> {
     ///
     /// [`String`]: crate::string::String
     /// [`dealloc`]: crate::alloc::GlobalAlloc::dealloc
+    /// [*currently allocated*]: crate::alloc::Allocator#currently-allocated-memory
     /// [*fit*]: crate::alloc::Allocator#memory-fitting
     ///
     /// # Examples
diff --git a/library/alloc/tests/slice.rs b/library/alloc/tests/slice.rs
index 21f894343be..0693beb48c4 100644
--- a/library/alloc/tests/slice.rs
+++ b/library/alloc/tests/slice.rs
@@ -1,15 +1,9 @@
-use std::cell::Cell;
-use std::cmp::Ordering::{self, Equal, Greater, Less};
+use std::cmp::Ordering::{Equal, Greater, Less};
 use std::convert::identity;
 use std::fmt;
 use std::mem;
 use std::panic;
 use std::rc::Rc;
-use std::sync::atomic::{AtomicUsize, Ordering::Relaxed};
-
-use rand::distributions::Standard;
-use rand::seq::SliceRandom;
-use rand::{thread_rng, Rng, RngCore};
 
 fn square(n: usize) -> usize {
     n * n
@@ -389,123 +383,6 @@ fn test_reverse() {
 }
 
 #[test]
-#[cfg_attr(miri, ignore)] // Miri is too slow
-fn test_sort() {
-    let mut rng = thread_rng();
-
-    for len in (2..25).chain(500..510) {
-        for &modulus in &[5, 10, 100, 1000] {
-            for _ in 0..10 {
-                let orig: Vec<_> =
-                    rng.sample_iter::<i32, _>(&Standard).map(|x| x % modulus).take(len).collect();
-
-                // Sort in default order.
-                let mut v = orig.clone();
-                v.sort();
-                assert!(v.windows(2).all(|w| w[0] <= w[1]));
-
-                // Sort in ascending order.
-                let mut v = orig.clone();
-                v.sort_by(|a, b| a.cmp(b));
-                assert!(v.windows(2).all(|w| w[0] <= w[1]));
-
-                // Sort in descending order.
-                let mut v = orig.clone();
-                v.sort_by(|a, b| b.cmp(a));
-                assert!(v.windows(2).all(|w| w[0] >= w[1]));
-
-                // Sort in lexicographic order.
-                let mut v1 = orig.clone();
-                let mut v2 = orig.clone();
-                v1.sort_by_key(|x| x.to_string());
-                v2.sort_by_cached_key(|x| x.to_string());
-                assert!(v1.windows(2).all(|w| w[0].to_string() <= w[1].to_string()));
-                assert!(v1 == v2);
-
-                // Sort with many pre-sorted runs.
-                let mut v = orig.clone();
-                v.sort();
-                v.reverse();
-                for _ in 0..5 {
-                    let a = rng.gen::<usize>() % len;
-                    let b = rng.gen::<usize>() % len;
-                    if a < b {
-                        v[a..b].reverse();
-                    } else {
-                        v.swap(a, b);
-                    }
-                }
-                v.sort();
-                assert!(v.windows(2).all(|w| w[0] <= w[1]));
-            }
-        }
-    }
-
-    // Sort using a completely random comparison function.
-    // This will reorder the elements *somehow*, but won't panic.
-    let mut v = [0; 500];
-    for i in 0..v.len() {
-        v[i] = i as i32;
-    }
-    v.sort_by(|_, _| *[Less, Equal, Greater].choose(&mut rng).unwrap());
-    v.sort();
-    for i in 0..v.len() {
-        assert_eq!(v[i], i as i32);
-    }
-
-    // Should not panic.
-    [0i32; 0].sort();
-    [(); 10].sort();
-    [(); 100].sort();
-
-    let mut v = [0xDEADBEEFu64];
-    v.sort();
-    assert!(v == [0xDEADBEEF]);
-}
-
-#[test]
-fn test_sort_stability() {
-    // Miri is too slow
-    let large_range = if cfg!(miri) { 0..0 } else { 500..510 };
-    let rounds = if cfg!(miri) { 1 } else { 10 };
-
-    for len in (2..25).chain(large_range) {
-        for _ in 0..rounds {
-            let mut counts = [0; 10];
-
-            // create a vector like [(6, 1), (5, 1), (6, 2), ...],
-            // where the first item of each tuple is random, but
-            // the second item represents which occurrence of that
-            // number this element is, i.e., the second elements
-            // will occur in sorted order.
-            let orig: Vec<_> = (0..len)
-                .map(|_| {
-                    let n = thread_rng().gen::<usize>() % 10;
-                    counts[n] += 1;
-                    (n, counts[n])
-                })
-                .collect();
-
-            let mut v = orig.clone();
-            // Only sort on the first element, so an unstable sort
-            // may mix up the counts.
-            v.sort_by(|&(a, _), &(b, _)| a.cmp(&b));
-
-            // This comparison includes the count (the second item
-            // of the tuple), so elements with equal first items
-            // will need to be ordered with increasing
-            // counts... i.e., exactly asserting that this sort is
-            // stable.
-            assert!(v.windows(2).all(|w| w[0] <= w[1]));
-
-            let mut v = orig.clone();
-            v.sort_by_cached_key(|&(x, _)| x);
-            assert!(v.windows(2).all(|w| w[0] <= w[1]));
-        }
-    }
-}
-
-#[test]
 fn test_rotate_left() {
     let expected: Vec<_> = (0..13).collect();
     let mut v = Vec::new();
@@ -1608,230 +1485,6 @@ fn test_copy_from_slice_dst_shorter() {
     dst.copy_from_slice(&src);
 }
 
-const MAX_LEN: usize = 80;
-
-static DROP_COUNTS: [AtomicUsize; MAX_LEN] = [
-    // FIXME(RFC 1109): AtomicUsize is not Copy.
-    AtomicUsize::new(0),
-    AtomicUsize::new(0),
-    AtomicUsize::new(0),
-    AtomicUsize::new(0),
-    AtomicUsize::new(0),
-    AtomicUsize::new(0),
-    AtomicUsize::new(0),
-    AtomicUsize::new(0),
-    AtomicUsize::new(0),
-    AtomicUsize::new(0),
-    AtomicUsize::new(0),
-    AtomicUsize::new(0),
-    AtomicUsize::new(0),
-    AtomicUsize::new(0),
-    AtomicUsize::new(0),
-    AtomicUsize::new(0),
-    AtomicUsize::new(0),
-    AtomicUsize::new(0),
-    AtomicUsize::new(0),
-    AtomicUsize::new(0),
-    AtomicUsize::new(0),
-    AtomicUsize::new(0),
-    AtomicUsize::new(0),
-    AtomicUsize::new(0),
-    AtomicUsize::new(0),
-    AtomicUsize::new(0),
-    AtomicUsize::new(0),
-    AtomicUsize::new(0),
-    AtomicUsize::new(0),
-    AtomicUsize::new(0),
-    AtomicUsize::new(0),
-    AtomicUsize::new(0),
-    AtomicUsize::new(0),
-    AtomicUsize::new(0),
-    AtomicUsize::new(0),
-    AtomicUsize::new(0),
-    AtomicUsize::new(0),
-    AtomicUsize::new(0),
-    AtomicUsize::new(0),
-    AtomicUsize::new(0),
-    AtomicUsize::new(0),
-    AtomicUsize::new(0),
-    AtomicUsize::new(0),
-    AtomicUsize::new(0),
-    AtomicUsize::new(0),
-    AtomicUsize::new(0),
-    AtomicUsize::new(0),
-    AtomicUsize::new(0),
-    AtomicUsize::new(0),
-    AtomicUsize::new(0),
-    AtomicUsize::new(0),
-    AtomicUsize::new(0),
-    AtomicUsize::new(0),
-    AtomicUsize::new(0),
-    AtomicUsize::new(0),
-    AtomicUsize::new(0),
-    AtomicUsize::new(0),
-    AtomicUsize::new(0),
-    AtomicUsize::new(0),
-    AtomicUsize::new(0),
-    AtomicUsize::new(0),
-    AtomicUsize::new(0),
-    AtomicUsize::new(0),
-    AtomicUsize::new(0),
-    AtomicUsize::new(0),
-    AtomicUsize::new(0),
-    AtomicUsize::new(0),
-    AtomicUsize::new(0),
-    AtomicUsize::new(0),
-    AtomicUsize::new(0),
-    AtomicUsize::new(0),
-    AtomicUsize::new(0),
-    AtomicUsize::new(0),
-    AtomicUsize::new(0),
-    AtomicUsize::new(0),
-    AtomicUsize::new(0),
-    AtomicUsize::new(0),
-    AtomicUsize::new(0),
-    AtomicUsize::new(0),
-    AtomicUsize::new(0),
-];
-
-static VERSIONS: AtomicUsize = AtomicUsize::new(0);
-
-#[derive(Clone, Eq)]
-struct DropCounter {
-    x: u32,
-    id: usize,
-    version: Cell<usize>,
-}
-
-impl PartialEq for DropCounter {
-    fn eq(&self, other: &Self) -> bool {
-        self.partial_cmp(other) == Some(Ordering::Equal)
-    }
-}
-
-impl PartialOrd for DropCounter {
-    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
-        self.version.set(self.version.get() + 1);
-        other.version.set(other.version.get() + 1);
-        VERSIONS.fetch_add(2, Relaxed);
-        self.x.partial_cmp(&other.x)
-    }
-}
-
-impl Ord for DropCounter {
-    fn cmp(&self, other: &Self) -> Ordering {
-        self.partial_cmp(other).unwrap()
-    }
-}
-
-impl Drop for DropCounter {
-    fn drop(&mut self) {
-        DROP_COUNTS[self.id].fetch_add(1, Relaxed);
-        VERSIONS.fetch_sub(self.version.get(), Relaxed);
-    }
-}
-
-macro_rules! test {
-    ($input:ident, $func:ident) => {
-        let len = $input.len();
-
-        // Work out the total number of comparisons required to sort
-        // this array...
-        let mut count = 0usize;
-        $input.to_owned().$func(|a, b| {
-            count += 1;
-            a.cmp(b)
-        });
-
-        // ... and then panic on each and every single one.
-        for panic_countdown in 0..count {
-            // Refresh the counters.
-            VERSIONS.store(0, Relaxed);
-            for i in 0..len {
-                DROP_COUNTS[i].store(0, Relaxed);
-            }
-
-            let v = $input.to_owned();
-            let _ = std::panic::catch_unwind(move || {
-                let mut v = v;
-                let mut panic_countdown = panic_countdown;
-                v.$func(|a, b| {
-                    if panic_countdown == 0 {
-                        SILENCE_PANIC.with(|s| s.set(true));
-                        panic!();
-                    }
-                    panic_countdown -= 1;
-                    a.cmp(b)
-                })
-            });
-
-            // Check that the number of things dropped is exactly
-            // what we expect (i.e., the contents of `v`).
-            for (i, c) in DROP_COUNTS.iter().enumerate().take(len) {
-                let count = c.load(Relaxed);
-                assert!(count == 1, "found drop count == {} for i == {}, len == {}", count, i, len);
-            }
-
-            // Check that the most recent versions of values were dropped.
-            assert_eq!(VERSIONS.load(Relaxed), 0);
-        }
-    };
-}
-
-thread_local!(static SILENCE_PANIC: Cell<bool> = Cell::new(false));
-
-#[test]
-#[cfg_attr(target_os = "emscripten", ignore)] // no threads
-fn panic_safe() {
-    panic::update_hook(move |prev, info| {
-        if !SILENCE_PANIC.with(|s| s.get()) {
-            prev(info);
-        }
-    });
-
-    let mut rng = thread_rng();
-
-    // Miri is too slow (but still need to `chain` to make the types match)
-    let lens = if cfg!(miri) { (1..10).chain(0..0) } else { (1..20).chain(70..MAX_LEN) };
-    let moduli: &[u32] = if cfg!(miri) { &[5] } else { &[5, 20, 50] };
-
-    for len in lens {
-        for &modulus in moduli {
-            for &has_runs in &[false, true] {
-                let mut input = (0..len)
-                    .map(|id| DropCounter {
-                        x: rng.next_u32() % modulus,
-                        id: id,
-                        version: Cell::new(0),
-                    })
-                    .collect::<Vec<_>>();
-
-                if has_runs {
-                    for c in &mut input {
-                        c.x = c.id as u32;
-                    }
-
-                    for _ in 0..5 {
-                        let a = rng.gen::<usize>() % len;
-                        let b = rng.gen::<usize>() % len;
-                        if a < b {
-                            input[a..b].reverse();
-                        } else {
-                            input.swap(a, b);
-                        }
-                    }
-                }
-
-                test!(input, sort_by);
-                test!(input, sort_unstable_by);
-            }
-        }
-    }
-
-    // Set default panic hook again.
-    drop(panic::take_hook());
-}
-
 #[test]
 fn repeat_generic_slice() {
     assert_eq!([1, 2].repeat(2), vec![1, 2, 1, 2]);
diff --git a/library/core/Cargo.toml b/library/core/Cargo.toml
index 2a7df9556cf..3dc8c84e0bf 100644
--- a/library/core/Cargo.toml
+++ b/library/core/Cargo.toml
@@ -24,8 +24,8 @@ path = "benches/lib.rs"
 test = true
 
 [dev-dependencies]
-rand = "0.7"
-rand_xorshift = "0.2"
+rand = { version = "0.8.5", default-features = false }
+rand_xorshift = { version = "0.3.0", default-features = false }
 
 [features]
 # Make panics and failed asserts immediately abort without formatting any message
diff --git a/library/core/benches/num/int_log/mod.rs b/library/core/benches/num/int_log/mod.rs
index 3c01e2998cd..bb61224b5ba 100644
--- a/library/core/benches/num/int_log/mod.rs
+++ b/library/core/benches/num/int_log/mod.rs
@@ -21,7 +21,7 @@ macro_rules! int_log_bench {
             /* Exponentially distributed random numbers from the whole range of the type.  */
             let numbers: Vec<$t> = (0..256)
                 .map(|_| {
-                    let x = rng.gen::<$t>() >> rng.gen_range(0, <$t>::BITS);
+                    let x = rng.gen::<$t>() >> rng.gen_range(0..<$t>::BITS);
                     if x != 0 { x } else { 1 }
                 })
                 .collect();
@@ -38,7 +38,7 @@ macro_rules! int_log_bench {
             /* Exponentially distributed random numbers from the range 0..256.  */
             let numbers: Vec<$t> = (0..256)
                 .map(|_| {
-                    let x = (rng.gen::<u8>() >> rng.gen_range(0, u8::BITS)) as $t;
+                    let x = (rng.gen::<u8>() >> rng.gen_range(0..u8::BITS)) as $t;
                     if x != 0 { x } else { 1 }
                 })
                 .collect();
diff --git a/library/core/src/future/future.rs b/library/core/src/future/future.rs
index f29d3e1e98b..8c7111cb3ff 100644
--- a/library/core/src/future/future.rs
+++ b/library/core/src/future/future.rs
@@ -37,6 +37,7 @@ use crate::task::{Context, Poll};
 pub trait Future {
     /// The type of value produced on completion.
     #[stable(feature = "futures_api", since = "1.36.0")]
+    #[rustc_diagnostic_item = "FutureOutput"]
     type Output;
 
     /// Attempt to resolve the future to a final value, registering
diff --git a/library/core/src/iter/sources/once_with.rs b/library/core/src/iter/sources/once_with.rs
index d79f85c2559..080ae27a30f 100644
--- a/library/core/src/iter/sources/once_with.rs
+++ b/library/core/src/iter/sources/once_with.rs
@@ -1,3 +1,4 @@
+use crate::fmt;
 use crate::iter::{FusedIterator, TrustedLen};
 
 /// Creates an iterator that lazily generates a value exactly once by invoking
@@ -66,12 +67,23 @@ pub fn once_with<A, F: FnOnce() -> A>(gen: F) -> OnceWith<F> {
 ///
 /// This `struct` is created by the [`once_with()`] function.
 /// See its documentation for more.
-#[derive(Clone, Debug)]
+#[derive(Clone)]
 #[stable(feature = "iter_once_with", since = "1.43.0")]
 pub struct OnceWith<F> {
     gen: Option<F>,
 }
 
+#[stable(feature = "iter_once_with_debug", since = "CURRENT_RUSTC_VERSION")]
+impl<F> fmt::Debug for OnceWith<F> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        if self.gen.is_some() {
+            f.write_str("OnceWith(Some(_))")
+        } else {
+            f.write_str("OnceWith(None)")
+        }
+    }
+}
+
 #[stable(feature = "iter_once_with", since = "1.43.0")]
 impl<A, F: FnOnce() -> A> Iterator for OnceWith<F> {
     type Item = A;
diff --git a/library/core/src/iter/sources/repeat_n.rs b/library/core/src/iter/sources/repeat_n.rs
index fd8d25ce1a5..dc61d6065b8 100644
--- a/library/core/src/iter/sources/repeat_n.rs
+++ b/library/core/src/iter/sources/repeat_n.rs
@@ -126,7 +126,7 @@ impl<A: Clone> Iterator for RepeatN<A> {
             // zero so it won't be dropped later, and thus it's okay to take it here.
             unsafe { ManuallyDrop::take(&mut self.element) }
         } else {
-            A::clone(&mut self.element)
+            A::clone(&self.element)
         })
     }
 
diff --git a/library/core/src/iter/sources/repeat_with.rs b/library/core/src/iter/sources/repeat_with.rs
index ab2d0472b47..20420a3ad8e 100644
--- a/library/core/src/iter/sources/repeat_with.rs
+++ b/library/core/src/iter/sources/repeat_with.rs
@@ -1,3 +1,4 @@
+use crate::fmt;
 use crate::iter::{FusedIterator, TrustedLen};
 use crate::ops::Try;
 
@@ -71,12 +72,19 @@ pub fn repeat_with<A, F: FnMut() -> A>(repeater: F) -> RepeatWith<F> {
 ///
 /// This `struct` is created by the [`repeat_with()`] function.
 /// See its documentation for more.
-#[derive(Copy, Clone, Debug)]
+#[derive(Copy, Clone)]
 #[stable(feature = "iterator_repeat_with", since = "1.28.0")]
 pub struct RepeatWith<F> {
     repeater: F,
 }
 
+#[stable(feature = "iterator_repeat_with_debug", since = "CURRENT_RUSTC_VERSION")]
+impl<F> fmt::Debug for RepeatWith<F> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.debug_struct("RepeatWith").finish_non_exhaustive()
+    }
+}
+
 #[stable(feature = "iterator_repeat_with", since = "1.28.0")]
 impl<A, F: FnMut() -> A> Iterator for RepeatWith<F> {
     type Item = A;
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index 0e3fef4ead3..9e0d7cab63e 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -158,6 +158,7 @@
 #![feature(const_unsafecell_get_mut)]
 #![feature(const_waker)]
 #![feature(core_panic)]
+#![feature(char_indices_offset)]
 #![feature(duration_consts_float)]
 #![feature(maybe_uninit_uninit_array)]
 #![feature(ptr_alignment_type)]
@@ -166,6 +167,8 @@
 #![feature(slice_ptr_get)]
 #![feature(slice_split_at_unchecked)]
 #![feature(str_internals)]
+#![feature(str_split_remainder)]
+#![feature(str_split_inclusive_remainder)]
 #![feature(strict_provenance)]
 #![feature(utf16_extra)]
 #![feature(utf16_extra_const)]
diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs
index cfc1cabe229..3b026bc0e0f 100644
--- a/library/core/src/macros/mod.rs
+++ b/library/core/src/macros/mod.rs
@@ -1315,22 +1315,41 @@ pub(crate) mod builtin {
 
     /// Parses a file as an expression or an item according to the context.
     ///
-    /// The file is located relative to the current file (similarly to how
-    /// modules are found). The provided path is interpreted in a platform-specific
-    /// way at compile time. So, for instance, an invocation with a Windows path
-    /// containing backslashes `\` would not compile correctly on Unix.
+    /// **Warning**: For multi-file Rust projects, the `include!` macro is probably not what you
+    /// are looking for. Usually, multi-file Rust projects use
+    /// [modules](https://doc.rust-lang.org/reference/items/modules.html). Multi-file projects and
+    /// modules are explained in the Rust-by-Example book
+    /// [here](https://doc.rust-lang.org/rust-by-example/mod/split.html) and the module system is
+    /// explained in the Rust Book
+    /// [here](https://doc.rust-lang.org/book/ch07-02-defining-modules-to-control-scope-and-privacy.html).
+    ///
+    /// The included file is placed in the surrounding code
+    /// [unhygienically](https://doc.rust-lang.org/reference/macros-by-example.html#hygiene). If
+    /// the included file is parsed as an expression and variables or functions share names across
+    /// both files, it could result in variables or functions being different from what the
+    /// included file expected.
+    ///
+    /// The included file is located relative to the current file (similarly to how modules are
+    /// found). The provided path is interpreted in a platform-specific way at compile time. So,
+    /// for instance, an invocation with a Windows path containing backslashes `\` would not
+    /// compile correctly on Unix.
     ///
-    /// Using this macro is often a bad idea, because if the file is
-    /// parsed as an expression, it is going to be placed in the
-    /// surrounding code unhygienically. This could result in variables
-    /// or functions being different from what the file expected if
-    /// there are variables or functions that have the same name in
-    /// the current file.
+    /// # Uses
+    ///
+    /// The `include!` macro is primarily used for two purposes. It is used to include
+    /// documentation that is written in a separate file and it is used to include [build artifacts
+    /// usually as a result from the `build.rs`
+    /// script](https://doc.rust-lang.org/cargo/reference/build-scripts.html#outputs-of-the-build-script).
+    ///
+    /// When using the `include` macro to include stretches of documentation, remember that the
+    /// included file still needs to be a valid rust syntax. It is also possible to
+    /// use the [`include_str`] macro as `#![doc = include_str!("...")]` (at the module level) or
+    /// `#[doc = include_str!("...")]` (at the item level) to include documentation from a plain
+    /// text or markdown file.
     ///
     /// # Examples
     ///
-    /// Assume there are two files in the same directory with the following
-    /// contents:
+    /// Assume there are two files in the same directory with the following contents:
     ///
     /// File 'monkeys.in':
     ///
diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs
index c0fb954ce2d..1326fc9ab09 100644
--- a/library/core/src/marker.rs
+++ b/library/core/src/marker.rs
@@ -623,6 +623,12 @@ impl<T: ?Sized> !Sync for *mut T {}
 /// (ideally) or `PhantomData<*const T>` (if no lifetime applies), so
 /// as not to indicate ownership.
 ///
+/// ## Layout
+///
+/// For all `T`, the following are guaranteed:
+/// * `size_of::<PhantomData<T>>() == 0`
+/// * `align_of::<PhantomData<T>>() == 1`
+///
 /// [drop check]: ../../nomicon/dropck.html
 #[lang = "phantom_data"]
 #[stable(feature = "rust1", since = "1.0.0")]
diff --git a/library/core/src/panicking.rs b/library/core/src/panicking.rs
index 0146a3c2fbf..48e90e6d794 100644
--- a/library/core/src/panicking.rs
+++ b/library/core/src/panicking.rs
@@ -64,13 +64,17 @@ pub const fn panic_fmt(fmt: fmt::Arguments<'_>) -> ! {
     unsafe { panic_impl(&pi) }
 }
 
-/// Like `panic`, but without unwinding and track_caller to reduce the impact on codesize.
-/// (No `fmt` variant as a `fmt::Arguments` needs more space to be passed.)
+/// Like `panic_fmt`, but for non-unwinding panics.
+///
+/// Has to be a separate function so that it can carry the `rustc_nounwind` attribute.
 #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)]
 #[cfg_attr(feature = "panic_immediate_abort", inline)]
-#[cfg_attr(not(bootstrap), lang = "panic_nounwind")] // needed by codegen for non-unwinding panics
+#[track_caller]
+// This attribute has the key side-effect that if the panic handler ignores `can_unwind`
+// and unwinds anyway, we will hit the "unwinding out of nounwind function" guard,
+// which causes a "panic in a function that cannot unwind".
 #[rustc_nounwind]
-pub fn panic_nounwind(msg: &'static str) -> ! {
+pub fn panic_nounwind_fmt(fmt: fmt::Arguments<'_>) -> ! {
     if cfg!(feature = "panic_immediate_abort") {
         super::intrinsics::abort()
     }
@@ -83,8 +87,6 @@ pub fn panic_nounwind(msg: &'static str) -> ! {
     }
 
     // PanicInfo with the `can_unwind` flag set to false forces an abort.
-    let pieces = [msg];
-    let fmt = fmt::Arguments::new_v1(&pieces, &[]);
     let pi = PanicInfo::internal_constructor(Some(&fmt), Location::caller(), false);
 
     // SAFETY: `panic_impl` is defined in safe Rust code and thus is safe to call.
@@ -112,6 +114,15 @@ pub const fn panic(expr: &'static str) -> ! {
     panic_fmt(fmt::Arguments::new_v1(&[expr], &[]));
 }
 
+/// Like `panic`, but without unwinding and track_caller to reduce the impact on codesize.
+#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)]
+#[cfg_attr(feature = "panic_immediate_abort", inline)]
+#[cfg_attr(not(bootstrap), lang = "panic_nounwind")] // needed by codegen for non-unwinding panics
+#[rustc_nounwind]
+pub fn panic_nounwind(expr: &'static str) -> ! {
+    panic_nounwind_fmt(fmt::Arguments::new_v1(&[expr], &[]));
+}
+
 #[inline]
 #[track_caller]
 #[rustc_diagnostic_item = "panic_str"]
diff --git a/library/core/src/str/iter.rs b/library/core/src/str/iter.rs
index 24083ee6af4..d969475aa48 100644
--- a/library/core/src/str/iter.rs
+++ b/library/core/src/str/iter.rs
@@ -585,16 +585,17 @@ where
 impl<'a, P: Pattern<'a>> SplitInternal<'a, P> {
     #[inline]
     fn get_end(&mut self) -> Option<&'a str> {
-        if !self.finished && (self.allow_trailing_empty || self.end - self.start > 0) {
+        if !self.finished {
             self.finished = true;
-            // SAFETY: `self.start` and `self.end` always lie on unicode boundaries.
-            unsafe {
-                let string = self.matcher.haystack().get_unchecked(self.start..self.end);
-                Some(string)
+
+            if self.allow_trailing_empty || self.end - self.start > 0 {
+                // SAFETY: `self.start` and `self.end` always lie on unicode boundaries.
+                let string = unsafe { self.matcher.haystack().get_unchecked(self.start..self.end) };
+                return Some(string);
             }
-        } else {
-            None
         }
+
+        None
     }
 
     #[inline]
@@ -716,14 +717,14 @@ impl<'a, P: Pattern<'a>> SplitInternal<'a, P> {
     }
 
     #[inline]
-    fn as_str(&self) -> &'a str {
+    fn remainder(&self) -> Option<&'a str> {
         // `Self::get_end` doesn't change `self.start`
         if self.finished {
-            return "";
+            return None;
         }
 
         // SAFETY: `self.start` and `self.end` always lie on unicode boundaries.
-        unsafe { self.matcher.haystack().get_unchecked(self.start..self.end) }
+        Some(unsafe { self.matcher.haystack().get_unchecked(self.start..self.end) })
     }
 }
 
@@ -746,44 +747,48 @@ generate_pattern_iterators! {
 }
 
 impl<'a, P: Pattern<'a>> Split<'a, P> {
-    /// Returns remainder of the split string
+    /// Returns remainder of the split string.
+    ///
+    /// If the iterator is empty, returns `None`.
     ///
     /// # Examples
     ///
     /// ```
-    /// #![feature(str_split_as_str)]
+    /// #![feature(str_split_remainder)]
     /// let mut split = "Mary had a little lamb".split(' ');
-    /// assert_eq!(split.as_str(), "Mary had a little lamb");
+    /// assert_eq!(split.remainder(), Some("Mary had a little lamb"));
     /// split.next();
-    /// assert_eq!(split.as_str(), "had a little lamb");
+    /// assert_eq!(split.remainder(), Some("had a little lamb"));
     /// split.by_ref().for_each(drop);
-    /// assert_eq!(split.as_str(), "");
+    /// assert_eq!(split.remainder(), None);
     /// ```
     #[inline]
-    #[unstable(feature = "str_split_as_str", issue = "77998")]
-    pub fn as_str(&self) -> &'a str {
-        self.0.as_str()
+    #[unstable(feature = "str_split_remainder", issue = "77998")]
+    pub fn remainder(&self) -> Option<&'a str> {
+        self.0.remainder()
     }
 }
 
 impl<'a, P: Pattern<'a>> RSplit<'a, P> {
-    /// Returns remainder of the split string
+    /// Returns remainder of the split string.
+    ///
+    /// If the iterator is empty, returns `None`.
     ///
     /// # Examples
     ///
     /// ```
-    /// #![feature(str_split_as_str)]
+    /// #![feature(str_split_remainder)]
     /// let mut split = "Mary had a little lamb".rsplit(' ');
-    /// assert_eq!(split.as_str(), "Mary had a little lamb");
+    /// assert_eq!(split.remainder(), Some("Mary had a little lamb"));
     /// split.next();
-    /// assert_eq!(split.as_str(), "Mary had a little");
+    /// assert_eq!(split.remainder(), Some("Mary had a little"));
     /// split.by_ref().for_each(drop);
-    /// assert_eq!(split.as_str(), "");
+    /// assert_eq!(split.remainder(), None);
     /// ```
     #[inline]
-    #[unstable(feature = "str_split_as_str", issue = "77998")]
-    pub fn as_str(&self) -> &'a str {
-        self.0.as_str()
+    #[unstable(feature = "str_split_remainder", issue = "77998")]
+    pub fn remainder(&self) -> Option<&'a str> {
+        self.0.remainder()
     }
 }
 
@@ -806,44 +811,48 @@ generate_pattern_iterators! {
 }
 
 impl<'a, P: Pattern<'a>> SplitTerminator<'a, P> {
-    /// Returns remainder of the split string
+    /// Returns remainder of the split string.
+    ///
+    /// If the iterator is empty, returns `None`.
     ///
     /// # Examples
     ///
     /// ```
-    /// #![feature(str_split_as_str)]
+    /// #![feature(str_split_remainder)]
     /// let mut split = "A..B..".split_terminator('.');
-    /// assert_eq!(split.as_str(), "A..B..");
+    /// assert_eq!(split.remainder(), Some("A..B.."));
     /// split.next();
-    /// assert_eq!(split.as_str(), ".B..");
+    /// assert_eq!(split.remainder(), Some(".B.."));
     /// split.by_ref().for_each(drop);
-    /// assert_eq!(split.as_str(), "");
+    /// assert_eq!(split.remainder(), None);
     /// ```
     #[inline]
-    #[unstable(feature = "str_split_as_str", issue = "77998")]
-    pub fn as_str(&self) -> &'a str {
-        self.0.as_str()
+    #[unstable(feature = "str_split_remainder", issue = "77998")]
+    pub fn remainder(&self) -> Option<&'a str> {
+        self.0.remainder()
     }
 }
 
 impl<'a, P: Pattern<'a>> RSplitTerminator<'a, P> {
-    /// Returns remainder of the split string
+    /// Returns remainder of the split string.
+    ///
+    /// If the iterator is empty, returns `None`.
     ///
     /// # Examples
     ///
     /// ```
-    /// #![feature(str_split_as_str)]
+    /// #![feature(str_split_remainder)]
     /// let mut split = "A..B..".rsplit_terminator('.');
-    /// assert_eq!(split.as_str(), "A..B..");
+    /// assert_eq!(split.remainder(), Some("A..B.."));
     /// split.next();
-    /// assert_eq!(split.as_str(), "A..B");
+    /// assert_eq!(split.remainder(), Some("A..B"));
     /// split.by_ref().for_each(drop);
-    /// assert_eq!(split.as_str(), "");
+    /// assert_eq!(split.remainder(), None);
     /// ```
     #[inline]
-    #[unstable(feature = "str_split_as_str", issue = "77998")]
-    pub fn as_str(&self) -> &'a str {
-        self.0.as_str()
+    #[unstable(feature = "str_split_remainder", issue = "77998")]
+    pub fn remainder(&self) -> Option<&'a str> {
+        self.0.remainder()
     }
 }
 
@@ -905,8 +914,8 @@ impl<'a, P: Pattern<'a>> SplitNInternal<'a, P> {
     }
 
     #[inline]
-    fn as_str(&self) -> &'a str {
-        self.iter.as_str()
+    fn remainder(&self) -> Option<&'a str> {
+        self.iter.remainder()
     }
 }
 
@@ -929,44 +938,48 @@ generate_pattern_iterators! {
 }
 
 impl<'a, P: Pattern<'a>> SplitN<'a, P> {
-    /// Returns remainder of the split string
+    /// Returns remainder of the split string.
+    ///
+    /// If the iterator is empty, returns `None`.
     ///
     /// # Examples
     ///
     /// ```
-    /// #![feature(str_split_as_str)]
+    /// #![feature(str_split_remainder)]
     /// let mut split = "Mary had a little lamb".splitn(3, ' ');
-    /// assert_eq!(split.as_str(), "Mary had a little lamb");
+    /// assert_eq!(split.remainder(), Some("Mary had a little lamb"));
     /// split.next();
-    /// assert_eq!(split.as_str(), "had a little lamb");
+    /// assert_eq!(split.remainder(), Some("had a little lamb"));
     /// split.by_ref().for_each(drop);
-    /// assert_eq!(split.as_str(), "");
+    /// assert_eq!(split.remainder(), None);
     /// ```
     #[inline]
-    #[unstable(feature = "str_split_as_str", issue = "77998")]
-    pub fn as_str(&self) -> &'a str {
-        self.0.as_str()
+    #[unstable(feature = "str_split_remainder", issue = "77998")]
+    pub fn remainder(&self) -> Option<&'a str> {
+        self.0.remainder()
     }
 }
 
 impl<'a, P: Pattern<'a>> RSplitN<'a, P> {
-    /// Returns remainder of the split string
+    /// Returns remainder of the split string.
+    ///
+    /// If the iterator is empty, returns `None`.
     ///
     /// # Examples
     ///
     /// ```
-    /// #![feature(str_split_as_str)]
+    /// #![feature(str_split_remainder)]
     /// let mut split = "Mary had a little lamb".rsplitn(3, ' ');
-    /// assert_eq!(split.as_str(), "Mary had a little lamb");
+    /// assert_eq!(split.remainder(), Some("Mary had a little lamb"));
     /// split.next();
-    /// assert_eq!(split.as_str(), "Mary had a little");
+    /// assert_eq!(split.remainder(), Some("Mary had a little"));
     /// split.by_ref().for_each(drop);
-    /// assert_eq!(split.as_str(), "");
+    /// assert_eq!(split.remainder(), None);
     /// ```
     #[inline]
-    #[unstable(feature = "str_split_as_str", issue = "77998")]
-    pub fn as_str(&self) -> &'a str {
-        self.0.as_str()
+    #[unstable(feature = "str_split_remainder", issue = "77998")]
+    pub fn remainder(&self) -> Option<&'a str> {
+        self.0.remainder()
     }
 }
 
@@ -1239,22 +1252,22 @@ impl<'a> SplitWhitespace<'a> {
     /// # Examples
     ///
     /// ```
-    /// #![feature(str_split_whitespace_as_str)]
+    /// #![feature(str_split_whitespace_remainder)]
     ///
     /// let mut split = "Mary had a little lamb".split_whitespace();
-    /// assert_eq!(split.as_str(), "Mary had a little lamb");
+    /// assert_eq!(split.remainder(), Some("Mary had a little lamb"));
     ///
     /// split.next();
-    /// assert_eq!(split.as_str(), "had a little lamb");
+    /// assert_eq!(split.remainder(), Some("had a little lamb"));
     ///
     /// split.by_ref().for_each(drop);
-    /// assert_eq!(split.as_str(), "");
+    /// assert_eq!(split.remainder(), None);
     /// ```
     #[inline]
     #[must_use]
-    #[unstable(feature = "str_split_whitespace_as_str", issue = "77998")]
-    pub fn as_str(&self) -> &'a str {
-        self.inner.iter.as_str()
+    #[unstable(feature = "str_split_whitespace_remainder", issue = "77998")]
+    pub fn remainder(&self) -> Option<&'a str> {
+        self.inner.iter.remainder()
     }
 }
 
@@ -1290,32 +1303,34 @@ impl<'a> DoubleEndedIterator for SplitAsciiWhitespace<'a> {
 impl FusedIterator for SplitAsciiWhitespace<'_> {}
 
 impl<'a> SplitAsciiWhitespace<'a> {
-    /// Returns remainder of the split string
+    /// Returns remainder of the split string.
+    ///
+    /// If the iterator is empty, returns `None`.
     ///
     /// # Examples
     ///
     /// ```
-    /// #![feature(str_split_whitespace_as_str)]
+    /// #![feature(str_split_whitespace_remainder)]
     ///
     /// let mut split = "Mary had a little lamb".split_ascii_whitespace();
-    /// assert_eq!(split.as_str(), "Mary had a little lamb");
+    /// assert_eq!(split.remainder(), Some("Mary had a little lamb"));
     ///
     /// split.next();
-    /// assert_eq!(split.as_str(), "had a little lamb");
+    /// assert_eq!(split.remainder(), Some("had a little lamb"));
     ///
     /// split.by_ref().for_each(drop);
-    /// assert_eq!(split.as_str(), "");
+    /// assert_eq!(split.remainder(), None);
     /// ```
     #[inline]
     #[must_use]
-    #[unstable(feature = "str_split_whitespace_as_str", issue = "77998")]
-    pub fn as_str(&self) -> &'a str {
+    #[unstable(feature = "str_split_whitespace_remainder", issue = "77998")]
+    pub fn remainder(&self) -> Option<&'a str> {
         if self.inner.iter.iter.finished {
-            return "";
+            return None;
         }
 
         // SAFETY: Slice is created from str.
-        unsafe { crate::str::from_utf8_unchecked(&self.inner.iter.iter.v) }
+        Some(unsafe { crate::str::from_utf8_unchecked(&self.inner.iter.iter.v) })
     }
 }
 
@@ -1358,23 +1373,25 @@ impl<'a, P: Pattern<'a, Searcher: ReverseSearcher<'a>>> DoubleEndedIterator
 impl<'a, P: Pattern<'a>> FusedIterator for SplitInclusive<'a, P> {}
 
 impl<'a, P: Pattern<'a>> SplitInclusive<'a, P> {
-    /// Returns remainder of the split string
+    /// Returns remainder of the split string.
+    ///
+    /// If the iterator is empty, returns `None`.
     ///
     /// # Examples
     ///
     /// ```
-    /// #![feature(str_split_inclusive_as_str)]
+    /// #![feature(str_split_inclusive_remainder)]
     /// let mut split = "Mary had a little lamb".split_inclusive(' ');
-    /// assert_eq!(split.as_str(), "Mary had a little lamb");
+    /// assert_eq!(split.remainder(), Some("Mary had a little lamb"));
     /// split.next();
-    /// assert_eq!(split.as_str(), "had a little lamb");
+    /// assert_eq!(split.remainder(), Some("had a little lamb"));
     /// split.by_ref().for_each(drop);
-    /// assert_eq!(split.as_str(), "");
+    /// assert_eq!(split.remainder(), None);
     /// ```
     #[inline]
-    #[unstable(feature = "str_split_inclusive_as_str", issue = "77998")]
-    pub fn as_str(&self) -> &'a str {
-        self.0.as_str()
+    #[unstable(feature = "str_split_inclusive_remainder", issue = "77998")]
+    pub fn remainder(&self) -> Option<&'a str> {
+        self.0.remainder()
     }
 }
 
diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs
index 99d4a40c4c9..c910cb65c55 100644
--- a/library/core/tests/lib.rs
+++ b/library/core/tests/lib.rs
@@ -155,3 +155,16 @@ mod time;
 mod tuple;
 mod unicode;
 mod waker;
+
+/// Copied from `std::test_helpers::test_rng`, see that function for rationale.
+#[track_caller]
+#[allow(dead_code)] // Not used in all configurations.
+pub(crate) fn test_rng() -> rand_xorshift::XorShiftRng {
+    use core::hash::{BuildHasher, Hash, Hasher};
+    let mut hasher = std::collections::hash_map::RandomState::new().build_hasher();
+    core::panic::Location::caller().hash(&mut hasher);
+    let hc64 = hasher.finish();
+    let seed_vec = hc64.to_le_bytes().into_iter().chain(0u8..8).collect::<Vec<u8>>();
+    let seed: [u8; 16] = seed_vec.as_slice().try_into().unwrap();
+    rand::SeedableRng::from_seed(seed)
+}
diff --git a/library/core/tests/num/flt2dec/random.rs b/library/core/tests/num/flt2dec/random.rs
index d0950039314..0084c1c814e 100644
--- a/library/core/tests/num/flt2dec/random.rs
+++ b/library/core/tests/num/flt2dec/random.rs
@@ -9,8 +9,6 @@ use core::num::flt2dec::MAX_SIG_DIGITS;
 use core::num::flt2dec::{decode, DecodableFloat, Decoded, FullDecoded};
 
 use rand::distributions::{Distribution, Uniform};
-use rand::rngs::StdRng;
-use rand::SeedableRng;
 
 pub fn decode_finite<T: DecodableFloat>(v: T) -> Decoded {
     match decode(v).1 {
@@ -92,7 +90,7 @@ where
     if cfg!(target_os = "emscripten") {
         return; // using rng pulls in i128 support, which doesn't work
     }
-    let mut rng = StdRng::from_entropy();
+    let mut rng = crate::test_rng();
     let f32_range = Uniform::new(0x0000_0001u32, 0x7f80_0000);
     iterate("f32_random_equivalence_test", k, n, f, g, |_| {
         let x = f32::from_bits(f32_range.sample(&mut rng));
@@ -108,7 +106,7 @@ where
     if cfg!(target_os = "emscripten") {
         return; // using rng pulls in i128 support, which doesn't work
     }
-    let mut rng = StdRng::from_entropy();
+    let mut rng = crate::test_rng();
     let f64_range = Uniform::new(0x0000_0000_0000_0001u64, 0x7ff0_0000_0000_0000);
     iterate("f64_random_equivalence_test", k, n, f, g, |_| {
         let x = f64::from_bits(f64_range.sample(&mut rng));
diff --git a/library/core/tests/slice.rs b/library/core/tests/slice.rs
index 4e06e0f4398..fd35d96c3fe 100644
--- a/library/core/tests/slice.rs
+++ b/library/core/tests/slice.rs
@@ -1805,7 +1805,7 @@ fn brute_force_rotate_test_1() {
 fn sort_unstable() {
     use core::cmp::Ordering::{Equal, Greater, Less};
     use core::slice::heapsort;
-    use rand::{rngs::StdRng, seq::SliceRandom, Rng, SeedableRng};
+    use rand::{seq::SliceRandom, Rng};
 
     // Miri is too slow (but still need to `chain` to make the types match)
     let lens = if cfg!(miri) { (2..20).chain(0..0) } else { (2..25).chain(500..510) };
@@ -1813,7 +1813,7 @@ fn sort_unstable() {
 
     let mut v = [0; 600];
     let mut tmp = [0; 600];
-    let mut rng = StdRng::from_entropy();
+    let mut rng = crate::test_rng();
 
     for len in lens {
         let v = &mut v[0..len];
@@ -1879,11 +1879,10 @@ fn sort_unstable() {
 #[cfg_attr(miri, ignore)] // Miri is too slow
 fn select_nth_unstable() {
     use core::cmp::Ordering::{Equal, Greater, Less};
-    use rand::rngs::StdRng;
     use rand::seq::SliceRandom;
-    use rand::{Rng, SeedableRng};
+    use rand::Rng;
 
-    let mut rng = StdRng::from_entropy();
+    let mut rng = crate::test_rng();
 
     for len in (2..21).chain(500..501) {
         let mut orig = vec![0; len];
diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml
index 29b5a468bf4..adf521d9b94 100644
--- a/library/std/Cargo.toml
+++ b/library/std/Cargo.toml
@@ -33,7 +33,8 @@ default-features = false
 features = ['read_core', 'elf', 'macho', 'pe', 'unaligned', 'archive']
 
 [dev-dependencies]
-rand = "0.7"
+rand = { version = "0.8.5", default-features = false, features = ["alloc"] }
+rand_xorshift = "0.3.0"
 
 [target.'cfg(any(all(target_family = "wasm", not(target_os = "emscripten")), all(target_vendor = "fortanix", target_env = "sgx")))'.dependencies]
 dlmalloc = { version = "0.2.3", features = ['rustc-dep-of-std'] }
diff --git a/library/std/src/alloc.rs b/library/std/src/alloc.rs
index 61c1ff578b2..c5a5991cc81 100644
--- a/library/std/src/alloc.rs
+++ b/library/std/src/alloc.rs
@@ -338,7 +338,7 @@ fn default_alloc_error_hook(layout: Layout) {
 
     #[allow(unused_unsafe)]
     if unsafe { __rust_alloc_error_handler_should_panic != 0 } {
-        panic!("memory allocation of {} bytes failed\n", layout.size());
+        panic!("memory allocation of {} bytes failed", layout.size());
     } else {
         rtprintpanic!("memory allocation of {} bytes failed\n", layout.size());
     }
diff --git a/library/std/src/collections/hash/map/tests.rs b/library/std/src/collections/hash/map/tests.rs
index 65634f2063f..6b89518e2e2 100644
--- a/library/std/src/collections/hash/map/tests.rs
+++ b/library/std/src/collections/hash/map/tests.rs
@@ -3,7 +3,8 @@ use super::HashMap;
 use super::RandomState;
 use crate::assert_matches::assert_matches;
 use crate::cell::RefCell;
-use rand::{thread_rng, Rng};
+use crate::test_helpers::test_rng;
+use rand::Rng;
 use realstd::collections::TryReserveErrorKind::*;
 
 // https://github.com/rust-lang/rust/issues/62301
@@ -710,16 +711,16 @@ fn test_entry_take_doesnt_corrupt() {
     }
 
     let mut m = HashMap::new();
-    let mut rng = thread_rng();
+    let mut rng = test_rng();
 
     // Populate the map with some items.
     for _ in 0..50 {
-        let x = rng.gen_range(-10, 10);
+        let x = rng.gen_range(-10..10);
         m.insert(x, ());
     }
 
     for _ in 0..1000 {
-        let x = rng.gen_range(-10, 10);
+        let x = rng.gen_range(-10..10);
         match m.entry(x) {
             Vacant(_) => {}
             Occupied(e) => {
diff --git a/library/std/src/collections/hash/set.rs b/library/std/src/collections/hash/set.rs
index cee884145c7..b59f89d321c 100644
--- a/library/std/src/collections/hash/set.rs
+++ b/library/std/src/collections/hash/set.rs
@@ -317,7 +317,7 @@ impl<T, S> HashSet<T, S> {
     ///
     /// let mut set = HashSet::from([1, 2, 3, 4, 5, 6]);
     /// set.retain(|&k| k % 2 == 0);
-    /// assert_eq!(set.len(), 3);
+    /// assert_eq!(set, HashSet::from([2, 4, 6]));
     /// ```
     ///
     /// # Performance
diff --git a/library/std/src/fs/tests.rs b/library/std/src/fs/tests.rs
index b385ebde439..eb582be012b 100644
--- a/library/std/src/fs/tests.rs
+++ b/library/std/src/fs/tests.rs
@@ -10,7 +10,7 @@ use crate::sys_common::io::test::{tmpdir, TempDir};
 use crate::thread;
 use crate::time::{Duration, Instant};
 
-use rand::{rngs::StdRng, RngCore, SeedableRng};
+use rand::RngCore;
 
 #[cfg(unix)]
 use crate::os::unix::fs::symlink as symlink_dir;
@@ -1181,7 +1181,7 @@ fn _assert_send_sync() {
 #[test]
 fn binary_file() {
     let mut bytes = [0; 1024];
-    StdRng::from_entropy().fill_bytes(&mut bytes);
+    crate::test_helpers::test_rng().fill_bytes(&mut bytes);
 
     let tmpdir = tmpdir();
 
@@ -1194,7 +1194,7 @@ fn binary_file() {
 #[test]
 fn write_then_read() {
     let mut bytes = [0; 1024];
-    StdRng::from_entropy().fill_bytes(&mut bytes);
+    crate::test_helpers::test_rng().fill_bytes(&mut bytes);
 
     let tmpdir = tmpdir();
 
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index 13dfd41abbf..a7e13f5b866 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -14,7 +14,7 @@
 //! # How to read this documentation
 //!
 //! If you already know the name of what you are looking for, the fastest way to
-//! find it is to use the <a href="#" onclick="focusSearchBar();">search
+//! find it is to use the <a href="#" onclick="window.searchState.focus();">search
 //! bar</a> at the top of the page.
 //!
 //! Otherwise, you may want to jump to one of these useful sections:
@@ -652,3 +652,30 @@ mod sealed {
     #[unstable(feature = "sealed", issue = "none")]
     pub trait Sealed {}
 }
+
+#[cfg(test)]
+#[allow(dead_code)] // Not used in all configurations.
+pub(crate) mod test_helpers {
+    /// Test-only replacement for `rand::thread_rng()`, which is unusable for
+    /// us, as we want to allow running stdlib tests on tier-3 targets which may
+    /// not have `getrandom` support.
+    ///
+    /// Does a bit of a song and dance to ensure that the seed is different on
+    /// each call (as some tests sadly rely on this), but doesn't try that hard.
+    ///
+    /// This is duplicated in the `core`, `alloc` test suites (as well as
+    /// `std`'s integration tests), but figuring out a mechanism to share these
+    /// seems far more painful than copy-pasting a 7 line function a couple
+    /// times, given that even under a perma-unstable feature, I don't think we
+    /// want to expose types from `rand` from `std`.
+    #[track_caller]
+    pub(crate) fn test_rng() -> rand_xorshift::XorShiftRng {
+        use core::hash::{BuildHasher, Hash, Hasher};
+        let mut hasher = crate::collections::hash_map::RandomState::new().build_hasher();
+        core::panic::Location::caller().hash(&mut hasher);
+        let hc64 = hasher.finish();
+        let seed_vec = hc64.to_le_bytes().into_iter().chain(0u8..8).collect::<Vec<u8>>();
+        let seed: [u8; 16] = seed_vec.as_slice().try_into().unwrap();
+        rand::SeedableRng::from_seed(seed)
+    }
+}
diff --git a/library/std/src/macros.rs b/library/std/src/macros.rs
index 6e4ba1404e5..fcc5cfafd80 100644
--- a/library/std/src/macros.rs
+++ b/library/std/src/macros.rs
@@ -3,6 +3,7 @@
 //! This module contains a set of macros which are exported from the standard
 //! library. Each macro is available for use when linking against the standard
 //! library.
+// ignore-tidy-dbg
 
 #[doc = include_str!("../../core/src/macros/panic.md")]
 #[macro_export]
diff --git a/library/std/src/path.rs b/library/std/src/path.rs
index 19d8f1edaf4..82d68369312 100644
--- a/library/std/src/path.rs
+++ b/library/std/src/path.rs
@@ -271,7 +271,7 @@ pub const MAIN_SEPARATOR: char = crate::sys::path::MAIN_SEP;
 /// The primary separator of path components for the current platform.
 ///
 /// For example, `/` on Unix and `\` on Windows.
-#[unstable(feature = "main_separator_str", issue = "94071")]
+#[stable(feature = "main_separator_str", since = "CURRENT_RUSTC_VERSION")]
 pub const MAIN_SEPARATOR_STR: &str = crate::sys::path::MAIN_SEP_STR;
 
 ////////////////////////////////////////////////////////////////////////////////
diff --git a/library/std/src/sync/rwlock/tests.rs b/library/std/src/sync/rwlock/tests.rs
index b5b3ad9898e..1a9d3d3f12f 100644
--- a/library/std/src/sync/rwlock/tests.rs
+++ b/library/std/src/sync/rwlock/tests.rs
@@ -2,7 +2,7 @@ use crate::sync::atomic::{AtomicUsize, Ordering};
 use crate::sync::mpsc::channel;
 use crate::sync::{Arc, RwLock, RwLockReadGuard, TryLockError};
 use crate::thread;
-use rand::{self, Rng};
+use rand::Rng;
 
 #[derive(Eq, PartialEq, Debug)]
 struct NonCopy(i32);
@@ -28,7 +28,7 @@ fn frob() {
         let tx = tx.clone();
         let r = r.clone();
         thread::spawn(move || {
-            let mut rng = rand::thread_rng();
+            let mut rng = crate::test_helpers::test_rng();
             for _ in 0..M {
                 if rng.gen_bool(1.0 / (N as f64)) {
                     drop(r.write().unwrap());
diff --git a/library/std/src/sys_common/io.rs b/library/std/src/sys_common/io.rs
index d1e9fed41fc..4a42ff3c618 100644
--- a/library/std/src/sys_common/io.rs
+++ b/library/std/src/sys_common/io.rs
@@ -39,9 +39,10 @@ pub mod test {
         }
     }
 
+    #[track_caller] // for `test_rng`
     pub fn tmpdir() -> TempDir {
         let p = env::temp_dir();
-        let mut r = rand::thread_rng();
+        let mut r = crate::test_helpers::test_rng();
         let ret = p.join(&format!("rust-{}", r.next_u32()));
         fs::create_dir(&ret).unwrap();
         TempDir(ret)
diff --git a/library/std/tests/env.rs b/library/std/tests/env.rs
index b095c2dde62..aae2c49d898 100644
--- a/library/std/tests/env.rs
+++ b/library/std/tests/env.rs
@@ -1,12 +1,24 @@
 use std::env::*;
 use std::ffi::{OsStr, OsString};
 
-use rand::distributions::Alphanumeric;
-use rand::{thread_rng, Rng};
+use rand::distributions::{Alphanumeric, DistString};
+
+/// Copied from `std::test_helpers::test_rng`, since these tests rely on the
+/// seed not being the same for every RNG invocation too.
+#[track_caller]
+pub(crate) fn test_rng() -> rand_xorshift::XorShiftRng {
+    use core::hash::{BuildHasher, Hash, Hasher};
+    let mut hasher = std::collections::hash_map::RandomState::new().build_hasher();
+    core::panic::Location::caller().hash(&mut hasher);
+    let hc64 = hasher.finish();
+    let seed_vec = hc64.to_le_bytes().into_iter().chain(0u8..8).collect::<Vec<u8>>();
+    let seed: [u8; 16] = seed_vec.as_slice().try_into().unwrap();
+    rand::SeedableRng::from_seed(seed)
+}
 
+#[track_caller]
 fn make_rand_name() -> OsString {
-    let rng = thread_rng();
-    let n = format!("TEST{}", rng.sample_iter(&Alphanumeric).take(10).collect::<String>());
+    let n = format!("TEST{}", Alphanumeric.sample_string(&mut test_rng(), 10));
     let n = OsString::from(n);
     assert!(var_os(&n).is_none());
     n
diff --git a/library/test/src/console.rs b/library/test/src/console.rs
index a3c39f71f08..24cbe035f2f 100644
--- a/library/test/src/console.rs
+++ b/library/test/src/console.rs
@@ -147,7 +147,7 @@ pub fn list_tests_console(opts: &TestOpts, tests: Vec<TestDescAndFn>) -> io::Res
     let mut ntest = 0;
     let mut nbench = 0;
 
-    for test in filter_tests(&opts, tests).into_iter() {
+    for test in filter_tests(opts, tests).into_iter() {
         use crate::TestFn::*;
 
         let TestDescAndFn { desc: TestDesc { name, .. }, testfn } = test;
@@ -244,7 +244,7 @@ fn on_test_event(
             let stdout = &completed_test.stdout;
 
             st.write_log_result(test, result, exec_time.as_ref())?;
-            out.write_result(test, result, exec_time.as_ref(), &*stdout, st)?;
+            out.write_result(test, result, exec_time.as_ref(), stdout, st)?;
             handle_test_result(st, completed_test);
         }
     }
@@ -262,7 +262,7 @@ pub fn run_tests_console(opts: &TestOpts, tests: Vec<TestDescAndFn>) -> io::Resu
 
     let max_name_len = tests
         .iter()
-        .max_by_key(|t| len_if_padded(*t))
+        .max_by_key(|t| len_if_padded(t))
         .map(|t| t.desc.name.as_slice().len())
         .unwrap_or(0);
 
diff --git a/library/test/src/formatters/json.rs b/library/test/src/formatters/json.rs
index 5526aadb67f..95d2faf2506 100644
--- a/library/test/src/formatters/json.rs
+++ b/library/test/src/formatters/json.rs
@@ -40,20 +40,20 @@ impl<T: Write> JsonFormatter<T> {
         extra: Option<&str>,
     ) -> io::Result<()> {
         // A doc test's name includes a filename which must be escaped for correct json.
-        self.write_message(&*format!(
+        self.write_message(&format!(
             r#"{{ "type": "{}", "name": "{}", "event": "{}""#,
             ty,
             EscapedString(name),
             evt
         ))?;
         if let Some(exec_time) = exec_time {
-            self.write_message(&*format!(r#", "exec_time": {}"#, exec_time.0.as_secs_f64()))?;
+            self.write_message(&format!(r#", "exec_time": {}"#, exec_time.0.as_secs_f64()))?;
         }
         if let Some(stdout) = stdout {
-            self.write_message(&*format!(r#", "stdout": "{}""#, EscapedString(stdout)))?;
+            self.write_message(&format!(r#", "stdout": "{}""#, EscapedString(stdout)))?;
         }
         if let Some(extra) = extra {
-            self.write_message(&*format!(r#", {extra}"#))?;
+            self.write_message(&format!(r#", {extra}"#))?;
         }
         self.writeln_message(" }")
     }
@@ -66,13 +66,13 @@ impl<T: Write> OutputFormatter for JsonFormatter<T> {
         } else {
             String::new()
         };
-        self.writeln_message(&*format!(
+        self.writeln_message(&format!(
             r#"{{ "type": "suite", "event": "started", "test_count": {test_count}{shuffle_seed_json} }}"#
         ))
     }
 
     fn write_test_start(&mut self, desc: &TestDesc) -> io::Result<()> {
-        self.writeln_message(&*format!(
+        self.writeln_message(&format!(
             r#"{{ "type": "test", "event": "started", "name": "{}" }}"#,
             EscapedString(desc.name.as_slice())
         ))
@@ -151,20 +151,20 @@ impl<T: Write> OutputFormatter for JsonFormatter<T> {
                     mbps
                 );
 
-                self.writeln_message(&*line)
+                self.writeln_message(&line)
             }
         }
     }
 
     fn write_timeout(&mut self, desc: &TestDesc) -> io::Result<()> {
-        self.writeln_message(&*format!(
+        self.writeln_message(&format!(
             r#"{{ "type": "test", "event": "timeout", "name": "{}" }}"#,
             EscapedString(desc.name.as_slice())
         ))
     }
 
     fn write_run_finish(&mut self, state: &ConsoleTestState) -> io::Result<bool> {
-        self.write_message(&*format!(
+        self.write_message(&format!(
             "{{ \"type\": \"suite\", \
              \"event\": \"{}\", \
              \"passed\": {}, \
diff --git a/library/test/src/formatters/junit.rs b/library/test/src/formatters/junit.rs
index e6fb4f5707b..7a40ce33cb7 100644
--- a/library/test/src/formatters/junit.rs
+++ b/library/test/src/formatters/junit.rs
@@ -64,7 +64,7 @@ impl<T: Write> OutputFormatter for JunitFormatter<T> {
     fn write_run_finish(&mut self, state: &ConsoleTestState) -> io::Result<bool> {
         self.write_message("<testsuites>")?;
 
-        self.write_message(&*format!(
+        self.write_message(&format!(
             "<testsuite name=\"test\" package=\"test\" id=\"0\" \
              errors=\"0\" \
              failures=\"{}\" \
@@ -73,12 +73,12 @@ impl<T: Write> OutputFormatter for JunitFormatter<T> {
              >",
             state.failed, state.total, state.ignored
         ))?;
-        for (desc, result, duration) in std::mem::replace(&mut self.results, Vec::new()) {
+        for (desc, result, duration) in std::mem::take(&mut self.results) {
             let (class_name, test_name) = parse_class_name(&desc);
             match result {
                 TestResult::TrIgnored => { /* no-op */ }
                 TestResult::TrFailed => {
-                    self.write_message(&*format!(
+                    self.write_message(&format!(
                         "<testcase classname=\"{}\" \
                          name=\"{}\" time=\"{}\">",
                         class_name,
@@ -90,19 +90,19 @@ impl<T: Write> OutputFormatter for JunitFormatter<T> {
                 }
 
                 TestResult::TrFailedMsg(ref m) => {
-                    self.write_message(&*format!(
+                    self.write_message(&format!(
                         "<testcase classname=\"{}\" \
                          name=\"{}\" time=\"{}\">",
                         class_name,
                         test_name,
                         duration.as_secs_f64()
                     ))?;
-                    self.write_message(&*format!("<failure message=\"{m}\" type=\"assert\"/>"))?;
+                    self.write_message(&format!("<failure message=\"{m}\" type=\"assert\"/>"))?;
                     self.write_message("</testcase>")?;
                 }
 
                 TestResult::TrTimedFail => {
-                    self.write_message(&*format!(
+                    self.write_message(&format!(
                         "<testcase classname=\"{}\" \
                          name=\"{}\" time=\"{}\">",
                         class_name,
@@ -114,7 +114,7 @@ impl<T: Write> OutputFormatter for JunitFormatter<T> {
                 }
 
                 TestResult::TrBench(ref b) => {
-                    self.write_message(&*format!(
+                    self.write_message(&format!(
                         "<testcase classname=\"benchmark::{}\" \
                          name=\"{}\" time=\"{}\" />",
                         class_name, test_name, b.ns_iter_summ.sum
@@ -122,7 +122,7 @@ impl<T: Write> OutputFormatter for JunitFormatter<T> {
                 }
 
                 TestResult::TrOk => {
-                    self.write_message(&*format!(
+                    self.write_message(&format!(
                         "<testcase classname=\"{}\" \
                          name=\"{}\" time=\"{}\"/>",
                         class_name,
diff --git a/library/test/src/formatters/pretty.rs b/library/test/src/formatters/pretty.rs
index 0299c8b5433..247778e515f 100644
--- a/library/test/src/formatters/pretty.rs
+++ b/library/test/src/formatters/pretty.rs
@@ -134,7 +134,7 @@ impl<T: Write> PrettyFormatter<T> {
 
         let mut results = Vec::new();
         let mut stdouts = String::new();
-        for &(ref f, ref stdout) in inputs {
+        for (f, stdout) in inputs {
             results.push(f.name.to_string());
             if !stdout.is_empty() {
                 stdouts.push_str(&format!("---- {} stdout ----\n", f.name));
@@ -171,9 +171,9 @@ impl<T: Write> PrettyFormatter<T> {
     fn write_test_name(&mut self, desc: &TestDesc) -> io::Result<()> {
         let name = desc.padded_name(self.max_name_len, desc.name.padding());
         if let Some(test_mode) = desc.test_mode() {
-            self.write_plain(&format!("test {name} - {test_mode} ... "))?;
+            self.write_plain(format!("test {name} - {test_mode} ... "))?;
         } else {
-            self.write_plain(&format!("test {name} ... "))?;
+            self.write_plain(format!("test {name} ... "))?;
         }
 
         Ok(())
@@ -188,7 +188,7 @@ impl<T: Write> OutputFormatter for PrettyFormatter<T> {
         } else {
             String::new()
         };
-        self.write_plain(&format!("\nrunning {test_count} {noun}{shuffle_seed_msg}\n"))
+        self.write_plain(format!("\nrunning {test_count} {noun}{shuffle_seed_msg}\n"))
     }
 
     fn write_test_start(&mut self, desc: &TestDesc) -> io::Result<()> {
@@ -221,7 +221,7 @@ impl<T: Write> OutputFormatter for PrettyFormatter<T> {
             TestResult::TrIgnored => self.write_ignored(desc.ignore_message)?,
             TestResult::TrBench(ref bs) => {
                 self.write_bench()?;
-                self.write_plain(&format!(": {}", fmt_bench_samples(bs)))?;
+                self.write_plain(format!(": {}", fmt_bench_samples(bs)))?;
             }
             TestResult::TrTimedFail => self.write_time_failed()?,
         }
@@ -231,7 +231,7 @@ impl<T: Write> OutputFormatter for PrettyFormatter<T> {
     }
 
     fn write_timeout(&mut self, desc: &TestDesc) -> io::Result<()> {
-        self.write_plain(&format!(
+        self.write_plain(format!(
             "test {} has been running for over {} seconds\n",
             desc.name,
             time::TEST_WARN_TIMEOUT_S
@@ -267,11 +267,11 @@ impl<T: Write> OutputFormatter for PrettyFormatter<T> {
             state.passed, state.failed, state.ignored, state.measured, state.filtered_out
         );
 
-        self.write_plain(&s)?;
+        self.write_plain(s)?;
 
         if let Some(ref exec_time) = state.exec_time {
             let time_str = format!("; finished in {exec_time}");
-            self.write_plain(&time_str)?;
+            self.write_plain(time_str)?;
         }
 
         self.write_plain("\n\n")?;
diff --git a/library/test/src/formatters/terse.rs b/library/test/src/formatters/terse.rs
index 5dace8baef7..0837ab16905 100644
--- a/library/test/src/formatters/terse.rs
+++ b/library/test/src/formatters/terse.rs
@@ -70,7 +70,7 @@ impl<T: Write> TerseFormatter<T> {
             // screen when dealing with line-buffered output (e.g., piping to
             // `stamp` in the rust CI).
             let out = format!(" {}/{}\n", self.test_count + 1, self.total_test_count);
-            self.write_plain(&out)?;
+            self.write_plain(out)?;
         }
 
         self.test_count += 1;
@@ -106,7 +106,7 @@ impl<T: Write> TerseFormatter<T> {
         self.write_plain("\nsuccesses:\n")?;
         let mut successes = Vec::new();
         let mut stdouts = String::new();
-        for &(ref f, ref stdout) in &state.not_failures {
+        for (f, stdout) in &state.not_failures {
             successes.push(f.name.to_string());
             if !stdout.is_empty() {
                 stdouts.push_str(&format!("---- {} stdout ----\n", f.name));
@@ -132,7 +132,7 @@ impl<T: Write> TerseFormatter<T> {
         self.write_plain("\nfailures:\n")?;
         let mut failures = Vec::new();
         let mut fail_out = String::new();
-        for &(ref f, ref stdout) in &state.failures {
+        for (f, stdout) in &state.failures {
             failures.push(f.name.to_string());
             if !stdout.is_empty() {
                 fail_out.push_str(&format!("---- {} stdout ----\n", f.name));
@@ -157,9 +157,9 @@ impl<T: Write> TerseFormatter<T> {
     fn write_test_name(&mut self, desc: &TestDesc) -> io::Result<()> {
         let name = desc.padded_name(self.max_name_len, desc.name.padding());
         if let Some(test_mode) = desc.test_mode() {
-            self.write_plain(&format!("test {name} - {test_mode} ... "))?;
+            self.write_plain(format!("test {name} - {test_mode} ... "))?;
         } else {
-            self.write_plain(&format!("test {name} ... "))?;
+            self.write_plain(format!("test {name} ... "))?;
         }
 
         Ok(())
@@ -175,7 +175,7 @@ impl<T: Write> OutputFormatter for TerseFormatter<T> {
         } else {
             String::new()
         };
-        self.write_plain(&format!("\nrunning {test_count} {noun}{shuffle_seed_msg}\n"))
+        self.write_plain(format!("\nrunning {test_count} {noun}{shuffle_seed_msg}\n"))
     }
 
     fn write_test_start(&mut self, desc: &TestDesc) -> io::Result<()> {
@@ -209,13 +209,13 @@ impl<T: Write> OutputFormatter for TerseFormatter<T> {
                     self.write_test_name(desc)?;
                 }
                 self.write_bench()?;
-                self.write_plain(&format!(": {}\n", fmt_bench_samples(bs)))
+                self.write_plain(format!(": {}\n", fmt_bench_samples(bs)))
             }
         }
     }
 
     fn write_timeout(&mut self, desc: &TestDesc) -> io::Result<()> {
-        self.write_plain(&format!(
+        self.write_plain(format!(
             "test {} has been running for over {} seconds\n",
             desc.name,
             time::TEST_WARN_TIMEOUT_S
@@ -245,11 +245,11 @@ impl<T: Write> OutputFormatter for TerseFormatter<T> {
             state.passed, state.failed, state.ignored, state.measured, state.filtered_out
         );
 
-        self.write_plain(&s)?;
+        self.write_plain(s)?;
 
         if let Some(ref exec_time) = state.exec_time {
             let time_str = format!("; finished in {exec_time}");
-            self.write_plain(&time_str)?;
+            self.write_plain(time_str)?;
         }
 
         self.write_plain("\n\n")?;
diff --git a/library/test/src/lib.rs b/library/test/src/lib.rs
index f6a41bbb88c..30dc4ff8553 100644
--- a/library/test/src/lib.rs
+++ b/library/test/src/lib.rs
@@ -789,7 +789,7 @@ fn run_test_in_spawned_subprocess(
         }
     });
     let record_result2 = record_result.clone();
-    panic::set_hook(Box::new(move |info| record_result2(Some(&info))));
+    panic::set_hook(Box::new(move |info| record_result2(Some(info))));
     if let Err(message) = testfn() {
         panic!("{}", message);
     }
diff --git a/library/test/src/term/terminfo/mod.rs b/library/test/src/term/terminfo/mod.rs
index 35585901971..67ba89410cd 100644
--- a/library/test/src/term/terminfo/mod.rs
+++ b/library/test/src/term/terminfo/mod.rs
@@ -149,7 +149,7 @@ impl<T: Write + Send> Terminal for TerminfoTerminal<T> {
         // are there any terminals that have color/attrs and not sgr0?
         // Try falling back to sgr, then op
         let cmd = match ["sgr0", "sgr", "op"].iter().find_map(|cap| self.ti.strings.get(*cap)) {
-            Some(op) => match expand(&op, &[], &mut Variables::new()) {
+            Some(op) => match expand(op, &[], &mut Variables::new()) {
                 Ok(cmd) => cmd,
                 Err(e) => return Err(io::Error::new(io::ErrorKind::InvalidData, e)),
             },
@@ -180,12 +180,12 @@ impl<T: Write + Send> TerminfoTerminal<T> {
     }
 
     fn dim_if_necessary(&self, color: color::Color) -> color::Color {
-        if color >= self.num_colors && color >= 8 && color < 16 { color - 8 } else { color }
+        if color >= self.num_colors && (8..16).contains(&color) { color - 8 } else { color }
     }
 
     fn apply_cap(&mut self, cmd: &str, params: &[Param]) -> io::Result<bool> {
         match self.ti.strings.get(cmd) {
-            Some(cmd) => match expand(&cmd, params, &mut Variables::new()) {
+            Some(cmd) => match expand(cmd, params, &mut Variables::new()) {
                 Ok(s) => self.out.write_all(&s).and(Ok(true)),
                 Err(e) => Err(io::Error::new(io::ErrorKind::InvalidData, e)),
             },
diff --git a/library/test/src/term/terminfo/parm.rs b/library/test/src/term/terminfo/parm.rs
index 0756c8374aa..2815f6cfc77 100644
--- a/library/test/src/term/terminfo/parm.rs
+++ b/library/test/src/term/terminfo/parm.rs
@@ -282,14 +282,14 @@ pub(crate) fn expand(
                 );
             }
             SetVar => {
-                if cur >= 'A' && cur <= 'Z' {
+                if cur.is_ascii_uppercase() {
                     if let Some(arg) = stack.pop() {
                         let idx = (cur as u8) - b'A';
                         vars.sta_va[idx as usize] = arg;
                     } else {
                         return Err("stack is empty".to_string());
                     }
-                } else if cur >= 'a' && cur <= 'z' {
+                } else if cur.is_ascii_lowercase() {
                     if let Some(arg) = stack.pop() {
                         let idx = (cur as u8) - b'a';
                         vars.dyn_va[idx as usize] = arg;
@@ -301,10 +301,10 @@ pub(crate) fn expand(
                 }
             }
             GetVar => {
-                if cur >= 'A' && cur <= 'Z' {
+                if cur.is_ascii_uppercase() {
                     let idx = (cur as u8) - b'A';
                     stack.push(vars.sta_va[idx as usize].clone());
-                } else if cur >= 'a' && cur <= 'z' {
+                } else if cur.is_ascii_lowercase() {
                     let idx = (cur as u8) - b'a';
                     stack.push(vars.dyn_va[idx as usize].clone());
                 } else {
diff --git a/library/test/src/term/terminfo/searcher.rs b/library/test/src/term/terminfo/searcher.rs
index 68e181a6895..87b91f34498 100644
--- a/library/test/src/term/terminfo/searcher.rs
+++ b/library/test/src/term/terminfo/searcher.rs
@@ -22,7 +22,7 @@ pub(crate) fn get_dbpath_for_term(term: &str) -> Option<PathBuf> {
 
     if let Ok(dirs) = env::var("TERMINFO_DIRS") {
         for i in dirs.split(':') {
-            if i == "" {
+            if i.is_empty() {
                 dirs_to_search.push(PathBuf::from("/usr/share/terminfo"));
             } else {
                 dirs_to_search.push(PathBuf::from(i));
@@ -49,7 +49,7 @@ pub(crate) fn get_dbpath_for_term(term: &str) -> Option<PathBuf> {
     for mut p in dirs_to_search {
         if fs::metadata(&p).is_ok() {
             p.push(&first_char.to_string());
-            p.push(&term);
+            p.push(term);
             if fs::metadata(&p).is_ok() {
                 return Some(p);
             }
diff --git a/library/test/src/test_result.rs b/library/test/src/test_result.rs
index 7c5b0d6c0f7..1da238e3e8c 100644
--- a/library/test/src/test_result.rs
+++ b/library/test/src/test_result.rs
@@ -33,7 +33,7 @@ pub fn calc_result<'a>(
 ) -> TestResult {
     let result = match (&desc.should_panic, task_result) {
         (&ShouldPanic::No, Ok(())) | (&ShouldPanic::Yes, Err(_)) => TestResult::TrOk,
-        (&ShouldPanic::YesWithMessage(msg), Err(ref err)) => {
+        (&ShouldPanic::YesWithMessage(msg), Err(err)) => {
             let maybe_panic_str = err
                 .downcast_ref::<String>()
                 .map(|e| &**e)
@@ -52,7 +52,7 @@ pub fn calc_result<'a>(
                     r#"expected panic with string value,
  found non-string value: `{:?}`
      expected substring: `{:?}`"#,
-                    (**err).type_id(),
+                    (*err).type_id(),
                     msg
                 ))
             }
diff --git a/library/test/src/types.rs b/library/test/src/types.rs
index 888afff7921..6f2e033095a 100644
--- a/library/test/src/types.rs
+++ b/library/test/src/types.rs
@@ -47,7 +47,7 @@ impl TestName {
         match *self {
             StaticTestName(s) => s,
             DynTestName(ref s) => s,
-            AlignedTestName(ref s, _) => &*s,
+            AlignedTestName(ref s, _) => s,
         }
     }
 
diff --git a/src/bootstrap/Cargo.lock b/src/bootstrap/Cargo.lock
index efe8ae3169f..4a0ba592577 100644
--- a/src/bootstrap/Cargo.lock
+++ b/src/bootstrap/Cargo.lock
@@ -36,6 +36,7 @@ dependencies = [
 name = "bootstrap"
 version = "0.0.0"
 dependencies = [
+ "build_helper",
  "cc",
  "cmake",
  "fd-lock",
@@ -71,6 +72,10 @@ dependencies = [
 ]
 
 [[package]]
+name = "build_helper"
+version = "0.1.0"
+
+[[package]]
 name = "cc"
 version = "1.0.73"
 source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml
index fafe82a9c12..22ceeca941e 100644
--- a/src/bootstrap/Cargo.toml
+++ b/src/bootstrap/Cargo.toml
@@ -30,6 +30,7 @@ path = "bin/sccache-plus-cl.rs"
 test = false
 
 [dependencies]
+build_helper = { path = "../tools/build_helper" }
 cmake = "0.1.38"
 fd-lock = "3.0.8"
 filetime = "0.2"
diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py
index 9cf43fc7a21..f3998e98583 100644
--- a/src/bootstrap/bootstrap.py
+++ b/src/bootstrap/bootstrap.py
@@ -934,8 +934,7 @@ def main():
     if len(sys.argv) > 1 and sys.argv[1] == 'help':
         sys.argv = [sys.argv[0], '-h'] + sys.argv[2:]
 
-    help_triggered = (
-        '-h' in sys.argv) or ('--help' in sys.argv) or (len(sys.argv) == 1)
+    help_triggered = len(sys.argv) == 1 or any(x in ["-h", "--help", "--version"] for x in sys.argv)
     try:
         bootstrap(help_triggered)
         if not help_triggered:
diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs
index 340aa78ebf9..68215790bed 100644
--- a/src/bootstrap/dist.rs
+++ b/src/bootstrap/dist.rs
@@ -2067,6 +2067,9 @@ impl Step for RustDev {
 
         builder.ensure(crate::native::Llvm { target });
 
+        // We want to package `lld` to use it with `download-ci-llvm`.
+        builder.ensure(crate::native::Lld { target });
+
         let src_bindir = builder.llvm_out(target).join("bin");
         // If updating this list, you likely want to change
         // src/bootstrap/download-ci-llvm-stamp as well, otherwise local users
diff --git a/src/bootstrap/download-ci-llvm-stamp b/src/bootstrap/download-ci-llvm-stamp
index d19a1ae95cf..94630e40f3c 100644
--- a/src/bootstrap/download-ci-llvm-stamp
+++ b/src/bootstrap/download-ci-llvm-stamp
@@ -1,4 +1,4 @@
 Change this file to make users of the `download-ci-llvm` configuration download
 a new version of LLVM from CI, even if the LLVM submodule hasn’t changed.
 
-Last change is for: https://github.com/rust-lang/rust/pull/102790
+Last change is for: https://github.com/rust-lang/rust/pull/104748
diff --git a/src/bootstrap/format.rs b/src/bootstrap/format.rs
index 84e46118959..bfc57a85cdb 100644
--- a/src/bootstrap/format.rs
+++ b/src/bootstrap/format.rs
@@ -1,7 +1,8 @@
 //! Runs rustfmt on the repository.
 
 use crate::builder::Builder;
-use crate::util::{output, program_out_of_date, t};
+use crate::util::{output, output_result, program_out_of_date, t};
+use build_helper::git::updated_master_branch;
 use ignore::WalkBuilder;
 use std::collections::VecDeque;
 use std::path::{Path, PathBuf};
@@ -78,50 +79,24 @@ fn update_rustfmt_version(build: &Builder<'_>) {
 /// rust-lang/master and what is now on the disk.
 ///
 /// Returns `None` if all files should be formatted.
-fn get_modified_rs_files(build: &Builder<'_>) -> Option<Vec<String>> {
-    let Ok(remote) = get_rust_lang_rust_remote() else { return None; };
+fn get_modified_rs_files(build: &Builder<'_>) -> Result<Option<Vec<String>>, String> {
+    let Ok(updated_master) = updated_master_branch(Some(&build.config.src)) else { return Ok(None); };
+
     if !verify_rustfmt_version(build) {
-        return None;
+        return Ok(None);
     }
 
     let merge_base =
-        output(build.config.git().arg("merge-base").arg(&format!("{remote}/master")).arg("HEAD"));
-    Some(
-        output(build.config.git().arg("diff-index").arg("--name-only").arg(merge_base.trim()))
-            .lines()
-            .map(|s| s.trim().to_owned())
-            .filter(|f| Path::new(f).extension().map_or(false, |ext| ext == "rs"))
-            .collect(),
-    )
-}
-
-/// Finds the remote for rust-lang/rust.
-/// For example for these remotes it will return `upstream`.
-/// ```text
-/// origin  https://github.com/Nilstrieb/rust.git (fetch)
-/// origin  https://github.com/Nilstrieb/rust.git (push)
-/// upstream        https://github.com/rust-lang/rust (fetch)
-/// upstream        https://github.com/rust-lang/rust (push)
-/// ```
-fn get_rust_lang_rust_remote() -> Result<String, String> {
-    let mut git = Command::new("git");
-    git.args(["config", "--local", "--get-regex", "remote\\..*\\.url"]);
-
-    let output = git.output().map_err(|err| format!("{err:?}"))?;
-    if !output.status.success() {
-        return Err("failed to execute git config command".to_owned());
-    }
-
-    let stdout = String::from_utf8(output.stdout).map_err(|err| format!("{err:?}"))?;
-
-    let rust_lang_remote = stdout
+        output_result(build.config.git().arg("merge-base").arg(&updated_master).arg("HEAD"))?;
+    Ok(Some(
+        output_result(
+            build.config.git().arg("diff-index").arg("--name-only").arg(merge_base.trim()),
+        )?
         .lines()
-        .find(|remote| remote.contains("rust-lang"))
-        .ok_or_else(|| "rust-lang/rust remote not found".to_owned())?;
-
-    let remote_name =
-        rust_lang_remote.split('.').nth(1).ok_or_else(|| "remote name not found".to_owned())?;
-    Ok(remote_name.into())
+        .map(|s| s.trim().to_owned())
+        .filter(|f| Path::new(f).extension().map_or(false, |ext| ext == "rs"))
+        .collect(),
+    ))
 }
 
 #[derive(serde::Deserialize)]
@@ -158,6 +133,9 @@ pub fn format(build: &Builder<'_>, check: bool, paths: &[PathBuf]) {
         Ok(status) => status.success(),
         Err(_) => false,
     };
+
+    let mut paths = paths.to_vec();
+
     if git_available {
         let in_working_tree = match build
             .config
@@ -191,10 +169,21 @@ pub fn format(build: &Builder<'_>, check: bool, paths: &[PathBuf]) {
                 ignore_fmt.add(&format!("!/{}", untracked_path)).expect(&untracked_path);
             }
             if !check && paths.is_empty() {
-                if let Some(files) = get_modified_rs_files(build) {
-                    for file in files {
-                        println!("formatting modified file {file}");
-                        ignore_fmt.add(&format!("/{file}")).expect(&file);
+                match get_modified_rs_files(build) {
+                    Ok(Some(files)) => {
+                        for file in files {
+                            println!("formatting modified file {file}");
+                            ignore_fmt.add(&format!("/{file}")).expect(&file);
+                        }
+                    }
+                    Ok(None) => {}
+                    Err(err) => {
+                        println!(
+                            "WARN: Something went wrong when running git commands:\n{err}\n\
+                            Falling back to formatting all files."
+                        );
+                        // Something went wrong when getting the version. Just format all the files.
+                        paths.push(".".into());
                     }
                 }
             }
@@ -204,6 +193,7 @@ pub fn format(build: &Builder<'_>, check: bool, paths: &[PathBuf]) {
     } else {
         println!("Could not find usable git. Skipping git-aware format checks");
     }
+
     let ignore_fmt = ignore_fmt.build().unwrap();
 
     let rustfmt_path = build.initial_rustfmt().unwrap_or_else(|| {
diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs
index 5ea41d10bc8..d44b96cfb99 100644
--- a/src/bootstrap/lib.rs
+++ b/src/bootstrap/lib.rs
@@ -113,6 +113,7 @@ use std::path::{Path, PathBuf};
 use std::process::Command;
 use std::str;
 
+use build_helper::ci::CiEnv;
 use channel::GitInfo;
 use config::{DryRun, Target};
 use filetime::FileTime;
@@ -121,7 +122,7 @@ use once_cell::sync::OnceCell;
 use crate::builder::Kind;
 use crate::config::{LlvmLibunwind, TargetSelection};
 use crate::util::{
-    exe, libdir, mtime, output, run, run_suppressed, symlink_dir, try_run_suppressed, CiEnv,
+    exe, libdir, mtime, output, run, run_suppressed, symlink_dir, try_run_suppressed,
 };
 
 mod bolt;
diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs
index 4e503dfe864..89bb2b770f9 100644
--- a/src/bootstrap/native.rs
+++ b/src/bootstrap/native.rs
@@ -24,6 +24,8 @@ use crate::util::get_clang_cl_resource_dir;
 use crate::util::{self, exe, output, t, up_to_date};
 use crate::{CLang, GitRepo};
 
+use build_helper::ci::CiEnv;
+
 #[derive(Clone)]
 pub struct LlvmResult {
     /// Path to llvm-config binary.
@@ -63,13 +65,13 @@ impl LdFlags {
     }
 }
 
-// This returns whether we've already previously built LLVM.
-//
-// It's used to avoid busting caches during x.py check -- if we've already built
-// LLVM, it's fine for us to not try to avoid doing so.
-//
-// This will return the llvm-config if it can get it (but it will not build it
-// if not).
+/// This returns whether we've already previously built LLVM.
+///
+/// It's used to avoid busting caches during x.py check -- if we've already built
+/// LLVM, it's fine for us to not try to avoid doing so.
+///
+/// This will return the llvm-config if it can get it (but it will not build it
+/// if not).
 pub fn prebuilt_llvm_config(
     builder: &Builder<'_>,
     target: TargetSelection,
@@ -217,7 +219,7 @@ pub(crate) fn is_ci_llvm_available(config: &Config, asserts: bool) -> bool {
         return false;
     }
 
-    if crate::util::CiEnv::is_ci() {
+    if CiEnv::is_ci() {
         // We assume we have access to git, so it's okay to unconditionally pass
         // `true` here.
         let llvm_sha = detect_llvm_sha(config, true);
@@ -823,8 +825,21 @@ impl Step for Lld {
         }
         let target = self.target;
 
-        let LlvmResult { llvm_config, llvm_cmake_dir } =
-            builder.ensure(Llvm { target: self.target });
+        let LlvmResult { llvm_config, llvm_cmake_dir } = builder.ensure(Llvm { target });
+
+        // The `dist` step packages LLD next to LLVM's binaries for download-ci-llvm. The root path
+        // we usually expect here is `./build/$triple/ci-llvm/`, with the binaries in its `bin`
+        // subfolder. We check if that's the case, and if LLD's binary already exists there next to
+        // `llvm-config`: if so, we can use it instead of building LLVM/LLD from source.
+        let ci_llvm_bin = llvm_config.parent().unwrap();
+        if ci_llvm_bin.is_dir() && ci_llvm_bin.file_name().unwrap() == "bin" {
+            let lld_path = ci_llvm_bin.join(exe("lld", target));
+            if lld_path.exists() {
+                // The following steps copying `lld` as `rust-lld` to the sysroot, expect it in the
+                // `bin` subfolder of this step's out dir.
+                return ci_llvm_bin.parent().unwrap().to_path_buf();
+            }
+        }
 
         let out_dir = builder.lld_out(target);
         let done_stamp = out_dir.join("lld-finished-building");
@@ -1072,12 +1087,12 @@ fn supported_sanitizers(
 
     match &*target.triple {
         "aarch64-apple-darwin" => darwin_libs("osx", &["asan", "lsan", "tsan"]),
-        "aarch64-fuchsia" => common_libs("fuchsia", "aarch64", &["asan"]),
+        "aarch64-unknown-fuchsia" => common_libs("fuchsia", "aarch64", &["asan"]),
         "aarch64-unknown-linux-gnu" => {
             common_libs("linux", "aarch64", &["asan", "lsan", "msan", "tsan", "hwasan"])
         }
         "x86_64-apple-darwin" => darwin_libs("osx", &["asan", "lsan", "tsan"]),
-        "x86_64-fuchsia" => common_libs("fuchsia", "x86_64", &["asan"]),
+        "x86_64-unknown-fuchsia" => common_libs("fuchsia", "x86_64", &["asan"]),
         "x86_64-unknown-freebsd" => common_libs("freebsd", "x86_64", &["asan", "msan", "tsan"]),
         "x86_64-unknown-netbsd" => {
             common_libs("netbsd", "x86_64", &["asan", "lsan", "msan", "tsan"])
diff --git a/src/bootstrap/run.rs b/src/bootstrap/run.rs
index 05de51f8cc5..e0280854541 100644
--- a/src/bootstrap/run.rs
+++ b/src/bootstrap/run.rs
@@ -105,6 +105,7 @@ impl Step for BumpStage0 {
 
     fn run(self, builder: &Builder<'_>) -> Self::Output {
         let mut cmd = builder.tool_cmd(Tool::BumpStage0);
+        cmd.args(builder.config.cmd.args());
         builder.run(&mut cmd);
     }
 }
diff --git a/src/bootstrap/setup.rs b/src/bootstrap/setup.rs
index cd360cbef96..ca4feac6fac 100644
--- a/src/bootstrap/setup.rs
+++ b/src/bootstrap/setup.rs
@@ -351,7 +351,7 @@ pub fn interactive_path() -> io::Result<Profile> {
     Ok(template)
 }
 
-// install a git hook to automatically run tidy --bless, if they want
+// install a git hook to automatically run tidy, if they want
 fn install_git_hook_maybe(config: &Config) -> io::Result<()> {
     let git = t!(config.git().args(&["rev-parse", "--git-common-dir"]).output().map(|output| {
         assert!(output.status.success(), "failed to run `git`");
@@ -367,7 +367,7 @@ fn install_git_hook_maybe(config: &Config) -> io::Result<()> {
     println!();
     println!(
         "Rust's CI will automatically fail if it doesn't pass `tidy`, the internal tool for ensuring code quality.
-If you'd like, x.py can install a git hook for you that will automatically run `tidy --bless` before
+If you'd like, x.py can install a git hook for you that will automatically run `test tidy` before
 pushing your code to ensure your code is up to par. If you decide later that this behavior is
 undesirable, simply delete the `pre-push` file from .git/hooks."
     );
diff --git a/src/bootstrap/util.rs b/src/bootstrap/util.rs
index 58220783228..93e53d383cd 100644
--- a/src/bootstrap/util.rs
+++ b/src/bootstrap/util.rs
@@ -255,35 +255,6 @@ pub enum CiEnv {
     GitHubActions,
 }
 
-impl CiEnv {
-    /// Obtains the current CI environment.
-    pub fn current() -> CiEnv {
-        if env::var("TF_BUILD").map_or(false, |e| e == "True") {
-            CiEnv::AzurePipelines
-        } else if env::var("GITHUB_ACTIONS").map_or(false, |e| e == "true") {
-            CiEnv::GitHubActions
-        } else {
-            CiEnv::None
-        }
-    }
-
-    pub fn is_ci() -> bool {
-        Self::current() != CiEnv::None
-    }
-
-    /// If in a CI environment, forces the command to run with colors.
-    pub fn force_coloring_in_ci(self, cmd: &mut Command) {
-        if self != CiEnv::None {
-            // Due to use of stamp/docker, the output stream of rustbuild is not
-            // a TTY in CI, so coloring is by-default turned off.
-            // The explicit `TERM=xterm` environment is needed for
-            // `--color always` to actually work. This env var was lost when
-            // compiling through the Makefile. Very strange.
-            cmd.env("TERM", "xterm").args(&["--color", "always"]);
-        }
-    }
-}
-
 pub fn forcing_clang_based_tests() -> bool {
     if let Some(var) = env::var_os("RUSTBUILD_FORCE_CLANG_BASED_TESTS") {
         match &var.to_string_lossy().to_lowercase()[..] {
@@ -441,6 +412,23 @@ pub fn output(cmd: &mut Command) -> String {
     String::from_utf8(output.stdout).unwrap()
 }
 
+pub fn output_result(cmd: &mut Command) -> Result<String, String> {
+    let output = match cmd.stderr(Stdio::inherit()).output() {
+        Ok(status) => status,
+        Err(e) => return Err(format!("failed to run command: {:?}: {}", cmd, e)),
+    };
+    if !output.status.success() {
+        return Err(format!(
+            "command did not execute successfully: {:?}\n\
+             expected success, got: {}\n{}",
+            cmd,
+            output.status,
+            String::from_utf8(output.stderr).map_err(|err| format!("{err:?}"))?
+        ));
+    }
+    Ok(String::from_utf8(output.stdout).map_err(|err| format!("{err:?}"))?)
+}
+
 /// Returns the last-modified time for `path`, or zero if it doesn't exist.
 pub fn mtime(path: &Path) -> SystemTime {
     fs::metadata(path).and_then(|f| f.modified()).unwrap_or(UNIX_EPOCH)
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 93ef7dfcbf5..0f5df95a0dd 100644
--- a/src/ci/docker/host-x86_64/dist-various-2/Dockerfile
+++ b/src/ci/docker/host-x86_64/dist-various-2/Dockerfile
@@ -30,18 +30,18 @@ RUN apt-key adv --batch --yes --keyserver keyserver.ubuntu.com --recv-keys 74DA7
 RUN add-apt-repository -y 'deb https://apt.dilos.org/dilos dilos2 main'
 
 ENV \
-    AR_x86_64_fuchsia=x86_64-fuchsia-ar \
-    CC_x86_64_fuchsia=x86_64-fuchsia-clang \
-    CFLAGS_x86_64_fuchsia="--target=x86_64-fuchsia --sysroot=/usr/local/core-linux-amd64-fuchsia-sdk/arch/x64/sysroot -I/usr/local/core-linux-amd64-fuchsia-sdk/pkg/fdio/include" \
-    CXX_x86_64_fuchsia=x86_64-fuchsia-clang++ \
-    CXXFLAGS_x86_64_fuchsia="--target=x86_64-fuchsia --sysroot=/usr/local/core-linux-amd64-fuchsia-sdk/arch/x64/sysroot -I/usr/local/core-linux-amd64-fuchsia-sdk/pkg/fdio/include" \
-    LDFLAGS_x86_64_fuchsia="--target=x86_64-fuchsia --sysroot=/usr/local/core-linux-amd64-fuchsia-sdk/arch/x64/sysroot -L/usr/local/core-linux-amd64-fuchsia-sdk/arch/x64/lib" \
-    AR_aarch64_fuchsia=aarch64-fuchsia-ar \
-    CC_aarch64_fuchsia=aarch64-fuchsia-clang \
-    CFLAGS_aarch64_fuchsia="--target=aarch64-fuchsia --sysroot=/usr/local/core-linux-amd64-fuchsia-sdk/arch/arm64/sysroot -I/usr/local/core-linux-amd64-fuchsia-sdk/pkg/fdio/include" \
-    CXX_aarch64_fuchsia=aarch64-fuchsia-clang++ \
-    CXXFLAGS_aarch64_fuchsia="--target=aarch64-fuchsia --sysroot=/usr/local/core-linux-amd64-fuchsia-sdk/arch/arm64/sysroot -I/usr/local/core-linux-amd64-fuchsia-sdk/pkg/fdio/include" \
-    LDFLAGS_aarch64_fuchsia="--target=aarch64-fuchsia --sysroot=/usr/local/core-linux-amd64-fuchsia-sdk/arch/arm64/sysroot -L/usr/local/core-linux-amd64-fuchsia-sdk/arch/arm64/lib" \
+    AR_x86_64_unknown_fuchsia=x86_64-unknown-fuchsia-ar \
+    CC_x86_64_unknown_fuchsia=x86_64-unknown-fuchsia-clang \
+    CFLAGS_x86_64_unknown_fuchsia="--target=x86_64-unknown-fuchsia --sysroot=/usr/local/core-linux-amd64-fuchsia-sdk/arch/x64/sysroot -I/usr/local/core-linux-amd64-fuchsia-sdk/pkg/fdio/include" \
+    CXX_x86_64_unknown_fuchsia=x86_64-unknown-fuchsia-clang++ \
+    CXXFLAGS_x86_64_unknown_fuchsia="--target=x86_64-unknown-fuchsia --sysroot=/usr/local/core-linux-amd64-fuchsia-sdk/arch/x64/sysroot -I/usr/local/core-linux-amd64-fuchsia-sdk/pkg/fdio/include" \
+    LDFLAGS_x86_64_unknown_fuchsia="--target=x86_64-unknown-fuchsia --sysroot=/usr/local/core-linux-amd64-fuchsia-sdk/arch/x64/sysroot -L/usr/local/core-linux-amd64-fuchsia-sdk/arch/x64/lib" \
+    AR_aarch64_unknown_fuchsia=aarch64-unknown-fuchsia-ar \
+    CC_aarch64_unknown_fuchsia=aarch64-unknown-fuchsia-clang \
+    CFLAGS_aarch64_unknown_fuchsia="--target=aarch64-unknown-fuchsia --sysroot=/usr/local/core-linux-amd64-fuchsia-sdk/arch/arm64/sysroot -I/usr/local/core-linux-amd64-fuchsia-sdk/pkg/fdio/include" \
+    CXX_aarch64_unknown_fuchsia=aarch64-unknown-fuchsia-clang++ \
+    CXXFLAGS_aarch64_unknown_fuchsia="--target=aarch64-unknown-fuchsia --sysroot=/usr/local/core-linux-amd64-fuchsia-sdk/arch/arm64/sysroot -I/usr/local/core-linux-amd64-fuchsia-sdk/pkg/fdio/include" \
+    LDFLAGS_aarch64_unknown_fuchsia="--target=aarch64-unknown-fuchsia --sysroot=/usr/local/core-linux-amd64-fuchsia-sdk/arch/arm64/sysroot -L/usr/local/core-linux-amd64-fuchsia-sdk/arch/arm64/lib" \
     AR_sparcv9_sun_solaris=sparcv9-sun-solaris2.10-ar \
     CC_sparcv9_sun_solaris=sparcv9-sun-solaris2.10-gcc \
     CXX_sparcv9_sun_solaris=sparcv9-sun-solaris2.10-g++ \
@@ -99,19 +99,19 @@ RUN /tmp/freebsd-toolchain.sh i686
 COPY scripts/sccache.sh /scripts/
 RUN sh /scripts/sccache.sh
 
-ENV CARGO_TARGET_X86_64_FUCHSIA_AR /usr/local/bin/llvm-ar
-ENV CARGO_TARGET_X86_64_FUCHSIA_RUSTFLAGS \
+ENV CARGO_TARGET_X86_64_UNKNOWN_FUCHSIA_AR /usr/local/bin/llvm-ar
+ENV CARGO_TARGET_X86_64_UNKNOWN_FUCHSIA_RUSTFLAGS \
 -C link-arg=--sysroot=/usr/local/core-linux-amd64-fuchsia-sdk/arch/x64/sysroot \
 -Lnative=/usr/local/core-linux-amd64-fuchsia-sdk/arch/x64/sysroot/lib \
 -Lnative=/usr/local/core-linux-amd64-fuchsia-sdk/arch/x64/lib
-ENV CARGO_TARGET_AARCH64_FUCHSIA_AR /usr/local/bin/llvm-ar
-ENV CARGO_TARGET_AARCH64_FUCHSIA_RUSTFLAGS \
+ENV CARGO_TARGET_AARCH64_UNKNOWN_FUCHSIA_AR /usr/local/bin/llvm-ar
+ENV CARGO_TARGET_AARCH64_UNKNOWN_FUCHSIA_RUSTFLAGS \
 -C link-arg=--sysroot=/usr/local/core-linux-amd64-fuchsia-sdk/arch/arm64/sysroot \
 -Lnative=/usr/local/core-linux-amd64-fuchsia-sdk/arch/arm64/sysroot/lib \
 -Lnative=/usr/local/core-linux-amd64-fuchsia-sdk/arch/arm64/lib
 
-ENV TARGETS=x86_64-fuchsia
-ENV TARGETS=$TARGETS,aarch64-fuchsia
+ENV TARGETS=x86_64-unknown-fuchsia
+ENV TARGETS=$TARGETS,aarch64-unknown-fuchsia
 ENV TARGETS=$TARGETS,wasm32-unknown-unknown
 ENV TARGETS=$TARGETS,wasm32-wasi
 ENV TARGETS=$TARGETS,sparcv9-sun-solaris
diff --git a/src/ci/docker/host-x86_64/dist-various-2/build-fuchsia-toolchain.sh b/src/ci/docker/host-x86_64/dist-various-2/build-fuchsia-toolchain.sh
index 80db9257754..d762b4672c6 100755
--- a/src/ci/docker/host-x86_64/dist-various-2/build-fuchsia-toolchain.sh
+++ b/src/ci/docker/host-x86_64/dist-various-2/build-fuchsia-toolchain.sh
@@ -29,9 +29,9 @@ install_clang() {
   # CFLAGS and CXXFLAGS env variables in main Dockerfile handle sysroot linking
   for arch in x86_64 aarch64; do
     for tool in clang clang++; do
-      ln -s /usr/local/bin/${tool} /usr/local/bin/${arch}-fuchsia-${tool}
+      ln -s /usr/local/bin/${tool} /usr/local/bin/${arch}-unknown-fuchsia-${tool}
     done
-    ln -s /usr/local/bin/llvm-ar /usr/local/bin/${arch}-fuchsia-ar
+    ln -s /usr/local/bin/llvm-ar /usr/local/bin/${arch}-unknown-fuchsia-ar
   done
 
   popd > /dev/null
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version b/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version
index 475434e5aef..c39e9c5fbc9 100644
--- a/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version
+++ b/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version
@@ -1 +1 @@
-0.13.4
\ No newline at end of file
+0.14.1
\ No newline at end of file
diff --git a/src/ci/docker/scripts/fuchsia-test-runner.py b/src/ci/docker/scripts/fuchsia-test-runner.py
index 3e86339859d..c8d1ff9aefb 100755
--- a/src/ci/docker/scripts/fuchsia-test-runner.py
+++ b/src/ci/docker/scripts/fuchsia-test-runner.py
@@ -4,7 +4,7 @@
 The Rust toolchain test runner for Fuchsia.
 
 For instructions on running the compiler test suite, see
-https://doc.rust-lang.org/stable/rustc/platform-support/fuchsia.html#aarch64-fuchsia-and-x86_64-fuchsia
+https://doc.rust-lang.org/stable/rustc/platform-support/fuchsia.html#aarch64-unknown-fuchsia-and-x86_64-unknown-fuchsia
 """
 
 import argparse
@@ -110,9 +110,9 @@ class TestEnvironment:
 
     def rustlib_dir(self):
         if self.target_arch == "x64":
-            return "x86_64-fuchsia"
+            return "x86_64-unknown-fuchsia"
         if self.target_arch == "arm64":
-            return "aarch64-fuchsia"
+            return "aarch64-unknown-fuchsia"
         raise Exception(f"Unrecognized target architecture {self.target_arch}")
 
     def libs_dir(self):
diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md
index 2d3b8309461..752f1cc4aba 100644
--- a/src/doc/rustc/src/SUMMARY.md
+++ b/src/doc/rustc/src/SUMMARY.md
@@ -22,10 +22,11 @@
     - [armv4t-none-eabi](platform-support/armv4t-none-eabi.md)
     - [armv5te-none-eabi](platform-support/armv5te-none-eabi.md)
     - [armv6k-nintendo-3ds](platform-support/armv6k-nintendo-3ds.md)
+    - [armv7-sony-vita-newlibeabihf](platform-support/armv7-sony-vita-newlibeabihf.md)
     - [armv7-unknown-linux-uclibceabi](platform-support/armv7-unknown-linux-uclibceabi.md)
     - [armv7-unknown-linux-uclibceabihf](platform-support/armv7-unknown-linux-uclibceabihf.md)
     - [\*-android and \*-androideabi](platform-support/android.md)
-    - [\*-fuchsia](platform-support/fuchsia.md)
+    - [\*-unknown-fuchsia](platform-support/fuchsia.md)
     - [\*-kmc-solid_\*](platform-support/kmc-solid.md)
     - [m68k-unknown-linux-gnu](platform-support/m68k-unknown-linux-gnu.md)
     - [mips64-openwrt-linux-musl](platform-support/mips64-openwrt-linux-musl.md)
diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md
index d0c3ddf2606..7ff26e420f1 100644
--- a/src/doc/rustc/src/platform-support.md
+++ b/src/doc/rustc/src/platform-support.md
@@ -124,7 +124,7 @@ target | std | notes
 -------|:---:|-------
 `aarch64-apple-ios` | ✓ | ARM64 iOS
 [`aarch64-apple-ios-sim`](platform-support/aarch64-apple-ios-sim.md) | ✓ | Apple iOS Simulator on ARM64
-`aarch64-fuchsia` | ✓ | ARM64 Fuchsia
+`aarch64-unknown-fuchsia` | ✓ | ARM64 Fuchsia
 [`aarch64-linux-android`](platform-support/android.md) | ✓ | ARM64 Android
 `aarch64-unknown-none-softfloat` | * | Bare ARM64, softfloat
 `aarch64-unknown-none` | * | Bare ARM64, hardfloat
@@ -177,7 +177,7 @@ target | std | notes
 `wasm32-wasi` | ✓ | WebAssembly with WASI
 `x86_64-apple-ios` | ✓ | 64-bit x86 iOS
 [`x86_64-fortanix-unknown-sgx`](platform-support/x86_64-fortanix-unknown-sgx.md) | ✓ | [Fortanix ABI] for 64-bit Intel SGX
-`x86_64-fuchsia` | ✓ | 64-bit Fuchsia
+`x86_64-unknown-fuchsia` | ✓ | 64-bit Fuchsia
 [`x86_64-linux-android`](platform-support/android.md) | ✓ | 64-bit x86 Android
 `x86_64-pc-solaris` | ✓ | 64-bit Solaris 10/11, illumos
 `x86_64-unknown-linux-gnux32` | ✓ | 64-bit Linux (x32 ABI) (kernel 4.15, glibc 2.27)
@@ -235,6 +235,7 @@ target | std | host | notes
 `armv6-unknown-netbsd-eabihf` | ? |  |
 [`armv6k-nintendo-3ds`](platform-support/armv6k-nintendo-3ds.md) | ? |  | ARMv6K Nintendo 3DS, Horizon (Requires devkitARM toolchain)
 `armv7-apple-ios` | ✓ |  | ARMv7 iOS, Cortex-a8
+[`armv7-sony-vita-newlibeabihf`](platform-support/armv7-sony-vita-newlibeabihf.md) | ? |  | ARM Cortex-A9 Sony PlayStation Vita (requires VITASDK toolchain)
 [`armv7-unknown-linux-uclibceabi`](platform-support/armv7-unknown-linux-uclibceabi.md) | ✓ | ✓ | ARMv7 Linux with uClibc, softfloat
 [`armv7-unknown-linux-uclibceabihf`](platform-support/armv7-unknown-linux-uclibceabihf.md) | ✓ | ? | ARMv7 Linux with uClibc, hardfloat
 `armv7-unknown-freebsd` | ✓ | ✓ | ARMv7 FreeBSD
diff --git a/src/doc/rustc/src/platform-support/armv7-sony-vita-eabihf.md b/src/doc/rustc/src/platform-support/armv7-sony-vita-eabihf.md
new file mode 100644
index 00000000000..6619c90b849
--- /dev/null
+++ b/src/doc/rustc/src/platform-support/armv7-sony-vita-eabihf.md
@@ -0,0 +1,127 @@
+# armv7-sony-vita-eabihf
+
+**Tier: 3**
+
+This tier supports the ARM Cortex A9 processor running on a PlayStation Vita console. `armv7-vita-newlibeabihf` aims to have support for `std` crate using `newlib` as a bridge.
+
+## Designated Developers
+
+* [@amg98](https://github.com/amg98)
+
+## Requirements
+
+This target is cross compiled, and requires installing [VITASDK](https://vitasdk.org/) toolchain on your system.
+
+## Building
+
+You can build Rust with support for the target by adding it to the `target`
+list in `config.toml`:
+
+```toml
+[build]
+build-stage = 1
+target = ["armv7-sony-vita-newlibeabihf"]
+```
+
+## Cross-compilation
+
+This target can be cross-compiled from `x86_64` on either Windows, MacOS or Linux systems. Other hosts are not supported for cross-compilation.
+
+## Testing
+
+Currently there is no support to run the rustc test suite for this target.
+
+## Building and Running Rust Programs
+
+To test your developed rust programs for PlayStation Vita, first you have to prepare a proper executable for the device using the resulting ELF file you get from compilation step. The needed steps can be automated using tools like `cargo-make`. Use the example below as a template for your project:
+
+```toml
+[env]
+TITLE = "Rust Hello World"
+TITLEID = "RUST00001"
+# At least a "sce_sys" folder should be place there for app metadata (title, icons, description...)
+# You can find sample assets for that on $VITASDK/share/gcc-arm-vita-eabi/samples/hello_world/sce_sys/
+STATIC_DIR = "static"   # Folder where static assets should be placed (sce_sys folder is at $STATIC_DIR/sce_sys)
+CARGO_TARGET_DIR = { script = ["echo ${CARGO_TARGET_DIR:=target}"] }
+RUST_TARGET_PATH = { script = ["echo $(pwd)"]}
+RUST_TARGET = "armv7-sony-vita-newlibeabihf"
+CARGO_OUT_DIR = "${CARGO_TARGET_DIR}/${RUST_TARGET}/release"
+
+[tasks.xbuild]
+# This is the command where you get the ELF executable file (e.g. call to cargo build)
+
+[tasks.strip]
+description = "Strip the produced ELF executable."
+dependencies = ["xbuild"]
+command = "arm-vita-eabi-strip"
+args = ["-g", '${CARGO_OUT_DIR}/${CARGO_MAKE_CRATE_FS_NAME}.elf']
+
+[tasks.velf]
+description = "Build an VELF executable from the obtained ELF file."
+dependencies = ["strip"]
+command = "vita-elf-create"
+args = ['${CARGO_OUT_DIR}/${CARGO_MAKE_CRATE_NAME}.elf', '${CARGO_OUT_DIR}/${CARGO_MAKE_CRATE_NAME}.velf']
+
+[tasks.eboot-bin]
+description = "Build an `eboot.bin` file from the obtained VELF file."
+dependencies = ["velf"]
+command = "vita-make-fself"
+args = ["-s", '${CARGO_OUT_DIR}/${CARGO_MAKE_CRATE_NAME}.velf', '${CARGO_OUT_DIR}/eboot.bin']
+
+[tasks.param-sfo]
+description = "Build the `param.sfo` manifest using with given TITLE and TITLEID."
+command = "vita-mksfoex"
+args = ["-s", 'TITLE_ID=${TITLEID}', '${TITLE}', '${CARGO_OUT_DIR}/param.sfo']
+
+[tasks.manifest]
+description = "List all static resources into a manifest file."
+script = [
+  'mkdir -p "${CARGO_OUT_DIR}"',
+  '''
+  if [ -d "${STATIC_DIR}" ]; then
+    find "${STATIC_DIR}" -type f > "${CARGO_OUT_DIR}/MANIFEST"
+  else
+    touch "${CARGO_OUT_DIR}/MANIFEST"
+  fi
+  '''
+]
+
+[tasks.vpk]
+description = "Build a VPK distribution of the project executable and resources."
+dependencies = ["eboot-bin", "param-sfo", "manifest"]
+script_runner = "@rust"
+script = [
+    '''
+    use std::io::BufRead;
+    use std::fs::File;
+
+    fn main() {
+
+      let crate_name = env!("CARGO_MAKE_CRATE_NAME");
+      let static_dir = env!("STATIC_DIR");
+      let out_dir = std::path::PathBuf::from(env!("CARGO_OUT_DIR"));
+
+      let mut cmd = ::std::process::Command::new("vita-pack-vpk");
+      cmd.arg("-s").arg(out_dir.join("param.sfo"));
+      cmd.arg("-b").arg(out_dir.join("eboot.bin"));
+
+      // Add files from MANIFEST
+      if let Ok(file) = File::open(out_dir.join("MANIFEST")) {
+          let mut reader = ::std::io::BufReader::new(file);
+          let mut lines = reader.lines();
+          while let Some(Ok(line)) = lines.next() {
+              let p1 = ::std::path::PathBuf::from(line);            // path on FS
+              let p2 = p1.strip_prefix(static_dir).unwrap();        // path in VPK
+              cmd.arg("--add").arg(format!("{}={}", p1.display(), p2.display()));
+          }
+      }
+
+      cmd.arg(out_dir.join(format!("{}.vpk", crate_name)))
+        .output()
+        .expect("command failed.");
+    }
+    '''
+]
+```
+
+After running the above script, you should be able to get a *.vpk file in the same folder your *.elf executable resides. Now you can pick it and install it on your own PlayStation Vita using, for example, [VitaShell](https://github.com/TheOfficialFloW/VitaShell/releases) or you can use an emulator. For the time being, the most mature emulator for PlayStation Vita is [Vita3K](https://vita3k.org/), although I personally recommend testing your programs in real hardware, as the emulator is quite experimental.
diff --git a/src/doc/rustc/src/platform-support/fuchsia.md b/src/doc/rustc/src/platform-support/fuchsia.md
index cc4ee2e67b1..95c242cc161 100644
--- a/src/doc/rustc/src/platform-support/fuchsia.md
+++ b/src/doc/rustc/src/platform-support/fuchsia.md
@@ -1,4 +1,4 @@
-# `aarch64-fuchsia` and `x86_64-fuchsia`
+# `aarch64-unknown-fuchsia` and `x86_64-unknown-fuchsia`
 
 **Tier: 2**
 
@@ -67,7 +67,7 @@ This walkthrough will cover:
 1. Building a Fuchsia package.
 1. Publishing and running a Fuchsia package to a Fuchsia emulator.
 
-For the purposes of this walkthrough, we will only target `x86_64-fuchsia`.
+For the purposes of this walkthrough, we will only target `x86_64-unknown-fuchsia`.
 
 ## Compiling a Rust binary targeting Fuchsia
 
@@ -83,8 +83,8 @@ to handle the installation of Fuchsia targets for you. This can be done by issui
 the following commands:
 
 ```sh
-rustup target add x86_64-fuchsia
-rustup target add aarch64-fuchsia
+rustup target add x86_64-unknown-fuchsia
+rustup target add aarch64-unknown-fuchsia
 ```
 
 After installing our Fuchsia targets, we can now compile a Rust binary that targets
@@ -127,7 +127,7 @@ during compilation:
 
 **`.cargo/config.toml`**
 ```txt
-[target.x86_64-fuchsia]
+[target.x86_64-unknown-fuchsia]
 
 rustflags = [
     "-Lnative=<SDK_PATH>/arch/x64/lib",
@@ -159,10 +159,10 @@ hello_fuchsia/
 Finally, we can build our rust binary as:
 
 ```sh
-cargo build --target x86_64-fuchsia
+cargo build --target x86_64-unknown-fuchsia
 ```
 
-Now we have a Rust binary at `target/x86_64-fuchsia/debug/hello_fuchsia`,
+Now we have a Rust binary at `target/x86_64-unknown-fuchsia/debug/hello_fuchsia`,
 targeting our desired Fuchsia target.
 
 **Current directory structure**
@@ -171,7 +171,7 @@ hello_fuchsia/
 ┣━ src/
 ┃  ┗━ main.rs
 ┣━ target/
-┃  ┗━ x86_64-fuchsia/
+┃  ┗━ x86_64-unknown-fuchsia/
 ┃     ┗━ debug/
 ┃        ┗━ hello_fuchsia
 ┣━ Cargo.toml
@@ -193,16 +193,19 @@ configuration in `config.toml`:
 
 ```toml
 [build]
-target = ["<host_platform>", "aarch64-fuchsia", "x86_64-fuchsia"]
+target = ["<host_platform>", "aarch64-unknown-fuchsia", "x86_64-unknown-fuchsia"]
 
 [rust]
 lld = true
 
-[target.x86_64-fuchsia]
+[llvm]
+download-ci-llvm = false
+
+[target.x86_64-unknown-fuchsia]
 cc = "clang"
 cxx = "clang++"
 
-[target.aarch64-fuchsia]
+[target.aarch64-unknown-fuchsia]
 cc = "clang"
 cxx = "clang++"
 ```
@@ -233,14 +236,14 @@ a script we name `config-env.sh`:
 # Configure this environment variable to be the path to the downloaded SDK
 export SDK_PATH="<SDK path goes here>"
 
-export CFLAGS_aarch64_fuchsia="--target=aarch64-fuchsia --sysroot=${SDK_PATH}/arch/arm64/sysroot -I${SDK_PATH}/pkg/fdio/include"
-export CXXFLAGS_aarch64_fuchsia="--target=aarch64-fuchsia --sysroot=${SDK_PATH}/arch/arm64/sysroot -I${SDK_PATH}/pkg/fdio/include"
-export LDFLAGS_aarch64_fuchsia="--target=aarch64-fuchsia --sysroot=${SDK_PATH}/arch/arm64/sysroot -L${SDK_PATH}/arch/arm64/lib"
-export CARGO_TARGET_AARCH64_FUCHSIA_RUSTFLAGS="-C link-arg=--sysroot=${SDK_PATH}/arch/arm64/sysroot -Lnative=${SDK_PATH}/arch/arm64/sysroot/lib -Lnative=${SDK_PATH}/arch/arm64/lib"
-export CFLAGS_x86_64_fuchsia="--target=x86_64-fuchsia --sysroot=${SDK_PATH}/arch/x64/sysroot -I${SDK_PATH}/pkg/fdio/include"
-export CXXFLAGS_x86_64_fuchsia="--target=x86_64-fuchsia --sysroot=${SDK_PATH}/arch/x64/sysroot -I${SDK_PATH}/pkg/fdio/include"
-export LDFLAGS_x86_64_fuchsia="--target=x86_64-fuchsia --sysroot=${SDK_PATH}/arch/x64/sysroot -L${SDK_PATH}/arch/x64/lib"
-export CARGO_TARGET_X86_64_FUCHSIA_RUSTFLAGS="-C link-arg=--sysroot=${SDK_PATH}/arch/x64/sysroot -Lnative=${SDK_PATH}/arch/x64/sysroot/lib -Lnative=${SDK_PATH}/arch/x64/lib"
+export CFLAGS_aarch64_unknown_fuchsia="--target=aarch64-unknown-fuchsia --sysroot=${SDK_PATH}/arch/arm64/sysroot -I${SDK_PATH}/pkg/fdio/include"
+export CXXFLAGS_aarch64_unknown_fuchsia="--target=aarch64-unknown-fuchsia --sysroot=${SDK_PATH}/arch/arm64/sysroot -I${SDK_PATH}/pkg/fdio/include"
+export LDFLAGS_aarch64_unknown_fuchsia="--target=aarch64-unknown-fuchsia --sysroot=${SDK_PATH}/arch/arm64/sysroot -L${SDK_PATH}/arch/arm64/lib"
+export CARGO_TARGET_AARCH64_UNKNOWN_FUCHSIA_RUSTFLAGS="-C link-arg=--sysroot=${SDK_PATH}/arch/arm64/sysroot -Lnative=${SDK_PATH}/arch/arm64/sysroot/lib -Lnative=${SDK_PATH}/arch/arm64/lib"
+export CFLAGS_x86_64_unknown_fuchsia="--target=x86_64-unknown-fuchsia --sysroot=${SDK_PATH}/arch/x64/sysroot -I${SDK_PATH}/pkg/fdio/include"
+export CXXFLAGS_x86_64_unknown_fuchsia="--target=x86_64-unknown-fuchsia --sysroot=${SDK_PATH}/arch/x64/sysroot -I${SDK_PATH}/pkg/fdio/include"
+export LDFLAGS_x86_64_unknown_fuchsia="--target=x86_64-unknown-fuchsia --sysroot=${SDK_PATH}/arch/x64/sysroot -L${SDK_PATH}/arch/x64/lib"
+export CARGO_TARGET_X86_64_UNKNOWN_FUCHSIA_RUSTFLAGS="-C link-arg=--sysroot=${SDK_PATH}/arch/x64/sysroot -Lnative=${SDK_PATH}/arch/x64/sysroot/lib -Lnative=${SDK_PATH}/arch/x64/lib"
 ```
 
 Finally, the Rust compiler can be built and installed:
@@ -285,7 +288,7 @@ hello_fuchsia/
 Using your freshly installed `rustc`, you can compile a binary for Fuchsia using
 the following options:
 
-* `--target x86_64-fuchsia`/`--target aarch64-fuchsia`: Targets the Fuchsia
+* `--target x86_64-unknown-fuchsia`/`--target aarch64-unknown-fuchsia`: Targets the Fuchsia
   platform of your choice
 * `-Lnative ${SDK_PATH}/arch/${ARCH}/lib`: Link against Fuchsia libraries from
   the SDK
@@ -296,7 +299,7 @@ Putting it all together:
 
 ```sh
 # Configure these for the Fuchsia target of your choice
-TARGET_ARCH="<x86_64-fuchsia|aarch64-fuchsia>"
+TARGET_ARCH="<x86_64-unknown-fuchsia|aarch64-unknown-fuchsia>"
 ARCH="<x64|aarch64>"
 
 rustc \
@@ -322,16 +325,16 @@ Before moving on, double check your directory structure:
 **Current directory structure**
 ```txt
 hello_fuchsia/
-┣━ src/                     (if using rustc)
-┃   ┗━ hello_fuchsia.rs     ...
-┣━ bin/                     ...
-┃  ┗━ hello_fuchsia         ...
-┣━ src/                     (if using cargo)
-┃  ┗━ main.rs               ...
-┗━ target/                  ...
-   ┗━ x86_64-fuchsia/       ...
-      ┗━ debug/             ...
-         ┗━ hello_fuchsia   ...
+┣━ src/                         (if using rustc)
+┃   ┗━ hello_fuchsia.rs         ...
+┣━ bin/                         ...
+┃  ┗━ hello_fuchsia             ...
+┣━ src/                         (if using cargo)
+┃  ┗━ main.rs                   ...
+┗━ target/                      ...
+   ┗━ x86_64-unknown-fuchsia/   ...
+      ┗━ debug/                 ...
+         ┗━ hello_fuchsia       ...
 ```
 
 With our Rust binary built, we can move to creating a Fuchsia package.
@@ -368,7 +371,7 @@ package must contain one.
 
 **`pkg/hello_fuchsia.manifest` if using cargo**
 ```txt
-bin/hello_fuchsia=target/x86_64-fuchsia/debug/hello_fuchsia
+bin/hello_fuchsia=target/x86_64-unknown-fuchsia/debug/hello_fuchsia
 lib/ld.so.1=<SDK_PATH>/arch/x64/sysroot/dist/lib/ld.so.1
 lib/libfdio.so=<SDK_PATH>/arch/x64/dist/libfdio.so
 meta/package=pkg/meta/package
@@ -543,16 +546,16 @@ structure will look like:
 **Final directory structure**
 ```txt
 hello_fuchsia/
-┣━ src/                     (if using rustc)
-┃   ┗━ hello_fuchsia.rs     ...
-┣━ bin/                     ...
-┃  ┗━ hello_fuchsia         ...
-┣━ src/                     (if using cargo)
-┃  ┗━ main.rs               ...
-┣━ target/                  ...
-┃  ┗━ x86_64-fuchsia/       ...
-┃     ┗━ debug/             ...
-┃        ┗━ hello_fuchsia   ...
+┣━ src/                         (if using rustc)
+┃   ┗━ hello_fuchsia.rs         ...
+┣━ bin/                         ...
+┃  ┗━ hello_fuchsia             ...
+┣━ src/                         (if using cargo)
+┃  ┗━ main.rs                   ...
+┣━ target/                      ...
+┃  ┗━ x86_64-unknown-fuchsia/   ...
+┃     ┗━ debug/                 ...
+┃        ┗━ hello_fuchsia       ...
 ┗━ pkg/
    ┣━ meta/
    ┃  ┣━ package
@@ -641,8 +644,8 @@ Tests can be run in the same way as a regular binary.
 
 * If using `cargo`, you can simply pass `test --no-run`
 to the `cargo` invocation and then repackage and rerun the Fuchsia package. From our previous example,
-this would look like `cargo test --target x86_64-fuchsia --no-run`, and moving the executable
-binary path found from the line `Executable unittests src/main.rs (target/x86_64-fuchsia/debug/deps/hello_fuchsia-<HASH>)`
+this would look like `cargo test --target x86_64-unknown-fuchsia --no-run`, and moving the executable
+binary path found from the line `Executable unittests src/main.rs (target/x86_64-unknown-fuchsia/debug/deps/hello_fuchsia-<HASH>)`
 into `pkg/hello_fuchsia.manifest`.
 
 * If using the compiled `rustc`, you can simply pass `--test`
@@ -711,7 +714,7 @@ run the full `src/test/ui` test suite:
     --config config.toml                                                      \
     --stage=2                                                                 \
     test src/test/ui                                                          \
-    --target x86_64-fuchsia                                                   \
+    --target x86_64-unknown-fuchsia                                           \
     --run=always --jobs 1                                                     \
     --test-args --target-rustcflags                                           \
     --test-args -L                                                            \
@@ -755,7 +758,7 @@ directory to launch `zxdb`:
 **In separate terminal**
 ```sh
 ${SDK_PATH}/tools/${ARCH}/ffx debug connect -- \
-    --symbol-path target/x86_64-fuchsia/debug
+    --symbol-path target/x86_64-unknown-fuchsia/debug
 ```
 
 * `--symbol-path` gets required symbol paths, which are
@@ -851,7 +854,7 @@ source code:
 
 ```sh
 ${SDK_PATH}/tools/${ARCH}/ffx debug connect -- \
-    --symbol-path target/x86_64-fuchsia/debug \
+    --symbol-path target/x86_64-unknown-fuchsia/debug \
     --build-dir ${RUST_SRC_PATH}/rust \
     --build-dir ${FUCHSIA_SRC_PATH}/fuchsia/out/default
 ```
diff --git a/src/doc/unstable-book/src/compiler-flags/dump-mono-stats-format.md b/src/doc/unstable-book/src/compiler-flags/dump-mono-stats-format.md
new file mode 100644
index 00000000000..a497a75261f
--- /dev/null
+++ b/src/doc/unstable-book/src/compiler-flags/dump-mono-stats-format.md
@@ -0,0 +1,6 @@
+# `dump-mono-stats-format`
+
+--------------------
+
+The `-Z dump-mono-stats-format` compiler flag controls what file format to use for `-Z dump-mono-stats`.
+The default is markdown; currently JSON is also supported. JSON can be useful for programatically manipulating the results (e.g. to find the item that took the longest to compile).
diff --git a/src/doc/unstable-book/src/compiler-flags/dump-mono-stats.md b/src/doc/unstable-book/src/compiler-flags/dump-mono-stats.md
new file mode 100644
index 00000000000..4c8bc8b4578
--- /dev/null
+++ b/src/doc/unstable-book/src/compiler-flags/dump-mono-stats.md
@@ -0,0 +1,14 @@
+# `dump-mono-stats`
+
+--------------------
+
+The `-Z dump-mono-stats` compiler flag generates a file with a list of the monomorphized items in the current crate.
+It is useful for investigating compile times.
+
+It accepts an optional directory where the file will be located. If no directory is specified, the file will be placed in the current directory.
+
+See also `-Z dump-mono-stats-format` and `-Z print-mono-items`. Unlike `print-mono-items`,
+`dump-mono-stats` aggregates monomorphized items by definition and includes a size estimate of how
+large the item is when codegened.
+
+See <https://rustc-dev-guide.rust-lang.org/backend/monomorph.html> for an overview of monomorphized items.
diff --git a/src/doc/unstable-book/src/compiler-flags/sanitizer.md b/src/doc/unstable-book/src/compiler-flags/sanitizer.md
index a9616c34bff..70c3a445b86 100644
--- a/src/doc/unstable-book/src/compiler-flags/sanitizer.md
+++ b/src/doc/unstable-book/src/compiler-flags/sanitizer.md
@@ -50,10 +50,10 @@ with runtime flag `ASAN_OPTIONS=detect_leaks=1` on macOS.
 AddressSanitizer is supported on the following targets:
 
 * `aarch64-apple-darwin`
-* `aarch64-fuchsia`
+* `aarch64-unknown-fuchsia`
 * `aarch64-unknown-linux-gnu`
 * `x86_64-apple-darwin`
-* `x86_64-fuchsia`
+* `x86_64-unknown-fuchsia`
 * `x86_64-unknown-freebsd`
 * `x86_64-unknown-linux-gnu`
 
diff --git a/src/etc/pre-push.sh b/src/etc/pre-push.sh
index 2a3086338b4..7a846d44ad6 100755
--- a/src/etc/pre-push.sh
+++ b/src/etc/pre-push.sh
@@ -1,6 +1,6 @@
 #!/usr/bin/env bash
 #
-# Call `tidy --bless` before git push
+# Call `tidy` before git push
 # Copy this script to .git/hooks to activate,
 # and remove it from .git/hooks to deactivate.
 #
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 07a9c48365f..025a4379f45 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -1960,7 +1960,6 @@ pub(crate) fn clean_variant_def<'tcx>(variant: &ty::VariantDef, cx: &mut DocCont
             variant.fields.iter().map(|field| clean_middle_field(field, cx)).collect(),
         ),
         None => VariantKind::Struct(VariantStruct {
-            ctor_kind: None,
             fields: variant.fields.iter().map(|field| clean_middle_field(field, cx)).collect(),
         }),
     };
@@ -1985,7 +1984,6 @@ fn clean_variant_data<'tcx>(
 
     let kind = match variant {
         hir::VariantData::Struct(..) => VariantKind::Struct(VariantStruct {
-            ctor_kind: None,
             fields: variant.fields().iter().map(|x| clean_field(x, cx)).collect(),
         }),
         hir::VariantData::Tuple(..) => {
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index 77ec0242621..827afafbba3 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -2111,7 +2111,6 @@ impl Union {
 /// only as a variant in an enum.
 #[derive(Clone, Debug)]
 pub(crate) struct VariantStruct {
-    pub(crate) ctor_kind: Option<CtorKind>,
     pub(crate) fields: Vec<Item>,
 }
 
@@ -2495,6 +2494,17 @@ impl Import {
     pub(crate) fn new_glob(source: ImportSource, should_be_displayed: bool) -> Self {
         Self { kind: ImportKind::Glob, source, should_be_displayed }
     }
+
+    pub(crate) fn imported_item_is_doc_hidden(&self, tcx: TyCtxt<'_>) -> bool {
+        match self.source.did {
+            Some(did) => tcx
+                .get_attrs(did, sym::doc)
+                .filter_map(ast::Attribute::meta_item_list)
+                .flatten()
+                .has_word(sym::hidden),
+            None => false,
+        }
+    }
 }
 
 #[derive(Clone, Debug)]
diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs
index d4d3e4f6ea7..c8899ee62b5 100644
--- a/src/librustdoc/html/render/context.rs
+++ b/src/librustdoc/html/render/context.rs
@@ -309,7 +309,7 @@ impl<'tcx> Context<'tcx> {
 
     pub(crate) fn href_from_span(&self, span: clean::Span, with_lines: bool) -> Option<String> {
         let mut root = self.root_path();
-        let mut path = String::new();
+        let mut path: String;
         let cnum = span.cnum(self.sess());
 
         // We can safely ignore synthetic `SourceFile`s.
@@ -340,10 +340,24 @@ impl<'tcx> Context<'tcx> {
                 ExternalLocation::Unknown => return None,
             };
 
-            sources::clean_path(&src_root, file, false, |component| {
-                path.push_str(&component.to_string_lossy());
+            let href = RefCell::new(PathBuf::new());
+            sources::clean_path(
+                &src_root,
+                file,
+                |component| {
+                    href.borrow_mut().push(component);
+                },
+                || {
+                    href.borrow_mut().pop();
+                },
+            );
+
+            path = href.into_inner().to_string_lossy().to_string();
+
+            if let Some(c) = path.as_bytes().last() && *c != b'/' {
                 path.push('/');
-            });
+            }
+
             let mut fname = file.file_name().expect("source has no filename").to_os_string();
             fname.push(".html");
             path.push_str(&fname.to_string_lossy());
diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs
index 40dfb069750..c16d6477fc3 100644
--- a/src/librustdoc/html/render/print_item.rs
+++ b/src/librustdoc/html/render/print_item.rs
@@ -1229,16 +1229,7 @@ fn item_enum(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, e: &clean::
                                 w.write_str(")");
                             }
                             clean::VariantKind::Struct(ref s) => {
-                                render_struct(
-                                    w,
-                                    v,
-                                    None,
-                                    s.ctor_kind,
-                                    &s.fields,
-                                    "    ",
-                                    false,
-                                    cx,
-                                );
+                                render_struct(w, v, None, None, &s.fields, "    ", false, cx);
                             }
                         },
                         _ => unreachable!(),
diff --git a/src/librustdoc/html/render/write_shared.rs b/src/librustdoc/html/render/write_shared.rs
index eaf149a4300..3ea4c4bea88 100644
--- a/src/librustdoc/html/render/write_shared.rs
+++ b/src/librustdoc/html/render/write_shared.rs
@@ -1,8 +1,9 @@
+use std::cell::RefCell;
 use std::fs::{self, File};
 use std::io::prelude::*;
 use std::io::{self, BufReader};
 use std::path::{Component, Path};
-use std::rc::Rc;
+use std::rc::{Rc, Weak};
 
 use itertools::Itertools;
 use rustc_data_structures::flock;
@@ -184,23 +185,26 @@ pub(super) fn write_shared(
 
     use std::ffi::OsString;
 
-    #[derive(Debug)]
+    #[derive(Debug, Default)]
     struct Hierarchy {
+        parent: Weak<Self>,
         elem: OsString,
-        children: FxHashMap<OsString, Hierarchy>,
-        elems: FxHashSet<OsString>,
+        children: RefCell<FxHashMap<OsString, Rc<Self>>>,
+        elems: RefCell<FxHashSet<OsString>>,
     }
 
     impl Hierarchy {
-        fn new(elem: OsString) -> Hierarchy {
-            Hierarchy { elem, children: FxHashMap::default(), elems: FxHashSet::default() }
+        fn with_parent(elem: OsString, parent: &Rc<Self>) -> Self {
+            Self { elem, parent: Rc::downgrade(parent), ..Self::default() }
         }
 
         fn to_json_string(&self) -> String {
-            let mut subs: Vec<&Hierarchy> = self.children.values().collect();
+            let borrow = self.children.borrow();
+            let mut subs: Vec<_> = borrow.values().collect();
             subs.sort_unstable_by(|a, b| a.elem.cmp(&b.elem));
             let mut files = self
                 .elems
+                .borrow()
                 .iter()
                 .map(|s| format!("\"{}\"", s.to_str().expect("invalid osstring conversion")))
                 .collect::<Vec<_>>();
@@ -220,36 +224,52 @@ pub(super) fn write_shared(
                 files = files
             )
         }
-    }
 
-    if cx.include_sources {
-        let mut hierarchy = Hierarchy::new(OsString::new());
-        for source in cx
-            .shared
-            .local_sources
-            .iter()
-            .filter_map(|p| p.0.strip_prefix(&cx.shared.src_root).ok())
-        {
-            let mut h = &mut hierarchy;
-            let mut elems = source
+        fn add_path(self: &Rc<Self>, path: &Path) {
+            let mut h = Rc::clone(&self);
+            let mut elems = path
                 .components()
                 .filter_map(|s| match s {
                     Component::Normal(s) => Some(s.to_owned()),
+                    Component::ParentDir => Some(OsString::from("..")),
                     _ => None,
                 })
                 .peekable();
             loop {
                 let cur_elem = elems.next().expect("empty file path");
+                if cur_elem == ".." {
+                    if let Some(parent) = h.parent.upgrade() {
+                        h = parent;
+                    }
+                    continue;
+                }
                 if elems.peek().is_none() {
-                    h.elems.insert(cur_elem);
+                    h.elems.borrow_mut().insert(cur_elem);
                     break;
                 } else {
-                    let e = cur_elem.clone();
-                    h = h.children.entry(cur_elem.clone()).or_insert_with(|| Hierarchy::new(e));
+                    let entry = Rc::clone(
+                        h.children
+                            .borrow_mut()
+                            .entry(cur_elem.clone())
+                            .or_insert_with(|| Rc::new(Self::with_parent(cur_elem, &h))),
+                    );
+                    h = entry;
                 }
             }
         }
+    }
 
+    if cx.include_sources {
+        let hierarchy = Rc::new(Hierarchy::default());
+        for source in cx
+            .shared
+            .local_sources
+            .iter()
+            .filter_map(|p| p.0.strip_prefix(&cx.shared.src_root).ok())
+        {
+            hierarchy.add_path(source);
+        }
+        let hierarchy = Rc::try_unwrap(hierarchy).unwrap();
         let dst = cx.dst.join(&format!("source-files{}.js", cx.shared.resource_suffix));
         let make_sources = || {
             let (mut all_sources, _krates) =
diff --git a/src/librustdoc/html/sources.rs b/src/librustdoc/html/sources.rs
index e639fadeb96..799c497d137 100644
--- a/src/librustdoc/html/sources.rs
+++ b/src/librustdoc/html/sources.rs
@@ -13,6 +13,7 @@ use rustc_middle::ty::TyCtxt;
 use rustc_session::Session;
 use rustc_span::source_map::FileName;
 
+use std::cell::RefCell;
 use std::ffi::OsStr;
 use std::fs;
 use std::path::{Component, Path, PathBuf};
@@ -72,12 +73,22 @@ impl LocalSourcesCollector<'_, '_> {
             return;
         }
 
-        let mut href = String::new();
-        clean_path(self.src_root, &p, false, |component| {
-            href.push_str(&component.to_string_lossy());
-            href.push('/');
-        });
+        let href = RefCell::new(PathBuf::new());
+        clean_path(
+            &self.src_root,
+            &p,
+            |component| {
+                href.borrow_mut().push(component);
+            },
+            || {
+                href.borrow_mut().pop();
+            },
+        );
 
+        let mut href = href.into_inner().to_string_lossy().to_string();
+        if let Some(c) = href.as_bytes().last() && *c != b'/' {
+            href.push('/');
+        }
         let mut src_fname = p.file_name().expect("source has no filename").to_os_string();
         src_fname.push(".html");
         href.push_str(&src_fname.to_string_lossy());
@@ -180,13 +191,28 @@ impl SourceCollector<'_, '_> {
 
         let shared = Rc::clone(&self.cx.shared);
         // Create the intermediate directories
-        let mut cur = self.dst.clone();
-        let mut root_path = String::from("../../");
-        clean_path(&shared.src_root, &p, false, |component| {
-            cur.push(component);
-            root_path.push_str("../");
-        });
+        let cur = RefCell::new(PathBuf::new());
+        let root_path = RefCell::new(PathBuf::new());
+
+        clean_path(
+            &shared.src_root,
+            &p,
+            |component| {
+                cur.borrow_mut().push(component);
+                root_path.borrow_mut().push("..");
+            },
+            || {
+                cur.borrow_mut().pop();
+                root_path.borrow_mut().pop();
+            },
+        );
 
+        let root_path = PathBuf::from("../../").join(root_path.into_inner());
+        let mut root_path = root_path.to_string_lossy();
+        if let Some(c) = root_path.as_bytes().last() && *c != b'/' {
+            root_path += "/";
+        }
+        let mut cur = self.dst.join(cur.into_inner());
         shared.ensure_dir(&cur)?;
 
         let src_fname = p.file_name().expect("source has no filename").to_os_string();
@@ -232,11 +258,13 @@ impl SourceCollector<'_, '_> {
 /// Takes a path to a source file and cleans the path to it. This canonicalizes
 /// things like ".." to components which preserve the "top down" hierarchy of a
 /// static HTML tree. Each component in the cleaned path will be passed as an
-/// argument to `f`. The very last component of the path (ie the file name) will
-/// be passed to `f` if `keep_filename` is true, and ignored otherwise.
-pub(crate) fn clean_path<F>(src_root: &Path, p: &Path, keep_filename: bool, mut f: F)
+/// argument to `f`. The very last component of the path (ie the file name) is ignored.
+/// If a `..` is encountered, the `parent` closure will be called to allow the callee to
+/// handle it.
+pub(crate) fn clean_path<F, P>(src_root: &Path, p: &Path, mut f: F, mut parent: P)
 where
     F: FnMut(&OsStr),
+    P: FnMut(),
 {
     // make it relative, if possible
     let p = p.strip_prefix(src_root).unwrap_or(p);
@@ -244,12 +272,12 @@ where
     let mut iter = p.components().peekable();
 
     while let Some(c) = iter.next() {
-        if !keep_filename && iter.peek().is_none() {
+        if iter.peek().is_none() {
             break;
         }
 
         match c {
-            Component::ParentDir => f("up".as_ref()),
+            Component::ParentDir => parent(),
             Component::Normal(c) => f(c),
             _ => continue,
         }
diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css
index bc0458bcd28..77401e8b76e 100644
--- a/src/librustdoc/html/static/css/rustdoc.css
+++ b/src/librustdoc/html/static/css/rustdoc.css
@@ -76,8 +76,6 @@
 }
 
 * {
-	-webkit-box-sizing: border-box;
-	-moz-box-sizing: border-box;
 	box-sizing: border-box;
 }
 
@@ -110,11 +108,7 @@ body {
 	/* Then override it with `anywhere`, which is required to make non-Safari browsers break
 	   more aggressively when we want them to. */
 	overflow-wrap: anywhere;
-
-	-webkit-font-feature-settings: "kern", "liga";
-	-moz-font-feature-settings: "kern", "liga";
 	font-feature-settings: "kern", "liga";
-
 	background-color: var(--main-background-color);
 	color: var(--main-color);
 }
@@ -358,6 +352,7 @@ img {
 .sub-logo-container, .logo-container {
 	/* zero text boxes so that computed line height = image height exactly */
 	line-height: 0;
+	display: block;
 }
 
 .sub-logo-container {
@@ -501,7 +496,7 @@ ul.block, .block li {
 	color: var(--sidebar-link-color);
 }
 .sidebar .current,
-.sidebar a:hover {
+.sidebar a:hover:not(.logo-container) {
 	background-color: var(--sidebar-current-link-background-color);
 }
 
@@ -543,8 +538,6 @@ ul.block, .block li {
 	overflow: initial;
 	text-align: right;
 	-webkit-user-select: none;
-	-moz-user-select: none;
-	-ms-user-select: none;
 	user-select: none;
 	padding: 14px 8px;
 	color: var(--src-line-numbers-span-color);
@@ -1374,7 +1367,7 @@ kbd {
 	vertical-align: middle;
 	border: solid 1px var(--border-color);
 	border-radius: 3px;
-	color: var(--kbd--color);
+	color: var(--kbd-color);
 	background-color: var(--kbd-background);
 	box-shadow: inset 0 -1px 0 var(--kbd-box-shadow-color);
 }
@@ -1576,7 +1569,7 @@ in storage.js
 
 	/* Hide the logo and item name from the sidebar. Those are displayed
 	   in the mobile-topbar instead. */
-	.sidebar .sidebar-logo,
+	.sidebar .logo-container,
 	.sidebar .location {
 		display: none;
 	}
@@ -1605,14 +1598,10 @@ in storage.js
 
 	.sidebar.shown,
 	.source-sidebar-expanded .source .sidebar,
-	.sidebar:focus-within {
+	.rustdoc:not(.source) .sidebar:focus-within {
 		left: 0;
 	}
 
-	.rustdoc.source > .sidebar {
-		width: 0;
-	}
-
 	.mobile-topbar h2 {
 		padding-bottom: 0;
 		margin: auto 0.5em auto auto;
@@ -1662,10 +1651,6 @@ in storage.js
 		margin-top: 1em;
 	}
 
-	.content {
-		margin-left: 0px;
-	}
-
 	.anchor {
 		display: none !important;
 	}
diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js
index 60e4e749224..51aee8e7c89 100644
--- a/src/librustdoc/html/static/js/main.js
+++ b/src/librustdoc/html/static/js/main.js
@@ -563,7 +563,7 @@ function loadCss(cssUrl) {
                 onEachLazy(code.getElementsByTagName("a"), elem => {
                     const href = elem.getAttribute("href");
 
-                    if (href && href.indexOf("http") !== 0) {
+                    if (href && !/^(?:[a-z+]+:)?\/\//.test(href)) {
                         elem.setAttribute("href", window.rootPath + href);
                     }
                 });
@@ -1040,9 +1040,6 @@ function loadCss(cssUrl) {
             help_button.appendChild(container);
 
             container.onblur = helpBlurHandler;
-            container.onclick = event => {
-                event.preventDefault();
-            };
             help_button.onblur = helpBlurHandler;
             help_button.children[0].onblur = helpBlurHandler;
         }
diff --git a/src/librustdoc/html/templates/page.html b/src/librustdoc/html/templates/page.html
index bcaff957af2..fddda293b9a 100644
--- a/src/librustdoc/html/templates/page.html
+++ b/src/librustdoc/html/templates/page.html
@@ -72,28 +72,24 @@
     {%- if page.css_class != "source" -%}
     <nav class="mobile-topbar"> {#- -#}
         <button class="sidebar-menu-toggle">&#9776;</button> {#- -#}
-        <a class="sidebar-logo" href="{{page.root_path|safe}}{{krate_with_trailing_slash|safe}}index.html"> {#- -#}
-            <div class="logo-container"> {#- -#}
-            {%- if !layout.logo.is_empty() -%}
-                <img src="{{layout.logo}}" alt="logo"> {#- -#}
-            {%- else -%}
-                <img class="rust-logo" src="{{static_root_path|safe}}{{files.rust_logo_svg}}" alt="logo"> {#- -#}
-            {%- endif -%}
-            </div> {#- -#}
+        <a class="logo-container" href="{{page.root_path|safe}}{{krate_with_trailing_slash|safe}}index.html"> {#- -#}
+        {%- if !layout.logo.is_empty() -%}
+            <img src="{{layout.logo}}" alt="logo"> {#- -#}
+        {%- else -%}
+            <img class="rust-logo" src="{{static_root_path|safe}}{{files.rust_logo_svg}}" alt="logo"> {#- -#}
+        {%- endif -%}
         </a> {#- -#}
         <h2></h2> {#- -#}
     </nav> {#- -#}
     {%- endif -%}
     <nav class="sidebar"> {#- -#}
         {%- if page.css_class != "source" -%}
-        <a class="sidebar-logo" href="{{page.root_path|safe}}{{krate_with_trailing_slash|safe}}index.html"> {#- -#}
-            <div class="logo-container"> {#- -#}
-                {%- if !layout.logo.is_empty()  %}
-                    <img src="{{layout.logo}}" alt="logo"> {#- -#}
-                {%- else -%}
-                    <img class="rust-logo" src="{{static_root_path|safe}}{{files.rust_logo_svg}}" alt="logo"> {#- -#}
-                {%- endif -%}
-            </div> {#- -#}
+        <a class="logo-container" href="{{page.root_path|safe}}{{krate_with_trailing_slash|safe}}index.html"> {#- -#}
+            {%- if !layout.logo.is_empty()  %}
+                <img src="{{layout.logo}}" alt="logo"> {#- -#}
+            {%- else -%}
+                <img class="rust-logo" src="{{static_root_path|safe}}{{files.rust_logo_svg}}" alt="logo"> {#- -#}
+            {%- endif -%}
         </a> {#- -#}
         {%- endif -%}
         {{- sidebar|safe -}}
diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs
index 84af194904d..56283b2c0ef 100644
--- a/src/librustdoc/json/conversions.rs
+++ b/src/librustdoc/json/conversions.rs
@@ -8,8 +8,9 @@ use std::convert::From;
 use std::fmt;
 
 use rustc_ast::ast;
-use rustc_hir::{def::CtorKind, def_id::DefId};
+use rustc_hir::{def::CtorKind, def::DefKind, def_id::DefId};
 use rustc_middle::ty::{self, TyCtxt};
+use rustc_span::symbol::sym;
 use rustc_span::{Pos, Symbol};
 use rustc_target::spec::abi::Abi as RustcAbi;
 
@@ -217,13 +218,27 @@ pub(crate) fn from_item_id_with_name(item_id: ItemId, tcx: TyCtxt<'_>, name: Opt
 
     impl<'a> fmt::Display for DisplayDefId<'a> {
         fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-            let name = match self.2 {
+            let DisplayDefId(def_id, tcx, name) = self;
+            let name = match name {
                 Some(name) => format!(":{}", name.as_u32()),
-                None => self
-                    .1
-                    .opt_item_name(self.0)
-                    .map(|n| format!(":{}", n.as_u32()))
-                    .unwrap_or_default(),
+                None => {
+                    // We need this workaround because primitive types' DefId actually refers to
+                    // their parent module, which isn't present in the output JSON items. So
+                    // instead, we directly get the primitive symbol and convert it to u32 to
+                    // generate the ID.
+                    if matches!(tcx.def_kind(def_id), DefKind::Mod) &&
+                        let Some(prim) = tcx.get_attrs(*def_id, sym::doc)
+                            .flat_map(|attr| attr.meta_item_list().unwrap_or_default())
+                            .filter(|attr| attr.has_name(sym::primitive))
+                            .find_map(|attr| attr.value_str()) {
+                        format!(":{}", prim.as_u32())
+                    } else {
+                        tcx
+                        .opt_item_name(*def_id)
+                        .map(|n| format!(":{}", n.as_u32()))
+                        .unwrap_or_default()
+                    }
+                }
             };
             write!(f, "{}:{}{}", self.0.krate.as_u32(), u32::from(self.0.index), name)
         }
@@ -237,7 +252,7 @@ pub(crate) fn from_item_id_with_name(item_id: ItemId, tcx: TyCtxt<'_>, name: Opt
         ItemId::Auto { for_, trait_ } => {
             Id(format!("a:{}-{}", DisplayDefId(trait_, tcx, None), DisplayDefId(for_, tcx, name)))
         }
-        ItemId::Primitive(ty, krate) => Id(format!("p:{}:{}", krate.as_u32(), ty.as_sym())),
+        ItemId::Primitive(_, _) => unreachable!(),
     }
 }
 
diff --git a/src/librustdoc/passes/check_doc_test_visibility.rs b/src/librustdoc/passes/check_doc_test_visibility.rs
index 057d2fdd9d5..6aa2dda980c 100644
--- a/src/librustdoc/passes/check_doc_test_visibility.rs
+++ b/src/librustdoc/passes/check_doc_test_visibility.rs
@@ -82,7 +82,7 @@ pub(crate) fn should_have_doc_example(cx: &DocContext<'_>, item: &clean::Item) -
     let hir_id = cx.tcx.hir().local_def_id_to_hir_id(item.item_id.expect_def_id().expect_local());
 
     // check if parent is trait impl
-    if let Some(parent_hir_id) = cx.tcx.hir().find_parent_node(hir_id) {
+    if let Some(parent_hir_id) = cx.tcx.hir().opt_parent_id(hir_id) {
         if let Some(parent_node) = cx.tcx.hir().find(parent_hir_id) {
             if matches!(
                 parent_node,
diff --git a/src/librustdoc/passes/stripper.rs b/src/librustdoc/passes/stripper.rs
index bf111133b9f..f8a0d77538d 100644
--- a/src/librustdoc/passes/stripper.rs
+++ b/src/librustdoc/passes/stripper.rs
@@ -248,6 +248,7 @@ pub(crate) struct ImportStripper<'tcx> {
 impl<'tcx> DocFolder for ImportStripper<'tcx> {
     fn fold_item(&mut self, i: Item) -> Option<Item> {
         match *i.kind {
+            clean::ImportItem(imp) if imp.imported_item_is_doc_hidden(self.tcx) => None,
             clean::ExternCrateItem { .. } | clean::ImportItem(..)
                 if i.visibility(self.tcx) != Some(Visibility::Public) =>
             {
diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs
index 310a01194ea..7db47035967 100644
--- a/src/librustdoc/visit_ast.rs
+++ b/src/librustdoc/visit_ast.rs
@@ -410,7 +410,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
 
     /// This method will create a new module and push it onto the "modules stack" then call
     /// `visit_mod_contents`. Once done, it'll remove it from the "modules stack" and instead
-    /// add into into the list of modules of the current module.
+    /// add into the list of modules of the current module.
     fn enter_mod(&mut self, id: hir::HirId, m: &'tcx hir::Mod<'tcx>, name: Symbol) {
         self.modules.push(Module::new(name, id, m.spans.inner_span));
 
diff --git a/src/test/assembly/stack-protector/stack-protector-target-support.rs b/src/test/assembly/stack-protector/stack-protector-target-support.rs
index 2fb62e93ea3..d5b48105ef2 100644
--- a/src/test/assembly/stack-protector/stack-protector-target-support.rs
+++ b/src/test/assembly/stack-protector/stack-protector-target-support.rs
@@ -26,7 +26,7 @@
 // [r9] needs-llvm-components: aarch64
 // [r10] compile-flags: --target aarch64-apple-ios
 // [r10] needs-llvm-components: aarch64
-// [r11] compile-flags: --target aarch64-fuchsia
+// [r11] compile-flags: --target aarch64-unknown-fuchsia
 // [r11] needs-llvm-components: aarch64
 // [r12] compile-flags: --target aarch64-linux-android
 // [r12] needs-llvm-components: aarch64
@@ -156,7 +156,7 @@
 // [r74] needs-llvm-components: x86
 // [r75] compile-flags:--target x86_64-fortanix-unknown-sgx
 // [r75] needs-llvm-components: x86
-// [r76] compile-flags:--target x86_64-fuchsia
+// [r76] compile-flags:--target x86_64-unknown-fuchsia
 // [r76] needs-llvm-components: x86
 // [r77] compile-flags:--target x86_64-linux-android
 // [r77] needs-llvm-components: x86
diff --git a/src/test/codegen/box-maybe-uninit-llvm14.rs b/src/test/codegen/box-maybe-uninit-llvm14.rs
index bd1a6599c33..7b5ae894311 100644
--- a/src/test/codegen/box-maybe-uninit-llvm14.rs
+++ b/src/test/codegen/box-maybe-uninit-llvm14.rs
@@ -2,7 +2,7 @@
 
 // Once we're done with llvm 14 and earlier, this test can be deleted.
 
-#![crate_type="lib"]
+#![crate_type = "lib"]
 
 use std::mem::MaybeUninit;
 
@@ -17,8 +17,16 @@ pub fn box_uninitialized() -> Box<MaybeUninit<usize>> {
     Box::new(MaybeUninit::uninit())
 }
 
-// FIXME: add a test for a bigger box. Currently broken, see
-// https://github.com/rust-lang/rust/issues/58201.
+// https://github.com/rust-lang/rust/issues/58201
+#[no_mangle]
+pub fn box_uninitialized2() -> Box<MaybeUninit<[usize; 1024 * 1024]>> {
+    // CHECK-LABEL: @box_uninitialized2
+    // CHECK-NOT: store
+    // CHECK-NOT: alloca
+    // CHECK-NOT: memcpy
+    // CHECK-NOT: memset
+    Box::new(MaybeUninit::uninit())
+}
 
 // Hide the LLVM 15+ `allocalign` attribute in the declaration of __rust_alloc
 // from the CHECK-NOT above. We don't check the attributes here because we can't rely
diff --git a/src/test/codegen/box-maybe-uninit.rs b/src/test/codegen/box-maybe-uninit.rs
index e105e26f16a..c82b56a71f5 100644
--- a/src/test/codegen/box-maybe-uninit.rs
+++ b/src/test/codegen/box-maybe-uninit.rs
@@ -1,6 +1,6 @@
 // compile-flags: -O
 // min-llvm-version: 15.0
-#![crate_type="lib"]
+#![crate_type = "lib"]
 
 use std::mem::MaybeUninit;
 
@@ -15,8 +15,16 @@ pub fn box_uninitialized() -> Box<MaybeUninit<usize>> {
     Box::new(MaybeUninit::uninit())
 }
 
-// FIXME: add a test for a bigger box. Currently broken, see
-// https://github.com/rust-lang/rust/issues/58201.
+// https://github.com/rust-lang/rust/issues/58201
+#[no_mangle]
+pub fn box_uninitialized2() -> Box<MaybeUninit<[usize; 1024 * 1024]>> {
+    // CHECK-LABEL: @box_uninitialized2
+    // CHECK-NOT: store
+    // CHECK-NOT: alloca
+    // CHECK-NOT: memcpy
+    // CHECK-NOT: memset
+    Box::new(MaybeUninit::uninit())
+}
 
 // Hide the `allocalign` attribute in the declaration of __rust_alloc
 // from the CHECK-NOT above, and also verify the attributes got set reasonably.
diff --git a/src/test/codegen/issue-86106.rs b/src/test/codegen/issue-86106.rs
new file mode 100644
index 00000000000..9ccbcb24f56
--- /dev/null
+++ b/src/test/codegen/issue-86106.rs
@@ -0,0 +1,62 @@
+// min-llvm-version: 15.0
+// compile-flags: -C opt-level=3 -Z merge-functions=disabled
+
+// The below two functions ensure that both `String::new()` and `"".to_string()`
+// produce the identical code.
+
+#![crate_type = "lib"]
+
+// CHECK-LABEL: define void @string_new
+#[no_mangle]
+pub fn string_new() -> String {
+    // CHECK-NOT: load i8
+    // CHECK: store i{{32|64}}
+    // CHECK-NEXT: getelementptr
+    // CHECK-NEXT: store ptr
+    // CHECK-NEXT: getelementptr
+    // CHECK-NEXT: store i{{32|64}}
+    // CHECK-NEXT: ret void
+    String::new()
+}
+
+// CHECK-LABEL: define void @empty_to_string
+#[no_mangle]
+pub fn empty_to_string() -> String {
+    // CHECK-NOT: load i8
+    // CHECK: store i{{32|64}}
+    // CHECK-NEXT: getelementptr
+    // CHECK-NEXT: store ptr
+    // CHECK-NEXT: getelementptr
+    // CHECK-NEXT: store i{{32|64}}
+    // CHECK-NEXT: ret void
+    "".to_string()
+}
+
+// The below two functions ensure that both `vec![]` and `vec![].clone()`
+// produce the identical code.
+
+// CHECK-LABEL: @empty_vec
+#[no_mangle]
+pub fn empty_vec() -> Vec<u8> {
+    // CHECK: store i{{32|64}}
+    // CHECK-NOT: load i8
+    // CHECK-NEXT: getelementptr
+    // CHECK-NEXT: store ptr
+    // CHECK-NEXT: getelementptr
+    // CHECK-NEXT: store i{{32|64}}
+    // CHECK-NEXT: ret void
+    vec![]
+}
+
+// CHECK-LABEL: @empty_vec_clone
+#[no_mangle]
+pub fn empty_vec_clone() -> Vec<u8> {
+    // CHECK: store i{{32|64}}
+    // CHECK-NOT: load i8
+    // CHECK-NEXT: getelementptr
+    // CHECK-NEXT: store ptr
+    // CHECK-NEXT: getelementptr
+    // CHECK-NEXT: store i{{32|64}}
+    // CHECK-NEXT: ret void
+    vec![].clone()
+}
diff --git a/src/test/codegen/noalias-flag.rs b/src/test/codegen/noalias-flag.rs
new file mode 100644
index 00000000000..a9ec61e286d
--- /dev/null
+++ b/src/test/codegen/noalias-flag.rs
@@ -0,0 +1,23 @@
+// compile-flags: -O -Zmutable-noalias=no
+
+#![crate_type = "lib"]
+
+// `-Zmutable-noalias=no` should disable noalias on mut refs...
+
+// CHECK-LABEL: @test_mut_ref(
+// CHECK-NOT: noalias
+// CHECK-SAME: %x
+#[no_mangle]
+pub fn test_mut_ref(x: &mut i32) -> &mut i32 {
+    x
+}
+
+// ...but not on shared refs
+
+// CHECK-LABEL: @test_ref(
+// CHECK-SAME: noalias
+// CHECK-SAME: %x
+#[no_mangle]
+pub fn test_ref(x: &i32) -> &i32 {
+    x
+}
diff --git a/src/test/codegen/zst-offset.rs b/src/test/codegen/zst-offset.rs
index 29d2a1754a3..844d5870a84 100644
--- a/src/test/codegen/zst-offset.rs
+++ b/src/test/codegen/zst-offset.rs
@@ -15,7 +15,7 @@ pub fn helper(_: usize) {
 pub fn scalar_layout(s: &(u64, ())) {
 // CHECK: getelementptr i8, {{.+}}, [[USIZE]] 8
     let x = &s.1;
-    &x; // keep variable in an alloca
+    witness(&x); // keep variable in an alloca
 }
 
 // Check that we correctly generate a GEP for a ZST that is not included in ScalarPair layout
@@ -24,7 +24,7 @@ pub fn scalar_layout(s: &(u64, ())) {
 pub fn scalarpair_layout(s: &(u64, u32, ())) {
 // CHECK: getelementptr i8, {{.+}}, [[USIZE]] 12
     let x = &s.2;
-    &x; // keep variable in an alloca
+    witness(&x); // keep variable in an alloca
 }
 
 #[repr(simd)]
@@ -36,5 +36,8 @@ pub struct U64x4(u64, u64, u64, u64);
 pub fn vector_layout(s: &(U64x4, ())) {
 // CHECK: getelementptr i8, {{.+}}, [[USIZE]] 32
     let x = &s.1;
-    &x; // keep variable in an alloca
+    witness(&x); // keep variable in an alloca
 }
+
+#[inline(never)]
+fn witness(_: &impl Sized) {}
diff --git a/src/test/incremental/hashes/closure_expressions.rs b/src/test/incremental/hashes/closure_expressions.rs
index 7bf99f6112e..927bcd96e6f 100644
--- a/src/test/incremental/hashes/closure_expressions.rs
+++ b/src/test/incremental/hashes/closure_expressions.rs
@@ -42,9 +42,9 @@ pub fn add_parameter() {
 }
 
 #[cfg(not(any(cfail1,cfail4)))]
-#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir, typeck")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, typeck")]
 #[rustc_clean(cfg="cfail3")]
-#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir, typeck")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, typeck")]
 #[rustc_clean(cfg="cfail6")]
 pub fn add_parameter() {
     let x = 0u32;
diff --git a/src/test/mir-opt/const_allocation.main.ConstProp.after.32bit.mir b/src/test/mir-opt/const_allocation.main.ConstProp.after.32bit.mir
index da5a64cac65..6140fc52f65 100644
--- a/src/test/mir-opt/const_allocation.main.ConstProp.after.32bit.mir
+++ b/src/test/mir-opt/const_allocation.main.ConstProp.after.32bit.mir
@@ -10,12 +10,12 @@ fn main() -> () {
         StorageLive(_2);                 // scope 0 at $DIR/const_allocation.rs:+1:5: +1:8
         _2 = const {alloc1: &&[(Option<i32>, &[&str])]}; // scope 0 at $DIR/const_allocation.rs:+1:5: +1:8
                                          // mir::Constant
-                                         // + span: $DIR/const_allocation.rs:8:5: 8:8
+                                         // + span: $DIR/const_allocation.rs:9:5: 9:8
                                          // + literal: Const { ty: &&[(Option<i32>, &[&str])], val: Value(Scalar(alloc1)) }
         _1 = (*_2);                      // scope 0 at $DIR/const_allocation.rs:+1:5: +1:8
         StorageDead(_2);                 // scope 0 at $DIR/const_allocation.rs:+1:8: +1:9
         StorageDead(_1);                 // scope 0 at $DIR/const_allocation.rs:+1:8: +1:9
-        nop;                             // scope 0 at $DIR/const_allocation.rs:+0:11: +2:2
+        _0 = const ();                   // scope 0 at $DIR/const_allocation.rs:+0:11: +2:2
         return;                          // scope 0 at $DIR/const_allocation.rs:+2:2: +2:2
     }
 }
diff --git a/src/test/mir-opt/const_allocation.main.ConstProp.after.64bit.mir b/src/test/mir-opt/const_allocation.main.ConstProp.after.64bit.mir
index febd990681e..b2ed23c6873 100644
--- a/src/test/mir-opt/const_allocation.main.ConstProp.after.64bit.mir
+++ b/src/test/mir-opt/const_allocation.main.ConstProp.after.64bit.mir
@@ -10,12 +10,12 @@ fn main() -> () {
         StorageLive(_2);                 // scope 0 at $DIR/const_allocation.rs:+1:5: +1:8
         _2 = const {alloc1: &&[(Option<i32>, &[&str])]}; // scope 0 at $DIR/const_allocation.rs:+1:5: +1:8
                                          // mir::Constant
-                                         // + span: $DIR/const_allocation.rs:8:5: 8:8
+                                         // + span: $DIR/const_allocation.rs:9:5: 9:8
                                          // + literal: Const { ty: &&[(Option<i32>, &[&str])], val: Value(Scalar(alloc1)) }
         _1 = (*_2);                      // scope 0 at $DIR/const_allocation.rs:+1:5: +1:8
         StorageDead(_2);                 // scope 0 at $DIR/const_allocation.rs:+1:8: +1:9
         StorageDead(_1);                 // scope 0 at $DIR/const_allocation.rs:+1:8: +1:9
-        nop;                             // scope 0 at $DIR/const_allocation.rs:+0:11: +2:2
+        _0 = const ();                   // scope 0 at $DIR/const_allocation.rs:+0:11: +2:2
         return;                          // scope 0 at $DIR/const_allocation.rs:+2:2: +2:2
     }
 }
diff --git a/src/test/mir-opt/const_allocation.rs b/src/test/mir-opt/const_allocation.rs
index b0fcb86fcee..91a2455eb83 100644
--- a/src/test/mir-opt/const_allocation.rs
+++ b/src/test/mir-opt/const_allocation.rs
@@ -1,3 +1,4 @@
+// unit-test: ConstProp
 // ignore-endian-big
 // EMIT_MIR_FOR_EACH_BIT_WIDTH
 static FOO: &[(Option<i32>, &[&str])] =
diff --git a/src/test/mir-opt/const_allocation2.main.ConstProp.after.32bit.mir b/src/test/mir-opt/const_allocation2.main.ConstProp.after.32bit.mir
index 389641f20f4..aab005c52d6 100644
--- a/src/test/mir-opt/const_allocation2.main.ConstProp.after.32bit.mir
+++ b/src/test/mir-opt/const_allocation2.main.ConstProp.after.32bit.mir
@@ -10,12 +10,12 @@ fn main() -> () {
         StorageLive(_2);                 // scope 0 at $DIR/const_allocation2.rs:+1:5: +1:8
         _2 = const {alloc1: &&[(Option<i32>, &[&u8])]}; // scope 0 at $DIR/const_allocation2.rs:+1:5: +1:8
                                          // mir::Constant
-                                         // + span: $DIR/const_allocation2.rs:5:5: 5:8
+                                         // + span: $DIR/const_allocation2.rs:6:5: 6:8
                                          // + literal: Const { ty: &&[(Option<i32>, &[&u8])], val: Value(Scalar(alloc1)) }
         _1 = (*_2);                      // scope 0 at $DIR/const_allocation2.rs:+1:5: +1:8
         StorageDead(_2);                 // scope 0 at $DIR/const_allocation2.rs:+1:8: +1:9
         StorageDead(_1);                 // scope 0 at $DIR/const_allocation2.rs:+1:8: +1:9
-        nop;                             // scope 0 at $DIR/const_allocation2.rs:+0:11: +2:2
+        _0 = const ();                   // scope 0 at $DIR/const_allocation2.rs:+0:11: +2:2
         return;                          // scope 0 at $DIR/const_allocation2.rs:+2:2: +2:2
     }
 }
diff --git a/src/test/mir-opt/const_allocation2.main.ConstProp.after.64bit.mir b/src/test/mir-opt/const_allocation2.main.ConstProp.after.64bit.mir
index ce3848e9216..0eff9474c20 100644
--- a/src/test/mir-opt/const_allocation2.main.ConstProp.after.64bit.mir
+++ b/src/test/mir-opt/const_allocation2.main.ConstProp.after.64bit.mir
@@ -10,12 +10,12 @@ fn main() -> () {
         StorageLive(_2);                 // scope 0 at $DIR/const_allocation2.rs:+1:5: +1:8
         _2 = const {alloc1: &&[(Option<i32>, &[&u8])]}; // scope 0 at $DIR/const_allocation2.rs:+1:5: +1:8
                                          // mir::Constant
-                                         // + span: $DIR/const_allocation2.rs:5:5: 5:8
+                                         // + span: $DIR/const_allocation2.rs:6:5: 6:8
                                          // + literal: Const { ty: &&[(Option<i32>, &[&u8])], val: Value(Scalar(alloc1)) }
         _1 = (*_2);                      // scope 0 at $DIR/const_allocation2.rs:+1:5: +1:8
         StorageDead(_2);                 // scope 0 at $DIR/const_allocation2.rs:+1:8: +1:9
         StorageDead(_1);                 // scope 0 at $DIR/const_allocation2.rs:+1:8: +1:9
-        nop;                             // scope 0 at $DIR/const_allocation2.rs:+0:11: +2:2
+        _0 = const ();                   // scope 0 at $DIR/const_allocation2.rs:+0:11: +2:2
         return;                          // scope 0 at $DIR/const_allocation2.rs:+2:2: +2:2
     }
 }
diff --git a/src/test/mir-opt/const_allocation2.rs b/src/test/mir-opt/const_allocation2.rs
index 30afedffb39..f2870aa47c5 100644
--- a/src/test/mir-opt/const_allocation2.rs
+++ b/src/test/mir-opt/const_allocation2.rs
@@ -1,3 +1,4 @@
+// unit-test: ConstProp
 // ignore-endian-big
 // EMIT_MIR_FOR_EACH_BIT_WIDTH
 // EMIT_MIR const_allocation2.main.ConstProp.after.mir
diff --git a/src/test/mir-opt/const_allocation3.main.ConstProp.after.32bit.mir b/src/test/mir-opt/const_allocation3.main.ConstProp.after.32bit.mir
index b72519159d7..55c6db5d0ce 100644
--- a/src/test/mir-opt/const_allocation3.main.ConstProp.after.32bit.mir
+++ b/src/test/mir-opt/const_allocation3.main.ConstProp.after.32bit.mir
@@ -10,12 +10,12 @@ fn main() -> () {
         StorageLive(_2);                 // scope 0 at $DIR/const_allocation3.rs:+1:5: +1:8
         _2 = const {alloc1: &&Packed};   // scope 0 at $DIR/const_allocation3.rs:+1:5: +1:8
                                          // mir::Constant
-                                         // + span: $DIR/const_allocation3.rs:5:5: 5:8
+                                         // + span: $DIR/const_allocation3.rs:6:5: 6:8
                                          // + literal: Const { ty: &&Packed, val: Value(Scalar(alloc1)) }
         _1 = (*_2);                      // scope 0 at $DIR/const_allocation3.rs:+1:5: +1:8
         StorageDead(_2);                 // scope 0 at $DIR/const_allocation3.rs:+1:8: +1:9
         StorageDead(_1);                 // scope 0 at $DIR/const_allocation3.rs:+1:8: +1:9
-        nop;                             // scope 0 at $DIR/const_allocation3.rs:+0:11: +2:2
+        _0 = const ();                   // scope 0 at $DIR/const_allocation3.rs:+0:11: +2:2
         return;                          // scope 0 at $DIR/const_allocation3.rs:+2:2: +2:2
     }
 }
diff --git a/src/test/mir-opt/const_allocation3.main.ConstProp.after.64bit.mir b/src/test/mir-opt/const_allocation3.main.ConstProp.after.64bit.mir
index 6bd047c7d9f..27492a7fd22 100644
--- a/src/test/mir-opt/const_allocation3.main.ConstProp.after.64bit.mir
+++ b/src/test/mir-opt/const_allocation3.main.ConstProp.after.64bit.mir
@@ -10,12 +10,12 @@ fn main() -> () {
         StorageLive(_2);                 // scope 0 at $DIR/const_allocation3.rs:+1:5: +1:8
         _2 = const {alloc1: &&Packed};   // scope 0 at $DIR/const_allocation3.rs:+1:5: +1:8
                                          // mir::Constant
-                                         // + span: $DIR/const_allocation3.rs:5:5: 5:8
+                                         // + span: $DIR/const_allocation3.rs:6:5: 6:8
                                          // + literal: Const { ty: &&Packed, val: Value(Scalar(alloc1)) }
         _1 = (*_2);                      // scope 0 at $DIR/const_allocation3.rs:+1:5: +1:8
         StorageDead(_2);                 // scope 0 at $DIR/const_allocation3.rs:+1:8: +1:9
         StorageDead(_1);                 // scope 0 at $DIR/const_allocation3.rs:+1:8: +1:9
-        nop;                             // scope 0 at $DIR/const_allocation3.rs:+0:11: +2:2
+        _0 = const ();                   // scope 0 at $DIR/const_allocation3.rs:+0:11: +2:2
         return;                          // scope 0 at $DIR/const_allocation3.rs:+2:2: +2:2
     }
 }
diff --git a/src/test/mir-opt/const_allocation3.rs b/src/test/mir-opt/const_allocation3.rs
index ddeb32ab9a5..da3fd089b02 100644
--- a/src/test/mir-opt/const_allocation3.rs
+++ b/src/test/mir-opt/const_allocation3.rs
@@ -1,3 +1,4 @@
+// unit-test: ConstProp
 // ignore-endian-big
 // EMIT_MIR_FOR_EACH_BIT_WIDTH
 // EMIT_MIR const_allocation3.main.ConstProp.after.mir
diff --git a/src/test/mir-opt/const_debuginfo.main.ConstDebugInfo.diff b/src/test/mir-opt/const_debuginfo.main.ConstDebugInfo.diff
index e959e1b2f2c..dd548adde7e 100644
--- a/src/test/mir-opt/const_debuginfo.main.ConstDebugInfo.diff
+++ b/src/test/mir-opt/const_debuginfo.main.ConstDebugInfo.diff
@@ -8,8 +8,8 @@
       let mut _6: u8;                      // in scope 0 at $DIR/const_debuginfo.rs:+4:15: +4:16
       let mut _7: u8;                      // in scope 0 at $DIR/const_debuginfo.rs:+4:19: +4:20
       let mut _8: u8;                      // in scope 0 at $DIR/const_debuginfo.rs:+4:23: +4:24
-      let mut _14: u32;                    // in scope 0 at $DIR/const_debuginfo.rs:+13:13: +13:16
-      let mut _15: u32;                    // in scope 0 at $DIR/const_debuginfo.rs:+13:19: +13:22
+      let mut _12: u32;                    // in scope 0 at $DIR/const_debuginfo.rs:+13:13: +13:16
+      let mut _13: u32;                    // in scope 0 at $DIR/const_debuginfo.rs:+13:19: +13:22
       scope 1 {
 -         debug x => _1;                   // in scope 1 at $DIR/const_debuginfo.rs:+1:9: +1:10
 +         debug x => const 1_u8;           // in scope 1 at $DIR/const_debuginfo.rs:+1:9: +1:10
@@ -29,23 +29,21 @@
                       scope 5 {
 -                         debug s => _9;   // in scope 5 at $DIR/const_debuginfo.rs:+6:9: +6:10
 +                         debug s => const "hello, world!"; // in scope 5 at $DIR/const_debuginfo.rs:+6:9: +6:10
-                          let _10: (bool, bool, u32); // in scope 5 at $DIR/const_debuginfo.rs:+8:9: +8:10
-                          let _16: bool;   // in scope 5 at $DIR/const_debuginfo.rs:+8:9: +8:10
-                          let _17: bool;   // in scope 5 at $DIR/const_debuginfo.rs:+8:9: +8:10
-                          let _18: u32;    // in scope 5 at $DIR/const_debuginfo.rs:+8:9: +8:10
+                          let _14: bool;   // in scope 5 at $DIR/const_debuginfo.rs:+8:9: +8:10
+                          let _15: bool;   // in scope 5 at $DIR/const_debuginfo.rs:+8:9: +8:10
+                          let _16: u32;    // in scope 5 at $DIR/const_debuginfo.rs:+8:9: +8:10
                           scope 6 {
-                              debug f => (bool, bool, u32){ .0 => _16, .1 => _17, .2 => _18, }; // in scope 6 at $DIR/const_debuginfo.rs:+8:9: +8:10
-                              let _11: std::option::Option<u16>; // in scope 6 at $DIR/const_debuginfo.rs:+10:9: +10:10
+                              debug f => (bool, bool, u32){ .0 => _14, .1 => _15, .2 => _16, }; // in scope 6 at $DIR/const_debuginfo.rs:+8:9: +8:10
+                              let _10: std::option::Option<u16>; // in scope 6 at $DIR/const_debuginfo.rs:+10:9: +10:10
                               scope 7 {
-                                  debug o => _11; // in scope 7 at $DIR/const_debuginfo.rs:+10:9: +10:10
-                                  let _12: Point; // in scope 7 at $DIR/const_debuginfo.rs:+12:9: +12:10
-                                  let _19: u32; // in scope 7 at $DIR/const_debuginfo.rs:+12:9: +12:10
-                                  let _20: u32; // in scope 7 at $DIR/const_debuginfo.rs:+12:9: +12:10
+                                  debug o => _10; // in scope 7 at $DIR/const_debuginfo.rs:+10:9: +10:10
+                                  let _17: u32; // in scope 7 at $DIR/const_debuginfo.rs:+12:9: +12:10
+                                  let _18: u32; // in scope 7 at $DIR/const_debuginfo.rs:+12:9: +12:10
                                   scope 8 {
-                                      debug p => Point{ .0 => _19, .1 => _20, }; // in scope 8 at $DIR/const_debuginfo.rs:+12:9: +12:10
-                                      let _13: u32; // in scope 8 at $DIR/const_debuginfo.rs:+13:9: +13:10
+                                      debug p => Point{ .0 => _17, .1 => _18, }; // in scope 8 at $DIR/const_debuginfo.rs:+12:9: +12:10
+                                      let _11: u32; // in scope 8 at $DIR/const_debuginfo.rs:+13:9: +13:10
                                       scope 9 {
--                                         debug a => _13; // in scope 9 at $DIR/const_debuginfo.rs:+13:9: +13:10
+-                                         debug a => _11; // in scope 9 at $DIR/const_debuginfo.rs:+13:9: +13:10
 +                                         debug a => const 64_u32; // in scope 9 at $DIR/const_debuginfo.rs:+13:9: +13:10
                                       }
                                   }
@@ -83,41 +81,40 @@
                                            // mir::Constant
                                            // + span: $DIR/const_debuginfo.rs:14:13: 14:28
                                            // + literal: Const { ty: &str, val: Value(Slice(..)) }
+          StorageLive(_14);                // scope 5 at $DIR/const_debuginfo.rs:+8:9: +8:10
+          StorageLive(_15);                // scope 5 at $DIR/const_debuginfo.rs:+8:9: +8:10
           StorageLive(_16);                // scope 5 at $DIR/const_debuginfo.rs:+8:9: +8:10
-          StorageLive(_17);                // scope 5 at $DIR/const_debuginfo.rs:+8:9: +8:10
-          StorageLive(_18);                // scope 5 at $DIR/const_debuginfo.rs:+8:9: +8:10
+          Deinit(_14);                     // scope 5 at $DIR/const_debuginfo.rs:+8:13: +8:34
+          Deinit(_15);                     // scope 5 at $DIR/const_debuginfo.rs:+8:13: +8:34
           Deinit(_16);                     // scope 5 at $DIR/const_debuginfo.rs:+8:13: +8:34
-          Deinit(_17);                     // scope 5 at $DIR/const_debuginfo.rs:+8:13: +8:34
-          Deinit(_18);                     // scope 5 at $DIR/const_debuginfo.rs:+8:13: +8:34
-          _16 = const true;                // scope 5 at $DIR/const_debuginfo.rs:+8:13: +8:34
-          _17 = const false;               // scope 5 at $DIR/const_debuginfo.rs:+8:13: +8:34
-          _18 = const 123_u32;             // scope 5 at $DIR/const_debuginfo.rs:+8:13: +8:34
-          StorageLive(_11);                // scope 6 at $DIR/const_debuginfo.rs:+10:9: +10:10
-          Deinit(_11);                     // scope 6 at $DIR/const_debuginfo.rs:+10:13: +10:24
-          ((_11 as Some).0: u16) = const 99_u16; // scope 6 at $DIR/const_debuginfo.rs:+10:13: +10:24
-          discriminant(_11) = 1;           // scope 6 at $DIR/const_debuginfo.rs:+10:13: +10:24
-          StorageLive(_19);                // scope 7 at $DIR/const_debuginfo.rs:+12:9: +12:10
-          StorageLive(_20);                // scope 7 at $DIR/const_debuginfo.rs:+12:9: +12:10
-          Deinit(_19);                     // scope 7 at $DIR/const_debuginfo.rs:+12:13: +12:35
-          Deinit(_20);                     // scope 7 at $DIR/const_debuginfo.rs:+12:13: +12:35
-          _19 = const 32_u32;              // scope 7 at $DIR/const_debuginfo.rs:+12:13: +12:35
-          _20 = const 32_u32;              // scope 7 at $DIR/const_debuginfo.rs:+12:13: +12:35
-          StorageLive(_13);                // scope 8 at $DIR/const_debuginfo.rs:+13:9: +13:10
-          StorageLive(_14);                // scope 8 at $DIR/const_debuginfo.rs:+13:13: +13:16
-          _14 = const 32_u32;              // scope 8 at $DIR/const_debuginfo.rs:+13:13: +13:16
-          StorageLive(_15);                // scope 8 at $DIR/const_debuginfo.rs:+13:19: +13:22
-          _15 = const 32_u32;              // scope 8 at $DIR/const_debuginfo.rs:+13:19: +13:22
-          _13 = const 64_u32;              // scope 8 at $DIR/const_debuginfo.rs:+13:13: +13:22
-          StorageDead(_15);                // scope 8 at $DIR/const_debuginfo.rs:+13:21: +13:22
-          StorageDead(_14);                // scope 8 at $DIR/const_debuginfo.rs:+13:21: +13:22
-          nop;                             // scope 0 at $DIR/const_debuginfo.rs:+0:11: +14:2
-          StorageDead(_13);                // scope 8 at $DIR/const_debuginfo.rs:+14:1: +14:2
-          StorageDead(_19);                // scope 7 at $DIR/const_debuginfo.rs:+14:1: +14:2
-          StorageDead(_20);                // scope 7 at $DIR/const_debuginfo.rs:+14:1: +14:2
-          StorageDead(_11);                // scope 6 at $DIR/const_debuginfo.rs:+14:1: +14:2
+          _14 = const true;                // scope 5 at $DIR/const_debuginfo.rs:+8:13: +8:34
+          _15 = const false;               // scope 5 at $DIR/const_debuginfo.rs:+8:13: +8:34
+          _16 = const 123_u32;             // scope 5 at $DIR/const_debuginfo.rs:+8:13: +8:34
+          StorageLive(_10);                // scope 6 at $DIR/const_debuginfo.rs:+10:9: +10:10
+          Deinit(_10);                     // scope 6 at $DIR/const_debuginfo.rs:+10:13: +10:24
+          ((_10 as Some).0: u16) = const 99_u16; // scope 6 at $DIR/const_debuginfo.rs:+10:13: +10:24
+          discriminant(_10) = 1;           // scope 6 at $DIR/const_debuginfo.rs:+10:13: +10:24
+          StorageLive(_17);                // scope 7 at $DIR/const_debuginfo.rs:+12:9: +12:10
+          StorageLive(_18);                // scope 7 at $DIR/const_debuginfo.rs:+12:9: +12:10
+          Deinit(_17);                     // scope 7 at $DIR/const_debuginfo.rs:+12:13: +12:35
+          Deinit(_18);                     // scope 7 at $DIR/const_debuginfo.rs:+12:13: +12:35
+          _17 = const 32_u32;              // scope 7 at $DIR/const_debuginfo.rs:+12:13: +12:35
+          _18 = const 32_u32;              // scope 7 at $DIR/const_debuginfo.rs:+12:13: +12:35
+          StorageLive(_11);                // scope 8 at $DIR/const_debuginfo.rs:+13:9: +13:10
+          StorageLive(_12);                // scope 8 at $DIR/const_debuginfo.rs:+13:13: +13:16
+          _12 = const 32_u32;              // scope 8 at $DIR/const_debuginfo.rs:+13:13: +13:16
+          StorageLive(_13);                // scope 8 at $DIR/const_debuginfo.rs:+13:19: +13:22
+          _13 = const 32_u32;              // scope 8 at $DIR/const_debuginfo.rs:+13:19: +13:22
+          _11 = const 64_u32;              // scope 8 at $DIR/const_debuginfo.rs:+13:13: +13:22
+          StorageDead(_13);                // scope 8 at $DIR/const_debuginfo.rs:+13:21: +13:22
+          StorageDead(_12);                // scope 8 at $DIR/const_debuginfo.rs:+13:21: +13:22
+          StorageDead(_11);                // scope 8 at $DIR/const_debuginfo.rs:+14:1: +14:2
+          StorageDead(_17);                // scope 7 at $DIR/const_debuginfo.rs:+14:1: +14:2
+          StorageDead(_18);                // scope 7 at $DIR/const_debuginfo.rs:+14:1: +14:2
+          StorageDead(_10);                // scope 6 at $DIR/const_debuginfo.rs:+14:1: +14:2
+          StorageDead(_14);                // scope 5 at $DIR/const_debuginfo.rs:+14:1: +14:2
+          StorageDead(_15);                // scope 5 at $DIR/const_debuginfo.rs:+14:1: +14:2
           StorageDead(_16);                // scope 5 at $DIR/const_debuginfo.rs:+14:1: +14:2
-          StorageDead(_17);                // scope 5 at $DIR/const_debuginfo.rs:+14:1: +14:2
-          StorageDead(_18);                // scope 5 at $DIR/const_debuginfo.rs:+14:1: +14:2
           StorageDead(_9);                 // scope 4 at $DIR/const_debuginfo.rs:+14:1: +14:2
           StorageDead(_4);                 // scope 3 at $DIR/const_debuginfo.rs:+14:1: +14:2
           StorageDead(_3);                 // scope 2 at $DIR/const_debuginfo.rs:+14:1: +14:2
diff --git a/src/test/mir-opt/const_prop/bad_op_mod_by_zero.main.ConstProp.diff b/src/test/mir-opt/const_prop/bad_op_mod_by_zero.main.ConstProp.diff
index 22151304259..8485703e39f 100644
--- a/src/test/mir-opt/const_prop/bad_op_mod_by_zero.main.ConstProp.diff
+++ b/src/test/mir-opt/const_prop/bad_op_mod_by_zero.main.ConstProp.diff
@@ -45,7 +45,6 @@
 -         _2 = Rem(const 1_i32, move _3);  // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:14: +2:19
 +         _2 = Rem(const 1_i32, const 0_i32); // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:14: +2:19
           StorageDead(_3);                 // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:18: +2:19
-          nop;                             // scope 0 at $DIR/bad_op_mod_by_zero.rs:+0:11: +3:2
           StorageDead(_2);                 // scope 1 at $DIR/bad_op_mod_by_zero.rs:+3:1: +3:2
           StorageDead(_1);                 // scope 0 at $DIR/bad_op_mod_by_zero.rs:+3:1: +3:2
           return;                          // scope 0 at $DIR/bad_op_mod_by_zero.rs:+3:2: +3:2
diff --git a/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.32bit.diff b/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.32bit.diff
index c27b19679a8..27e41d4869d 100644
--- a/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.32bit.diff
+++ b/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.32bit.diff
@@ -6,17 +6,16 @@
       let _1: *const [i32];                // in scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:9: +1:10
       let mut _2: *const [i32; 3];         // in scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35
       let _3: &[i32; 3];                   // in scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35
-      let _4: [i32; 3];                    // in scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:26: +1:35
-      let _6: usize;                       // in scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:23: +3:24
-      let mut _7: usize;                   // in scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25
-      let mut _8: bool;                    // in scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25
-      let mut _9: &[i32; 3];               // in scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35
+      let _5: usize;                       // in scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:23: +3:24
+      let mut _6: usize;                   // in scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25
+      let mut _7: bool;                    // in scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25
+      let mut _8: &[i32; 3];               // in scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35
       scope 1 {
           debug a => _1;                   // in scope 1 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:9: +1:10
           scope 2 {
-              let _5: i32;                 // in scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:13: +3:15
+              let _4: i32;                 // in scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:13: +3:15
               scope 3 {
-                  debug _b => _5;          // in scope 3 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:13: +3:15
+                  debug _b => _4;          // in scope 3 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:13: +3:15
               }
           }
       }
@@ -25,30 +24,29 @@
           StorageLive(_1);                 // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:9: +1:10
           StorageLive(_2);                 // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35
           StorageLive(_3);                 // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35
-          _9 = const _;                    // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35
+          _8 = const _;                    // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35
                                            // mir::Constant
                                            // + span: $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35
                                            // + literal: Const { ty: &[i32; 3], val: Unevaluated(main, [], Some(promoted[0])) }
-          _3 = _9;                         // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35
+          _3 = _8;                         // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35
           _2 = &raw const (*_3);           // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35
           _1 = move _2 as *const [i32] (Pointer(Unsize)); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35
           StorageDead(_2);                 // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:34: +1:35
           StorageDead(_3);                 // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:35: +1:36
-          StorageLive(_5);                 // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:13: +3:15
-          StorageLive(_6);                 // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:23: +3:24
-          _6 = const 3_usize;              // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:23: +3:24
-          _7 = Len((*_1));                 // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25
--         _8 = Lt(_6, _7);                 // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25
--         assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, _6) -> bb1; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25
-+         _8 = Lt(const 3_usize, _7);      // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25
-+         assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, const 3_usize) -> bb1; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25
+          StorageLive(_4);                 // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:13: +3:15
+          StorageLive(_5);                 // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:23: +3:24
+          _5 = const 3_usize;              // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:23: +3:24
+          _6 = Len((*_1));                 // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25
+-         _7 = Lt(_5, _6);                 // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25
+-         assert(move _7, "index out of bounds: the length is {} but the index is {}", move _6, _5) -> bb1; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25
++         _7 = Lt(const 3_usize, _6);      // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25
++         assert(move _7, "index out of bounds: the length is {} but the index is {}", move _6, const 3_usize) -> bb1; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25
       }
   
       bb1: {
-          _5 = (*_1)[_6];                  // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25
-          StorageDead(_6);                 // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:25: +3:26
-          nop;                             // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+2:5: +4:6
-          StorageDead(_5);                 // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+4:5: +4:6
+          _4 = (*_1)[_5];                  // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25
+          StorageDead(_5);                 // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:25: +3:26
+          StorageDead(_4);                 // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+4:5: +4:6
           StorageDead(_1);                 // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+5:1: +5:2
           return;                          // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+5:2: +5:2
       }
diff --git a/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.64bit.diff b/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.64bit.diff
index c27b19679a8..27e41d4869d 100644
--- a/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.64bit.diff
+++ b/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.64bit.diff
@@ -6,17 +6,16 @@
       let _1: *const [i32];                // in scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:9: +1:10
       let mut _2: *const [i32; 3];         // in scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35
       let _3: &[i32; 3];                   // in scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35
-      let _4: [i32; 3];                    // in scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:26: +1:35
-      let _6: usize;                       // in scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:23: +3:24
-      let mut _7: usize;                   // in scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25
-      let mut _8: bool;                    // in scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25
-      let mut _9: &[i32; 3];               // in scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35
+      let _5: usize;                       // in scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:23: +3:24
+      let mut _6: usize;                   // in scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25
+      let mut _7: bool;                    // in scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25
+      let mut _8: &[i32; 3];               // in scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35
       scope 1 {
           debug a => _1;                   // in scope 1 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:9: +1:10
           scope 2 {
-              let _5: i32;                 // in scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:13: +3:15
+              let _4: i32;                 // in scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:13: +3:15
               scope 3 {
-                  debug _b => _5;          // in scope 3 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:13: +3:15
+                  debug _b => _4;          // in scope 3 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:13: +3:15
               }
           }
       }
@@ -25,30 +24,29 @@
           StorageLive(_1);                 // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:9: +1:10
           StorageLive(_2);                 // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35
           StorageLive(_3);                 // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35
-          _9 = const _;                    // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35
+          _8 = const _;                    // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35
                                            // mir::Constant
                                            // + span: $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35
                                            // + literal: Const { ty: &[i32; 3], val: Unevaluated(main, [], Some(promoted[0])) }
-          _3 = _9;                         // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35
+          _3 = _8;                         // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35
           _2 = &raw const (*_3);           // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35
           _1 = move _2 as *const [i32] (Pointer(Unsize)); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35
           StorageDead(_2);                 // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:34: +1:35
           StorageDead(_3);                 // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:35: +1:36
-          StorageLive(_5);                 // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:13: +3:15
-          StorageLive(_6);                 // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:23: +3:24
-          _6 = const 3_usize;              // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:23: +3:24
-          _7 = Len((*_1));                 // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25
--         _8 = Lt(_6, _7);                 // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25
--         assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, _6) -> bb1; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25
-+         _8 = Lt(const 3_usize, _7);      // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25
-+         assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, const 3_usize) -> bb1; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25
+          StorageLive(_4);                 // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:13: +3:15
+          StorageLive(_5);                 // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:23: +3:24
+          _5 = const 3_usize;              // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:23: +3:24
+          _6 = Len((*_1));                 // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25
+-         _7 = Lt(_5, _6);                 // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25
+-         assert(move _7, "index out of bounds: the length is {} but the index is {}", move _6, _5) -> bb1; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25
++         _7 = Lt(const 3_usize, _6);      // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25
++         assert(move _7, "index out of bounds: the length is {} but the index is {}", move _6, const 3_usize) -> bb1; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25
       }
   
       bb1: {
-          _5 = (*_1)[_6];                  // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25
-          StorageDead(_6);                 // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:25: +3:26
-          nop;                             // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+2:5: +4:6
-          StorageDead(_5);                 // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+4:5: +4:6
+          _4 = (*_1)[_5];                  // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25
+          StorageDead(_5);                 // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:25: +3:26
+          StorageDead(_4);                 // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+4:5: +4:6
           StorageDead(_1);                 // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+5:1: +5:2
           return;                          // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+5:2: +5:2
       }
diff --git a/src/test/mir-opt/const_prop/control_flow_simplification.hello.ConstProp.diff b/src/test/mir-opt/const_prop/control_flow_simplification.hello.ConstProp.diff
index 147670f8a91..f270ab8b69f 100644
--- a/src/test/mir-opt/const_prop/control_flow_simplification.hello.ConstProp.diff
+++ b/src/test/mir-opt/const_prop/control_flow_simplification.hello.ConstProp.diff
@@ -25,7 +25,6 @@
       }
   
       bb2: {
-          nop;                             // scope 0 at $DIR/control_flow_simplification.rs:+3:6: +3:6
           StorageDead(_1);                 // scope 0 at $DIR/control_flow_simplification.rs:+3:5: +3:6
           return;                          // scope 0 at $DIR/control_flow_simplification.rs:+4:2: +4:2
       }
diff --git a/src/test/mir-opt/const_prop/invalid_constant.main.ConstProp.diff b/src/test/mir-opt/const_prop/invalid_constant.main.ConstProp.diff
index 67a4dc3c092..6c4757c1a81 100644
--- a/src/test/mir-opt/const_prop/invalid_constant.main.ConstProp.diff
+++ b/src/test/mir-opt/const_prop/invalid_constant.main.ConstProp.diff
@@ -7,8 +7,6 @@
       let mut _2: main::InvalidChar;       // in scope 0 at $DIR/invalid_constant.rs:+6:34: +6:63
       let mut _4: E;                       // in scope 0 at $DIR/invalid_constant.rs:+13:25: +13:59
       let mut _5: main::InvalidTag;        // in scope 0 at $DIR/invalid_constant.rs:+13:34: +13:55
-      let mut _7: Empty;                   // in scope 0 at $DIR/invalid_constant.rs:+20:35: +20:73
-      let mut _8: main::NoVariants;        // in scope 0 at $DIR/invalid_constant.rs:+20:44: +20:65
       scope 1 {
           debug _invalid_char => _1;       // in scope 1 at $DIR/invalid_constant.rs:+6:9: +6:22
           let _3: [E; 1];                  // in scope 1 at $DIR/invalid_constant.rs:+13:9: +13:21
@@ -17,9 +15,9 @@
               let _6: [Empty; 1];          // in scope 3 at $DIR/invalid_constant.rs:+20:9: +20:31
               scope 5 {
                   debug _enum_without_variants => _6; // in scope 5 at $DIR/invalid_constant.rs:+20:9: +20:31
-                  let _9: main::Str<"���">; // in scope 5 at $DIR/invalid_constant.rs:+24:9: +24:22
+                  let _7: main::Str<"���">; // in scope 5 at $DIR/invalid_constant.rs:+24:9: +24:22
                   scope 7 {
-                      debug _non_utf8_str => _9; // in scope 7 at $DIR/invalid_constant.rs:+24:9: +24:22
+                      debug _non_utf8_str => _7; // in scope 7 at $DIR/invalid_constant.rs:+24:9: +24:22
                   }
               }
               scope 6 {
@@ -57,17 +55,8 @@
           StorageDead(_4);                 // scope 1 at $DIR/invalid_constant.rs:+13:59: +13:60
           StorageDead(_5);                 // scope 1 at $DIR/invalid_constant.rs:+13:60: +13:61
           StorageLive(_6);                 // scope 3 at $DIR/invalid_constant.rs:+20:9: +20:31
-          StorageLive(_7);                 // scope 3 at $DIR/invalid_constant.rs:+20:35: +20:73
-          StorageLive(_8);                 // scope 6 at $DIR/invalid_constant.rs:+20:44: +20:65
-          Deinit(_8);                      // scope 6 at $DIR/invalid_constant.rs:+20:44: +20:65
-          (_8.0: u32) = const 0_u32;       // scope 6 at $DIR/invalid_constant.rs:+20:44: +20:65
-          nop;                             // scope 6 at $DIR/invalid_constant.rs:+20:44: +20:71
-          nop;                             // scope 3 at $DIR/invalid_constant.rs:+20:34: +20:74
-          StorageDead(_7);                 // scope 3 at $DIR/invalid_constant.rs:+20:73: +20:74
-          StorageDead(_8);                 // scope 3 at $DIR/invalid_constant.rs:+20:74: +20:75
-          StorageLive(_9);                 // scope 5 at $DIR/invalid_constant.rs:+24:9: +24:22
-          nop;                             // scope 0 at $DIR/invalid_constant.rs:+0:11: +27:2
-          StorageDead(_9);                 // scope 5 at $DIR/invalid_constant.rs:+27:1: +27:2
+          StorageLive(_7);                 // scope 5 at $DIR/invalid_constant.rs:+24:9: +24:22
+          StorageDead(_7);                 // scope 5 at $DIR/invalid_constant.rs:+27:1: +27:2
           StorageDead(_6);                 // scope 3 at $DIR/invalid_constant.rs:+27:1: +27:2
           StorageDead(_3);                 // scope 1 at $DIR/invalid_constant.rs:+27:1: +27:2
           StorageDead(_1);                 // scope 0 at $DIR/invalid_constant.rs:+27:1: +27:2
diff --git a/src/test/mir-opt/const_prop/issue_66971.main.ConstProp.diff b/src/test/mir-opt/const_prop/issue_66971.main.ConstProp.diff
index 7d8e647cbce..488e772d0ea 100644
--- a/src/test/mir-opt/const_prop/issue_66971.main.ConstProp.diff
+++ b/src/test/mir-opt/const_prop/issue_66971.main.ConstProp.diff
@@ -5,18 +5,13 @@
       let mut _0: ();                      // return place in scope 0 at $DIR/issue_66971.rs:+0:11: +0:11
       let _1: ();                          // in scope 0 at $DIR/issue_66971.rs:+1:5: +1:23
       let mut _2: ((), u8, u8);            // in scope 0 at $DIR/issue_66971.rs:+1:12: +1:22
-      let mut _3: ();                      // in scope 0 at $DIR/issue_66971.rs:+1:13: +1:15
   
       bb0: {
           StorageLive(_1);                 // scope 0 at $DIR/issue_66971.rs:+1:5: +1:23
           StorageLive(_2);                 // scope 0 at $DIR/issue_66971.rs:+1:12: +1:22
-          StorageLive(_3);                 // scope 0 at $DIR/issue_66971.rs:+1:13: +1:15
-          nop;                             // scope 0 at $DIR/issue_66971.rs:+1:13: +1:15
           Deinit(_2);                      // scope 0 at $DIR/issue_66971.rs:+1:12: +1:22
-          nop;                             // scope 0 at $DIR/issue_66971.rs:+1:12: +1:22
           (_2.1: u8) = const 0_u8;         // scope 0 at $DIR/issue_66971.rs:+1:12: +1:22
           (_2.2: u8) = const 0_u8;         // scope 0 at $DIR/issue_66971.rs:+1:12: +1:22
-          StorageDead(_3);                 // scope 0 at $DIR/issue_66971.rs:+1:21: +1:22
           _1 = encode(move _2) -> bb1;     // scope 0 at $DIR/issue_66971.rs:+1:5: +1:23
                                            // mir::Constant
                                            // + span: $DIR/issue_66971.rs:17:5: 17:11
@@ -26,7 +21,6 @@
       bb1: {
           StorageDead(_2);                 // scope 0 at $DIR/issue_66971.rs:+1:22: +1:23
           StorageDead(_1);                 // scope 0 at $DIR/issue_66971.rs:+1:23: +1:24
-          nop;                             // scope 0 at $DIR/issue_66971.rs:+0:11: +2:2
           return;                          // scope 0 at $DIR/issue_66971.rs:+2:2: +2:2
       }
   }
diff --git a/src/test/mir-opt/const_prop/issue_67019.main.ConstProp.diff b/src/test/mir-opt/const_prop/issue_67019.main.ConstProp.diff
index 79cd8bf4839..cd53048597b 100644
--- a/src/test/mir-opt/const_prop/issue_67019.main.ConstProp.diff
+++ b/src/test/mir-opt/const_prop/issue_67019.main.ConstProp.diff
@@ -27,7 +27,6 @@
       bb1: {
           StorageDead(_2);                 // scope 0 at $DIR/issue_67019.rs:+1:19: +1:20
           StorageDead(_1);                 // scope 0 at $DIR/issue_67019.rs:+1:20: +1:21
-          nop;                             // scope 0 at $DIR/issue_67019.rs:+0:11: +2:2
           return;                          // scope 0 at $DIR/issue_67019.rs:+2:2: +2:2
       }
   }
diff --git a/src/test/mir-opt/const_prop/large_array_index.main.ConstProp.32bit.diff b/src/test/mir-opt/const_prop/large_array_index.main.ConstProp.32bit.diff
index 96de39258e4..5331e5b8212 100644
--- a/src/test/mir-opt/const_prop/large_array_index.main.ConstProp.32bit.diff
+++ b/src/test/mir-opt/const_prop/large_array_index.main.ConstProp.32bit.diff
@@ -29,7 +29,6 @@
           _1 = _2[_3];                     // scope 0 at $DIR/large_array_index.rs:+2:17: +2:32
           StorageDead(_3);                 // scope 0 at $DIR/large_array_index.rs:+2:32: +2:33
           StorageDead(_2);                 // scope 0 at $DIR/large_array_index.rs:+2:32: +2:33
-          nop;                             // scope 0 at $DIR/large_array_index.rs:+0:11: +3:2
           StorageDead(_1);                 // scope 0 at $DIR/large_array_index.rs:+3:1: +3:2
           return;                          // scope 0 at $DIR/large_array_index.rs:+3:2: +3:2
       }
diff --git a/src/test/mir-opt/const_prop/large_array_index.main.ConstProp.64bit.diff b/src/test/mir-opt/const_prop/large_array_index.main.ConstProp.64bit.diff
index 96de39258e4..5331e5b8212 100644
--- a/src/test/mir-opt/const_prop/large_array_index.main.ConstProp.64bit.diff
+++ b/src/test/mir-opt/const_prop/large_array_index.main.ConstProp.64bit.diff
@@ -29,7 +29,6 @@
           _1 = _2[_3];                     // scope 0 at $DIR/large_array_index.rs:+2:17: +2:32
           StorageDead(_3);                 // scope 0 at $DIR/large_array_index.rs:+2:32: +2:33
           StorageDead(_2);                 // scope 0 at $DIR/large_array_index.rs:+2:32: +2:33
-          nop;                             // scope 0 at $DIR/large_array_index.rs:+0:11: +3:2
           StorageDead(_1);                 // scope 0 at $DIR/large_array_index.rs:+3:1: +3:2
           return;                          // scope 0 at $DIR/large_array_index.rs:+3:2: +3:2
       }
diff --git a/src/test/mir-opt/const_prop/mutable_variable.main.ConstProp.diff b/src/test/mir-opt/const_prop/mutable_variable.main.ConstProp.diff
index 3bbd6a87f97..a672c457a72 100644
--- a/src/test/mir-opt/const_prop/mutable_variable.main.ConstProp.diff
+++ b/src/test/mir-opt/const_prop/mutable_variable.main.ConstProp.diff
@@ -19,7 +19,6 @@
           StorageLive(_2);                 // scope 1 at $DIR/mutable_variable.rs:+3:9: +3:10
 -         _2 = _1;                         // scope 1 at $DIR/mutable_variable.rs:+3:13: +3:14
 +         _2 = const 99_i32;               // scope 1 at $DIR/mutable_variable.rs:+3:13: +3:14
-          nop;                             // scope 0 at $DIR/mutable_variable.rs:+0:11: +4:2
           StorageDead(_2);                 // scope 1 at $DIR/mutable_variable.rs:+4:1: +4:2
           StorageDead(_1);                 // scope 0 at $DIR/mutable_variable.rs:+4:1: +4:2
           return;                          // scope 0 at $DIR/mutable_variable.rs:+4:2: +4:2
diff --git a/src/test/mir-opt/const_prop/mutable_variable_aggregate.main.ConstProp.diff b/src/test/mir-opt/const_prop/mutable_variable_aggregate.main.ConstProp.diff
index fed6a98b9f3..f6bf522065b 100644
--- a/src/test/mir-opt/const_prop/mutable_variable_aggregate.main.ConstProp.diff
+++ b/src/test/mir-opt/const_prop/mutable_variable_aggregate.main.ConstProp.diff
@@ -21,7 +21,6 @@
           StorageLive(_2);                 // scope 1 at $DIR/mutable_variable_aggregate.rs:+3:9: +3:10
 -         _2 = _1;                         // scope 1 at $DIR/mutable_variable_aggregate.rs:+3:13: +3:14
 +         _2 = const (42_i32, 99_i32);     // scope 1 at $DIR/mutable_variable_aggregate.rs:+3:13: +3:14
-          nop;                             // scope 0 at $DIR/mutable_variable_aggregate.rs:+0:11: +4:2
           StorageDead(_2);                 // scope 1 at $DIR/mutable_variable_aggregate.rs:+4:1: +4:2
           StorageDead(_1);                 // scope 0 at $DIR/mutable_variable_aggregate.rs:+4:1: +4:2
           return;                          // scope 0 at $DIR/mutable_variable_aggregate.rs:+4:2: +4:2
diff --git a/src/test/mir-opt/const_prop/mutable_variable_aggregate_mut_ref.main.ConstProp.diff b/src/test/mir-opt/const_prop/mutable_variable_aggregate_mut_ref.main.ConstProp.diff
index 90eebd8feac..213a70227d8 100644
--- a/src/test/mir-opt/const_prop/mutable_variable_aggregate_mut_ref.main.ConstProp.diff
+++ b/src/test/mir-opt/const_prop/mutable_variable_aggregate_mut_ref.main.ConstProp.diff
@@ -26,7 +26,6 @@
           ((*_2).1: i32) = const 99_i32;   // scope 2 at $DIR/mutable_variable_aggregate_mut_ref.rs:+3:5: +3:13
           StorageLive(_3);                 // scope 2 at $DIR/mutable_variable_aggregate_mut_ref.rs:+4:9: +4:10
           _3 = _1;                         // scope 2 at $DIR/mutable_variable_aggregate_mut_ref.rs:+4:13: +4:14
-          nop;                             // scope 0 at $DIR/mutable_variable_aggregate_mut_ref.rs:+0:11: +5:2
           StorageDead(_3);                 // scope 2 at $DIR/mutable_variable_aggregate_mut_ref.rs:+5:1: +5:2
           StorageDead(_2);                 // scope 1 at $DIR/mutable_variable_aggregate_mut_ref.rs:+5:1: +5:2
           StorageDead(_1);                 // scope 0 at $DIR/mutable_variable_aggregate_mut_ref.rs:+5:1: +5:2
diff --git a/src/test/mir-opt/const_prop/mutable_variable_aggregate_partial_read.main.ConstProp.diff b/src/test/mir-opt/const_prop/mutable_variable_aggregate_partial_read.main.ConstProp.diff
index 6eda503c1ee..149aa6290d0 100644
--- a/src/test/mir-opt/const_prop/mutable_variable_aggregate_partial_read.main.ConstProp.diff
+++ b/src/test/mir-opt/const_prop/mutable_variable_aggregate_partial_read.main.ConstProp.diff
@@ -26,7 +26,6 @@
           StorageLive(_2);                 // scope 1 at $DIR/mutable_variable_aggregate_partial_read.rs:+4:9: +4:10
 -         _2 = (_1.1: i32);                // scope 1 at $DIR/mutable_variable_aggregate_partial_read.rs:+4:13: +4:16
 +         _2 = const 99_i32;               // scope 1 at $DIR/mutable_variable_aggregate_partial_read.rs:+4:13: +4:16
-          nop;                             // scope 0 at $DIR/mutable_variable_aggregate_partial_read.rs:+0:11: +5:2
           StorageDead(_2);                 // scope 1 at $DIR/mutable_variable_aggregate_partial_read.rs:+5:1: +5:2
           StorageDead(_1);                 // scope 0 at $DIR/mutable_variable_aggregate_partial_read.rs:+5:1: +5:2
           return;                          // scope 0 at $DIR/mutable_variable_aggregate_partial_read.rs:+5:2: +5:2
diff --git a/src/test/mir-opt/const_prop/mutable_variable_no_prop.main.ConstProp.diff b/src/test/mir-opt/const_prop/mutable_variable_no_prop.main.ConstProp.diff
index eb3a7bc96d8..b9d551c5e5f 100644
--- a/src/test/mir-opt/const_prop/mutable_variable_no_prop.main.ConstProp.diff
+++ b/src/test/mir-opt/const_prop/mutable_variable_no_prop.main.ConstProp.diff
@@ -4,39 +4,34 @@
   fn main() -> () {
       let mut _0: ();                      // return place in scope 0 at $DIR/mutable_variable_no_prop.rs:+0:11: +0:11
       let mut _1: u32;                     // in scope 0 at $DIR/mutable_variable_no_prop.rs:+1:9: +1:14
-      let _2: ();                          // in scope 0 at $DIR/mutable_variable_no_prop.rs:+2:5: +4:6
-      let mut _3: u32;                     // in scope 0 at $DIR/mutable_variable_no_prop.rs:+3:13: +3:19
-      let mut _4: *mut u32;                // in scope 0 at $DIR/mutable_variable_no_prop.rs:+3:13: +3:19
+      let mut _2: u32;                     // in scope 0 at $DIR/mutable_variable_no_prop.rs:+3:13: +3:19
+      let mut _3: *mut u32;                // in scope 0 at $DIR/mutable_variable_no_prop.rs:+3:13: +3:19
       scope 1 {
           debug x => _1;                   // in scope 1 at $DIR/mutable_variable_no_prop.rs:+1:9: +1:14
-          let _5: u32;                     // in scope 1 at $DIR/mutable_variable_no_prop.rs:+5:9: +5:10
+          let _4: u32;                     // in scope 1 at $DIR/mutable_variable_no_prop.rs:+5:9: +5:10
           scope 2 {
           }
           scope 3 {
-              debug y => _5;               // in scope 3 at $DIR/mutable_variable_no_prop.rs:+5:9: +5:10
+              debug y => _4;               // in scope 3 at $DIR/mutable_variable_no_prop.rs:+5:9: +5:10
           }
       }
   
       bb0: {
           StorageLive(_1);                 // scope 0 at $DIR/mutable_variable_no_prop.rs:+1:9: +1:14
           _1 = const 42_u32;               // scope 0 at $DIR/mutable_variable_no_prop.rs:+1:17: +1:19
-          StorageLive(_2);                 // scope 1 at $DIR/mutable_variable_no_prop.rs:+2:5: +4:6
+          StorageLive(_2);                 // scope 2 at $DIR/mutable_variable_no_prop.rs:+3:13: +3:19
           StorageLive(_3);                 // scope 2 at $DIR/mutable_variable_no_prop.rs:+3:13: +3:19
-          StorageLive(_4);                 // scope 2 at $DIR/mutable_variable_no_prop.rs:+3:13: +3:19
-          _4 = const {alloc1: *mut u32};   // scope 2 at $DIR/mutable_variable_no_prop.rs:+3:13: +3:19
+          _3 = const {alloc1: *mut u32};   // scope 2 at $DIR/mutable_variable_no_prop.rs:+3:13: +3:19
                                            // mir::Constant
                                            // + span: $DIR/mutable_variable_no_prop.rs:10:13: 10:19
                                            // + literal: Const { ty: *mut u32, val: Value(Scalar(alloc1)) }
-          _3 = (*_4);                      // scope 2 at $DIR/mutable_variable_no_prop.rs:+3:13: +3:19
-          _1 = move _3;                    // scope 2 at $DIR/mutable_variable_no_prop.rs:+3:9: +3:19
-          StorageDead(_3);                 // scope 2 at $DIR/mutable_variable_no_prop.rs:+3:18: +3:19
-          StorageDead(_4);                 // scope 2 at $DIR/mutable_variable_no_prop.rs:+3:19: +3:20
-          nop;                             // scope 2 at $DIR/mutable_variable_no_prop.rs:+2:5: +4:6
-          StorageDead(_2);                 // scope 1 at $DIR/mutable_variable_no_prop.rs:+4:5: +4:6
-          StorageLive(_5);                 // scope 1 at $DIR/mutable_variable_no_prop.rs:+5:9: +5:10
-          _5 = _1;                         // scope 1 at $DIR/mutable_variable_no_prop.rs:+5:13: +5:14
-          nop;                             // scope 0 at $DIR/mutable_variable_no_prop.rs:+0:11: +6:2
-          StorageDead(_5);                 // scope 1 at $DIR/mutable_variable_no_prop.rs:+6:1: +6:2
+          _2 = (*_3);                      // scope 2 at $DIR/mutable_variable_no_prop.rs:+3:13: +3:19
+          _1 = move _2;                    // scope 2 at $DIR/mutable_variable_no_prop.rs:+3:9: +3:19
+          StorageDead(_2);                 // scope 2 at $DIR/mutable_variable_no_prop.rs:+3:18: +3:19
+          StorageDead(_3);                 // scope 2 at $DIR/mutable_variable_no_prop.rs:+3:19: +3:20
+          StorageLive(_4);                 // scope 1 at $DIR/mutable_variable_no_prop.rs:+5:9: +5:10
+          _4 = _1;                         // scope 1 at $DIR/mutable_variable_no_prop.rs:+5:13: +5:14
+          StorageDead(_4);                 // scope 1 at $DIR/mutable_variable_no_prop.rs:+6:1: +6:2
           StorageDead(_1);                 // scope 0 at $DIR/mutable_variable_no_prop.rs:+6:1: +6:2
           return;                          // scope 0 at $DIR/mutable_variable_no_prop.rs:+6:2: +6:2
       }
diff --git a/src/test/mir-opt/const_prop/mutable_variable_unprop_assign.main.ConstProp.diff b/src/test/mir-opt/const_prop/mutable_variable_unprop_assign.main.ConstProp.diff
index 2e4b0e79e9f..c3f77b960a2 100644
--- a/src/test/mir-opt/const_prop/mutable_variable_unprop_assign.main.ConstProp.diff
+++ b/src/test/mir-opt/const_prop/mutable_variable_unprop_assign.main.ConstProp.diff
@@ -4,20 +4,19 @@
   fn main() -> () {
       let mut _0: ();                      // return place in scope 0 at $DIR/mutable_variable_unprop_assign.rs:+0:11: +0:11
       let _1: i32;                         // in scope 0 at $DIR/mutable_variable_unprop_assign.rs:+1:9: +1:10
-      let mut _3: i32;                     // in scope 0 at $DIR/mutable_variable_unprop_assign.rs:+3:11: +3:12
+      let mut _2: i32;                     // in scope 0 at $DIR/mutable_variable_unprop_assign.rs:+3:11: +3:12
       scope 1 {
           debug a => _1;                   // in scope 1 at $DIR/mutable_variable_unprop_assign.rs:+1:9: +1:10
-          let mut _2: (i32, i32);          // in scope 1 at $DIR/mutable_variable_unprop_assign.rs:+2:9: +2:14
+          let mut _5: i32;                 // in scope 1 at $DIR/mutable_variable_unprop_assign.rs:+2:9: +2:14
           let mut _6: i32;                 // in scope 1 at $DIR/mutable_variable_unprop_assign.rs:+2:9: +2:14
-          let mut _7: i32;                 // in scope 1 at $DIR/mutable_variable_unprop_assign.rs:+2:9: +2:14
           scope 2 {
-              debug x => (i32, i32){ .0 => _6, .1 => _7, }; // in scope 2 at $DIR/mutable_variable_unprop_assign.rs:+2:9: +2:14
-              let _4: i32;                 // in scope 2 at $DIR/mutable_variable_unprop_assign.rs:+4:9: +4:10
+              debug x => (i32, i32){ .0 => _5, .1 => _6, }; // in scope 2 at $DIR/mutable_variable_unprop_assign.rs:+2:9: +2:14
+              let _3: i32;                 // in scope 2 at $DIR/mutable_variable_unprop_assign.rs:+4:9: +4:10
               scope 3 {
-                  debug y => _4;           // in scope 3 at $DIR/mutable_variable_unprop_assign.rs:+4:9: +4:10
-                  let _5: i32;             // in scope 3 at $DIR/mutable_variable_unprop_assign.rs:+5:9: +5:10
+                  debug y => _3;           // in scope 3 at $DIR/mutable_variable_unprop_assign.rs:+4:9: +4:10
+                  let _4: i32;             // in scope 3 at $DIR/mutable_variable_unprop_assign.rs:+5:9: +5:10
                   scope 4 {
-                      debug z => _5;       // in scope 4 at $DIR/mutable_variable_unprop_assign.rs:+5:9: +5:10
+                      debug z => _4;       // in scope 4 at $DIR/mutable_variable_unprop_assign.rs:+5:9: +5:10
                   }
               }
           }
@@ -32,26 +31,25 @@
       }
   
       bb1: {
+          StorageLive(_5);                 // scope 1 at $DIR/mutable_variable_unprop_assign.rs:+2:9: +2:14
           StorageLive(_6);                 // scope 1 at $DIR/mutable_variable_unprop_assign.rs:+2:9: +2:14
-          StorageLive(_7);                 // scope 1 at $DIR/mutable_variable_unprop_assign.rs:+2:9: +2:14
+          Deinit(_5);                      // scope 1 at $DIR/mutable_variable_unprop_assign.rs:+2:29: +2:35
           Deinit(_6);                      // scope 1 at $DIR/mutable_variable_unprop_assign.rs:+2:29: +2:35
-          Deinit(_7);                      // scope 1 at $DIR/mutable_variable_unprop_assign.rs:+2:29: +2:35
-          _6 = const 1_i32;                // scope 1 at $DIR/mutable_variable_unprop_assign.rs:+2:29: +2:35
-          _7 = const 2_i32;                // scope 1 at $DIR/mutable_variable_unprop_assign.rs:+2:29: +2:35
-          StorageLive(_3);                 // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+3:11: +3:12
-          _3 = _1;                         // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+3:11: +3:12
-          _7 = move _3;                    // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+3:5: +3:12
-          StorageDead(_3);                 // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+3:11: +3:12
-          StorageLive(_4);                 // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+4:9: +4:10
-          _4 = _7;                         // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+4:13: +4:16
-          StorageLive(_5);                 // scope 3 at $DIR/mutable_variable_unprop_assign.rs:+5:9: +5:10
--         _5 = _6;                         // scope 3 at $DIR/mutable_variable_unprop_assign.rs:+5:13: +5:16
-+         _5 = const 1_i32;                // scope 3 at $DIR/mutable_variable_unprop_assign.rs:+5:13: +5:16
-          nop;                             // scope 0 at $DIR/mutable_variable_unprop_assign.rs:+0:11: +6:2
-          StorageDead(_5);                 // scope 3 at $DIR/mutable_variable_unprop_assign.rs:+6:1: +6:2
-          StorageDead(_4);                 // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+6:1: +6:2
+          _5 = const 1_i32;                // scope 1 at $DIR/mutable_variable_unprop_assign.rs:+2:29: +2:35
+          _6 = const 2_i32;                // scope 1 at $DIR/mutable_variable_unprop_assign.rs:+2:29: +2:35
+          StorageLive(_2);                 // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+3:11: +3:12
+          _2 = _1;                         // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+3:11: +3:12
+          _6 = move _2;                    // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+3:5: +3:12
+          StorageDead(_2);                 // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+3:11: +3:12
+          StorageLive(_3);                 // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+4:9: +4:10
+          _3 = _6;                         // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+4:13: +4:16
+          StorageLive(_4);                 // scope 3 at $DIR/mutable_variable_unprop_assign.rs:+5:9: +5:10
+-         _4 = _5;                         // scope 3 at $DIR/mutable_variable_unprop_assign.rs:+5:13: +5:16
++         _4 = const 1_i32;                // scope 3 at $DIR/mutable_variable_unprop_assign.rs:+5:13: +5:16
+          StorageDead(_4);                 // scope 3 at $DIR/mutable_variable_unprop_assign.rs:+6:1: +6:2
+          StorageDead(_3);                 // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+6:1: +6:2
+          StorageDead(_5);                 // scope 1 at $DIR/mutable_variable_unprop_assign.rs:+6:1: +6:2
           StorageDead(_6);                 // scope 1 at $DIR/mutable_variable_unprop_assign.rs:+6:1: +6:2
-          StorageDead(_7);                 // scope 1 at $DIR/mutable_variable_unprop_assign.rs:+6:1: +6:2
           StorageDead(_1);                 // scope 0 at $DIR/mutable_variable_unprop_assign.rs:+6:1: +6:2
           return;                          // scope 0 at $DIR/mutable_variable_unprop_assign.rs:+6:2: +6:2
       }
diff --git a/src/test/mir-opt/const_prop/optimizes_into_variable.main.ConstProp.32bit.diff b/src/test/mir-opt/const_prop/optimizes_into_variable.main.ConstProp.32bit.diff
index 7e8ebd31ad1..7c7aeac4c45 100644
--- a/src/test/mir-opt/const_prop/optimizes_into_variable.main.ConstProp.32bit.diff
+++ b/src/test/mir-opt/const_prop/optimizes_into_variable.main.ConstProp.32bit.diff
@@ -9,9 +9,7 @@
       let _5: usize;                       // in scope 0 at $DIR/optimizes_into_variable.rs:+2:32: +2:33
       let mut _6: usize;                   // in scope 0 at $DIR/optimizes_into_variable.rs:+2:13: +2:34
       let mut _7: bool;                    // in scope 0 at $DIR/optimizes_into_variable.rs:+2:13: +2:34
-      let mut _9: Point;                   // in scope 0 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
-      let mut _10: u32;                    // in scope 0 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
-      let mut _11: u32;                    // in scope 0 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
+      let mut _9: u32;                     // in scope 0 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
       scope 1 {
           debug x => _1;                   // in scope 1 at $DIR/optimizes_into_variable.rs:+1:9: +1:10
           let _3: i32;                     // in scope 1 at $DIR/optimizes_into_variable.rs:+2:9: +2:10
@@ -53,17 +51,12 @@
           StorageDead(_5);                 // scope 1 at $DIR/optimizes_into_variable.rs:+2:34: +2:35
           StorageDead(_4);                 // scope 1 at $DIR/optimizes_into_variable.rs:+2:34: +2:35
           StorageLive(_8);                 // scope 2 at $DIR/optimizes_into_variable.rs:+3:9: +3:10
-          StorageLive(_10);                // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
-          StorageLive(_11);                // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
-          Deinit(_10);                     // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
-          Deinit(_11);                     // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
-          _10 = const 12_u32;              // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
-          _11 = const 42_u32;              // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
--         _8 = _11;                        // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:38
+          StorageLive(_9);                 // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
+          Deinit(_9);                      // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
+          _9 = const 42_u32;               // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
+-         _8 = _9;                         // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:38
 +         _8 = const 42_u32;               // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:38
-          StorageDead(_10);                // scope 2 at $DIR/optimizes_into_variable.rs:+3:38: +3:39
-          StorageDead(_11);                // scope 2 at $DIR/optimizes_into_variable.rs:+3:38: +3:39
-          nop;                             // scope 0 at $DIR/optimizes_into_variable.rs:+0:11: +4:2
+          StorageDead(_9);                 // scope 2 at $DIR/optimizes_into_variable.rs:+3:38: +3:39
           StorageDead(_8);                 // scope 2 at $DIR/optimizes_into_variable.rs:+4:1: +4:2
           StorageDead(_3);                 // scope 1 at $DIR/optimizes_into_variable.rs:+4:1: +4:2
           StorageDead(_1);                 // scope 0 at $DIR/optimizes_into_variable.rs:+4:1: +4:2
diff --git a/src/test/mir-opt/const_prop/optimizes_into_variable.main.ConstProp.64bit.diff b/src/test/mir-opt/const_prop/optimizes_into_variable.main.ConstProp.64bit.diff
index 7e8ebd31ad1..7c7aeac4c45 100644
--- a/src/test/mir-opt/const_prop/optimizes_into_variable.main.ConstProp.64bit.diff
+++ b/src/test/mir-opt/const_prop/optimizes_into_variable.main.ConstProp.64bit.diff
@@ -9,9 +9,7 @@
       let _5: usize;                       // in scope 0 at $DIR/optimizes_into_variable.rs:+2:32: +2:33
       let mut _6: usize;                   // in scope 0 at $DIR/optimizes_into_variable.rs:+2:13: +2:34
       let mut _7: bool;                    // in scope 0 at $DIR/optimizes_into_variable.rs:+2:13: +2:34
-      let mut _9: Point;                   // in scope 0 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
-      let mut _10: u32;                    // in scope 0 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
-      let mut _11: u32;                    // in scope 0 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
+      let mut _9: u32;                     // in scope 0 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
       scope 1 {
           debug x => _1;                   // in scope 1 at $DIR/optimizes_into_variable.rs:+1:9: +1:10
           let _3: i32;                     // in scope 1 at $DIR/optimizes_into_variable.rs:+2:9: +2:10
@@ -53,17 +51,12 @@
           StorageDead(_5);                 // scope 1 at $DIR/optimizes_into_variable.rs:+2:34: +2:35
           StorageDead(_4);                 // scope 1 at $DIR/optimizes_into_variable.rs:+2:34: +2:35
           StorageLive(_8);                 // scope 2 at $DIR/optimizes_into_variable.rs:+3:9: +3:10
-          StorageLive(_10);                // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
-          StorageLive(_11);                // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
-          Deinit(_10);                     // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
-          Deinit(_11);                     // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
-          _10 = const 12_u32;              // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
-          _11 = const 42_u32;              // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
--         _8 = _11;                        // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:38
+          StorageLive(_9);                 // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
+          Deinit(_9);                      // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
+          _9 = const 42_u32;               // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
+-         _8 = _9;                         // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:38
 +         _8 = const 42_u32;               // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:38
-          StorageDead(_10);                // scope 2 at $DIR/optimizes_into_variable.rs:+3:38: +3:39
-          StorageDead(_11);                // scope 2 at $DIR/optimizes_into_variable.rs:+3:38: +3:39
-          nop;                             // scope 0 at $DIR/optimizes_into_variable.rs:+0:11: +4:2
+          StorageDead(_9);                 // scope 2 at $DIR/optimizes_into_variable.rs:+3:38: +3:39
           StorageDead(_8);                 // scope 2 at $DIR/optimizes_into_variable.rs:+4:1: +4:2
           StorageDead(_3);                 // scope 1 at $DIR/optimizes_into_variable.rs:+4:1: +4:2
           StorageDead(_1);                 // scope 0 at $DIR/optimizes_into_variable.rs:+4:1: +4:2
diff --git a/src/test/mir-opt/const_prop/optimizes_into_variable.main.SimplifyLocals.after.32bit.mir b/src/test/mir-opt/const_prop/optimizes_into_variable.main.SimplifyLocals-final.after.32bit.mir
index 75cea8ad2ce..d926b9df733 100644
--- a/src/test/mir-opt/const_prop/optimizes_into_variable.main.SimplifyLocals.after.32bit.mir
+++ b/src/test/mir-opt/const_prop/optimizes_into_variable.main.SimplifyLocals-final.after.32bit.mir
@@ -1,4 +1,4 @@
-// MIR for `main` after SimplifyLocals
+// MIR for `main` after SimplifyLocals-final
 
 fn main() -> () {
     let mut _0: ();                      // return place in scope 0 at $DIR/optimizes_into_variable.rs:+0:11: +0:11
diff --git a/src/test/mir-opt/const_prop/optimizes_into_variable.main.SimplifyLocals.after.64bit.mir b/src/test/mir-opt/const_prop/optimizes_into_variable.main.SimplifyLocals-final.after.64bit.mir
index 75cea8ad2ce..d926b9df733 100644
--- a/src/test/mir-opt/const_prop/optimizes_into_variable.main.SimplifyLocals.after.64bit.mir
+++ b/src/test/mir-opt/const_prop/optimizes_into_variable.main.SimplifyLocals-final.after.64bit.mir
@@ -1,4 +1,4 @@
-// MIR for `main` after SimplifyLocals
+// MIR for `main` after SimplifyLocals-final
 
 fn main() -> () {
     let mut _0: ();                      // return place in scope 0 at $DIR/optimizes_into_variable.rs:+0:11: +0:11
diff --git a/src/test/mir-opt/const_prop/optimizes_into_variable.rs b/src/test/mir-opt/const_prop/optimizes_into_variable.rs
index 02566654818..abea07e2025 100644
--- a/src/test/mir-opt/const_prop/optimizes_into_variable.rs
+++ b/src/test/mir-opt/const_prop/optimizes_into_variable.rs
@@ -9,7 +9,7 @@ struct Point {
 // EMIT_MIR_FOR_EACH_BIT_WIDTH
 // EMIT_MIR optimizes_into_variable.main.ScalarReplacementOfAggregates.diff
 // EMIT_MIR optimizes_into_variable.main.ConstProp.diff
-// EMIT_MIR optimizes_into_variable.main.SimplifyLocals.after.mir
+// EMIT_MIR optimizes_into_variable.main.SimplifyLocals-final.after.mir
 // EMIT_MIR optimizes_into_variable.main.PreCodegen.after.mir
 fn main() {
     let x = 2 + 2;
diff --git a/src/test/mir-opt/const_prop/read_immutable_static.main.ConstProp.diff b/src/test/mir-opt/const_prop/read_immutable_static.main.ConstProp.diff
index b9c283a5482..388c6ca810b 100644
--- a/src/test/mir-opt/const_prop/read_immutable_static.main.ConstProp.diff
+++ b/src/test/mir-opt/const_prop/read_immutable_static.main.ConstProp.diff
@@ -36,7 +36,6 @@
           StorageDead(_2);                 // scope 0 at $DIR/read_immutable_static.rs:+1:21: +1:22
           StorageDead(_5);                 // scope 0 at $DIR/read_immutable_static.rs:+1:22: +1:23
           StorageDead(_3);                 // scope 0 at $DIR/read_immutable_static.rs:+1:22: +1:23
-          nop;                             // scope 0 at $DIR/read_immutable_static.rs:+0:11: +2:2
           StorageDead(_1);                 // scope 0 at $DIR/read_immutable_static.rs:+2:1: +2:2
           return;                          // scope 0 at $DIR/read_immutable_static.rs:+2:2: +2:2
       }
diff --git a/src/test/mir-opt/const_prop/ref_deref.main.ConstProp.diff b/src/test/mir-opt/const_prop/ref_deref.main.ConstProp.diff
index 09ce67ff15d..8a73f0390e1 100644
--- a/src/test/mir-opt/const_prop/ref_deref.main.ConstProp.diff
+++ b/src/test/mir-opt/const_prop/ref_deref.main.ConstProp.diff
@@ -13,7 +13,7 @@
           StorageLive(_2);                 // scope 0 at $DIR/ref_deref.rs:+1:6: +1:10
           _4 = const _;                    // scope 0 at $DIR/ref_deref.rs:+1:6: +1:10
                                            // mir::Constant
-                                           // + span: $DIR/ref_deref.rs:5:6: 5:10
+                                           // + span: $DIR/ref_deref.rs:6:6: 6:10
                                            // + literal: Const { ty: &i32, val: Unevaluated(main, [], Some(promoted[0])) }
           _2 = _4;                         // scope 0 at $DIR/ref_deref.rs:+1:6: +1:10
 -         _1 = (*_2);                      // scope 0 at $DIR/ref_deref.rs:+1:5: +1:10
diff --git a/src/test/mir-opt/const_prop/ref_deref.main.PromoteTemps.diff b/src/test/mir-opt/const_prop/ref_deref.main.PromoteTemps.diff
index 902cd785031..015ec4d078c 100644
--- a/src/test/mir-opt/const_prop/ref_deref.main.PromoteTemps.diff
+++ b/src/test/mir-opt/const_prop/ref_deref.main.PromoteTemps.diff
@@ -16,7 +16,7 @@
 -         _2 = &_3;                        // scope 0 at $DIR/ref_deref.rs:+1:6: +1:10
 +         _4 = const _;                    // scope 0 at $DIR/ref_deref.rs:+1:6: +1:10
 +                                          // mir::Constant
-+                                          // + span: $DIR/ref_deref.rs:5:6: 5:10
++                                          // + span: $DIR/ref_deref.rs:6:6: 6:10
 +                                          // + literal: Const { ty: &i32, val: Unevaluated(main, [], Some(promoted[0])) }
 +         _2 = &(*_4);                     // scope 0 at $DIR/ref_deref.rs:+1:6: +1:10
           _1 = (*_2);                      // scope 0 at $DIR/ref_deref.rs:+1:5: +1:10
diff --git a/src/test/mir-opt/const_prop/ref_deref.rs b/src/test/mir-opt/const_prop/ref_deref.rs
index 30ec9766367..d2549c8b6aa 100644
--- a/src/test/mir-opt/const_prop/ref_deref.rs
+++ b/src/test/mir-opt/const_prop/ref_deref.rs
@@ -1,3 +1,4 @@
+// compile-flags: -Zmir-enable-passes=-SimplifyLocals-before-const-prop
 // EMIT_MIR ref_deref.main.PromoteTemps.diff
 // EMIT_MIR ref_deref.main.ConstProp.diff
 
diff --git a/src/test/mir-opt/const_prop/ref_deref_project.rs b/src/test/mir-opt/const_prop/ref_deref_project.rs
index 659c11d9b0c..2fdd4e15319 100644
--- a/src/test/mir-opt/const_prop/ref_deref_project.rs
+++ b/src/test/mir-opt/const_prop/ref_deref_project.rs
@@ -1,4 +1,4 @@
-// unit-test
+// compile-flags: -Zmir-enable-passes=-SimplifyLocals-before-const-prop
 // EMIT_MIR ref_deref_project.main.PromoteTemps.diff
 // EMIT_MIR ref_deref_project.main.ConstProp.diff
 
diff --git a/src/test/mir-opt/const_prop/reify_fn_ptr.main.ConstProp.diff b/src/test/mir-opt/const_prop/reify_fn_ptr.main.ConstProp.diff
index 237a6f94aa7..15c93f270d7 100644
--- a/src/test/mir-opt/const_prop/reify_fn_ptr.main.ConstProp.diff
+++ b/src/test/mir-opt/const_prop/reify_fn_ptr.main.ConstProp.diff
@@ -3,26 +3,21 @@
   
   fn main() -> () {
       let mut _0: ();                      // return place in scope 0 at $DIR/reify_fn_ptr.rs:+0:11: +0:11
-      let mut _1: *const fn();             // in scope 0 at $DIR/reify_fn_ptr.rs:+1:13: +1:41
-      let mut _2: usize;                   // in scope 0 at $DIR/reify_fn_ptr.rs:+1:13: +1:26
-      let mut _3: fn();                    // in scope 0 at $DIR/reify_fn_ptr.rs:+1:13: +1:17
+      let mut _1: usize;                   // in scope 0 at $DIR/reify_fn_ptr.rs:+1:13: +1:26
+      let mut _2: fn();                    // in scope 0 at $DIR/reify_fn_ptr.rs:+1:13: +1:17
       scope 1 {
       }
   
       bb0: {
-          StorageLive(_1);                 // scope 0 at $DIR/reify_fn_ptr.rs:+1:13: +1:41
-          StorageLive(_2);                 // scope 0 at $DIR/reify_fn_ptr.rs:+1:13: +1:26
-          StorageLive(_3);                 // scope 0 at $DIR/reify_fn_ptr.rs:+1:13: +1:17
-          _3 = main as fn() (Pointer(ReifyFnPointer)); // scope 0 at $DIR/reify_fn_ptr.rs:+1:13: +1:17
+          StorageLive(_1);                 // scope 0 at $DIR/reify_fn_ptr.rs:+1:13: +1:26
+          StorageLive(_2);                 // scope 0 at $DIR/reify_fn_ptr.rs:+1:13: +1:17
+          _2 = main as fn() (Pointer(ReifyFnPointer)); // scope 0 at $DIR/reify_fn_ptr.rs:+1:13: +1:17
                                            // mir::Constant
                                            // + span: $DIR/reify_fn_ptr.rs:4:13: 4:17
                                            // + literal: Const { ty: fn() {main}, val: Value(<ZST>) }
-          _2 = move _3 as usize (PointerExposeAddress); // scope 0 at $DIR/reify_fn_ptr.rs:+1:13: +1:26
-          StorageDead(_3);                 // scope 0 at $DIR/reify_fn_ptr.rs:+1:25: +1:26
-          _1 = move _2 as *const fn() (PointerFromExposedAddress); // scope 0 at $DIR/reify_fn_ptr.rs:+1:13: +1:41
-          StorageDead(_2);                 // scope 0 at $DIR/reify_fn_ptr.rs:+1:40: +1:41
-          StorageDead(_1);                 // scope 0 at $DIR/reify_fn_ptr.rs:+1:41: +1:42
-          nop;                             // scope 0 at $DIR/reify_fn_ptr.rs:+0:11: +2:2
+          _1 = move _2 as usize (PointerExposeAddress); // scope 0 at $DIR/reify_fn_ptr.rs:+1:13: +1:26
+          StorageDead(_2);                 // scope 0 at $DIR/reify_fn_ptr.rs:+1:25: +1:26
+          StorageDead(_1);                 // scope 0 at $DIR/reify_fn_ptr.rs:+1:40: +1:41
           return;                          // scope 0 at $DIR/reify_fn_ptr.rs:+2:2: +2:2
       }
   }
diff --git a/src/test/mir-opt/const_prop/repeat.main.ConstProp.32bit.diff b/src/test/mir-opt/const_prop/repeat.main.ConstProp.32bit.diff
index 7c497799691..636032adb81 100644
--- a/src/test/mir-opt/const_prop/repeat.main.ConstProp.32bit.diff
+++ b/src/test/mir-opt/const_prop/repeat.main.ConstProp.32bit.diff
@@ -35,7 +35,6 @@
           StorageDead(_2);                 // scope 0 at $DIR/repeat.rs:+1:31: +1:32
           StorageDead(_4);                 // scope 0 at $DIR/repeat.rs:+1:32: +1:33
           StorageDead(_3);                 // scope 0 at $DIR/repeat.rs:+1:32: +1:33
-          nop;                             // scope 0 at $DIR/repeat.rs:+0:11: +2:2
           StorageDead(_1);                 // scope 0 at $DIR/repeat.rs:+2:1: +2:2
           return;                          // scope 0 at $DIR/repeat.rs:+2:2: +2:2
       }
diff --git a/src/test/mir-opt/const_prop/repeat.main.ConstProp.64bit.diff b/src/test/mir-opt/const_prop/repeat.main.ConstProp.64bit.diff
index 7c497799691..636032adb81 100644
--- a/src/test/mir-opt/const_prop/repeat.main.ConstProp.64bit.diff
+++ b/src/test/mir-opt/const_prop/repeat.main.ConstProp.64bit.diff
@@ -35,7 +35,6 @@
           StorageDead(_2);                 // scope 0 at $DIR/repeat.rs:+1:31: +1:32
           StorageDead(_4);                 // scope 0 at $DIR/repeat.rs:+1:32: +1:33
           StorageDead(_3);                 // scope 0 at $DIR/repeat.rs:+1:32: +1:33
-          nop;                             // scope 0 at $DIR/repeat.rs:+0:11: +2:2
           StorageDead(_1);                 // scope 0 at $DIR/repeat.rs:+2:1: +2:2
           return;                          // scope 0 at $DIR/repeat.rs:+2:2: +2:2
       }
diff --git a/src/test/mir-opt/const_prop/scalar_literal_propagation.main.ConstProp.diff b/src/test/mir-opt/const_prop/scalar_literal_propagation.main.ConstProp.diff
index 5920937e0fd..d518eff04eb 100644
--- a/src/test/mir-opt/const_prop/scalar_literal_propagation.main.ConstProp.diff
+++ b/src/test/mir-opt/const_prop/scalar_literal_propagation.main.ConstProp.diff
@@ -27,7 +27,6 @@
       bb1: {
           StorageDead(_3);                 // scope 1 at $DIR/scalar_literal_propagation.rs:+2:14: +2:15
           StorageDead(_2);                 // scope 1 at $DIR/scalar_literal_propagation.rs:+2:15: +2:16
-          nop;                             // scope 0 at $DIR/scalar_literal_propagation.rs:+0:11: +3:2
           StorageDead(_1);                 // scope 0 at $DIR/scalar_literal_propagation.rs:+3:1: +3:2
           return;                          // scope 0 at $DIR/scalar_literal_propagation.rs:+3:2: +3:2
       }
diff --git a/src/test/mir-opt/const_prop/slice_len.main.ConstProp.32bit.diff b/src/test/mir-opt/const_prop/slice_len.main.ConstProp.32bit.diff
index 44445731e72..9017fd18e48 100644
--- a/src/test/mir-opt/const_prop/slice_len.main.ConstProp.32bit.diff
+++ b/src/test/mir-opt/const_prop/slice_len.main.ConstProp.32bit.diff
@@ -20,7 +20,7 @@
           StorageLive(_4);                 // scope 0 at $DIR/slice_len.rs:+1:6: +1:19
           _9 = const _;                    // scope 0 at $DIR/slice_len.rs:+1:6: +1:19
                                            // mir::Constant
-                                           // + span: $DIR/slice_len.rs:5:6: 5:19
+                                           // + span: $DIR/slice_len.rs:6:6: 6:19
                                            // + literal: Const { ty: &[u32; 3], val: Unevaluated(main, [], Some(promoted[0])) }
           _4 = _9;                         // scope 0 at $DIR/slice_len.rs:+1:6: +1:19
           _3 = _4;                         // scope 0 at $DIR/slice_len.rs:+1:6: +1:19
diff --git a/src/test/mir-opt/const_prop/slice_len.main.ConstProp.64bit.diff b/src/test/mir-opt/const_prop/slice_len.main.ConstProp.64bit.diff
index 44445731e72..9017fd18e48 100644
--- a/src/test/mir-opt/const_prop/slice_len.main.ConstProp.64bit.diff
+++ b/src/test/mir-opt/const_prop/slice_len.main.ConstProp.64bit.diff
@@ -20,7 +20,7 @@
           StorageLive(_4);                 // scope 0 at $DIR/slice_len.rs:+1:6: +1:19
           _9 = const _;                    // scope 0 at $DIR/slice_len.rs:+1:6: +1:19
                                            // mir::Constant
-                                           // + span: $DIR/slice_len.rs:5:6: 5:19
+                                           // + span: $DIR/slice_len.rs:6:6: 6:19
                                            // + literal: Const { ty: &[u32; 3], val: Unevaluated(main, [], Some(promoted[0])) }
           _4 = _9;                         // scope 0 at $DIR/slice_len.rs:+1:6: +1:19
           _3 = _4;                         // scope 0 at $DIR/slice_len.rs:+1:6: +1:19
diff --git a/src/test/mir-opt/const_prop/slice_len.rs b/src/test/mir-opt/const_prop/slice_len.rs
index fa9eafa8b0b..eaaf34b960e 100644
--- a/src/test/mir-opt/const_prop/slice_len.rs
+++ b/src/test/mir-opt/const_prop/slice_len.rs
@@ -1,3 +1,4 @@
+// compile-flags: -Zmir-enable-passes=-SimplifyLocals-before-const-prop
 // EMIT_MIR_FOR_EACH_BIT_WIDTH
 
 // EMIT_MIR slice_len.main.ConstProp.diff
diff --git a/src/test/mir-opt/const_prop/tuple_literal_propagation.main.ConstProp.diff b/src/test/mir-opt/const_prop/tuple_literal_propagation.main.ConstProp.diff
index a0603c60dc7..e4c92b617c6 100644
--- a/src/test/mir-opt/const_prop/tuple_literal_propagation.main.ConstProp.diff
+++ b/src/test/mir-opt/const_prop/tuple_literal_propagation.main.ConstProp.diff
@@ -28,7 +28,6 @@
       bb1: {
           StorageDead(_3);                 // scope 1 at $DIR/tuple_literal_propagation.rs:+3:14: +3:15
           StorageDead(_2);                 // scope 1 at $DIR/tuple_literal_propagation.rs:+3:15: +3:16
-          nop;                             // scope 0 at $DIR/tuple_literal_propagation.rs:+0:11: +4:2
           StorageDead(_1);                 // scope 0 at $DIR/tuple_literal_propagation.rs:+4:1: +4:2
           return;                          // scope 0 at $DIR/tuple_literal_propagation.rs:+4:2: +4:2
       }
diff --git a/src/test/mir-opt/const_prop_miscompile.bar.ConstProp.diff b/src/test/mir-opt/const_prop_miscompile.bar.ConstProp.diff
index 459da2e3358..ea9fec0aa15 100644
--- a/src/test/mir-opt/const_prop_miscompile.bar.ConstProp.diff
+++ b/src/test/mir-opt/const_prop_miscompile.bar.ConstProp.diff
@@ -4,16 +4,15 @@
   fn bar() -> () {
       let mut _0: ();                      // return place in scope 0 at $DIR/const_prop_miscompile.rs:+0:10: +0:10
       let mut _1: (i32,);                  // in scope 0 at $DIR/const_prop_miscompile.rs:+1:9: +1:14
-      let _2: ();                          // in scope 0 at $DIR/const_prop_miscompile.rs:+2:5: +4:6
-      let mut _3: *mut i32;                // in scope 0 at $DIR/const_prop_miscompile.rs:+3:10: +3:22
-      let mut _5: i32;                     // in scope 0 at $DIR/const_prop_miscompile.rs:+5:13: +5:20
+      let mut _2: *mut i32;                // in scope 0 at $DIR/const_prop_miscompile.rs:+3:10: +3:22
+      let mut _4: i32;                     // in scope 0 at $DIR/const_prop_miscompile.rs:+5:13: +5:20
       scope 1 {
           debug v => _1;                   // in scope 1 at $DIR/const_prop_miscompile.rs:+1:9: +1:14
-          let _4: bool;                    // in scope 1 at $DIR/const_prop_miscompile.rs:+5:9: +5:10
+          let _3: bool;                    // in scope 1 at $DIR/const_prop_miscompile.rs:+5:9: +5:10
           scope 2 {
           }
           scope 3 {
-              debug y => _4;               // in scope 3 at $DIR/const_prop_miscompile.rs:+5:9: +5:10
+              debug y => _3;               // in scope 3 at $DIR/const_prop_miscompile.rs:+5:9: +5:10
           }
       }
   
@@ -21,20 +20,16 @@
           StorageLive(_1);                 // scope 0 at $DIR/const_prop_miscompile.rs:+1:9: +1:14
           Deinit(_1);                      // scope 0 at $DIR/const_prop_miscompile.rs:+1:17: +1:21
           (_1.0: i32) = const 1_i32;       // scope 0 at $DIR/const_prop_miscompile.rs:+1:17: +1:21
-          StorageLive(_2);                 // scope 1 at $DIR/const_prop_miscompile.rs:+2:5: +4:6
-          StorageLive(_3);                 // scope 2 at $DIR/const_prop_miscompile.rs:+3:10: +3:22
-          _3 = &raw mut (_1.0: i32);       // scope 2 at $DIR/const_prop_miscompile.rs:+3:10: +3:22
-          (*_3) = const 5_i32;             // scope 2 at $DIR/const_prop_miscompile.rs:+3:9: +3:26
-          StorageDead(_3);                 // scope 2 at $DIR/const_prop_miscompile.rs:+3:26: +3:27
-          nop;                             // scope 2 at $DIR/const_prop_miscompile.rs:+2:5: +4:6
-          StorageDead(_2);                 // scope 1 at $DIR/const_prop_miscompile.rs:+4:5: +4:6
-          StorageLive(_4);                 // scope 1 at $DIR/const_prop_miscompile.rs:+5:9: +5:10
-          StorageLive(_5);                 // scope 1 at $DIR/const_prop_miscompile.rs:+5:13: +5:20
-          _5 = (_1.0: i32);                // scope 1 at $DIR/const_prop_miscompile.rs:+5:15: +5:18
-          _4 = Eq(move _5, const 5_i32);   // scope 1 at $DIR/const_prop_miscompile.rs:+5:13: +5:25
-          StorageDead(_5);                 // scope 1 at $DIR/const_prop_miscompile.rs:+5:24: +5:25
-          nop;                             // scope 0 at $DIR/const_prop_miscompile.rs:+0:10: +6:2
-          StorageDead(_4);                 // scope 1 at $DIR/const_prop_miscompile.rs:+6:1: +6:2
+          StorageLive(_2);                 // scope 2 at $DIR/const_prop_miscompile.rs:+3:10: +3:22
+          _2 = &raw mut (_1.0: i32);       // scope 2 at $DIR/const_prop_miscompile.rs:+3:10: +3:22
+          (*_2) = const 5_i32;             // scope 2 at $DIR/const_prop_miscompile.rs:+3:9: +3:26
+          StorageDead(_2);                 // scope 2 at $DIR/const_prop_miscompile.rs:+3:26: +3:27
+          StorageLive(_3);                 // scope 1 at $DIR/const_prop_miscompile.rs:+5:9: +5:10
+          StorageLive(_4);                 // scope 1 at $DIR/const_prop_miscompile.rs:+5:13: +5:20
+          _4 = (_1.0: i32);                // scope 1 at $DIR/const_prop_miscompile.rs:+5:15: +5:18
+          _3 = Eq(move _4, const 5_i32);   // scope 1 at $DIR/const_prop_miscompile.rs:+5:13: +5:25
+          StorageDead(_4);                 // scope 1 at $DIR/const_prop_miscompile.rs:+5:24: +5:25
+          StorageDead(_3);                 // scope 1 at $DIR/const_prop_miscompile.rs:+6:1: +6:2
           StorageDead(_1);                 // scope 0 at $DIR/const_prop_miscompile.rs:+6:1: +6:2
           return;                          // scope 0 at $DIR/const_prop_miscompile.rs:+6:2: +6:2
       }
diff --git a/src/test/mir-opt/const_prop_miscompile.foo.ConstProp.diff b/src/test/mir-opt/const_prop_miscompile.foo.ConstProp.diff
index e8bd98cf8cb..043f4047417 100644
--- a/src/test/mir-opt/const_prop_miscompile.foo.ConstProp.diff
+++ b/src/test/mir-opt/const_prop_miscompile.foo.ConstProp.diff
@@ -27,7 +27,6 @@
           _4 = (_1.0: i32);                // scope 1 at $DIR/const_prop_miscompile.rs:+3:15: +3:18
           _3 = Eq(move _4, const 5_i32);   // scope 1 at $DIR/const_prop_miscompile.rs:+3:13: +3:25
           StorageDead(_4);                 // scope 1 at $DIR/const_prop_miscompile.rs:+3:24: +3:25
-          nop;                             // scope 0 at $DIR/const_prop_miscompile.rs:+0:10: +4:2
           StorageDead(_3);                 // scope 1 at $DIR/const_prop_miscompile.rs:+4:1: +4:2
           StorageDead(_1);                 // scope 0 at $DIR/const_prop_miscompile.rs:+4:1: +4:2
           return;                          // scope 0 at $DIR/const_prop_miscompile.rs:+4:2: +4:2
diff --git a/src/test/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.diff
index bf4557ed3d9..02aafd7acc4 100644
--- a/src/test/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.diff
+++ b/src/test/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.diff
@@ -5,40 +5,34 @@
       let mut _0: ();                      // return place in scope 0 at $DIR/inherit_overflow.rs:+0:11: +0:11
       let mut _1: u8;                      // in scope 0 at $DIR/inherit_overflow.rs:+3:13: +3:47
       let mut _2: u8;                      // in scope 0 at $DIR/inherit_overflow.rs:+3:13: +3:47
-      let mut _3: u8;                      // in scope 0 at $DIR/inherit_overflow.rs:+3:13: +3:47
       scope 1 {
       }
       scope 2 (inlined <u8 as Add>::add) { // at $DIR/inherit_overflow.rs:7:13: 7:47
-          debug self => _2;                // in scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL
-          debug other => _3;               // in scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL
+          debug self => _1;                // in scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL
+          debug other => _2;               // in scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL
+          let mut _3: u8;                  // in scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL
           let mut _4: u8;                  // in scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL
-          let mut _5: u8;                  // in scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL
-          let mut _6: (u8, bool);          // in scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL
+          let mut _5: (u8, bool);          // in scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL
       }
   
       bb0: {
           StorageLive(_1);                 // scope 0 at $DIR/inherit_overflow.rs:+3:13: +3:47
+          _1 = const u8::MAX;              // scope 0 at $DIR/inherit_overflow.rs:+3:13: +3:47
           StorageLive(_2);                 // scope 0 at $DIR/inherit_overflow.rs:+3:13: +3:47
-          _2 = const u8::MAX;              // scope 0 at $DIR/inherit_overflow.rs:+3:13: +3:47
-          StorageLive(_3);                 // scope 0 at $DIR/inherit_overflow.rs:+3:13: +3:47
-          _3 = const 1_u8;                 // scope 0 at $DIR/inherit_overflow.rs:+3:13: +3:47
+          _2 = const 1_u8;                 // scope 0 at $DIR/inherit_overflow.rs:+3:13: +3:47
+          StorageLive(_3);                 // scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL
+          _3 = const u8::MAX;              // scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL
           StorageLive(_4);                 // scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL
-          _4 = const u8::MAX;              // scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL
-          StorageLive(_5);                 // scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL
-          _5 = const 1_u8;                 // scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL
-          _6 = CheckedAdd(const u8::MAX, const 1_u8); // scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL
-          assert(!move (_6.1: bool), "attempt to compute `{} + {}`, which would overflow", const u8::MAX, const 1_u8) -> bb1; // scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL
+          _4 = const 1_u8;                 // scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL
+          _5 = CheckedAdd(const u8::MAX, const 1_u8); // scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL
+          assert(!move (_5.1: bool), "attempt to compute `{} + {}`, which would overflow", const u8::MAX, const 1_u8) -> bb1; // scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL
       }
   
       bb1: {
--         _1 = move (_6.0: u8);            // scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL
-+         _1 = const 0_u8;                 // scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL
-          StorageDead(_5);                 // scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL
           StorageDead(_4);                 // scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL
-          StorageDead(_3);                 // scope 0 at $DIR/inherit_overflow.rs:+3:13: +3:47
+          StorageDead(_3);                 // scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL
           StorageDead(_2);                 // scope 0 at $DIR/inherit_overflow.rs:+3:13: +3:47
-          StorageDead(_1);                 // scope 0 at $DIR/inherit_overflow.rs:+3:47: +3:48
-          nop;                             // scope 0 at $DIR/inherit_overflow.rs:+0:11: +4:2
+          StorageDead(_1);                 // scope 0 at $DIR/inherit_overflow.rs:+3:13: +3:47
           return;                          // scope 0 at $DIR/inherit_overflow.rs:+4:2: +4:2
       }
   }
diff --git a/src/test/mir-opt/dead-store-elimination/cycle.cycle.DeadStoreElimination.diff b/src/test/mir-opt/dead-store-elimination/cycle.cycle.DeadStoreElimination.diff
index 80f8905adc9..cd3b792fb75 100644
--- a/src/test/mir-opt/dead-store-elimination/cycle.cycle.DeadStoreElimination.diff
+++ b/src/test/mir-opt/dead-store-elimination/cycle.cycle.DeadStoreElimination.diff
@@ -59,14 +59,6 @@
 -         _4 = const ();                   // scope 0 at $DIR/cycle.rs:+3:18: +8:6
 -         StorageDead(_6);                 // scope 0 at $DIR/cycle.rs:+8:5: +8:6
 +         StorageLive(_5);                 // scope 0 at $DIR/cycle.rs:+4:13: +4:17
-+         nop;                             // scope 0 at $DIR/cycle.rs:+4:20: +4:21
-+         nop;                             // scope 1 at $DIR/cycle.rs:+5:13: +5:14
-+         nop;                             // scope 1 at $DIR/cycle.rs:+5:9: +5:14
-+         nop;                             // scope 1 at $DIR/cycle.rs:+6:13: +6:14
-+         nop;                             // scope 1 at $DIR/cycle.rs:+6:9: +6:14
-+         nop;                             // scope 1 at $DIR/cycle.rs:+7:13: +7:17
-+         nop;                             // scope 1 at $DIR/cycle.rs:+7:9: +7:17
-+         nop;                             // scope 0 at $DIR/cycle.rs:+3:18: +8:6
           StorageDead(_5);                 // scope 0 at $DIR/cycle.rs:+8:5: +8:6
 +         StorageDead(_4);                 // scope 0 at $DIR/cycle.rs:+8:5: +8:6
           goto -> bb1;                     // scope 0 at $DIR/cycle.rs:+3:5: +8:6
diff --git a/src/test/mir-opt/dest-prop/dead_stores_better.f.DestinationPropagation.after.mir b/src/test/mir-opt/dest-prop/dead_stores_better.f.DestinationPropagation.after.mir
index ba7f76d2841..26068931aaf 100644
--- a/src/test/mir-opt/dest-prop/dead_stores_better.f.DestinationPropagation.after.mir
+++ b/src/test/mir-opt/dest-prop/dead_stores_better.f.DestinationPropagation.after.mir
@@ -13,7 +13,6 @@ fn f(_1: usize) -> usize {
     bb0: {
         nop;                             // scope 0 at $DIR/dead_stores_better.rs:+1:9: +1:10
         nop;                             // scope 0 at $DIR/dead_stores_better.rs:+1:13: +1:14
-        nop;                             // scope 1 at $DIR/dead_stores_better.rs:+2:5: +2:10
         nop;                             // scope 1 at $DIR/dead_stores_better.rs:+3:9: +3:10
         nop;                             // scope 1 at $DIR/dead_stores_better.rs:+3:9: +3:10
         nop;                             // scope 1 at $DIR/dead_stores_better.rs:+3:5: +3:10
diff --git a/src/test/mir-opt/dest-prop/union.main.DestinationPropagation.diff b/src/test/mir-opt/dest-prop/union.main.DestinationPropagation.diff
index 85d994bc8b9..fbed3178801 100644
--- a/src/test/mir-opt/dest-prop/union.main.DestinationPropagation.diff
+++ b/src/test/mir-opt/dest-prop/union.main.DestinationPropagation.diff
@@ -25,11 +25,8 @@
       }
   
       bb1: {
-          nop;                             // scope 0 at $DIR/union.rs:+5:14: +5:30
-          nop;                             // scope 0 at $DIR/union.rs:+5:14: +5:30
           StorageDead(_2);                 // scope 0 at $DIR/union.rs:+5:29: +5:30
           StorageLive(_3);                 // scope 1 at $DIR/union.rs:+7:10: +7:26
-          nop;                             // scope 2 at $DIR/union.rs:+7:19: +7:24
           StorageDead(_3);                 // scope 1 at $DIR/union.rs:+7:26: +7:27
           StorageDead(_1);                 // scope 0 at $DIR/union.rs:+8:1: +8:2
           return;                          // scope 0 at $DIR/union.rs:+8:2: +8:2
diff --git a/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.diff b/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.diff
index 17b81633991..bf3bcfdb594 100644
--- a/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.diff
+++ b/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.diff
@@ -7,41 +7,36 @@
       let mut _2: std::option::Option<i32>; // in scope 0 at $DIR/issue_73223.rs:+1:23: +1:30
       let mut _3: isize;                   // in scope 0 at $DIR/issue_73223.rs:+2:9: +2:16
       let _4: i32;                         // in scope 0 at $DIR/issue_73223.rs:+2:14: +2:15
-      let mut _5: !;                       // in scope 0 at $DIR/issue_73223.rs:+3:17: +3:23
-      let mut _7: i32;                     // in scope 0 at $DIR/issue_73223.rs:+6:22: +6:27
-      let _8: ();                          // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let mut _9: (&i32, &i32);            // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let mut _10: &i32;                   // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let mut _11: &i32;                   // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let _12: i32;                        // in scope 0 at $DIR/issue_73223.rs:+7:23: +7:24
-      let mut _15: bool;                   // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let mut _16: bool;                   // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let mut _17: i32;                    // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let mut _18: i32;                    // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let mut _19: !;                      // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let _21: !;                          // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let mut _22: core::panicking::AssertKind; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let mut _23: &i32;                   // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let _24: &i32;                       // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let mut _6: i32;                     // in scope 0 at $DIR/issue_73223.rs:+6:22: +6:27
+      let mut _7: &i32;                    // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let mut _8: &i32;                    // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let mut _11: bool;                   // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let mut _12: bool;                   // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let mut _13: i32;                    // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let mut _14: i32;                    // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let _16: !;                          // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let mut _17: core::panicking::AssertKind; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let mut _18: &i32;                   // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let _19: &i32;                       // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let mut _20: &i32;                   // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let _21: &i32;                       // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let mut _22: std::option::Option<std::fmt::Arguments<'_>>; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let mut _24: &i32;                   // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
       let mut _25: &i32;                   // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let _26: &i32;                       // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let mut _27: std::option::Option<std::fmt::Arguments<'_>>; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let mut _29: &i32;                   // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let mut _30: &i32;                   // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
       scope 1 {
           debug split => _1;               // in scope 1 at $DIR/issue_73223.rs:+1:9: +1:14
-          let _6: std::option::Option<i32>; // in scope 1 at $DIR/issue_73223.rs:+6:9: +6:14
+          let _5: std::option::Option<i32>; // in scope 1 at $DIR/issue_73223.rs:+6:9: +6:14
           scope 3 {
-              debug _prev => _6;           // in scope 3 at $DIR/issue_73223.rs:+6:9: +6:14
-              let _13: &i32;               // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-              let _14: &i32;               // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-              let mut _28: &i32;           // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+              debug _prev => _5;           // in scope 3 at $DIR/issue_73223.rs:+6:9: +6:14
+              let _9: &i32;                // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+              let _10: &i32;               // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+              let mut _23: &i32;           // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
               scope 4 {
-                  debug left_val => _13;   // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-                  debug right_val => _14;  // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-                  let _20: core::panicking::AssertKind; // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+                  debug left_val => _9;    // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+                  debug right_val => _10;  // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+                  let _15: core::panicking::AssertKind; // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                   scope 5 {
-                      debug kind => _20;   // in scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+                      debug kind => _15;   // in scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                   }
               }
           }
@@ -61,7 +56,6 @@
       }
   
       bb1: {
-          nop;                             // scope 0 at $DIR/issue_73223.rs:+3:17: +3:23
           StorageDead(_2);                 // scope 0 at $DIR/issue_73223.rs:+4:6: +4:7
           StorageDead(_1);                 // scope 0 at $DIR/issue_73223.rs:+8:1: +8:2
           return;                          // scope 0 at $DIR/issue_73223.rs:+8:2: +8:2
@@ -77,70 +71,69 @@
           _1 = _4;                         // scope 2 at $DIR/issue_73223.rs:+2:20: +2:21
           StorageDead(_4);                 // scope 0 at $DIR/issue_73223.rs:+2:20: +2:21
           StorageDead(_2);                 // scope 0 at $DIR/issue_73223.rs:+4:6: +4:7
-          StorageLive(_6);                 // scope 1 at $DIR/issue_73223.rs:+6:9: +6:14
-          StorageLive(_7);                 // scope 1 at $DIR/issue_73223.rs:+6:22: +6:27
-          _7 = _1;                         // scope 1 at $DIR/issue_73223.rs:+6:22: +6:27
-          Deinit(_6);                      // scope 1 at $DIR/issue_73223.rs:+6:17: +6:28
-          ((_6 as Some).0: i32) = move _7; // scope 1 at $DIR/issue_73223.rs:+6:17: +6:28
-          discriminant(_6) = 1;            // scope 1 at $DIR/issue_73223.rs:+6:17: +6:28
-          StorageDead(_7);                 // scope 1 at $DIR/issue_73223.rs:+6:27: +6:28
+          StorageLive(_5);                 // scope 1 at $DIR/issue_73223.rs:+6:9: +6:14
+          StorageLive(_6);                 // scope 1 at $DIR/issue_73223.rs:+6:22: +6:27
+          _6 = _1;                         // scope 1 at $DIR/issue_73223.rs:+6:22: +6:27
+          Deinit(_5);                      // scope 1 at $DIR/issue_73223.rs:+6:17: +6:28
+          ((_5 as Some).0: i32) = move _6; // scope 1 at $DIR/issue_73223.rs:+6:17: +6:28
+          discriminant(_5) = 1;            // scope 1 at $DIR/issue_73223.rs:+6:17: +6:28
+          StorageDead(_6);                 // scope 1 at $DIR/issue_73223.rs:+6:27: +6:28
+          StorageLive(_24);                // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageLive(_25);                // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageLive(_7);                 // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _7 = &_1;                        // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           StorageLive(_8);                 // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageLive(_29);                // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageLive(_30);                // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageLive(_10);                // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _10 = &_1;                       // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageLive(_11);                // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _28 = const _;                   // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _23 = const _;                   // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // mir::Constant
                                            // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // + literal: Const { ty: &i32, val: Unevaluated(main, [], Some(promoted[0])) }
-          _11 = _28;                       // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          Deinit(_29);                     // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          Deinit(_30);                     // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _29 = move _10;                  // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _30 = move _11;                  // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageDead(_11);                // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageDead(_10);                // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageLive(_13);                // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _13 = _29;                       // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageLive(_14);                // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _14 = _30;                       // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageLive(_15);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageLive(_16);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageLive(_17);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _17 = (*_13);                    // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageLive(_18);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _18 = const 1_i32;               // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _16 = Eq(move _17, const 1_i32); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageDead(_18);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageDead(_17);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _15 = Not(move _16);             // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageDead(_16);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          switchInt(move _15) -> [0: bb5, otherwise: bb4]; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _8 = _23;                        // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          Deinit(_24);                     // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          Deinit(_25);                     // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _24 = move _7;                   // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _25 = move _8;                   // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageDead(_8);                 // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageDead(_7);                 // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageLive(_9);                 // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _9 = _24;                        // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageLive(_10);                // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _10 = _25;                       // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageLive(_11);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageLive(_12);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageLive(_13);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _13 = (*_9);                     // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageLive(_14);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _14 = const 1_i32;               // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _12 = Eq(move _13, const 1_i32); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageDead(_14);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageDead(_13);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _11 = Not(move _12);             // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageDead(_12);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          switchInt(move _11) -> [0: bb5, otherwise: bb4]; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
       }
   
       bb4: {
-          StorageLive(_20);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          Deinit(_20);                     // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          discriminant(_20) = 0;           // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageLive(_21);                // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageLive(_22);                // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _22 = const core::panicking::AssertKind::Eq; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageLive(_15);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          Deinit(_15);                     // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          discriminant(_15) = 0;           // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageLive(_16);                // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageLive(_17);                // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _17 = const core::panicking::AssertKind::Eq; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // mir::Constant
                                            // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // + literal: Const { ty: core::panicking::AssertKind, val: Value(Scalar(0x00)) }
-          StorageLive(_23);                // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageLive(_24);                // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _24 = _13;                       // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _23 = _24;                       // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageLive(_25);                // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageLive(_26);                // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _26 = _14;                       // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _25 = _26;                       // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageLive(_27);                // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          Deinit(_27);                     // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          discriminant(_27) = 0;           // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _21 = core::panicking::assert_failed::<i32, i32>(const core::panicking::AssertKind::Eq, move _23, move _25, move _27); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageLive(_18);                // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageLive(_19);                // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _19 = _9;                        // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _18 = _19;                       // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageLive(_20);                // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageLive(_21);                // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _21 = _10;                       // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _20 = _21;                       // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageLive(_22);                // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          Deinit(_22);                     // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          discriminant(_22) = 0;           // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _16 = core::panicking::assert_failed::<i32, i32>(const core::panicking::AssertKind::Eq, move _18, move _20, move _22); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // mir::Constant
                                            // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // + literal: Const { ty: for<'a, 'b, 'c> fn(core::panicking::AssertKind, &'a i32, &'b i32, Option<Arguments<'c>>) -> ! {core::panicking::assert_failed::<i32, i32>}, val: Value(<ZST>) }
@@ -150,15 +143,12 @@
       }
   
       bb5: {
-          nop;                             // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageDead(_15);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageDead(_14);                // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageDead(_13);                // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageDead(_29);                // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageDead(_30);                // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageDead(_8);                 // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          nop;                             // scope 0 at $DIR/issue_73223.rs:+0:11: +8:2
-          StorageDead(_6);                 // scope 1 at $DIR/issue_73223.rs:+8:1: +8:2
+          StorageDead(_11);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageDead(_10);                // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageDead(_9);                 // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageDead(_24);                // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageDead(_25);                // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageDead(_5);                 // scope 1 at $DIR/issue_73223.rs:+8:1: +8:2
           StorageDead(_1);                 // scope 0 at $DIR/issue_73223.rs:+8:1: +8:2
           return;                          // scope 0 at $DIR/issue_73223.rs:+8:2: +8:2
       }
diff --git a/src/test/mir-opt/issue_76432.test.SimplifyComparisonIntegral.diff b/src/test/mir-opt/issue_76432.test.SimplifyComparisonIntegral.diff
index e97b46f6ecc..c24543daeac 100644
--- a/src/test/mir-opt/issue_76432.test.SimplifyComparisonIntegral.diff
+++ b/src/test/mir-opt/issue_76432.test.SimplifyComparisonIntegral.diff
@@ -11,26 +11,19 @@
       let mut _6: T;                       // in scope 0 at $DIR/issue_76432.rs:+1:21: +1:22
       let mut _7: T;                       // in scope 0 at $DIR/issue_76432.rs:+1:24: +1:25
       let mut _8: T;                       // in scope 0 at $DIR/issue_76432.rs:+1:27: +1:28
-      let _9: [*const T; 3];               // in scope 0 at $DIR/issue_76432.rs:+2:5: +5:6
+      let mut _9: usize;                   // in scope 0 at $DIR/issue_76432.rs:+3:9: +3:33
       let mut _10: usize;                  // in scope 0 at $DIR/issue_76432.rs:+3:9: +3:33
-      let mut _11: usize;                  // in scope 0 at $DIR/issue_76432.rs:+3:9: +3:33
-      let mut _12: bool;                   // in scope 0 at $DIR/issue_76432.rs:+3:9: +3:33
-      let mut _16: *const T;               // in scope 0 at $DIR/issue_76432.rs:+3:38: +3:52
-      let mut _17: *const T;               // in scope 0 at $DIR/issue_76432.rs:+3:38: +3:52
-      let mut _18: *const T;               // in scope 0 at $DIR/issue_76432.rs:+3:54: +3:68
-      let mut _19: *const T;               // in scope 0 at $DIR/issue_76432.rs:+3:54: +3:68
-      let mut _20: *const T;               // in scope 0 at $DIR/issue_76432.rs:+3:70: +3:84
-      let mut _21: *const T;               // in scope 0 at $DIR/issue_76432.rs:+3:70: +3:84
-      let mut _22: !;                      // in scope 0 at $SRC_DIR/core/src/panic.rs:LL:COL
+      let mut _11: bool;                   // in scope 0 at $DIR/issue_76432.rs:+3:9: +3:33
+      let mut _15: !;                      // in scope 0 at $SRC_DIR/core/src/panic.rs:LL:COL
       scope 1 {
           debug v => _2;                   // in scope 1 at $DIR/issue_76432.rs:+1:9: +1:10
-          let _13: &T;                     // in scope 1 at $DIR/issue_76432.rs:+3:10: +3:16
-          let _14: &T;                     // in scope 1 at $DIR/issue_76432.rs:+3:18: +3:24
-          let _15: &T;                     // in scope 1 at $DIR/issue_76432.rs:+3:26: +3:32
+          let _12: &T;                     // in scope 1 at $DIR/issue_76432.rs:+3:10: +3:16
+          let _13: &T;                     // in scope 1 at $DIR/issue_76432.rs:+3:18: +3:24
+          let _14: &T;                     // in scope 1 at $DIR/issue_76432.rs:+3:26: +3:32
           scope 2 {
-              debug v1 => _13;             // in scope 2 at $DIR/issue_76432.rs:+3:10: +3:16
-              debug v2 => _14;             // in scope 2 at $DIR/issue_76432.rs:+3:18: +3:24
-              debug v3 => _15;             // in scope 2 at $DIR/issue_76432.rs:+3:26: +3:32
+              debug v1 => _12;             // in scope 2 at $DIR/issue_76432.rs:+3:10: +3:16
+              debug v2 => _13;             // in scope 2 at $DIR/issue_76432.rs:+3:18: +3:24
+              debug v3 => _14;             // in scope 2 at $DIR/issue_76432.rs:+3:26: +3:32
           }
       }
   
@@ -54,18 +47,17 @@
           _2 = move _3 as &[T] (Pointer(Unsize)); // scope 0 at $DIR/issue_76432.rs:+1:19: +1:29
           StorageDead(_3);                 // scope 0 at $DIR/issue_76432.rs:+1:28: +1:29
           StorageDead(_4);                 // scope 0 at $DIR/issue_76432.rs:+1:29: +1:30
-          StorageLive(_9);                 // scope 1 at $DIR/issue_76432.rs:+2:5: +5:6
-          _10 = Len((*_2));                // scope 1 at $DIR/issue_76432.rs:+3:9: +3:33
-          _11 = const 3_usize;             // scope 1 at $DIR/issue_76432.rs:+3:9: +3:33
--         _12 = Eq(move _10, const 3_usize); // scope 1 at $DIR/issue_76432.rs:+3:9: +3:33
--         switchInt(move _12) -> [0: bb1, otherwise: bb2]; // scope 1 at $DIR/issue_76432.rs:+3:9: +3:33
+          _9 = Len((*_2));                 // scope 1 at $DIR/issue_76432.rs:+3:9: +3:33
+          _10 = const 3_usize;             // scope 1 at $DIR/issue_76432.rs:+3:9: +3:33
+-         _11 = Eq(move _9, const 3_usize); // scope 1 at $DIR/issue_76432.rs:+3:9: +3:33
+-         switchInt(move _11) -> [0: bb1, otherwise: bb2]; // scope 1 at $DIR/issue_76432.rs:+3:9: +3:33
 +         nop;                             // scope 1 at $DIR/issue_76432.rs:+3:9: +3:33
-+         switchInt(move _10) -> [3: bb2, otherwise: bb1]; // scope 1 at $DIR/issue_76432.rs:+3:9: +3:33
++         switchInt(move _9) -> [3: bb2, otherwise: bb1]; // scope 1 at $DIR/issue_76432.rs:+3:9: +3:33
       }
   
       bb1: {
-          StorageLive(_22);                // scope 1 at $SRC_DIR/core/src/panic.rs:LL:COL
-          _22 = core::panicking::panic(const "internal error: entered unreachable code"); // scope 1 at $SRC_DIR/core/src/panic.rs:LL:COL
+          StorageLive(_15);                // scope 1 at $SRC_DIR/core/src/panic.rs:LL:COL
+          _15 = core::panicking::panic(const "internal error: entered unreachable code"); // scope 1 at $SRC_DIR/core/src/panic.rs:LL:COL
                                            // mir::Constant
                                            // + span: $SRC_DIR/core/src/panic.rs:LL:COL
                                            // + literal: Const { ty: fn(&'static str) -> ! {core::panicking::panic}, val: Value(<ZST>) }
@@ -75,36 +67,15 @@
       }
   
       bb2: {
-          StorageLive(_13);                // scope 1 at $DIR/issue_76432.rs:+3:10: +3:16
-          _13 = &(*_2)[0 of 3];            // scope 1 at $DIR/issue_76432.rs:+3:10: +3:16
-          StorageLive(_14);                // scope 1 at $DIR/issue_76432.rs:+3:18: +3:24
-          _14 = &(*_2)[1 of 3];            // scope 1 at $DIR/issue_76432.rs:+3:18: +3:24
-          StorageLive(_15);                // scope 1 at $DIR/issue_76432.rs:+3:26: +3:32
-          _15 = &(*_2)[2 of 3];            // scope 1 at $DIR/issue_76432.rs:+3:26: +3:32
-          StorageLive(_16);                // scope 2 at $DIR/issue_76432.rs:+3:38: +3:52
-          StorageLive(_17);                // scope 2 at $DIR/issue_76432.rs:+3:38: +3:52
-          _17 = &raw const (*_13);         // scope 2 at $DIR/issue_76432.rs:+3:38: +3:40
-          _16 = _17;                       // scope 2 at $DIR/issue_76432.rs:+3:38: +3:52
-          StorageLive(_18);                // scope 2 at $DIR/issue_76432.rs:+3:54: +3:68
-          StorageLive(_19);                // scope 2 at $DIR/issue_76432.rs:+3:54: +3:68
-          _19 = &raw const (*_14);         // scope 2 at $DIR/issue_76432.rs:+3:54: +3:56
-          _18 = _19;                       // scope 2 at $DIR/issue_76432.rs:+3:54: +3:68
-          StorageLive(_20);                // scope 2 at $DIR/issue_76432.rs:+3:70: +3:84
-          StorageLive(_21);                // scope 2 at $DIR/issue_76432.rs:+3:70: +3:84
-          _21 = &raw const (*_15);         // scope 2 at $DIR/issue_76432.rs:+3:70: +3:72
-          _20 = _21;                       // scope 2 at $DIR/issue_76432.rs:+3:70: +3:84
-          _9 = [move _16, move _18, move _20]; // scope 2 at $DIR/issue_76432.rs:+3:37: +3:85
-          StorageDead(_21);                // scope 2 at $DIR/issue_76432.rs:+3:84: +3:85
-          StorageDead(_20);                // scope 2 at $DIR/issue_76432.rs:+3:84: +3:85
-          StorageDead(_19);                // scope 2 at $DIR/issue_76432.rs:+3:84: +3:85
-          StorageDead(_18);                // scope 2 at $DIR/issue_76432.rs:+3:84: +3:85
-          StorageDead(_17);                // scope 2 at $DIR/issue_76432.rs:+3:84: +3:85
-          StorageDead(_16);                // scope 2 at $DIR/issue_76432.rs:+3:84: +3:85
-          StorageDead(_15);                // scope 1 at $DIR/issue_76432.rs:+3:84: +3:85
+          StorageLive(_12);                // scope 1 at $DIR/issue_76432.rs:+3:10: +3:16
+          _12 = &(*_2)[0 of 3];            // scope 1 at $DIR/issue_76432.rs:+3:10: +3:16
+          StorageLive(_13);                // scope 1 at $DIR/issue_76432.rs:+3:18: +3:24
+          _13 = &(*_2)[1 of 3];            // scope 1 at $DIR/issue_76432.rs:+3:18: +3:24
+          StorageLive(_14);                // scope 1 at $DIR/issue_76432.rs:+3:26: +3:32
+          _14 = &(*_2)[2 of 3];            // scope 1 at $DIR/issue_76432.rs:+3:26: +3:32
           StorageDead(_14);                // scope 1 at $DIR/issue_76432.rs:+3:84: +3:85
           StorageDead(_13);                // scope 1 at $DIR/issue_76432.rs:+3:84: +3:85
-          StorageDead(_9);                 // scope 1 at $DIR/issue_76432.rs:+5:6: +5:7
-          nop;                             // scope 0 at $DIR/issue_76432.rs:+0:44: +6:2
+          StorageDead(_12);                // scope 1 at $DIR/issue_76432.rs:+3:84: +3:85
           StorageDead(_5);                 // scope 0 at $DIR/issue_76432.rs:+6:1: +6:2
           StorageDead(_2);                 // scope 0 at $DIR/issue_76432.rs:+6:1: +6:2
           return;                          // scope 0 at $DIR/issue_76432.rs:+6:2: +6:2
diff --git a/src/test/mir-opt/simplify_if.main.SimplifyConstCondition-after-const-prop.diff b/src/test/mir-opt/simplify_if.main.SimplifyConstCondition-after-const-prop.diff
index aea01147443..f9e22866bee 100644
--- a/src/test/mir-opt/simplify_if.main.SimplifyConstCondition-after-const-prop.diff
+++ b/src/test/mir-opt/simplify_if.main.SimplifyConstCondition-after-const-prop.diff
@@ -23,12 +23,10 @@
   
       bb2: {
           StorageDead(_2);                 // scope 0 at $DIR/simplify_if.rs:+2:15: +2:16
-          nop;                             // scope 0 at $DIR/simplify_if.rs:+1:14: +3:6
           goto -> bb4;                     // scope 0 at $DIR/simplify_if.rs:+1:5: +3:6
       }
   
       bb3: {
-          nop;                             // scope 0 at $DIR/simplify_if.rs:+3:6: +3:6
           goto -> bb4;                     // scope 0 at $DIR/simplify_if.rs:+1:5: +3:6
       }
   
diff --git a/src/test/mir-opt/simplify_locals.c.SimplifyLocals.diff b/src/test/mir-opt/simplify_locals.c.SimplifyLocals-before-const-prop.diff
index 1a5143aa0fa..1be27e96397 100644
--- a/src/test/mir-opt/simplify_locals.c.SimplifyLocals.diff
+++ b/src/test/mir-opt/simplify_locals.c.SimplifyLocals-before-const-prop.diff
@@ -1,5 +1,5 @@
-- // MIR for `c` before SimplifyLocals
-+ // MIR for `c` after SimplifyLocals
+- // MIR for `c` before SimplifyLocals-before-const-prop
++ // MIR for `c` after SimplifyLocals-before-const-prop
   
   fn c() -> () {
       let mut _0: ();                      // return place in scope 0 at $DIR/simplify_locals.rs:+0:8: +0:8
diff --git a/src/test/mir-opt/simplify_locals.d1.SimplifyLocals.diff b/src/test/mir-opt/simplify_locals.d1.SimplifyLocals-before-const-prop.diff
index 6426bf926a4..98173803018 100644
--- a/src/test/mir-opt/simplify_locals.d1.SimplifyLocals.diff
+++ b/src/test/mir-opt/simplify_locals.d1.SimplifyLocals-before-const-prop.diff
@@ -1,5 +1,5 @@
-- // MIR for `d1` before SimplifyLocals
-+ // MIR for `d1` after SimplifyLocals
+- // MIR for `d1` before SimplifyLocals-before-const-prop
++ // MIR for `d1` after SimplifyLocals-before-const-prop
   
   fn d1() -> () {
       let mut _0: ();                      // return place in scope 0 at $DIR/simplify_locals.rs:+0:9: +0:9
diff --git a/src/test/mir-opt/simplify_locals.d2.SimplifyLocals.diff b/src/test/mir-opt/simplify_locals.d2.SimplifyLocals-before-const-prop.diff
index db5ab182d6f..b152dc8cca3 100644
--- a/src/test/mir-opt/simplify_locals.d2.SimplifyLocals.diff
+++ b/src/test/mir-opt/simplify_locals.d2.SimplifyLocals-before-const-prop.diff
@@ -1,5 +1,5 @@
-- // MIR for `d2` before SimplifyLocals
-+ // MIR for `d2` after SimplifyLocals
+- // MIR for `d2` before SimplifyLocals-before-const-prop
++ // MIR for `d2` after SimplifyLocals-before-const-prop
   
   fn d2() -> () {
       let mut _0: ();                      // return place in scope 0 at $DIR/simplify_locals.rs:+0:9: +0:9
diff --git a/src/test/mir-opt/simplify_locals.expose_addr.SimplifyLocals.diff b/src/test/mir-opt/simplify_locals.expose_addr.SimplifyLocals-before-const-prop.diff
index c707b0da07e..9ca1dbbd071 100644
--- a/src/test/mir-opt/simplify_locals.expose_addr.SimplifyLocals.diff
+++ b/src/test/mir-opt/simplify_locals.expose_addr.SimplifyLocals-before-const-prop.diff
@@ -1,5 +1,5 @@
-- // MIR for `expose_addr` before SimplifyLocals
-+ // MIR for `expose_addr` after SimplifyLocals
+- // MIR for `expose_addr` before SimplifyLocals-before-const-prop
++ // MIR for `expose_addr` after SimplifyLocals-before-const-prop
   
   fn expose_addr(_1: *const usize) -> () {
       debug p => _1;                       // in scope 0 at $DIR/simplify_locals.rs:+0:16: +0:17
diff --git a/src/test/mir-opt/simplify_locals.r.SimplifyLocals.diff b/src/test/mir-opt/simplify_locals.r.SimplifyLocals-before-const-prop.diff
index ff6eb2cff5e..19dacb427f5 100644
--- a/src/test/mir-opt/simplify_locals.r.SimplifyLocals.diff
+++ b/src/test/mir-opt/simplify_locals.r.SimplifyLocals-before-const-prop.diff
@@ -1,5 +1,5 @@
-- // MIR for `r` before SimplifyLocals
-+ // MIR for `r` after SimplifyLocals
+- // MIR for `r` before SimplifyLocals-before-const-prop
++ // MIR for `r` after SimplifyLocals-before-const-prop
   
   fn r() -> () {
       let mut _0: ();                      // return place in scope 0 at $DIR/simplify_locals.rs:+0:8: +0:8
diff --git a/src/test/mir-opt/simplify_locals.rs b/src/test/mir-opt/simplify_locals.rs
index 89d9391f832..7bbc0481c68 100644
--- a/src/test/mir-opt/simplify_locals.rs
+++ b/src/test/mir-opt/simplify_locals.rs
@@ -1,4 +1,4 @@
-// unit-test: SimplifyLocals
+// unit-test: SimplifyLocals-before-const-prop
 
 
 #![feature(thread_local)]
@@ -9,26 +9,26 @@ enum E {
      B,
 }
 
-// EMIT_MIR simplify_locals.c.SimplifyLocals.diff
+// EMIT_MIR simplify_locals.c.SimplifyLocals-before-const-prop.diff
 fn c() {
     let bytes = [0u8; 10];
     // Unused cast
     let _: &[u8] = &bytes;
 }
 
-// EMIT_MIR simplify_locals.d1.SimplifyLocals.diff
+// EMIT_MIR simplify_locals.d1.SimplifyLocals-before-const-prop.diff
 fn d1() {
     // Unused set discriminant
     let _ = E::A;
 }
 
-// EMIT_MIR simplify_locals.d2.SimplifyLocals.diff
+// EMIT_MIR simplify_locals.d2.SimplifyLocals-before-const-prop.diff
 fn d2() {
     // Unused set discriminant
     {(10, E::A)}.1 = E::B;
 }
 
-// EMIT_MIR simplify_locals.r.SimplifyLocals.diff
+// EMIT_MIR simplify_locals.r.SimplifyLocals-before-const-prop.diff
 fn r() {
     let mut a = 1;
     // Unused references
@@ -38,31 +38,31 @@ fn r() {
 
 #[thread_local] static mut X: u32 = 0;
 
-// EMIT_MIR simplify_locals.t1.SimplifyLocals.diff
+// EMIT_MIR simplify_locals.t1.SimplifyLocals-before-const-prop.diff
 fn t1() {
     // Unused thread local
     unsafe { X };
 }
 
-// EMIT_MIR simplify_locals.t2.SimplifyLocals.diff
+// EMIT_MIR simplify_locals.t2.SimplifyLocals-before-const-prop.diff
 fn t2() {
     // Unused thread local
     unsafe { &mut X };
 }
 
-// EMIT_MIR simplify_locals.t3.SimplifyLocals.diff
+// EMIT_MIR simplify_locals.t3.SimplifyLocals-before-const-prop.diff
 fn t3() {
     // Unused thread local
     unsafe { *&mut X };
 }
 
-// EMIT_MIR simplify_locals.t4.SimplifyLocals.diff
+// EMIT_MIR simplify_locals.t4.SimplifyLocals-before-const-prop.diff
 fn t4() -> u32 {
     // Used thread local
     unsafe { X + 1 }
 }
 
-// EMIT_MIR simplify_locals.expose_addr.SimplifyLocals.diff
+// EMIT_MIR simplify_locals.expose_addr.SimplifyLocals-before-const-prop.diff
 fn expose_addr(p: *const usize) {
     // Used pointer to address cast. Has a side effect of exposing the provenance.
     p as usize;
diff --git a/src/test/mir-opt/simplify_locals.t1.SimplifyLocals.diff b/src/test/mir-opt/simplify_locals.t1.SimplifyLocals-before-const-prop.diff
index 49db7747963..1b2e1158e45 100644
--- a/src/test/mir-opt/simplify_locals.t1.SimplifyLocals.diff
+++ b/src/test/mir-opt/simplify_locals.t1.SimplifyLocals-before-const-prop.diff
@@ -1,5 +1,5 @@
-- // MIR for `t1` before SimplifyLocals
-+ // MIR for `t1` after SimplifyLocals
+- // MIR for `t1` before SimplifyLocals-before-const-prop
++ // MIR for `t1` after SimplifyLocals-before-const-prop
   
   fn t1() -> () {
       let mut _0: ();                      // return place in scope 0 at $DIR/simplify_locals.rs:+0:9: +0:9
diff --git a/src/test/mir-opt/simplify_locals.t2.SimplifyLocals.diff b/src/test/mir-opt/simplify_locals.t2.SimplifyLocals-before-const-prop.diff
index e3f4ae3701b..cf019357be7 100644
--- a/src/test/mir-opt/simplify_locals.t2.SimplifyLocals.diff
+++ b/src/test/mir-opt/simplify_locals.t2.SimplifyLocals-before-const-prop.diff
@@ -1,5 +1,5 @@
-- // MIR for `t2` before SimplifyLocals
-+ // MIR for `t2` after SimplifyLocals
+- // MIR for `t2` before SimplifyLocals-before-const-prop
++ // MIR for `t2` after SimplifyLocals-before-const-prop
   
   fn t2() -> () {
       let mut _0: ();                      // return place in scope 0 at $DIR/simplify_locals.rs:+0:9: +0:9
diff --git a/src/test/mir-opt/simplify_locals.t3.SimplifyLocals.diff b/src/test/mir-opt/simplify_locals.t3.SimplifyLocals-before-const-prop.diff
index f1ce7778e19..90ee215808c 100644
--- a/src/test/mir-opt/simplify_locals.t3.SimplifyLocals.diff
+++ b/src/test/mir-opt/simplify_locals.t3.SimplifyLocals-before-const-prop.diff
@@ -1,5 +1,5 @@
-- // MIR for `t3` before SimplifyLocals
-+ // MIR for `t3` after SimplifyLocals
+- // MIR for `t3` before SimplifyLocals-before-const-prop
++ // MIR for `t3` after SimplifyLocals-before-const-prop
   
   fn t3() -> () {
       let mut _0: ();                      // return place in scope 0 at $DIR/simplify_locals.rs:+0:9: +0:9
diff --git a/src/test/mir-opt/simplify_locals.t4.SimplifyLocals.diff b/src/test/mir-opt/simplify_locals.t4.SimplifyLocals-before-const-prop.diff
index 71cf9594b9e..9add9a6c5e0 100644
--- a/src/test/mir-opt/simplify_locals.t4.SimplifyLocals.diff
+++ b/src/test/mir-opt/simplify_locals.t4.SimplifyLocals-before-const-prop.diff
@@ -1,5 +1,5 @@
-- // MIR for `t4` before SimplifyLocals
-+ // MIR for `t4` after SimplifyLocals
+- // MIR for `t4` before SimplifyLocals-before-const-prop
++ // MIR for `t4` after SimplifyLocals-before-const-prop
   
   fn t4() -> u32 {
       let mut _0: u32;                     // return place in scope 0 at $DIR/simplify_locals.rs:+0:12: +0:15
diff --git a/src/test/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals.diff b/src/test/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.diff
index a2b55229303..f888c622d90 100644
--- a/src/test/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals.diff
+++ b/src/test/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.diff
@@ -1,5 +1,5 @@
-- // MIR for `foo` before SimplifyLocals
-+ // MIR for `foo` after SimplifyLocals
+- // MIR for `foo` before SimplifyLocals-final
++ // MIR for `foo` after SimplifyLocals-final
   
   fn foo() -> () {
       let mut _0: ();                      // return place in scope 0 at $DIR/simplify_locals_fixedpoint.rs:+0:13: +0:13
diff --git a/src/test/mir-opt/simplify_locals_fixedpoint.rs b/src/test/mir-opt/simplify_locals_fixedpoint.rs
index 78b1f9f55e5..1fdba6e99e3 100644
--- a/src/test/mir-opt/simplify_locals_fixedpoint.rs
+++ b/src/test/mir-opt/simplify_locals_fixedpoint.rs
@@ -12,4 +12,4 @@ fn main() {
     foo::<()>();
 }
 
-// EMIT_MIR simplify_locals_fixedpoint.foo.SimplifyLocals.diff
+// EMIT_MIR simplify_locals_fixedpoint.foo.SimplifyLocals-final.diff
diff --git a/src/test/mir-opt/simplify_locals_removes_unused_consts.main.SimplifyLocals.diff b/src/test/mir-opt/simplify_locals_removes_unused_consts.main.SimplifyLocals-before-const-prop.diff
index 78272272b07..efb2b0961cc 100644
--- a/src/test/mir-opt/simplify_locals_removes_unused_consts.main.SimplifyLocals.diff
+++ b/src/test/mir-opt/simplify_locals_removes_unused_consts.main.SimplifyLocals-before-const-prop.diff
@@ -1,5 +1,5 @@
-- // MIR for `main` before SimplifyLocals
-+ // MIR for `main` after SimplifyLocals
+- // MIR for `main` before SimplifyLocals-before-const-prop
++ // MIR for `main` after SimplifyLocals-before-const-prop
   
   fn main() -> () {
       let mut _0: ();                      // return place in scope 0 at $DIR/simplify_locals_removes_unused_consts.rs:+0:11: +0:11
diff --git a/src/test/mir-opt/simplify_locals_removes_unused_consts.rs b/src/test/mir-opt/simplify_locals_removes_unused_consts.rs
index 39b7911d4ae..7a03a2837ae 100644
--- a/src/test/mir-opt/simplify_locals_removes_unused_consts.rs
+++ b/src/test/mir-opt/simplify_locals_removes_unused_consts.rs
@@ -1,4 +1,4 @@
-// unit-test: SimplifyLocals
+// unit-test: SimplifyLocals-before-const-prop
 // compile-flags: -C overflow-checks=no
 
 fn use_zst(_: ((), ())) {}
@@ -9,7 +9,7 @@ struct Temp {
 
 fn use_u8(_: u8) {}
 
-// EMIT_MIR simplify_locals_removes_unused_consts.main.SimplifyLocals.diff
+// EMIT_MIR simplify_locals_removes_unused_consts.main.SimplifyLocals-before-const-prop.diff
 fn main() {
     let ((), ()) = ((), ());
     use_zst(((), ()));
diff --git a/src/test/mir-opt/simplify_locals_removes_unused_discriminant_reads.map.SimplifyLocals.diff b/src/test/mir-opt/simplify_locals_removes_unused_discriminant_reads.map.SimplifyLocals-before-const-prop.diff
index 9ec138dd82f..027c983e6b4 100644
--- a/src/test/mir-opt/simplify_locals_removes_unused_discriminant_reads.map.SimplifyLocals.diff
+++ b/src/test/mir-opt/simplify_locals_removes_unused_discriminant_reads.map.SimplifyLocals-before-const-prop.diff
@@ -1,5 +1,5 @@
-- // MIR for `map` before SimplifyLocals
-+ // MIR for `map` after SimplifyLocals
+- // MIR for `map` before SimplifyLocals-before-const-prop
++ // MIR for `map` after SimplifyLocals-before-const-prop
   
   fn map(_1: Option<Box<()>>) -> Option<Box<()>> {
       debug x => _1;                       // in scope 0 at $DIR/simplify_locals_removes_unused_discriminant_reads.rs:+0:8: +0:9
diff --git a/src/test/mir-opt/simplify_locals_removes_unused_discriminant_reads.rs b/src/test/mir-opt/simplify_locals_removes_unused_discriminant_reads.rs
index d09bd92c4e8..de65857412c 100644
--- a/src/test/mir-opt/simplify_locals_removes_unused_discriminant_reads.rs
+++ b/src/test/mir-opt/simplify_locals_removes_unused_discriminant_reads.rs
@@ -1,4 +1,4 @@
-// unit-test: SimplifyLocals
+// unit-test: SimplifyLocals-before-const-prop
 
 fn map(x: Option<Box<()>>) -> Option<Box<()>> {
     match x {
@@ -11,4 +11,4 @@ fn main() {
     map(None);
 }
 
-// EMIT_MIR simplify_locals_removes_unused_discriminant_reads.map.SimplifyLocals.diff
+// EMIT_MIR simplify_locals_removes_unused_discriminant_reads.map.SimplifyLocals-before-const-prop.diff
diff --git a/src/test/mir-opt/simplify_match.main.ConstProp.diff b/src/test/mir-opt/simplify_match.main.ConstProp.diff
index f00ac5716a7..70bfbf1b3e3 100644
--- a/src/test/mir-opt/simplify_match.main.ConstProp.diff
+++ b/src/test/mir-opt/simplify_match.main.ConstProp.diff
@@ -21,7 +21,6 @@
       }
   
       bb1: {
-          nop;                             // scope 0 at $DIR/simplify_match.rs:+3:18: +3:20
           goto -> bb3;                     // scope 0 at $DIR/simplify_match.rs:+3:18: +3:20
       }
   
diff --git a/src/test/mir-opt/uninhabited_enum.process_never.SimplifyLocals.after.mir b/src/test/mir-opt/uninhabited_enum.process_never.SimplifyLocals-final.after.mir
index 2c0fcc6621a..b4fb330f3df 100644
--- a/src/test/mir-opt/uninhabited_enum.process_never.SimplifyLocals.after.mir
+++ b/src/test/mir-opt/uninhabited_enum.process_never.SimplifyLocals-final.after.mir
@@ -1,4 +1,4 @@
-// MIR for `process_never` after SimplifyLocals
+// MIR for `process_never` after SimplifyLocals-final
 
 fn process_never(_1: *const !) -> () {
     debug input => _1;                   // in scope 0 at $DIR/uninhabited_enum.rs:+0:22: +0:27
diff --git a/src/test/mir-opt/uninhabited_enum.process_void.SimplifyLocals.after.mir b/src/test/mir-opt/uninhabited_enum.process_void.SimplifyLocals-final.after.mir
index ae341a7b97b..2af864998cb 100644
--- a/src/test/mir-opt/uninhabited_enum.process_void.SimplifyLocals.after.mir
+++ b/src/test/mir-opt/uninhabited_enum.process_void.SimplifyLocals-final.after.mir
@@ -1,4 +1,4 @@
-// MIR for `process_void` after SimplifyLocals
+// MIR for `process_void` after SimplifyLocals-final
 
 fn process_void(_1: *const Void) -> () {
     debug input => _1;                   // in scope 0 at $DIR/uninhabited_enum.rs:+0:21: +0:26
diff --git a/src/test/mir-opt/uninhabited_enum.rs b/src/test/mir-opt/uninhabited_enum.rs
index 97c6e8cd531..19db548157a 100644
--- a/src/test/mir-opt/uninhabited_enum.rs
+++ b/src/test/mir-opt/uninhabited_enum.rs
@@ -2,13 +2,13 @@
 
 pub enum Void {}
 
-// EMIT_MIR uninhabited_enum.process_never.SimplifyLocals.after.mir
+// EMIT_MIR uninhabited_enum.process_never.SimplifyLocals-final.after.mir
 #[no_mangle]
 pub fn process_never(input: *const !) {
    let _input = unsafe { &*input };
 }
 
-// EMIT_MIR uninhabited_enum.process_void.SimplifyLocals.after.mir
+// EMIT_MIR uninhabited_enum.process_void.SimplifyLocals-final.after.mir
 #[no_mangle]
 pub fn process_void(input: *const Void) {
    let _input = unsafe { &*input };
diff --git a/src/test/mir-opt/while_let_loops.change_loop_body.ConstProp.diff b/src/test/mir-opt/while_let_loops.change_loop_body.ConstProp.diff
index 984ef476e10..bb1de59d4a7 100644
--- a/src/test/mir-opt/while_let_loops.change_loop_body.ConstProp.diff
+++ b/src/test/mir-opt/while_let_loops.change_loop_body.ConstProp.diff
@@ -4,13 +4,8 @@
   fn change_loop_body() -> () {
       let mut _0: ();                      // return place in scope 0 at $DIR/while_let_loops.rs:+0:27: +0:27
       let mut _1: i32;                     // in scope 0 at $DIR/while_let_loops.rs:+1:9: +1:15
-      let mut _2: ();                      // in scope 0 at $DIR/while_let_loops.rs:+0:1: +6:2
-      let mut _3: std::option::Option<u32>; // in scope 0 at $DIR/while_let_loops.rs:+2:28: +2:32
-      let mut _4: isize;                   // in scope 0 at $DIR/while_let_loops.rs:+2:15: +2:25
-      let mut _5: !;                       // in scope 0 at $DIR/while_let_loops.rs:+2:33: +5:6
-      let mut _6: !;                       // in scope 0 at $DIR/while_let_loops.rs:+2:5: +5:6
-      let _7: ();                          // in scope 0 at $DIR/while_let_loops.rs:+2:5: +5:6
-      let mut _8: !;                       // in scope 0 at $DIR/while_let_loops.rs:+2:5: +5:6
+      let mut _2: std::option::Option<u32>; // in scope 0 at $DIR/while_let_loops.rs:+2:28: +2:32
+      let mut _3: isize;                   // in scope 0 at $DIR/while_let_loops.rs:+2:15: +2:25
       scope 1 {
           debug _x => _1;                  // in scope 1 at $DIR/while_let_loops.rs:+1:9: +1:15
           scope 2 {
@@ -20,34 +15,30 @@
       bb0: {
           StorageLive(_1);                 // scope 0 at $DIR/while_let_loops.rs:+1:9: +1:15
           _1 = const 0_i32;                // scope 0 at $DIR/while_let_loops.rs:+1:18: +1:19
-          StorageLive(_3);                 // scope 2 at $DIR/while_let_loops.rs:+2:28: +2:32
-          Deinit(_3);                      // scope 2 at $DIR/while_let_loops.rs:+2:28: +2:32
-          discriminant(_3) = 0;            // scope 2 at $DIR/while_let_loops.rs:+2:28: +2:32
--         _4 = discriminant(_3);           // scope 2 at $DIR/while_let_loops.rs:+2:15: +2:25
--         switchInt(move _4) -> [1: bb1, otherwise: bb3]; // scope 2 at $DIR/while_let_loops.rs:+2:15: +2:25
-+         _4 = const 0_isize;              // scope 2 at $DIR/while_let_loops.rs:+2:15: +2:25
+          StorageLive(_2);                 // scope 2 at $DIR/while_let_loops.rs:+2:28: +2:32
+          Deinit(_2);                      // scope 2 at $DIR/while_let_loops.rs:+2:28: +2:32
+          discriminant(_2) = 0;            // scope 2 at $DIR/while_let_loops.rs:+2:28: +2:32
+-         _3 = discriminant(_2);           // scope 2 at $DIR/while_let_loops.rs:+2:15: +2:25
+-         switchInt(move _3) -> [1: bb1, otherwise: bb3]; // scope 2 at $DIR/while_let_loops.rs:+2:15: +2:25
++         _3 = const 0_isize;              // scope 2 at $DIR/while_let_loops.rs:+2:15: +2:25
 +         switchInt(const 0_isize) -> [1: bb1, otherwise: bb3]; // scope 2 at $DIR/while_let_loops.rs:+2:15: +2:25
       }
   
       bb1: {
-          switchInt(((_3 as Some).0: u32)) -> [0: bb2, otherwise: bb3]; // scope 2 at $DIR/while_let_loops.rs:+2:15: +2:25
+          switchInt(((_2 as Some).0: u32)) -> [0: bb2, otherwise: bb3]; // scope 2 at $DIR/while_let_loops.rs:+2:15: +2:25
       }
   
       bb2: {
           _1 = const 1_i32;                // scope 2 at $DIR/while_let_loops.rs:+3:9: +3:15
-          nop;                             // scope 2 at $DIR/while_let_loops.rs:+4:9: +4:14
           goto -> bb4;                     // scope 2 at $DIR/while_let_loops.rs:+4:9: +4:14
       }
   
       bb3: {
-          StorageLive(_7);                 // scope 1 at $DIR/while_let_loops.rs:+2:5: +5:6
-          nop;                             // scope 1 at $DIR/while_let_loops.rs:+2:5: +5:6
-          StorageDead(_7);                 // scope 1 at $DIR/while_let_loops.rs:+5:5: +5:6
           goto -> bb4;                     // scope 1 at no-location
       }
   
       bb4: {
-          StorageDead(_3);                 // scope 1 at $DIR/while_let_loops.rs:+5:5: +5:6
+          StorageDead(_2);                 // scope 1 at $DIR/while_let_loops.rs:+5:5: +5:6
           StorageDead(_1);                 // scope 0 at $DIR/while_let_loops.rs:+6:1: +6:2
           return;                          // scope 0 at $DIR/while_let_loops.rs:+6:2: +6:2
       }
diff --git a/src/test/mir-opt/while_storage.while_loop.PreCodegen.after.mir b/src/test/mir-opt/while_storage.while_loop.PreCodegen.after.mir
index 1556c240dc5..b95d91b13dd 100644
--- a/src/test/mir-opt/while_storage.while_loop.PreCodegen.after.mir
+++ b/src/test/mir-opt/while_storage.while_loop.PreCodegen.after.mir
@@ -44,7 +44,7 @@ fn while_loop(_1: bool) -> () {
 
     bb5: {
         StorageDead(_4);                 // scope 0 at $DIR/while_storage.rs:+4:9: +4:10
-        goto -> bb8;                     // scope 0 at no-location
+        goto -> bb7;                     // scope 0 at no-location
     }
 
     bb6: {
@@ -54,10 +54,6 @@ fn while_loop(_1: bool) -> () {
     }
 
     bb7: {
-        goto -> bb8;                     // scope 0 at no-location
-    }
-
-    bb8: {
         StorageDead(_2);                 // scope 0 at $DIR/while_storage.rs:+5:5: +5:6
         return;                          // scope 0 at $DIR/while_storage.rs:+6:2: +6:2
     }
diff --git a/src/test/run-make/dump-mono-stats/Makefile b/src/test/run-make/dump-mono-stats/Makefile
new file mode 100644
index 00000000000..fe1112fb0a4
--- /dev/null
+++ b/src/test/run-make/dump-mono-stats/Makefile
@@ -0,0 +1,5 @@
+include ../../run-make-fulldeps/tools.mk
+
+all:
+	$(RUSTC) --crate-type lib foo.rs -Z dump-mono-stats=$(TMPDIR) -Zdump-mono-stats-format=json
+	cat $(TMPDIR)/foo.mono_items.json | $(CGREP) '"name":"bar"'
diff --git a/src/test/run-make/dump-mono-stats/foo.rs b/src/test/run-make/dump-mono-stats/foo.rs
new file mode 100644
index 00000000000..c5c0bc606cd
--- /dev/null
+++ b/src/test/run-make/dump-mono-stats/foo.rs
@@ -0,0 +1 @@
+pub fn bar() {}
diff --git a/src/test/rustdoc-gui/anchors.goml b/src/test/rustdoc-gui/anchors.goml
index fb8e288fae8..c9b53a1a0f7 100644
--- a/src/test/rustdoc-gui/anchors.goml
+++ b/src/test/rustdoc-gui/anchors.goml
@@ -3,70 +3,72 @@
 define-function: (
     "check-colors",
     (theme, main_color, title_color, fqn_color, fqn_type_color, src_link_color, sidebar_link_color),
-    [
-        ("goto", "file://" + |DOC_PATH| + "/staged_api/struct.Foo.html"),
+    block {
+        goto: "file://" + |DOC_PATH| + "/staged_api/struct.Foo.html"
         // This is needed to ensure that the text color is computed.
-        ("show-text", true),
+        show-text: true
 
         // Setting the theme.
-        ("local-storage", {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}),
+        local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}
         // We reload the page so the local storage settings are being used.
-        ("reload"),
+        reload:
 
-        ("assert-css", ("#toggle-all-docs", {"color": |main_color|})),
-        ("assert-css", (".fqn a:nth-of-type(1)", {"color": |fqn_color|})),
-        ("assert-css", (".fqn a:nth-of-type(2)", {"color": |fqn_type_color|})),
-        ("assert-css", (
+        assert-css: ("#toggle-all-docs", {"color": |main_color|})
+        assert-css: (".fqn a:nth-of-type(1)", {"color": |fqn_color|})
+        assert-css: (".fqn a:nth-of-type(2)", {"color": |fqn_type_color|})
+        assert-css: (
              ".rightside .srclink",
              {"color": |src_link_color|, "text-decoration": "none solid " + |src_link_color|},
              ALL,
-        )),
-        (
-            "compare-elements-css",
-            (".rightside .srclink", ".rightside.srclink", ["color", "text-decoration"]),
-        ),
-        (
-            "compare-elements-css",
-            (".main-heading .srclink", ".rightside.srclink", ["color", "text-decoration"]),
-        ),
+        )
+        compare-elements-css: (
+            ".rightside .srclink",
+            ".rightside.srclink",
+            ["color", "text-decoration"],
+        )
+        compare-elements-css: (
+            ".main-heading .srclink",
+            ".rightside.srclink",
+            ["color", "text-decoration"],
+        )
 
-        ("move-cursor-to", ".main-heading .srclink"),
-        ("assert-css", (
+        move-cursor-to: ".main-heading .srclink"
+        assert-css: (
              ".main-heading .srclink",
              {"color": |src_link_color|, "text-decoration": "underline solid " + |src_link_color|},
-        )),
-        ("move-cursor-to", ".impl-items .rightside .srclink"),
-        ("assert-css", (
+        )
+        move-cursor-to: ".impl-items .rightside .srclink"
+        assert-css: (
              ".impl-items .rightside .srclink",
              {"color": |src_link_color|, "text-decoration": "none solid " + |src_link_color|},
-        )),
-        ("move-cursor-to", ".impl-items .rightside.srclink"),
-        ("assert-css", (
+        )
+        move-cursor-to: ".impl-items .rightside.srclink"
+        assert-css: (
              ".impl-items .rightside.srclink",
              {"color": |src_link_color|, "text-decoration": "none solid " + |src_link_color|},
-        )),
+        )
 
-        ("goto", "file://" + |DOC_PATH| + "/test_docs/struct.HeavilyDocumentedStruct.html"),
+        goto: "file://" + |DOC_PATH| + "/test_docs/struct.HeavilyDocumentedStruct.html"
         // Since we changed page, we need to set the theme again.
-        ("local-storage", {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}),
+        local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}
         // We reload the page so the local storage settings are being used.
-        ("reload"),
+        reload:
 
-        ("assert-css", ("#top-doc-prose-title", {"color": |title_color|})),
+        assert-css: ("#top-doc-prose-title", {"color": |title_color|})
 
-        ("assert-css", (".sidebar a", {"color": |sidebar_link_color|})),
-        ("assert-css", ("h1.fqn a", {"color": |title_color|})),
+        assert-css: (".sidebar a", {"color": |sidebar_link_color|})
+        assert-css: ("h1.fqn a", {"color": |title_color|})
 
         // We move the cursor over the "Implementations" title so the anchor is displayed.
-        ("move-cursor-to", "h2#implementations"),
-        ("assert-css", ("h2#implementations a.anchor", {"color": |main_color|})),
+        move-cursor-to: "h2#implementations"
+        assert-css: ("h2#implementations a.anchor", {"color": |main_color|})
 
         // Same thing with the impl block title.
-        ("move-cursor-to", "#impl-HeavilyDocumentedStruct"),
-        ("assert-css", ("#impl-HeavilyDocumentedStruct a.anchor", {"color": |main_color|})),
+        move-cursor-to: "#impl-HeavilyDocumentedStruct"
+        assert-css: ("#impl-HeavilyDocumentedStruct a.anchor", {"color": |main_color|})
 
-        ("assert-css", ("#title-for-struct-impl-item-doc", {"margin-left": "0px"})),
-    ],
+        assert-css: ("#title-for-struct-impl-item-doc", {"margin-left": "0px"})
+    },
 )
 
 call-function: (
diff --git a/src/test/rustdoc-gui/code-color.goml b/src/test/rustdoc-gui/code-color.goml
index 118f04ad6dc..cb550a4573a 100644
--- a/src/test/rustdoc-gui/code-color.goml
+++ b/src/test/rustdoc-gui/code-color.goml
@@ -9,14 +9,14 @@ show-text: true
 define-function: (
     "check-colors",
     (theme, doc_code_color, doc_inline_code_color),
-    [
+    block {
         // Set the theme.
-        ("local-storage", {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}),
+        local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}
         // We reload the page so the local storage settings are being used.
-        ("reload"),
-        ("assert-css", (".docblock pre > code", {"color": |doc_code_color|}, ALL)),
-        ("assert-css", (".docblock > p > code", {"color": |doc_inline_code_color|}, ALL)),
-    ],
+        reload:
+        assert-css: (".docblock pre > code", {"color": |doc_code_color|}, ALL)
+        assert-css: (".docblock > p > code", {"color": |doc_inline_code_color|}, ALL)
+    },
 )
 
 call-function: ("check-colors", ("ayu", "rgb(230, 225, 207)", "rgb(255, 180, 84)"))
diff --git a/src/test/rustdoc-gui/codeblock-tooltip.goml b/src/test/rustdoc-gui/codeblock-tooltip.goml
index d4443f821d2..a3ef4e77b54 100644
--- a/src/test/rustdoc-gui/codeblock-tooltip.goml
+++ b/src/test/rustdoc-gui/codeblock-tooltip.goml
@@ -5,32 +5,32 @@ show-text: true
 define-function: (
     "check-colors",
     (theme, background, color, border),
-    [
+    block {
         // Setting the theme.
-        ("local-storage", {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}),
-        ("reload"),
+        local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}
+        reload:
 
         // compile_fail block
-        ("assert-css", (
+        assert-css: (
             ".docblock .example-wrap.compile_fail .tooltip",
             {"color": "rgba(255, 0, 0, 0.5)"},
-        )),
-        ("assert-css", (
+        )
+        assert-css: (
             ".docblock .example-wrap.compile_fail",
             {"border-left": "2px solid rgba(255, 0, 0, 0.5)"},
-        )),
+        )
 
-        ("move-cursor-to", ".docblock .example-wrap.compile_fail .tooltip"),
+        move-cursor-to: ".docblock .example-wrap.compile_fail .tooltip"
 
-        ("assert-css", (
+        assert-css: (
             ".docblock .example-wrap.compile_fail .tooltip",
             {"color": "rgb(255, 0, 0)"},
-        )),
-        ("assert-css", (
+        )
+        assert-css: (
             ".docblock .example-wrap.compile_fail",
             {"border-left": "2px solid rgb(255, 0, 0)"},
-        )),
-        ("assert-css", (
+        )
+        assert-css: (
             ".docblock .example-wrap.compile_fail .tooltip::after",
             {
                 "content": '"This example deliberately fails to compile"',
@@ -39,37 +39,37 @@ define-function: (
                 "color": |color|,
                 "border": "1px solid " + |border|,
             },
-        )),
-        ("assert-css", (
+        )
+        assert-css: (
             ".docblock .example-wrap.compile_fail .tooltip::before",
             {
                 "border-width": "5px",
                 "border-style": "solid",
                 "border-color": "rgba(0, 0, 0, 0) " + |background| + " rgba(0, 0, 0, 0) rgba(0, 0, 0, 0)",
             },
-        )),
+        )
 
         // should_panic block
-        ("assert-css", (
+        assert-css: (
             ".docblock .example-wrap.should_panic .tooltip",
             {"color": "rgba(255, 0, 0, 0.5)"},
-        )),
-        ("assert-css", (
+        )
+        assert-css: (
             ".docblock .example-wrap.should_panic",
             {"border-left": "2px solid rgba(255, 0, 0, 0.5)"},
-        )),
+        )
 
-        ("move-cursor-to", ".docblock .example-wrap.should_panic .tooltip"),
+        move-cursor-to: ".docblock .example-wrap.should_panic .tooltip"
 
-        ("assert-css", (
+        assert-css: (
             ".docblock .example-wrap.should_panic .tooltip",
             {"color": "rgb(255, 0, 0)"},
-        )),
-        ("assert-css", (
+        )
+        assert-css: (
             ".docblock .example-wrap.should_panic",
             {"border-left": "2px solid rgb(255, 0, 0)"},
-        )),
-        ("assert-css", (
+        )
+        assert-css: (
             ".docblock .example-wrap.should_panic .tooltip::after",
             {
                 "content": '"This example panics"',
@@ -78,37 +78,37 @@ define-function: (
                 "color": |color|,
                 "border": "1px solid " + |border|,
             },
-        )),
-        ("assert-css", (
+        )
+        assert-css: (
             ".docblock .example-wrap.should_panic .tooltip::before",
             {
                 "border-width": "5px",
                 "border-style": "solid",
                 "border-color": "rgba(0, 0, 0, 0) " + |background| + " rgba(0, 0, 0, 0) rgba(0, 0, 0, 0)",
             },
-        )),
+        )
 
         // ignore block
-        ("assert-css", (
+        assert-css: (
             ".docblock .example-wrap.ignore .tooltip",
             {"color": "rgba(255, 142, 0, 0.6)"},
-        )),
-        ("assert-css", (
+        )
+        assert-css: (
             ".docblock .example-wrap.ignore",
             {"border-left": "2px solid rgba(255, 142, 0, 0.6)"},
-        )),
+        )
 
-        ("move-cursor-to", ".docblock .example-wrap.ignore .tooltip"),
+        move-cursor-to: ".docblock .example-wrap.ignore .tooltip"
 
-        ("assert-css", (
+        assert-css: (
             ".docblock .example-wrap.ignore .tooltip",
             {"color": "rgb(255, 142, 0)"},
-        )),
-        ("assert-css", (
+        )
+        assert-css: (
             ".docblock .example-wrap.ignore",
             {"border-left": "2px solid rgb(255, 142, 0)"},
-        )),
-        ("assert-css", (
+        )
+        assert-css: (
             ".docblock .example-wrap.ignore .tooltip::after",
             {
                 "content": '"This example is not tested"',
@@ -117,16 +117,16 @@ define-function: (
                 "color": |color|,
                 "border": "1px solid " + |border|,
             },
-        )),
-        ("assert-css", (
+        )
+        assert-css: (
             ".docblock .example-wrap.ignore .tooltip::before",
             {
                 "border-width": "5px",
                 "border-style": "solid",
                 "border-color": "rgba(0, 0, 0, 0) " + |background| + " rgba(0, 0, 0, 0) rgba(0, 0, 0, 0)",
             },
-        )),
-    ],
+        )
+    },
 )
 
 call-function: ("check-colors", {
diff --git a/src/test/rustdoc-gui/docblock-code-block-line-number.goml b/src/test/rustdoc-gui/docblock-code-block-line-number.goml
index a3ed008719c..69bcf5339ef 100644
--- a/src/test/rustdoc-gui/docblock-code-block-line-number.goml
+++ b/src/test/rustdoc-gui/docblock-code-block-line-number.goml
@@ -11,19 +11,19 @@ assert-false: "pre.example-line-numbers"
 define-function: (
     "check-colors",
     (theme, color),
-    [
+    block {
         // We now set the setting to show the line numbers on code examples.
-        ("local-storage", {
+        local-storage: {
             "rustdoc-theme": |theme|,
             "rustdoc-use-system-theme": "false",
             "rustdoc-line-numbers": "true"
-        }),
+        }
         // We reload to make the line numbers appear and change theme.
-        ("reload"),
+        reload:
         // We wait for them to be added into the DOM by the JS...
-        ("wait-for", "pre.example-line-numbers"),
+        wait-for: "pre.example-line-numbers"
         // If the test didn't fail, it means that it was found!
-        ("assert-css", (
+        assert-css: (
             "pre.example-line-numbers",
             {
                 "color": |color|,
@@ -32,8 +32,8 @@ define-function: (
                 "text-align": "right",
             },
             ALL,
-        )),
-    ],
+        )
+    },
 )
 call-function: ("check-colors", {
     "theme": "ayu",
diff --git a/src/test/rustdoc-gui/docblock-table.goml b/src/test/rustdoc-gui/docblock-table.goml
index 6f9209e0ab4..3dcb8abd415 100644
--- a/src/test/rustdoc-gui/docblock-table.goml
+++ b/src/test/rustdoc-gui/docblock-table.goml
@@ -7,32 +7,32 @@ compare-elements-css: (".impl-items .docblock table td", ".top-doc .docblock tab
 define-function: (
     "check-colors",
     (theme, border_color, zebra_stripe_color),
-    [
-        ("local-storage", {"rustdoc-use-system-theme": "false", "rustdoc-theme": |theme|}),
-        ("reload"),
-        ("assert-css", (".top-doc .docblock table tbody tr:nth-child(1)", {
+    block {
+        local-storage: {"rustdoc-use-system-theme": "false", "rustdoc-theme": |theme|}
+        reload:
+        assert-css: (".top-doc .docblock table tbody tr:nth-child(1)", {
             "background-color": "rgba(0, 0, 0, 0)",
-        })),
-        ("assert-css", (".top-doc .docblock table tbody tr:nth-child(2)", {
+        })
+        assert-css: (".top-doc .docblock table tbody tr:nth-child(2)", {
             "background-color": |zebra_stripe_color|,
-        })),
-        ("assert-css", (".top-doc .docblock table tbody tr:nth-child(3)", {
+        })
+        assert-css: (".top-doc .docblock table tbody tr:nth-child(3)", {
             "background-color": "rgba(0, 0, 0, 0)",
-        })),
-        ("assert-css", (".top-doc .docblock table tbody tr:nth-child(4)", {
+        })
+        assert-css: (".top-doc .docblock table tbody tr:nth-child(4)", {
             "background-color": |zebra_stripe_color|,
-        })),
-        ("assert-css", (".top-doc .docblock table td", {
+        })
+        assert-css: (".top-doc .docblock table td", {
             "border-style": "solid",
             "border-width": "1px",
             "border-color": |border_color|,
-        })),
-        ("assert-css", (".top-doc .docblock table th", {
+        })
+        assert-css: (".top-doc .docblock table th", {
             "border-style": "solid",
             "border-width": "1px",
             "border-color": |border_color|,
-        })),
-    ]
+        })
+    }
 )
 
 call-function: ("check-colors", {
diff --git a/src/test/rustdoc-gui/escape-key.goml b/src/test/rustdoc-gui/escape-key.goml
index 78e9f23093e..5d80d24969d 100644
--- a/src/test/rustdoc-gui/escape-key.goml
+++ b/src/test/rustdoc-gui/escape-key.goml
@@ -5,7 +5,7 @@ goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
 write: (".search-input", "test")
 // To be SURE that the search will be run.
 press-key: 'Enter'
-wait-for: "#search h1" // The search element is empty before the first search 
+wait-for: "#search h1" // The search element is empty before the first search
 // Check that the currently displayed element is search.
 wait-for: "#alternative-display #search"
 assert-attribute: ("#main-content", {"class": "content hidden"})
diff --git a/src/test/rustdoc-gui/headers-color.goml b/src/test/rustdoc-gui/headers-color.goml
index c80a49c52f0..92cf050a514 100644
--- a/src/test/rustdoc-gui/headers-color.goml
+++ b/src/test/rustdoc-gui/headers-color.goml
@@ -3,39 +3,39 @@
 define-function: (
     "check-colors",
     (theme, color, code_header_color, focus_background_color, headings_color),
-    [
-        ("goto", "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html"),
+    block {
+        goto: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html"
         // This is needed so that the text color is computed.
-        ("show-text", true),
-        ("local-storage", {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}),
-        ("reload"),
-        ("assert-css", (
+        show-text: true
+        local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}
+        reload:
+        assert-css: (
             ".impl",
             {"color": |color|, "background-color": "rgba(0, 0, 0, 0)"},
             ALL,
-        )),
-        ("assert-css", (
+        )
+        assert-css: (
             ".impl .code-header",
             {"color": |code_header_color|, "background-color": "rgba(0, 0, 0, 0)"},
             ALL,
-        )),
-        ("goto", "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html#impl-Foo"),
-        ("assert-css", (
+        )
+        goto: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html#impl-Foo"
+        assert-css: (
             "#impl-Foo",
             {"color": |color|, "background-color": |focus_background_color|},
-        )),
-        ("goto", "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html#method.must_use"),
-        ("assert-css", (
+        )
+        goto: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html#method.must_use"
+        assert-css: (
             "#method\.must_use",
             {"color": |color|, "background-color": |focus_background_color|},
             ALL,
-        )),
-        ("goto", "file://" + |DOC_PATH| + "/test_docs/index.html"),
-        ("assert-css", (".small-section-header a", {"color": |color|}, ALL)),
-        ("goto", "file://" + |DOC_PATH| + "/test_docs/struct.HeavilyDocumentedStruct.html"),
+        )
+        goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
+        assert-css: (".small-section-header a", {"color": |color|}, ALL)
+        goto: "file://" + |DOC_PATH| + "/test_docs/struct.HeavilyDocumentedStruct.html"
         // We select headings (h2, h3, h...).
-        ("assert-css", (".docblock > :not(p) > a", {"color": |headings_color|}, ALL)),
-    ],
+        assert-css: (".docblock > :not(p) > a", {"color": |headings_color|}, ALL)
+    },
 )
 
 call-function: (
diff --git a/src/test/rustdoc-gui/headings.goml b/src/test/rustdoc-gui/headings.goml
index 85e17ca9551..45b3fee26e4 100644
--- a/src/test/rustdoc-gui/headings.goml
+++ b/src/test/rustdoc-gui/headings.goml
@@ -157,38 +157,38 @@ goto: "file://" + |DOC_PATH| + "/test_docs/struct.HeavilyDocumentedStruct.html"
 define-function: (
     "check-colors",
     (theme, heading_color, small_heading_color, heading_border_color),
-    [
-        ("local-storage", {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}),
-        ("reload"),
-        ("assert-css", (
+    block {
+        local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}
+        reload:
+        assert-css: (
             ".top-doc .docblock h2",
             {"color": |heading_color|, "border-bottom": "1px solid " + |heading_border_color|},
-        )),
-        ("assert-css", (
+        )
+        assert-css: (
             ".top-doc .docblock h3",
             {"color": |heading_color|, "border-bottom": "1px solid " + |heading_border_color|},
-        )),
-        ("assert-css", (
+        )
+        assert-css: (
             ".top-doc .docblock h4",
             {"color": |heading_color|, "border-bottom": "1px solid " + |heading_border_color|},
-        )),
-        ("assert-css", (
+        )
+        assert-css: (
             ".top-doc .docblock h5",
             {"color": |small_heading_color|, "border-bottom-width": "0px"},
-        )),
-        ("assert-css", (
+        )
+        assert-css: (
             "#implementations-list .docblock h4",
             {"color": |heading_color|, "border-bottom-width": "0px"},
-        )),
-        ("assert-css", (
+        )
+        assert-css: (
             "#implementations-list .docblock h5",
             {"color": |small_heading_color|, "border-bottom-width": "0px"},
-        )),
-        ("assert-css", (
+        )
+        assert-css: (
             "#implementations-list .docblock h6",
             {"color": |small_heading_color|, "border-bottom-width": "0px"},
-        )),
-    ],
+        )
+    },
 )
 call-function: (
     "check-colors",
@@ -221,11 +221,11 @@ call-function: (
 define-function: (
     "check-since-color",
     (theme),
-    [
-        ("local-storage", {"rustdoc-theme": |theme|}),
-        ("reload"),
-        ("assert-css", (".since", {"color": "rgb(128, 128, 128)"}, ALL)),
-    ],
+    block {
+        local-storage: {"rustdoc-theme": |theme|}
+        reload:
+        assert-css: (".since", {"color": "rgb(128, 128, 128)"}, ALL)
+    },
 )
 
 goto: "file://" + |DOC_PATH| + "/staged_api/struct.Foo.html"
diff --git a/src/test/rustdoc-gui/help-page.goml b/src/test/rustdoc-gui/help-page.goml
index 80203901ed3..5f4c1ba2f85 100644
--- a/src/test/rustdoc-gui/help-page.goml
+++ b/src/test/rustdoc-gui/help-page.goml
@@ -18,17 +18,17 @@ show-text: true
 define-function: (
     "check-colors",
     (theme, color, background, box_shadow),
-    [
+    block {
         // Setting the theme.
-        ("local-storage", {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}),
+        local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}
         // We reload the page so the local storage settings are being used.
-        ("reload"),
-        ("assert-css", ("#help kbd", {
+        reload:
+        assert-css: ("#help kbd", {
             "color": |color|,
             "background-color": |background|,
             "box-shadow": |box_shadow| + " 0px -1px 0px 0px inset",
-        }, ALL)),
-    ],
+        }, ALL)
+    },
 )
 
 call-function: ("check-colors", {
@@ -39,7 +39,7 @@ call-function: ("check-colors", {
 })
 call-function: ("check-colors", {
     "theme": "dark",
-    "color": "rgb(221, 221, 221)",
+    "color": "rgb(0, 0, 0)",
     "background": "rgb(250, 251, 252)",
     "box_shadow": "rgb(198, 203, 209)",
 })
@@ -61,3 +61,12 @@ click: "#help-button > a"
 assert-css: ("#help", {"display": "none"})
 compare-elements-property-false: (".sub", "#help", ["offsetWidth"])
 compare-elements-position-false: (".sub", "#help", ("x"))
+
+// This test ensures that the "the rustdoc book" anchor link within the help popover works.
+goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
+size: (1000, 1000) // Popover only appears when the screen width is >700px.
+assert-false: "#help"
+click: "#help-button > a"
+click: ".popover a[href='https://doc.rust-lang.org/rustdoc/']"
+wait-for: 2000
+assert-document-property: {"URL": "https://doc.rust-lang.org/rustdoc/"}
diff --git a/src/test/rustdoc-gui/highlight-colors.goml b/src/test/rustdoc-gui/highlight-colors.goml
index ff1be389dcb..b182150a577 100644
--- a/src/test/rustdoc-gui/highlight-colors.goml
+++ b/src/test/rustdoc-gui/highlight-colors.goml
@@ -21,24 +21,24 @@ define-function: (
         comment,
         doc_comment,
     ),
-    [
-        ("local-storage", {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}),
-        ("reload"),
-        ("assert-css", ("pre.rust .kw", {"color": |kw|}, ALL)),
-        ("assert-css", ("pre.rust .kw-2", {"color": |kw2|}, ALL)),
-        ("assert-css", ("pre.rust .prelude-ty", {"color": |prelude_ty|}, ALL)),
-        ("assert-css", ("pre.rust .prelude-val", {"color": |prelude_val|}, ALL)),
-        ("assert-css", ("pre.rust .lifetime", {"color": |lifetime|}, ALL)),
-        ("assert-css", ("pre.rust .number", {"color": |number|}, ALL)),
-        ("assert-css", ("pre.rust .string", {"color": |string|}, ALL)),
-        ("assert-css", ("pre.rust .bool-val", {"color": |bool_val|}, ALL)),
-        ("assert-css", ("pre.rust .self", {"color": |self|}, ALL)),
-        ("assert-css", ("pre.rust .attr", {"color": |attr|}, ALL)),
-        ("assert-css", ("pre.rust .macro", {"color": |macro|}, ALL)),
-        ("assert-css", ("pre.rust .question-mark", {"color": |question_mark|}, ALL)),
-        ("assert-css", ("pre.rust .comment", {"color": |comment|}, ALL)),
-        ("assert-css", ("pre.rust .doccomment", {"color": |doc_comment|}, ALL)),
-    ],
+    block {
+        local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}
+        reload:
+        assert-css: ("pre.rust .kw", {"color": |kw|}, ALL)
+        assert-css: ("pre.rust .kw-2", {"color": |kw2|}, ALL)
+        assert-css: ("pre.rust .prelude-ty", {"color": |prelude_ty|}, ALL)
+        assert-css: ("pre.rust .prelude-val", {"color": |prelude_val|}, ALL)
+        assert-css: ("pre.rust .lifetime", {"color": |lifetime|}, ALL)
+        assert-css: ("pre.rust .number", {"color": |number|}, ALL)
+        assert-css: ("pre.rust .string", {"color": |string|}, ALL)
+        assert-css: ("pre.rust .bool-val", {"color": |bool_val|}, ALL)
+        assert-css: ("pre.rust .self", {"color": |self|}, ALL)
+        assert-css: ("pre.rust .attr", {"color": |attr|}, ALL)
+        assert-css: ("pre.rust .macro", {"color": |macro|}, ALL)
+        assert-css: ("pre.rust .question-mark", {"color": |question_mark|}, ALL)
+        assert-css: ("pre.rust .comment", {"color": |comment|}, ALL)
+        assert-css: ("pre.rust .doccomment", {"color": |doc_comment|}, ALL)
+    },
 )
 
 call-function: ("check-colors", {
diff --git a/src/test/rustdoc-gui/impl-doc.goml b/src/test/rustdoc-gui/impl-doc.goml
index 7322032b3f5..6caffb9c39f 100644
--- a/src/test/rustdoc-gui/impl-doc.goml
+++ b/src/test/rustdoc-gui/impl-doc.goml
@@ -3,7 +3,7 @@ goto: "file://" + |DOC_PATH| + "/test_docs/struct.TypeWithImplDoc.html"
 
 // The text is about 24px tall, so if there's a margin, then their position will be >24px apart
 compare-elements-position-near-false: (
-	"#implementations-list > .implementors-toggle > .docblock > p",
-	"#implementations-list > .implementors-toggle > .impl-items",
-	{"y": 24}
+    "#implementations-list > .implementors-toggle > .docblock > p",
+    "#implementations-list > .implementors-toggle > .impl-items",
+    {"y": 24}
 )
diff --git a/src/test/rustdoc-gui/implementors.goml b/src/test/rustdoc-gui/implementors.goml
index 4999283dc8b..997c0ed8f01 100644
--- a/src/test/rustdoc-gui/implementors.goml
+++ b/src/test/rustdoc-gui/implementors.goml
@@ -33,3 +33,9 @@ goto: "file://" + |DOC_PATH| + "/lib2/trait.TraitToReexport.html"
 assert-count: ("#implementors-list .impl", 1)
 goto: "file://" + |DOC_PATH| + "/implementors/trait.TraitToReexport.html"
 assert-count: ("#implementors-list .impl", 1)
+
+// Now check that the link is properly rewritten for a crate called `http`.
+// An older version of rustdoc had a buggy check for absolute links.
+goto: "file://" + |DOC_PATH| + "/http/trait.HttpTrait.html"
+assert-count: ("#implementors-list .impl", 1)
+assert-attribute: ("#implementors-list .impl a.trait", {"href": "../http/trait.HttpTrait.html"})
diff --git a/src/test/rustdoc-gui/item-decl-colors.goml b/src/test/rustdoc-gui/item-decl-colors.goml
index 2e07f19b13d..c58e3eb7c23 100644
--- a/src/test/rustdoc-gui/item-decl-colors.goml
+++ b/src/test/rustdoc-gui/item-decl-colors.goml
@@ -17,22 +17,23 @@ define-function: (
         fn_color,
         assoc_type_color,
     ),
-    [
-        ("goto", "file://" + |DOC_PATH| + "/test_docs/struct.WithGenerics.html"),
-        ("show-text", true),
-        ("local-storage", {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}),
-        ("reload"),
-        ("assert-css", (".item-decl .code-attribute", {"color": |attr_color|}, ALL)),
-        ("assert-css", (".item-decl .trait", {"color": |trait_color|}, ALL)),
+    block {
+        goto: "file://" + |DOC_PATH| + "/test_docs/struct.WithGenerics.html"
+        show-text: true
+        local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}
+        reload:
+        assert-css: (".item-decl .code-attribute", {"color": |attr_color|}, ALL)
+        assert-css: (".item-decl .trait", {"color": |trait_color|}, ALL)
         // We need to add `code` here because otherwise it would select the parent too.
-        ("assert-css", (".item-decl code .struct", {"color": |struct_color|}, ALL)),
-        ("assert-css", (".item-decl .enum", {"color": |enum_color|}, ALL)),
-        ("assert-css", (".item-decl .primitive", {"color": |primitive_color|}, ALL)),
-        ("goto", "file://" + |DOC_PATH| + "/test_docs/trait.TraitWithoutGenerics.html"),
-        ("assert-css", (".item-decl .constant", {"color": |constant_color|}, ALL)),
-        ("assert-css", (".item-decl .fn", {"color": |fn_color|}, ALL)),
-        ("assert-css", (".item-decl .associatedtype", {"color": |assoc_type_color|}, ALL)),
-    ],
+        assert-css: (".item-decl code .struct", {"color": |struct_color|}, ALL)
+        assert-css: (".item-decl .enum", {"color": |enum_color|}, ALL)
+        assert-css: (".item-decl .primitive", {"color": |primitive_color|}, ALL)
+
+        goto: "file://" + |DOC_PATH| + "/test_docs/trait.TraitWithoutGenerics.html"
+        assert-css: (".item-decl .constant", {"color": |constant_color|}, ALL)
+        assert-css: (".item-decl .fn", {"color": |fn_color|}, ALL)
+        assert-css: (".item-decl .associatedtype", {"color": |assoc_type_color|}, ALL)
+    },
 )
 
 call-function: (
diff --git a/src/test/rustdoc-gui/jump-to-def-background.goml b/src/test/rustdoc-gui/jump-to-def-background.goml
index b65faf13d0c..8ee3ccf4a21 100644
--- a/src/test/rustdoc-gui/jump-to-def-background.goml
+++ b/src/test/rustdoc-gui/jump-to-def-background.goml
@@ -4,17 +4,17 @@ goto: "file://" + |DOC_PATH| + "/src/link_to_definition/lib.rs.html"
 define-function: (
     "check-background-color",
     (theme, background_color),
-    [
+    block {
         // Set the theme.
-        ("local-storage", { "rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false" }),
+        local-storage: { "rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false" }
         // We reload the page so the local storage settings are being used.
-        ("reload"),
-        ("assert-css", (
+        reload:
+        assert-css: (
             "body.source .example-wrap pre.rust a",
             {"background-color": |background_color|},
             ALL,
-        )),
-    ],
+        )
+    },
 )
 
 call-function: ("check-background-color", ("ayu", "rgb(51, 51, 51)"))
diff --git a/src/test/rustdoc-gui/links-color.goml b/src/test/rustdoc-gui/links-color.goml
index 9402c09eb69..14f7d99351a 100644
--- a/src/test/rustdoc-gui/links-color.goml
+++ b/src/test/rustdoc-gui/links-color.goml
@@ -8,29 +8,29 @@ define-function: (
     "check-colors",
     (theme, mod, macro, struct, enum, trait, fn, type, union, keyword,
      sidebar, sidebar_current, sidebar_current_background),
-    [
-        ("local-storage", {
+    block {
+        local-storage: {
             "rustdoc-theme": |theme|,
             "rustdoc-use-system-theme": "false",
-        }),
-        ("reload"),
+        }
+        reload:
         // Checking results colors.
-        ("assert-css", (".item-table .mod", {"color": |mod|}, ALL)),
-        ("assert-css", (".item-table .macro", {"color": |macro|}, ALL)),
-        ("assert-css", (".item-table .struct", {"color": |struct|}, ALL)),
-        ("assert-css", (".item-table .enum", {"color": |enum|}, ALL)),
-        ("assert-css", (".item-table .trait", {"color": |trait|}, ALL)),
-        ("assert-css", (".item-table .fn", {"color": |fn|}, ALL)),
-        ("assert-css", (".item-table .type", {"color": |type|}, ALL)),
-        ("assert-css", (".item-table .union", {"color": |union|}, ALL)),
-        ("assert-css", (".item-table .keyword", {"color": |keyword|}, ALL)),
+        assert-css: (".item-table .mod", {"color": |mod|}, ALL)
+        assert-css: (".item-table .macro", {"color": |macro|}, ALL)
+        assert-css: (".item-table .struct", {"color": |struct|}, ALL)
+        assert-css: (".item-table .enum", {"color": |enum|}, ALL)
+        assert-css: (".item-table .trait", {"color": |trait|}, ALL)
+        assert-css: (".item-table .fn", {"color": |fn|}, ALL)
+        assert-css: (".item-table .type", {"color": |type|}, ALL)
+        assert-css: (".item-table .union", {"color": |union|}, ALL)
+        assert-css: (".item-table .keyword", {"color": |keyword|}, ALL)
         // Checking sidebar elements.
-        ("assert-css", (
+        assert-css: (
             ".sidebar-elems a:not(.current)",
             {"color": |sidebar|, "background-color": "rgba(0, 0, 0, 0)", "font-weight": "400"},
             ALL,
-        )),
-        ("assert-css", (
+        )
+        assert-css: (
             ".sidebar-elems a.current",
             {
                 "color": |sidebar_current|,
@@ -38,8 +38,8 @@ define-function: (
                 "font-weight": "500",
             },
             ALL,
-        )),
-    ],
+        )
+    },
 )
 
 call-function: (
diff --git a/src/test/rustdoc-gui/mobile.goml b/src/test/rustdoc-gui/mobile.goml
index 704542a39d2..895864d8944 100644
--- a/src/test/rustdoc-gui/mobile.goml
+++ b/src/test/rustdoc-gui/mobile.goml
@@ -27,4 +27,8 @@ assert-css-false: (".content .out-of-band .since::before", { "content": "\"Since
 goto: "file://" + |DOC_PATH| + "/settings.html"
 size: (400, 600)
 // Ignored for now https://github.com/rust-lang/rust/issues/93784.
-// compare-elements-position-near-false: ("#preferred-light-theme .setting-name", "#preferred-light-theme .choice", {"y": 16})
+// compare-elements-position-near-false: (
+//     "#preferred-light-theme .setting-name",
+//     "#preferred-light-theme .choice",
+//     {"y": 16},
+// )
diff --git a/src/test/rustdoc-gui/notable-trait.goml b/src/test/rustdoc-gui/notable-trait.goml
index 7d4bd27d42d..b4fa7d0dbf0 100644
--- a/src/test/rustdoc-gui/notable-trait.goml
+++ b/src/test/rustdoc-gui/notable-trait.goml
@@ -123,40 +123,40 @@ assert-count: ("//*[@class='notable popover']", 0)
 define-function: (
     "check-colors",
     (theme, header_color, content_color, type_color, trait_color),
-    [
-        ("goto", "file://" + |DOC_PATH| + "/test_docs/struct.NotableStructWithLongName.html"),
+    block {
+        goto: "file://" + |DOC_PATH| + "/test_docs/struct.NotableStructWithLongName.html"
         // This is needed to ensure that the text color is computed.
-        ("show-text", true),
+        show-text: true
 
         // Setting the theme.
-        ("local-storage", {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}),
+        local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}
         // We reload the page so the local storage settings are being used.
-        ("reload"),
+        reload:
 
-        ("move-cursor-to", "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits']"),
-        ("assert-count", (".notable.popover", 1)),
+        move-cursor-to: "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits']"
+        assert-count: (".notable.popover", 1)
 
-        ("assert-css", (
+        assert-css: (
              ".notable.popover h3",
              {"color": |header_color|},
              ALL,
-        )),
-        ("assert-css", (
+        )
+        assert-css: (
              ".notable.popover pre",
              {"color": |content_color|},
              ALL,
-        )),
-        ("assert-css", (
+        )
+        assert-css: (
              ".notable.popover pre a.struct",
              {"color": |type_color|},
              ALL,
-        )),
-        ("assert-css", (
+        )
+        assert-css: (
              ".notable.popover pre a.trait",
              {"color": |trait_color|},
              ALL,
-        )),
-    ]
+        )
+    },
 )
 
 call-function: (
diff --git a/src/test/rustdoc-gui/run-on-hover.goml b/src/test/rustdoc-gui/run-on-hover.goml
index 57d63049f28..8dcb62c10aa 100644
--- a/src/test/rustdoc-gui/run-on-hover.goml
+++ b/src/test/rustdoc-gui/run-on-hover.goml
@@ -8,27 +8,27 @@ 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", {
+    block {
+        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", {
+        })
+        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", {
diff --git a/src/test/rustdoc-gui/rust-logo.goml b/src/test/rustdoc-gui/rust-logo.goml
index 816cc9abd69..2d15e8b9699 100644
--- a/src/test/rustdoc-gui/rust-logo.goml
+++ b/src/test/rustdoc-gui/rust-logo.goml
@@ -4,40 +4,55 @@ goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
 define-function: (
     "check-logo",
     (theme, filter),
-    [
+    block {
         // Going to the doc page.
-        ("goto", "file://" + |DOC_PATH| + "/test_docs/index.html"),
+        goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
         // Changing theme.
-        ("local-storage", {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}),
-        ("reload"),
-        ("assert-css", (".rust-logo", {"filter": |filter|})),
+        local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}
+        reload:
+        assert-css: (".rust-logo", {"filter": |filter|})
         // Going to the source code page.
-        ("goto", "file://" + |DOC_PATH| + "/src/test_docs/lib.rs.html"),
+        goto: "file://" + |DOC_PATH| + "/src/test_docs/lib.rs.html"
         // Changing theme (since it's local files, the local storage works by folder).
-        ("local-storage", {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}),
-        ("reload"),
-        ("assert-css", (".rust-logo", {"filter": |filter|})),
+        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"),
+        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"),
+        local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}
+        reload:
         // Check there is no rust logo
-        ("assert-false", ".rust-logo"),
+        assert-false: ".rust-logo"
         // Check there is no filter.
-        ("assert-css", (".sidebar .logo-container img", {"filter": "none"})),
-    ],
+        assert-css: (".sidebar .logo-container img", {"filter": "none"})
+    },
 )
 
 call-function: (
     "check-logo",
-    ("ayu", "drop-shadow(rgb(255, 255, 255) 1px 0px 0px) drop-shadow(rgb(255, 255, 255) 0px 1px 0px) drop-shadow(rgb(255, 255, 255) -1px 0px 0px) drop-shadow(rgb(255, 255, 255) 0px -1px 0px)"),
+    {
+        "theme": "ayu",
+        "filter": "drop-shadow(rgb(255, 255, 255) 1px 0px 0px) " +
+            "drop-shadow(rgb(255, 255, 255) 0px 1px 0px) " +
+            "drop-shadow(rgb(255, 255, 255) -1px 0px 0px) " +
+            "drop-shadow(rgb(255, 255, 255) 0px -1px 0px)",
+    },
 )
 call-function: (
     "check-logo",
-    ("dark", "drop-shadow(rgb(255, 255, 255) 1px 0px 0px) drop-shadow(rgb(255, 255, 255) 0px 1px 0px) drop-shadow(rgb(255, 255, 255) -1px 0px 0px) drop-shadow(rgb(255, 255, 255) 0px -1px 0px)"),
+    {
+        "theme": "dark",
+        "filter": "drop-shadow(rgb(255, 255, 255) 1px 0px 0px) " +
+            "drop-shadow(rgb(255, 255, 255) 0px 1px 0px) " +
+            "drop-shadow(rgb(255, 255, 255) -1px 0px 0px) " +
+            "drop-shadow(rgb(255, 255, 255) 0px -1px 0px)",
+    },
 )
 call-function: (
     "check-logo",
-    ("light", "none"),
+    {
+        "theme": "light",
+        "filter": "none",
+    },
 )
diff --git a/src/test/rustdoc-gui/scrape-examples-button-focus.goml b/src/test/rustdoc-gui/scrape-examples-button-focus.goml
index bba518db099..10651a3f669 100644
--- a/src/test/rustdoc-gui/scrape-examples-button-focus.goml
+++ b/src/test/rustdoc-gui/scrape-examples-button-focus.goml
@@ -5,25 +5,25 @@ store-property: (initialScrollTop, ".scraped-example-list > .scraped-example pre
 focus: ".scraped-example-list > .scraped-example .next"
 press-key: "Enter"
 assert-property-false: (".scraped-example-list > .scraped-example pre", {
-	"scrollTop": |initialScrollTop|
+    "scrollTop": |initialScrollTop|
 })
 focus: ".scraped-example-list > .scraped-example .prev"
 press-key: "Enter"
 assert-property: (".scraped-example-list > .scraped-example pre", {
-	"scrollTop": |initialScrollTop|
+    "scrollTop": |initialScrollTop|
 })
 
 // The expand button increases the scrollHeight of the minimized code viewport
 store-property: (smallOffsetHeight, ".scraped-example-list > .scraped-example pre", "offsetHeight")
 assert-property-false: (".scraped-example-list > .scraped-example pre", {
-	"scrollHeight": |smallOffsetHeight|
+    "scrollHeight": |smallOffsetHeight|
 })
 focus: ".scraped-example-list > .scraped-example .expand"
 press-key: "Enter"
 assert-property-false: (".scraped-example-list > .scraped-example pre", {
-	"offsetHeight": |smallOffsetHeight|
+    "offsetHeight": |smallOffsetHeight|
 })
 store-property: (fullOffsetHeight, ".scraped-example-list > .scraped-example pre", "offsetHeight")
 assert-property: (".scraped-example-list > .scraped-example pre", {
-	"scrollHeight": |fullOffsetHeight|
+    "scrollHeight": |fullOffsetHeight|
 })
diff --git a/src/test/rustdoc-gui/scrape-examples-color.goml b/src/test/rustdoc-gui/scrape-examples-color.goml
index 360e2af8ba4..40f31b2771b 100644
--- a/src/test/rustdoc-gui/scrape-examples-color.goml
+++ b/src/test/rustdoc-gui/scrape-examples-color.goml
@@ -6,29 +6,29 @@ define-function: (
     "check-colors",
     (theme, highlight, highlight_focus, help_border, help_color, help_hover_border,
      help_hover_color),
-    [
-        ("local-storage", { "rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false", }),
-        ("reload"),
-        ("wait-for", ".more-examples-toggle"),
-        ("assert-css", (".scraped-example .example-wrap .rust span.highlight:not(.focus)", {
+    block {
+        local-storage: { "rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false", }
+        reload:
+        wait-for: ".more-examples-toggle"
+        assert-css: (".scraped-example .example-wrap .rust span.highlight:not(.focus)", {
             "background-color": |highlight|,
-        }, ALL)),
-        ("assert-css", (".scraped-example .example-wrap .rust span.highlight.focus", {
+        }, ALL)
+        assert-css: (".scraped-example .example-wrap .rust span.highlight.focus", {
             "background-color": |highlight_focus|,
-        }, ALL)),
+        }, ALL)
 
-        ("assert-css", (".scraped-example-list .scrape-help", {
+        assert-css: (".scraped-example-list .scrape-help", {
             "border-color": |help_border|,
             "color": |help_color|,
-        })),
-        ("move-cursor-to", ".scraped-example-list .scrape-help"),
-        ("assert-css", (".scraped-example-list .scrape-help:hover", {
+        })
+        move-cursor-to: ".scraped-example-list .scrape-help"
+        assert-css: (".scraped-example-list .scrape-help:hover", {
             "border-color": |help_hover_border|,
             "color": |help_hover_color|,
-        })),
+        })
         // Moving the cursor to another item to not break next runs.
-        ("move-cursor-to", ".search-input"),
-    ]
+        move-cursor-to: ".search-input"
+    }
 )
 
 call-function: ("check-colors", {
diff --git a/src/test/rustdoc-gui/scrape-examples-toggle.goml b/src/test/rustdoc-gui/scrape-examples-toggle.goml
index 8c84fbc0c30..2d5df6a5d25 100644
--- a/src/test/rustdoc-gui/scrape-examples-toggle.goml
+++ b/src/test/rustdoc-gui/scrape-examples-toggle.goml
@@ -6,24 +6,24 @@ show-text: true
 define-function: (
     "check-color",
     (theme, toggle_line_color, toggle_line_hover_color),
-    [
-        ("local-storage", {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}),
-        ("reload"),
+    block {
+        local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}
+        reload:
 
         // Clicking "More examples..." will open additional examples
-        ("assert-attribute-false", (".more-examples-toggle", {"open": ""})),
-        ("click", ".more-examples-toggle"),
-        ("assert-attribute", (".more-examples-toggle", {"open": ""})),
+        assert-attribute-false: (".more-examples-toggle", {"open": ""})
+        click: ".more-examples-toggle"
+        assert-attribute: (".more-examples-toggle", {"open": ""})
 
-        ("assert-css", (".toggle-line-inner", {"background-color": |toggle_line_color|}, ALL)),
-        ("move-cursor-to", ".toggle-line"),
-        ("assert-css", (
+        assert-css: (".toggle-line-inner", {"background-color": |toggle_line_color|}, ALL)
+        move-cursor-to: ".toggle-line"
+        assert-css: (
             ".toggle-line:hover .toggle-line-inner",
             {"background-color": |toggle_line_hover_color|},
-        )),
+        )
         // Moving cursor away from the toggle line to prevent disrupting next test.
-        ("move-cursor-to", ".search-input"),
-    ],
+        move-cursor-to: ".search-input"
+    },
 )
 
 call-function: ("check-color", {
diff --git a/src/test/rustdoc-gui/search-filter.goml b/src/test/rustdoc-gui/search-filter.goml
index e556da0c54e..5bc6e87d6d2 100644
--- a/src/test/rustdoc-gui/search-filter.goml
+++ b/src/test/rustdoc-gui/search-filter.goml
@@ -15,6 +15,7 @@ click: "#crate-search"
 press-key: "ArrowDown"
 press-key: "ArrowDown"
 press-key: "ArrowDown"
+press-key: "ArrowDown"
 press-key: "Enter"
 // Waiting for the search results to appear...
 wait-for: "#search-tabs"
@@ -39,6 +40,7 @@ click: "#crate-search"
 press-key: "ArrowUp"
 press-key: "ArrowUp"
 press-key: "ArrowUp"
+press-key: "ArrowUp"
 press-key: "Enter"
 // Waiting for the search results to appear...
 wait-for: "#search-tabs"
diff --git a/src/test/rustdoc-gui/search-no-result.goml b/src/test/rustdoc-gui/search-no-result.goml
index b88be32c94a..b76a44fa992 100644
--- a/src/test/rustdoc-gui/search-no-result.goml
+++ b/src/test/rustdoc-gui/search-no-result.goml
@@ -5,18 +5,18 @@ show-text: true
 define-function: (
     "check-no-result",
     (theme, link, link_hover),
-    [
+    block {
         // Changing theme.
-        ("local-storage", {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}),
-        ("reload"),
-        ("wait-for", "#results"),
-        ("assert", ".search-failed.active"),
-        ("assert-css", ("#results a", {"color": |link|}, ALL)),
-        ("move-cursor-to", "#results a"),
-        ("assert-css", ("#results a:hover", {"color": |link_hover|})),
+        local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}
+        reload:
+        wait-for: "#results"
+        assert: ".search-failed.active"
+        assert-css: ("#results a", {"color": |link|}, ALL)
+        move-cursor-to: "#results a"
+        assert-css: ("#results a:hover", {"color": |link_hover|})
         // Moving the cursor to some other place to not create issues with next function run.
-        ("move-cursor-to", ".search-input"),
-    ]
+        move-cursor-to: ".search-input"
+    },
 )
 
 call-function: ("check-no-result", {
diff --git a/src/test/rustdoc-gui/search-result-color.goml b/src/test/rustdoc-gui/search-result-color.goml
index 3c5fe9b74b7..d6d54ec4bee 100644
--- a/src/test/rustdoc-gui/search-result-color.goml
+++ b/src/test/rustdoc-gui/search-result-color.goml
@@ -3,53 +3,32 @@
 define-function: (
     "check-result-color",
     (result_kind, color, hover_color),
-    [
-        (
-            "assert-css",
-            (".result-" + |result_kind| + " ." + |result_kind|, {"color": |color|}, ALL),
-        ),
-        (
-            "assert-css",
-            (
-                ".result-" + |result_kind|,
-                {"color": |entry_color|, "background-color": |background_color|},
-            ),
-        ),
-        (
-            "move-cursor-to",
+    block {
+        assert-css: (".result-" + |result_kind| + " ." + |result_kind|, {"color": |color|}, ALL)
+        assert-css: (
             ".result-" + |result_kind|,
-        ),
-        (
-            "assert-css",
-            (
-                ".result-" + |result_kind| + ":hover",
-                {"color": |hover_entry_color|, "background-color": |hover_background_color|},
-            ),
-        ),
-        (
-            "assert-css",
-            (".result-" + |result_kind| + ":hover ." + |result_kind|, {"color": |hover_color|}),
-        ),
-        (
-            "move-cursor-to",
-            ".search-input",
-        ),
-        (
-            "focus",
-            ".result-" + |result_kind|,
-        ),
-        (
-            "assert-css",
-            (
-                ".result-" + |result_kind| + ":focus",
-                {"color": |hover_entry_color|, "background-color": |hover_background_color|},
-            ),
-        ),
-        (
-            "assert-css",
-            (".result-" + |result_kind| + ":focus ." + |result_kind|, {"color": |hover_color|}),
-        ),
-    ],
+            {"color": |entry_color|, "background-color": |background_color|},
+        )
+        move-cursor-to: ".result-" + |result_kind|
+        assert-css: (
+            ".result-" + |result_kind| + ":hover",
+            {"color": |hover_entry_color|, "background-color": |hover_background_color|},
+        )
+        assert-css: (
+            ".result-" + |result_kind| + ":hover ." + |result_kind|,
+            {"color": |hover_color|},
+        )
+        move-cursor-to: ".search-input"
+        focus: ".result-" + |result_kind|
+        assert-css: (
+            ".result-" + |result_kind| + ":focus",
+            {"color": |hover_entry_color|, "background-color": |hover_background_color|},
+        )
+        assert-css: (
+            ".result-" + |result_kind| + ":focus ." + |result_kind|,
+            {"color": |hover_color|},
+        )
+    },
 )
 
 goto: "file://" + |DOC_PATH| + "/test_docs/index.html?search=coo"
@@ -389,20 +368,20 @@ show-text: true
 define-function: (
     "check-alias",
     (theme, alias, grey),
-    [
-        ("local-storage", {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}),
-        ("reload"),
-        ("write", (".search-input", "thisisanalias")),
+    block {
+        local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}
+        reload:
+        write: (".search-input", "thisisanalias")
         // To be SURE that the search will be run.
-        ("press-key", 'Enter'),
+        press-key: 'Enter'
         // Waiting for the search results to appear...
-        ("wait-for", "#search-tabs"),
+        wait-for: "#search-tabs"
         // Checking that the colors for the alias element are the ones expected.
-        ("assert-css", (".result-name > .alias", {"color": |alias|})),
-        ("assert-css", (".result-name > .alias > .grey", {"color": |grey|})),
+        assert-css: (".result-name > .alias", {"color": |alias|})
+        assert-css: (".result-name > .alias > .grey", {"color": |grey|})
         // Leave the search results to prevent reloading with an already filled search input.
-        ("press-key", "Escape"),
-    ],
+        press-key: "Escape"
+    },
 )
 
 call-function: ("check-alias", {
diff --git a/src/test/rustdoc-gui/search-result-display.goml b/src/test/rustdoc-gui/search-result-display.goml
index 13a5e4c717b..43e608228d8 100644
--- a/src/test/rustdoc-gui/search-result-display.goml
+++ b/src/test/rustdoc-gui/search-result-display.goml
@@ -42,17 +42,17 @@ show-text: true
 define-function: (
     "check-filter",
     (theme, border, filter, hover_border, hover_filter),
-    [
-        ("local-storage", {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}),
-        ("reload"),
-        ("wait-for", "#crate-search"),
-        ("assert-css", ("#crate-search", {"border": "1px solid " + |border|})),
-        ("assert-css", ("#crate-search-div::after", {"filter": |filter|})),
-        ("move-cursor-to", "#crate-search"),
-        ("assert-css", ("#crate-search", {"border": "1px solid " + |hover_border|})),
-        ("assert-css", ("#crate-search-div::after", {"filter": |hover_filter|})),
-        ("move-cursor-to", ".search-input"),
-    ],
+    block {
+        local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}
+        reload:
+        wait-for: "#crate-search"
+        assert-css: ("#crate-search", {"border": "1px solid " + |border|})
+        assert-css: ("#crate-search-div::after", {"filter": |filter|})
+        move-cursor-to: "#crate-search"
+        assert-css: ("#crate-search", {"border": "1px solid " + |hover_border|})
+        assert-css: ("#crate-search-div::after", {"filter": |hover_filter|})
+        move-cursor-to: ".search-input"
+    },
 )
 
 call-function: ("check-filter", {
diff --git a/src/test/rustdoc-gui/search-tab.goml b/src/test/rustdoc-gui/search-tab.goml
index c2634a04c8a..36958f70044 100644
--- a/src/test/rustdoc-gui/search-tab.goml
+++ b/src/test/rustdoc-gui/search-tab.goml
@@ -7,35 +7,35 @@ define-function: (
     (theme, background, background_selected, background_hover, border_bottom,
      border_bottom_selected, border_bottom_hover, border_top, border_top_selected,
      border_top_hover),
-    [
+    block {
         // Setting the theme.
-        ("local-storage", {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}),
-        ("reload"),
+        local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}
+        reload:
 
         // These two commands are used to be sure the search will be run.
-        ("focus", ".search-input"),
-        ("press-key", "Enter"),
+        focus: ".search-input"
+        press-key: "Enter"
 
-        ("wait-for", "#search-tabs"),
-        ("assert-css", ("#search-tabs > button:not(.selected)", {
+        wait-for: "#search-tabs"
+        assert-css: ("#search-tabs > button:not(.selected)", {
             "background-color": |background|,
             "border-bottom": |border_bottom|,
             "border-top": |border_top|,
-        })),
-        ("assert-css", ("#search-tabs > button.selected", {
+        })
+        assert-css: ("#search-tabs > button.selected", {
             "background-color": |background_selected|,
             "border-bottom": |border_bottom_selected|,
             "border-top": |border_top_selected|,
-        })),
-        ("move-cursor-to", "#search-tabs > button:not(.selected)"),
-        ("assert-css", ("#search-tabs > button:not(.selected):hover", {
+        })
+        move-cursor-to: "#search-tabs > button:not(.selected)"
+        assert-css: ("#search-tabs > button:not(.selected):hover", {
             "background-color": |background_hover|,
             "border-bottom": |border_bottom_hover|,
             "border-top": |border_top_hover|,
-        })),
+        })
         // To prevent disrupting next run of this function.
-        ("move-cursor-to", ".search-input"),
-    ],
+        move-cursor-to: ".search-input"
+    },
 )
 
 call-function: ("check-colors", {
diff --git a/src/test/rustdoc-gui/sidebar-links-color.goml b/src/test/rustdoc-gui/sidebar-links-color.goml
index 7ef7ec90cd2..1d5fdb7a48f 100644
--- a/src/test/rustdoc-gui/sidebar-links-color.goml
+++ b/src/test/rustdoc-gui/sidebar-links-color.goml
@@ -12,80 +12,80 @@ define-function: (
         trait_hover_background, fn, fn_hover, fn_hover_background, type, type_hover,
         type_hover_background, keyword, keyword_hover, keyword_hover_background,
     ),
-    [
-        ("local-storage", { "rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false" }),
-        ("reload"),
+    block {
+        local-storage: { "rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false" }
+        reload:
         // Struct
-        ("assert-css", (
+        assert-css: (
             ".sidebar .block.struct a:not(.current)",
             {"color": |struct|, "background-color": "rgba(0, 0, 0, 0)"},
-        )),
-        ("move-cursor-to", ".sidebar .block.struct a:not(.current)"),
-        ("assert-css", (
+        )
+        move-cursor-to: ".sidebar .block.struct a:not(.current)"
+        assert-css: (
             ".sidebar .block.struct a:hover",
             {"color": |struct_hover|, "background-color": |struct_hover_background|},
-        )),
+        )
         // Enum
-        ("assert-css", (
+        assert-css: (
             ".sidebar .block.enum a",
             {"color": |enum|, "background-color": "rgba(0, 0, 0, 0)"},
-        )),
-        ("move-cursor-to", ".sidebar .block.enum a"),
-        ("assert-css", (
+        )
+        move-cursor-to: ".sidebar .block.enum a"
+        assert-css: (
             ".sidebar .block.enum a:hover",
             {"color": |enum_hover|, "background-color": |enum_hover_background|},
-        )),
+        )
         // Union
-        ("assert-css", (
+        assert-css: (
             ".sidebar .block.union a",
             {"color": |union|, "background-color": "rgba(0, 0, 0, 0)"},
-        )),
-        ("move-cursor-to", ".sidebar .block.union a"),
-        ("assert-css", (
+        )
+        move-cursor-to: ".sidebar .block.union a"
+        assert-css: (
             ".sidebar .block.union a:hover",
             {"color": |union_hover|, "background-color": |union_hover_background|},
-        )),
+        )
         // Trait
-        ("assert-css", (
+        assert-css: (
             ".sidebar .block.trait a",
             {"color": |trait|, "background-color": "rgba(0, 0, 0, 0)"},
-        )),
-        ("move-cursor-to", ".sidebar .block.trait a"),
-        ("assert-css", (
+        )
+        move-cursor-to: ".sidebar .block.trait a"
+        assert-css: (
             ".sidebar .block.trait a:hover",
             {"color": |trait_hover|, "background-color": |trait_hover_background|},
-        )),
+        )
         // Function
-        ("assert-css", (
+        assert-css: (
             ".sidebar .block.fn a",
             {"color": |fn|, "background-color": "rgba(0, 0, 0, 0)"},
-        )),
-        ("move-cursor-to", ".sidebar .block.fn a"),
-        ("assert-css", (
+        )
+        move-cursor-to: ".sidebar .block.fn a"
+        assert-css: (
             ".sidebar .block.fn a:hover",
             {"color": |fn_hover|, "background-color": |fn_hover_background|},
-        )),
+        )
         // Type definition
-        ("assert-css", (
+        assert-css: (
             ".sidebar .block.type a",
             {"color": |type|, "background-color": "rgba(0, 0, 0, 0)"},
-        )),
-        ("move-cursor-to", ".sidebar .block.type a"),
-        ("assert-css", (
+        )
+        move-cursor-to: ".sidebar .block.type a"
+        assert-css: (
             ".sidebar .block.type a:hover",
             {"color": |type_hover|, "background-color": |type_hover_background|},
-        )),
+        )
         // Keyword
-        ("assert-css", (
+        assert-css: (
             ".sidebar .block.keyword a",
             {"color": |keyword|, "background-color": "rgba(0, 0, 0, 0)"},
-        )),
-        ("move-cursor-to", ".sidebar .block.keyword a"),
-        ("assert-css", (
+        )
+        move-cursor-to: ".sidebar .block.keyword a"
+        assert-css: (
             ".sidebar .block.keyword a:hover",
             {"color": |keyword_hover|, "background-color": |keyword_hover_background|},
-        )),
-    ]
+        )
+    }
 )
 
 call-function: (
diff --git a/src/test/rustdoc-gui/sidebar-mobile.goml b/src/test/rustdoc-gui/sidebar-mobile.goml
index 38d01f7f612..d5f4b619629 100644
--- a/src/test/rustdoc-gui/sidebar-mobile.goml
+++ b/src/test/rustdoc-gui/sidebar-mobile.goml
@@ -58,17 +58,17 @@ show-text: true
 define-function: (
     "check-colors",
     (theme, color, background),
-    [
-        ("local-storage", {"rustdoc-use-system-theme": "false", "rustdoc-theme": |theme|}),
-        ("reload"),
+    block {
+        local-storage: {"rustdoc-use-system-theme": "false", "rustdoc-theme": |theme|}
+        reload:
 
         // Open the sidebar menu.
-        ("click", ".sidebar-menu-toggle"),
-        ("assert-css", (".sidebar", {
+        click: ".sidebar-menu-toggle"
+        assert-css: (".sidebar", {
             "background-color": |background|,
             "color": |color|,
-        })),
-    ],
+        })
+    },
 )
 
 call-function: ("check-colors", {
diff --git a/src/test/rustdoc-gui/sidebar-source-code-display.goml b/src/test/rustdoc-gui/sidebar-source-code-display.goml
index df4506e1119..f3eb8ff76a3 100644
--- a/src/test/rustdoc-gui/sidebar-source-code-display.goml
+++ b/src/test/rustdoc-gui/sidebar-source-code-display.goml
@@ -35,88 +35,88 @@ define-function: (
         theme, color, color_hover, background, background_hover, background_toggle,
         background_toggle_hover,
     ),
-    [
-        ("local-storage", {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}),
-        ("reload"),
-        ("wait-for-css", ("#src-sidebar-toggle", {"visibility": "visible"})),
-        ("assert-css", (
+    block {
+        local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}
+        reload:
+        wait-for-css: ("#src-sidebar-toggle", {"visibility": "visible"})
+        assert-css: (
             "#source-sidebar details[open] > .files a.selected",
             {"color": |color_hover|, "background-color": |background|},
-        )),
+        )
 
         // Without hover or focus.
-        ("assert-css", ("#src-sidebar-toggle > button", {"background-color": |background_toggle|})),
+        assert-css: ("#src-sidebar-toggle > button", {"background-color": |background_toggle|})
         // With focus.
-        ("focus", "#src-sidebar-toggle > button"),
-        ("assert-css", (
+        focus: "#src-sidebar-toggle > button"
+        assert-css: (
             "#src-sidebar-toggle > button:focus",
             {"background-color": |background_toggle_hover|},
-        )),
-        ("focus", ".search-input"),
+        )
+        focus: ".search-input"
         // With hover.
-        ("move-cursor-to", "#src-sidebar-toggle > button"),
-        ("assert-css", (
+        move-cursor-to: "#src-sidebar-toggle > button"
+        assert-css: (
             "#src-sidebar-toggle > button:hover",
             {"background-color": |background_toggle_hover|},
-        )),
+        )
 
         // Without hover or focus.
-        ("assert-css", (
+        assert-css: (
             "#source-sidebar details[open] > .files a:not(.selected)",
             {"color": |color|, "background-color": |background_toggle|},
-        )),
+        )
         // With focus.
-        ("focus", "#source-sidebar details[open] > .files a:not(.selected)"),
-        ("wait-for-css", (
+        focus: "#source-sidebar details[open] > .files a:not(.selected)"
+        wait-for-css: (
             "#source-sidebar details[open] > .files a:not(.selected):focus",
             {"color": |color_hover|, "background-color": |background_hover|},
-        )),
-        ("focus", ".search-input"),
+        )
+        focus: ".search-input"
         // With hover.
-        ("move-cursor-to", "#source-sidebar details[open] > .files a:not(.selected)"),
-        ("assert-css", (
+        move-cursor-to: "#source-sidebar details[open] > .files a:not(.selected)"
+        assert-css: (
             "#source-sidebar details[open] > .files a:not(.selected):hover",
             {"color": |color_hover|, "background-color": |background_hover|},
-        )),
+        )
 
         // Without hover or focus.
-        ("assert-css", (
+        assert-css: (
             "#source-sidebar .dir-entry summary",
             {"color": |color|, "background-color": |background_toggle|},
-        )),
+        )
         // With focus.
-        ("focus", "#source-sidebar .dir-entry summary"),
-        ("wait-for-css", (
+        focus: "#source-sidebar .dir-entry summary"
+        wait-for-css: (
             "#source-sidebar .dir-entry summary:focus",
             {"color": |color_hover|, "background-color": |background_hover|},
-        )),
-        ("focus", ".search-input"),
+        )
+        focus: ".search-input"
         // With hover.
-        ("move-cursor-to", "#source-sidebar .dir-entry summary"),
-        ("assert-css", (
+        move-cursor-to: "#source-sidebar .dir-entry summary"
+        assert-css: (
             "#source-sidebar .dir-entry summary:hover",
             {"color": |color_hover|, "background-color": |background_hover|},
-        )),
+        )
 
         // Without hover or focus.
-        ("assert-css", (
+        assert-css: (
             "#source-sidebar details[open] > .folders > details > summary",
             {"color": |color|, "background-color": |background_toggle|},
-        )),
+        )
         // With focus.
-        ("focus", "#source-sidebar details[open] > .folders > details > summary"),
-        ("wait-for-css", (
+        focus: "#source-sidebar details[open] > .folders > details > summary"
+        wait-for-css: (
             "#source-sidebar details[open] > .folders > details > summary:focus",
             {"color": |color_hover|, "background-color": |background_hover|},
-        )),
-        ("focus", ".search-input"),
+        )
+        focus: ".search-input"
         // With hover.
-        ("move-cursor-to", "#source-sidebar details[open] > .folders > details > summary"),
-        ("assert-css", (
+        move-cursor-to: "#source-sidebar details[open] > .folders > details > summary"
+        assert-css: (
             "#source-sidebar details[open] > .folders > details > summary:hover",
             {"color": |color_hover|, "background-color": |background_hover|},
-        )),
-    ],
+        )
+    },
 )
 
 call-function: ("check-colors", {
@@ -171,15 +171,15 @@ assert-css: (
 
 // We now check that the scroll position is kept when opening the sidebar.
 click: "#src-sidebar-toggle"
-wait-for-css: (".sidebar", {"width": "0px"})
+wait-for-css: (".sidebar", {"left": "-1000px"})
 // We scroll to line 117 to change the scroll position.
 scroll-to: '//*[@id="117"]'
 assert-window-property: {"pageYOffset": "2542"}
 // Expanding the sidebar...
 click: "#src-sidebar-toggle"
-wait-for-css: (".sidebar", {"width": "500px"})
+wait-for-css: (".sidebar", {"left": "0px"})
 click: "#src-sidebar-toggle"
-wait-for-css: (".sidebar", {"width": "0px"})
+wait-for-css: (".sidebar", {"left": "-1000px"})
 // The "scrollTop" property should be the same.
 assert-window-property: {"pageYOffset": "2542"}
 
diff --git a/src/test/rustdoc-gui/sidebar-source-code.goml b/src/test/rustdoc-gui/sidebar-source-code.goml
index d5f57ed6102..c8a29b58d34 100644
--- a/src/test/rustdoc-gui/sidebar-source-code.goml
+++ b/src/test/rustdoc-gui/sidebar-source-code.goml
@@ -7,43 +7,43 @@ show-text: true
 define-function: (
     "check-colors",
     (theme, color, background_color),
-    [
-        ("local-storage", {
+    block {
+        local-storage: {
             "rustdoc-theme": |theme|,
             "rustdoc-use-system-theme": "false",
-        }),
-        ("reload"),
+        }
+        reload:
         // Checking results colors.
-        ("assert-css", (".source .sidebar", {
-        	"color": |color|,
-        	"background-color": |background_color|
-        }, ALL)),
-    ],
+        assert-css: (".source .sidebar", {
+            "color": |color|,
+            "background-color": |background_color|
+        }, ALL)
+    },
 )
 
 call-function: (
-	"check-colors",
-	{
-		"theme": "ayu",
-		"color": "rgb(197, 197, 197)",
-		"background_color": "rgb(20, 25, 31)",
-	}
+    "check-colors",
+    {
+        "theme": "ayu",
+        "color": "rgb(197, 197, 197)",
+        "background_color": "rgb(20, 25, 31)",
+    }
 )
 call-function: (
-	"check-colors",
-	{
-		"theme": "dark",
-		"color": "rgb(221, 221, 221)",
-		"background_color": "rgb(80, 80, 80)",
-	}
+    "check-colors",
+    {
+        "theme": "dark",
+        "color": "rgb(221, 221, 221)",
+        "background_color": "rgb(80, 80, 80)",
+    }
 )
 call-function: (
-	"check-colors",
-	{
-		"theme": "light",
-		"color": "rgb(0, 0, 0)",
-		"background_color": "rgb(245, 245, 245)",
-	}
+    "check-colors",
+    {
+        "theme": "light",
+        "color": "rgb(0, 0, 0)",
+        "background_color": "rgb(245, 245, 245)",
+    }
 )
 
 // Next, desktop mode layout.
@@ -73,15 +73,15 @@ 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)]", 7)
+assert-count: ("//*[@id='source-sidebar']/details[not(text()='lib2') and not(@open)]", 8)
 
 // We now switch to mobile mode.
 size: (600, 600)
-wait-for-css: (".source-sidebar-expanded nav.sidebar", {"width": "600px"})
+wait-for-css: (".source-sidebar-expanded nav.sidebar", {"left": "0px"})
 // We collapse the sidebar.
 click: (10, 10)
-// We check that the sidebar has the expected width (0).
-assert-css: ("nav.sidebar", {"width": "0px"})
+// We check that the sidebar has been moved off-screen.
+assert-css: ("nav.sidebar", {"left": "-1000px"})
 // We ensure that the class has been removed.
 assert-false: ".source-sidebar-expanded"
 assert: "nav.sidebar"
diff --git a/src/test/rustdoc-gui/sidebar.goml b/src/test/rustdoc-gui/sidebar.goml
index bfd7567a224..9c742be0587 100644
--- a/src/test/rustdoc-gui/sidebar.goml
+++ b/src/test/rustdoc-gui/sidebar.goml
@@ -7,43 +7,43 @@ show-text: true
 define-function: (
     "check-colors",
     (theme, color, background_color),
-    [
-        ("local-storage", {
+    block {
+        local-storage: {
             "rustdoc-theme": |theme|,
             "rustdoc-use-system-theme": "false",
-        }),
-        ("reload"),
+        }
+        reload:
         // Checking results colors.
-        ("assert-css", (".sidebar", {
-        	"color": |color|,
-        	"background-color": |background_color|
-        }, ALL)),
-    ],
+        assert-css: (".sidebar", {
+            "color": |color|,
+            "background-color": |background_color|
+        }, ALL)
+    },
 )
 
 call-function: (
-	"check-colors",
-	{
-		"theme": "ayu",
-		"color": "rgb(197, 197, 197)",
-		"background_color": "rgb(20, 25, 31)",
-	}
+    "check-colors",
+    {
+        "theme": "ayu",
+        "color": "rgb(197, 197, 197)",
+        "background_color": "rgb(20, 25, 31)",
+    }
 )
 call-function: (
-	"check-colors",
-	{
-		"theme": "dark",
-		"color": "rgb(221, 221, 221)",
-		"background_color": "rgb(80, 80, 80)",
-	}
+    "check-colors",
+    {
+        "theme": "dark",
+        "color": "rgb(221, 221, 221)",
+        "background_color": "rgb(80, 80, 80)",
+    }
 )
 call-function: (
-	"check-colors",
-	{
-		"theme": "light",
-		"color": "rgb(0, 0, 0)",
-		"background_color": "rgb(245, 245, 245)",
-	}
+    "check-colors",
+    {
+        "theme": "light",
+        "color": "rgb(0, 0, 0)",
+        "background_color": "rgb(245, 245, 245)",
+    }
 )
 
 local-storage: {"rustdoc-theme": "light"}
@@ -148,4 +148,4 @@ assert-text: ("#toggle-all-docs", "[+]")
 assert-property: (".sidebar", {"clientWidth": "200"})
 click: "#toggle-all-docs"
 assert-text: ("#toggle-all-docs", "[−]")
-assert-property: (".sidebar", {"clientWidth": "200"})
\ No newline at end of file
+assert-property: (".sidebar", {"clientWidth": "200"})
diff --git a/src/test/rustdoc-gui/source-code-page.goml b/src/test/rustdoc-gui/source-code-page.goml
index aa792196960..7c35119e695 100644
--- a/src/test/rustdoc-gui/source-code-page.goml
+++ b/src/test/rustdoc-gui/source-code-page.goml
@@ -22,20 +22,20 @@ assert-attribute-false: (".src-line-numbers > a:nth-child(7)", {"class": "line-h
 define-function: (
     "check-colors",
     (theme, color, background_color, highlight_color, highlight_background_color),
-    [
-        ("local-storage", {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}),
-        ("reload"),
-        ("assert-css", (
+    block {
+        local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}
+        reload:
+        assert-css: (
             ".src-line-numbers > a:not(.line-highlighted)",
             {"color": |color|, "background-color": |background_color|},
             ALL,
-        )),
-        ("assert-css", (
+        )
+        assert-css: (
             ".src-line-numbers > a.line-highlighted",
             {"color": |highlight_color|, "background-color": |highlight_background_color|},
             ALL,
-        )),
-    ],
+        )
+    },
 )
 
 call-function: ("check-colors", {
@@ -102,7 +102,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", "huge_logo")
+assert-text: ("#source-sidebar details:first-of-type > summary", "http")
 // We now click on it.
 click: "#source-sidebar details:first-of-type > summary"
 assert-property: ("#source-sidebar details:first-of-type", {"open": "true"})
@@ -124,28 +124,28 @@ store-property: (
 define-function: (
     "check-sidebar-dir-entry",
     (x, y),
-    [
-        ("assert", "details:first-of-type.dir-entry[open] > summary::marker"),
-        ("assert-css", ("#source-sidebar > details:first-of-type.dir-entry", {"padding-left": "4px"})),
+    block {
+        assert: "details:first-of-type.dir-entry[open] > summary::marker"
+        assert-css: ("#source-sidebar > details:first-of-type.dir-entry", {"padding-left": "4px"})
         // This check ensures that the summary is only one line.
-       ("assert-property", (
+        assert-property: (
             "#source-sidebar > details:first-of-type.dir-entry[open] > summary",
             {"offsetHeight": |link_height|}
-        )),
-        ("assert-position", (
+        )
+        assert-position: (
             "#source-sidebar > details:first-of-type.dir-entry[open] > summary",
             {"x": |x|, "y": |y|}
-        )),
-        ("assert-property", (
+        )
+        assert-property: (
             "#source-sidebar > details:first-of-type.dir-entry[open] > .files > a",
             {"offsetHeight": |link_height|}
-        )),
-        ("assert-position", (
+        )
+        assert-position: (
             "#source-sidebar > details:first-of-type.dir-entry[open] > .files > a",
             // left margin
             {"x": |x| + 27, "y": |y| + |link_height|}
-        )),
-    ]
+        )
+    }
 )
 store-property: (
     source_sidebar_title_height,
diff --git a/src/test/rustdoc-gui/src/lib2/Cargo.lock b/src/test/rustdoc-gui/src/lib2/Cargo.lock
index a5873ceb325..425a3ae7e5c 100644
--- a/src/test/rustdoc-gui/src/lib2/Cargo.lock
+++ b/src/test/rustdoc-gui/src/lib2/Cargo.lock
@@ -3,12 +3,20 @@
 version = 3
 
 [[package]]
+name = "http"
+version = "0.1.0"
+
+[[package]]
 name = "implementors"
 version = "0.1.0"
+dependencies = [
+ "http",
+]
 
 [[package]]
 name = "lib2"
 version = "0.1.0"
 dependencies = [
+ "http",
  "implementors",
 ]
diff --git a/src/test/rustdoc-gui/src/lib2/Cargo.toml b/src/test/rustdoc-gui/src/lib2/Cargo.toml
index 2e37f3f667a..8bca77ff834 100644
--- a/src/test/rustdoc-gui/src/lib2/Cargo.toml
+++ b/src/test/rustdoc-gui/src/lib2/Cargo.toml
@@ -8,3 +8,4 @@ path = "lib.rs"
 
 [dependencies]
 implementors = { path = "./implementors" }
+http = { path = "./http" }
diff --git a/src/test/rustdoc-gui/src/lib2/http/Cargo.toml b/src/test/rustdoc-gui/src/lib2/http/Cargo.toml
new file mode 100644
index 00000000000..fa719efa526
--- /dev/null
+++ b/src/test/rustdoc-gui/src/lib2/http/Cargo.toml
@@ -0,0 +1,7 @@
+[package]
+name = "http"
+version = "0.1.0"
+edition = "2018"
+
+[lib]
+path = "lib.rs"
diff --git a/src/test/rustdoc-gui/src/lib2/http/lib.rs b/src/test/rustdoc-gui/src/lib2/http/lib.rs
new file mode 100644
index 00000000000..204e0749427
--- /dev/null
+++ b/src/test/rustdoc-gui/src/lib2/http/lib.rs
@@ -0,0 +1 @@
+pub trait HttpTrait {}
diff --git a/src/test/rustdoc-gui/src/lib2/implementors/Cargo.toml b/src/test/rustdoc-gui/src/lib2/implementors/Cargo.toml
index 7ef1052c49f..9dafc43df5f 100644
--- a/src/test/rustdoc-gui/src/lib2/implementors/Cargo.toml
+++ b/src/test/rustdoc-gui/src/lib2/implementors/Cargo.toml
@@ -5,3 +5,6 @@ edition = "2018"
 
 [lib]
 path = "lib.rs"
+
+[dependencies]
+http = { path = "../http/" }
diff --git a/src/test/rustdoc-gui/src/lib2/implementors/lib.rs b/src/test/rustdoc-gui/src/lib2/implementors/lib.rs
index 1620e842291..2842ac50dc1 100644
--- a/src/test/rustdoc-gui/src/lib2/implementors/lib.rs
+++ b/src/test/rustdoc-gui/src/lib2/implementors/lib.rs
@@ -10,6 +10,8 @@ impl Whatever for Struct {
     type Foo = u8;
 }
 
+impl http::HttpTrait for Struct {}
+
 mod traits {
     pub trait TraitToReexport {
         fn method() {}
diff --git a/src/test/rustdoc-gui/stab-badge.goml b/src/test/rustdoc-gui/stab-badge.goml
index aaed8440a40..50ba1ba62db 100644
--- a/src/test/rustdoc-gui/stab-badge.goml
+++ b/src/test/rustdoc-gui/stab-badge.goml
@@ -2,40 +2,40 @@
 goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
 show-text: true
 define-function: (
-	"check-badge",
-	(theme, background, color),
-	[
-        ("local-storage", {"rustdoc-use-system-theme": "false", "rustdoc-theme": |theme|}),
-        ("goto", "file://" + |DOC_PATH| + "/test_docs/index.html"),
-		("assert", (".docblock .stab")),
-		("assert", (".item-table .stab")),
-		("assert-css", (".stab", {
-			"border-radius": "3px",
-			"color": |color|,
-			"background-color": |background|,
-		})),
-        ("goto", "file://" + |DOC_PATH| + "/test_docs/fn.replaced_function.html"),
-		("assert", (".item-info .stab")),
-		("assert-css", (".stab", {
-			"border-radius": "3px",
-			"color": |color|,
-			"background-color": |background|,
-		})),
-	]
+    "check-badge",
+    (theme, background, color),
+    block {
+        local-storage: {"rustdoc-use-system-theme": "false", "rustdoc-theme": |theme|}
+        goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
+        assert: ".docblock .stab"
+        assert: ".item-table .stab"
+        assert-css: (".stab", {
+            "border-radius": "3px",
+            "color": |color|,
+            "background-color": |background|,
+        })
+        goto: "file://" + |DOC_PATH| + "/test_docs/fn.replaced_function.html"
+        assert: (".item-info .stab")
+        assert-css: (".stab", {
+            "border-radius": "3px",
+            "color": |color|,
+            "background-color": |background|,
+        })
+    },
 )
 
 call-function: ("check-badge", {
-	"theme": "ayu",
-	"color": "rgb(197, 197, 197)",
-	"background": "rgb(49, 69, 89)",
+    "theme": "ayu",
+    "color": "rgb(197, 197, 197)",
+    "background": "rgb(49, 69, 89)",
 })
 call-function: ("check-badge", {
-	"theme": "dark",
-	"color": "rgb(221, 221, 221)",
-	"background": "rgb(49, 69, 89)",
+    "theme": "dark",
+    "color": "rgb(221, 221, 221)",
+    "background": "rgb(49, 69, 89)",
 })
 call-function: ("check-badge", {
-	"theme": "light",
-	"color": "rgb(0, 0, 0)",
-	"background": "rgb(255, 245, 214)",
+    "theme": "light",
+    "color": "rgb(0, 0, 0)",
+    "background": "rgb(255, 245, 214)",
 })
diff --git a/src/test/rustdoc-gui/target.goml b/src/test/rustdoc-gui/target.goml
index 3e5c30dc7ea..ca393ee5891 100644
--- a/src/test/rustdoc-gui/target.goml
+++ b/src/test/rustdoc-gui/target.goml
@@ -8,14 +8,14 @@ assert: "#method\.a_method:target"
 define-function: (
     "check-style",
     (theme, background, border),
-    [
-        ("local-storage", {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}),
-        ("reload"),
-        ("assert-css", ("#method\.a_method:target", {
+    block {
+        local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}
+        reload:
+        assert-css: ("#method\.a_method:target", {
             "background-color": |background|,
             "border-right": "3px solid " + |border|,
-        })),
-    ],
+        })
+    },
 )
 
 call-function: ("check-style", {
diff --git a/src/test/rustdoc-gui/toggle-docs.goml b/src/test/rustdoc-gui/toggle-docs.goml
index 45bb8daf1f2..89ce78e3aab 100644
--- a/src/test/rustdoc-gui/toggle-docs.goml
+++ b/src/test/rustdoc-gui/toggle-docs.goml
@@ -50,24 +50,24 @@ show-text: true
 define-function: (
     "check-color",
     (theme, filter),
-    [
+    block {
         // Setting the theme.
-	("local-storage", {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}),
+        local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}
         // We reload the page so the local storage settings are being used.
-        ("reload"),
+        reload:
 
-        ("assert-css", ("details.rustdoc-toggle > summary::before", {
+        assert-css: ("details.rustdoc-toggle > summary::before", {
             "opacity": "0.5",
             "filter": |filter|,
-        }, ALL)),
-        ("move-cursor-to", "details.rustdoc-toggle summary"),
-        ("assert-css", ("details.rustdoc-toggle > summary:hover::before", {
+        }, ALL)
+        move-cursor-to: "details.rustdoc-toggle summary"
+        assert-css: ("details.rustdoc-toggle > summary:hover::before", {
             "opacity": "1",
             "filter": |filter|,
-        })),
+        })
         // moving the cursor somewhere else to not mess with next function calls.
-        ("move-cursor-to", ".search-input"),
-    ]
+        move-cursor-to: ".search-input"
+    },
 )
 
 call-function: ("check-color", {"theme": "ayu", "filter": "invert(1)"})
diff --git a/src/test/rustdoc-gui/type-declation-overflow.goml b/src/test/rustdoc-gui/type-declation-overflow.goml
index c014eb52e71..9b60bc04738 100644
--- a/src/test/rustdoc-gui/type-declation-overflow.goml
+++ b/src/test/rustdoc-gui/type-declation-overflow.goml
@@ -1,3 +1,4 @@
+// ignore-tidy-linelength
 // This test ensures that the items declaration content overflow is handled inside the <pre> directly.
 
 // We need to disable this check because
diff --git a/src/test/rustdoc-gui/unsafe-fn.goml b/src/test/rustdoc-gui/unsafe-fn.goml
index 5e43b85fce0..d3a672ddde6 100644
--- a/src/test/rustdoc-gui/unsafe-fn.goml
+++ b/src/test/rustdoc-gui/unsafe-fn.goml
@@ -14,13 +14,13 @@ define-function: (
     // `theme` is the theme being tested.
     // `color` is the expected color of the `<sup>` element.
     (theme, color),
-    [
+    block {
         // Set the theme.
-        ("local-storage", {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}),
+        local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}
         // We reload the page so the local storage settings are being used.
-        ("reload"),
-        ("assert-css", (".item-left sup", {"color": |color|})),
-    ],
+        reload:
+        assert-css: (".item-left sup", {"color": |color|})
+    },
 )
 
 call-function: ("sup-check", ("dark", "rgb(221, 221, 221)"))
diff --git a/src/test/rustdoc-json/doc_hidden_failure.rs b/src/test/rustdoc-json/doc_hidden_failure.rs
index 6573166c47f..0d2c6b2209b 100644
--- a/src/test/rustdoc-json/doc_hidden_failure.rs
+++ b/src/test/rustdoc-json/doc_hidden_failure.rs
@@ -14,7 +14,8 @@ mod auto {
     }
 }
 
-// @count "$.index[*][?(@.name=='builders')]" 2
+// @count "$.index[*][?(@.name=='builders')]" 1
+// @has "$.index[*][?(@.name == 'ActionRowBuilder')"]
 pub use auto::*;
 
 pub mod builders {
diff --git a/src/test/rustdoc-json/primitives/local_primitive.rs b/src/test/rustdoc-json/primitives/local_primitive.rs
new file mode 100644
index 00000000000..f27e6a2adec
--- /dev/null
+++ b/src/test/rustdoc-json/primitives/local_primitive.rs
@@ -0,0 +1,21 @@
+// Regression test for <https://github.com/rust-lang/rust/issues/104064>.
+
+#![feature(no_core)]
+#![feature(rustc_attrs)]
+#![feature(rustdoc_internals)]
+#![no_core]
+#![rustc_coherence_is_core]
+
+//! Link to [i32][prim@i32] [i64][prim@i64]
+
+#[doc(primitive = "i32")]
+mod prim_i32 {}
+
+// @set local_i32 = "$.index[*][?(@.name=='i32')].id"
+
+// @has "$.index[*][?(@.name=='local_primitive')]"
+// @ismany "$.index[*][?(@.name=='local_primitive')].inner.items[*]" $local_i32
+// @is "$.index[*][?(@.name=='local_primitive')].links['prim@i32']" $local_i32
+
+// Let's ensure the `prim_i32` module isn't present in the output JSON:
+// @!has "$.index[*][?(@.name=='prim_i32')]"
diff --git a/src/test/rustdoc-json/reexport/pub_use_doc_hidden.rs b/src/test/rustdoc-json/reexport/pub_use_doc_hidden.rs
new file mode 100644
index 00000000000..a2a25d08448
--- /dev/null
+++ b/src/test/rustdoc-json/reexport/pub_use_doc_hidden.rs
@@ -0,0 +1,15 @@
+// Regression test for <https://github.com/rust-lang/rust/issues/106379>
+
+#![feature(no_core)]
+#![no_core]
+
+mod repeat_n {
+    #[doc(hidden)]
+    pub struct RepeatN {}
+}
+
+pub use repeat_n::RepeatN;
+
+// @count "$.index[*][?(@.name=='pub_use_doc_hidden')].inner.items[*]" 0
+// @!has "$.index[*][?(@.kind=='struct')]"
+// @!has "$.index[*][?(@.kind=='import')]"
diff --git a/src/test/rustdoc-ui/issue-105742.stderr b/src/test/rustdoc-ui/issue-105742.stderr
index cc101b7ff37..ffb602cf861 100644
--- a/src/test/rustdoc-ui/issue-105742.stderr
+++ b/src/test/rustdoc-ui/issue-105742.stderr
@@ -12,7 +12,7 @@ LL |     type Item<'a, T>;
 help: add missing lifetime argument
    |
 LL |     <Self as SVec>::Item<'a>,
-   |                     ~~~~~~~~
+   |                         ++++
 
 error[E0107]: missing generics for associated type `SVec::Item`
   --> $DIR/issue-105742.rs:13:21
@@ -28,7 +28,7 @@ LL |     type Item<'a, T>;
 help: add missing generic argument
    |
 LL |     <Self as SVec>::Item<T>,
-   |                     ~~~~~~~
+   |                         +++
 
 error[E0107]: missing generics for associated type `SVec::Item`
   --> $DIR/issue-105742.rs:18:37
@@ -44,7 +44,7 @@ LL |     type Item<'a, T>;
 help: add missing lifetime argument
    |
 LL |     Output = <Index<<Self as SVec>::Item<'a>,
-   |                                     ~~~~~~~~
+   |                                         ++++
 
 error[E0107]: missing generics for associated type `SVec::Item`
   --> $DIR/issue-105742.rs:18:37
@@ -60,7 +60,7 @@ LL |     type Item<'a, T>;
 help: add missing generic argument
    |
 LL |     Output = <Index<<Self as SVec>::Item<T>,
-   |                                     ~~~~~~~
+   |                                         +++
 
 error[E0107]: missing generics for associated type `SVec::Item`
   --> $DIR/issue-105742.rs:23:30
@@ -76,7 +76,7 @@ LL |     type Item<'a, T>;
 help: add missing lifetime argument
    |
 LL |     Output = <Self as SVec>::Item<'a>> as SVec>::Item,
-   |                              ~~~~~~~~
+   |                                  ++++
 
 error[E0107]: missing generics for associated type `SVec::Item`
   --> $DIR/issue-105742.rs:23:30
@@ -92,7 +92,7 @@ LL |     type Item<'a, T>;
 help: add missing generic argument
    |
 LL |     Output = <Self as SVec>::Item<T>> as SVec>::Item,
-   |                              ~~~~~~~
+   |                                  +++
 
 error[E0107]: missing generics for associated type `SVec::Item`
   --> $DIR/issue-105742.rs:23:46
@@ -108,7 +108,7 @@ LL |     type Item<'a, T>;
 help: add missing lifetime argument
    |
 LL |     Output = <Self as SVec>::Item> as SVec>::Item<'a>,
-   |                                              ~~~~~~~~
+   |                                                  ++++
 
 error[E0107]: missing generics for associated type `SVec::Item`
   --> $DIR/issue-105742.rs:23:46
@@ -124,7 +124,7 @@ LL |     type Item<'a, T>;
 help: add missing generic argument
    |
 LL |     Output = <Self as SVec>::Item> as SVec>::Item<T>,
-   |                                              ~~~~~~~
+   |                                                  +++
 
 error[E0107]: missing generics for associated type `SVec::Item`
   --> $DIR/issue-105742.rs:5:40
@@ -140,7 +140,7 @@ LL |     type Item<'a, T>;
 help: add missing lifetime argument
    |
 LL | pub fn next<'a, T>(s: &'a mut dyn SVec<Item<'_> = T, Output = T>) {
-   |                                        ~~~~~~~~
+   |                                            ++++
 
 error[E0107]: missing generics for associated type `SVec::Item`
   --> $DIR/issue-105742.rs:5:40
@@ -156,7 +156,7 @@ LL |     type Item<'a, T>;
 help: add missing generic argument
    |
 LL | pub fn next<'a, T>(s: &'a mut dyn SVec<Item<T> = T, Output = T>) {
-   |                                        ~~~~~~~
+   |                                            +++
 
 error[E0107]: missing generics for associated type `SVec::Item`
   --> $DIR/issue-105742.rs:13:21
@@ -172,7 +172,7 @@ LL |     type Item<'a, T>;
 help: add missing lifetime argument
    |
 LL |     <Self as SVec>::Item<'a>,
-   |                     ~~~~~~~~
+   |                         ++++
 
 error[E0107]: missing generics for associated type `SVec::Item`
   --> $DIR/issue-105742.rs:13:21
@@ -188,7 +188,7 @@ LL |     type Item<'a, T>;
 help: add missing generic argument
    |
 LL |     <Self as SVec>::Item<T>,
-   |                     ~~~~~~~
+   |                         +++
 
 error[E0107]: missing generics for associated type `SVec::Item`
   --> $DIR/issue-105742.rs:18:37
@@ -204,7 +204,7 @@ LL |     type Item<'a, T>;
 help: add missing lifetime argument
    |
 LL |     Output = <Index<<Self as SVec>::Item<'a>,
-   |                                     ~~~~~~~~
+   |                                         ++++
 
 error[E0107]: missing generics for associated type `SVec::Item`
   --> $DIR/issue-105742.rs:18:37
@@ -220,7 +220,7 @@ LL |     type Item<'a, T>;
 help: add missing generic argument
    |
 LL |     Output = <Index<<Self as SVec>::Item<T>,
-   |                                     ~~~~~~~
+   |                                         +++
 
 error[E0107]: missing generics for associated type `SVec::Item`
   --> $DIR/issue-105742.rs:23:30
@@ -236,7 +236,7 @@ LL |     type Item<'a, T>;
 help: add missing lifetime argument
    |
 LL |     Output = <Self as SVec>::Item<'a>> as SVec>::Item,
-   |                              ~~~~~~~~
+   |                                  ++++
 
 error[E0107]: missing generics for associated type `SVec::Item`
   --> $DIR/issue-105742.rs:23:30
@@ -252,7 +252,7 @@ LL |     type Item<'a, T>;
 help: add missing generic argument
    |
 LL |     Output = <Self as SVec>::Item<T>> as SVec>::Item,
-   |                              ~~~~~~~
+   |                                  +++
 
 error[E0107]: missing generics for associated type `SVec::Item`
   --> $DIR/issue-105742.rs:23:46
@@ -268,7 +268,7 @@ LL |     type Item<'a, T>;
 help: add missing lifetime argument
    |
 LL |     Output = <Self as SVec>::Item> as SVec>::Item<'a>,
-   |                                              ~~~~~~~~
+   |                                                  ++++
 
 error[E0107]: missing generics for associated type `SVec::Item`
   --> $DIR/issue-105742.rs:23:46
@@ -284,7 +284,7 @@ LL |     type Item<'a, T>;
 help: add missing generic argument
    |
 LL |     Output = <Self as SVec>::Item> as SVec>::Item<T>,
-   |                                              ~~~~~~~
+   |                                                  +++
 
 error[E0038]: the trait `SVec` cannot be made into an object
   --> $DIR/issue-105742.rs:5:31
@@ -329,7 +329,7 @@ LL |     type Item<'a, T>;
 help: add missing lifetime argument
    |
 LL |     fn len(&self) -> <Self as SVec>::Item<'_>;
-   |                                      ~~~~~~~~
+   |                                          ++++
 
 error[E0107]: missing generics for associated type `SVec::Item`
   --> $DIR/issue-105742.rs:35:38
@@ -345,7 +345,7 @@ LL |     type Item<'a, T>;
 help: add missing generic argument
    |
 LL |     fn len(&self) -> <Self as SVec>::Item<T>;
-   |                                      ~~~~~~~
+   |                                          +++
 
 error[E0107]: missing generics for associated type `SVec::Item`
   --> $DIR/issue-105742.rs:35:38
@@ -361,7 +361,7 @@ LL |     type Item<'a, T>;
 help: add missing lifetime argument
    |
 LL |     fn len(&self) -> <Self as SVec>::Item<'_>;
-   |                                      ~~~~~~~~
+   |                                          ++++
 
 error[E0107]: missing generics for associated type `SVec::Item`
   --> $DIR/issue-105742.rs:35:38
@@ -377,7 +377,7 @@ LL |     type Item<'a, T>;
 help: add missing generic argument
    |
 LL |     fn len(&self) -> <Self as SVec>::Item<T>;
-   |                                      ~~~~~~~
+   |                                          +++
 
 error: aborting due to 23 previous errors
 
diff --git a/src/test/rustdoc-ui/z-help.stdout b/src/test/rustdoc-ui/z-help.stdout
index 53677b18377..537dc92be19 100644
--- a/src/test/rustdoc-ui/z-help.stdout
+++ b/src/test/rustdoc-ui/z-help.stdout
@@ -8,7 +8,6 @@
     -Z                       branch-protection=val -- set options for branch target identification and pointer authentication on AArch64
     -Z                           cf-protection=val -- instrument control-flow architecture protection
     -Z               cgu-partitioning-strategy=val -- the codegen unit partitioning strategy to use
-    -Z                                   chalk=val -- enable the experimental Chalk-based trait solving engine
     -Z                         codegen-backend=val -- the backend to use
     -Z                             combine-cgu=val -- combine CGUs into a single one
     -Z                              crate-attr=val -- inject the given attribute in the crate
@@ -35,7 +34,8 @@
     -Z            dump-mir-exclude-pass-number=val -- exclude the pass number when dumping MIR (used in tests) (default: no)
     -Z                       dump-mir-graphviz=val -- in addition to `.mir` files, create graphviz `.dot` files (and with `-Z instrument-coverage`, also create a `.dot` file for the MIR-derived coverage graph) (default: no)
     -Z                       dump-mir-spanview=val -- in addition to `.mir` files, create `.html` files to view spans for all `statement`s (including terminators), only `terminator` spans, or computed `block` spans (one span encompassing a block's terminator and all statements). If `-Z instrument-coverage` is also enabled, create an additional `.html` file showing the computed coverage spans.
-    -Z                         dump-mono-stats=val -- output statistics about monomorphization collection (format: markdown)
+    -Z                         dump-mono-stats=val -- output statistics about monomorphization collection
+    -Z                  dump-mono-stats-format=val -- the format to use for -Z dump-mono-stats (`markdown` (default) or `json`)
     -Z                           dwarf-version=val -- version of DWARF debug information to emit (default: 2 or 4, depending on platform)
     -Z                               dylib-lto=val -- enables LTO for dylib crate type
     -Z                        emit-stack-sizes=val -- emit a section containing stack size metadata (default: no)
@@ -174,6 +174,7 @@
     -Z                               tls-model=val -- choose the TLS model to use (`rustc --print tls-models` for details)
     -Z                            trace-macros=val -- for every macro invocation, print its name and arguments (default: no)
     -Z                       track-diagnostics=val -- tracks where in rustc a diagnostic was emitted
+    -Z                            trait-solver=val -- specify the trait solver mode used by rustc (default: classic)
     -Z                translate-additional-ftl=val -- additional fluent translation to preferentially use (for testing translation)
     -Z        translate-directionality-markers=val -- emit directionality isolation markers in translated diagnostics
     -Z                          translate-lang=val -- language identifier for diagnostic output
diff --git a/src/test/rustdoc/src-links.rs b/src/test/rustdoc/src-links.rs
index 353ce10243e..7a6c733d464 100644
--- a/src/test/rustdoc/src-links.rs
+++ b/src/test/rustdoc/src-links.rs
@@ -7,6 +7,11 @@
 #[path = "src-links/mod.rs"]
 pub mod qux;
 
+// @has src/foo/src-links.rs.html
+// @has foo/fizz/index.html '//a/@href' '../src/foo/src-links/fizz.rs.html'
+#[path = "src-links/../src-links/fizz.rs"]
+pub mod fizz;
+
 // @has foo/bar/index.html '//a/@href' '../../src/foo/src-links.rs.html'
 pub mod bar {
 
diff --git a/src/test/rustdoc/src-links/fizz.rs b/src/test/rustdoc/src-links/fizz.rs
new file mode 100644
index 00000000000..d2b76b1cec8
--- /dev/null
+++ b/src/test/rustdoc/src-links/fizz.rs
@@ -0,0 +1 @@
+pub struct Buzz;
diff --git a/src/test/ui/alloc-error/alloc-error-handler-bad-signature-3.rs b/src/test/ui/alloc-error/alloc-error-handler-bad-signature-3.rs
index 8430fabe84d..ea9ad39a70d 100644
--- a/src/test/ui/alloc-error/alloc-error-handler-bad-signature-3.rs
+++ b/src/test/ui/alloc-error/alloc-error-handler-bad-signature-3.rs
@@ -7,7 +7,7 @@
 struct Layout;
 
 #[alloc_error_handler]
-fn oom() -> ! { //~ ERROR this function takes 0 arguments but 1 argument was supplied
+fn oom() -> ! { //~ ERROR function takes 0 arguments but 1 argument was supplied
     loop {}
 }
 
diff --git a/src/test/ui/argument-suggestions/basic.rs b/src/test/ui/argument-suggestions/basic.rs
index 3e96322d67e..961e7a50e56 100644
--- a/src/test/ui/argument-suggestions/basic.rs
+++ b/src/test/ui/argument-suggestions/basic.rs
@@ -18,11 +18,11 @@ fn permuted(_x: X, _y: Y, _z: Z) {}
 
 fn main() {
     invalid(1.0); //~ ERROR mismatched types
-    extra(""); //~ ERROR this function takes
-    missing(); //~ ERROR this function takes
+    extra(""); //~ ERROR function takes
+    missing(); //~ ERROR function takes
     swapped("", 1); //~ ERROR arguments to this function are incorrect
     permuted(Y {}, Z {}, X {}); //~ ERROR arguments to this function are incorrect
 
     let closure = |x| x;
-    closure(); //~ ERROR this function takes
+    closure(); //~ ERROR function takes
 }
diff --git a/src/test/ui/argument-suggestions/display-is-suggestable.rs b/src/test/ui/argument-suggestions/display-is-suggestable.rs
index d765bc4f74d..acb61f54308 100644
--- a/src/test/ui/argument-suggestions/display-is-suggestable.rs
+++ b/src/test/ui/argument-suggestions/display-is-suggestable.rs
@@ -4,5 +4,5 @@ fn foo(x: &(dyn Display + Send)) {}
 
 fn main() {
     foo();
-    //~^ ERROR this function takes 1 argument but 0 arguments were supplied
+    //~^ ERROR function takes 1 argument but 0 arguments were supplied
 }
diff --git a/src/test/ui/argument-suggestions/exotic-calls.rs b/src/test/ui/argument-suggestions/exotic-calls.rs
index a18e967668d..569a39a2b45 100644
--- a/src/test/ui/argument-suggestions/exotic-calls.rs
+++ b/src/test/ui/argument-suggestions/exotic-calls.rs
@@ -1,11 +1,11 @@
 fn foo<T: Fn()>(t: T) {
     t(1i32);
-    //~^ ERROR this function takes 0 arguments but 1 argument was supplied
+    //~^ ERROR function takes 0 arguments but 1 argument was supplied
 }
 
 fn bar(t: impl Fn()) {
     t(1i32);
-    //~^ ERROR this function takes 0 arguments but 1 argument was supplied
+    //~^ ERROR function takes 0 arguments but 1 argument was supplied
 }
 
 fn baz() -> impl Fn() {
@@ -14,13 +14,13 @@ fn baz() -> impl Fn() {
 
 fn baz2() {
     baz()(1i32)
-    //~^ ERROR this function takes 0 arguments but 1 argument was supplied
+    //~^ ERROR function takes 0 arguments but 1 argument was supplied
 }
 
 fn qux() {
     let x = || {};
     x(1i32);
-    //~^ ERROR this function takes 0 arguments but 1 argument was supplied
+    //~^ ERROR function takes 0 arguments but 1 argument was supplied
 }
 
 fn main() {}
diff --git a/src/test/ui/argument-suggestions/extern-fn-arg-names.rs b/src/test/ui/argument-suggestions/extern-fn-arg-names.rs
index 6c925a3d653..df2fd6624cd 100644
--- a/src/test/ui/argument-suggestions/extern-fn-arg-names.rs
+++ b/src/test/ui/argument-suggestions/extern-fn-arg-names.rs
@@ -5,5 +5,5 @@ extern "Rust" {
 
 fn main() {
     dstfn(1);
-    //~^ ERROR this function takes 2 arguments but 1 argument was supplied
+    //~^ ERROR function takes 2 arguments but 1 argument was supplied
 }
diff --git a/src/test/ui/argument-suggestions/extra_arguments.rs b/src/test/ui/argument-suggestions/extra_arguments.rs
index 3706ac4e8e1..3f83de95e2d 100644
--- a/src/test/ui/argument-suggestions/extra_arguments.rs
+++ b/src/test/ui/argument-suggestions/extra_arguments.rs
@@ -4,30 +4,30 @@ fn two_arg_same(_a: i32, _b: i32) {}
 fn two_arg_diff(_a: i32, _b: &str) {}
 
 fn main() {
-  empty(""); //~ ERROR this function takes
+  empty(""); //~ ERROR function takes
 
-  one_arg(1, 1); //~ ERROR this function takes
-  one_arg(1, ""); //~ ERROR this function takes
-  one_arg(1, "", 1.0); //~ ERROR this function takes
+  one_arg(1, 1); //~ ERROR function takes
+  one_arg(1, ""); //~ ERROR function takes
+  one_arg(1, "", 1.0); //~ ERROR function takes
 
-  two_arg_same(1, 1, 1); //~ ERROR this function takes
-  two_arg_same(1, 1, 1.0); //~ ERROR this function takes
+  two_arg_same(1, 1, 1); //~ ERROR function takes
+  two_arg_same(1, 1, 1.0); //~ ERROR function takes
 
-  two_arg_diff(1, 1, ""); //~ ERROR this function takes
-  two_arg_diff(1, "", ""); //~ ERROR this function takes
-  two_arg_diff(1, 1, "", ""); //~ ERROR this function takes
-  two_arg_diff(1, "", 1, ""); //~ ERROR this function takes
+  two_arg_diff(1, 1, ""); //~ ERROR function takes
+  two_arg_diff(1, "", ""); //~ ERROR function takes
+  two_arg_diff(1, 1, "", ""); //~ ERROR function takes
+  two_arg_diff(1, "", 1, ""); //~ ERROR function takes
 
   // Check with weird spacing and newlines
-  two_arg_same(1, 1,     ""); //~ ERROR this function takes
-  two_arg_diff(1, 1,     ""); //~ ERROR this function takes
-  two_arg_same( //~ ERROR this function takes
+  two_arg_same(1, 1,     ""); //~ ERROR function takes
+  two_arg_diff(1, 1,     ""); //~ ERROR function takes
+  two_arg_same( //~ ERROR function takes
     1,
     1,
     ""
   );
 
-  two_arg_diff( //~ ERROR this function takes
+  two_arg_diff( //~ ERROR function takes
     1,
     1,
     ""
diff --git a/src/test/ui/argument-suggestions/issue-100154.rs b/src/test/ui/argument-suggestions/issue-100154.rs
index 4446b4bc2fc..fb0af05e9dc 100644
--- a/src/test/ui/argument-suggestions/issue-100154.rs
+++ b/src/test/ui/argument-suggestions/issue-100154.rs
@@ -2,6 +2,6 @@ fn foo(i: impl std::fmt::Display) {}
 
 fn main() {
     foo::<()>(());
-    //~^ ERROR this function takes 0 generic arguments but 1 generic argument was supplied
+    //~^ ERROR function takes 0 generic arguments but 1 generic argument was supplied
     //~| ERROR `()` doesn't implement `std::fmt::Display`
 }
diff --git a/src/test/ui/argument-suggestions/issue-100478.rs b/src/test/ui/argument-suggestions/issue-100478.rs
index 6bef6ad1038..fb50fa11537 100644
--- a/src/test/ui/argument-suggestions/issue-100478.rs
+++ b/src/test/ui/argument-suggestions/issue-100478.rs
@@ -31,7 +31,7 @@ fn three_diff(_a: T1, _b: T2, _c: T3) {}
 fn four_shuffle(_a: T1, _b: T2, _c: T3, _d: T4) {}
 
 fn main() {
-    three_diff(T2::new(0)); //~ ERROR this function takes
+    three_diff(T2::new(0)); //~ ERROR function takes
     four_shuffle(T3::default(), T4::default(), T1::default(), T2::default()); //~ ERROR 35:5: 35:17: arguments to this function are incorrect [E0308]
     four_shuffle(T3::default(), T2::default(), T1::default(), T3::default()); //~ ERROR 36:5: 36:17: arguments to this function are incorrect [E0308]
 
diff --git a/src/test/ui/argument-suggestions/issue-101097.rs b/src/test/ui/argument-suggestions/issue-101097.rs
index 7994d3cd995..25f7f583799 100644
--- a/src/test/ui/argument-suggestions/issue-101097.rs
+++ b/src/test/ui/argument-suggestions/issue-101097.rs
@@ -13,7 +13,7 @@ fn f(
 ) {}
 
 fn main() {
-    f(C, A, A, A, B, B, C); //~ ERROR this function takes 6 arguments but 7 arguments were supplied [E0061]
+    f(C, A, A, A, B, B, C); //~ ERROR function takes 6 arguments but 7 arguments were supplied [E0061]
     f(C, C, A, A, B, B);  //~ ERROR arguments to this function are incorrect [E0308]
     f(A, A, D, D, B, B);  //~ arguments to this function are incorrect [E0308]
     f(C, C, B, B, A, A);  //~ arguments to this function are incorrect [E0308]
diff --git a/src/test/ui/argument-suggestions/issue-96638.rs b/src/test/ui/argument-suggestions/issue-96638.rs
index 9c6e81ab8cc..5e720f174c2 100644
--- a/src/test/ui/argument-suggestions/issue-96638.rs
+++ b/src/test/ui/argument-suggestions/issue-96638.rs
@@ -5,5 +5,5 @@ fn arg<T>() -> T { todo!() }
 fn main() {
     let x = arg(); // `x` must be inferred
     // The reference on `&x` is important to reproduce the ICE
-    f(&x, ""); //~ ERROR this function takes 3 arguments but 2 arguments were supplied
+    f(&x, ""); //~ ERROR function takes 3 arguments but 2 arguments were supplied
 }
diff --git a/src/test/ui/argument-suggestions/issue-97197.rs b/src/test/ui/argument-suggestions/issue-97197.rs
index 6f9f4293e49..4c22608ae6a 100644
--- a/src/test/ui/argument-suggestions/issue-97197.rs
+++ b/src/test/ui/argument-suggestions/issue-97197.rs
@@ -1,6 +1,6 @@
 fn main() {
     g((), ());
-    //~^ ERROR this function takes 6 arguments but 2 arguments were supplied
+    //~^ ERROR function takes 6 arguments but 2 arguments were supplied
 }
 
 pub fn g(a1: (), a2: bool, a3: bool, a4: bool, a5: bool, a6: ()) -> () {}
diff --git a/src/test/ui/argument-suggestions/issue-97484.rs b/src/test/ui/argument-suggestions/issue-97484.rs
index bb383ab1f8b..9e537b0c35f 100644
--- a/src/test/ui/argument-suggestions/issue-97484.rs
+++ b/src/test/ui/argument-suggestions/issue-97484.rs
@@ -10,5 +10,5 @@ fn foo(a: &A, d: D, e: &E, g: G) {}
 
 fn main() {
     foo(&&A, B, C, D, E, F, G);
-    //~^ ERROR this function takes 4 arguments but 7 arguments were supplied
+    //~^ ERROR function takes 4 arguments but 7 arguments were supplied
 }
diff --git a/src/test/ui/argument-suggestions/issue-98894.rs b/src/test/ui/argument-suggestions/issue-98894.rs
index c2618a96716..e421eba9775 100644
--- a/src/test/ui/argument-suggestions/issue-98894.rs
+++ b/src/test/ui/argument-suggestions/issue-98894.rs
@@ -1,4 +1,4 @@
 fn main() {
     (|_, ()| ())(if true {} else {return;});
-    //~^ ERROR this function takes 2 arguments but 1 argument was supplied
+    //~^ ERROR function takes 2 arguments but 1 argument was supplied
 }
diff --git a/src/test/ui/argument-suggestions/issue-98897.rs b/src/test/ui/argument-suggestions/issue-98897.rs
index c55f495d698..27734f74dee 100644
--- a/src/test/ui/argument-suggestions/issue-98897.rs
+++ b/src/test/ui/argument-suggestions/issue-98897.rs
@@ -1,4 +1,4 @@
 fn main() {
     (|_, ()| ())([return, ()]);
-    //~^ ERROR this function takes 2 arguments but 1 argument was supplied
+    //~^ ERROR function takes 2 arguments but 1 argument was supplied
 }
diff --git a/src/test/ui/argument-suggestions/issue-99482.rs b/src/test/ui/argument-suggestions/issue-99482.rs
index 731b863069b..7bbb39f8d62 100644
--- a/src/test/ui/argument-suggestions/issue-99482.rs
+++ b/src/test/ui/argument-suggestions/issue-99482.rs
@@ -1,5 +1,5 @@
 fn main() {
     let f = |_: (), f: fn()| f;
     let _f = f(main);
-    //~^ ERROR this function takes 2 arguments but 1 argument was supplied
+    //~^ ERROR function takes 2 arguments but 1 argument was supplied
 }
diff --git a/src/test/ui/argument-suggestions/missing_arguments.rs b/src/test/ui/argument-suggestions/missing_arguments.rs
index ae0dabf27b1..c26564641cb 100644
--- a/src/test/ui/argument-suggestions/missing_arguments.rs
+++ b/src/test/ui/argument-suggestions/missing_arguments.rs
@@ -7,34 +7,34 @@ fn four_repeated(_a: i32, _b: f32, _c: f32, _d: &str) {}
 fn complex(_a: i32, _b: f32, _c: i32, _d: f32, _e: &str) {}
 
 fn main() {
-  one_arg(); //~ ERROR this function takes
+  one_arg(); //~ ERROR function takes
   // The headers here show the types expected,
   // with formatting to emphasize which arguments are missing
   /*         i32     f32    */
-  two_same(               ); //~ ERROR this function takes
-  two_same(   1           ); //~ ERROR this function takes
-  two_diff(               ); //~ ERROR this function takes
-  two_diff(   1           ); //~ ERROR this function takes
-  two_diff(          1.0  ); //~ ERROR this function takes
+  two_same(               ); //~ ERROR function takes
+  two_same(   1           ); //~ ERROR function takes
+  two_diff(               ); //~ ERROR function takes
+  two_diff(   1           ); //~ ERROR function takes
+  two_diff(          1.0  ); //~ ERROR function takes
 
   /*           i32     i32     i32    */
-  three_same(                       ); //~ ERROR this function takes
-  three_same(   1                   ); //~ ERROR this function takes
-  three_same(   1,      1           ); //~ ERROR this function takes
+  three_same(                       ); //~ ERROR function takes
+  three_same(   1                   ); //~ ERROR function takes
+  three_same(   1,      1           ); //~ ERROR function takes
 
   /*           i32     f32     &str   */
-  three_diff(          1.0,     ""  ); //~ ERROR this function takes
-  three_diff(   1,              ""  ); //~ ERROR this function takes
-  three_diff(   1,     1.0          ); //~ ERROR this function takes
-  three_diff(                   ""  ); //~ ERROR this function takes
-  three_diff(          1.0          ); //~ ERROR this function takes
-  three_diff(   1                   ); //~ ERROR this function takes
+  three_diff(          1.0,     ""  ); //~ ERROR function takes
+  three_diff(   1,              ""  ); //~ ERROR function takes
+  three_diff(   1,     1.0          ); //~ ERROR function takes
+  three_diff(                   ""  ); //~ ERROR function takes
+  three_diff(          1.0          ); //~ ERROR function takes
+  three_diff(   1                   ); //~ ERROR function takes
 
   /*              i32     f32     f32     &str   */
-  four_repeated(                               ); //~ ERROR this function takes
-  four_repeated(   1,                     ""   ); //~ ERROR this function takes
+  four_repeated(                               ); //~ ERROR function takes
+  four_repeated(   1,                     ""   ); //~ ERROR function takes
 
   /*        i32   f32   i32   f32   &str   */
-  complex(                               ); //~ ERROR this function takes
-  complex(   1,                     ""   ); //~ ERROR this function takes
+  complex(                               ); //~ ERROR function takes
+  complex(   1,                     ""   ); //~ ERROR function takes
 }
diff --git a/src/test/ui/argument-suggestions/mixed_cases.rs b/src/test/ui/argument-suggestions/mixed_cases.rs
index 73678482b30..86e94a4382c 100644
--- a/src/test/ui/argument-suggestions/mixed_cases.rs
+++ b/src/test/ui/argument-suggestions/mixed_cases.rs
@@ -7,11 +7,11 @@ fn three_args(_a: i32, _b: f32, _c: &str) {}
 
 fn main() {
   // Extra + Invalid
-  two_args(1, "", X {}); //~ ERROR this function takes
-  three_args(1, "", X {}, ""); //~ ERROR this function takes
+  two_args(1, "", X {}); //~ ERROR function takes
+  three_args(1, "", X {}, ""); //~ ERROR function takes
 
   // Missing and Invalid
-  three_args(1, X {}); //~ ERROR this function takes
+  three_args(1, X {}); //~ ERROR function takes
 
   // Missing and Extra
   three_args(1, "", X {}); //~ ERROR arguments to this function are incorrect
@@ -20,5 +20,5 @@ fn main() {
   three_args("", X {}, 1); //~ ERROR arguments to this function are incorrect
 
   // Swapped and missing
-  three_args("", 1); //~ ERROR this function takes
+  three_args("", 1); //~ ERROR function takes
 }
diff --git a/src/test/ui/argument-suggestions/too-long.stderr b/src/test/ui/argument-suggestions/too-long.stderr
index bd430194c5e..4928943294b 100644
--- a/src/test/ui/argument-suggestions/too-long.stderr
+++ b/src/test/ui/argument-suggestions/too-long.stderr
@@ -4,7 +4,7 @@ error[E0308]: mismatched types
 LL |     qux.foo(a, b, c, d, e, f, g, h, i, j, k, l);
    |         ---                ^ expected `i32`, found `&i32`
    |         |
-   |         arguments to this function are incorrect
+   |         arguments to this method are incorrect
    |
 note: associated function defined here
   --> $DIR/too-long.rs:4:8
diff --git a/src/test/ui/issues/issue-105330.rs b/src/test/ui/associated-consts/issue-105330.rs
index 86e45f10b0e..86e45f10b0e 100644
--- a/src/test/ui/issues/issue-105330.rs
+++ b/src/test/ui/associated-consts/issue-105330.rs
diff --git a/src/test/ui/issues/issue-105330.stderr b/src/test/ui/associated-consts/issue-105330.stderr
index 30c380152a5..30c380152a5 100644
--- a/src/test/ui/issues/issue-105330.stderr
+++ b/src/test/ui/associated-consts/issue-105330.stderr
diff --git a/src/test/ui/associated-types/associated-type-projection-from-supertrait.stderr b/src/test/ui/associated-types/associated-type-projection-from-supertrait.stderr
index e761c6c62a6..d6b18d4ed32 100644
--- a/src/test/ui/associated-types/associated-type-projection-from-supertrait.stderr
+++ b/src/test/ui/associated-types/associated-type-projection-from-supertrait.stderr
@@ -32,7 +32,7 @@ error[E0308]: mismatched types
 LL | fn f() { ModelT.chip_paint(Blue); }
    |                 ---------- ^^^^ expected struct `Black`, found struct `Blue`
    |                 |
-   |                 arguments to this function are incorrect
+   |                 arguments to this method are incorrect
    |
 note: associated function defined here
   --> $DIR/associated-type-projection-from-supertrait.rs:12:8
@@ -46,7 +46,7 @@ error[E0308]: mismatched types
 LL | fn g() { ModelU.chip_paint(Black); }
    |                 ---------- ^^^^^ expected struct `Blue`, found struct `Black`
    |                 |
-   |                 arguments to this function are incorrect
+   |                 arguments to this method are incorrect
    |
 note: associated function defined here
   --> $DIR/associated-type-projection-from-supertrait.rs:12:8
diff --git a/src/test/ui/associated-types/associated-types-for-unimpl-trait.stderr b/src/test/ui/associated-types/associated-types-for-unimpl-trait.stderr
index 389cc7beddd..6552c8be780 100644
--- a/src/test/ui/associated-types/associated-types-for-unimpl-trait.stderr
+++ b/src/test/ui/associated-types/associated-types-for-unimpl-trait.stderr
@@ -1,8 +1,8 @@
 error[E0277]: the trait bound `Self: Get` is not satisfied
-  --> $DIR/associated-types-for-unimpl-trait.rs:10:5
+  --> $DIR/associated-types-for-unimpl-trait.rs:10:40
    |
 LL |     fn uhoh<U:Get>(&self, foo: U, bar: <Self as Get>::Value) {}
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self`
+   |                                        ^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self`
    |
 help: consider further restricting `Self`
    |
diff --git a/src/test/ui/associated-types/associated-types-no-suitable-bound.stderr b/src/test/ui/associated-types/associated-types-no-suitable-bound.stderr
index 1feaa612ee6..b2ee1b5e6d0 100644
--- a/src/test/ui/associated-types/associated-types-no-suitable-bound.stderr
+++ b/src/test/ui/associated-types/associated-types-no-suitable-bound.stderr
@@ -1,8 +1,8 @@
 error[E0277]: the trait bound `T: Get` is not satisfied
-  --> $DIR/associated-types-no-suitable-bound.rs:11:5
+  --> $DIR/associated-types-no-suitable-bound.rs:11:21
    |
 LL |     fn uhoh<T>(foo: <T as Get>::Value) {}
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `T`
+   |                     ^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `T`
    |
 help: consider restricting type parameter `T`
    |
diff --git a/src/test/ui/associated-types/associated-types-no-suitable-supertrait-2.stderr b/src/test/ui/associated-types/associated-types-no-suitable-supertrait-2.stderr
index cc3ed556115..2e40dbd065d 100644
--- a/src/test/ui/associated-types/associated-types-no-suitable-supertrait-2.stderr
+++ b/src/test/ui/associated-types/associated-types-no-suitable-supertrait-2.stderr
@@ -1,8 +1,8 @@
 error[E0277]: the trait bound `Self: Get` is not satisfied
-  --> $DIR/associated-types-no-suitable-supertrait-2.rs:17:5
+  --> $DIR/associated-types-no-suitable-supertrait-2.rs:17:40
    |
 LL |     fn uhoh<U:Get>(&self, foo: U, bar: <Self as Get>::Value) {}
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self`
+   |                                        ^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self`
    |
 help: consider further restricting `Self`
    |
diff --git a/src/test/ui/associated-types/associated-types-no-suitable-supertrait.stderr b/src/test/ui/associated-types/associated-types-no-suitable-supertrait.stderr
index 18f2830d8b2..bd3ee2abd2c 100644
--- a/src/test/ui/associated-types/associated-types-no-suitable-supertrait.stderr
+++ b/src/test/ui/associated-types/associated-types-no-suitable-supertrait.stderr
@@ -1,14 +1,14 @@
 error[E0277]: the trait bound `(T, U): Get` is not satisfied
-  --> $DIR/associated-types-no-suitable-supertrait.rs:22:5
+  --> $DIR/associated-types-no-suitable-supertrait.rs:22:40
    |
 LL |     fn uhoh<U:Get>(&self, foo: U, bar: <(T, U) as Get>::Value) {}
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `(T, U)`
+   |                                        ^^^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `(T, U)`
 
 error[E0277]: the trait bound `Self: Get` is not satisfied
-  --> $DIR/associated-types-no-suitable-supertrait.rs:17:5
+  --> $DIR/associated-types-no-suitable-supertrait.rs:17:40
    |
 LL |     fn uhoh<U:Get>(&self, foo: U, bar: <Self as Get>::Value) {}
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self`
+   |                                        ^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self`
    |
 help: consider further restricting `Self`
    |
diff --git a/src/test/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.stderr b/src/test/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.stderr
index 66d59bccdbb..2e67c21940f 100644
--- a/src/test/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.stderr
+++ b/src/test/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.stderr
@@ -1,8 +1,8 @@
 error[E0277]: the trait bound `Self: Get` is not satisfied
-  --> $DIR/associated-types-projection-to-unrelated-trait-in-method-without-default.rs:10:5
+  --> $DIR/associated-types-projection-to-unrelated-trait-in-method-without-default.rs:10:40
    |
 LL |     fn okay<U:Get>(&self, foo: U, bar: <Self as Get>::Value);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self`
+   |                                        ^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self`
    |
 help: consider further restricting `Self`
    |
diff --git a/src/test/ui/associated-types/defaults-specialization.stderr b/src/test/ui/associated-types/defaults-specialization.stderr
index 8df326351fa..7e21f7fc306 100644
--- a/src/test/ui/associated-types/defaults-specialization.stderr
+++ b/src/test/ui/associated-types/defaults-specialization.stderr
@@ -22,8 +22,8 @@ note: type in trait
    |
 LL |     fn make() -> Self::Ty {
    |                  ^^^^^^^^
-   = note: expected fn pointer `fn() -> <A<T> as Tr>::Ty`
-              found fn pointer `fn() -> u8`
+   = note: expected signature `fn() -> <A<T> as Tr>::Ty`
+              found signature `fn() -> u8`
 
 error[E0053]: method `make` has an incompatible type for trait
   --> $DIR/defaults-specialization.rs:35:18
@@ -42,8 +42,8 @@ note: type in trait
    |
 LL |     fn make() -> Self::Ty {
    |                  ^^^^^^^^
-   = note: expected fn pointer `fn() -> <B<T> as Tr>::Ty`
-              found fn pointer `fn() -> bool`
+   = note: expected signature `fn() -> <B<T> as Tr>::Ty`
+              found signature `fn() -> bool`
 
 error[E0308]: mismatched types
   --> $DIR/defaults-specialization.rs:10:9
diff --git a/src/test/ui/issues/issue-25700-1.rs b/src/test/ui/associated-types/issue-25700-1.rs
index 5e71a52ba4e..5e71a52ba4e 100644
--- a/src/test/ui/issues/issue-25700-1.rs
+++ b/src/test/ui/associated-types/issue-25700-1.rs
diff --git a/src/test/ui/issues/issue-25700-2.rs b/src/test/ui/associated-types/issue-25700-2.rs
index 89b1db496f9..89b1db496f9 100644
--- a/src/test/ui/issues/issue-25700-2.rs
+++ b/src/test/ui/associated-types/issue-25700-2.rs
diff --git a/src/test/ui/issues/issue-25700.rs b/src/test/ui/associated-types/issue-25700.rs
index e5b9a97523d..e5b9a97523d 100644
--- a/src/test/ui/issues/issue-25700.rs
+++ b/src/test/ui/associated-types/issue-25700.rs
diff --git a/src/test/ui/issues/issue-25700.stderr b/src/test/ui/associated-types/issue-25700.stderr
index fa309a55c3c..fa309a55c3c 100644
--- a/src/test/ui/issues/issue-25700.stderr
+++ b/src/test/ui/associated-types/issue-25700.stderr
diff --git a/src/test/ui/associated-types/issue-59324.rs b/src/test/ui/associated-types/issue-59324.rs
index 9e68e9e7751..551f13ee178 100644
--- a/src/test/ui/associated-types/issue-59324.rs
+++ b/src/test/ui/associated-types/issue-59324.rs
@@ -15,9 +15,9 @@ pub trait ThriftService<Bug: NotFoo>:
 {
     fn get_service(
     //~^ ERROR the trait bound `Bug: Foo` is not satisfied
-    //~| ERROR the trait bound `Bug: Foo` is not satisfied
         &self,
     ) -> Self::AssocType;
+    //~^ ERROR the trait bound `Bug: Foo` is not satisfied
 }
 
 fn with_factory<H>(factory: dyn ThriftService<()>) {}
diff --git a/src/test/ui/associated-types/issue-59324.stderr b/src/test/ui/associated-types/issue-59324.stderr
index 62cf1f37a77..a84b599b52b 100644
--- a/src/test/ui/associated-types/issue-59324.stderr
+++ b/src/test/ui/associated-types/issue-59324.stderr
@@ -20,7 +20,7 @@ LL | |
 LL | |
 LL | |     Service<AssocType = <Bug as Foo>::OnlyFoo>
 ...  |
-LL | |     ) -> Self::AssocType;
+LL | |
 LL | | }
    | |_^ the trait `Foo` is not implemented for `Bug`
    |
@@ -34,7 +34,6 @@ error[E0277]: the trait bound `Bug: Foo` is not satisfied
    |
 LL | /     fn get_service(
 LL | |
-LL | |
 LL | |         &self,
 LL | |     ) -> Self::AssocType;
    | |_________________________^ the trait `Foo` is not implemented for `Bug`
@@ -45,20 +44,16 @@ LL | pub trait ThriftService<Bug: NotFoo + Foo>:
    |                                     +++++
 
 error[E0277]: the trait bound `(): Foo` is not satisfied
-  --> $DIR/issue-59324.rs:23:1
+  --> $DIR/issue-59324.rs:23:29
    |
 LL | fn with_factory<H>(factory: dyn ThriftService<()>) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `()`
+   |                             ^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `()`
 
 error[E0277]: the trait bound `Bug: Foo` is not satisfied
-  --> $DIR/issue-59324.rs:16:5
+  --> $DIR/issue-59324.rs:19:10
    |
-LL | /     fn get_service(
-LL | |
-LL | |
-LL | |         &self,
-LL | |     ) -> Self::AssocType;
-   | |_________________________^ the trait `Foo` is not implemented for `Bug`
+LL |     ) -> Self::AssocType;
+   |          ^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `Bug`
    |
 help: consider further restricting this bound
    |
diff --git a/src/test/ui/async-await/in-trait/async-example-desugared-boxed-in-trait.stderr b/src/test/ui/async-await/in-trait/async-example-desugared-boxed-in-trait.stderr
index 22d2928f2f5..13e7222551a 100644
--- a/src/test/ui/async-await/in-trait/async-example-desugared-boxed-in-trait.stderr
+++ b/src/test/ui/async-await/in-trait/async-example-desugared-boxed-in-trait.stderr
@@ -9,8 +9,8 @@ note: type in trait
    |
 LL |     fn foo(&self) -> Pin<Box<dyn Future<Output = i32> + '_>>;
    |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = note: expected fn pointer `fn(&i32) -> Pin<Box<dyn Future<Output = i32>>>`
-              found fn pointer `fn(&i32) -> impl Future<Output = i32>`
+   = note: expected signature `fn(&i32) -> Pin<Box<dyn Future<Output = i32>>>`
+              found signature `fn(&i32) -> impl Future<Output = i32>`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/borrowck/borrowck-drop-from-guard.rs b/src/test/ui/borrowck/borrowck-drop-from-guard.rs
index 4995029a70f..0f320af2657 100644
--- a/src/test/ui/borrowck/borrowck-drop-from-guard.rs
+++ b/src/test/ui/borrowck/borrowck-drop-from-guard.rs
@@ -1,3 +1,5 @@
+#![feature(if_let_guard)]
+
 fn foo(_:String) {}
 
 fn main()
@@ -8,4 +10,11 @@ fn main()
         Some(_) => {}
         None => { foo(my_str); } //~ ERROR [E0382]
     }
+
+    let my_str = "hello".to_owned();
+    match Some(42) {
+        Some(_) if let Some(()) = { drop(my_str); None } => {}
+        Some(_) => {}
+        None => { foo(my_str); } //~ ERROR [E0382]
+    }
 }
diff --git a/src/test/ui/borrowck/borrowck-drop-from-guard.stderr b/src/test/ui/borrowck/borrowck-drop-from-guard.stderr
index eaf4bb38bc5..9fa28efd855 100644
--- a/src/test/ui/borrowck/borrowck-drop-from-guard.stderr
+++ b/src/test/ui/borrowck/borrowck-drop-from-guard.stderr
@@ -1,5 +1,5 @@
 error[E0382]: use of moved value: `my_str`
-  --> $DIR/borrowck-drop-from-guard.rs:9:23
+  --> $DIR/borrowck-drop-from-guard.rs:11:23
    |
 LL |     let my_str = "hello".to_owned();
    |         ------ move occurs because `my_str` has type `String`, which does not implement the `Copy` trait
@@ -15,6 +15,23 @@ help: consider cloning the value if the performance cost is acceptable
 LL |         Some(_) if { drop(my_str.clone()); false } => {}
    |                                 ++++++++
 
-error: aborting due to previous error
+error[E0382]: use of moved value: `my_str`
+  --> $DIR/borrowck-drop-from-guard.rs:18:23
+   |
+LL |     let my_str = "hello".to_owned();
+   |         ------ move occurs because `my_str` has type `String`, which does not implement the `Copy` trait
+LL |     match Some(42) {
+LL |         Some(_) if let Some(()) = { drop(my_str); None } => {}
+   |                                          ------ value moved here
+LL |         Some(_) => {}
+LL |         None => { foo(my_str); }
+   |                       ^^^^^^ value used here after move
+   |
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL |         Some(_) if let Some(()) = { drop(my_str.clone()); None } => {}
+   |                                                ++++++++
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/borrowck/borrowck-mutate-in-guard.rs b/src/test/ui/borrowck/borrowck-mutate-in-guard.rs
index 9cbceeb945c..d80a9e81576 100644
--- a/src/test/ui/borrowck/borrowck-mutate-in-guard.rs
+++ b/src/test/ui/borrowck/borrowck-mutate-in-guard.rs
@@ -1,9 +1,11 @@
+#![feature(if_let_guard)]
+
 enum Enum<'a> {
     A(&'a isize),
     B(bool),
 }
 
-fn foo() -> isize {
+fn if_guard() -> isize {
     let mut n = 42;
     let mut x = Enum::A(&mut n);
     match x {
@@ -16,6 +18,17 @@ fn foo() -> isize {
     }
 }
 
-fn main() {
-    foo();
+fn if_let_guard() -> isize {
+    let mut n = 42;
+    let mut x = Enum::A(&mut n);
+    match x {
+        Enum::A(_) if let Some(()) = { x = Enum::B(false); None } => 1,
+        //~^ ERROR cannot assign `x` in match guard
+        Enum::A(_) if let Some(()) = { let y = &mut x; *y = Enum::B(false); None } => 1,
+        //~^ ERROR cannot mutably borrow `x` in match guard
+        Enum::A(p) => *p,
+        Enum::B(_) => 2,
+    }
 }
+
+fn main() {}
diff --git a/src/test/ui/borrowck/borrowck-mutate-in-guard.stderr b/src/test/ui/borrowck/borrowck-mutate-in-guard.stderr
index 6d05e97252d..dbb3272fdc3 100644
--- a/src/test/ui/borrowck/borrowck-mutate-in-guard.stderr
+++ b/src/test/ui/borrowck/borrowck-mutate-in-guard.stderr
@@ -1,5 +1,5 @@
 error[E0510]: cannot assign `x` in match guard
-  --> $DIR/borrowck-mutate-in-guard.rs:10:25
+  --> $DIR/borrowck-mutate-in-guard.rs:12:25
    |
 LL |     match x {
    |           - value is immutable in match guard
@@ -7,7 +7,7 @@ LL |         Enum::A(_) if { x = Enum::B(false); false } => 1,
    |                         ^^^^^^^^^^^^^^^^^^ cannot assign
 
 error[E0510]: cannot mutably borrow `x` in match guard
-  --> $DIR/borrowck-mutate-in-guard.rs:12:33
+  --> $DIR/borrowck-mutate-in-guard.rs:14:33
    |
 LL |     match x {
    |           - value is immutable in match guard
@@ -15,6 +15,23 @@ LL |     match x {
 LL |         Enum::A(_) if { let y = &mut x; *y = Enum::B(false); false } => 1,
    |                                 ^^^^^^ cannot mutably borrow
 
-error: aborting due to 2 previous errors
+error[E0510]: cannot assign `x` in match guard
+  --> $DIR/borrowck-mutate-in-guard.rs:25:40
+   |
+LL |     match x {
+   |           - value is immutable in match guard
+LL |         Enum::A(_) if let Some(()) = { x = Enum::B(false); None } => 1,
+   |                                        ^^^^^^^^^^^^^^^^^^ cannot assign
+
+error[E0510]: cannot mutably borrow `x` in match guard
+  --> $DIR/borrowck-mutate-in-guard.rs:27:48
+   |
+LL |     match x {
+   |           - value is immutable in match guard
+...
+LL |         Enum::A(_) if let Some(()) = { let y = &mut x; *y = Enum::B(false); None } => 1,
+   |                                                ^^^^^^ cannot mutably borrow
+
+error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0510`.
diff --git a/src/test/ui/borrowck/issue-31287-drop-in-guard.rs b/src/test/ui/borrowck/issue-31287-drop-in-guard.rs
index 07125b98a1f..5b824adc6e2 100644
--- a/src/test/ui/borrowck/issue-31287-drop-in-guard.rs
+++ b/src/test/ui/borrowck/issue-31287-drop-in-guard.rs
@@ -1,8 +1,15 @@
+#![feature(if_let_guard)]
+
 fn main() {
     let a = Some("...".to_owned());
     let b = match a {
         Some(_) if { drop(a); false } => None,
         x => x, //~ ERROR use of moved value: `a`
     };
-    println!("{:?}", b);
+
+    let a = Some("...".to_owned());
+    let b = match a {
+        Some(_) if let Some(()) = { drop(a); None } => None,
+        x => x, //~ ERROR use of moved value: `a`
+    };
 }
diff --git a/src/test/ui/borrowck/issue-31287-drop-in-guard.stderr b/src/test/ui/borrowck/issue-31287-drop-in-guard.stderr
index ad898fcabd9..18f371c2073 100644
--- a/src/test/ui/borrowck/issue-31287-drop-in-guard.stderr
+++ b/src/test/ui/borrowck/issue-31287-drop-in-guard.stderr
@@ -1,5 +1,5 @@
 error[E0382]: use of moved value: `a`
-  --> $DIR/issue-31287-drop-in-guard.rs:5:9
+  --> $DIR/issue-31287-drop-in-guard.rs:7:9
    |
 LL |     let a = Some("...".to_owned());
    |         - move occurs because `a` has type `Option<String>`, which does not implement the `Copy` trait
@@ -14,6 +14,22 @@ help: consider cloning the value if the performance cost is acceptable
 LL |         Some(_) if { drop(a.clone()); false } => None,
    |                            ++++++++
 
-error: aborting due to previous error
+error[E0382]: use of moved value: `a`
+  --> $DIR/issue-31287-drop-in-guard.rs:13:9
+   |
+LL |     let a = Some("...".to_owned());
+   |         - move occurs because `a` has type `Option<String>`, which does not implement the `Copy` trait
+LL |     let b = match a {
+LL |         Some(_) if let Some(()) = { drop(a); None } => None,
+   |                                          - value moved here
+LL |         x => x,
+   |         ^ value used here after move
+   |
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL |         Some(_) if let Some(()) = { drop(a.clone()); None } => None,
+   |                                           ++++++++
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/borrowck/issue-93078.rs b/src/test/ui/borrowck/issue-93078.rs
new file mode 100644
index 00000000000..2e608c5db3e
--- /dev/null
+++ b/src/test/ui/borrowck/issue-93078.rs
@@ -0,0 +1,15 @@
+trait Modify {
+    fn modify(&mut self) ;
+}
+
+impl<T> Modify for T  {
+    fn modify(&mut self)  {}
+}
+
+trait Foo {
+    fn mute(&mut self) {
+        self.modify(); //~ ERROR cannot borrow `self` as mutable
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/borrowck/issue-93078.stderr b/src/test/ui/borrowck/issue-93078.stderr
new file mode 100644
index 00000000000..771a652a173
--- /dev/null
+++ b/src/test/ui/borrowck/issue-93078.stderr
@@ -0,0 +1,12 @@
+error[E0596]: cannot borrow `self` as mutable, as it is not declared as mutable
+  --> $DIR/issue-93078.rs:11:9
+   |
+LL |         self.modify();
+   |         ^^^^^^^^^^^^^ cannot borrow as mutable
+   |
+   = note: as `Self` may be unsized, this call attempts to take `&mut &mut self`
+   = note: however, `&mut self` expands to `self: &mut Self`, therefore `self` cannot be borrowed mutably
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/src/test/ui/borrowck/regions-bound-missing-bound-in-impl.stderr b/src/test/ui/borrowck/regions-bound-missing-bound-in-impl.stderr
index 1e3b071ef92..930fea9158d 100644
--- a/src/test/ui/borrowck/regions-bound-missing-bound-in-impl.stderr
+++ b/src/test/ui/borrowck/regions-bound-missing-bound-in-impl.stderr
@@ -22,8 +22,8 @@ error[E0308]: method not compatible with trait
 LL |     fn wrong_bound1<'b,'c,'d:'a+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>) {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch
    |
-   = note: expected fn pointer `fn(&'a isize, Inv<'c>, Inv<'c>, Inv<'_>)`
-              found fn pointer `fn(&'a isize, Inv<'_>, Inv<'c>, Inv<'_>)`
+   = note: expected signature `fn(&'a isize, Inv<'c>, Inv<'c>, Inv<'_>)`
+              found signature `fn(&'a isize, Inv<'_>, Inv<'c>, Inv<'_>)`
 note: the lifetime `'c` as defined here...
   --> $DIR/regions-bound-missing-bound-in-impl.rs:27:24
    |
@@ -41,8 +41,8 @@ error[E0308]: method not compatible with trait
 LL |     fn wrong_bound1<'b,'c,'d:'a+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>) {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch
    |
-   = note: expected fn pointer `fn(&'a isize, Inv<'c>, Inv<'c>, Inv<'_>)`
-              found fn pointer `fn(&'a isize, Inv<'_>, Inv<'c>, Inv<'_>)`
+   = note: expected signature `fn(&'a isize, Inv<'c>, Inv<'c>, Inv<'_>)`
+              found signature `fn(&'a isize, Inv<'_>, Inv<'c>, Inv<'_>)`
 note: the lifetime `'c` as defined here...
   --> $DIR/regions-bound-missing-bound-in-impl.rs:27:24
    |
diff --git a/src/test/ui/c-variadic/variadic-ffi-1.rs b/src/test/ui/c-variadic/variadic-ffi-1.rs
index 24407a71ce6..acd8a25dc53 100644
--- a/src/test/ui/c-variadic/variadic-ffi-1.rs
+++ b/src/test/ui/c-variadic/variadic-ffi-1.rs
@@ -19,8 +19,8 @@ extern "C" fn bar(f: isize, x: u8) {}
 
 fn main() {
     unsafe {
-        foo(); //~ ERROR this function takes at least 2 arguments but 0 arguments were supplied
-        foo(1); //~ ERROR this function takes at least 2 arguments but 1 argument was supplied
+        foo(); //~ ERROR function takes at least 2 arguments but 0 arguments were supplied
+        foo(1); //~ ERROR function takes at least 2 arguments but 1 argument was supplied
 
         let x: unsafe extern "C" fn(f: isize, x: u8) = foo; //~ ERROR mismatched types
         let y: extern "C" fn(f: isize, x: u8, ...) = bar; //~ ERROR mismatched types
diff --git a/src/test/ui/chalkify/arithmetic.rs b/src/test/ui/chalkify/arithmetic.rs
index a20acce4c76..6c78a71b0fc 100644
--- a/src/test/ui/chalkify/arithmetic.rs
+++ b/src/test/ui/chalkify/arithmetic.rs
@@ -1,5 +1,5 @@
 // check-pass
-// compile-flags: -Z chalk
+// compile-flags: -Z trait-solver=chalk
 
 fn main() {
     1 + 2;
diff --git a/src/test/ui/chalkify/assert.rs b/src/test/ui/chalkify/assert.rs
index f4ebf91924c..834c8935e76 100644
--- a/src/test/ui/chalkify/assert.rs
+++ b/src/test/ui/chalkify/assert.rs
@@ -1,5 +1,5 @@
 // run-pass
-// compile-flags: -Z chalk
+// compile-flags: -Z trait-solver=chalk
 
 fn main() {
     assert_eq!(1, 1);
diff --git a/src/test/ui/chalkify/basic.rs b/src/test/ui/chalkify/basic.rs
index dbd60fc8bb1..4a7cd939669 100644
--- a/src/test/ui/chalkify/basic.rs
+++ b/src/test/ui/chalkify/basic.rs
@@ -1,5 +1,5 @@
 // check-pass
-// compile-flags: -Z chalk
+// compile-flags: -Z trait-solver=chalk
 
 trait Foo {}
 
diff --git a/src/test/ui/chalkify/bugs/async.rs b/src/test/ui/chalkify/bugs/async.rs
index ae5224dbd6f..ed0f5dc9bd3 100644
--- a/src/test/ui/chalkify/bugs/async.rs
+++ b/src/test/ui/chalkify/bugs/async.rs
@@ -1,6 +1,6 @@
 // check-fail
 // known-bug: unknown
-// compile-flags: -Z chalk --edition=2021
+// compile-flags: -Z trait-solver=chalk --edition=2021
 
 fn main() -> () {}
 
diff --git a/src/test/ui/chalkify/builtin-copy-clone.rs b/src/test/ui/chalkify/builtin-copy-clone.rs
index 7712e946542..a478c006ef1 100644
--- a/src/test/ui/chalkify/builtin-copy-clone.rs
+++ b/src/test/ui/chalkify/builtin-copy-clone.rs
@@ -1,5 +1,5 @@
 // run-pass
-// compile-flags: -Z chalk
+// compile-flags: -Z trait-solver=chalk
 
 // Test that `Clone` is correctly implemented for builtin types.
 
diff --git a/src/test/ui/chalkify/chalk_initial_program.rs b/src/test/ui/chalkify/chalk_initial_program.rs
index df25bad622b..21de72b6fcc 100644
--- a/src/test/ui/chalkify/chalk_initial_program.rs
+++ b/src/test/ui/chalkify/chalk_initial_program.rs
@@ -1,4 +1,4 @@
-// compile-flags: -Z chalk
+// compile-flags: -Z trait-solver=chalk
 
 trait Foo { }
 
diff --git a/src/test/ui/chalkify/closure.rs b/src/test/ui/chalkify/closure.rs
index 568e2e30c41..a908a1e97ec 100644
--- a/src/test/ui/chalkify/closure.rs
+++ b/src/test/ui/chalkify/closure.rs
@@ -1,4 +1,4 @@
-// compile-flags: -Z chalk
+// compile-flags: -Z trait-solver=chalk
 
 fn main() -> () {
     let t = || {};
diff --git a/src/test/ui/chalkify/generic_impls.rs b/src/test/ui/chalkify/generic_impls.rs
index d70c6f8055d..7d33e12d8be 100644
--- a/src/test/ui/chalkify/generic_impls.rs
+++ b/src/test/ui/chalkify/generic_impls.rs
@@ -1,4 +1,4 @@
-// compile-flags: -Z chalk
+// compile-flags: -Z trait-solver=chalk
 
 trait Foo { }
 
diff --git a/src/test/ui/chalkify/impl_wf.rs b/src/test/ui/chalkify/impl_wf.rs
index 66f57c2d110..c8dfd4c3a5b 100644
--- a/src/test/ui/chalkify/impl_wf.rs
+++ b/src/test/ui/chalkify/impl_wf.rs
@@ -1,4 +1,4 @@
-// compile-flags: -Z chalk
+// compile-flags: -Z trait-solver=chalk
 
 trait Foo: Sized { }
 
diff --git a/src/test/ui/chalkify/impl_wf_2.rs b/src/test/ui/chalkify/impl_wf_2.rs
index 758a7185e39..325044ad634 100644
--- a/src/test/ui/chalkify/impl_wf_2.rs
+++ b/src/test/ui/chalkify/impl_wf_2.rs
@@ -1,6 +1,6 @@
 // Split out of impl_wf.rs to work around rust aborting compilation early
 
-// compile-flags: -Z chalk
+// compile-flags: -Z trait-solver=chalk
 
 trait Foo: Sized { }
 
diff --git a/src/test/ui/chalkify/inherent_impl.rs b/src/test/ui/chalkify/inherent_impl.rs
index a2730219fbe..f0f24d485cd 100644
--- a/src/test/ui/chalkify/inherent_impl.rs
+++ b/src/test/ui/chalkify/inherent_impl.rs
@@ -1,5 +1,5 @@
 // run-pass
-// compile-flags: -Z chalk
+// compile-flags: -Z trait-solver=chalk
 
 trait Foo { }
 
diff --git a/src/test/ui/chalkify/inherent_impl_min.rs b/src/test/ui/chalkify/inherent_impl_min.rs
index 774c46e401c..3eda7102dec 100644
--- a/src/test/ui/chalkify/inherent_impl_min.rs
+++ b/src/test/ui/chalkify/inherent_impl_min.rs
@@ -1,5 +1,5 @@
 // run-pass
-// compile-flags: -Z chalk
+// compile-flags: -Z trait-solver=chalk
 
 trait Foo { }
 
diff --git a/src/test/ui/chalkify/lower_env1.rs b/src/test/ui/chalkify/lower_env1.rs
index e3c75695921..c8762001e6a 100644
--- a/src/test/ui/chalkify/lower_env1.rs
+++ b/src/test/ui/chalkify/lower_env1.rs
@@ -1,5 +1,5 @@
 // check-pass
-// compile-flags: -Z chalk
+// compile-flags: -Z trait-solver=chalk
 
 #![allow(dead_code)]
 
diff --git a/src/test/ui/chalkify/lower_env2.rs b/src/test/ui/chalkify/lower_env2.rs
index b5432ce0e30..7d4f81f12ea 100644
--- a/src/test/ui/chalkify/lower_env2.rs
+++ b/src/test/ui/chalkify/lower_env2.rs
@@ -1,5 +1,5 @@
 // check-pass
-// compile-flags: -Z chalk
+// compile-flags: -Z trait-solver=chalk
 
 #![allow(dead_code)]
 
diff --git a/src/test/ui/chalkify/lower_env3.rs b/src/test/ui/chalkify/lower_env3.rs
index 673f08d78ab..5b70c4abbb5 100644
--- a/src/test/ui/chalkify/lower_env3.rs
+++ b/src/test/ui/chalkify/lower_env3.rs
@@ -1,5 +1,5 @@
 // check-pass
-// compile-flags: -Z chalk
+// compile-flags: -Z trait-solver=chalk
 
 #![allow(dead_code)]
 
diff --git a/src/test/ui/chalkify/lower_impl.rs b/src/test/ui/chalkify/lower_impl.rs
index f586cf08391..6f79b3ba386 100644
--- a/src/test/ui/chalkify/lower_impl.rs
+++ b/src/test/ui/chalkify/lower_impl.rs
@@ -1,5 +1,5 @@
 // check-pass
-// compile-flags: -Z chalk
+// compile-flags: -Z trait-solver=chalk
 
 trait Foo { }
 
diff --git a/src/test/ui/chalkify/lower_struct.rs b/src/test/ui/chalkify/lower_struct.rs
index 94a0716d383..6be0d4dd5bd 100644
--- a/src/test/ui/chalkify/lower_struct.rs
+++ b/src/test/ui/chalkify/lower_struct.rs
@@ -1,5 +1,5 @@
 // check-pass
-// compile-flags: -Z chalk
+// compile-flags: -Z trait-solver=chalk
 
 struct Foo<'a, T> where Box<T>: Clone {
     _x: std::marker::PhantomData<&'a T>,
diff --git a/src/test/ui/chalkify/lower_trait.rs b/src/test/ui/chalkify/lower_trait.rs
index d8f6180ceb3..8f5b358220b 100644
--- a/src/test/ui/chalkify/lower_trait.rs
+++ b/src/test/ui/chalkify/lower_trait.rs
@@ -1,5 +1,5 @@
 // check-pass
-// compile-flags: -Z chalk
+// compile-flags: -Z trait-solver=chalk
 
 trait Bar { }
 
diff --git a/src/test/ui/chalkify/lower_trait_higher_rank.rs b/src/test/ui/chalkify/lower_trait_higher_rank.rs
index a48979491a1..f04a1deea87 100644
--- a/src/test/ui/chalkify/lower_trait_higher_rank.rs
+++ b/src/test/ui/chalkify/lower_trait_higher_rank.rs
@@ -1,5 +1,5 @@
 // check-pass
-// compile-flags: -Z chalk
+// compile-flags: -Z trait-solver=chalk
 
 trait Foo<F: ?Sized> where for<'a> F: Fn(&'a (u8, u16)) -> &'a u8
 {
diff --git a/src/test/ui/chalkify/lower_trait_where_clause.rs b/src/test/ui/chalkify/lower_trait_where_clause.rs
index 19cff8db7cb..a21d2f31963 100644
--- a/src/test/ui/chalkify/lower_trait_where_clause.rs
+++ b/src/test/ui/chalkify/lower_trait_where_clause.rs
@@ -1,5 +1,5 @@
 // check-pass
-// compile-flags: -Z chalk
+// compile-flags: -Z trait-solver=chalk
 
 use std::borrow::Borrow;
 
diff --git a/src/test/ui/chalkify/println.rs b/src/test/ui/chalkify/println.rs
index 0f0df29019e..edddc382152 100644
--- a/src/test/ui/chalkify/println.rs
+++ b/src/test/ui/chalkify/println.rs
@@ -1,5 +1,5 @@
 // check-pass
-// compile-flags: -Z chalk
+// compile-flags: -Z trait-solver=chalk
 
 fn main() {
     println!("hello");
diff --git a/src/test/ui/chalkify/projection.rs b/src/test/ui/chalkify/projection.rs
index d6a8dd7a4a2..19bb2ae1497 100644
--- a/src/test/ui/chalkify/projection.rs
+++ b/src/test/ui/chalkify/projection.rs
@@ -1,5 +1,5 @@
 // run-pass
-// compile-flags: -Z chalk
+// compile-flags: -Z trait-solver=chalk
 
 trait Foo { }
 
diff --git a/src/test/ui/chalkify/recursive_where_clause_on_type.rs b/src/test/ui/chalkify/recursive_where_clause_on_type.rs
index 87324a5f79b..c2c8aa6aabe 100644
--- a/src/test/ui/chalkify/recursive_where_clause_on_type.rs
+++ b/src/test/ui/chalkify/recursive_where_clause_on_type.rs
@@ -1,6 +1,6 @@
 // FIXME(chalk): should fail, see comments
 // check-fail
-// compile-flags: -Z chalk
+// compile-flags: -Z trait-solver=chalk
 
 #![feature(trivial_bounds)]
 
@@ -25,6 +25,6 @@ fn foo<T: Foo>() {
 fn main() {
     // For some reason, the error is duplicated...
 
-    foo::<S>() //~ ERROR the type `S` is not well-formed (chalk)
-    //~^ ERROR the type `S` is not well-formed (chalk)
+    foo::<S>() //~ ERROR the type `S` is not well-formed
+    //~^ ERROR the type `S` is not well-formed
 }
diff --git a/src/test/ui/chalkify/recursive_where_clause_on_type.stderr b/src/test/ui/chalkify/recursive_where_clause_on_type.stderr
index fddd5895927..cead5adeaaa 100644
--- a/src/test/ui/chalkify/recursive_where_clause_on_type.stderr
+++ b/src/test/ui/chalkify/recursive_where_clause_on_type.stderr
@@ -1,10 +1,10 @@
-error: the type `S` is not well-formed (chalk)
+error: the type `S` is not well-formed
   --> $DIR/recursive_where_clause_on_type.rs:28:11
    |
 LL |     foo::<S>()
    |           ^
 
-error: the type `S` is not well-formed (chalk)
+error: the type `S` is not well-formed
   --> $DIR/recursive_where_clause_on_type.rs:28:5
    |
 LL |     foo::<S>()
diff --git a/src/test/ui/chalkify/super_trait.rs b/src/test/ui/chalkify/super_trait.rs
index eeff9fd9b80..540ae51e57f 100644
--- a/src/test/ui/chalkify/super_trait.rs
+++ b/src/test/ui/chalkify/super_trait.rs
@@ -1,5 +1,5 @@
 // run-pass
-// compile-flags: -Z chalk
+// compile-flags: -Z trait-solver=chalk
 
 trait Foo { }
 trait Bar: Foo { }
diff --git a/src/test/ui/chalkify/trait-objects.rs b/src/test/ui/chalkify/trait-objects.rs
index d56abc42bf5..144d9788b82 100644
--- a/src/test/ui/chalkify/trait-objects.rs
+++ b/src/test/ui/chalkify/trait-objects.rs
@@ -1,5 +1,5 @@
 // check-pass
-// compile-flags: -Z chalk
+// compile-flags: -Z trait-solver=chalk
 
 use std::fmt::Display;
 
diff --git a/src/test/ui/chalkify/trait_implied_bound.rs b/src/test/ui/chalkify/trait_implied_bound.rs
index 8a2e1cf5990..f97dbf6b7e7 100644
--- a/src/test/ui/chalkify/trait_implied_bound.rs
+++ b/src/test/ui/chalkify/trait_implied_bound.rs
@@ -1,5 +1,5 @@
 // run-pass
-// compile-flags: -Z chalk
+// compile-flags: -Z trait-solver=chalk
 
 trait Foo { }
 trait Bar<U> where U: Foo { }
diff --git a/src/test/ui/chalkify/type_implied_bound.rs b/src/test/ui/chalkify/type_implied_bound.rs
index 8673f5319bd..70f1b4265e4 100644
--- a/src/test/ui/chalkify/type_implied_bound.rs
+++ b/src/test/ui/chalkify/type_implied_bound.rs
@@ -1,5 +1,5 @@
 // run-pass
-// compile-flags: -Z chalk
+// compile-flags: -Z trait-solver=chalk
 
 trait Eq { }
 trait Hash: Eq { }
diff --git a/src/test/ui/chalkify/type_inference.rs b/src/test/ui/chalkify/type_inference.rs
index 369777a7904..d7167d0dc57 100644
--- a/src/test/ui/chalkify/type_inference.rs
+++ b/src/test/ui/chalkify/type_inference.rs
@@ -1,4 +1,4 @@
-// compile-flags: -Z chalk
+// compile-flags: -Z trait-solver=chalk
 
 trait Foo { }
 impl Foo for i32 { }
diff --git a/src/test/ui/chalkify/type_wf.rs b/src/test/ui/chalkify/type_wf.rs
index eeeefcfb7dd..37d2f5ca832 100644
--- a/src/test/ui/chalkify/type_wf.rs
+++ b/src/test/ui/chalkify/type_wf.rs
@@ -1,5 +1,5 @@
 // check-fail
-// compile-flags: -Z chalk
+// compile-flags: -Z trait-solver=chalk
 
 trait Foo { }
 
diff --git a/src/test/ui/check-cfg/well-known-values.stderr b/src/test/ui/check-cfg/well-known-values.stderr
index 29ececea5d3..69d799783a9 100644
--- a/src/test/ui/check-cfg/well-known-values.stderr
+++ b/src/test/ui/check-cfg/well-known-values.stderr
@@ -6,7 +6,7 @@ LL | #[cfg(target_os = "linuz")]
    |                   |
    |                   help: did you mean: `"linux"`
    |
-   = note: expected values for `target_os` are: aix, android, cuda, dragonfly, emscripten, espidf, freebsd, fuchsia, haiku, hermit, horizon, illumos, ios, l4re, linux, macos, netbsd, none, nto, openbsd, psp, redox, solaris, solid_asp3, tvos, uefi, unknown, vxworks, wasi, watchos, windows, xous
+   = note: expected values for `target_os` are: aix, android, cuda, dragonfly, emscripten, espidf, freebsd, fuchsia, haiku, hermit, horizon, illumos, ios, l4re, linux, macos, netbsd, none, nto, openbsd, psp, redox, solaris, solid_asp3, tvos, uefi, unknown, vita, vxworks, wasi, watchos, windows, xous
    = note: `#[warn(unexpected_cfgs)]` on by default
 
 warning: unexpected `cfg` condition value
diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-3.rs b/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-3.rs
index bdd6cb79b60..00f50c33e1c 100644
--- a/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-3.rs
+++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-3.rs
@@ -8,10 +8,9 @@ struct Point {
 fn main() {
     let mut c = {
         let mut p = Point {x: "1".to_string(), y: "2".to_string() };
-        || {
+        || { //~ ERROR closure may outlive the current block, but it borrows `p`
            let x = &mut p.x;
            println!("{:?}", p);
-            //~^ ERROR `p` does not live long enough
         }
     };
     c();
diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-3.stderr b/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-3.stderr
index dab1809a381..ee923804786 100644
--- a/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-3.stderr
+++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-3.stderr
@@ -1,18 +1,22 @@
-error[E0597]: `p` does not live long enough
-  --> $DIR/borrowck-3.rs:13:29
+error[E0373]: closure may outlive the current block, but it borrows `p`, which is owned by the current block
+  --> $DIR/borrowck-3.rs:11:9
    |
-LL |     let mut c = {
-   |         ----- borrow later stored here
-LL |         let mut p = Point {x: "1".to_string(), y: "2".to_string() };
 LL |         || {
-   |         -- value captured here
+   |         ^^ may outlive borrowed value `p`
 LL |            let x = &mut p.x;
 LL |            println!("{:?}", p);
-   |                             ^ borrowed value does not live long enough
-...
-LL |     };
-   |     - `p` dropped here while still borrowed
+   |                             - `p` is borrowed here
+   |
+note: block requires argument type to outlive `'1`
+  --> $DIR/borrowck-3.rs:9:9
+   |
+LL |     let mut c = {
+   |         ^^^^^
+help: to force the closure to take ownership of `p` (and any other referenced variables), use the `move` keyword
+   |
+LL |         move || {
+   |         ++++
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0597`.
+For more information about this error, try `rustc --explain E0373`.
diff --git a/src/test/ui/closures/supertrait-hint-cycle-2.rs b/src/test/ui/closures/supertrait-hint-cycle-2.rs
new file mode 100644
index 00000000000..fda81b18d1e
--- /dev/null
+++ b/src/test/ui/closures/supertrait-hint-cycle-2.rs
@@ -0,0 +1,18 @@
+// check-pass
+
+trait Foo<'a> {
+    type Input;
+}
+
+impl<F: Fn(u32)> Foo<'_> for F {
+    type Input = u32;
+}
+
+trait SuperFn: for<'a> Foo<'a> + for<'a> Fn(<Self as Foo<'a>>::Input) {}
+impl<T> SuperFn for T where T: for<'a> Fn(<Self as Foo<'a>>::Input) + for<'a> Foo<'a> {}
+
+fn needs_super(_: impl SuperFn) {}
+
+fn main() {
+    needs_super(|_: u32| {});
+}
diff --git a/src/test/ui/closures/supertrait-hint-cycle-3.rs b/src/test/ui/closures/supertrait-hint-cycle-3.rs
new file mode 100644
index 00000000000..8149474df19
--- /dev/null
+++ b/src/test/ui/closures/supertrait-hint-cycle-3.rs
@@ -0,0 +1,16 @@
+// check-pass
+
+
+trait Foo<'a> {
+    type Input;
+}
+
+impl<F: Fn(u32)> Foo<'_> for F {
+    type Input = u32;
+}
+
+fn needs_super<F: for<'a> Fn(<F as Foo<'a>>::Input) + for<'a> Foo<'a>>(_: F) {}
+
+fn main() {
+    needs_super(|_: u32| {});
+}
diff --git a/src/test/ui/closures/supertrait-hint-cycle.rs b/src/test/ui/closures/supertrait-hint-cycle.rs
new file mode 100644
index 00000000000..dbb06b2ef7a
--- /dev/null
+++ b/src/test/ui/closures/supertrait-hint-cycle.rs
@@ -0,0 +1,65 @@
+// edition:2021
+// check-pass
+
+#![feature(type_alias_impl_trait)]
+#![feature(closure_lifetime_binder)]
+
+use std::future::Future;
+
+trait AsyncFn<I, R>: FnMut(I) -> Self::Fut {
+    type Fut: Future<Output = R>;
+}
+
+impl<F, I, R, Fut> AsyncFn<I, R> for F
+where
+    Fut: Future<Output = R>,
+    F: FnMut(I) -> Fut,
+{
+    type Fut = Fut;
+}
+
+async fn call<C, R, F>(mut ctx: C, mut f: F) -> Result<R, ()>
+where
+    F: for<'a> AsyncFn<&'a mut C, Result<R, ()>>,
+{
+    loop {
+        match f(&mut ctx).await {
+            Ok(val) => return Ok(val),
+            Err(_) => continue,
+        }
+    }
+}
+
+trait Cap<'a> {}
+impl<T> Cap<'_> for T {}
+
+fn works(ctx: &mut usize) {
+    let mut inner = 0;
+
+    type Ret<'a, 'b: 'a> = impl Future<Output = Result<usize, ()>> + 'a + Cap<'b>;
+
+    let callback = for<'a, 'b> |c: &'a mut &'b mut usize| -> Ret<'a, 'b> {
+        inner += 1;
+        async move {
+            let _c = c;
+            Ok(1usize)
+        }
+    };
+    call(ctx, callback);
+}
+
+fn doesnt_work_but_should(ctx: &mut usize) {
+    let mut inner = 0;
+
+    type Ret<'a, 'b: 'a> = impl Future<Output = Result<usize, ()>> + 'a + Cap<'b>;
+
+    call(ctx, for<'a, 'b> |c: &'a mut &'b mut usize| -> Ret<'a, 'b> {
+        inner += 1;
+        async move {
+            let _c = c;
+            Ok(1usize)
+        }
+    });
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-82859-slice-miscompile.rs b/src/test/ui/codegen/issue-82859-slice-miscompile.rs
index b64eb499071..b64eb499071 100644
--- a/src/test/ui/issues/issue-82859-slice-miscompile.rs
+++ b/src/test/ui/codegen/issue-82859-slice-miscompile.rs
diff --git a/src/test/ui/coherence/coherence-default-trait-impl.stderr b/src/test/ui/coherence/coherence-default-trait-impl.stderr
index 63201878272..7be5b92a7de 100644
--- a/src/test/ui/coherence/coherence-default-trait-impl.stderr
+++ b/src/test/ui/coherence/coherence-default-trait-impl.stderr
@@ -2,7 +2,7 @@ error[E0199]: implementing the trait `MySafeTrait` is not unsafe
   --> $DIR/coherence-default-trait-impl.rs:8:1
    |
 LL | unsafe impl MySafeTrait for Foo {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 help: remove `unsafe` from this trait implementation
    |
@@ -14,7 +14,7 @@ error[E0200]: the trait `MyUnsafeTrait` requires an `unsafe impl` declaration
   --> $DIR/coherence-default-trait-impl.rs:13:1
    |
 LL | impl MyUnsafeTrait for Foo {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: the trait `MyUnsafeTrait` enforces invariants that the compiler can't check. Review the trait documentation and make sure this implementation upholds those invariants before adding the `unsafe` keyword
 help: add `unsafe` to this trait implementation
diff --git a/src/test/ui/issues/issue-10626.rs b/src/test/ui/command/issue-10626.rs
index 696a2dd1657..696a2dd1657 100644
--- a/src/test/ui/issues/issue-10626.rs
+++ b/src/test/ui/command/issue-10626.rs
diff --git a/src/test/ui/compare-method/bad-self-type.stderr b/src/test/ui/compare-method/bad-self-type.stderr
index 90e907157a5..cad942e646e 100644
--- a/src/test/ui/compare-method/bad-self-type.stderr
+++ b/src/test/ui/compare-method/bad-self-type.stderr
@@ -7,8 +7,8 @@ LL |     fn poll(self, _: &mut Context<'_>) -> Poll<()> {
    |             expected struct `Pin`, found struct `MyFuture`
    |             help: change the self-receiver type to match the trait: `self: Pin<&mut MyFuture>`
    |
-   = note: expected fn pointer `fn(Pin<&mut MyFuture>, &mut Context<'_>) -> Poll<_>`
-              found fn pointer `fn(MyFuture, &mut Context<'_>) -> Poll<_>`
+   = note: expected signature `fn(Pin<&mut MyFuture>, &mut Context<'_>) -> Poll<_>`
+              found signature `fn(MyFuture, &mut Context<'_>) -> Poll<_>`
 
 error[E0053]: method `foo` has an incompatible type for trait
   --> $DIR/bad-self-type.rs:22:18
@@ -24,8 +24,8 @@ note: type in trait
    |
 LL |     fn foo(self);
    |            ^^^^
-   = note: expected fn pointer `fn(MyFuture)`
-              found fn pointer `fn(Box<MyFuture>)`
+   = note: expected signature `fn(MyFuture)`
+              found signature `fn(Box<MyFuture>)`
 
 error[E0053]: method `bar` has an incompatible type for trait
   --> $DIR/bad-self-type.rs:24:18
@@ -38,8 +38,8 @@ note: type in trait
    |
 LL |     fn bar(self) -> Option<()>;
    |                     ^^^^^^^^^^
-   = note: expected fn pointer `fn(MyFuture) -> Option<()>`
-              found fn pointer `fn(MyFuture)`
+   = note: expected signature `fn(MyFuture) -> Option<()>`
+              found signature `fn(MyFuture)`
 help: change the output type to match the trait
    |
 LL |     fn bar(self) -> Option<()> {}
diff --git a/src/test/ui/compare-method/issue-90444.stderr b/src/test/ui/compare-method/issue-90444.stderr
index ee63f34b799..52e23d03b14 100644
--- a/src/test/ui/compare-method/issue-90444.stderr
+++ b/src/test/ui/compare-method/issue-90444.stderr
@@ -7,8 +7,8 @@ LL |     fn from(_: fn((), (), &mut ())) -> Self {
    |                types differ in mutability
    |                help: change the parameter type to match the trait: `for<'a> fn((), (), &'a ())`
    |
-   = note: expected fn pointer `fn(for<'a> fn((), (), &'a ())) -> A`
-              found fn pointer `fn(for<'a> fn((), (), &'a mut ())) -> A`
+   = note: expected signature `fn(for<'a> fn((), (), &'a ())) -> A`
+              found signature `fn(for<'a> fn((), (), &'a mut ())) -> A`
 
 error[E0053]: method `from` has an incompatible type for trait
   --> $DIR/issue-90444.rs:11:16
@@ -19,8 +19,8 @@ LL |     fn from(_: fn((), (), u64)) -> Self {
    |                expected `u32`, found `u64`
    |                help: change the parameter type to match the trait: `fn((), (), u32)`
    |
-   = note: expected fn pointer `fn(fn((), (), u32)) -> B`
-              found fn pointer `fn(fn((), (), u64)) -> B`
+   = note: expected signature `fn(fn((), (), u32)) -> B`
+              found signature `fn(fn((), (), u64)) -> B`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/compare-method/reordered-type-param.stderr b/src/test/ui/compare-method/reordered-type-param.stderr
index 49b5b1b92cd..1552d542d15 100644
--- a/src/test/ui/compare-method/reordered-type-param.stderr
+++ b/src/test/ui/compare-method/reordered-type-param.stderr
@@ -14,8 +14,8 @@ note: type in trait
    |
 LL |   fn b<C:Clone,D>(&self, x: C) -> C;
    |                             ^
-   = note: expected fn pointer `fn(&E, F) -> F`
-              found fn pointer `fn(&E, G) -> G`
+   = note: expected signature `fn(&E, F) -> F`
+              found signature `fn(&E, G) -> G`
    = note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound
    = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters
 
diff --git a/src/test/ui/const-generics/assoc_const_eq_diagnostic.rs b/src/test/ui/const-generics/assoc_const_eq_diagnostic.rs
new file mode 100644
index 00000000000..4d0aaf88e40
--- /dev/null
+++ b/src/test/ui/const-generics/assoc_const_eq_diagnostic.rs
@@ -0,0 +1,18 @@
+#![feature(associated_const_equality)]
+
+pub enum Mode {
+    Cool,
+}
+
+pub trait Parse {
+    const MODE: Mode;
+}
+
+pub trait CoolStuff: Parse<MODE = Mode::Cool> {}
+//~^ ERROR expected associated constant bound
+//~| ERROR expected type
+
+fn no_help() -> Mode::Cool {}
+//~^ ERROR expected type, found variant
+
+fn main() {}
diff --git a/src/test/ui/const-generics/assoc_const_eq_diagnostic.stderr b/src/test/ui/const-generics/assoc_const_eq_diagnostic.stderr
new file mode 100644
index 00000000000..ba727ee0ea3
--- /dev/null
+++ b/src/test/ui/const-generics/assoc_const_eq_diagnostic.stderr
@@ -0,0 +1,33 @@
+error[E0573]: expected type, found variant `Mode::Cool`
+  --> $DIR/assoc_const_eq_diagnostic.rs:11:35
+   |
+LL | pub trait CoolStuff: Parse<MODE = Mode::Cool> {}
+   |                                   ^^^^^^^^^^
+   |                                   |
+   |                                   not a type
+   |                                   help: try using the variant's enum: `Mode`
+
+error[E0573]: expected type, found variant `Mode::Cool`
+  --> $DIR/assoc_const_eq_diagnostic.rs:15:17
+   |
+LL | fn no_help() -> Mode::Cool {}
+   |                 ^^^^^^^^^^
+   |                 |
+   |                 not a type
+   |                 help: try using the variant's enum: `Mode`
+
+error: expected associated constant bound, found type
+  --> $DIR/assoc_const_eq_diagnostic.rs:11:28
+   |
+LL | pub trait CoolStuff: Parse<MODE = Mode::Cool> {}
+   |                            ^^^^^^^^^^^^^^^^^ help: if equating a const, try wrapping with braces: `MODE = { const }`
+   |
+note: associated constant defined here
+  --> $DIR/assoc_const_eq_diagnostic.rs:8:5
+   |
+LL |     const MODE: Mode;
+   |     ^^^^^^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0573`.
diff --git a/src/test/ui/const-generics/generic_const_exprs/issue-76595.rs b/src/test/ui/const-generics/generic_const_exprs/issue-76595.rs
index faa8b3d10de..10247ce6bca 100644
--- a/src/test/ui/const-generics/generic_const_exprs/issue-76595.rs
+++ b/src/test/ui/const-generics/generic_const_exprs/issue-76595.rs
@@ -13,5 +13,5 @@ fn test<T, const P: usize>() where Bool<{core::mem::size_of::<T>() > 4}>: True {
 
 fn main() {
     test::<2>();
-    //~^ ERROR this function takes 2 generic arguments
+    //~^ ERROR function takes 2 generic arguments
 }
diff --git a/src/test/ui/const-generics/incorrect-number-of-const-args.rs b/src/test/ui/const-generics/incorrect-number-of-const-args.rs
index de2d126afd7..8660cb2fb54 100644
--- a/src/test/ui/const-generics/incorrect-number-of-const-args.rs
+++ b/src/test/ui/const-generics/incorrect-number-of-const-args.rs
@@ -4,8 +4,8 @@ fn foo<const X: usize, const Y: usize>() -> usize {
 
 fn main() {
     foo::<0>();
-    //~^ ERROR this function takes 2
+    //~^ ERROR function takes 2
 
     foo::<0, 0, 0>();
-    //~^ ERROR this function takes 2
+    //~^ ERROR function takes 2
 }
diff --git a/src/test/ui/consts/invalid-union.32bit.stderr b/src/test/ui/consts/invalid-union.32bit.stderr
index 4758ea4ae88..0dd18a55786 100644
--- a/src/test/ui/consts/invalid-union.32bit.stderr
+++ b/src/test/ui/consts/invalid-union.32bit.stderr
@@ -21,12 +21,6 @@ note: erroneous constant used
 LL |     let _: &'static _ = &C;
    |                         ^^
 
-note: erroneous constant used
-  --> $DIR/invalid-union.rs:43:25
-   |
-LL |     let _: &'static _ = &C;
-   |                         ^^
-
 error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/invalid-union.64bit.stderr b/src/test/ui/consts/invalid-union.64bit.stderr
index 22b85d20ce9..07f36ee2832 100644
--- a/src/test/ui/consts/invalid-union.64bit.stderr
+++ b/src/test/ui/consts/invalid-union.64bit.stderr
@@ -21,12 +21,6 @@ note: erroneous constant used
 LL |     let _: &'static _ = &C;
    |                         ^^
 
-note: erroneous constant used
-  --> $DIR/invalid-union.rs:43:25
-   |
-LL |     let _: &'static _ = &C;
-   |                         ^^
-
 error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/issue-103790.stderr b/src/test/ui/consts/issue-103790.stderr
index 41b0816dc32..34d8ee281cf 100644
--- a/src/test/ui/consts/issue-103790.stderr
+++ b/src/test/ui/consts/issue-103790.stderr
@@ -20,7 +20,7 @@ LL | struct S<const S: (), const S: S = { S }>;
 help: add missing generic argument
    |
 LL | struct S<const S: (), const S: S<S> = { S }>;
-   |                                ~~~~
+   |                                 +++
 
 error[E0391]: cycle detected when computing type of `S::S`
   --> $DIR/issue-103790.rs:4:32
diff --git a/src/test/ui/issues/issue-2734.rs b/src/test/ui/drop/issue-2734.rs
index df4f394dc37..df4f394dc37 100644
--- a/src/test/ui/issues/issue-2734.rs
+++ b/src/test/ui/drop/issue-2734.rs
diff --git a/src/test/ui/dropck/dropck-eyepatch-implies-unsafe-impl.stderr b/src/test/ui/dropck/dropck-eyepatch-implies-unsafe-impl.stderr
index 82169ee01be..5cec2bcb038 100644
--- a/src/test/ui/dropck/dropck-eyepatch-implies-unsafe-impl.stderr
+++ b/src/test/ui/dropck/dropck-eyepatch-implies-unsafe-impl.stderr
@@ -1,13 +1,8 @@
 error[E0569]: requires an `unsafe impl` declaration due to `#[may_dangle]` attribute
   --> $DIR/dropck-eyepatch-implies-unsafe-impl.rs:21:1
    |
-LL | / impl<#[may_dangle] A, B: fmt::Debug> Drop for Pt<A, B> {
-LL | |
-LL | |
-LL | |     // (unsafe to access self.1  due to #[may_dangle] on A)
-LL | |     fn drop(&mut self) { println!("drop {} {:?}", self.0, self.2); }
-LL | | }
-   | |_^
+LL | impl<#[may_dangle] A, B: fmt::Debug> Drop for Pt<A, B> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: the trait `Drop` enforces invariants that the compiler can't check. Review the trait documentation and make sure this implementation upholds those invariants before adding the `unsafe` keyword
 help: add `unsafe` to this trait implementation
@@ -18,13 +13,8 @@ LL | unsafe impl<#[may_dangle] A, B: fmt::Debug> Drop for Pt<A, B> {
 error[E0569]: requires an `unsafe impl` declaration due to `#[may_dangle]` attribute
   --> $DIR/dropck-eyepatch-implies-unsafe-impl.rs:27:1
    |
-LL | / impl<#[may_dangle] 'a, 'b, B: fmt::Debug> Drop for Pr<'a, 'b, B> {
-LL | |
-LL | |
-LL | |     // (unsafe to access self.1 due to #[may_dangle] on 'a)
-LL | |     fn drop(&mut self) { println!("drop {} {:?}", self.0, self.2); }
-LL | | }
-   | |_^
+LL | impl<#[may_dangle] 'a, 'b, B: fmt::Debug> Drop for Pr<'a, 'b, B> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: the trait `Drop` enforces invariants that the compiler can't check. Review the trait documentation and make sure this implementation upholds those invariants before adding the `unsafe` keyword
 help: add `unsafe` to this trait implementation
diff --git a/src/test/ui/issues/issue-34053.rs b/src/test/ui/dropck/issue-34053.rs
index fa23ae8f95b..fa23ae8f95b 100644
--- a/src/test/ui/issues/issue-34053.rs
+++ b/src/test/ui/dropck/issue-34053.rs
diff --git a/src/test/ui/issues/issue-72554.rs b/src/test/ui/enum-discriminant/issue-72554.rs
index 54f7e9ac592..54f7e9ac592 100644
--- a/src/test/ui/issues/issue-72554.rs
+++ b/src/test/ui/enum-discriminant/issue-72554.rs
diff --git a/src/test/ui/issues/issue-72554.stderr b/src/test/ui/enum-discriminant/issue-72554.stderr
index d12be539f7c..d12be539f7c 100644
--- a/src/test/ui/issues/issue-72554.stderr
+++ b/src/test/ui/enum-discriminant/issue-72554.stderr
diff --git a/src/test/ui/error-codes/E0013.rs b/src/test/ui/error-codes/E0013.rs
new file mode 100644
index 00000000000..9b3982a785b
--- /dev/null
+++ b/src/test/ui/error-codes/E0013.rs
@@ -0,0 +1,4 @@
+static X: i32 = 42;
+const Y: i32 = X; //~ ERROR constants cannot refer to statics [E0013]
+
+fn main() {}
diff --git a/src/test/ui/error-codes/E0013.stderr b/src/test/ui/error-codes/E0013.stderr
new file mode 100644
index 00000000000..dc22053a638
--- /dev/null
+++ b/src/test/ui/error-codes/E0013.stderr
@@ -0,0 +1,11 @@
+error[E0013]: constants cannot refer to statics
+  --> $DIR/E0013.rs:2:16
+   |
+LL | const Y: i32 = X;
+   |                ^
+   |
+   = help: consider extracting the value of the `static` to a `const`, and referring to that
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0013`.
diff --git a/src/test/ui/error-codes/E0015.rs b/src/test/ui/error-codes/E0015.rs
new file mode 100644
index 00000000000..b0211358d81
--- /dev/null
+++ b/src/test/ui/error-codes/E0015.rs
@@ -0,0 +1,8 @@
+fn create_some() -> Option<u8> {
+    Some(1)
+}
+
+const FOO: Option<u8> = create_some();
+//~^ ERROR cannot call non-const fn `create_some` in constants [E0015]
+
+fn main() {}
diff --git a/src/test/ui/error-codes/E0015.stderr b/src/test/ui/error-codes/E0015.stderr
new file mode 100644
index 00000000000..ec1ce47b2ce
--- /dev/null
+++ b/src/test/ui/error-codes/E0015.stderr
@@ -0,0 +1,11 @@
+error[E0015]: cannot call non-const fn `create_some` in constants
+  --> $DIR/E0015.rs:5:25
+   |
+LL | const FOO: Option<u8> = create_some();
+   |                         ^^^^^^^^^^^^^
+   |
+   = note: calls in constants are limited to constant functions, tuple structs and tuple variants
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0015`.
diff --git a/src/test/ui/error-codes/E0199.stderr b/src/test/ui/error-codes/E0199.stderr
index 99d808c0d4b..68c308b15cc 100644
--- a/src/test/ui/error-codes/E0199.stderr
+++ b/src/test/ui/error-codes/E0199.stderr
@@ -2,7 +2,7 @@ error[E0199]: implementing the trait `Bar` is not unsafe
   --> $DIR/E0199.rs:6:1
    |
 LL | unsafe impl Bar for Foo { }
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^^^^
    |
 help: remove `unsafe` from this trait implementation
    |
diff --git a/src/test/ui/error-codes/E0200.stderr b/src/test/ui/error-codes/E0200.stderr
index 1fd86aecee1..c70a2d4f3d1 100644
--- a/src/test/ui/error-codes/E0200.stderr
+++ b/src/test/ui/error-codes/E0200.stderr
@@ -2,7 +2,7 @@ error[E0200]: the trait `Bar` requires an `unsafe impl` declaration
   --> $DIR/E0200.rs:5:1
    |
 LL | impl Bar for Foo { }
-   | ^^^^^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^
    |
    = note: the trait `Bar` enforces invariants that the compiler can't check. Review the trait documentation and make sure this implementation upholds those invariants before adding the `unsafe` keyword
 help: add `unsafe` to this trait implementation
diff --git a/src/test/ui/error-codes/E0637.stderr b/src/test/ui/error-codes/E0637.stderr
index 35a4b34fb0a..78341735e19 100644
--- a/src/test/ui/error-codes/E0637.stderr
+++ b/src/test/ui/error-codes/E0637.stderr
@@ -21,6 +21,12 @@ error[E0637]: `&` without an explicit lifetime name cannot be used here
    |
 LL |     T: Into<&u32>,
    |             ^ explicit lifetime name needed here
+   |
+help: consider introducing a higher-ranked lifetime here with `for<'a>`
+  --> $DIR/E0637.rs:13:8
+   |
+LL |     T: Into<&u32>,
+   |        ^
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/issues/issue-13655.rs b/src/test/ui/extern/issue-13655.rs
index 6dd1847995f..6dd1847995f 100644
--- a/src/test/ui/issues/issue-13655.rs
+++ b/src/test/ui/extern/issue-13655.rs
diff --git a/src/test/ui/fmt/ifmt-bad-arg.stderr b/src/test/ui/fmt/ifmt-bad-arg.stderr
index a8a2a47fe46..c2619d6df58 100644
--- a/src/test/ui/fmt/ifmt-bad-arg.stderr
+++ b/src/test/ui/fmt/ifmt-bad-arg.stderr
@@ -170,7 +170,7 @@ LL |     format!("foo %s baz", "bar");
    |                  |
    |                  help: format specifiers use curly braces: `{}`
    |
-   = note: printf formatting not supported; see the documentation for `std::fmt`
+   = note: printf formatting is not supported; see the documentation for `std::fmt`
 
 error: invalid format string: expected `'}'`, found `'t'`
   --> $DIR/ifmt-bad-arg.rs:75:1
diff --git a/src/test/ui/fmt/issue-89173.rs b/src/test/ui/fmt/issue-89173.rs
index 96277d4d0d9..fc99af40859 100644
--- a/src/test/ui/fmt/issue-89173.rs
+++ b/src/test/ui/fmt/issue-89173.rs
@@ -10,5 +10,5 @@ fn main() {
     //~| NOTE: argument never used
     //~| NOTE: argument never used
     //~| NOTE: format specifiers use curly braces, and you have to use a positional or named parameter for the width
-    //~| NOTE: printf formatting not supported
+    //~| NOTE: printf formatting is not supported
 }
diff --git a/src/test/ui/fmt/issue-89173.stderr b/src/test/ui/fmt/issue-89173.stderr
index 7b21e0a4fc8..ddeb769eadc 100644
--- a/src/test/ui/fmt/issue-89173.stderr
+++ b/src/test/ui/fmt/issue-89173.stderr
@@ -12,7 +12,7 @@ note: format specifiers use curly braces, and you have to use a positional or na
    |
 LL |     print!("%0*x", width, num);
    |             ^^^^
-   = note: printf formatting not supported; see the documentation for `std::fmt`
+   = note: printf formatting is not supported; see the documentation for `std::fmt`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/fn/issue-3044.rs b/src/test/ui/fn/issue-3044.rs
index 7c626a01b12..19bee733ec0 100644
--- a/src/test/ui/fn/issue-3044.rs
+++ b/src/test/ui/fn/issue-3044.rs
@@ -1,6 +1,6 @@
 fn main() {
     let needlesArr: Vec<char> = vec!['a', 'f'];
     needlesArr.iter().fold(|x, y| {
-        //~^ ERROR this function takes 2 arguments but 1 argument was supplied
+        //~^ ERROR this method takes 2 arguments but 1 argument was supplied
     });
 }
diff --git a/src/test/ui/fn/issue-3044.stderr b/src/test/ui/fn/issue-3044.stderr
index 1232b83c391..2690ad71176 100644
--- a/src/test/ui/fn/issue-3044.stderr
+++ b/src/test/ui/fn/issue-3044.stderr
@@ -1,4 +1,4 @@
-error[E0061]: this function takes 2 arguments but 1 argument was supplied
+error[E0061]: this method takes 2 arguments but 1 argument was supplied
   --> $DIR/issue-3044.rs:3:23
    |
 LL |       needlesArr.iter().fold(|x, y| {
diff --git a/src/test/ui/fn/issue-80179.rs b/src/test/ui/fn/issue-80179.rs
index fcef6f1b60e..35e39bebb29 100644
--- a/src/test/ui/fn/issue-80179.rs
+++ b/src/test/ui/fn/issue-80179.rs
@@ -18,9 +18,9 @@ fn returns_fn_ptr() -> _ {
 fn returns_closure() -> _ {
 //~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types [E0121]
 //~| NOTE not allowed in type signatures
-//~| HELP consider using an `Fn`, `FnMut`, or `FnOnce` trait bound
-//~| NOTE for more information on `Fn` traits and closure types, see
-//        https://doc.rust-lang.org/book/ch13-01-closures.html
+//~| HELP replace with an appropriate return type
+//~| SUGGESTION impl Fn() -> i32
+//~| NOTE for more information on `Fn` traits and closure types
     || 0
 }
 
diff --git a/src/test/ui/fn/issue-80179.stderr b/src/test/ui/fn/issue-80179.stderr
index 2ca4ae982d9..f5d6c44db75 100644
--- a/src/test/ui/fn/issue-80179.stderr
+++ b/src/test/ui/fn/issue-80179.stderr
@@ -11,9 +11,11 @@ error[E0121]: the placeholder `_` is not allowed within types on item signatures
   --> $DIR/issue-80179.rs:18:25
    |
 LL | fn returns_closure() -> _ {
-   |                         ^ not allowed in type signatures
+   |                         ^
+   |                         |
+   |                         not allowed in type signatures
+   |                         help: replace with an appropriate return type: `impl Fn() -> i32`
    |
-   = help: consider using an `Fn`, `FnMut`, or `FnOnce` trait bound
    = note: for more information on `Fn` traits and closure types, see https://doc.rust-lang.org/book/ch13-01-closures.html
 
 error: aborting due to 2 previous errors
diff --git a/src/test/ui/fn/suggest-return-closure.rs b/src/test/ui/fn/suggest-return-closure.rs
new file mode 100644
index 00000000000..33daa1ea0b4
--- /dev/null
+++ b/src/test/ui/fn/suggest-return-closure.rs
@@ -0,0 +1,34 @@
+fn fn_once() -> _ {
+    //~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types [E0121]
+    //~| NOTE not allowed in type signatures
+    //~| HELP replace with an appropriate return type
+    //~| SUGGESTION impl FnOnce()
+    //~| NOTE for more information on `Fn` traits and closure types
+    let x = String::new();
+    || {
+        drop(x);
+    }
+}
+
+fn fn_mut() -> _ {
+    //~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types [E0121]
+    //~| NOTE not allowed in type signatures
+    //~| HELP replace with an appropriate return type
+    //~| SUGGESTION impl FnMut(char)
+    //~| NOTE for more information on `Fn` traits and closure types
+    let x = String::new();
+    |c| {
+        x.push(c);
+    }
+}
+
+fn fun() -> _ {
+    //~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types [E0121]
+    //~| NOTE not allowed in type signatures
+    //~| HELP replace with an appropriate return type
+    //~| SUGGESTION impl Fn() -> i32
+    //~| NOTE for more information on `Fn` traits and closure types
+    || 1i32
+}
+
+fn main() {}
diff --git a/src/test/ui/fn/suggest-return-closure.stderr b/src/test/ui/fn/suggest-return-closure.stderr
new file mode 100644
index 00000000000..341044469ea
--- /dev/null
+++ b/src/test/ui/fn/suggest-return-closure.stderr
@@ -0,0 +1,36 @@
+error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types
+  --> $DIR/suggest-return-closure.rs:1:17
+   |
+LL | fn fn_once() -> _ {
+   |                 ^
+   |                 |
+   |                 not allowed in type signatures
+   |                 help: replace with an appropriate return type: `impl FnOnce()`
+   |
+   = note: for more information on `Fn` traits and closure types, see https://doc.rust-lang.org/book/ch13-01-closures.html
+
+error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types
+  --> $DIR/suggest-return-closure.rs:13:16
+   |
+LL | fn fn_mut() -> _ {
+   |                ^
+   |                |
+   |                not allowed in type signatures
+   |                help: replace with an appropriate return type: `impl FnMut(char)`
+   |
+   = note: for more information on `Fn` traits and closure types, see https://doc.rust-lang.org/book/ch13-01-closures.html
+
+error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types
+  --> $DIR/suggest-return-closure.rs:25:13
+   |
+LL | fn fun() -> _ {
+   |             ^
+   |             |
+   |             not allowed in type signatures
+   |             help: replace with an appropriate return type: `impl Fn() -> i32`
+   |
+   = note: for more information on `Fn` traits and closure types, see https://doc.rust-lang.org/book/ch13-01-closures.html
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0121`.
diff --git a/src/test/ui/fn/suggest-return-future.rs b/src/test/ui/fn/suggest-return-future.rs
new file mode 100644
index 00000000000..750740d9426
--- /dev/null
+++ b/src/test/ui/fn/suggest-return-future.rs
@@ -0,0 +1,23 @@
+// edition: 2021
+
+async fn a() -> i32 {
+    0
+}
+
+fn foo() -> _ {
+    //~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types [E0121]
+    //~| NOTE not allowed in type signatures
+    //~| HELP replace with an appropriate return type
+    //~| SUGGESTION impl Future<Output = i32>
+    a()
+}
+
+fn bar() -> _ {
+    //~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types [E0121]
+    //~| NOTE not allowed in type signatures
+    //~| HELP replace with an appropriate return type
+    //~| SUGGESTION impl Future<Output = i32>
+    async { a().await }
+}
+
+fn main() {}
diff --git a/src/test/ui/fn/suggest-return-future.stderr b/src/test/ui/fn/suggest-return-future.stderr
new file mode 100644
index 00000000000..a4c8b5d8c4b
--- /dev/null
+++ b/src/test/ui/fn/suggest-return-future.stderr
@@ -0,0 +1,21 @@
+error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types
+  --> $DIR/suggest-return-future.rs:7:13
+   |
+LL | fn foo() -> _ {
+   |             ^
+   |             |
+   |             not allowed in type signatures
+   |             help: replace with an appropriate return type: `impl Future<Output = i32>`
+
+error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types
+  --> $DIR/suggest-return-future.rs:15:13
+   |
+LL | fn bar() -> _ {
+   |             ^
+   |             |
+   |             not allowed in type signatures
+   |             help: replace with an appropriate return type: `impl Future<Output = i32>`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0121`.
diff --git a/src/test/ui/generator/issue-102645.rs b/src/test/ui/generator/issue-102645.rs
index 0589c5a009a..35acd5cd727 100644
--- a/src/test/ui/generator/issue-102645.rs
+++ b/src/test/ui/generator/issue-102645.rs
@@ -14,7 +14,7 @@ fn main() {
         a = d;
     };
     Pin::new(&mut b).resume();
-    //~^ ERROR this function takes 1 argument but 0 arguments were supplied
+    //~^ ERROR this method takes 1 argument but 0 arguments were supplied
     // This type error is required to reproduce the ICE...
 }
 
diff --git a/src/test/ui/generator/issue-102645.stderr b/src/test/ui/generator/issue-102645.stderr
index afb39c9e594..f6d2440295e 100644
--- a/src/test/ui/generator/issue-102645.stderr
+++ b/src/test/ui/generator/issue-102645.stderr
@@ -1,4 +1,4 @@
-error[E0061]: this function takes 1 argument but 0 arguments were supplied
+error[E0061]: this method takes 1 argument but 0 arguments were supplied
   --> $DIR/issue-102645.rs:16:22
    |
 LL |     Pin::new(&mut b).resume();
diff --git a/src/test/ui/generic-associated-types/elided-in-expr-position.stderr b/src/test/ui/generic-associated-types/elided-in-expr-position.stderr
index a9996123f23..842b23bd49d 100644
--- a/src/test/ui/generic-associated-types/elided-in-expr-position.stderr
+++ b/src/test/ui/generic-associated-types/elided-in-expr-position.stderr
@@ -12,7 +12,7 @@ LL |     type Assoc<'a> where Self: 'a;
 help: add missing lifetime argument
    |
 LL |     fn g(&self) -> Self::Assoc<'_>;
-   |                          ~~~~~~~~~
+   |                               ++++
 
 error[E0107]: missing generics for associated type `Trait::Assoc`
   --> $DIR/elided-in-expr-position.rs:31:26
@@ -28,7 +28,7 @@ LL |     type Assoc<'a> where Self: 'a;
 help: add missing lifetime argument
    |
 LL |     fn g(&self) -> Self::Assoc<'_> {
-   |                          ~~~~~~~~~
+   |                               ++++
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/generic-associated-types/gat-trait-path-missing-lifetime.stderr b/src/test/ui/generic-associated-types/gat-trait-path-missing-lifetime.stderr
index 452dfefd1e3..499221637ba 100644
--- a/src/test/ui/generic-associated-types/gat-trait-path-missing-lifetime.stderr
+++ b/src/test/ui/generic-associated-types/gat-trait-path-missing-lifetime.stderr
@@ -12,7 +12,7 @@ LL |   type Y<'a>;
 help: add missing lifetime argument
    |
 LL |   fn foo<'a, T1: X<Y<'a> = T1>>(t : T1) -> T1::Y<'a> {
-   |                    ~~~~~
+   |                     ++++
 
 error[E0107]: missing generics for associated type `X::Y`
   --> $DIR/gat-trait-path-missing-lifetime.rs:8:20
@@ -28,7 +28,7 @@ LL |   type Y<'a>;
 help: add missing lifetime argument
    |
 LL |   fn foo<'a, T1: X<Y<'a> = T1>>(t : T1) -> T1::Y<'a> {
-   |                    ~~~~~
+   |                     ++++
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/generic-associated-types/issue-71176.stderr b/src/test/ui/generic-associated-types/issue-71176.stderr
index 386c97161c8..4b4fe43e8c4 100644
--- a/src/test/ui/generic-associated-types/issue-71176.stderr
+++ b/src/test/ui/generic-associated-types/issue-71176.stderr
@@ -12,7 +12,7 @@ LL |     type A<'a>;
 help: add missing lifetime argument
    |
 LL |   inner: Box<dyn Provider<A<'a> = B>>,
-   |                           ~~~~~
+   |                            ++++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/generic-associated-types/issue-76535.base.stderr b/src/test/ui/generic-associated-types/issue-76535.base.stderr
index 088f69b09f7..52c6e3eec60 100644
--- a/src/test/ui/generic-associated-types/issue-76535.base.stderr
+++ b/src/test/ui/generic-associated-types/issue-76535.base.stderr
@@ -12,7 +12,7 @@ LL |     type SubType<'a>: SubTrait where Self: 'a;
 help: add missing lifetime argument
    |
 LL |     let sub: Box<dyn SuperTrait<SubType<'a> = SubStruct>> = Box::new(SuperStruct::new(0));
-   |                                 ~~~~~~~~~~~
+   |                                        ++++
 
 error[E0038]: the trait `SuperTrait` cannot be made into an object
   --> $DIR/issue-76535.rs:39:14
diff --git a/src/test/ui/generic-associated-types/issue-76535.extended.stderr b/src/test/ui/generic-associated-types/issue-76535.extended.stderr
index e79f0a73f5b..369b86d2928 100644
--- a/src/test/ui/generic-associated-types/issue-76535.extended.stderr
+++ b/src/test/ui/generic-associated-types/issue-76535.extended.stderr
@@ -12,7 +12,7 @@ LL |     type SubType<'a>: SubTrait where Self: 'a;
 help: add missing lifetime argument
    |
 LL |     let sub: Box<dyn SuperTrait<SubType<'a> = SubStruct>> = Box::new(SuperStruct::new(0));
-   |                                 ~~~~~~~~~~~
+   |                                        ++++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/generic-associated-types/issue-78671.base.stderr b/src/test/ui/generic-associated-types/issue-78671.base.stderr
index 514f8d45a15..bad8c1c9dba 100644
--- a/src/test/ui/generic-associated-types/issue-78671.base.stderr
+++ b/src/test/ui/generic-associated-types/issue-78671.base.stderr
@@ -12,7 +12,7 @@ LL |     type Member<T>;
 help: add missing generic argument
    |
 LL |     Box::new(Family) as &dyn CollectionFamily<Member<T>=usize>
-   |                                               ~~~~~~~~~
+   |                                                     +++
 
 error[E0038]: the trait `CollectionFamily` cannot be made into an object
   --> $DIR/issue-78671.rs:10:25
diff --git a/src/test/ui/generic-associated-types/issue-78671.extended.stderr b/src/test/ui/generic-associated-types/issue-78671.extended.stderr
index 6fa09a4c7e5..1d8a3d410f8 100644
--- a/src/test/ui/generic-associated-types/issue-78671.extended.stderr
+++ b/src/test/ui/generic-associated-types/issue-78671.extended.stderr
@@ -12,7 +12,7 @@ LL |     type Member<T>;
 help: add missing generic argument
    |
 LL |     Box::new(Family) as &dyn CollectionFamily<Member<T>=usize>
-   |                                               ~~~~~~~~~
+   |                                                     +++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/generic-associated-types/issue-79422.base.stderr b/src/test/ui/generic-associated-types/issue-79422.base.stderr
index 3c1a29d48b2..f1de77bc3c0 100644
--- a/src/test/ui/generic-associated-types/issue-79422.base.stderr
+++ b/src/test/ui/generic-associated-types/issue-79422.base.stderr
@@ -12,7 +12,7 @@ LL |     type VRefCont<'a>: RefCont<'a, V> where Self: 'a;
 help: add missing lifetime argument
    |
 LL |         as Box<dyn MapLike<u8, u8, VRefCont<'a> = dyn RefCont<'_, u8>>>;
-   |                                    ~~~~~~~~~~~~
+   |                                            ++++
 
 error[E0038]: the trait `MapLike` cannot be made into an object
   --> $DIR/issue-79422.rs:47:12
diff --git a/src/test/ui/generic-associated-types/issue-79422.extended.stderr b/src/test/ui/generic-associated-types/issue-79422.extended.stderr
index 58c921bf09f..d79de0ca627 100644
--- a/src/test/ui/generic-associated-types/issue-79422.extended.stderr
+++ b/src/test/ui/generic-associated-types/issue-79422.extended.stderr
@@ -12,7 +12,7 @@ LL |     type VRefCont<'a>: RefCont<'a, V> where Self: 'a;
 help: add missing lifetime argument
    |
 LL |         as Box<dyn MapLike<u8, u8, VRefCont<'a> = dyn RefCont<'_, u8>>>;
-   |                                    ~~~~~~~~~~~~
+   |                                            ++++
 
 error[E0271]: type mismatch resolving `<BTreeMap<u8, u8> as MapLike<u8, u8>>::VRefCont<'_> == (dyn RefCont<'_, u8> + 'static)`
   --> $DIR/issue-79422.rs:44:13
diff --git a/src/test/ui/generic-associated-types/issue-79636-1.stderr b/src/test/ui/generic-associated-types/issue-79636-1.stderr
index 155477048ca..6e0d2ff4ded 100644
--- a/src/test/ui/generic-associated-types/issue-79636-1.stderr
+++ b/src/test/ui/generic-associated-types/issue-79636-1.stderr
@@ -12,7 +12,7 @@ LL |     type Wrapped<B>;
 help: add missing generic argument
    |
 LL |     MInner: Monad<Unwrapped = A, Wrapped<B> = MOuter::Wrapped<A>>,
-   |                                  ~~~~~~~~~~
+   |                                         +++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/generic-associated-types/issue-79636-2.stderr b/src/test/ui/generic-associated-types/issue-79636-2.stderr
index 6a36bfc37f2..16287323995 100644
--- a/src/test/ui/generic-associated-types/issue-79636-2.stderr
+++ b/src/test/ui/generic-associated-types/issue-79636-2.stderr
@@ -12,7 +12,7 @@ LL |     type Wrapped<A>: SomeTrait;
 help: add missing generic argument
    |
 LL |     W: SomeTrait<Wrapped<A> = W>,
-   |                  ~~~~~~~~~~
+   |                         +++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/generic-associated-types/issue-80433.stderr b/src/test/ui/generic-associated-types/issue-80433.stderr
index 20a407dd412..4f4f96a4b92 100644
--- a/src/test/ui/generic-associated-types/issue-80433.stderr
+++ b/src/test/ui/generic-associated-types/issue-80433.stderr
@@ -12,7 +12,7 @@ LL |     type Output<'a>;
 help: add missing lifetime argument
    |
 LL | fn test_simpler<'a>(dst: &'a mut impl TestMut<Output<'a> = &'a mut f32>)
-   |                                               ~~~~~~~~~~
+   |                                                     ++++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/generic-associated-types/issue-81712-cyclic-traits.stderr b/src/test/ui/generic-associated-types/issue-81712-cyclic-traits.stderr
index c8961e28ede..e0fc225f463 100644
--- a/src/test/ui/generic-associated-types/issue-81712-cyclic-traits.stderr
+++ b/src/test/ui/generic-associated-types/issue-81712-cyclic-traits.stderr
@@ -12,7 +12,7 @@ LL |     type DType<T>: D<T, CType = Self>;
 help: add missing generic argument
    |
 LL |     type CType: C<DType<T> = Self>;
-   |                   ~~~~~~~~
+   |                        +++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/generic-associated-types/issue-81862.stderr b/src/test/ui/generic-associated-types/issue-81862.stderr
index 9e21c567c73..df30be65ec5 100644
--- a/src/test/ui/generic-associated-types/issue-81862.stderr
+++ b/src/test/ui/generic-associated-types/issue-81862.stderr
@@ -12,7 +12,7 @@ LL |     type Item<'a>;
 help: add missing lifetime argument
    |
 LL |     fn next(&mut self) -> Option<Self::Item<'_>>;
-   |                                        ~~~~~~~~
+   |                                            ++++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/generic-associated-types/missing_lifetime_args.stderr b/src/test/ui/generic-associated-types/missing_lifetime_args.stderr
index 752587c25a7..8f74b12c008 100644
--- a/src/test/ui/generic-associated-types/missing_lifetime_args.stderr
+++ b/src/test/ui/generic-associated-types/missing_lifetime_args.stderr
@@ -12,7 +12,7 @@ LL |     type Y<'a, 'b>;
 help: add missing lifetime arguments
    |
 LL | fn foo<'c, 'd>(_arg: Box<dyn X<Y<'_, '_> = (&'c u32, &'d u32)>>) {}
-   |                                ~~~~~~~~~
+   |                                 ++++++++
 
 error[E0107]: this struct takes 3 lifetime arguments but 2 lifetime arguments were supplied
   --> $DIR/missing_lifetime_args.rs:14:26
diff --git a/src/test/ui/generics/generic-type-less-params-with-defaults.stderr b/src/test/ui/generics/generic-type-less-params-with-defaults.stderr
index e45a0d9ca77..6450bbd8b43 100644
--- a/src/test/ui/generics/generic-type-less-params-with-defaults.stderr
+++ b/src/test/ui/generics/generic-type-less-params-with-defaults.stderr
@@ -12,7 +12,7 @@ LL | struct Vec<T, A = Heap>(
 help: add missing generic argument
    |
 LL |     let _: Vec<T>;
-   |            ~~~~~~
+   |               +++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/generics/issue-65285-incorrect-explicit-lifetime-name-needed.stderr b/src/test/ui/generics/issue-65285-incorrect-explicit-lifetime-name-needed.stderr
index e45387acaf3..9d859fddf56 100644
--- a/src/test/ui/generics/issue-65285-incorrect-explicit-lifetime-name-needed.stderr
+++ b/src/test/ui/generics/issue-65285-incorrect-explicit-lifetime-name-needed.stderr
@@ -3,6 +3,12 @@ error[E0637]: `&` without an explicit lifetime name cannot be used here
    |
 LL | fn should_error<T>() where T : Into<&u32> {}
    |                                     ^ explicit lifetime name needed here
+   |
+help: consider introducing a higher-ranked lifetime here with `for<'a>`
+  --> $DIR/issue-65285-incorrect-explicit-lifetime-name-needed.rs:5:32
+   |
+LL | fn should_error<T>() where T : Into<&u32> {}
+   |                                ^
 
 error[E0106]: missing lifetime specifier
   --> $DIR/issue-65285-incorrect-explicit-lifetime-name-needed.rs:9:20
diff --git a/src/test/ui/generics/wrong-number-of-args.stderr b/src/test/ui/generics/wrong-number-of-args.stderr
index b48966a1a1e..75e33f680ea 100644
--- a/src/test/ui/generics/wrong-number-of-args.stderr
+++ b/src/test/ui/generics/wrong-number-of-args.stderr
@@ -251,7 +251,7 @@ LL |     struct Ty<A, B>;
 help: add missing generic arguments
    |
 LL |     type A = Ty<A, B>;
-   |              ~~~~~~~~
+   |                ++++++
 
 error[E0107]: this struct takes 2 generic arguments but 1 generic argument was supplied
   --> $DIR/wrong-number-of-args.rs:30:14
@@ -315,7 +315,7 @@ LL |     struct Ty<'a, T>;
 help: add missing generic argument
    |
 LL |     type A = Ty<T>;
-   |              ~~~~~
+   |                +++
 
 error[E0107]: this struct takes 1 generic argument but 0 generic arguments were supplied
   --> $DIR/wrong-number-of-args.rs:54:14
@@ -391,7 +391,7 @@ LL |     struct Ty<A, B, C = &'static str>;
 help: add missing generic arguments
    |
 LL |     type A = Ty<A, B>;
-   |              ~~~~~~~~
+   |                ++++++
 
 error[E0107]: this struct takes at least 2 generic arguments but 1 generic argument was supplied
   --> $DIR/wrong-number-of-args.rs:84:14
@@ -483,7 +483,7 @@ LL |     trait GenericType<A> {
 help: add missing generic argument
    |
 LL |     type D = Box<dyn GenericType<A>>;
-   |                      ~~~~~~~~~~~~~~
+   |                                 +++
 
 error[E0107]: this trait takes 1 generic argument but 2 generic arguments were supplied
   --> $DIR/wrong-number-of-args.rs:133:22
@@ -892,7 +892,7 @@ LL |         type A = HashMap;
 help: add missing generic arguments
    |
 LL |         type A = HashMap<K, V>;
-   |                  ~~~~~~~~~~~~~
+   |                         ++++++
 
 error[E0107]: this struct takes at least 2 generic arguments but 1 generic argument was supplied
   --> $DIR/wrong-number-of-args.rs:314:18
@@ -954,7 +954,7 @@ LL |         type A = Result;
 help: add missing generic arguments
    |
 LL |         type A = Result<T, E>;
-   |                  ~~~~~~~~~~~~
+   |                        ++++++
 
 error[E0107]: this enum takes 2 generic arguments but 1 generic argument was supplied
   --> $DIR/wrong-number-of-args.rs:338:18
diff --git a/src/test/ui/higher-rank-trait-bounds/issue-58451.rs b/src/test/ui/higher-rank-trait-bounds/issue-58451.rs
index f36d549e476..6006a108c5c 100644
--- a/src/test/ui/higher-rank-trait-bounds/issue-58451.rs
+++ b/src/test/ui/higher-rank-trait-bounds/issue-58451.rs
@@ -9,5 +9,5 @@ where
 {}
 
 fn main() {
-    f(&[f()]); //~ ERROR this function takes 1 argument
+    f(&[f()]); //~ ERROR function takes 1 argument
 }
diff --git a/src/test/ui/illegal-sized-bound/mutability-mismatch-arg.fixed b/src/test/ui/illegal-sized-bound/mutability-mismatch-arg.fixed
new file mode 100644
index 00000000000..74f3c887f02
--- /dev/null
+++ b/src/test/ui/illegal-sized-bound/mutability-mismatch-arg.fixed
@@ -0,0 +1,9 @@
+// run-rustfix
+fn test(t: &mut dyn Iterator<Item=&u64>) -> u64 {
+     *t.min().unwrap() //~ ERROR the `min` method cannot be invoked on
+}
+
+fn main() {
+     let array = [0u64];
+     test(&mut array.iter());
+}
diff --git a/src/test/ui/illegal-sized-bound/mutability-mismatch-arg.rs b/src/test/ui/illegal-sized-bound/mutability-mismatch-arg.rs
new file mode 100644
index 00000000000..3b02c5a5ad1
--- /dev/null
+++ b/src/test/ui/illegal-sized-bound/mutability-mismatch-arg.rs
@@ -0,0 +1,9 @@
+// run-rustfix
+fn test(t: &dyn Iterator<Item=&u64>) -> u64 {
+     *t.min().unwrap() //~ ERROR the `min` method cannot be invoked on
+}
+
+fn main() {
+     let array = [0u64];
+     test(&mut array.iter());
+}
diff --git a/src/test/ui/illegal-sized-bound/mutability-mismatch-arg.stderr b/src/test/ui/illegal-sized-bound/mutability-mismatch-arg.stderr
new file mode 100644
index 00000000000..89613bd5c20
--- /dev/null
+++ b/src/test/ui/illegal-sized-bound/mutability-mismatch-arg.stderr
@@ -0,0 +1,13 @@
+error: the `min` method cannot be invoked on `&dyn Iterator<Item = &u64>`
+  --> $DIR/mutability-mismatch-arg.rs:3:9
+   |
+LL |      *t.min().unwrap()
+   |         ^^^
+   |
+help: you need `&mut dyn Iterator<Item = &u64>` instead of `&dyn Iterator<Item = &u64>`
+   |
+LL | fn test(t: &mut dyn Iterator<Item=&u64>) -> u64 {
+   |             +++
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/illegal-sized-bound/mutability-mismatch.rs b/src/test/ui/illegal-sized-bound/mutability-mismatch.rs
index deb84f6fe97..01bb3537c2d 100644
--- a/src/test/ui/illegal-sized-bound/mutability-mismatch.rs
+++ b/src/test/ui/illegal-sized-bound/mutability-mismatch.rs
@@ -4,7 +4,6 @@ pub trait MutTrait {
     fn function(&mut self)
     where
         Self: Sized;
-    //~^ this has a `Sized` requirement
 }
 
 impl MutTrait for MutType {
@@ -17,7 +16,6 @@ pub trait Trait {
     fn function(&self)
     where
         Self: Sized;
-    //~^ this has a `Sized` requirement
 }
 
 impl Trait for Type {
@@ -26,9 +24,9 @@ impl Trait for Type {
 
 fn main() {
     (&MutType as &dyn MutTrait).function();
-    //~^ ERROR the `function` method cannot be invoked on a trait object
-    //~| NOTE you need `&mut dyn MutTrait` instead of `&dyn MutTrait`
+    //~^ ERROR the `function` method cannot be invoked on `&dyn MutTrait`
+    //~| HELP you need `&mut dyn MutTrait` instead of `&dyn MutTrait`
     (&mut Type as &mut dyn Trait).function();
-    //~^ ERROR the `function` method cannot be invoked on a trait object
-    //~| NOTE you need `&dyn Trait` instead of `&mut dyn Trait`
+    //~^ ERROR the `function` method cannot be invoked on `&mut dyn Trait`
+    //~| HELP you need `&dyn Trait` instead of `&mut dyn Trait`
 }
diff --git a/src/test/ui/illegal-sized-bound/mutability-mismatch.stderr b/src/test/ui/illegal-sized-bound/mutability-mismatch.stderr
index dbbf79a4f1a..2ca571d9b79 100644
--- a/src/test/ui/illegal-sized-bound/mutability-mismatch.stderr
+++ b/src/test/ui/illegal-sized-bound/mutability-mismatch.stderr
@@ -1,24 +1,18 @@
-error: the `function` method cannot be invoked on a trait object
-  --> $DIR/mutability-mismatch.rs:28:33
+error: the `function` method cannot be invoked on `&dyn MutTrait`
+  --> $DIR/mutability-mismatch.rs:26:33
    |
-LL |         Self: Sized;
-   |               ----- this has a `Sized` requirement
-...
 LL |     (&MutType as &dyn MutTrait).function();
    |                                 ^^^^^^^^
    |
-   = note: you need `&mut dyn MutTrait` instead of `&dyn MutTrait`
+   = help: you need `&mut dyn MutTrait` instead of `&dyn MutTrait`
 
-error: the `function` method cannot be invoked on a trait object
-  --> $DIR/mutability-mismatch.rs:31:35
+error: the `function` method cannot be invoked on `&mut dyn Trait`
+  --> $DIR/mutability-mismatch.rs:29:35
    |
-LL |         Self: Sized;
-   |               ----- this has a `Sized` requirement
-...
 LL |     (&mut Type as &mut dyn Trait).function();
    |                                   ^^^^^^^^
    |
-   = note: you need `&dyn Trait` instead of `&mut dyn Trait`
+   = help: you need `&dyn Trait` instead of `&mut dyn Trait`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/impl-trait/explicit-generic-args-with-impl-trait/not-enough-args.rs b/src/test/ui/impl-trait/explicit-generic-args-with-impl-trait/not-enough-args.rs
index 7249a36f5fe..a93bdb1788f 100644
--- a/src/test/ui/impl-trait/explicit-generic-args-with-impl-trait/not-enough-args.rs
+++ b/src/test/ui/impl-trait/explicit-generic-args-with-impl-trait/not-enough-args.rs
@@ -2,5 +2,5 @@ fn f<T: ?Sized, U: ?Sized>(_: impl AsRef<T>, _: impl AsRef<U>) {}
 
 fn main() {
     f::<[u8]>("a", b"a");
-    //~^ ERROR: this function takes 2 generic arguments but 1 generic argument was supplied
+    //~^ ERROR function takes 2 generic arguments but 1 generic argument was supplied
 }
diff --git a/src/test/ui/impl-trait/impl-generic-mismatch-ab.stderr b/src/test/ui/impl-trait/impl-generic-mismatch-ab.stderr
index acf768d5795..db97fc2bdc4 100644
--- a/src/test/ui/impl-trait/impl-generic-mismatch-ab.stderr
+++ b/src/test/ui/impl-trait/impl-generic-mismatch-ab.stderr
@@ -13,8 +13,8 @@ note: type in trait
    |
 LL |     fn foo<A: Debug>(&self, a: &A, b: &impl Debug);
    |                                ^^
-   = note: expected fn pointer `fn(&(), &B, &impl Debug)`
-              found fn pointer `fn(&(), &impl Debug, &B)`
+   = note: expected signature `fn(&(), &B, &impl Debug)`
+              found signature `fn(&(), &impl Debug, &B)`
    = note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound
    = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters
 
diff --git a/src/test/ui/impl-trait/in-trait/box-coerce-span-in-default.rs b/src/test/ui/impl-trait/in-trait/box-coerce-span-in-default.rs
new file mode 100644
index 00000000000..a4d483dee7a
--- /dev/null
+++ b/src/test/ui/impl-trait/in-trait/box-coerce-span-in-default.rs
@@ -0,0 +1,49 @@
+// check-pass
+
+#![feature(return_position_impl_trait_in_trait)]
+//~^ WARN the feature `return_position_impl_trait_in_trait` is incomplete
+
+struct TestA {}
+struct TestB {}
+
+impl TestTrait for TestA {
+    type Output = ();
+}
+impl TestTrait for TestB {
+    type Output = ();
+}
+
+trait TestTrait {
+    type Output;
+}
+
+impl<A, B> TestTrait for GreeterOutput<A, B>
+where
+    A: TestTrait<Output = ()>,
+    B: TestTrait<Output = ()>,
+{
+    type Output = ();
+}
+
+enum GreeterOutput<A, B>
+where
+    A: TestTrait<Output = ()>,
+    B: TestTrait<Output = ()>,
+{
+    SayHello(A),
+    SayGoodbye(B),
+}
+
+trait Greeter {
+    fn test_func(&self, func: &str) -> impl TestTrait<Output = ()> {
+        match func {
+            "SayHello" => GreeterOutput::SayHello(TestA {}),
+            "SayGoodbye" => GreeterOutput::SayGoodbye(TestB {}),
+            _ => GreeterOutput::SayHello(TestA {}),
+        }
+    }
+}
+
+fn main() {
+    println!("Hello, world!");
+}
diff --git a/src/test/ui/impl-trait/in-trait/box-coerce-span-in-default.stderr b/src/test/ui/impl-trait/in-trait/box-coerce-span-in-default.stderr
new file mode 100644
index 00000000000..d681ecf25e8
--- /dev/null
+++ b/src/test/ui/impl-trait/in-trait/box-coerce-span-in-default.stderr
@@ -0,0 +1,11 @@
+warning: the feature `return_position_impl_trait_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/box-coerce-span-in-default.rs:3:12
+   |
+LL | #![feature(return_position_impl_trait_in_trait)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/impl-trait/in-trait/method-signature-matches.stderr b/src/test/ui/impl-trait/in-trait/method-signature-matches.stderr
index 2b32c52c829..4dfd772222e 100644
--- a/src/test/ui/impl-trait/in-trait/method-signature-matches.stderr
+++ b/src/test/ui/impl-trait/in-trait/method-signature-matches.stderr
@@ -12,8 +12,8 @@ note: type in trait
    |
 LL |     fn owo(x: ()) -> impl Sized;
    |               ^^
-   = note: expected fn pointer `fn(())`
-              found fn pointer `fn(u8)`
+   = note: expected signature `fn(())`
+              found signature `fn(u8)`
 
 error[E0053]: method `owo` has an incompatible type for trait
   --> $DIR/method-signature-matches.rs:20:21
@@ -39,8 +39,8 @@ note: type in trait
    |
 LL |     async fn owo(x: ()) {}
    |                     ^^
-   = note: expected fn pointer `fn(()) -> _`
-              found fn pointer `fn(u8) -> _`
+   = note: expected signature `fn(()) -> _`
+              found signature `fn(u8) -> _`
 
 error[E0050]: method `calm_down_please` has 3 parameters but the declaration in trait `TooMuch::calm_down_please` has 0
   --> $DIR/method-signature-matches.rs:29:28
@@ -75,8 +75,8 @@ note: type in trait
    |
 LL |     fn early<'early, T>(x: &'early T) -> impl Sized;
    |                            ^^^^^^^^^
-   = note: expected fn pointer `fn(&'early T)`
-              found fn pointer `fn(&())`
+   = note: expected signature `fn(&'early T)`
+              found signature `fn(&())`
 
 error: aborting due to 5 previous errors
 
diff --git a/src/test/ui/impl-trait/in-trait/signature-mismatch.stderr b/src/test/ui/impl-trait/in-trait/signature-mismatch.stderr
index 6663d7faa1e..e105660173b 100644
--- a/src/test/ui/impl-trait/in-trait/signature-mismatch.stderr
+++ b/src/test/ui/impl-trait/in-trait/signature-mismatch.stderr
@@ -7,8 +7,8 @@ LL |     fn async_fn(&self, buff: &[u8]) -> impl Future<Output = Vec<u8>>;
 LL |     fn async_fn<'a>(&self, buff: &'a [u8]) -> impl Future<Output = Vec<u8>> + 'a {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found `fn(&'1 Struct, &'2 [u8]) -> impl Future<Output = Vec<u8>> + '2`
    |
-   = note: expected `fn(&'1 Struct, &'2 [u8]) -> impl Future<Output = Vec<u8>> + 'static`
-              found `fn(&'1 Struct, &'2 [u8]) -> impl Future<Output = Vec<u8>> + '2`
+   = note: expected signature `fn(&'1 Struct, &'2 [u8]) -> impl Future<Output = Vec<u8>> + 'static`
+              found signature `fn(&'1 Struct, &'2 [u8]) -> impl Future<Output = Vec<u8>> + '2`
    = help: the lifetime requirements from the `impl` do not correspond to the requirements in the `trait`
    = help: verify the lifetime relationships in the `trait` and `impl` between the `self` argument, the other inputs and its output
 
diff --git a/src/test/ui/impl-trait/in-trait/specialization-broken.stderr b/src/test/ui/impl-trait/in-trait/specialization-broken.stderr
index a30e6346b29..37cfd74498d 100644
--- a/src/test/ui/impl-trait/in-trait/specialization-broken.stderr
+++ b/src/test/ui/impl-trait/in-trait/specialization-broken.stderr
@@ -15,8 +15,8 @@ note: type in trait
    |
 LL |     fn bar(&self) -> impl Sized;
    |                      ^^^^^^^^^^
-   = note: expected fn pointer `fn(&U) -> impl Sized`
-              found fn pointer `fn(&U) -> U`
+   = note: expected signature `fn(&U) -> impl Sized`
+              found signature `fn(&U) -> U`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/impl-trait/issues/issue-92305.stderr b/src/test/ui/impl-trait/issues/issue-92305.stderr
index f09c14d3df1..86d7184da7a 100644
--- a/src/test/ui/impl-trait/issues/issue-92305.stderr
+++ b/src/test/ui/impl-trait/issues/issue-92305.stderr
@@ -7,7 +7,7 @@ LL | fn f<T>(data: &[T]) -> impl Iterator<Item = Vec> {
 help: add missing generic argument
    |
 LL | fn f<T>(data: &[T]) -> impl Iterator<Item = Vec<T>> {
-   |                                             ~~~~~~
+   |                                                +++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr b/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr
index 3ee26f74a78..c7c6ca44012 100644
--- a/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr
+++ b/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr
@@ -18,8 +18,8 @@ LL |         fn eq(&self, _other: &(Foo, i32)) -> bool {
    |                              expected struct `Bar`, found opaque type
    |                              help: change the parameter type to match the trait: `&(a::Bar, i32)`
    |
-   = note: expected fn pointer `fn(&a::Bar, &(a::Bar, i32)) -> _`
-              found fn pointer `fn(&a::Bar, &(a::Foo, i32)) -> _`
+   = note: expected signature `fn(&a::Bar, &(a::Bar, i32)) -> _`
+              found signature `fn(&a::Bar, &(a::Foo, i32)) -> _`
 
 error: unconstrained opaque type
   --> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:18:16
@@ -41,8 +41,8 @@ LL |         fn eq(&self, _other: &(Bar, i32)) -> bool {
    |                              expected opaque type, found struct `Bar`
    |                              help: change the parameter type to match the trait: `&(b::Foo, i32)`
    |
-   = note: expected fn pointer `fn(&b::Bar, &(b::Foo, i32)) -> _`
-              found fn pointer `fn(&b::Bar, &(b::Bar, i32)) -> _`
+   = note: expected signature `fn(&b::Bar, &(b::Foo, i32)) -> _`
+              found signature `fn(&b::Bar, &(b::Bar, i32)) -> _`
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/impl-trait/static-return-lifetime-infered.rs b/src/test/ui/impl-trait/static-return-lifetime-infered.rs
index f940c1949d0..36ef9ea4443 100644
--- a/src/test/ui/impl-trait/static-return-lifetime-infered.rs
+++ b/src/test/ui/impl-trait/static-return-lifetime-infered.rs
@@ -6,12 +6,10 @@ impl A {
     fn iter_values_anon(&self) -> impl Iterator<Item=u32> {
         self.x.iter().map(|a| a.0)
         //~^ ERROR: captures lifetime that does not appear in bounds
-        //~| ERROR: captures lifetime that does not appear in bounds
     }
     fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> {
         self.x.iter().map(|a| a.0)
         //~^ ERROR: captures lifetime that does not appear in bounds
-        //~| ERROR: captures lifetime that does not appear in bounds
     }
 }
 
diff --git a/src/test/ui/impl-trait/static-return-lifetime-infered.stderr b/src/test/ui/impl-trait/static-return-lifetime-infered.stderr
index b365bd88454..c451f8e37c4 100644
--- a/src/test/ui/impl-trait/static-return-lifetime-infered.stderr
+++ b/src/test/ui/impl-trait/static-return-lifetime-infered.stderr
@@ -12,36 +12,10 @@ LL |     fn iter_values_anon(&self) -> impl Iterator<Item=u32> + '_ {
    |                                                           ++++
 
 error[E0700]: hidden type for `impl Iterator<Item = u32>` captures lifetime that does not appear in bounds
-  --> $DIR/static-return-lifetime-infered.rs:7:9
-   |
-LL |     fn iter_values_anon(&self) -> impl Iterator<Item=u32> {
-   |                         ----- hidden type `Map<std::slice::Iter<'_, (u32, u32)>, [closure@$DIR/static-return-lifetime-infered.rs:7:27: 7:30]>` captures the anonymous lifetime defined here
-LL |         self.x.iter().map(|a| a.0)
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-help: to declare that `impl Iterator<Item = u32>` captures `'_`, you can add an explicit `'_` lifetime bound
-   |
-LL |     fn iter_values_anon(&self) -> impl Iterator<Item=u32> + '_ {
-   |                                                           ++++
-
-error[E0700]: hidden type for `impl Iterator<Item = u32>` captures lifetime that does not appear in bounds
-  --> $DIR/static-return-lifetime-infered.rs:12:9
-   |
-LL |     fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> {
-   |                    -- hidden type `Map<std::slice::Iter<'a, (u32, u32)>, [closure@$DIR/static-return-lifetime-infered.rs:12:27: 12:30]>` captures the lifetime `'a` as defined here
-LL |         self.x.iter().map(|a| a.0)
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-help: to declare that `impl Iterator<Item = u32>` captures `'a`, you can add an explicit `'a` lifetime bound
-   |
-LL |     fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> + 'a {
-   |                                                             ++++
-
-error[E0700]: hidden type for `impl Iterator<Item = u32>` captures lifetime that does not appear in bounds
-  --> $DIR/static-return-lifetime-infered.rs:12:9
+  --> $DIR/static-return-lifetime-infered.rs:11:9
    |
 LL |     fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> {
-   |                    -- hidden type `Map<std::slice::Iter<'a, (u32, u32)>, [closure@$DIR/static-return-lifetime-infered.rs:12:27: 12:30]>` captures the lifetime `'a` as defined here
+   |                    -- hidden type `Map<std::slice::Iter<'a, (u32, u32)>, [closure@$DIR/static-return-lifetime-infered.rs:11:27: 11:30]>` captures the lifetime `'a` as defined here
 LL |         self.x.iter().map(|a| a.0)
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
@@ -50,6 +24,6 @@ help: to declare that `impl Iterator<Item = u32>` captures `'a`, you can add an
 LL |     fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> + 'a {
    |                                                             ++++
 
-error: aborting due to 4 previous errors
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0700`.
diff --git a/src/test/ui/impl-trait/trait_type.stderr b/src/test/ui/impl-trait/trait_type.stderr
index bea24339837..81e4c933e53 100644
--- a/src/test/ui/impl-trait/trait_type.stderr
+++ b/src/test/ui/impl-trait/trait_type.stderr
@@ -7,8 +7,8 @@ LL |    fn fmt(&self, x: &str) -> () { }
    |                     types differ in mutability
    |                     help: change the parameter type to match the trait: `&mut Formatter<'_>`
    |
-   = note: expected fn pointer `fn(&MyType, &mut Formatter<'_>) -> Result<(), std::fmt::Error>`
-              found fn pointer `fn(&MyType, &str)`
+   = note: expected signature `fn(&MyType, &mut Formatter<'_>) -> Result<(), std::fmt::Error>`
+              found signature `fn(&MyType, &str)`
 
 error[E0050]: method `fmt` has 1 parameter but the declaration in trait `std::fmt::Display::fmt` has 2
   --> $DIR/trait_type.rs:12:11
diff --git a/src/test/ui/implied-bounds/hrlt-implied-trait-bounds-guard.rs b/src/test/ui/implied-bounds/hrlt-implied-trait-bounds-guard.rs
index 79844dcbdac..c177655c5ac 100644
--- a/src/test/ui/implied-bounds/hrlt-implied-trait-bounds-guard.rs
+++ b/src/test/ui/implied-bounds/hrlt-implied-trait-bounds-guard.rs
@@ -1,5 +1,5 @@
 // A test exploiting the bug behind #25860 except with
-// implied trait bounds which currently don't exist without `-Zchalk`.
+// implied trait bounds which currently don't exist without `-Ztrait-solver=chalk`.
 use std::marker::PhantomData;
 struct Foo<'a, 'b, T>(PhantomData<(&'a (), &'b (), T)>)
 where
diff --git a/src/test/ui/issues/issue-11374.stderr b/src/test/ui/issues/issue-11374.stderr
index 15b2bbeb7c2..ace77814a3a 100644
--- a/src/test/ui/issues/issue-11374.stderr
+++ b/src/test/ui/issues/issue-11374.stderr
@@ -6,7 +6,7 @@ LL |     c.read_to(v);
    |       |       |
    |       |       expected `&mut [u8]`, found struct `Vec`
    |       |       help: consider mutably borrowing here: `&mut v`
-   |       arguments to this function are incorrect
+   |       arguments to this method are incorrect
    |
    = note: expected mutable reference `&mut [u8]`
                          found struct `Vec<_>`
diff --git a/src/test/ui/issues/issue-13033.rs b/src/test/ui/issues/issue-13033.rs
index 7631831a81a..fdb356e70c5 100644
--- a/src/test/ui/issues/issue-13033.rs
+++ b/src/test/ui/issues/issue-13033.rs
@@ -7,8 +7,8 @@ struct Baz;
 impl Foo for Baz {
     fn bar(&mut self, other: &dyn Foo) {}
     //~^ ERROR method `bar` has an incompatible type for trait
-    //~| expected fn pointer `fn(&mut Baz, &mut dyn Foo)`
-    //~| found fn pointer `fn(&mut Baz, &dyn Foo)`
+    //~| expected signature `fn(&mut Baz, &mut dyn Foo)`
+    //~| found signature `fn(&mut Baz, &dyn Foo)`
 }
 
 fn main() {}
diff --git a/src/test/ui/issues/issue-13033.stderr b/src/test/ui/issues/issue-13033.stderr
index 72e549813e8..db2c1189e1e 100644
--- a/src/test/ui/issues/issue-13033.stderr
+++ b/src/test/ui/issues/issue-13033.stderr
@@ -12,8 +12,8 @@ note: type in trait
    |
 LL |     fn bar(&mut self, other: &mut dyn Foo);
    |                              ^^^^^^^^^^^^
-   = note: expected fn pointer `fn(&mut Baz, &mut dyn Foo)`
-              found fn pointer `fn(&mut Baz, &dyn Foo)`
+   = note: expected signature `fn(&mut Baz, &mut dyn Foo)`
+              found signature `fn(&mut Baz, &dyn Foo)`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-14092.stderr b/src/test/ui/issues/issue-14092.stderr
index 132e2b101a5..3a43627e691 100644
--- a/src/test/ui/issues/issue-14092.stderr
+++ b/src/test/ui/issues/issue-14092.stderr
@@ -7,7 +7,7 @@ LL | fn fn1(0: Box) {}
 help: add missing generic argument
    |
 LL | fn fn1(0: Box<T>) {}
-   |           ~~~~~~
+   |              +++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-15094.rs b/src/test/ui/issues/issue-15094.rs
index 71b75a6e7e0..cb27e2bcfb6 100644
--- a/src/test/ui/issues/issue-15094.rs
+++ b/src/test/ui/issues/issue-15094.rs
@@ -10,8 +10,8 @@ impl<T: fmt::Debug> ops::FnOnce<(),> for Debuger<T> {
     type Output = ();
     fn call_once(self, _args: ()) {
     //~^ ERROR `call_once` has an incompatible type for trait
-    //~| expected fn pointer `extern "rust-call" fn
-    //~| found fn pointer `fn
+    //~| expected signature `extern "rust-call" fn
+    //~| found signature `fn
         println!("{:?}", self.x);
     }
 }
diff --git a/src/test/ui/issues/issue-15094.stderr b/src/test/ui/issues/issue-15094.stderr
index 2dcdaba170a..b7c950892dc 100644
--- a/src/test/ui/issues/issue-15094.stderr
+++ b/src/test/ui/issues/issue-15094.stderr
@@ -4,8 +4,8 @@ error[E0053]: method `call_once` has an incompatible type for trait
 LL |     fn call_once(self, _args: ()) {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected "rust-call" fn, found "Rust" fn
    |
-   = note: expected fn pointer `extern "rust-call" fn(Debuger<_>, ())`
-              found fn pointer `fn(Debuger<_>, ())`
+   = note: expected signature `extern "rust-call" fn(Debuger<_>, ())`
+              found signature `fn(Debuger<_>, ())`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-18611.stderr b/src/test/ui/issues/issue-18611.stderr
index 22c3470b61e..bd18d46223e 100644
--- a/src/test/ui/issues/issue-18611.stderr
+++ b/src/test/ui/issues/issue-18611.stderr
@@ -1,10 +1,8 @@
 error[E0277]: the trait bound `isize: HasState` is not satisfied
-  --> $DIR/issue-18611.rs:1:1
+  --> $DIR/issue-18611.rs:1:18
    |
-LL | / fn add_state(op: <isize as HasState>::State) {
-LL | |
-LL | | }
-   | |_^ the trait `HasState` is not implemented for `isize`
+LL | fn add_state(op: <isize as HasState>::State) {
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `HasState` is not implemented for `isize`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-20225.stderr b/src/test/ui/issues/issue-20225.stderr
index 6f4813ca623..5822160107c 100644
--- a/src/test/ui/issues/issue-20225.stderr
+++ b/src/test/ui/issues/issue-20225.stderr
@@ -9,8 +9,8 @@ LL |   extern "rust-call" fn call(&self, (_,): (T,)) {}
    |                                           expected `&T`, found type parameter `T`
    |                                           help: change the parameter type to match the trait: `(&'a T,)`
    |
-   = note: expected fn pointer `extern "rust-call" fn(&Foo, (&'a T,))`
-              found fn pointer `extern "rust-call" fn(&Foo, (T,))`
+   = note: expected signature `extern "rust-call" fn(&Foo, (&'a T,))`
+              found signature `extern "rust-call" fn(&Foo, (T,))`
 
 error[E0053]: method `call_mut` has an incompatible type for trait
   --> $DIR/issue-20225.rs:11:51
@@ -23,8 +23,8 @@ LL |   extern "rust-call" fn call_mut(&mut self, (_,): (T,)) {}
    |                                                   expected `&T`, found type parameter `T`
    |                                                   help: change the parameter type to match the trait: `(&'a T,)`
    |
-   = note: expected fn pointer `extern "rust-call" fn(&mut Foo, (&'a T,))`
-              found fn pointer `extern "rust-call" fn(&mut Foo, (T,))`
+   = note: expected signature `extern "rust-call" fn(&mut Foo, (&'a T,))`
+              found signature `extern "rust-call" fn(&mut Foo, (T,))`
 
 error[E0053]: method `call_once` has an incompatible type for trait
   --> $DIR/issue-20225.rs:18:47
@@ -38,8 +38,8 @@ LL |   extern "rust-call" fn call_once(self, (_,): (T,)) {}
    |                                               expected `&T`, found type parameter `T`
    |                                               help: change the parameter type to match the trait: `(&'a T,)`
    |
-   = note: expected fn pointer `extern "rust-call" fn(Foo, (&'a T,))`
-              found fn pointer `extern "rust-call" fn(Foo, (T,))`
+   = note: expected signature `extern "rust-call" fn(Foo, (&'a T,))`
+              found signature `extern "rust-call" fn(Foo, (T,))`
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/issues/issue-20831-debruijn.stderr b/src/test/ui/issues/issue-20831-debruijn.stderr
index ef62dece836..c3af1f6786b 100644
--- a/src/test/ui/issues/issue-20831-debruijn.stderr
+++ b/src/test/ui/issues/issue-20831-debruijn.stderr
@@ -1,14 +1,8 @@
 error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
-  --> $DIR/issue-20831-debruijn.rs:28:5
+  --> $DIR/issue-20831-debruijn.rs:28:33
    |
-LL | /     fn subscribe(&mut self, t : Box<dyn Subscriber<Input=<Self as Publisher>::Output> + 'a>) {
-LL | |         // Not obvious, but there is an implicit lifetime here -------^
-LL | |
-LL | |         //
-...  |
-LL | |         self.sub = t;
-LL | |     }
-   | |_____^
+LL |     fn subscribe(&mut self, t : Box<dyn Subscriber<Input=<Self as Publisher>::Output> + 'a>) {
+   |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: first, the lifetime cannot outlive the anonymous lifetime defined here...
   --> $DIR/issue-20831-debruijn.rs:28:58
@@ -21,16 +15,10 @@ note: ...but the lifetime must also be valid for the lifetime `'a` as defined he
 LL | impl<'a> Publisher<'a> for MyStruct<'a> {
    |      ^^
 note: ...so that the types are compatible
-  --> $DIR/issue-20831-debruijn.rs:28:5
+  --> $DIR/issue-20831-debruijn.rs:28:33
    |
-LL | /     fn subscribe(&mut self, t : Box<dyn Subscriber<Input=<Self as Publisher>::Output> + 'a>) {
-LL | |         // Not obvious, but there is an implicit lifetime here -------^
-LL | |
-LL | |         //
-...  |
-LL | |         self.sub = t;
-LL | |     }
-   | |_____^
+LL |     fn subscribe(&mut self, t : Box<dyn Subscriber<Input=<Self as Publisher>::Output> + 'a>) {
+   |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: expected `<MyStruct<'a> as Publisher<'_>>`
               found `<MyStruct<'_> as Publisher<'_>>`
 
diff --git a/src/test/ui/issues/issue-21332.stderr b/src/test/ui/issues/issue-21332.stderr
index d92966da17c..0e1beebf293 100644
--- a/src/test/ui/issues/issue-21332.stderr
+++ b/src/test/ui/issues/issue-21332.stderr
@@ -7,8 +7,8 @@ LL |     fn next(&mut self) -> Result<i32, i32> { Ok(7) }
    |                           expected enum `Option`, found enum `Result`
    |                           help: change the output type to match the trait: `Option<i32>`
    |
-   = note: expected fn pointer `fn(&mut S) -> Option<i32>`
-              found fn pointer `fn(&mut S) -> Result<i32, i32>`
+   = note: expected signature `fn(&mut S) -> Option<i32>`
+              found signature `fn(&mut S) -> Result<i32, i32>`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-23024.stderr b/src/test/ui/issues/issue-23024.stderr
index 014eb2897b4..2c325ffccee 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));
 help: add missing generic argument
    |
 LL |     println!("{:?}",(vfnfer[0] as dyn Fn<Args>)(3));
-   |                                       ~~~~~~~~
+   |                                         ++++++
 
 error[E0191]: the value of the associated type `Output` (from trait `FnOnce`) must be specified
   --> $DIR/issue-23024.rs:8:39
diff --git a/src/test/ui/issues/issue-25386.rs b/src/test/ui/issues/issue-25386.rs
index a76d8a615f6..b26cc77680d 100644
--- a/src/test/ui/issues/issue-25386.rs
+++ b/src/test/ui/issues/issue-25386.rs
@@ -24,5 +24,4 @@ macro_rules! check_ptr_exist {
 fn main() {
     let item = stuff::Item::new();
     println!("{}", check_ptr_exist!(item, name));
-    //~^ ERROR field `name` of struct `CObj` is private
 }
diff --git a/src/test/ui/issues/issue-25386.stderr b/src/test/ui/issues/issue-25386.stderr
index bce269393ee..727b9690829 100644
--- a/src/test/ui/issues/issue-25386.stderr
+++ b/src/test/ui/issues/issue-25386.stderr
@@ -9,12 +9,6 @@ LL |     println!("{}", check_ptr_exist!(item, name));
    |
    = note: this error originates in the macro `check_ptr_exist` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error[E0616]: field `name` of struct `CObj` is private
-  --> $DIR/issue-25386.rs:26:43
-   |
-LL |     println!("{}", check_ptr_exist!(item, name));
-   |                                           ^^^^ private field
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0616`.
diff --git a/src/test/ui/issues/issue-25439.stderr b/src/test/ui/issues/issue-25439.stderr
index 325c28c15e2..dadae23fdf3 100644
--- a/src/test/ui/issues/issue-25439.stderr
+++ b/src/test/ui/issues/issue-25439.stderr
@@ -2,12 +2,17 @@ error[E0644]: closure/generator type that references itself
   --> $DIR/issue-25439.rs:8:9
    |
 LL |     fix(|_, x| x);
-   |         ^^^^^^^^ cyclic type of infinite size
+   |         ^^^^^^ cyclic type of infinite size
    |
    = note: closures cannot capture themselves or take themselves as argument;
            this error may be the result of a recent compiler bug-fix,
            see issue #46062 <https://github.com/rust-lang/rust/issues/46062>
            for more information
+note: required by a bound in `fix`
+  --> $DIR/issue-25439.rs:3:33
+   |
+LL | fn fix<F>(f: F) -> i32 where F: Fn(Helper<F>, i32) -> i32 {
+   |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `fix`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-26094.rs b/src/test/ui/issues/issue-26094.rs
index df8c2f73910..d3d670aa92a 100644
--- a/src/test/ui/issues/issue-26094.rs
+++ b/src/test/ui/issues/issue-26094.rs
@@ -8,6 +8,6 @@ fn some_function() {} //~ NOTE defined here
 
 fn main() {
     some_macro!(some_function);
-    //~^ ERROR this function takes 0 arguments but 1 argument was supplied
+    //~^ ERROR function takes 0 arguments but 1 argument was supplied
     //~| NOTE in this expansion of some_macro!
 }
diff --git a/src/test/ui/issues/issue-29723.rs b/src/test/ui/issues/issue-29723.rs
index ce91022f093..399e9ba0df7 100644
--- a/src/test/ui/issues/issue-29723.rs
+++ b/src/test/ui/issues/issue-29723.rs
@@ -1,5 +1,7 @@
 // test for https://github.com/rust-lang/rust/issues/29723
 
+#![feature(if_let_guard)]
+
 fn main() {
     let s = String::new();
     let _s = match 0 {
@@ -11,4 +13,10 @@ fn main() {
             //~^ ERROR use of moved value: `s`
         }
     };
+
+    let s = String::new();
+    let _s = match 0 {
+        0 if let Some(()) = { drop(s); None } => String::from("oops"),
+        _ => s //~ ERROR use of moved value: `s`
+    };
 }
diff --git a/src/test/ui/issues/issue-29723.stderr b/src/test/ui/issues/issue-29723.stderr
index 92ee5cf22b7..044d8a9b5dd 100644
--- a/src/test/ui/issues/issue-29723.stderr
+++ b/src/test/ui/issues/issue-29723.stderr
@@ -1,5 +1,5 @@
 error[E0382]: use of moved value: `s`
-  --> $DIR/issue-29723.rs:10:13
+  --> $DIR/issue-29723.rs:12:13
    |
 LL |     let s = String::new();
    |         - move occurs because `s` has type `String`, which does not implement the `Copy` trait
@@ -15,6 +15,22 @@ help: consider cloning the value if the performance cost is acceptable
 LL |         0 if { drop(s.clone()); false } => String::from("oops"),
    |                      ++++++++
 
-error: aborting due to previous error
+error[E0382]: use of moved value: `s`
+  --> $DIR/issue-29723.rs:20:14
+   |
+LL |     let s = String::new();
+   |         - move occurs because `s` has type `String`, which does not implement the `Copy` trait
+LL |     let _s = match 0 {
+LL |         0 if let Some(()) = { drop(s); None } => String::from("oops"),
+   |                                    - value moved here
+LL |         _ => s
+   |              ^ value used here after move
+   |
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL |         0 if let Some(()) = { drop(s.clone()); None } => String::from("oops"),
+   |                                     ++++++++
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/issues/issue-35570.stderr b/src/test/ui/issues/issue-35570.stderr
index ebc40f6786f..3dc33729d8f 100644
--- a/src/test/ui/issues/issue-35570.stderr
+++ b/src/test/ui/issues/issue-35570.stderr
@@ -1,4 +1,10 @@
 error[E0277]: the trait bound `for<'a> (): Trait2<'a>` is not satisfied
+  --> $DIR/issue-35570.rs:8:40
+   |
+LL | fn _ice(param: Box<dyn for <'a> Trait1<<() as Trait2<'a>>::Ty>>) {
+   |                                        ^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> Trait2<'a>` is not implemented for `()`
+
+error[E0277]: the trait bound `for<'a> (): Trait2<'a>` is not satisfied
   --> $DIR/issue-35570.rs:8:1
    |
 LL | / fn _ice(param: Box<dyn for <'a> Trait1<<() as Trait2<'a>>::Ty>>) {
@@ -8,12 +14,6 @@ LL | |     let _e: (usize, usize) = unsafe{mem::transmute(param)};
 LL | | }
    | |_^ the trait `for<'a> Trait2<'a>` is not implemented for `()`
 
-error[E0277]: the trait bound `for<'a> (): Trait2<'a>` is not satisfied
-  --> $DIR/issue-35570.rs:8:40
-   |
-LL | fn _ice(param: Box<dyn for <'a> Trait1<<() as Trait2<'a>>::Ty>>) {
-   |                                        ^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> Trait2<'a>` is not implemented for `()`
-
 error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/issues/issue-37884.stderr b/src/test/ui/issues/issue-37884.stderr
index e9f50b41f6a..7ddb36c8e6f 100644
--- a/src/test/ui/issues/issue-37884.stderr
+++ b/src/test/ui/issues/issue-37884.stderr
@@ -4,8 +4,8 @@ error[E0308]: method not compatible with trait
 LL |     fn next(&'a mut self) -> Option<Self::Item>
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch
    |
-   = note: expected fn pointer `fn(&mut RepeatMut<'a, T>) -> Option<_>`
-              found fn pointer `fn(&'a mut RepeatMut<'a, T>) -> Option<_>`
+   = note: expected signature `fn(&mut RepeatMut<'a, T>) -> Option<_>`
+              found signature `fn(&'a mut RepeatMut<'a, T>) -> Option<_>`
 note: the anonymous lifetime as defined here...
   --> $DIR/issue-37884.rs:6:5
    |
diff --git a/src/test/ui/issues/issue-48364.stderr b/src/test/ui/issues/issue-48364.stderr
index da3e62e35dc..60bbfc0c6e2 100644
--- a/src/test/ui/issues/issue-48364.stderr
+++ b/src/test/ui/issues/issue-48364.stderr
@@ -4,7 +4,7 @@ error[E0308]: mismatched types
 LL |     b"".starts_with(stringify!(foo))
    |         ----------- ^^^^^^^^^^^^^^^ expected slice `[u8]`, found `str`
    |         |
-   |         arguments to this function are incorrect
+   |         arguments to this method are incorrect
    |
    = note: expected reference `&[u8]`
               found reference `&'static str`
diff --git a/src/test/ui/issues/issue-4935.rs b/src/test/ui/issues/issue-4935.rs
index b342bbb1b8e..c95020a0c00 100644
--- a/src/test/ui/issues/issue-4935.rs
+++ b/src/test/ui/issues/issue-4935.rs
@@ -3,4 +3,4 @@
 fn foo(a: usize) {}
 //~^ defined here
 fn main() { foo(5, 6) }
-//~^ ERROR this function takes 1 argument but 2 arguments were supplied
+//~^ ERROR function takes 1 argument but 2 arguments were supplied
diff --git a/src/test/ui/issues/issue-86756.stderr b/src/test/ui/issues/issue-86756.stderr
index 693cfecedc4..6c5917bdf6e 100644
--- a/src/test/ui/issues/issue-86756.stderr
+++ b/src/test/ui/issues/issue-86756.stderr
@@ -42,7 +42,7 @@ LL | trait Foo<T, T = T> {}
 help: add missing generic argument
    |
 LL |     eq::<dyn, Foo<T>>
-   |               ~~~~~~
+   |                  +++
 
 error: aborting due to 3 previous errors; 1 warning emitted
 
diff --git a/src/test/ui/layout/thin-meta-implies-thin-ptr.rs b/src/test/ui/layout/thin-meta-implies-thin-ptr.rs
new file mode 100644
index 00000000000..972579ea8be
--- /dev/null
+++ b/src/test/ui/layout/thin-meta-implies-thin-ptr.rs
@@ -0,0 +1,11 @@
+// check-pass
+
+#![feature(ptr_metadata)]
+
+use std::ptr::Thin;
+
+fn main() {}
+
+fn foo<T: ?Sized + Thin>(t: *const T) -> *const () {
+    unsafe { std::mem::transmute(t) }
+}
diff --git a/src/test/ui/lexer/error-stage.stderr b/src/test/ui/lexer/error-stage.stderr
index 697a7c28da1..ecbdb14dc86 100644
--- a/src/test/ui/lexer/error-stage.stderr
+++ b/src/test/ui/lexer/error-stage.stderr
@@ -49,6 +49,8 @@ error: integer literal is too large
    |
 LL |     999340282366920938463463374607431768211455999;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: value exceeds limit of `340282366920938463463374607431768211455`
 
 error: aborting due to 8 previous errors
 
diff --git a/src/test/ui/lexer/lex-bad-numeric-literals.rs b/src/test/ui/lexer/lex-bad-numeric-literals.rs
index cf8440ca488..56bdc50e40d 100644
--- a/src/test/ui/lexer/lex-bad-numeric-literals.rs
+++ b/src/test/ui/lexer/lex-bad-numeric-literals.rs
@@ -1,3 +1,5 @@
+// ignore-tidy-linelength
+
 fn main() {
     0o1.0; //~ ERROR: octal float literal is not supported
     0o2f32; //~ ERROR: octal float literal is not supported
@@ -15,6 +17,12 @@ fn main() {
     //~^ ERROR: integer literal is too large
     9900000000000000000000000000999999999999999999999999999999;
     //~^ ERROR: integer literal is too large
+    0b111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111110;
+    //~^ ERROR: integer literal is too large
+    0o37777777777777777777777777777777777777777770;
+    //~^ ERROR: integer literal is too large
+    0xffffffffffffffffffffffffffffffff0;
+    //~^ ERROR: integer literal is too large
     0x; //~ ERROR: no valid digits
     0xu32; //~ ERROR: no valid digits
     0ou32; //~ ERROR: no valid digits
diff --git a/src/test/ui/lexer/lex-bad-numeric-literals.stderr b/src/test/ui/lexer/lex-bad-numeric-literals.stderr
index f05d6160302..1457541970a 100644
--- a/src/test/ui/lexer/lex-bad-numeric-literals.stderr
+++ b/src/test/ui/lexer/lex-bad-numeric-literals.stderr
@@ -1,141 +1,169 @@
 error: octal float literal is not supported
-  --> $DIR/lex-bad-numeric-literals.rs:2:5
+  --> $DIR/lex-bad-numeric-literals.rs:4:5
    |
 LL |     0o1.0;
    |     ^^^^^
 
 error: octal float literal is not supported
-  --> $DIR/lex-bad-numeric-literals.rs:4:5
+  --> $DIR/lex-bad-numeric-literals.rs:6:5
    |
 LL |     0o3.0f32;
    |     ^^^^^
 
 error: octal float literal is not supported
-  --> $DIR/lex-bad-numeric-literals.rs:5:5
+  --> $DIR/lex-bad-numeric-literals.rs:7:5
    |
 LL |     0o4e4;
    |     ^^^^^
 
 error: octal float literal is not supported
-  --> $DIR/lex-bad-numeric-literals.rs:6:5
+  --> $DIR/lex-bad-numeric-literals.rs:8:5
    |
 LL |     0o5.0e5;
    |     ^^^^^^^
 
 error: octal float literal is not supported
-  --> $DIR/lex-bad-numeric-literals.rs:7:5
+  --> $DIR/lex-bad-numeric-literals.rs:9:5
    |
 LL |     0o6e6f32;
    |     ^^^^^
 
 error: octal float literal is not supported
-  --> $DIR/lex-bad-numeric-literals.rs:8:5
+  --> $DIR/lex-bad-numeric-literals.rs:10:5
    |
 LL |     0o7.0e7f64;
    |     ^^^^^^^
 
 error: hexadecimal float literal is not supported
-  --> $DIR/lex-bad-numeric-literals.rs:9:5
+  --> $DIR/lex-bad-numeric-literals.rs:11:5
    |
 LL |     0x8.0e+9;
    |     ^^^^^^^^
 
 error: hexadecimal float literal is not supported
-  --> $DIR/lex-bad-numeric-literals.rs:10:5
+  --> $DIR/lex-bad-numeric-literals.rs:12:5
    |
 LL |     0x9.0e-9;
    |     ^^^^^^^^
 
 error[E0768]: no valid digits found for number
-  --> $DIR/lex-bad-numeric-literals.rs:11:5
+  --> $DIR/lex-bad-numeric-literals.rs:13:5
    |
 LL |     0o;
    |     ^^
 
 error: expected at least one digit in exponent
-  --> $DIR/lex-bad-numeric-literals.rs:12:5
+  --> $DIR/lex-bad-numeric-literals.rs:14:5
    |
 LL |     1e+;
    |     ^^^
 
 error: hexadecimal float literal is not supported
-  --> $DIR/lex-bad-numeric-literals.rs:13:5
+  --> $DIR/lex-bad-numeric-literals.rs:15:5
    |
 LL |     0x539.0;
    |     ^^^^^^^
 
 error[E0768]: no valid digits found for number
-  --> $DIR/lex-bad-numeric-literals.rs:18:5
+  --> $DIR/lex-bad-numeric-literals.rs:26:5
    |
 LL |     0x;
    |     ^^
 
 error[E0768]: no valid digits found for number
-  --> $DIR/lex-bad-numeric-literals.rs:19:5
+  --> $DIR/lex-bad-numeric-literals.rs:27:5
    |
 LL |     0xu32;
    |     ^^
 
 error[E0768]: no valid digits found for number
-  --> $DIR/lex-bad-numeric-literals.rs:20:5
+  --> $DIR/lex-bad-numeric-literals.rs:28:5
    |
 LL |     0ou32;
    |     ^^
 
 error[E0768]: no valid digits found for number
-  --> $DIR/lex-bad-numeric-literals.rs:21:5
+  --> $DIR/lex-bad-numeric-literals.rs:29:5
    |
 LL |     0bu32;
    |     ^^
 
 error[E0768]: no valid digits found for number
-  --> $DIR/lex-bad-numeric-literals.rs:22:5
+  --> $DIR/lex-bad-numeric-literals.rs:30:5
    |
 LL |     0b;
    |     ^^
 
 error: octal float literal is not supported
-  --> $DIR/lex-bad-numeric-literals.rs:24:5
+  --> $DIR/lex-bad-numeric-literals.rs:32:5
    |
 LL |     0o123.456;
    |     ^^^^^^^^^
 
 error: binary float literal is not supported
-  --> $DIR/lex-bad-numeric-literals.rs:26:5
+  --> $DIR/lex-bad-numeric-literals.rs:34:5
    |
 LL |     0b111.101;
    |     ^^^^^^^^^
 
 error: octal float literal is not supported
-  --> $DIR/lex-bad-numeric-literals.rs:3:5
+  --> $DIR/lex-bad-numeric-literals.rs:5:5
    |
 LL |     0o2f32;
    |     ^^^^^^ not supported
 
 error: integer literal is too large
-  --> $DIR/lex-bad-numeric-literals.rs:14:5
+  --> $DIR/lex-bad-numeric-literals.rs:16:5
    |
 LL |     9900000000000000000000000000999999999999999999999999999999;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: value exceeds limit of `340282366920938463463374607431768211455`
 
 error: integer literal is too large
-  --> $DIR/lex-bad-numeric-literals.rs:16:5
+  --> $DIR/lex-bad-numeric-literals.rs:18:5
    |
 LL |     9900000000000000000000000000999999999999999999999999999999;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: value exceeds limit of `340282366920938463463374607431768211455`
+
+error: integer literal is too large
+  --> $DIR/lex-bad-numeric-literals.rs:20:5
+   |
+LL |     0b111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111110;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: value exceeds limit of `0b11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111`
+
+error: integer literal is too large
+  --> $DIR/lex-bad-numeric-literals.rs:22:5
+   |
+LL |     0o37777777777777777777777777777777777777777770;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: value exceeds limit of `0o3777777777777777777777777777777777777777777`
+
+error: integer literal is too large
+  --> $DIR/lex-bad-numeric-literals.rs:24:5
+   |
+LL |     0xffffffffffffffffffffffffffffffff0;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: value exceeds limit of `0xffffffffffffffffffffffffffffffff`
 
 error: octal float literal is not supported
-  --> $DIR/lex-bad-numeric-literals.rs:23:5
+  --> $DIR/lex-bad-numeric-literals.rs:31:5
    |
 LL |     0o123f64;
    |     ^^^^^^^^ not supported
 
 error: binary float literal is not supported
-  --> $DIR/lex-bad-numeric-literals.rs:25:5
+  --> $DIR/lex-bad-numeric-literals.rs:33:5
    |
 LL |     0b101f64;
    |     ^^^^^^^^ not supported
 
-error: aborting due to 23 previous errors
+error: aborting due to 26 previous errors
 
 For more information about this error, try `rustc --explain E0768`.
diff --git a/src/test/ui/lifetimes/issue-105227.fixed b/src/test/ui/lifetimes/issue-105227.fixed
new file mode 100644
index 00000000000..f6ed9c82e91
--- /dev/null
+++ b/src/test/ui/lifetimes/issue-105227.fixed
@@ -0,0 +1,26 @@
+// Regression test for issue #105227.
+
+// run-rustfix
+#![allow(warnings)]
+fn chars0<'a>(v :(&'a  str, &'a str)) -> impl Iterator<Item = char> + 'a  {
+//~^ HELP to declare that `impl Iterator<Item = char>` captures `'_`, you can introduce a named lifetime parameter `'a`
+    v.0.chars().chain(v.1.chars())
+    //~^ ERROR hidden type for `impl Iterator<Item = char>` captures lifetime that does not appear in bounds
+}
+
+fn chars1<'a>(v0 : &'a  str, v1 : &'a str) -> impl Iterator<Item = char> + 'a  {
+//~^ HELP to declare that `impl Iterator<Item = char>` captures `'_`, you can introduce a named lifetime parameter `'a`
+    v0.chars().chain(v1.chars())
+    //~^ ERROR hidden type for `impl Iterator<Item = char>` captures lifetime that does not appear in bound
+}
+
+fn chars2<'b>(v0 : &'b str, v1 : &'b str, v2 : &'b str) ->
+//~^ HELP to declare that `impl Iterator<Item = char>` captures `'_`, you can use the named lifetime parameter `'b`
+    (impl Iterator<Item = char> + 'b , &'b str)
+{
+    (v0.chars().chain(v1.chars()), v2)
+    //~^ ERROR hidden type for `impl Iterator<Item = char>` captures lifetime that does not appear in bound
+}
+
+fn main() {
+}
diff --git a/src/test/ui/lifetimes/issue-105227.rs b/src/test/ui/lifetimes/issue-105227.rs
new file mode 100644
index 00000000000..6427a50bb87
--- /dev/null
+++ b/src/test/ui/lifetimes/issue-105227.rs
@@ -0,0 +1,26 @@
+// Regression test for issue #105227.
+
+// run-rustfix
+#![allow(warnings)]
+fn chars0(v :(& str, &str)) -> impl Iterator<Item = char> {
+//~^ HELP to declare that `impl Iterator<Item = char>` captures `'_`, you can introduce a named lifetime parameter `'a`
+    v.0.chars().chain(v.1.chars())
+    //~^ ERROR hidden type for `impl Iterator<Item = char>` captures lifetime that does not appear in bounds
+}
+
+fn chars1(v0 : & str, v1 : &str) -> impl Iterator<Item = char> {
+//~^ HELP to declare that `impl Iterator<Item = char>` captures `'_`, you can introduce a named lifetime parameter `'a`
+    v0.chars().chain(v1.chars())
+    //~^ ERROR hidden type for `impl Iterator<Item = char>` captures lifetime that does not appear in bound
+}
+
+fn chars2<'b>(v0 : &str, v1 : &'_ str, v2 : &'b str) ->
+//~^ HELP to declare that `impl Iterator<Item = char>` captures `'_`, you can use the named lifetime parameter `'b`
+    (impl Iterator<Item = char>, &'b str)
+{
+    (v0.chars().chain(v1.chars()), v2)
+    //~^ ERROR hidden type for `impl Iterator<Item = char>` captures lifetime that does not appear in bound
+}
+
+fn main() {
+}
diff --git a/src/test/ui/lifetimes/issue-105227.stderr b/src/test/ui/lifetimes/issue-105227.stderr
new file mode 100644
index 00000000000..d2114593735
--- /dev/null
+++ b/src/test/ui/lifetimes/issue-105227.stderr
@@ -0,0 +1,47 @@
+error[E0700]: hidden type for `impl Iterator<Item = char>` captures lifetime that does not appear in bounds
+  --> $DIR/issue-105227.rs:7:5
+   |
+LL | fn chars0(v :(& str, &str)) -> impl Iterator<Item = char> {
+   |               ----- hidden type `std::iter::Chain<Chars<'_>, Chars<'_>>` captures the anonymous lifetime defined here
+LL |
+LL |     v.0.chars().chain(v.1.chars())
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: to declare that `impl Iterator<Item = char>` captures `'_`, you can introduce a named lifetime parameter `'a`
+   |
+LL | fn chars0<'a>(v :(&'a  str, &'a str)) -> impl Iterator<Item = char> + 'a  {
+   |          ++++      ++        ++                                     ++++
+
+error[E0700]: hidden type for `impl Iterator<Item = char>` captures lifetime that does not appear in bounds
+  --> $DIR/issue-105227.rs:13:5
+   |
+LL | fn chars1(v0 : & str, v1 : &str) -> impl Iterator<Item = char> {
+   |                ----- hidden type `std::iter::Chain<Chars<'_>, Chars<'_>>` captures the anonymous lifetime defined here
+LL |
+LL |     v0.chars().chain(v1.chars())
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: to declare that `impl Iterator<Item = char>` captures `'_`, you can introduce a named lifetime parameter `'a`
+   |
+LL | fn chars1<'a>(v0 : &'a  str, v1 : &'a str) -> impl Iterator<Item = char> + 'a  {
+   |          ++++       ++             ++                                    ++++
+
+error[E0700]: hidden type for `impl Iterator<Item = char>` captures lifetime that does not appear in bounds
+  --> $DIR/issue-105227.rs:21:5
+   |
+LL | fn chars2<'b>(v0 : &str, v1 : &'_ str, v2 : &'b str) ->
+   |                    ---- hidden type `std::iter::Chain<Chars<'_>, Chars<'_>>` captures the anonymous lifetime defined here
+...
+LL |     (v0.chars().chain(v1.chars()), v2)
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: to declare that `impl Iterator<Item = char>` captures `'_`, you can use the named lifetime parameter `'b`
+   |
+LL ~ fn chars2<'b>(v0 : &'b str, v1 : &'b str, v2 : &'b str) ->
+LL |
+LL ~     (impl Iterator<Item = char> + 'b , &'b str)
+   |
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0700`.
diff --git a/src/test/ui/lifetimes/issue-26638.rs b/src/test/ui/lifetimes/issue-26638.rs
index 000ab6492bb..4bec3b3415b 100644
--- a/src/test/ui/lifetimes/issue-26638.rs
+++ b/src/test/ui/lifetimes/issue-26638.rs
@@ -5,7 +5,7 @@ fn parse_type(iter: Box<dyn Iterator<Item=&str>+'static>) -> &str { iter.next()
 fn parse_type_2(iter: fn(&u8)->&u8) -> &str { iter() }
 //~^ ERROR missing lifetime specifier [E0106]
 //~| ERROR mismatched types
-//~| ERROR this function takes 1 argument but 0 arguments were supplied
+//~| ERROR function takes 1 argument but 0 arguments were supplied
 
 fn parse_type_3() -> &str { unimplemented!() }
 //~^ ERROR missing lifetime specifier [E0106]
diff --git a/src/test/ui/lifetimes/lifetime-mismatch-between-trait-and-impl.stderr b/src/test/ui/lifetimes/lifetime-mismatch-between-trait-and-impl.stderr
index 3040a8512ce..9c61d5a0c25 100644
--- a/src/test/ui/lifetimes/lifetime-mismatch-between-trait-and-impl.stderr
+++ b/src/test/ui/lifetimes/lifetime-mismatch-between-trait-and-impl.stderr
@@ -7,8 +7,8 @@ LL |     fn foo<'a>(x: &i32, y: &'a i32) -> &'a i32;
 LL |     fn foo<'a>(x: &'a i32, y: &'a i32) -> &'a i32 {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found `fn(&'1 i32, &'1 i32) -> &'1 i32`
    |
-   = note: expected `fn(&'1 i32, &'a i32) -> &'a i32`
-              found `fn(&'1 i32, &'1 i32) -> &'1 i32`
+   = note: expected signature `fn(&'1 i32, &'a i32) -> &'a i32`
+              found signature `fn(&'1 i32, &'1 i32) -> &'1 i32`
    = help: the lifetime requirements from the `impl` do not correspond to the requirements in the `trait`
    = help: verify the lifetime relationships in the `trait` and `impl` between the `self` argument, the other inputs and its output
 
diff --git a/src/test/ui/lifetimes/missing-lifetime-in-alias.stderr b/src/test/ui/lifetimes/missing-lifetime-in-alias.stderr
index 428b8f14b6f..20159e14407 100644
--- a/src/test/ui/lifetimes/missing-lifetime-in-alias.stderr
+++ b/src/test/ui/lifetimes/missing-lifetime-in-alias.stderr
@@ -39,7 +39,7 @@ LL |     type Bar<'b>
 help: add missing lifetime argument
    |
 LL | type C<'a, 'b> = <A<'a> as Trait>::Bar<'a>;
-   |                                    ~~~~~~~
+   |                                       ++++
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/macros/format-foreign.stderr b/src/test/ui/macros/format-foreign.stderr
index ff5236dc949..7971c2ab2b9 100644
--- a/src/test/ui/macros/format-foreign.stderr
+++ b/src/test/ui/macros/format-foreign.stderr
@@ -8,7 +8,7 @@ LL |     println!("%.*3$s %s!\n", "Hello,", "World", 4);
    |              |               argument never used
    |              multiple missing formatting specifiers
    |
-   = note: printf formatting not supported; see the documentation for `std::fmt`
+   = note: printf formatting is not supported; see the documentation for `std::fmt`
 help: format specifiers use curly braces
    |
 LL |     println!("{:.2$} {}!\n", "Hello,", "World", 4);
@@ -22,7 +22,7 @@ LL |     println!("%1$*2$.*3$f", 123.456);
    |               |
    |               help: format specifiers use curly braces: `{0:1$.2$}`
    |
-   = note: printf formatting not supported; see the documentation for `std::fmt`
+   = note: printf formatting is not supported; see the documentation for `std::fmt`
 
 error: multiple unused formatting arguments
   --> $DIR/format-foreign.rs:6:7
@@ -37,7 +37,7 @@ LL | | "###, "Hello,", "World", 4);
    | |____|  argument never used
    |      multiple missing formatting specifiers
    |
-   = note: printf formatting not supported; see the documentation for `std::fmt`
+   = note: printf formatting is not supported; see the documentation for `std::fmt`
 help: format specifiers use curly braces
    |
 LL ~     println!(r###"{:.2$}
@@ -60,7 +60,7 @@ LL |     println!("Hi there, $NAME.", NAME="Tim");
    |                         |
    |                         help: format specifiers use curly braces: `{NAME}`
    |
-   = note: shell formatting not supported; see the documentation for `std::fmt`
+   = note: shell formatting is not supported; see the documentation for `std::fmt`
 
 error: multiple unused formatting arguments
   --> $DIR/format-foreign.rs:15:32
@@ -72,7 +72,7 @@ LL |     println!("$1 $0 $$ $NAME", 1, 2, NAME=3);
    |              |                 argument never used
    |              multiple missing formatting specifiers
    |
-   = note: shell formatting not supported; see the documentation for `std::fmt`
+   = note: shell formatting is not supported; see the documentation for `std::fmt`
 help: format specifiers use curly braces
    |
 LL |     println!("{1} {0} $$ {NAME}", 1, 2, NAME=3);
diff --git a/src/test/ui/macros/format-unused-lables.stderr b/src/test/ui/macros/format-unused-lables.stderr
index 7423c7b7c8b..fad87fa2aee 100644
--- a/src/test/ui/macros/format-unused-lables.stderr
+++ b/src/test/ui/macros/format-unused-lables.stderr
@@ -44,7 +44,7 @@ LL |        "things"
 LL |              , UNUSED="args");
    |                       ^^^^^^ named argument never used
    |
-   = note: shell formatting not supported; see the documentation for `std::fmt`
+   = note: shell formatting is not supported; see the documentation for `std::fmt`
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/macros/issue-104769-concat_bytes-invalid-literal.stderr b/src/test/ui/macros/issue-104769-concat_bytes-invalid-literal.stderr
index 8d70faa494d..8807279c27f 100644
--- a/src/test/ui/macros/issue-104769-concat_bytes-invalid-literal.stderr
+++ b/src/test/ui/macros/issue-104769-concat_bytes-invalid-literal.stderr
@@ -11,6 +11,8 @@ error: integer literal is too large
    |
 LL |     concat_bytes!(888888888888888888888888888888888888888);
    |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: value exceeds limit of `340282366920938463463374607431768211455`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/issues/issue-10536.rs b/src/test/ui/macros/issue-10536.rs
index f536d8f940a..f536d8f940a 100644
--- a/src/test/ui/issues/issue-10536.rs
+++ b/src/test/ui/macros/issue-10536.rs
diff --git a/src/test/ui/issues/issue-10536.stderr b/src/test/ui/macros/issue-10536.stderr
index cc048445871..cc048445871 100644
--- a/src/test/ui/issues/issue-10536.stderr
+++ b/src/test/ui/macros/issue-10536.stderr
diff --git a/src/test/ui/macros/issue-92267.stderr b/src/test/ui/macros/issue-92267.stderr
index d2d66c81198..5359f68cd55 100644
--- a/src/test/ui/macros/issue-92267.stderr
+++ b/src/test/ui/macros/issue-92267.stderr
@@ -10,7 +10,7 @@ note: format specifiers use curly braces, and the conversion specifier `
    |
 LL | pub fn main() { println!("🦀%%%", 0) }
    |                               ^^
-   = note: printf formatting not supported; see the documentation for `std::fmt`
+   = note: printf formatting is not supported; see the documentation for `std::fmt`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/methods/issues/issue-61525.stderr b/src/test/ui/methods/issues/issue-61525.stderr
index aec968d7c44..3e73b950a14 100644
--- a/src/test/ui/methods/issues/issue-61525.stderr
+++ b/src/test/ui/methods/issues/issue-61525.stderr
@@ -23,7 +23,7 @@ error[E0308]: mismatched types
 LL |         1.query::<dyn ToString>("")
    |           --------------------- ^^ expected trait object `dyn ToString`, found `&str`
    |           |
-   |           arguments to this function are incorrect
+   |           arguments to this method are incorrect
    |
    = note: expected trait object `dyn ToString`
                  found reference `&'static str`
diff --git a/src/test/ui/methods/method-call-err-msg.rs b/src/test/ui/methods/method-call-err-msg.rs
index d53ef445afc..4807a956aa2 100644
--- a/src/test/ui/methods/method-call-err-msg.rs
+++ b/src/test/ui/methods/method-call-err-msg.rs
@@ -10,13 +10,13 @@ impl Foo {
 
 fn main() {
     let x = Foo;
-    x.zero(0)   //~ ERROR this function takes 0 arguments but 1 argument was supplied
-     .one()     //~ ERROR this function takes 1 argument but 0 arguments were supplied
-     .two(0);   //~ ERROR this function takes 2 arguments but 1 argument was supplied
+    x.zero(0)   //~ ERROR this method takes 0 arguments but 1 argument was supplied
+     .one()     //~ ERROR this method takes 1 argument but 0 arguments were supplied
+     .two(0);   //~ ERROR this method takes 2 arguments but 1 argument was supplied
 
     let y = Foo;
     y.zero()
      .take()    //~ ERROR not an iterator
      .one(0);
-    y.three::<usize>(); //~ ERROR this function takes 3 arguments but 0 arguments were supplied
+    y.three::<usize>(); //~ ERROR this method takes 3 arguments but 0 arguments were supplied
 }
diff --git a/src/test/ui/methods/method-call-err-msg.stderr b/src/test/ui/methods/method-call-err-msg.stderr
index 3f4e647491e..81269b73b9a 100644
--- a/src/test/ui/methods/method-call-err-msg.stderr
+++ b/src/test/ui/methods/method-call-err-msg.stderr
@@ -1,4 +1,4 @@
-error[E0061]: this function takes 0 arguments but 1 argument was supplied
+error[E0061]: this method takes 0 arguments but 1 argument was supplied
   --> $DIR/method-call-err-msg.rs:13:7
    |
 LL |     x.zero(0)
@@ -14,7 +14,7 @@ help: remove the extra argument
 LL |     x.zero()
    |           ~~
 
-error[E0061]: this function takes 1 argument but 0 arguments were supplied
+error[E0061]: this method takes 1 argument but 0 arguments were supplied
   --> $DIR/method-call-err-msg.rs:14:7
    |
 LL |      .one()
@@ -30,7 +30,7 @@ help: provide the argument
 LL |      .one(/* isize */)
    |          ~~~~~~~~~~~~~
 
-error[E0061]: this function takes 2 arguments but 1 argument was supplied
+error[E0061]: this method takes 2 arguments but 1 argument was supplied
   --> $DIR/method-call-err-msg.rs:15:7
    |
 LL |      .two(0);
@@ -67,7 +67,7 @@ note: the trait `Iterator` must be implemented
    = note: the following trait defines an item `take`, perhaps you need to implement it:
            candidate #1: `Iterator`
 
-error[E0061]: this function takes 3 arguments but 0 arguments were supplied
+error[E0061]: this method takes 3 arguments but 0 arguments were supplied
   --> $DIR/method-call-err-msg.rs:21:7
    |
 LL |     y.three::<usize>();
diff --git a/src/test/ui/mismatched_types/E0053.stderr b/src/test/ui/mismatched_types/E0053.stderr
index 54b41926451..154f2fcbee0 100644
--- a/src/test/ui/mismatched_types/E0053.stderr
+++ b/src/test/ui/mismatched_types/E0053.stderr
@@ -12,8 +12,8 @@ note: type in trait
    |
 LL |     fn foo(x: u16);
    |               ^^^
-   = note: expected fn pointer `fn(u16)`
-              found fn pointer `fn(i16)`
+   = note: expected signature `fn(u16)`
+              found signature `fn(i16)`
 
 error[E0053]: method `bar` has an incompatible type for trait
   --> $DIR/E0053.rs:11:12
@@ -29,8 +29,8 @@ note: type in trait
    |
 LL |     fn bar(&self);
    |            ^^^^^
-   = note: expected fn pointer `fn(&Bar)`
-              found fn pointer `fn(&mut Bar)`
+   = note: expected signature `fn(&Bar)`
+              found signature `fn(&mut Bar)`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/mismatched_types/issue-74918-missing-lifetime.stderr b/src/test/ui/mismatched_types/issue-74918-missing-lifetime.stderr
index b75c7a99fdd..9ddea162944 100644
--- a/src/test/ui/mismatched_types/issue-74918-missing-lifetime.stderr
+++ b/src/test/ui/mismatched_types/issue-74918-missing-lifetime.stderr
@@ -18,8 +18,8 @@ LL |     fn next(&mut self) -> Option<IteratorChunk<T, S>> {
    |
    = note: expected `fn(&'1 mut ChunkingIterator<T, S>) -> Option<IteratorChunk<'static, T, S>>`
    |
-   = note: expected `fn(&'1 mut ChunkingIterator<T, S>) -> Option<IteratorChunk<'static, T, S>>`
-              found `fn(&'1 mut ChunkingIterator<T, S>) -> Option<IteratorChunk<'1, T, S>>`
+   = note: expected signature `fn(&'1 mut ChunkingIterator<T, S>) -> Option<IteratorChunk<'static, T, S>>`
+              found signature `fn(&'1 mut ChunkingIterator<T, S>) -> Option<IteratorChunk<'1, T, S>>`
    = help: the lifetime requirements from the `impl` do not correspond to the requirements in the `trait`
    = help: verify the lifetime relationships in the `trait` and `impl` between the `self` argument, the other inputs and its output
 
diff --git a/src/test/ui/mismatched_types/issue-75361-mismatched-impl.stderr b/src/test/ui/mismatched_types/issue-75361-mismatched-impl.stderr
index 2a2c23c9421..88416ba4bb6 100644
--- a/src/test/ui/mismatched_types/issue-75361-mismatched-impl.stderr
+++ b/src/test/ui/mismatched_types/issue-75361-mismatched-impl.stderr
@@ -7,8 +7,8 @@ LL |   fn adjacent_edges(&self) -> Box<dyn MyTrait<Item = &Self::EdgeType>>;
 LL |   fn adjacent_edges(&self) -> Box<dyn MyTrait<Item = &Self::EdgeType> + '_> {
    |   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found `fn(&'1 T) -> Box<(dyn MyTrait<Item = &'1 T> + '1)>`
    |
-   = note: expected `fn(&'1 T) -> Box<(dyn MyTrait<Item = &'1 T> + 'static)>`
-              found `fn(&'1 T) -> Box<(dyn MyTrait<Item = &'1 T> + '1)>`
+   = note: expected signature `fn(&'1 T) -> Box<(dyn MyTrait<Item = &'1 T> + 'static)>`
+              found signature `fn(&'1 T) -> Box<(dyn MyTrait<Item = &'1 T> + '1)>`
 help: the lifetime requirements from the `impl` do not correspond to the requirements in the `trait`
   --> $DIR/issue-75361-mismatched-impl.rs:12:55
    |
diff --git a/src/test/ui/mismatched_types/overloaded-calls-bad.rs b/src/test/ui/mismatched_types/overloaded-calls-bad.rs
index 232cd2ba88c..5b1804d825d 100644
--- a/src/test/ui/mismatched_types/overloaded-calls-bad.rs
+++ b/src/test/ui/mismatched_types/overloaded-calls-bad.rs
@@ -33,9 +33,9 @@ fn main() {
     let ans = s("what");
     //~^ ERROR mismatched types
     let ans = s();
-    //~^ ERROR this function takes 1 argument but 0 arguments were supplied
+    //~^ ERROR function takes 1 argument but 0 arguments were supplied
     let ans = s("burma", "shave");
-    //~^ ERROR this function takes 1 argument but 2 arguments were supplied
+    //~^ ERROR function takes 1 argument but 2 arguments were supplied
 
     F("");
     //~^ ERROR mismatched types
diff --git a/src/test/ui/mismatched_types/trait-impl-fn-incompatibility.stderr b/src/test/ui/mismatched_types/trait-impl-fn-incompatibility.stderr
index 6b2ba53daa0..6e7bf5eb46d 100644
--- a/src/test/ui/mismatched_types/trait-impl-fn-incompatibility.stderr
+++ b/src/test/ui/mismatched_types/trait-impl-fn-incompatibility.stderr
@@ -12,8 +12,8 @@ note: type in trait
    |
 LL |     fn foo(x: u16);
    |               ^^^
-   = note: expected fn pointer `fn(u16)`
-              found fn pointer `fn(i16)`
+   = note: expected signature `fn(u16)`
+              found signature `fn(i16)`
 
 error[E0053]: method `bar` has an incompatible type for trait
   --> $DIR/trait-impl-fn-incompatibility.rs:10:28
@@ -29,8 +29,8 @@ note: type in trait
    |
 LL |     fn bar(&mut self, bar: &mut Bar);
    |                            ^^^^^^^^
-   = note: expected fn pointer `fn(&mut Bar, &mut Bar)`
-              found fn pointer `fn(&mut Bar, &Bar)`
+   = note: expected signature `fn(&mut Bar, &mut Bar)`
+              found signature `fn(&mut Bar, &Bar)`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/nll/issue-24535-allow-mutable-borrow-in-match-guard.rs b/src/test/ui/nll/issue-24535-allow-mutable-borrow-in-match-guard.rs
index 7253d35ed2d..ccfc8937fd7 100644
--- a/src/test/ui/nll/issue-24535-allow-mutable-borrow-in-match-guard.rs
+++ b/src/test/ui/nll/issue-24535-allow-mutable-borrow-in-match-guard.rs
@@ -5,6 +5,8 @@
 // See further discussion on rust-lang/rust#24535,
 // rust-lang/rfcs#1006, and rust-lang/rfcs#107
 
+#![feature(if_let_guard)]
+
 fn main() {
     rust_issue_24535();
     rfcs_issue_1006_1();
@@ -23,6 +25,12 @@ fn rust_issue_24535() {
         3 if compare(&a, &mut 3) => (),
         _ => panic!("nope"),
     }
+
+    match a {
+        0 => panic!("nope"),
+        3 if let true = compare(&a, &mut 3) => (),
+        _ => panic!("nope"),
+    }
 }
 
 fn rfcs_issue_1006_1() {
diff --git a/src/test/ui/nll/issue-27282-move-match-input-into-guard.rs b/src/test/ui/nll/issue-27282-move-match-input-into-guard.rs
index 4109c10e2e4..85feda5824b 100644
--- a/src/test/ui/nll/issue-27282-move-match-input-into-guard.rs
+++ b/src/test/ui/nll/issue-27282-move-match-input-into-guard.rs
@@ -7,6 +7,8 @@
 // reaches the panic code when executed, despite the compiler warning
 // about that match arm being unreachable.
 
+#![feature(if_let_guard)]
+
 fn main() {
     let b = &mut true;
     match b {
@@ -17,4 +19,16 @@ fn main() {
         &mut true => { println!("You might think we should get here"); },
         _ => panic!("surely we could never get here, since rustc warns it is unreachable."),
     }
+
+    let b = &mut true;
+    match b {
+        //~^ ERROR use of moved value: `b` [E0382]
+        &mut false => {}
+        _ if let Some(()) = {
+            (|| { let bar = b; *bar = false; })();
+            None
+        } => {}
+        &mut true => {}
+        _ => {}
+    }
 }
diff --git a/src/test/ui/nll/issue-27282-move-match-input-into-guard.stderr b/src/test/ui/nll/issue-27282-move-match-input-into-guard.stderr
index 9be1a927999..ae797800457 100644
--- a/src/test/ui/nll/issue-27282-move-match-input-into-guard.stderr
+++ b/src/test/ui/nll/issue-27282-move-match-input-into-guard.stderr
@@ -1,5 +1,5 @@
 error[E0382]: use of moved value: `b`
-  --> $DIR/issue-27282-move-match-input-into-guard.rs:12:5
+  --> $DIR/issue-27282-move-match-input-into-guard.rs:14:5
    |
 LL |     let b = &mut true;
    |         - move occurs because `b` has type `&mut bool`, which does not implement the `Copy` trait
@@ -11,6 +11,19 @@ LL |         _ if { (|| { let bar = b; *bar = false; })();
    |                 |
    |                 value moved into closure here
 
-error: aborting due to previous error
+error[E0382]: use of moved value: `b`
+  --> $DIR/issue-27282-move-match-input-into-guard.rs:24:5
+   |
+LL |     let b = &mut true;
+   |         - move occurs because `b` has type `&mut bool`, which does not implement the `Copy` trait
+LL |     match b {
+   |     ^^^^^^^ value used here after move
+...
+LL |             (|| { let bar = b; *bar = false; })();
+   |              --             - variable moved due to use in closure
+   |              |
+   |              value moved into closure here
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/nll/issue-27282-move-ref-mut-into-guard.rs b/src/test/ui/nll/issue-27282-move-ref-mut-into-guard.rs
index afa0ba780de..833ca8afd61 100644
--- a/src/test/ui/nll/issue-27282-move-ref-mut-into-guard.rs
+++ b/src/test/ui/nll/issue-27282-move-ref-mut-into-guard.rs
@@ -2,6 +2,8 @@
 // mutable borrows in match guards by hiding the mutable borrow in a
 // guard behind a move (of the ref mut pattern id) within a closure.
 
+#![feature(if_let_guard)]
+
 fn main() {
     match Some(&4) {
         None => {},
@@ -10,4 +12,12 @@ fn main() {
         //~^ ERROR cannot move out of `foo` in pattern guard [E0507]
         Some(s) => std::process::exit(*s),
     }
+
+    match Some(&4) {
+        None => {},
+        ref mut foo
+            if let Some(()) = { (|| { let bar = foo; bar.take() })(); None } => {},
+        //~^ ERROR cannot move out of `foo` in pattern guard [E0507]
+        Some(s) => std::process::exit(*s),
+    }
 }
diff --git a/src/test/ui/nll/issue-27282-move-ref-mut-into-guard.stderr b/src/test/ui/nll/issue-27282-move-ref-mut-into-guard.stderr
index a0d32616f83..45119018d4e 100644
--- a/src/test/ui/nll/issue-27282-move-ref-mut-into-guard.stderr
+++ b/src/test/ui/nll/issue-27282-move-ref-mut-into-guard.stderr
@@ -1,5 +1,5 @@
 error[E0507]: cannot move out of `foo` in pattern guard
-  --> $DIR/issue-27282-move-ref-mut-into-guard.rs:9:19
+  --> $DIR/issue-27282-move-ref-mut-into-guard.rs:11:19
    |
 LL |             if { (|| { let bar = foo; bar.take() })(); false } => {},
    |                   ^^             --- move occurs because `foo` has type `&mut Option<&i32>`, which does not implement the `Copy` trait
@@ -8,6 +8,16 @@ LL |             if { (|| { let bar = foo; bar.take() })(); false } => {},
    |
    = note: variables bound in patterns cannot be moved from until after the end of the pattern guard
 
-error: aborting due to previous error
+error[E0507]: cannot move out of `foo` in pattern guard
+  --> $DIR/issue-27282-move-ref-mut-into-guard.rs:19:34
+   |
+LL |             if let Some(()) = { (|| { let bar = foo; bar.take() })(); None } => {},
+   |                                  ^^             --- move occurs because `foo` has type `&mut Option<&i32>`, which does not implement the `Copy` trait
+   |                                  |
+   |                                  move out of `foo` occurs here
+   |
+   = note: variables bound in patterns cannot be moved from until after the end of the pattern guard
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0507`.
diff --git a/src/test/ui/nll/issue-27282-mutation-in-guard.rs b/src/test/ui/nll/issue-27282-mutation-in-guard.rs
index 395c7d214d0..4f41fc23fc3 100644
--- a/src/test/ui/nll/issue-27282-mutation-in-guard.rs
+++ b/src/test/ui/nll/issue-27282-mutation-in-guard.rs
@@ -1,3 +1,5 @@
+#![feature(if_let_guard)]
+
 fn main() {
     match Some(&4) {
         None => {},
@@ -10,4 +12,15 @@ fn main() {
         Some(ref _s) => println!("Note this arm is bogus; the `Some` became `None` in the guard."),
         _ => println!("Here is some supposedly unreachable code."),
     }
+
+    match Some(&4) {
+        None => {},
+        ref mut foo
+            if let Some(()) = {
+                (|| { let bar = foo; bar.take() })();
+                //~^ ERROR cannot move out of `foo` in pattern guard
+                None
+            } => {},
+        Some(_) => {},
+    }
 }
diff --git a/src/test/ui/nll/issue-27282-mutation-in-guard.stderr b/src/test/ui/nll/issue-27282-mutation-in-guard.stderr
index c4ce7e62fda..1ba696593af 100644
--- a/src/test/ui/nll/issue-27282-mutation-in-guard.stderr
+++ b/src/test/ui/nll/issue-27282-mutation-in-guard.stderr
@@ -1,5 +1,5 @@
 error[E0507]: cannot move out of `foo` in pattern guard
-  --> $DIR/issue-27282-mutation-in-guard.rs:6:18
+  --> $DIR/issue-27282-mutation-in-guard.rs:8:18
    |
 LL |                 (|| { let bar = foo; bar.take() })();
    |                  ^^             --- move occurs because `foo` has type `&mut Option<&i32>`, which does not implement the `Copy` trait
@@ -8,6 +8,16 @@ LL |                 (|| { let bar = foo; bar.take() })();
    |
    = note: variables bound in patterns cannot be moved from until after the end of the pattern guard
 
-error: aborting due to previous error
+error[E0507]: cannot move out of `foo` in pattern guard
+  --> $DIR/issue-27282-mutation-in-guard.rs:20:18
+   |
+LL |                 (|| { let bar = foo; bar.take() })();
+   |                  ^^             --- move occurs because `foo` has type `&mut Option<&i32>`, which does not implement the `Copy` trait
+   |                  |
+   |                  move out of `foo` occurs here
+   |
+   = note: variables bound in patterns cannot be moved from until after the end of the pattern guard
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0507`.
diff --git a/src/test/ui/nll/issue-27282-reborrow-ref-mut-in-guard.rs b/src/test/ui/nll/issue-27282-reborrow-ref-mut-in-guard.rs
index 82d8b9e9ed9..ac06b2b0102 100644
--- a/src/test/ui/nll/issue-27282-reborrow-ref-mut-in-guard.rs
+++ b/src/test/ui/nll/issue-27282-reborrow-ref-mut-in-guard.rs
@@ -3,7 +3,9 @@
 // It reborrows instead of moving the `ref mut` pattern borrow. This
 // means that our conservative check for mutation in guards will
 // reject it. But I want to make sure that we continue to reject it
-// (under NLL) even when that conservaive check goes away.
+// (under NLL) even when that conservative check goes away.
+
+#![feature(if_let_guard)]
 
 fn main() {
     let mut b = &mut true;
@@ -15,4 +17,14 @@ fn main() {
         &mut true => { println!("You might think we should get here"); },
         _ => panic!("surely we could never get here, since rustc warns it is unreachable."),
     }
+
+    let mut b = &mut true;
+    match b {
+        &mut false => {},
+        ref mut r if let Some(()) = { (|| { let bar = &mut *r; **bar = false; })();
+        //~^ ERROR cannot borrow `r` as mutable, as it is immutable for the pattern guard
+                             None } => { &mut *r; },
+        &mut true => {},
+        _ => {},
+    }
 }
diff --git a/src/test/ui/nll/issue-27282-reborrow-ref-mut-in-guard.stderr b/src/test/ui/nll/issue-27282-reborrow-ref-mut-in-guard.stderr
index 48433432de1..5eb7a25bf9f 100644
--- a/src/test/ui/nll/issue-27282-reborrow-ref-mut-in-guard.stderr
+++ b/src/test/ui/nll/issue-27282-reborrow-ref-mut-in-guard.stderr
@@ -1,5 +1,5 @@
 error[E0596]: cannot borrow `r` as mutable, as it is immutable for the pattern guard
-  --> $DIR/issue-27282-reborrow-ref-mut-in-guard.rs:12:25
+  --> $DIR/issue-27282-reborrow-ref-mut-in-guard.rs:14:25
    |
 LL |         ref mut r if { (|| { let bar = &mut *r; **bar = false; })();
    |                         ^^                  -- mutable borrow occurs due to use of `r` in closure
@@ -8,6 +8,16 @@ LL |         ref mut r if { (|| { let bar = &mut *r; **bar = false; })();
    |
    = note: variables bound in patterns are immutable until the end of the pattern guard
 
-error: aborting due to previous error
+error[E0596]: cannot borrow `r` as mutable, as it is immutable for the pattern guard
+  --> $DIR/issue-27282-reborrow-ref-mut-in-guard.rs:24:40
+   |
+LL |         ref mut r if let Some(()) = { (|| { let bar = &mut *r; **bar = false; })();
+   |                                        ^^                  -- mutable borrow occurs due to use of `r` in closure
+   |                                        |
+   |                                        cannot borrow as mutable
+   |
+   = note: variables bound in patterns are immutable until the end of the pattern guard
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0596`.
diff --git a/src/test/ui/issues/issue-54189.rs b/src/test/ui/nll/issue-54189.rs
index 70aecc384ef..70aecc384ef 100644
--- a/src/test/ui/issues/issue-54189.rs
+++ b/src/test/ui/nll/issue-54189.rs
diff --git a/src/test/ui/issues/issue-54189.stderr b/src/test/ui/nll/issue-54189.stderr
index 4787abd49d1..4787abd49d1 100644
--- a/src/test/ui/issues/issue-54189.stderr
+++ b/src/test/ui/nll/issue-54189.stderr
diff --git a/src/test/ui/nll/match-cfg-fake-edges.rs b/src/test/ui/nll/match-cfg-fake-edges.rs
index 252f7f8ba07..1afc7931a6b 100644
--- a/src/test/ui/nll/match-cfg-fake-edges.rs
+++ b/src/test/ui/nll/match-cfg-fake-edges.rs
@@ -1,6 +1,8 @@
 // Test that we have enough false edges to avoid exposing the exact matching
 // algorithm in borrow checking.
 
+#![feature(if_let_guard)]
+
 fn guard_always_precedes_arm(y: i32) {
     let mut x;
     // x should always be initialized, as the only way to reach the arm is
@@ -9,6 +11,12 @@ fn guard_always_precedes_arm(y: i32) {
         0 | 2 if { x = 2; true } => x,
         _ => 2,
     };
+
+    let mut x;
+    match y {
+        0 | 2 if let Some(()) = { x = 2; Some(()) } => x,
+        _ => 2,
+    };
 }
 
 fn guard_may_be_skipped(y: i32) {
@@ -23,6 +31,16 @@ fn guard_may_be_skipped(y: i32) {
         } => 2,
         _ => 3,
     };
+
+    let x;
+    match y {
+        _ if let Some(()) = { x = 2; Some(()) } => 1,
+        _ if let Some(()) = {
+            x; //~ ERROR E0381
+            None
+        } => 2,
+        _ => 3,
+    };
 }
 
 fn guard_may_be_taken(y: bool) {
@@ -37,6 +55,16 @@ fn guard_may_be_taken(y: bool) {
         }
         false => 3,
     };
+
+    let x = String::new();
+    match y {
+        false if let Some(()) = { drop(x); Some(()) } => 1,
+        true => {
+            x; //~ ERROR use of moved value: `x`
+            2
+        }
+        false => 3,
+    };
 }
 
 fn main() {}
diff --git a/src/test/ui/nll/match-cfg-fake-edges.stderr b/src/test/ui/nll/match-cfg-fake-edges.stderr
index f72ed3af718..a6261345cea 100644
--- a/src/test/ui/nll/match-cfg-fake-edges.stderr
+++ b/src/test/ui/nll/match-cfg-fake-edges.stderr
@@ -1,5 +1,5 @@
 error[E0381]: used binding `x` isn't initialized
-  --> $DIR/match-cfg-fake-edges.rs:21:13
+  --> $DIR/match-cfg-fake-edges.rs:29:13
    |
 LL |     let x;
    |         - binding declared here but left uninitialized
@@ -15,8 +15,25 @@ help: consider assigning a value
 LL |     let x = 0;
    |           +++
 
+error[E0381]: used binding `x` isn't initialized
+  --> $DIR/match-cfg-fake-edges.rs:39:13
+   |
+LL |     let x;
+   |         - binding declared here but left uninitialized
+LL |     match y {
+LL |         _ if let Some(()) = { x = 2; Some(()) } => 1,
+   |                               ----- binding initialized here in some conditions
+LL |         _ if let Some(()) = {
+LL |             x;
+   |             ^ `x` used here but it isn't initialized
+   |
+help: consider assigning a value
+   |
+LL |     let x = 0;
+   |           +++
+
 error[E0382]: use of moved value: `x`
-  --> $DIR/match-cfg-fake-edges.rs:35:13
+  --> $DIR/match-cfg-fake-edges.rs:53:13
    |
 LL |     let x = String::new();
    |         - move occurs because `x` has type `String`, which does not implement the `Copy` trait
@@ -32,7 +49,24 @@ help: consider cloning the value if the performance cost is acceptable
 LL |         false if { drop(x.clone()); true } => 1,
    |                          ++++++++
 
-error: aborting due to 2 previous errors
+error[E0382]: use of moved value: `x`
+  --> $DIR/match-cfg-fake-edges.rs:63:13
+   |
+LL |     let x = String::new();
+   |         - move occurs because `x` has type `String`, which does not implement the `Copy` trait
+LL |     match y {
+LL |         false if let Some(()) = { drop(x); Some(()) } => 1,
+   |                                        - value moved here
+LL |         true => {
+LL |             x;
+   |             ^ value used here after move
+   |
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL |         false if let Some(()) = { drop(x.clone()); Some(()) } => 1,
+   |                                         ++++++++
+
+error: aborting due to 4 previous errors
 
 Some errors have detailed explanations: E0381, E0382.
 For more information about an error, try `rustc --explain E0381`.
diff --git a/src/test/ui/nll/match-guards-always-borrow.rs b/src/test/ui/nll/match-guards-always-borrow.rs
index 87dba187ba2..ff63cc09273 100644
--- a/src/test/ui/nll/match-guards-always-borrow.rs
+++ b/src/test/ui/nll/match-guards-always-borrow.rs
@@ -1,3 +1,5 @@
+#![feature(if_let_guard)]
+
 // Here is arielb1's basic example from rust-lang/rust#27282
 // that AST borrowck is flummoxed by:
 
@@ -10,6 +12,15 @@ fn should_reject_destructive_mutate_in_guard() {
             false } => { },
         Some(s) => std::process::exit(*s),
     }
+
+    match Some(&4) {
+        None => {},
+        ref mut foo if let Some(()) = {
+            (|| { let bar = foo; bar.take() })();
+            //~^ ERROR cannot move out of `foo` in pattern guard [E0507]
+            None } => { },
+        Some(s) => std::process::exit(*s),
+    }
 }
 
 // Here below is a case that needs to keep working: we only use the
@@ -18,7 +29,13 @@ fn should_reject_destructive_mutate_in_guard() {
 fn allow_mutate_in_arm_body() {
     match Some(&4) {
         None => {},
-        ref mut foo if foo.is_some() && false => { foo.take(); () }
+        ref mut foo if foo.is_some() => { foo.take(); () }
+        Some(s) => std::process::exit(*s),
+    }
+
+    match Some(&4) {
+        None => {},
+        ref mut foo if let Some(_) = foo => { foo.take(); () }
         Some(s) => std::process::exit(*s),
     }
 }
@@ -29,7 +46,13 @@ fn allow_mutate_in_arm_body() {
 fn allow_move_into_arm_body() {
     match Some(&4) {
         None => {},
-        mut foo if foo.is_some() && false => { foo.take(); () }
+        mut foo if foo.is_some() => { foo.unwrap(); () }
+        Some(s) => std::process::exit(*s),
+    }
+
+    match Some(&4) {
+        None => {},
+        mut foo if let Some(_) = foo => { foo.unwrap(); () }
         Some(s) => std::process::exit(*s),
     }
 }
diff --git a/src/test/ui/nll/match-guards-always-borrow.stderr b/src/test/ui/nll/match-guards-always-borrow.stderr
index c0fb5f65382..fa01d3a6fd1 100644
--- a/src/test/ui/nll/match-guards-always-borrow.stderr
+++ b/src/test/ui/nll/match-guards-always-borrow.stderr
@@ -1,5 +1,5 @@
 error[E0507]: cannot move out of `foo` in pattern guard
-  --> $DIR/match-guards-always-borrow.rs:8:14
+  --> $DIR/match-guards-always-borrow.rs:10:14
    |
 LL |             (|| { let bar = foo; bar.take() })();
    |              ^^             --- move occurs because `foo` has type `&mut Option<&i32>`, which does not implement the `Copy` trait
@@ -8,6 +8,16 @@ LL |             (|| { let bar = foo; bar.take() })();
    |
    = note: variables bound in patterns cannot be moved from until after the end of the pattern guard
 
-error: aborting due to previous error
+error[E0507]: cannot move out of `foo` in pattern guard
+  --> $DIR/match-guards-always-borrow.rs:19:14
+   |
+LL |             (|| { let bar = foo; bar.take() })();
+   |              ^^             --- move occurs because `foo` has type `&mut Option<&i32>`, which does not implement the `Copy` trait
+   |              |
+   |              move out of `foo` occurs here
+   |
+   = note: variables bound in patterns cannot be moved from until after the end of the pattern guard
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0507`.
diff --git a/src/test/ui/nll/match-guards-partially-borrow.rs b/src/test/ui/nll/match-guards-partially-borrow.rs
index 81ae19ebf8a..3a9e1654b1c 100644
--- a/src/test/ui/nll/match-guards-partially-borrow.rs
+++ b/src/test/ui/nll/match-guards-partially-borrow.rs
@@ -5,7 +5,9 @@
 // Test that we don't allow mutating the value being matched on in a way that
 // changes which patterns it matches, until we have chosen an arm.
 
-fn ok_mutation_in_guard(mut q: i32) {
+#![feature(if_let_guard)]
+
+fn ok_mutation_in_if_guard(mut q: i32) {
     match q {
         // OK, mutation doesn't change which patterns g matches
         _ if { q = 1; false } => (),
@@ -13,7 +15,15 @@ fn ok_mutation_in_guard(mut q: i32) {
     }
 }
 
-fn ok_mutation_in_guard2(mut u: bool) {
+fn ok_mutation_in_if_let_guard(mut q: i32) {
+    match q {
+        // OK, mutation doesn't change which patterns g matches
+        _ if let Some(()) = { q = 1; None } => (),
+        _ => (),
+    }
+}
+
+fn ok_mutation_in_if_guard2(mut u: bool) {
     // OK value of u is unused before modification
     match u {
         _ => (),
@@ -25,7 +35,19 @@ fn ok_mutation_in_guard2(mut u: bool) {
     }
 }
 
-fn ok_mutation_in_guard4(mut w: (&mut bool,)) {
+fn ok_mutation_in_if_let_guard2(mut u: bool) {
+    // OK value of u is unused before modification
+    match u {
+        _ => (),
+        _ if let Some(()) = {
+            u = true;
+            None
+        } => (),
+        x => (),
+    }
+}
+
+fn ok_mutation_in_if_guard4(mut w: (&mut bool,)) {
     // OK value of u is unused before modification
     match w {
         _ => (),
@@ -37,7 +59,19 @@ fn ok_mutation_in_guard4(mut w: (&mut bool,)) {
     }
 }
 
-fn ok_indirect_mutation_in_guard(mut p: &bool) {
+fn ok_mutation_in_if_let_guard4(mut w: (&mut bool,)) {
+    // OK value of u is unused before modification
+    match w {
+        _ => (),
+        _ if let Some(()) = {
+            *w.0 = true;
+            None
+        } => (),
+        x => (),
+    }
+}
+
+fn ok_indirect_mutation_in_if_guard(mut p: &bool) {
     match *p {
         // OK, mutation doesn't change which patterns s matches
         _ if {
@@ -48,7 +82,18 @@ fn ok_indirect_mutation_in_guard(mut p: &bool) {
     }
 }
 
-fn mutation_invalidates_pattern_in_guard(mut q: bool) {
+fn ok_indirect_mutation_in_if_let_guard(mut p: &bool) {
+    match *p {
+        // OK, mutation doesn't change which patterns s matches
+        _ if let Some(()) = {
+            p = &true;
+            None
+        } => (),
+        _ => (),
+    }
+}
+
+fn mutation_invalidates_pattern_in_if_guard(mut q: bool) {
     match q {
         // q doesn't match the pattern with the guard by the end of the guard.
         false if {
@@ -59,7 +104,18 @@ fn mutation_invalidates_pattern_in_guard(mut q: bool) {
     }
 }
 
-fn mutation_invalidates_previous_pattern_in_guard(mut r: bool) {
+fn mutation_invalidates_pattern_in_if_let_guard(mut q: bool) {
+    match q {
+        // q doesn't match the pattern with the guard by the end of the guard.
+        false if let Some(()) = {
+            q = true; //~ ERROR
+            Some(())
+        } => (),
+        _ => (),
+    }
+}
+
+fn mutation_invalidates_previous_pattern_in_if_guard(mut r: bool) {
     match r {
         // r matches a previous pattern by the end of the guard.
         true => (),
@@ -71,7 +127,19 @@ fn mutation_invalidates_previous_pattern_in_guard(mut r: bool) {
     }
 }
 
-fn match_on_borrowed_early_end(mut s: bool) {
+fn mutation_invalidates_previous_pattern_in_if_let_guard(mut r: bool) {
+    match r {
+        // r matches a previous pattern by the end of the guard.
+        true => (),
+        _ if let Some(()) = {
+            r = true; //~ ERROR
+            Some(())
+        } => (),
+        _ => (),
+    }
+}
+
+fn match_on_borrowed_early_end_if_guard(mut s: bool) {
     let h = &mut s;
     // OK value of s is unused before modification.
     match s {
@@ -84,7 +152,20 @@ fn match_on_borrowed_early_end(mut s: bool) {
     }
 }
 
-fn bad_mutation_in_guard(mut t: bool) {
+fn match_on_borrowed_early_end_if_let_guard(mut s: bool) {
+    let h = &mut s;
+    // OK value of s is unused before modification.
+    match s {
+        _ if let Some(()) = {
+            *h = !*h;
+            None
+        } => (),
+        true => (),
+        false => (),
+    }
+}
+
+fn bad_mutation_in_if_guard(mut t: bool) {
     match t {
         true => (),
         false if {
@@ -95,7 +176,18 @@ fn bad_mutation_in_guard(mut t: bool) {
     }
 }
 
-fn bad_mutation_in_guard2(mut x: Option<Option<&i32>>) {
+fn bad_mutation_in_if_let_guard(mut t: bool) {
+    match t {
+        true => (),
+        false if let Some(()) = {
+            t = true; //~ ERROR
+            None
+        } => (),
+        false => (),
+    }
+}
+
+fn bad_mutation_in_if_guard2(mut x: Option<Option<&i32>>) {
     // Check that nested patterns are checked.
     match x {
         None => (),
@@ -111,7 +203,23 @@ fn bad_mutation_in_guard2(mut x: Option<Option<&i32>>) {
     }
 }
 
-fn bad_mutation_in_guard3(mut t: bool) {
+fn bad_mutation_in_if_let_guard2(mut x: Option<Option<&i32>>) {
+    // Check that nested patterns are checked.
+    match x {
+        None => (),
+        Some(None) => (),
+        _ if let Some(()) = {
+            match x {
+                Some(ref mut r) => *r = None, //~ ERROR
+                _ => return,
+            };
+            None
+        } => (),
+        Some(Some(r)) => println!("{}", r),
+    }
+}
+
+fn bad_mutation_in_if_guard3(mut t: bool) {
     match t {
         s if {
             t = !t; //~ ERROR
@@ -121,7 +229,17 @@ fn bad_mutation_in_guard3(mut t: bool) {
     }
 }
 
-fn bad_indirect_mutation_in_guard(mut y: &bool) {
+fn bad_mutation_in_if_let_guard3(mut t: bool) {
+    match t {
+        s if let Some(()) = {
+            t = !t; //~ ERROR
+            None
+        } => (), // What value should `s` have in the arm?
+        _ => (),
+    }
+}
+
+fn bad_indirect_mutation_in_if_guard(mut y: &bool) {
     match *y {
         true => (),
         false if {
@@ -132,7 +250,18 @@ fn bad_indirect_mutation_in_guard(mut y: &bool) {
     }
 }
 
-fn bad_indirect_mutation_in_guard2(mut z: &bool) {
+fn bad_indirect_mutation_in_if_let_guard(mut y: &bool) {
+    match *y {
+        true => (),
+        false if let Some(()) = {
+            y = &true; //~ ERROR
+            None
+        } => (),
+        false => (),
+    }
+}
+
+fn bad_indirect_mutation_in_if_guard2(mut z: &bool) {
     match z {
         &true => (),
         &false if {
@@ -143,8 +272,19 @@ fn bad_indirect_mutation_in_guard2(mut z: &bool) {
     }
 }
 
-fn bad_indirect_mutation_in_guard3(mut a: &bool) {
-    // Same as bad_indirect_mutation_in_guard2, but using match ergonomics
+fn bad_indirect_mutation_in_if_let_guard2(mut z: &bool) {
+    match z {
+        &true => (),
+        &false if let Some(()) = {
+            z = &true; //~ ERROR
+            None
+        } => (),
+        &false => (),
+    }
+}
+
+fn bad_indirect_mutation_in_if_guard3(mut a: &bool) {
+    // Same as bad_indirect_mutation_in_if_guard2, but using match ergonomics
     match a {
         true => (),
         false if {
@@ -155,7 +295,19 @@ fn bad_indirect_mutation_in_guard3(mut a: &bool) {
     }
 }
 
-fn bad_indirect_mutation_in_guard4(mut b: &bool) {
+fn bad_indirect_mutation_in_if_let_guard3(mut a: &bool) {
+    // Same as bad_indirect_mutation_in_if_guard2, but using match ergonomics
+    match a {
+        true => (),
+        false if let Some(()) = {
+            a = &true; //~ ERROR
+            None
+        } => (),
+        false => (),
+    }
+}
+
+fn bad_indirect_mutation_in_if_guard4(mut b: &bool) {
     match b {
         &_ => (),
         &_ if {
@@ -166,4 +318,15 @@ fn bad_indirect_mutation_in_guard4(mut b: &bool) {
     }
 }
 
+fn bad_indirect_mutation_in_if_let_guard4(mut b: &bool) {
+    match b {
+        &_ => (),
+        &_ if let Some(()) = {
+            b = &true; //~ ERROR
+            None
+        } => (),
+        &b => (),
+    }
+}
+
 fn main() {}
diff --git a/src/test/ui/nll/match-guards-partially-borrow.stderr b/src/test/ui/nll/match-guards-partially-borrow.stderr
index 48e3a7c6993..60b8dee71a8 100644
--- a/src/test/ui/nll/match-guards-partially-borrow.stderr
+++ b/src/test/ui/nll/match-guards-partially-borrow.stderr
@@ -1,5 +1,5 @@
 error[E0510]: cannot assign `q` in match guard
-  --> $DIR/match-guards-partially-borrow.rs:55:13
+  --> $DIR/match-guards-partially-borrow.rs:100:13
    |
 LL |     match q {
    |           - value is immutable in match guard
@@ -7,8 +7,26 @@ LL |     match q {
 LL |             q = true;
    |             ^^^^^^^^ cannot assign
 
+error[E0510]: cannot assign `q` in match guard
+  --> $DIR/match-guards-partially-borrow.rs:111:13
+   |
+LL |     match q {
+   |           - value is immutable in match guard
+...
+LL |             q = true;
+   |             ^^^^^^^^ cannot assign
+
+error[E0510]: cannot assign `r` in match guard
+  --> $DIR/match-guards-partially-borrow.rs:123:13
+   |
+LL |     match r {
+   |           - value is immutable in match guard
+...
+LL |             r = true;
+   |             ^^^^^^^^ cannot assign
+
 error[E0510]: cannot assign `r` in match guard
-  --> $DIR/match-guards-partially-borrow.rs:67:13
+  --> $DIR/match-guards-partially-borrow.rs:135:13
    |
 LL |     match r {
    |           - value is immutable in match guard
@@ -17,7 +35,16 @@ LL |             r = true;
    |             ^^^^^^^^ cannot assign
 
 error[E0510]: cannot assign `t` in match guard
-  --> $DIR/match-guards-partially-borrow.rs:91:13
+  --> $DIR/match-guards-partially-borrow.rs:172:13
+   |
+LL |     match t {
+   |           - value is immutable in match guard
+...
+LL |             t = true;
+   |             ^^^^^^^^ cannot assign
+
+error[E0510]: cannot assign `t` in match guard
+  --> $DIR/match-guards-partially-borrow.rs:183:13
    |
 LL |     match t {
    |           - value is immutable in match guard
@@ -26,7 +53,16 @@ LL |             t = true;
    |             ^^^^^^^^ cannot assign
 
 error[E0510]: cannot mutably borrow `x.0` in match guard
-  --> $DIR/match-guards-partially-borrow.rs:105:22
+  --> $DIR/match-guards-partially-borrow.rs:197:22
+   |
+LL |     match x {
+   |           - value is immutable in match guard
+...
+LL |                 Some(ref mut r) => *r = None,
+   |                      ^^^^^^^^^ cannot mutably borrow
+
+error[E0510]: cannot mutably borrow `x.0` in match guard
+  --> $DIR/match-guards-partially-borrow.rs:213:22
    |
 LL |     match x {
    |           - value is immutable in match guard
@@ -35,7 +71,7 @@ LL |                 Some(ref mut r) => *r = None,
    |                      ^^^^^^^^^ cannot mutably borrow
 
 error[E0506]: cannot assign to `t` because it is borrowed
-  --> $DIR/match-guards-partially-borrow.rs:117:13
+  --> $DIR/match-guards-partially-borrow.rs:225:13
    |
 LL |         s if {
    |         - borrow of `t` occurs here
@@ -45,8 +81,28 @@ LL |             false
 LL |         } => (), // What value should `s` have in the arm?
    |         - borrow later used here
 
+error[E0506]: cannot assign to `t` because it is borrowed
+  --> $DIR/match-guards-partially-borrow.rs:235:13
+   |
+LL |         s if let Some(()) = {
+   |         - borrow of `t` occurs here
+LL |             t = !t;
+   |             ^^^^^^ assignment to borrowed `t` occurs here
+LL |             None
+LL |         } => (), // What value should `s` have in the arm?
+   |         - borrow later used here
+
+error[E0510]: cannot assign `y` in match guard
+  --> $DIR/match-guards-partially-borrow.rs:246:13
+   |
+LL |     match *y {
+   |           -- value is immutable in match guard
+...
+LL |             y = &true;
+   |             ^^^^^^^^^ cannot assign
+
 error[E0510]: cannot assign `y` in match guard
-  --> $DIR/match-guards-partially-borrow.rs:128:13
+  --> $DIR/match-guards-partially-borrow.rs:257:13
    |
 LL |     match *y {
    |           -- value is immutable in match guard
@@ -55,7 +111,16 @@ LL |             y = &true;
    |             ^^^^^^^^^ cannot assign
 
 error[E0510]: cannot assign `z` in match guard
-  --> $DIR/match-guards-partially-borrow.rs:139:13
+  --> $DIR/match-guards-partially-borrow.rs:268:13
+   |
+LL |     match z {
+   |           - value is immutable in match guard
+...
+LL |             z = &true;
+   |             ^^^^^^^^^ cannot assign
+
+error[E0510]: cannot assign `z` in match guard
+  --> $DIR/match-guards-partially-borrow.rs:279:13
    |
 LL |     match z {
    |           - value is immutable in match guard
@@ -64,7 +129,16 @@ LL |             z = &true;
    |             ^^^^^^^^^ cannot assign
 
 error[E0510]: cannot assign `a` in match guard
-  --> $DIR/match-guards-partially-borrow.rs:151:13
+  --> $DIR/match-guards-partially-borrow.rs:291:13
+   |
+LL |     match a {
+   |           - value is immutable in match guard
+...
+LL |             a = &true;
+   |             ^^^^^^^^^ cannot assign
+
+error[E0510]: cannot assign `a` in match guard
+  --> $DIR/match-guards-partially-borrow.rs:303:13
    |
 LL |     match a {
    |           - value is immutable in match guard
@@ -73,7 +147,16 @@ LL |             a = &true;
    |             ^^^^^^^^^ cannot assign
 
 error[E0510]: cannot assign `b` in match guard
-  --> $DIR/match-guards-partially-borrow.rs:162:13
+  --> $DIR/match-guards-partially-borrow.rs:314:13
+   |
+LL |     match b {
+   |           - value is immutable in match guard
+...
+LL |             b = &true;
+   |             ^^^^^^^^^ cannot assign
+
+error[E0510]: cannot assign `b` in match guard
+  --> $DIR/match-guards-partially-borrow.rs:325:13
    |
 LL |     match b {
    |           - value is immutable in match guard
@@ -81,7 +164,7 @@ LL |     match b {
 LL |             b = &true;
    |             ^^^^^^^^^ cannot assign
 
-error: aborting due to 9 previous errors
+error: aborting due to 18 previous errors
 
 Some errors have detailed explanations: E0506, E0510.
 For more information about an error, try `rustc --explain E0506`.
diff --git a/src/test/ui/nll/normalization-bounds-error.stderr b/src/test/ui/nll/normalization-bounds-error.stderr
index 6abe53127c3..0fc3670d6c5 100644
--- a/src/test/ui/nll/normalization-bounds-error.stderr
+++ b/src/test/ui/nll/normalization-bounds-error.stderr
@@ -1,8 +1,8 @@
 error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'d` due to conflicting requirements
-  --> $DIR/normalization-bounds-error.rs:12:1
+  --> $DIR/normalization-bounds-error.rs:12:31
    |
 LL | fn visit_seq<'d, 'a: 'd>() -> <&'a () as Visitor<'d>>::Value {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: first, the lifetime cannot outlive the lifetime `'d` as defined here...
   --> $DIR/normalization-bounds-error.rs:12:14
@@ -15,10 +15,10 @@ note: ...but the lifetime must also be valid for the lifetime `'a` as defined he
 LL | fn visit_seq<'d, 'a: 'd>() -> <&'a () as Visitor<'d>>::Value {}
    |                  ^^
 note: ...so that the types are compatible
-  --> $DIR/normalization-bounds-error.rs:12:1
+  --> $DIR/normalization-bounds-error.rs:12:31
    |
 LL | fn visit_seq<'d, 'a: 'd>() -> <&'a () as Visitor<'d>>::Value {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: expected `Visitor<'d>`
               found `Visitor<'_>`
 
diff --git a/src/test/ui/not-enough-arguments.rs b/src/test/ui/not-enough-arguments.rs
index 42476255188..4a2ea5e44c7 100644
--- a/src/test/ui/not-enough-arguments.rs
+++ b/src/test/ui/not-enough-arguments.rs
@@ -25,7 +25,7 @@ fn bar(
 
 fn main() {
   foo(1, 2, 3);
-  //~^ ERROR this function takes 4 arguments but 3
+  //~^ ERROR function takes 4 arguments but 3
   bar(1, 2, 3);
-  //~^ ERROR this function takes 6 arguments but 3
+  //~^ ERROR function takes 6 arguments but 3
 }
diff --git a/src/test/ui/parser/int-literal-too-large-span.stderr b/src/test/ui/parser/int-literal-too-large-span.stderr
index 7cae85fc9fe..49d6aa5eff8 100644
--- a/src/test/ui/parser/int-literal-too-large-span.stderr
+++ b/src/test/ui/parser/int-literal-too-large-span.stderr
@@ -3,6 +3,8 @@ error: integer literal is too large
    |
 LL |     9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: value exceeds limit of `340282366920938463463374607431768211455`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/parser/issues/issue-5544-a.stderr b/src/test/ui/parser/issues/issue-5544-a.stderr
index de579c3c134..6e68c75850a 100644
--- a/src/test/ui/parser/issues/issue-5544-a.stderr
+++ b/src/test/ui/parser/issues/issue-5544-a.stderr
@@ -3,6 +3,8 @@ error: integer literal is too large
    |
 LL |     let __isize = 340282366920938463463374607431768211456; // 2^128
    |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: value exceeds limit of `340282366920938463463374607431768211455`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/parser/issues/issue-5544-b.stderr b/src/test/ui/parser/issues/issue-5544-b.stderr
index 7df212dedfe..5d0e76d5d94 100644
--- a/src/test/ui/parser/issues/issue-5544-b.stderr
+++ b/src/test/ui/parser/issues/issue-5544-b.stderr
@@ -3,6 +3,8 @@ error: integer literal is too large
    |
 LL |     let __isize = 0xffff_ffff_ffff_ffff_ffff_ffff_ffff_ffff_ff;
    |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: value exceeds limit of `0xffffffffffffffffffffffffffffffff`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/parser/nested-bad-turbofish.rs b/src/test/ui/parser/nested-bad-turbofish.rs
new file mode 100644
index 00000000000..02099fde212
--- /dev/null
+++ b/src/test/ui/parser/nested-bad-turbofish.rs
@@ -0,0 +1,3 @@
+fn main() {
+    foo<<S as T>::V>(); //~ ERROR
+}
diff --git a/src/test/ui/parser/nested-bad-turbofish.stderr b/src/test/ui/parser/nested-bad-turbofish.stderr
new file mode 100644
index 00000000000..d82fa80e594
--- /dev/null
+++ b/src/test/ui/parser/nested-bad-turbofish.stderr
@@ -0,0 +1,11 @@
+error: comparison operators cannot be chained
+  --> $DIR/nested-bad-turbofish.rs:2:16
+   |
+LL |     foo<<S as T>::V>();
+   |                ^   ^
+   |
+   = help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
+   = help: or use `(...)` if you meant to specify fn arguments
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/privacy/private-field-ty-err.rs b/src/test/ui/privacy/private-field-ty-err.rs
new file mode 100644
index 00000000000..10db6069567
--- /dev/null
+++ b/src/test/ui/privacy/private-field-ty-err.rs
@@ -0,0 +1,20 @@
+fn main() {
+    let x = foo::Foo::default();
+    if x.len {
+        //~^ ERROR field `len` of struct `Foo` is private
+        println!("foo");
+    }
+}
+
+mod foo {
+    #[derive(Default)]
+    pub struct Foo {
+        len: String,
+    }
+
+    impl Foo {
+        pub fn len(&self) -> usize {
+            42
+        }
+    }
+}
diff --git a/src/test/ui/privacy/private-field-ty-err.stderr b/src/test/ui/privacy/private-field-ty-err.stderr
new file mode 100644
index 00000000000..e583a25fd8f
--- /dev/null
+++ b/src/test/ui/privacy/private-field-ty-err.stderr
@@ -0,0 +1,14 @@
+error[E0616]: field `len` of struct `Foo` is private
+  --> $DIR/private-field-ty-err.rs:3:10
+   |
+LL |     if x.len {
+   |          ^^^ private field
+   |
+help: a method `len` also exists, call it with parentheses
+   |
+LL |     if x.len() {
+   |             ++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0616`.
diff --git a/src/test/ui/process/process-panic-after-fork.rs b/src/test/ui/process/process-panic-after-fork.rs
index 6d4d2492225..da268312173 100644
--- a/src/test/ui/process/process-panic-after-fork.rs
+++ b/src/test/ui/process/process-panic-after-fork.rs
@@ -84,42 +84,47 @@ fn expect_aborted(status: ExitStatus) {
 
     #[cfg(target_os = "android")]
     {
-        // Android signals an abort() call with SIGSEGV at address 0xdeadbaad
-        // See e.g. https://groups.google.com/g/android-ndk/c/laW1CJc7Icc
-        assert!(signal == libc::SIGSEGV);
-
-        // Additional checks performed:
-        // 1. Find last tombstone (similar to coredump but in text format) from the
-        //    same executable (path) as we are (must be because of usage of fork):
-        //    This ensures that we look into the correct tombstone.
-        // 2. Cause of crash is a SIGSEGV with address 0xdeadbaad.
-        // 3. libc::abort call is in one of top two functions on callstack.
-        // The last two steps distinguish between a normal SIGSEGV and one caused
-        // by libc::abort.
-
-        let this_exe = std::env::current_exe().unwrap().into_os_string().into_string().unwrap();
-        let exe_string = format!(">>> {this_exe} <<<");
-        let tombstone = (0..100)
-            .map(|n| format!("/data/tombstones/tombstone_{n:02}"))
-            .filter(|f| std::path::Path::new(&f).exists())
-            .map(|f| std::fs::read_to_string(&f).expect("Cannot read tombstone file"))
-            .filter(|f| f.contains(&exe_string))
-            .last()
-            .expect("no tombstone found");
-
-        println!("Content of tombstone:\n{tombstone}");
-
-        assert!(
-            tombstone.contains("signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr deadbaad")
-        );
-        let abort_on_top = tombstone
-            .lines()
-            .skip_while(|l| !l.contains("backtrace:"))
-            .skip(1)
-            .take_while(|l| l.starts_with("    #"))
-            .take(2)
-            .any(|f| f.contains("/system/lib/libc.so (abort"));
-        assert!(abort_on_top);
+        assert!(signal == libc::SIGABRT || signal == libc::SIGSEGV);
+
+        if signal == libc::SIGSEGV {
+            // Pre-KitKat versions of Android signal an abort() with SIGSEGV at address 0xdeadbaad
+            // See e.g. https://groups.google.com/g/android-ndk/c/laW1CJc7Icc
+            //
+            // This behavior was changed in KitKat to send a standard SIGABRT signal.
+            // See: https://r.android.com/60341
+            //
+            // Additional checks performed:
+            // 1. Find last tombstone (similar to coredump but in text format) from the
+            //    same executable (path) as we are (must be because of usage of fork):
+            //    This ensures that we look into the correct tombstone.
+            // 2. Cause of crash is a SIGSEGV with address 0xdeadbaad.
+            // 3. libc::abort call is in one of top two functions on callstack.
+            // The last two steps distinguish between a normal SIGSEGV and one caused
+            // by libc::abort.
+
+            let this_exe = std::env::current_exe().unwrap().into_os_string().into_string().unwrap();
+            let exe_string = format!(">>> {this_exe} <<<");
+            let tombstone = (0..100)
+                .map(|n| format!("/data/tombstones/tombstone_{n:02}"))
+                .filter(|f| std::path::Path::new(&f).exists())
+                .map(|f| std::fs::read_to_string(&f).expect("Cannot read tombstone file"))
+                .filter(|f| f.contains(&exe_string))
+                .last()
+                .expect("no tombstone found");
+
+            println!("Content of tombstone:\n{tombstone}");
+
+            assert!(tombstone
+                .contains("signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr deadbaad"));
+            let abort_on_top = tombstone
+                .lines()
+                .skip_while(|l| !l.contains("backtrace:"))
+                .skip(1)
+                .take_while(|l| l.starts_with("    #"))
+                .take(2)
+                .any(|f| f.contains("/system/lib/libc.so (abort"));
+            assert!(abort_on_top);
+        }
     }
 }
 
diff --git a/src/test/ui/regions/regions-implied-bounds-projection-gap-hr-1.stderr b/src/test/ui/regions/regions-implied-bounds-projection-gap-hr-1.stderr
index 66f592c34dd..3fd39810d44 100644
--- a/src/test/ui/regions/regions-implied-bounds-projection-gap-hr-1.stderr
+++ b/src/test/ui/regions/regions-implied-bounds-projection-gap-hr-1.stderr
@@ -1,12 +1,8 @@
 error[E0277]: the trait bound `for<'z> T: Trait2<'y, 'z>` is not satisfied
-  --> $DIR/regions-implied-bounds-projection-gap-hr-1.rs:21:1
+  --> $DIR/regions-implied-bounds-projection-gap-hr-1.rs:21:49
    |
-LL | / fn callee<'x, 'y, T>(t: &'x dyn for<'z> Trait1< <T as Trait2<'y, 'z>>::Foo >)
-LL | |
-LL | |
-LL | | {
-LL | | }
-   | |_^ the trait `for<'z> Trait2<'y, 'z>` is not implemented for `T`
+LL | fn callee<'x, 'y, T>(t: &'x dyn for<'z> Trait1< <T as Trait2<'y, 'z>>::Foo >)
+   |                                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'z> Trait2<'y, 'z>` is not implemented for `T`
    |
 help: consider restricting type parameter `T`
    |
@@ -14,10 +10,14 @@ LL | fn callee<'x, 'y, T: for<'z> Trait2<'y, 'z>>(t: &'x dyn for<'z> Trait1< <T
    |                    ++++++++++++++++++++++++
 
 error[E0277]: the trait bound `for<'z> T: Trait2<'y, 'z>` is not satisfied
-  --> $DIR/regions-implied-bounds-projection-gap-hr-1.rs:21:49
+  --> $DIR/regions-implied-bounds-projection-gap-hr-1.rs:21:1
    |
-LL | fn callee<'x, 'y, T>(t: &'x dyn for<'z> Trait1< <T as Trait2<'y, 'z>>::Foo >)
-   |                                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'z> Trait2<'y, 'z>` is not implemented for `T`
+LL | / fn callee<'x, 'y, T>(t: &'x dyn for<'z> Trait1< <T as Trait2<'y, 'z>>::Foo >)
+LL | |
+LL | |
+LL | | {
+LL | | }
+   | |_^ the trait `for<'z> Trait2<'y, 'z>` is not implemented for `T`
    |
 help: consider restricting type parameter `T`
    |
diff --git a/src/test/ui/resolve/resolve-primitive-fallback.rs b/src/test/ui/resolve/resolve-primitive-fallback.rs
index 992bcd7977f..05cabd9e3cd 100644
--- a/src/test/ui/resolve/resolve-primitive-fallback.rs
+++ b/src/test/ui/resolve/resolve-primitive-fallback.rs
@@ -2,7 +2,7 @@ fn main() {
     // Make sure primitive type fallback doesn't work in value namespace
     std::mem::size_of(u16);
     //~^ ERROR expected value, found builtin type `u16`
-    //~| ERROR this function takes 0 arguments but 1 argument was supplied
+    //~| ERROR function takes 0 arguments but 1 argument was supplied
 
     // Make sure primitive type fallback doesn't work with global paths
     let _: ::u8;
diff --git a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-across-arms.rs b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-across-arms.rs
index d1f685f3e7a..6f0d2b04591 100644
--- a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-across-arms.rs
+++ b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-across-arms.rs
@@ -1,6 +1,8 @@
+#![feature(if_let_guard)]
+
 enum VecWrapper { A(Vec<i32>) }
 
-fn foo(x: VecWrapper) -> usize {
+fn if_guard(x: VecWrapper) -> usize {
     match x {
         VecWrapper::A(v) if { drop(v); false } => 1,
         //~^ ERROR cannot move out of `v` in pattern guard
@@ -8,6 +10,15 @@ fn foo(x: VecWrapper) -> usize {
     }
 }
 
+fn if_let_guard(x: VecWrapper) -> usize {
+    match x {
+        VecWrapper::A(v) if let Some(()) = { drop(v); None } => 1,
+        //~^ ERROR cannot move out of `v` in pattern guard
+        VecWrapper::A(v) => v.len()
+    }
+}
+
 fn main() {
-    foo(VecWrapper::A(vec![107]));
+    if_guard(VecWrapper::A(vec![107]));
+    if_let_guard(VecWrapper::A(vec![107]));
 }
diff --git a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-across-arms.stderr b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-across-arms.stderr
index 6c3d1caf807..a749361bf30 100644
--- a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-across-arms.stderr
+++ b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-across-arms.stderr
@@ -1,11 +1,19 @@
 error[E0507]: cannot move out of `v` in pattern guard
-  --> $DIR/rfc-reject-double-move-across-arms.rs:5:36
+  --> $DIR/rfc-reject-double-move-across-arms.rs:7:36
    |
 LL |         VecWrapper::A(v) if { drop(v); false } => 1,
    |                                    ^ move occurs because `v` has type `Vec<i32>`, which does not implement the `Copy` trait
    |
    = note: variables bound in patterns cannot be moved from until after the end of the pattern guard
 
-error: aborting due to previous error
+error[E0507]: cannot move out of `v` in pattern guard
+  --> $DIR/rfc-reject-double-move-across-arms.rs:15:51
+   |
+LL |         VecWrapper::A(v) if let Some(()) = { drop(v); None } => 1,
+   |                                                   ^ move occurs because `v` has type `Vec<i32>`, which does not implement the `Copy` trait
+   |
+   = note: variables bound in patterns cannot be moved from until after the end of the pattern guard
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0507`.
diff --git a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-in-first-arm.rs b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-in-first-arm.rs
index 571f51c9001..827335f6a84 100644
--- a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-in-first-arm.rs
+++ b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-in-first-arm.rs
@@ -1,6 +1,8 @@
+#![feature(if_let_guard)]
+
 struct A { a: Box<i32> }
 
-fn foo(n: i32) {
+fn if_guard(n: i32) {
     let x = A { a: Box::new(n) };
     let _y = match x {
         A { a: v } if { drop(v); true } => v,
@@ -9,6 +11,16 @@ fn foo(n: i32) {
     };
 }
 
+fn if_let_guard(n: i32) {
+    let x = A { a: Box::new(n) };
+    let _y = match x {
+        A { a: v } if let Some(()) = { drop(v); Some(()) } => v,
+        //~^ ERROR cannot move out of `v` in pattern guard
+        _ => Box::new(0),
+    };
+}
+
 fn main() {
-    foo(107);
+    if_guard(107);
+    if_let_guard(107);
 }
diff --git a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-in-first-arm.stderr b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-in-first-arm.stderr
index d1204bc2601..9285492b224 100644
--- a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-in-first-arm.stderr
+++ b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-in-first-arm.stderr
@@ -1,11 +1,19 @@
 error[E0507]: cannot move out of `v` in pattern guard
-  --> $DIR/rfc-reject-double-move-in-first-arm.rs:6:30
+  --> $DIR/rfc-reject-double-move-in-first-arm.rs:8:30
    |
 LL |         A { a: v } if { drop(v); true } => v,
    |                              ^ move occurs because `v` has type `Box<i32>`, which does not implement the `Copy` trait
    |
    = note: variables bound in patterns cannot be moved from until after the end of the pattern guard
 
-error: aborting due to previous error
+error[E0507]: cannot move out of `v` in pattern guard
+  --> $DIR/rfc-reject-double-move-in-first-arm.rs:17:45
+   |
+LL |         A { a: v } if let Some(()) = { drop(v); Some(()) } => v,
+   |                                             ^ move occurs because `v` has type `Box<i32>`, which does not implement the `Copy` trait
+   |
+   = note: variables bound in patterns cannot be moved from until after the end of the pattern guard
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0507`.
diff --git a/src/test/ui/span/issue-34264.rs b/src/test/ui/span/issue-34264.rs
index 5b8fc71384e..9227ee482df 100644
--- a/src/test/ui/span/issue-34264.rs
+++ b/src/test/ui/span/issue-34264.rs
@@ -4,8 +4,8 @@ fn bar(x, y: usize) {} //~ ERROR expected one of
 
 fn main() {
     foo(Some(42), 2);
-    foo(Some(42), 2, ""); //~ ERROR this function takes
+    foo(Some(42), 2, ""); //~ ERROR function takes
     bar("", ""); //~ ERROR mismatched types
     bar(1, 2);
-    bar(1, 2, 3); //~ ERROR this function takes
+    bar(1, 2, 3); //~ ERROR function takes
 }
diff --git a/src/test/ui/span/missing-unit-argument.rs b/src/test/ui/span/missing-unit-argument.rs
index 5b9861da6e8..db96ae223d9 100644
--- a/src/test/ui/span/missing-unit-argument.rs
+++ b/src/test/ui/span/missing-unit-argument.rs
@@ -9,9 +9,9 @@ impl S {
 
 fn main() {
     let _: Result<(), String> = Ok(); //~ ERROR this enum variant takes
-    foo(); //~ ERROR this function takes
-    foo(()); //~ ERROR this function takes
-    bar(); //~ ERROR this function takes
-    S.baz(); //~ ERROR this function takes
-    S.generic::<()>(); //~ ERROR this function takes
+    foo(); //~ ERROR function takes
+    foo(()); //~ ERROR function takes
+    bar(); //~ ERROR function takes
+    S.baz(); //~ ERROR this method takes
+    S.generic::<()>(); //~ ERROR this method takes
 }
diff --git a/src/test/ui/span/missing-unit-argument.stderr b/src/test/ui/span/missing-unit-argument.stderr
index 48a2e763af6..ef4d732b51d 100644
--- a/src/test/ui/span/missing-unit-argument.stderr
+++ b/src/test/ui/span/missing-unit-argument.stderr
@@ -59,7 +59,7 @@ help: provide the argument
 LL |     bar(());
    |        ~~~~
 
-error[E0061]: this function takes 1 argument but 0 arguments were supplied
+error[E0061]: this method takes 1 argument but 0 arguments were supplied
   --> $DIR/missing-unit-argument.rs:15:7
    |
 LL |     S.baz();
@@ -75,7 +75,7 @@ help: provide the argument
 LL |     S.baz(());
    |          ~~~~
 
-error[E0061]: this function takes 1 argument but 0 arguments were supplied
+error[E0061]: this method takes 1 argument but 0 arguments were supplied
   --> $DIR/missing-unit-argument.rs:16:7
    |
 LL |     S.generic::<()>();
diff --git a/src/test/ui/specialization/min_specialization/issue-79224.rs b/src/test/ui/specialization/min_specialization/issue-79224.rs
index 408732fe944..104bddd076e 100644
--- a/src/test/ui/specialization/min_specialization/issue-79224.rs
+++ b/src/test/ui/specialization/min_specialization/issue-79224.rs
@@ -15,8 +15,10 @@ impl ToString for Cow<'_, str> {
     }
 }
 
-impl<B: ?Sized> Display for Cow<'_, B> { //~ ERROR: the trait bound `B: Clone` is not satisfied [E0277]
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { //~ ERROR: the trait bound `B: Clone` is not satisfied [E0277]
+impl<B: ?Sized> Display for Cow<'_, B> {
+    //~^ ERROR: the trait bound `B: Clone` is not satisfied [E0277]
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        //~^ ERROR: the trait bound `B: Clone` is not satisfied [E0277]
         write!(f, "foo")
     }
 }
diff --git a/src/test/ui/specialization/min_specialization/issue-79224.stderr b/src/test/ui/specialization/min_specialization/issue-79224.stderr
index fd34a59d2bd..be6f04ae62a 100644
--- a/src/test/ui/specialization/min_specialization/issue-79224.stderr
+++ b/src/test/ui/specialization/min_specialization/issue-79224.stderr
@@ -1,12 +1,8 @@
 error[E0277]: the trait bound `B: Clone` is not satisfied
-  --> $DIR/issue-79224.rs:18:1
+  --> $DIR/issue-79224.rs:18:17
    |
-LL | / impl<B: ?Sized> Display for Cow<'_, B> {
-LL | |     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-LL | |         write!(f, "foo")
-LL | |     }
-LL | | }
-   | |_^ the trait `Clone` is not implemented for `B`
+LL | impl<B: ?Sized> Display for Cow<'_, B> {
+   |                 ^^^^^^^ the trait `Clone` is not implemented for `B`
    |
    = note: required for `B` to implement `ToOwned`
 help: consider further restricting this bound
@@ -15,12 +11,10 @@ LL | impl<B: ?Sized + std::clone::Clone> Display for Cow<'_, B> {
    |                +++++++++++++++++++
 
 error[E0277]: the trait bound `B: Clone` is not satisfied
-  --> $DIR/issue-79224.rs:19:5
+  --> $DIR/issue-79224.rs:20:12
    |
-LL | /     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-LL | |         write!(f, "foo")
-LL | |     }
-   | |_____^ the trait `Clone` is not implemented for `B`
+LL |     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+   |            ^^^^^ the trait `Clone` is not implemented for `B`
    |
    = note: required for `B` to implement `ToOwned`
 help: consider further restricting this bound
diff --git a/src/test/ui/suggestions/args-instead-of-tuple-errors.rs b/src/test/ui/suggestions/args-instead-of-tuple-errors.rs
index 5403b8d6d28..f5931a1baea 100644
--- a/src/test/ui/suggestions/args-instead-of-tuple-errors.rs
+++ b/src/test/ui/suggestions/args-instead-of-tuple-errors.rs
@@ -6,7 +6,7 @@ fn main() {
     let _: Option<(i32, bool)> = Some(1, 2);
     //~^ ERROR this enum variant takes 1 argument but 2 arguments were supplied
     int_bool(1, 2);
-    //~^ ERROR this function takes 1 argument but 2 arguments were supplied
+    //~^ ERROR function takes 1 argument but 2 arguments were supplied
 
     let _: Option<(i8,)> = Some();
     //~^ ERROR this enum variant takes 1 argument but 0 arguments were supplied
diff --git a/src/test/ui/suggestions/args-instead-of-tuple.fixed b/src/test/ui/suggestions/args-instead-of-tuple.fixed
index 66e53f9ce2c..f913995d7e2 100644
--- a/src/test/ui/suggestions/args-instead-of-tuple.fixed
+++ b/src/test/ui/suggestions/args-instead-of-tuple.fixed
@@ -5,11 +5,11 @@
 
 fn main() {
     let _: Result<(i32, i8), ()> = Ok((1, 2));
-    //~^ ERROR this enum variant takes 1 argument but 2 arguments were supplied
+    //~^ ERROR enum variant takes 1 argument but 2 arguments were supplied
     let _: Option<(i32, i8, &'static str)> = Some((1, 2, "hi"));
-    //~^ ERROR this enum variant takes 1 argument but 3 arguments were supplied
+    //~^ ERROR enum variant takes 1 argument but 3 arguments were supplied
     let _: Option<()> = Some(());
-    //~^ ERROR this enum variant takes 1 argument but 0 arguments were supplied
+    //~^ ERROR enum variant takes 1 argument but 0 arguments were supplied
 
     let _: Option<(i32,)> = Some((3,));
     //~^ ERROR mismatched types
@@ -17,9 +17,9 @@ fn main() {
     let _: Option<(i32,)> = Some((3,));
     //~^ ERROR mismatched types
 
-    two_ints((1, 2)); //~ ERROR this function takes 1 argument
+    two_ints((1, 2)); //~ ERROR function takes 1 argument
 
-    with_generic((3, 4)); //~ ERROR this function takes 1 argument
+    with_generic((3, 4)); //~ ERROR function takes 1 argument
 }
 
 fn two_ints(_: (i32, i32)) {
@@ -28,6 +28,6 @@ fn two_ints(_: (i32, i32)) {
 fn with_generic<T: Copy + Send>((a, b): (i32, T)) {
     if false {
         // test generics/bound handling
-        with_generic((a, b)); //~ ERROR this function takes 1 argument
+        with_generic((a, b)); //~ ERROR function takes 1 argument
     }
 }
diff --git a/src/test/ui/suggestions/args-instead-of-tuple.rs b/src/test/ui/suggestions/args-instead-of-tuple.rs
index a15bff07ebf..1c65407b395 100644
--- a/src/test/ui/suggestions/args-instead-of-tuple.rs
+++ b/src/test/ui/suggestions/args-instead-of-tuple.rs
@@ -5,11 +5,11 @@
 
 fn main() {
     let _: Result<(i32, i8), ()> = Ok(1, 2);
-    //~^ ERROR this enum variant takes 1 argument but 2 arguments were supplied
+    //~^ ERROR enum variant takes 1 argument but 2 arguments were supplied
     let _: Option<(i32, i8, &'static str)> = Some(1, 2, "hi");
-    //~^ ERROR this enum variant takes 1 argument but 3 arguments were supplied
+    //~^ ERROR enum variant takes 1 argument but 3 arguments were supplied
     let _: Option<()> = Some();
-    //~^ ERROR this enum variant takes 1 argument but 0 arguments were supplied
+    //~^ ERROR enum variant takes 1 argument but 0 arguments were supplied
 
     let _: Option<(i32,)> = Some(3);
     //~^ ERROR mismatched types
@@ -17,9 +17,9 @@ fn main() {
     let _: Option<(i32,)> = Some((3));
     //~^ ERROR mismatched types
 
-    two_ints(1, 2); //~ ERROR this function takes 1 argument
+    two_ints(1, 2); //~ ERROR function takes 1 argument
 
-    with_generic(3, 4); //~ ERROR this function takes 1 argument
+    with_generic(3, 4); //~ ERROR function takes 1 argument
 }
 
 fn two_ints(_: (i32, i32)) {
@@ -28,6 +28,6 @@ fn two_ints(_: (i32, i32)) {
 fn with_generic<T: Copy + Send>((a, b): (i32, T)) {
     if false {
         // test generics/bound handling
-        with_generic(a, b); //~ ERROR this function takes 1 argument
+        with_generic(a, b); //~ ERROR function takes 1 argument
     }
 }
diff --git a/src/test/ui/suggestions/args-instead-of-tuple.stderr b/src/test/ui/suggestions/args-instead-of-tuple.stderr
index c8499010d68..3ed9dbf4abb 100644
--- a/src/test/ui/suggestions/args-instead-of-tuple.stderr
+++ b/src/test/ui/suggestions/args-instead-of-tuple.stderr
@@ -1,4 +1,4 @@
-error[E0061]: this enum variant takes 1 argument but 2 arguments were supplied
+error[E0061]: enum variant takes 1 argument but 2 arguments were supplied
   --> $DIR/args-instead-of-tuple.rs:7:36
    |
 LL |     let _: Result<(i32, i8), ()> = Ok(1, 2);
@@ -11,7 +11,7 @@ help: wrap these arguments in parentheses to construct a tuple
 LL |     let _: Result<(i32, i8), ()> = Ok((1, 2));
    |                                       +    +
 
-error[E0061]: this enum variant takes 1 argument but 3 arguments were supplied
+error[E0061]: enum variant takes 1 argument but 3 arguments were supplied
   --> $DIR/args-instead-of-tuple.rs:9:46
    |
 LL |     let _: Option<(i32, i8, &'static str)> = Some(1, 2, "hi");
@@ -71,7 +71,7 @@ help: use a trailing comma to create a tuple with one element
 LL |     let _: Option<(i32,)> = Some((3,));
    |                                    +
 
-error[E0061]: this function takes 1 argument but 2 arguments were supplied
+error[E0061]: function takes 1 argument but 2 arguments were supplied
   --> $DIR/args-instead-of-tuple.rs:20:5
    |
 LL |     two_ints(1, 2);
@@ -87,7 +87,7 @@ help: wrap these arguments in parentheses to construct a tuple
 LL |     two_ints((1, 2));
    |              +    +
 
-error[E0061]: this function takes 1 argument but 2 arguments were supplied
+error[E0061]: function takes 1 argument but 2 arguments were supplied
   --> $DIR/args-instead-of-tuple.rs:22:5
    |
 LL |     with_generic(3, 4);
@@ -103,7 +103,7 @@ help: wrap these arguments in parentheses to construct a tuple
 LL |     with_generic((3, 4));
    |                  +    +
 
-error[E0061]: this function takes 1 argument but 2 arguments were supplied
+error[E0061]: function takes 1 argument but 2 arguments were supplied
   --> $DIR/args-instead-of-tuple.rs:31:9
    |
 LL |         with_generic(a, b);
diff --git a/src/test/ui/suggestions/imm-ref-trait-object.rs b/src/test/ui/suggestions/imm-ref-trait-object.rs
index 288d6c699f5..c1c969b90e4 100644
--- a/src/test/ui/suggestions/imm-ref-trait-object.rs
+++ b/src/test/ui/suggestions/imm-ref-trait-object.rs
@@ -1,5 +1,5 @@
 fn test(t: &dyn Iterator<Item=&u64>) -> u64 {
-     t.min().unwrap() //~ ERROR the `min` method cannot be invoked on a trait object
+     t.min().unwrap() //~ ERROR the `min` method cannot be invoked on `&dyn Iterator<Item = &u64>`
 }
 
 fn main() {
diff --git a/src/test/ui/suggestions/imm-ref-trait-object.stderr b/src/test/ui/suggestions/imm-ref-trait-object.stderr
index 7791b308d5d..f7f7902c17d 100644
--- a/src/test/ui/suggestions/imm-ref-trait-object.stderr
+++ b/src/test/ui/suggestions/imm-ref-trait-object.stderr
@@ -1,13 +1,13 @@
-error: the `min` method cannot be invoked on a trait object
+error: the `min` method cannot be invoked on `&dyn Iterator<Item = &u64>`
   --> $DIR/imm-ref-trait-object.rs:2:8
    |
 LL |      t.min().unwrap()
    |        ^^^
-  --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
    |
-   = note: this has a `Sized` requirement
+help: you need `&mut dyn Iterator<Item = &u64>` instead of `&dyn Iterator<Item = &u64>`
    |
-   = note: you need `&mut dyn Iterator<Item = &u64>` instead of `&dyn Iterator<Item = &u64>`
+LL | fn test(t: &mut dyn Iterator<Item=&u64>) -> u64 {
+   |             +++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/suggestions/impl-trait-missing-lifetime-gated.rs b/src/test/ui/suggestions/impl-trait-missing-lifetime-gated.rs
index 9839e973bdf..a1a51c4814e 100644
--- a/src/test/ui/suggestions/impl-trait-missing-lifetime-gated.rs
+++ b/src/test/ui/suggestions/impl-trait-missing-lifetime-gated.rs
@@ -60,4 +60,9 @@ mod in_path {
     //~| ERROR missing lifetime specifier
 }
 
+// This must not err, as the `&` actually resolves to `'a`.
+fn resolved_anonymous<'a, T>(f: impl Fn(&'a str) -> &T) {
+    f("f")
+}
+
 fn main() {}
diff --git a/src/test/ui/suggestions/issue-106443-sugg-clone-for-arg.rs b/src/test/ui/suggestions/issue-106443-sugg-clone-for-arg.rs
new file mode 100644
index 00000000000..48efdb82c46
--- /dev/null
+++ b/src/test/ui/suggestions/issue-106443-sugg-clone-for-arg.rs
@@ -0,0 +1,23 @@
+#[derive(Clone)]
+struct S;
+
+// without Clone
+struct T;
+
+fn foo(_: S) {}
+
+fn test1() {
+    let s = &S;
+    foo(s); //~ ERROR mismatched types
+}
+
+fn bar(_: T) {}
+fn test2() {
+    let t = &T;
+    bar(t); //~ ERROR mismatched types
+}
+
+fn main() {
+    test1();
+    test2();
+}
diff --git a/src/test/ui/suggestions/issue-106443-sugg-clone-for-arg.stderr b/src/test/ui/suggestions/issue-106443-sugg-clone-for-arg.stderr
new file mode 100644
index 00000000000..1e66fe3af24
--- /dev/null
+++ b/src/test/ui/suggestions/issue-106443-sugg-clone-for-arg.stderr
@@ -0,0 +1,35 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-106443-sugg-clone-for-arg.rs:11:9
+   |
+LL |     foo(s);
+   |     --- ^ expected struct `S`, found `&S`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/issue-106443-sugg-clone-for-arg.rs:7:4
+   |
+LL | fn foo(_: S) {}
+   |    ^^^ ----
+help: consider using clone here
+   |
+LL |     foo(s.clone());
+   |          ++++++++
+
+error[E0308]: mismatched types
+  --> $DIR/issue-106443-sugg-clone-for-arg.rs:17:9
+   |
+LL |     bar(t);
+   |     --- ^ expected struct `T`, found `&T`
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/issue-106443-sugg-clone-for-arg.rs:14:4
+   |
+LL | fn bar(_: T) {}
+   |    ^^^ ----
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/suggestions/issue-106443-sugg-clone-for-bound.rs b/src/test/ui/suggestions/issue-106443-sugg-clone-for-bound.rs
new file mode 100644
index 00000000000..3b2e316b296
--- /dev/null
+++ b/src/test/ui/suggestions/issue-106443-sugg-clone-for-bound.rs
@@ -0,0 +1,20 @@
+#[derive(Clone)]
+struct S;
+
+trait X {}
+
+impl X for S {}
+
+fn foo<T: X>(_: T) {}
+fn bar<T: X>(s: &T) {
+    foo(s); //~ ERROR the trait bound `&T: X` is not satisfied
+}
+
+fn bar_with_clone<T: X + Clone>(s: &T) {
+    foo(s); //~ ERROR the trait bound `&T: X` is not satisfied
+}
+
+fn main() {
+    let s = &S;
+    bar(s);
+}
diff --git a/src/test/ui/suggestions/issue-106443-sugg-clone-for-bound.stderr b/src/test/ui/suggestions/issue-106443-sugg-clone-for-bound.stderr
new file mode 100644
index 00000000000..8607917ede6
--- /dev/null
+++ b/src/test/ui/suggestions/issue-106443-sugg-clone-for-bound.stderr
@@ -0,0 +1,29 @@
+error[E0277]: the trait bound `&T: X` is not satisfied
+  --> $DIR/issue-106443-sugg-clone-for-bound.rs:10:9
+   |
+LL |     foo(s);
+   |         ^ the trait `X` is not implemented for `&T`
+   |
+help: consider further restricting this bound
+   |
+LL | fn bar<T: X + Clone>(s: &T) {
+   |             +++++++
+help: consider using clone here
+   |
+LL |     foo(s.clone());
+   |          ++++++++
+
+error[E0277]: the trait bound `&T: X` is not satisfied
+  --> $DIR/issue-106443-sugg-clone-for-bound.rs:14:9
+   |
+LL |     foo(s);
+   |         ^ the trait `X` is not implemented for `&T`
+   |
+help: consider using clone here
+   |
+LL |     foo(s.clone());
+   |          ++++++++
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/suggestions/missing-type-param-used-in-param.fixed b/src/test/ui/suggestions/missing-type-param-used-in-param.fixed
index cc4120041b9..be439403104 100644
--- a/src/test/ui/suggestions/missing-type-param-used-in-param.fixed
+++ b/src/test/ui/suggestions/missing-type-param-used-in-param.fixed
@@ -3,6 +3,6 @@
 fn two_type_params<A, B>(_: B) {}
 
 fn main() {
-    two_type_params::<String, _>(100); //~ ERROR this function takes 2 generic arguments
+    two_type_params::<String, _>(100); //~ ERROR function takes 2 generic arguments
     two_type_params::<String, _>(100);
 }
diff --git a/src/test/ui/suggestions/missing-type-param-used-in-param.rs b/src/test/ui/suggestions/missing-type-param-used-in-param.rs
index 19286331b60..d444998d35b 100644
--- a/src/test/ui/suggestions/missing-type-param-used-in-param.rs
+++ b/src/test/ui/suggestions/missing-type-param-used-in-param.rs
@@ -3,6 +3,6 @@
 fn two_type_params<A, B>(_: B) {}
 
 fn main() {
-    two_type_params::<String>(100); //~ ERROR this function takes 2 generic arguments
+    two_type_params::<String>(100); //~ ERROR function takes 2 generic arguments
     two_type_params::<String, _>(100);
 }
diff --git a/src/test/ui/suggestions/sugg-else-for-closure.stderr b/src/test/ui/suggestions/sugg-else-for-closure.stderr
index da4db46aad3..5f59d0f541c 100644
--- a/src/test/ui/suggestions/sugg-else-for-closure.stderr
+++ b/src/test/ui/suggestions/sugg-else-for-closure.stderr
@@ -4,7 +4,7 @@ error[E0308]: mismatched types
 LL |     let _s = y.unwrap_or(|| x.split('.').nth(1).unwrap());
    |                --------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `&str`, found closure
    |                |
-   |                arguments to this function are incorrect
+   |                arguments to this method are incorrect
    |
    = note: expected reference `&str`
                 found closure `[closure@$DIR/sugg-else-for-closure.rs:6:26: 6:28]`
diff --git a/src/test/ui/suggestions/trait-with-missing-associated-type-restriction.stderr b/src/test/ui/suggestions/trait-with-missing-associated-type-restriction.stderr
index 7583c875a1a..f520d88c6ba 100644
--- a/src/test/ui/suggestions/trait-with-missing-associated-type-restriction.stderr
+++ b/src/test/ui/suggestions/trait-with-missing-associated-type-restriction.stderr
@@ -78,7 +78,7 @@ error[E0308]: mismatched types
 LL |     x.funk(3);
    |       ---- ^ expected associated type, found integer
    |       |
-   |       arguments to this function are incorrect
+   |       arguments to this method are incorrect
    |
    = note: expected associated type `<T as Trait<i32>>::A`
                          found type `{integer}`
diff --git a/src/test/ui/tag-type-args.stderr b/src/test/ui/tag-type-args.stderr
index 107af76413d..5b54880a685 100644
--- a/src/test/ui/tag-type-args.stderr
+++ b/src/test/ui/tag-type-args.stderr
@@ -12,7 +12,7 @@ LL | enum Quux<T> { Bar }
 help: add missing generic argument
    |
 LL | fn foo(c: Quux<T>) { assert!((false)); }
-   |           ~~~~~~~
+   |               +++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/traits/impl-method-mismatch.rs b/src/test/ui/traits/impl-method-mismatch.rs
index 683b1c1aa43..62580755c81 100644
--- a/src/test/ui/traits/impl-method-mismatch.rs
+++ b/src/test/ui/traits/impl-method-mismatch.rs
@@ -6,8 +6,8 @@ impl Mumbo for usize {
     // Cannot have a larger effect than the trait:
     unsafe fn jumbo(&self, x: &usize) { *self + *x; }
     //~^ ERROR method `jumbo` has an incompatible type for trait
-    //~| expected fn pointer `fn
-    //~| found fn pointer `unsafe fn
+    //~| expected signature `fn
+    //~| found signature `unsafe fn
 }
 
 fn main() {}
diff --git a/src/test/ui/traits/impl-method-mismatch.stderr b/src/test/ui/traits/impl-method-mismatch.stderr
index 30aa97d2934..252b5aff96a 100644
--- a/src/test/ui/traits/impl-method-mismatch.stderr
+++ b/src/test/ui/traits/impl-method-mismatch.stderr
@@ -9,8 +9,8 @@ note: type in trait
    |
 LL |     fn jumbo(&self, x: &usize) -> usize;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = note: expected fn pointer `fn(&usize, &usize) -> usize`
-              found fn pointer `unsafe fn(&usize, &usize)`
+   = note: expected signature `fn(&usize, &usize) -> usize`
+              found signature `unsafe fn(&usize, &usize)`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/traits/issue-35869.stderr b/src/test/ui/traits/issue-35869.stderr
index 0780109b843..6d985bdeaf8 100644
--- a/src/test/ui/traits/issue-35869.stderr
+++ b/src/test/ui/traits/issue-35869.stderr
@@ -12,8 +12,8 @@ note: type in trait
    |
 LL |     fn foo(_: fn(u8) -> ());
    |               ^^^^^^^^^^^^
-   = note: expected fn pointer `fn(fn(u8))`
-              found fn pointer `fn(fn(u16))`
+   = note: expected signature `fn(fn(u8))`
+              found signature `fn(fn(u16))`
 
 error[E0053]: method `bar` has an incompatible type for trait
   --> $DIR/issue-35869.rs:13:15
@@ -29,8 +29,8 @@ note: type in trait
    |
 LL |     fn bar(_: Option<u8>);
    |               ^^^^^^^^^^
-   = note: expected fn pointer `fn(Option<u8>)`
-              found fn pointer `fn(Option<u16>)`
+   = note: expected signature `fn(Option<u8>)`
+              found signature `fn(Option<u16>)`
 
 error[E0053]: method `baz` has an incompatible type for trait
   --> $DIR/issue-35869.rs:15:15
@@ -46,8 +46,8 @@ note: type in trait
    |
 LL |     fn baz(_: (u8, u16));
    |               ^^^^^^^^^
-   = note: expected fn pointer `fn((u8, _))`
-              found fn pointer `fn((u16, _))`
+   = note: expected signature `fn((u8, _))`
+              found signature `fn((u16, _))`
 
 error[E0053]: method `qux` has an incompatible type for trait
   --> $DIR/issue-35869.rs:17:17
@@ -63,8 +63,8 @@ note: type in trait
    |
 LL |     fn qux() -> u8;
    |                 ^^
-   = note: expected fn pointer `fn() -> u8`
-              found fn pointer `fn() -> u16`
+   = note: expected signature `fn() -> u8`
+              found signature `fn() -> u16`
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/traits/issue-52893.stderr b/src/test/ui/traits/issue-52893.stderr
index 0ee44921bf5..7924d3db06f 100644
--- a/src/test/ui/traits/issue-52893.stderr
+++ b/src/test/ui/traits/issue-52893.stderr
@@ -7,7 +7,7 @@ LL | impl<F, Name, P> AddClass<Name, F> for Class<P>
 LL |         builder.push(output);
    |                 ---- ^^^^^^ expected type parameter `F`, found struct `Class`
    |                 |
-   |                 arguments to this function are incorrect
+   |                 arguments to this method are incorrect
    |
    = note: expected type parameter `F`
                       found struct `Class<P>`
diff --git a/src/test/ui/traits/issue-91594.stderr b/src/test/ui/traits/issue-91594.stderr
index 5fcd090a834..9f9acf85113 100644
--- a/src/test/ui/traits/issue-91594.stderr
+++ b/src/test/ui/traits/issue-91594.stderr
@@ -1,8 +1,8 @@
 error[E0277]: the trait bound `Foo: HasComponent<()>` is not satisfied
-  --> $DIR/issue-91594.rs:10:1
+  --> $DIR/issue-91594.rs:10:6
    |
 LL | impl HasComponent<<Foo as Component<Foo>>::Interface> for Foo {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `HasComponent<()>` is not implemented for `Foo`
+   |      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `HasComponent<()>` is not implemented for `Foo`
    |
    = help: the trait `HasComponent<<Foo as Component<Foo>>::Interface>` is implemented for `Foo`
 note: required for `Foo` to implement `Component<Foo>`
diff --git a/src/test/ui/issues/issue-99875.rs b/src/test/ui/traits/issue-99875.rs
index cf73fd8d31f..cf73fd8d31f 100644
--- a/src/test/ui/issues/issue-99875.rs
+++ b/src/test/ui/traits/issue-99875.rs
diff --git a/src/test/ui/issues/issue-99875.stderr b/src/test/ui/traits/issue-99875.stderr
index 3ff8f12f1b8..3ff8f12f1b8 100644
--- a/src/test/ui/issues/issue-99875.stderr
+++ b/src/test/ui/traits/issue-99875.stderr
diff --git a/src/test/ui/traits/matching-lifetimes.stderr b/src/test/ui/traits/matching-lifetimes.stderr
index de1c878a513..f8119ed415d 100644
--- a/src/test/ui/traits/matching-lifetimes.stderr
+++ b/src/test/ui/traits/matching-lifetimes.stderr
@@ -4,8 +4,8 @@ error[E0308]: method not compatible with trait
 LL |     fn foo(x: Foo<'b,'a>) {
    |     ^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch
    |
-   = note: expected fn pointer `fn(Foo<'a, 'b>)`
-              found fn pointer `fn(Foo<'b, 'a>)`
+   = note: expected signature `fn(Foo<'a, 'b>)`
+              found signature `fn(Foo<'b, 'a>)`
 note: the lifetime `'b` as defined here...
   --> $DIR/matching-lifetimes.rs:13:9
    |
@@ -23,8 +23,8 @@ error[E0308]: method not compatible with trait
 LL |     fn foo(x: Foo<'b,'a>) {
    |     ^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch
    |
-   = note: expected fn pointer `fn(Foo<'a, 'b>)`
-              found fn pointer `fn(Foo<'b, 'a>)`
+   = note: expected signature `fn(Foo<'a, 'b>)`
+              found signature `fn(Foo<'b, 'a>)`
 note: the lifetime `'a` as defined here...
   --> $DIR/matching-lifetimes.rs:13:6
    |
diff --git a/src/test/ui/traits/param-without-lifetime-constraint.stderr b/src/test/ui/traits/param-without-lifetime-constraint.stderr
index 118b2cf3ecd..b128b6518ce 100644
--- a/src/test/ui/traits/param-without-lifetime-constraint.stderr
+++ b/src/test/ui/traits/param-without-lifetime-constraint.stderr
@@ -7,8 +7,8 @@ LL |     fn get_relation(&self) -> To;
 LL |     fn get_relation(&self) -> &ProofReader {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found `fn(&'1 Article) -> &'1 ProofReader`
    |
-   = note: expected `fn(&'1 Article) -> &'2 ProofReader`
-              found `fn(&'1 Article) -> &'1 ProofReader`
+   = note: expected signature `fn(&'1 Article) -> &'2 ProofReader`
+              found signature `fn(&'1 Article) -> &'1 ProofReader`
 help: the lifetime requirements from the `impl` do not correspond to the requirements in the `trait`
   --> $DIR/param-without-lifetime-constraint.rs:10:31
    |
diff --git a/src/test/ui/traits/safety-trait-impl-cc.stderr b/src/test/ui/traits/safety-trait-impl-cc.stderr
index 0b1fb30478f..0ca565787f6 100644
--- a/src/test/ui/traits/safety-trait-impl-cc.stderr
+++ b/src/test/ui/traits/safety-trait-impl-cc.stderr
@@ -1,12 +1,8 @@
 error[E0200]: the trait `Foo` requires an `unsafe impl` declaration
   --> $DIR/safety-trait-impl-cc.rs:9:1
    |
-LL | / impl lib::Foo for Bar {
-LL | |     fn foo(&self) -> isize {
-LL | |         panic!();
-LL | |     }
-LL | | }
-   | |_^
+LL | impl lib::Foo for Bar {
+   | ^^^^^^^^^^^^^^^^^^^^^
    |
    = note: the trait `Foo` enforces invariants that the compiler can't check. Review the trait documentation and make sure this implementation upholds those invariants before adding the `unsafe` keyword
 help: add `unsafe` to this trait implementation
diff --git a/src/test/ui/traits/safety-trait-impl.stderr b/src/test/ui/traits/safety-trait-impl.stderr
index 721e2b48b95..e78e0e3a6ba 100644
--- a/src/test/ui/traits/safety-trait-impl.stderr
+++ b/src/test/ui/traits/safety-trait-impl.stderr
@@ -2,7 +2,7 @@ error[E0200]: the trait `UnsafeTrait` requires an `unsafe impl` declaration
   --> $DIR/safety-trait-impl.rs:14:1
    |
 LL | impl UnsafeTrait for u16 { }
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: the trait `UnsafeTrait` enforces invariants that the compiler can't check. Review the trait documentation and make sure this implementation upholds those invariants before adding the `unsafe` keyword
 help: add `unsafe` to this trait implementation
@@ -14,7 +14,7 @@ error[E0199]: implementing the trait `SafeTrait` is not unsafe
   --> $DIR/safety-trait-impl.rs:16:1
    |
 LL | unsafe impl SafeTrait for u32 { }
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 help: remove `unsafe` from this trait implementation
    |
diff --git a/src/test/ui/traits/self-without-lifetime-constraint.stderr b/src/test/ui/traits/self-without-lifetime-constraint.stderr
index 85fada3b87c..05a49820a82 100644
--- a/src/test/ui/traits/self-without-lifetime-constraint.stderr
+++ b/src/test/ui/traits/self-without-lifetime-constraint.stderr
@@ -7,8 +7,8 @@ LL |     fn column_result(value: ValueRef<'_>) -> FromSqlResult<Self, &Self>;
 LL |     fn column_result(value: ValueRef<'_>) -> FromSqlResult<&str, &&str> {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found `fn(ValueRef<'1>) -> Result<(&'1 str, &'1 &'1 str), FromSqlError>`
    |
-   = note: expected `fn(ValueRef<'1>) -> Result<(&'2 str, &'1 &'2 str), FromSqlError>`
-              found `fn(ValueRef<'1>) -> Result<(&'1 str, &'1 &'1 str), FromSqlError>`
+   = note: expected signature `fn(ValueRef<'1>) -> Result<(&'2 str, &'1 &'2 str), FromSqlError>`
+              found signature `fn(ValueRef<'1>) -> Result<(&'1 str, &'1 &'1 str), FromSqlError>`
 help: the lifetime requirements from the `impl` do not correspond to the requirements in the `trait`
   --> $DIR/self-without-lifetime-constraint.rs:41:60
    |
diff --git a/src/test/ui/tuple/add-tuple-within-arguments.rs b/src/test/ui/tuple/add-tuple-within-arguments.rs
index 089c703fda5..01b13b29fb4 100644
--- a/src/test/ui/tuple/add-tuple-within-arguments.rs
+++ b/src/test/ui/tuple/add-tuple-within-arguments.rs
@@ -4,7 +4,7 @@ fn bar(s: &str, a: (&str,), s2: &str) {}
 
 fn main() {
     foo("hi", 1, 2, "hi");
-    //~^ ERROR this function takes 3 arguments but 4 arguments were supplied
+    //~^ ERROR function takes 3 arguments but 4 arguments were supplied
     bar("hi", "hi", "hi");
     //~^ ERROR mismatched types
 }
diff --git a/src/test/ui/tuple/add-tuple-within-arguments.stderr b/src/test/ui/tuple/add-tuple-within-arguments.stderr
index 7029d298d71..2e20a4cca08 100644
--- a/src/test/ui/tuple/add-tuple-within-arguments.stderr
+++ b/src/test/ui/tuple/add-tuple-within-arguments.stderr
@@ -1,4 +1,4 @@
-error[E0061]: this function takes 3 arguments but 4 arguments were supplied
+error[E0061]: function takes 3 arguments but 4 arguments were supplied
   --> $DIR/add-tuple-within-arguments.rs:6:5
    |
 LL |     foo("hi", 1, 2, "hi");
diff --git a/src/test/ui/tuple/wrong_argument_ice-2.rs b/src/test/ui/tuple/wrong_argument_ice-2.rs
index b0f814616f2..e1c1d748fec 100644
--- a/src/test/ui/tuple/wrong_argument_ice-2.rs
+++ b/src/test/ui/tuple/wrong_argument_ice-2.rs
@@ -11,7 +11,7 @@ impl Foo {
 fn bar() {
     let x = Foo;
     test(x.qux(), x.qux());
-    //~^ ERROR this function takes 1 argument but 2 arguments were supplied
+    //~^ ERROR function takes 1 argument but 2 arguments were supplied
 }
 
 fn main() {}
diff --git a/src/test/ui/tuple/wrong_argument_ice-2.stderr b/src/test/ui/tuple/wrong_argument_ice-2.stderr
index 0c2a4c41461..41244209214 100644
--- a/src/test/ui/tuple/wrong_argument_ice-2.stderr
+++ b/src/test/ui/tuple/wrong_argument_ice-2.stderr
@@ -1,4 +1,4 @@
-error[E0061]: this function takes 1 argument but 2 arguments were supplied
+error[E0061]: function takes 1 argument but 2 arguments were supplied
   --> $DIR/wrong_argument_ice-2.rs:13:5
    |
 LL |     test(x.qux(), x.qux());
diff --git a/src/test/ui/tuple/wrong_argument_ice-3.rs b/src/test/ui/tuple/wrong_argument_ice-3.rs
index 951687c3759..96633180b57 100644
--- a/src/test/ui/tuple/wrong_argument_ice-3.rs
+++ b/src/test/ui/tuple/wrong_argument_ice-3.rs
@@ -7,7 +7,7 @@ fn test(process: &Process, groups: Vec<Group>) -> Vec<Group> {
 
     if groups.capacity() == 0 {
         groups.push(new_group, vec![process]);
-        //~^ ERROR this function takes 1 argument but 2 arguments were supplied
+        //~^ ERROR this method takes 1 argument but 2 arguments were supplied
         return groups;
     }
 
diff --git a/src/test/ui/tuple/wrong_argument_ice-3.stderr b/src/test/ui/tuple/wrong_argument_ice-3.stderr
index fe3712ef839..0a503e1fe58 100644
--- a/src/test/ui/tuple/wrong_argument_ice-3.stderr
+++ b/src/test/ui/tuple/wrong_argument_ice-3.stderr
@@ -1,4 +1,4 @@
-error[E0061]: this function takes 1 argument but 2 arguments were supplied
+error[E0061]: this method takes 1 argument but 2 arguments were supplied
   --> $DIR/wrong_argument_ice-3.rs:9:16
    |
 LL |         groups.push(new_group, vec![process]);
diff --git a/src/test/ui/tuple/wrong_argument_ice-4.rs b/src/test/ui/tuple/wrong_argument_ice-4.rs
index 479bd0d819f..883d92dcce1 100644
--- a/src/test/ui/tuple/wrong_argument_ice-4.rs
+++ b/src/test/ui/tuple/wrong_argument_ice-4.rs
@@ -1,6 +1,6 @@
 fn main() {
     (|| {})(|| {
-        //~^ ERROR this function takes 0 arguments but 1 argument was supplied
+        //~^ ERROR function takes 0 arguments but 1 argument was supplied
         let b = 1;
     });
 }
diff --git a/src/test/ui/tuple/wrong_argument_ice.rs b/src/test/ui/tuple/wrong_argument_ice.rs
index da967d8c146..b7e0225feb7 100644
--- a/src/test/ui/tuple/wrong_argument_ice.rs
+++ b/src/test/ui/tuple/wrong_argument_ice.rs
@@ -9,7 +9,7 @@ pub struct BuildPlanBuilder {
 impl BuildPlanBuilder {
     pub fn or(&mut self) -> &mut Self {
         self.acc.push_back(self.current_provides, self.current_requires);
-        //~^ ERROR this function takes 1 argument but 2 arguments were supplied
+        //~^ ERROR method takes 1 argument but 2 arguments were supplied
         self
     }
 }
diff --git a/src/test/ui/tuple/wrong_argument_ice.stderr b/src/test/ui/tuple/wrong_argument_ice.stderr
index 452413fc516..f1b00ae0b92 100644
--- a/src/test/ui/tuple/wrong_argument_ice.stderr
+++ b/src/test/ui/tuple/wrong_argument_ice.stderr
@@ -1,4 +1,4 @@
-error[E0061]: this function takes 1 argument but 2 arguments were supplied
+error[E0061]: method takes 1 argument but 2 arguments were supplied
   --> $DIR/wrong_argument_ice.rs:11:18
    |
 LL |         self.acc.push_back(self.current_provides, self.current_requires);
diff --git a/src/test/ui/type/ascription/issue-34255-1.stderr b/src/test/ui/type/ascription/issue-34255-1.stderr
index fd43e1114c8..fafff19f8f6 100644
--- a/src/test/ui/type/ascription/issue-34255-1.stderr
+++ b/src/test/ui/type/ascription/issue-34255-1.stderr
@@ -28,7 +28,7 @@ LL |         input_cells: Vec::new()
 help: add missing generic argument
    |
 LL |         input_cells: Vec<T>::new()
-   |                      ~~~~~~
+   |                         +++
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/type/binding-assigned-block-without-tail-expression.rs b/src/test/ui/type/binding-assigned-block-without-tail-expression.rs
new file mode 100644
index 00000000000..09afd27a079
--- /dev/null
+++ b/src/test/ui/type/binding-assigned-block-without-tail-expression.rs
@@ -0,0 +1,22 @@
+struct S;
+fn main() {
+    let x = {
+        println!("foo");
+        42;
+    };
+    let y = {};
+    let z = {
+        "hi";
+    };
+    let s = {
+        S;
+    };
+    println!("{}", x); //~ ERROR E0277
+    println!("{}", y); //~ ERROR E0277
+    println!("{}", z); //~ ERROR E0277
+    println!("{}", s); //~ ERROR E0277
+    let _: i32 = x; //~ ERROR E0308
+    let _: i32 = y; //~ ERROR E0308
+    let _: i32 = z; //~ ERROR E0308
+    let _: i32 = s; //~ ERROR E0308
+}
diff --git a/src/test/ui/type/binding-assigned-block-without-tail-expression.stderr b/src/test/ui/type/binding-assigned-block-without-tail-expression.stderr
new file mode 100644
index 00000000000..3e96d7f317b
--- /dev/null
+++ b/src/test/ui/type/binding-assigned-block-without-tail-expression.stderr
@@ -0,0 +1,109 @@
+error[E0277]: `()` doesn't implement `std::fmt::Display`
+  --> $DIR/binding-assigned-block-without-tail-expression.rs:14:20
+   |
+LL |         42;
+   |           - help: remove this semicolon
+...
+LL |     println!("{}", x);
+   |                    ^ `()` cannot be formatted with the default formatter
+   |
+   = help: the trait `std::fmt::Display` is not implemented for `()`
+   = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
+   = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: `()` doesn't implement `std::fmt::Display`
+  --> $DIR/binding-assigned-block-without-tail-expression.rs:15:20
+   |
+LL |     let y = {};
+   |             -- this empty block is missing a tail expression
+...
+LL |     println!("{}", y);
+   |                    ^ `()` cannot be formatted with the default formatter
+   |
+   = help: the trait `std::fmt::Display` is not implemented for `()`
+   = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
+   = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: `()` doesn't implement `std::fmt::Display`
+  --> $DIR/binding-assigned-block-without-tail-expression.rs:16:20
+   |
+LL |         "hi";
+   |             - help: remove this semicolon
+...
+LL |     println!("{}", z);
+   |                    ^ `()` cannot be formatted with the default formatter
+   |
+   = help: the trait `std::fmt::Display` is not implemented for `()`
+   = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
+   = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: `()` doesn't implement `std::fmt::Display`
+  --> $DIR/binding-assigned-block-without-tail-expression.rs:17:20
+   |
+LL |       let s = {
+   |  _____________-
+LL | |         S;
+LL | |     };
+   | |_____- this block is missing a tail expression
+...
+LL |       println!("{}", s);
+   |                      ^ `()` cannot be formatted with the default formatter
+   |
+   = help: the trait `std::fmt::Display` is not implemented for `()`
+   = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
+   = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0308]: mismatched types
+  --> $DIR/binding-assigned-block-without-tail-expression.rs:18:18
+   |
+LL |         42;
+   |           - help: remove this semicolon
+...
+LL |     let _: i32 = x;
+   |            ---   ^ expected `i32`, found `()`
+   |            |
+   |            expected due to this
+
+error[E0308]: mismatched types
+  --> $DIR/binding-assigned-block-without-tail-expression.rs:19:18
+   |
+LL |     let y = {};
+   |             -- this empty block is missing a tail expression
+...
+LL |     let _: i32 = y;
+   |            ---   ^ expected `i32`, found `()`
+   |            |
+   |            expected due to this
+
+error[E0308]: mismatched types
+  --> $DIR/binding-assigned-block-without-tail-expression.rs:20:18
+   |
+LL |       let z = {
+   |  _____________-
+LL | |         "hi";
+LL | |     };
+   | |_____- this block is missing a tail expression
+...
+LL |       let _: i32 = z;
+   |              ---   ^ expected `i32`, found `()`
+   |              |
+   |              expected due to this
+
+error[E0308]: mismatched types
+  --> $DIR/binding-assigned-block-without-tail-expression.rs:21:18
+   |
+LL |       let s = {
+   |  _____________-
+LL | |         S;
+LL | |     };
+   | |_____- this block is missing a tail expression
+...
+LL |       let _: i32 = s;
+   |              ---   ^ expected `i32`, found `()`
+   |              |
+   |              expected due to this
+
+error: aborting due to 8 previous errors
+
+Some errors have detailed explanations: E0277, E0308.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/type/closure-with-wrong-borrows.rs b/src/test/ui/type/closure-with-wrong-borrows.rs
new file mode 100644
index 00000000000..5f6a78351a2
--- /dev/null
+++ b/src/test/ui/type/closure-with-wrong-borrows.rs
@@ -0,0 +1,10 @@
+struct S<'a>(&'a str);
+
+fn f(inner: fn(&str, &S)) {
+}
+
+#[allow(unreachable_code)]
+fn main() {
+    let inner: fn(_, _) = unimplemented!();
+    f(inner); //~ ERROR mismatched types
+}
diff --git a/src/test/ui/type/closure-with-wrong-borrows.stderr b/src/test/ui/type/closure-with-wrong-borrows.stderr
new file mode 100644
index 00000000000..7370bc76467
--- /dev/null
+++ b/src/test/ui/type/closure-with-wrong-borrows.stderr
@@ -0,0 +1,19 @@
+error[E0308]: mismatched types
+  --> $DIR/closure-with-wrong-borrows.rs:9:7
+   |
+LL |     f(inner);
+   |     - ^^^^^ one type is more general than the other
+   |     |
+   |     arguments to this function are incorrect
+   |
+   = note: expected fn pointer `for<'a, 'b, 'c> fn(&'a str, &'b S<'c>)`
+              found fn pointer `fn(_, _)`
+note: function defined here
+  --> $DIR/closure-with-wrong-borrows.rs:3:4
+   |
+LL | fn f(inner: fn(&str, &S)) {
+   |    ^ -------------------
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/type/issue-58355.rs b/src/test/ui/type/issue-58355.rs
new file mode 100644
index 00000000000..3b62fdece40
--- /dev/null
+++ b/src/test/ui/type/issue-58355.rs
@@ -0,0 +1,7 @@
+#![crate_type = "lib"]
+
+pub fn foo(callback: fn() -> dyn ToString) {
+    let mut x: Option<Box<dyn Fn() -> dyn ToString>> = None;
+    x = Some(Box::new(callback));
+    //~^ ERROR: the size for values of type `dyn ToString` cannot be known at compilation time
+}
diff --git a/src/test/ui/type/issue-58355.stderr b/src/test/ui/type/issue-58355.stderr
new file mode 100644
index 00000000000..6f89a7b0049
--- /dev/null
+++ b/src/test/ui/type/issue-58355.stderr
@@ -0,0 +1,13 @@
+error[E0277]: the size for values of type `dyn ToString` cannot be known at compilation time
+  --> $DIR/issue-58355.rs:5:14
+   |
+LL |     x = Some(Box::new(callback));
+   |              ^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: within `fn() -> dyn ToString`, the trait `Sized` is not implemented for `dyn ToString`
+   = note: required because it appears within the type `fn() -> dyn ToString`
+   = note: required for the cast from `fn() -> dyn ToString` to the object type `dyn Fn() -> (dyn ToString + 'static)`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/type/type-ascription-instead-of-initializer.rs b/src/test/ui/type/type-ascription-instead-of-initializer.rs
index 9f9b6f06bbc..8978c85ed49 100644
--- a/src/test/ui/type/type-ascription-instead-of-initializer.rs
+++ b/src/test/ui/type/type-ascription-instead-of-initializer.rs
@@ -1,4 +1,4 @@
 fn main() {
     let x: Vec::with_capacity(10, 20);  //~ ERROR expected type, found `10`
-    //~^ ERROR this function takes 1 argument
+    //~^ ERROR function takes 1 argument
 }
diff --git a/src/test/ui/type/type-check/assignment-in-if.stderr b/src/test/ui/type/type-check/assignment-in-if.stderr
index 9f4558adab1..de133e5599c 100644
--- a/src/test/ui/type/type-check/assignment-in-if.stderr
+++ b/src/test/ui/type/type-check/assignment-in-if.stderr
@@ -67,6 +67,9 @@ LL |             x == 5
 error[E0308]: mismatched types
   --> $DIR/assignment-in-if.rs:44:18
    |
+LL |     if y = (Foo { foo: x }) {
+   |                        - here the type of `x` is inferred to be `usize`
+...
 LL |     if x == x && x = x && x == x {
    |        ------    ^ expected `bool`, found `usize`
    |        |
@@ -75,6 +78,9 @@ LL |     if x == x && x = x && x == x {
 error[E0308]: mismatched types
   --> $DIR/assignment-in-if.rs:44:22
    |
+LL |     if y = (Foo { foo: x }) {
+   |                        - here the type of `x` is inferred to be `usize`
+...
 LL |     if x == x && x = x && x == x {
    |                      ^ expected `bool`, found `usize`
 
@@ -92,6 +98,9 @@ LL |     if x == x && x == x && x == x {
 error[E0308]: mismatched types
   --> $DIR/assignment-in-if.rs:51:28
    |
+LL |     if y = (Foo { foo: x }) {
+   |                        - here the type of `x` is inferred to be `usize`
+...
 LL |     if x == x && x == x && x = x {
    |        ----------------    ^ expected `bool`, found `usize`
    |        |
diff --git a/src/test/ui/type/type-check/point-at-inference-2.rs b/src/test/ui/type/type-check/point-at-inference-2.rs
new file mode 100644
index 00000000000..6557d7fa191
--- /dev/null
+++ b/src/test/ui/type/type-check/point-at-inference-2.rs
@@ -0,0 +1,13 @@
+fn bar(_: Vec<i32>) {}
+fn baz(_: &Vec<&i32>) {}
+fn main() {
+    let v = vec![&1];
+    bar(v); //~ ERROR E0308
+    let v = vec![];
+    baz(&v);
+    baz(&v);
+    bar(v); //~ ERROR E0308
+    let v = vec![];
+    baz(&v);
+    bar(v); //~ ERROR E0308
+}
diff --git a/src/test/ui/type/type-check/point-at-inference-2.stderr b/src/test/ui/type/type-check/point-at-inference-2.stderr
new file mode 100644
index 00000000000..13227c5e245
--- /dev/null
+++ b/src/test/ui/type/type-check/point-at-inference-2.stderr
@@ -0,0 +1,56 @@
+error[E0308]: mismatched types
+  --> $DIR/point-at-inference-2.rs:5:9
+   |
+LL |     bar(v);
+   |     --- ^ expected `i32`, found `&{integer}`
+   |     |
+   |     arguments to this function are incorrect
+   |
+   = note: expected struct `Vec<i32>`
+              found struct `Vec<&{integer}>`
+note: function defined here
+  --> $DIR/point-at-inference-2.rs:1:4
+   |
+LL | fn bar(_: Vec<i32>) {}
+   |    ^^^ -----------
+
+error[E0308]: mismatched types
+  --> $DIR/point-at-inference-2.rs:9:9
+   |
+LL |     baz(&v);
+   |          - here the type of `v` is inferred to be `Vec<&i32>`
+LL |     baz(&v);
+LL |     bar(v);
+   |     --- ^ expected `i32`, found `&i32`
+   |     |
+   |     arguments to this function are incorrect
+   |
+   = note: expected struct `Vec<i32>`
+              found struct `Vec<&i32>`
+note: function defined here
+  --> $DIR/point-at-inference-2.rs:1:4
+   |
+LL | fn bar(_: Vec<i32>) {}
+   |    ^^^ -----------
+
+error[E0308]: mismatched types
+  --> $DIR/point-at-inference-2.rs:12:9
+   |
+LL |     baz(&v);
+   |          - here the type of `v` is inferred to be `Vec<&i32>`
+LL |     bar(v);
+   |     --- ^ expected `i32`, found `&i32`
+   |     |
+   |     arguments to this function are incorrect
+   |
+   = note: expected struct `Vec<i32>`
+              found struct `Vec<&i32>`
+note: function defined here
+  --> $DIR/point-at-inference-2.rs:1:4
+   |
+LL | fn bar(_: Vec<i32>) {}
+   |    ^^^ -----------
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/type/type-check/point-at-inference-3.fixed b/src/test/ui/type/type-check/point-at-inference-3.fixed
new file mode 100644
index 00000000000..1a960133ceb
--- /dev/null
+++ b/src/test/ui/type/type-check/point-at-inference-3.fixed
@@ -0,0 +1,12 @@
+// run-rustfix
+fn main() {
+    let mut v = Vec::new();
+    v.push(0i32);
+    //~^ NOTE this is of type `i32`, which causes `v` to be inferred as `Vec<i32>`
+    v.push(0);
+    v.push(1i32); //~ ERROR mismatched types
+    //~^ NOTE expected `i32`, found `u32`
+    //~| NOTE arguments to this method are incorrect
+    //~| NOTE associated function defined here
+    //~| HELP change the type of the numeric literal from `u32` to `i32`
+}
diff --git a/src/test/ui/type/type-check/point-at-inference-3.rs b/src/test/ui/type/type-check/point-at-inference-3.rs
new file mode 100644
index 00000000000..92910ae1a31
--- /dev/null
+++ b/src/test/ui/type/type-check/point-at-inference-3.rs
@@ -0,0 +1,12 @@
+// run-rustfix
+fn main() {
+    let mut v = Vec::new();
+    v.push(0i32);
+    //~^ NOTE this is of type `i32`, which causes `v` to be inferred as `Vec<i32>`
+    v.push(0);
+    v.push(1u32); //~ ERROR mismatched types
+    //~^ NOTE expected `i32`, found `u32`
+    //~| NOTE arguments to this method are incorrect
+    //~| NOTE associated function defined here
+    //~| HELP change the type of the numeric literal from `u32` to `i32`
+}
diff --git a/src/test/ui/type/type-check/point-at-inference-3.stderr b/src/test/ui/type/type-check/point-at-inference-3.stderr
new file mode 100644
index 00000000000..999c3148362
--- /dev/null
+++ b/src/test/ui/type/type-check/point-at-inference-3.stderr
@@ -0,0 +1,21 @@
+error[E0308]: mismatched types
+  --> $DIR/point-at-inference-3.rs:7:12
+   |
+LL |     v.push(0i32);
+   |            ---- this is of type `i32`, which causes `v` to be inferred as `Vec<i32>`
+...
+LL |     v.push(1u32);
+   |       ---- ^^^^ expected `i32`, found `u32`
+   |       |
+   |       arguments to this method are incorrect
+   |
+note: associated function defined here
+  --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
+help: change the type of the numeric literal from `u32` to `i32`
+   |
+LL |     v.push(1i32);
+   |             ~~~
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/type/type-check/point-at-inference.fixed b/src/test/ui/type/type-check/point-at-inference.fixed
new file mode 100644
index 00000000000..f41fbe59fba
--- /dev/null
+++ b/src/test/ui/type/type-check/point-at-inference.fixed
@@ -0,0 +1,13 @@
+// run-rustfix
+fn bar(_: Vec<i32>) {}
+fn baz(_: &impl std::any::Any) {}
+fn main() {
+    let v = vec![1, 2, 3, 4, 5];
+    let mut foo = vec![];
+    baz(&foo);
+    for i in &v {
+        foo.push(*i);
+    }
+    baz(&foo);
+    bar(foo); //~ ERROR E0308
+}
diff --git a/src/test/ui/type/type-check/point-at-inference.rs b/src/test/ui/type/type-check/point-at-inference.rs
new file mode 100644
index 00000000000..6419e42e70d
--- /dev/null
+++ b/src/test/ui/type/type-check/point-at-inference.rs
@@ -0,0 +1,13 @@
+// run-rustfix
+fn bar(_: Vec<i32>) {}
+fn baz(_: &impl std::any::Any) {}
+fn main() {
+    let v = vec![1, 2, 3, 4, 5];
+    let mut foo = vec![];
+    baz(&foo);
+    for i in &v {
+        foo.push(i);
+    }
+    baz(&foo);
+    bar(foo); //~ ERROR E0308
+}
diff --git a/src/test/ui/type/type-check/point-at-inference.stderr b/src/test/ui/type/type-check/point-at-inference.stderr
new file mode 100644
index 00000000000..70428fe841b
--- /dev/null
+++ b/src/test/ui/type/type-check/point-at-inference.stderr
@@ -0,0 +1,26 @@
+error[E0308]: mismatched types
+  --> $DIR/point-at-inference.rs:12:9
+   |
+LL |         foo.push(i);
+   |                  - this is of type `&{integer}`, which causes `foo` to be inferred as `Vec<&{integer}>`
+...
+LL |     bar(foo);
+   |     --- ^^^ expected `i32`, found `&{integer}`
+   |     |
+   |     arguments to this function are incorrect
+   |
+   = note: expected struct `Vec<i32>`
+              found struct `Vec<&{integer}>`
+note: function defined here
+  --> $DIR/point-at-inference.rs:2:4
+   |
+LL | fn bar(_: Vec<i32>) {}
+   |    ^^^ -----------
+help: consider dereferencing the borrow
+   |
+LL |         foo.push(*i);
+   |                  +
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/typeck/issue-105946.rs b/src/test/ui/typeck/issue-105946.rs
new file mode 100644
index 00000000000..bf01751d5f6
--- /dev/null
+++ b/src/test/ui/typeck/issue-105946.rs
@@ -0,0 +1,12 @@
+fn digit() -> str {
+  return {};
+  //~^ ERROR: mismatched types [E0308]
+}
+fn main() {
+    let [_y..] = [box 1, box 2];
+    //~^ ERROR: cannot find value `_y` in this scope [E0425]
+    //~| ERROR: `X..` patterns in slices are experimental [E0658]
+    //~| ERROR: box expression syntax is experimental; you can call `Box::new` instead [E0658]
+    //~| ERROR: box expression syntax is experimental; you can call `Box::new` instead [E0658]
+    //~| ERROR: pattern requires 1 element but array has 2 [E0527]
+}
diff --git a/src/test/ui/typeck/issue-105946.stderr b/src/test/ui/typeck/issue-105946.stderr
new file mode 100644
index 00000000000..d803de4df47
--- /dev/null
+++ b/src/test/ui/typeck/issue-105946.stderr
@@ -0,0 +1,49 @@
+error[E0425]: cannot find value `_y` in this scope
+  --> $DIR/issue-105946.rs:6:10
+   |
+LL |     let [_y..] = [box 1, box 2];
+   |          ^^ not found in this scope
+
+error[E0658]: `X..` patterns in slices are experimental
+  --> $DIR/issue-105946.rs:6:10
+   |
+LL |     let [_y..] = [box 1, box 2];
+   |          ^^^^
+   |
+   = note: see issue #67264 <https://github.com/rust-lang/rust/issues/67264> for more information
+   = help: add `#![feature(half_open_range_patterns_in_slices)]` to the crate attributes to enable
+
+error[E0658]: box expression syntax is experimental; you can call `Box::new` instead
+  --> $DIR/issue-105946.rs:6:19
+   |
+LL |     let [_y..] = [box 1, box 2];
+   |                   ^^^^^
+   |
+   = note: see issue #49733 <https://github.com/rust-lang/rust/issues/49733> for more information
+   = help: add `#![feature(box_syntax)]` to the crate attributes to enable
+
+error[E0658]: box expression syntax is experimental; you can call `Box::new` instead
+  --> $DIR/issue-105946.rs:6:26
+   |
+LL |     let [_y..] = [box 1, box 2];
+   |                          ^^^^^
+   |
+   = note: see issue #49733 <https://github.com/rust-lang/rust/issues/49733> for more information
+   = help: add `#![feature(box_syntax)]` to the crate attributes to enable
+
+error[E0308]: mismatched types
+  --> $DIR/issue-105946.rs:2:10
+   |
+LL |   return {};
+   |          ^^ expected `str`, found `()`
+
+error[E0527]: pattern requires 1 element but array has 2
+  --> $DIR/issue-105946.rs:6:9
+   |
+LL |     let [_y..] = [box 1, box 2];
+   |         ^^^^^^ expected 2 elements
+
+error: aborting due to 6 previous errors
+
+Some errors have detailed explanations: E0308, E0425, E0527, E0658.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-18937-1.rs b/src/test/ui/typeck/issue-18937-1.rs
index 57e56d832c6..57e56d832c6 100644
--- a/src/test/ui/issues/issue-18937-1.rs
+++ b/src/test/ui/typeck/issue-18937-1.rs
diff --git a/src/test/ui/issues/issue-18937.rs b/src/test/ui/typeck/issue-18937.rs
index af85e5b2b02..af85e5b2b02 100644
--- a/src/test/ui/issues/issue-18937.rs
+++ b/src/test/ui/typeck/issue-18937.rs
diff --git a/src/test/ui/issues/issue-18937.stderr b/src/test/ui/typeck/issue-18937.stderr
index 5e2ba0ef4fc..5e2ba0ef4fc 100644
--- a/src/test/ui/issues/issue-18937.stderr
+++ b/src/test/ui/typeck/issue-18937.stderr
diff --git a/src/test/ui/issues/issue-31173.rs b/src/test/ui/typeck/issue-31173.rs
index f678df5b42b..f678df5b42b 100644
--- a/src/test/ui/issues/issue-31173.rs
+++ b/src/test/ui/typeck/issue-31173.rs
diff --git a/src/test/ui/issues/issue-31173.stderr b/src/test/ui/typeck/issue-31173.stderr
index f3be99f9bcb..f3be99f9bcb 100644
--- a/src/test/ui/issues/issue-31173.stderr
+++ b/src/test/ui/typeck/issue-31173.stderr
diff --git a/src/test/ui/typeck/remove-extra-argument.fixed b/src/test/ui/typeck/remove-extra-argument.fixed
index a9338c76cdc..d09306bf794 100644
--- a/src/test/ui/typeck/remove-extra-argument.fixed
+++ b/src/test/ui/typeck/remove-extra-argument.fixed
@@ -4,6 +4,6 @@ fn l(_a: Vec<u8>) {}
 
 fn main() {
     l(vec![])
-    //~^ ERROR this function takes 1 argument but 2 arguments were supplied
+    //~^ ERROR function takes 1 argument but 2 arguments were supplied
     //~| HELP remove the extra argument
 }
diff --git a/src/test/ui/typeck/remove-extra-argument.rs b/src/test/ui/typeck/remove-extra-argument.rs
index 659cb8b267f..2181c37cee9 100644
--- a/src/test/ui/typeck/remove-extra-argument.rs
+++ b/src/test/ui/typeck/remove-extra-argument.rs
@@ -4,6 +4,6 @@ fn l(_a: Vec<u8>) {}
 
 fn main() {
     l(vec![], vec![])
-    //~^ ERROR this function takes 1 argument but 2 arguments were supplied
+    //~^ ERROR function takes 1 argument but 2 arguments were supplied
     //~| HELP remove the extra argument
 }
diff --git a/src/test/ui/ufcs/ufcs-qpath-missing-params.stderr b/src/test/ui/ufcs/ufcs-qpath-missing-params.stderr
index a832964d220..d0ec47d6132 100644
--- a/src/test/ui/ufcs/ufcs-qpath-missing-params.stderr
+++ b/src/test/ui/ufcs/ufcs-qpath-missing-params.stderr
@@ -12,7 +12,7 @@ LL | pub trait IntoCow<'a, B: ?Sized> where B: ToOwned {
 help: add missing generic argument
    |
 LL |     <String as IntoCow<B>>::into_cow("foo".to_string());
-   |                ~~~~~~~~~~
+   |                       +++
 
 error[E0107]: missing generics for trait `IntoCow`
   --> $DIR/ufcs-qpath-missing-params.rs:17:16
@@ -28,7 +28,7 @@ LL | pub trait IntoCow<'a, B: ?Sized> where B: ToOwned {
 help: add missing generic argument
    |
 LL |     <String as IntoCow<B>>::into_cow::<str>("foo".to_string());
-   |                ~~~~~~~~~~
+   |                       +++
 
 error[E0107]: this associated function takes 0 generic arguments but 1 generic argument was supplied
   --> $DIR/ufcs-qpath-missing-params.rs:17:26
diff --git a/src/test/ui/unboxed-closures/unboxed-closure-no-cyclic-sig.stderr b/src/test/ui/unboxed-closures/unboxed-closure-no-cyclic-sig.stderr
index 167479270b5..6d5dbca0558 100644
--- a/src/test/ui/unboxed-closures/unboxed-closure-no-cyclic-sig.stderr
+++ b/src/test/ui/unboxed-closures/unboxed-closure-no-cyclic-sig.stderr
@@ -2,12 +2,17 @@ error[E0644]: closure/generator type that references itself
   --> $DIR/unboxed-closure-no-cyclic-sig.rs:8:7
    |
 LL |     g(|_| {  });
-   |       ^^^^^^^^ cyclic type of infinite size
+   |       ^^^ cyclic type of infinite size
    |
    = note: closures cannot capture themselves or take themselves as argument;
            this error may be the result of a recent compiler bug-fix,
            see issue #46062 <https://github.com/rust-lang/rust/issues/46062>
            for more information
+note: required by a bound in `g`
+  --> $DIR/unboxed-closure-no-cyclic-sig.rs:5:24
+   |
+LL | fn g<F>(_: F) where F: FnOnce(Option<F>) {}
+   |                        ^^^^^^^^^^^^^^^^^ required by this bound in `g`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/unboxed-closures/unboxed-closure-region.rs b/src/test/ui/unboxed-closures/unboxed-closure-region.rs
index f202492eda5..51fe118c93f 100644
--- a/src/test/ui/unboxed-closures/unboxed-closure-region.rs
+++ b/src/test/ui/unboxed-closures/unboxed-closure-region.rs
@@ -5,7 +5,7 @@
 fn main() {
     let _f = {
         let x = 0;
-        || x //~ ERROR `x` does not live long enough
+        || x //~ ERROR closure may outlive the current block, but it borrows `x`
     };
     _f;
 }
diff --git a/src/test/ui/unboxed-closures/unboxed-closure-region.stderr b/src/test/ui/unboxed-closures/unboxed-closure-region.stderr
index b40b2f67d9b..43e9af24a7c 100644
--- a/src/test/ui/unboxed-closures/unboxed-closure-region.stderr
+++ b/src/test/ui/unboxed-closures/unboxed-closure-region.stderr
@@ -1,16 +1,21 @@
-error[E0597]: `x` does not live long enough
-  --> $DIR/unboxed-closure-region.rs:8:12
+error[E0373]: closure may outlive the current block, but it borrows `x`, which is owned by the current block
+  --> $DIR/unboxed-closure-region.rs:8:9
    |
-LL |     let _f = {
-   |         -- borrow later stored here
-LL |         let x = 0;
 LL |         || x
-   |         -- ^ borrowed value does not live long enough
+   |         ^^ - `x` is borrowed here
    |         |
-   |         value captured here
-LL |     };
-   |     - `x` dropped here while still borrowed
+   |         may outlive borrowed value `x`
+   |
+note: block requires argument type to outlive `'1`
+  --> $DIR/unboxed-closure-region.rs:6:9
+   |
+LL |     let _f = {
+   |         ^^
+help: to force the closure to take ownership of `x` (and any other referenced variables), use the `move` keyword
+   |
+LL |         move || x
+   |         ++++
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0597`.
+For more information about this error, try `rustc --explain E0373`.
diff --git a/src/test/ui/underscore-lifetime/where-clause-inherent-impl-ampersand.rust2015.stderr b/src/test/ui/underscore-lifetime/where-clause-inherent-impl-ampersand.rust2015.stderr
index fe726cb49c7..f4d14b5f87b 100644
--- a/src/test/ui/underscore-lifetime/where-clause-inherent-impl-ampersand.rust2015.stderr
+++ b/src/test/ui/underscore-lifetime/where-clause-inherent-impl-ampersand.rust2015.stderr
@@ -3,6 +3,12 @@ error[E0637]: `&` without an explicit lifetime name cannot be used here
    |
 LL |     T: WithType<&u32>
    |                 ^ explicit lifetime name needed here
+   |
+help: consider introducing a higher-ranked lifetime here with `for<'a>`
+  --> $DIR/where-clause-inherent-impl-ampersand.rs:13:8
+   |
+LL |     T: WithType<&u32>
+   |        ^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/underscore-lifetime/where-clause-inherent-impl-ampersand.rust2018.stderr b/src/test/ui/underscore-lifetime/where-clause-inherent-impl-ampersand.rust2018.stderr
index fe726cb49c7..f4d14b5f87b 100644
--- a/src/test/ui/underscore-lifetime/where-clause-inherent-impl-ampersand.rust2018.stderr
+++ b/src/test/ui/underscore-lifetime/where-clause-inherent-impl-ampersand.rust2018.stderr
@@ -3,6 +3,12 @@ error[E0637]: `&` without an explicit lifetime name cannot be used here
    |
 LL |     T: WithType<&u32>
    |                 ^ explicit lifetime name needed here
+   |
+help: consider introducing a higher-ranked lifetime here with `for<'a>`
+  --> $DIR/where-clause-inherent-impl-ampersand.rs:13:8
+   |
+LL |     T: WithType<&u32>
+   |        ^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/underscore-lifetime/where-clause-trait-impl-region.rust2015.stderr b/src/test/ui/underscore-lifetime/where-clause-trait-impl-region.rust2015.stderr
index fbd14de2107..63fc1a19b93 100644
--- a/src/test/ui/underscore-lifetime/where-clause-trait-impl-region.rust2015.stderr
+++ b/src/test/ui/underscore-lifetime/where-clause-trait-impl-region.rust2015.stderr
@@ -3,6 +3,12 @@ error[E0637]: `&` without an explicit lifetime name cannot be used here
    |
 LL |     T: WithType<&u32>
    |                 ^ explicit lifetime name needed here
+   |
+help: consider introducing a higher-ranked lifetime here with `for<'a>`
+  --> $DIR/where-clause-trait-impl-region.rs:11:8
+   |
+LL |     T: WithType<&u32>
+   |        ^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/underscore-lifetime/where-clause-trait-impl-region.rust2018.stderr b/src/test/ui/underscore-lifetime/where-clause-trait-impl-region.rust2018.stderr
index fbd14de2107..63fc1a19b93 100644
--- a/src/test/ui/underscore-lifetime/where-clause-trait-impl-region.rust2018.stderr
+++ b/src/test/ui/underscore-lifetime/where-clause-trait-impl-region.rust2018.stderr
@@ -3,6 +3,12 @@ error[E0637]: `&` without an explicit lifetime name cannot be used here
    |
 LL |     T: WithType<&u32>
    |                 ^ explicit lifetime name needed here
+   |
+help: consider introducing a higher-ranked lifetime here with `for<'a>`
+  --> $DIR/where-clause-trait-impl-region.rs:11:8
+   |
+LL |     T: WithType<&u32>
+   |        ^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/unsafe/auxiliary/issue-106126.rs b/src/test/ui/unsafe/auxiliary/issue-106126.rs
new file mode 100644
index 00000000000..091a3edb756
--- /dev/null
+++ b/src/test/ui/unsafe/auxiliary/issue-106126.rs
@@ -0,0 +1,9 @@
+#[macro_export]
+macro_rules! foo {
+    () => {
+        unsafe fn __unsf() {}
+        unsafe fn __foo() {
+            __unsf();
+        }
+    };
+}
diff --git a/src/test/ui/unsafe/issue-106126-good-path-bug.rs b/src/test/ui/unsafe/issue-106126-good-path-bug.rs
new file mode 100644
index 00000000000..93f478ee358
--- /dev/null
+++ b/src/test/ui/unsafe/issue-106126-good-path-bug.rs
@@ -0,0 +1,12 @@
+// Regression test for #106126.
+// check-pass
+// aux-build:issue-106126.rs
+
+#![deny(unsafe_op_in_unsafe_fn)]
+
+#[macro_use]
+extern crate issue_106126;
+
+foo!();
+
+fn main() {}
diff --git a/src/test/ui/unsafe/unsafe-trait-impl.rs b/src/test/ui/unsafe/unsafe-trait-impl.rs
index 03a251be1a9..1fc84ca0256 100644
--- a/src/test/ui/unsafe/unsafe-trait-impl.rs
+++ b/src/test/ui/unsafe/unsafe-trait-impl.rs
@@ -7,8 +7,8 @@ trait Foo {
 impl Foo for u32 {
     fn len(&self) -> u32 { *self }
     //~^ ERROR method `len` has an incompatible type for trait
-    //~| expected fn pointer `unsafe fn(&u32) -> _`
-    //~| found fn pointer `fn(&u32) -> _`
+    //~| expected signature `unsafe fn(&u32) -> _`
+    //~| found signature `fn(&u32) -> _`
 }
 
 fn main() { }
diff --git a/src/test/ui/unsafe/unsafe-trait-impl.stderr b/src/test/ui/unsafe/unsafe-trait-impl.stderr
index 8a0cba1fac5..18ba79404b7 100644
--- a/src/test/ui/unsafe/unsafe-trait-impl.stderr
+++ b/src/test/ui/unsafe/unsafe-trait-impl.stderr
@@ -9,8 +9,8 @@ note: type in trait
    |
 LL |     unsafe fn len(&self) -> u32;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = note: expected fn pointer `unsafe fn(&u32) -> _`
-              found fn pointer `fn(&u32) -> _`
+   = note: expected signature `unsafe fn(&u32) -> _`
+              found signature `fn(&u32) -> _`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/wf/issue-103573.stderr b/src/test/ui/wf/issue-103573.stderr
index fcf3f15e4d3..5227badb77d 100644
--- a/src/test/ui/wf/issue-103573.stderr
+++ b/src/test/ui/wf/issue-103573.stderr
@@ -1,8 +1,8 @@
 error[E0277]: the trait bound `<<Self as TraitC<E>>::TypeC<'a> as TraitB>::TypeB: TraitA` is not satisfied
-  --> $DIR/issue-103573.rs:18:5
+  --> $DIR/issue-103573.rs:18:18
    |
 LL |     fn g<'a>(_: &<<Self::TypeC<'a> as TraitB>::TypeB as TraitA>::TypeA);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `TraitA` is not implemented for `<<Self as TraitC<E>>::TypeC<'a> as TraitB>::TypeB`
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `TraitA` is not implemented for `<<Self as TraitC<E>>::TypeC<'a> as TraitB>::TypeB`
    |
 help: consider further restricting the associated type
    |
diff --git a/src/test/ui/wf/wf-foreign-fn-decl-ret.stderr b/src/test/ui/wf/wf-foreign-fn-decl-ret.stderr
index 78312a09105..b03023b5fd1 100644
--- a/src/test/ui/wf/wf-foreign-fn-decl-ret.stderr
+++ b/src/test/ui/wf/wf-foreign-fn-decl-ret.stderr
@@ -1,8 +1,8 @@
 error[E0277]: the trait bound `(): Foo` is not satisfied
-  --> $DIR/wf-foreign-fn-decl-ret.rs:11:5
+  --> $DIR/wf-foreign-fn-decl-ret.rs:11:25
    |
 LL |     pub fn lint_me() -> <() as Foo>::Assoc;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `()`
+   |                         ^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `()`
 
 error[E0277]: the trait bound `u32: Unsatisfied` is not satisfied
   --> $DIR/wf-foreign-fn-decl-ret.rs:14:32
diff --git a/src/test/ui/wrong-mul-method-signature.stderr b/src/test/ui/wrong-mul-method-signature.stderr
index 8338f61b22a..504a6032b01 100644
--- a/src/test/ui/wrong-mul-method-signature.stderr
+++ b/src/test/ui/wrong-mul-method-signature.stderr
@@ -7,8 +7,8 @@ LL |     fn mul(self, s: &f64) -> Vec1 {
    |                     expected `f64`, found `&f64`
    |                     help: change the parameter type to match the trait: `f64`
    |
-   = note: expected fn pointer `fn(Vec1, f64) -> Vec1`
-              found fn pointer `fn(Vec1, &f64) -> Vec1`
+   = note: expected signature `fn(Vec1, f64) -> Vec1`
+              found signature `fn(Vec1, &f64) -> Vec1`
 
 error[E0053]: method `mul` has an incompatible type for trait
   --> $DIR/wrong-mul-method-signature.rs:33:21
@@ -19,8 +19,8 @@ LL |     fn mul(self, s: f64) -> Vec2 {
    |                     expected struct `Vec2`, found `f64`
    |                     help: change the parameter type to match the trait: `Vec2`
    |
-   = note: expected fn pointer `fn(Vec2, Vec2) -> f64`
-              found fn pointer `fn(Vec2, f64) -> Vec2`
+   = note: expected signature `fn(Vec2, Vec2) -> f64`
+              found signature `fn(Vec2, f64) -> Vec2`
 
 error[E0053]: method `mul` has an incompatible type for trait
   --> $DIR/wrong-mul-method-signature.rs:52:29
@@ -31,8 +31,8 @@ LL |     fn mul(self, s: f64) -> f64 {
    |                             expected `i32`, found `f64`
    |                             help: change the output type to match the trait: `i32`
    |
-   = note: expected fn pointer `fn(Vec3, _) -> i32`
-              found fn pointer `fn(Vec3, _) -> f64`
+   = note: expected signature `fn(Vec3, _) -> i32`
+              found signature `fn(Vec3, _) -> f64`
 
 error[E0308]: mismatched types
   --> $DIR/wrong-mul-method-signature.rs:63:45
diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs
index 0551e835bb0..21dad9eb74a 100644
--- a/src/tools/build-manifest/src/main.rs
+++ b/src/tools/build-manifest/src/main.rs
@@ -51,7 +51,7 @@ static TARGETS: &[&str] = &[
     "aarch64-apple-darwin",
     "aarch64-apple-ios",
     "aarch64-apple-ios-sim",
-    "aarch64-fuchsia",
+    "aarch64-unknown-fuchsia",
     "aarch64-linux-android",
     "aarch64-pc-windows-msvc",
     "aarch64-unknown-hermit",
@@ -138,7 +138,7 @@ static TARGETS: &[&str] = &[
     "x86_64-apple-darwin",
     "x86_64-apple-ios",
     "x86_64-fortanix-unknown-sgx",
-    "x86_64-fuchsia",
+    "x86_64-unknown-fuchsia",
     "x86_64-linux-android",
     "x86_64-pc-windows-gnu",
     "x86_64-pc-windows-msvc",
diff --git a/src/tools/build_helper/Cargo.toml b/src/tools/build_helper/Cargo.toml
new file mode 100644
index 00000000000..99f6fea2ecf
--- /dev/null
+++ b/src/tools/build_helper/Cargo.toml
@@ -0,0 +1,8 @@
+[package]
+name = "build_helper"
+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/tools/build_helper/src/ci.rs b/src/tools/build_helper/src/ci.rs
new file mode 100644
index 00000000000..9f113c72b93
--- /dev/null
+++ b/src/tools/build_helper/src/ci.rs
@@ -0,0 +1,40 @@
+use std::process::Command;
+
+#[derive(Copy, Clone, PartialEq, Eq, Debug)]
+pub enum CiEnv {
+    /// Not a CI environment.
+    None,
+    /// The Azure Pipelines environment, for Linux (including Docker), Windows, and macOS builds.
+    AzurePipelines,
+    /// The GitHub Actions environment, for Linux (including Docker), Windows and macOS builds.
+    GitHubActions,
+}
+
+impl CiEnv {
+    /// Obtains the current CI environment.
+    pub fn current() -> CiEnv {
+        if std::env::var("TF_BUILD").map_or(false, |e| e == "True") {
+            CiEnv::AzurePipelines
+        } else if std::env::var("GITHUB_ACTIONS").map_or(false, |e| e == "true") {
+            CiEnv::GitHubActions
+        } else {
+            CiEnv::None
+        }
+    }
+
+    pub fn is_ci() -> bool {
+        Self::current() != CiEnv::None
+    }
+
+    /// If in a CI environment, forces the command to run with colors.
+    pub fn force_coloring_in_ci(self, cmd: &mut Command) {
+        if self != CiEnv::None {
+            // Due to use of stamp/docker, the output stream of rustbuild is not
+            // a TTY in CI, so coloring is by-default turned off.
+            // The explicit `TERM=xterm` environment is needed for
+            // `--color always` to actually work. This env var was lost when
+            // compiling through the Makefile. Very strange.
+            cmd.env("TERM", "xterm").args(&["--color", "always"]);
+        }
+    }
+}
diff --git a/src/tools/build_helper/src/git.rs b/src/tools/build_helper/src/git.rs
new file mode 100644
index 00000000000..dc62051cb85
--- /dev/null
+++ b/src/tools/build_helper/src/git.rs
@@ -0,0 +1,75 @@
+use std::{path::Path, process::Command};
+
+/// Finds the remote for rust-lang/rust.
+/// For example for these remotes it will return `upstream`.
+/// ```text
+/// origin  https://github.com/Nilstrieb/rust.git (fetch)
+/// origin  https://github.com/Nilstrieb/rust.git (push)
+/// upstream        https://github.com/rust-lang/rust (fetch)
+/// upstream        https://github.com/rust-lang/rust (push)
+/// ```
+pub fn get_rust_lang_rust_remote(git_dir: Option<&Path>) -> Result<String, String> {
+    let mut git = Command::new("git");
+    if let Some(git_dir) = git_dir {
+        git.current_dir(git_dir);
+    }
+    git.args(["config", "--local", "--get-regex", "remote\\..*\\.url"]);
+
+    let output = git.output().map_err(|err| format!("{err:?}"))?;
+    if !output.status.success() {
+        return Err("failed to execute git config command".to_owned());
+    }
+
+    let stdout = String::from_utf8(output.stdout).map_err(|err| format!("{err:?}"))?;
+
+    let rust_lang_remote = stdout
+        .lines()
+        .find(|remote| remote.contains("rust-lang"))
+        .ok_or_else(|| "rust-lang/rust remote not found".to_owned())?;
+
+    let remote_name =
+        rust_lang_remote.split('.').nth(1).ok_or_else(|| "remote name not found".to_owned())?;
+    Ok(remote_name.into())
+}
+
+pub fn rev_exists(rev: &str, git_dir: Option<&Path>) -> Result<bool, String> {
+    let mut git = Command::new("git");
+    if let Some(git_dir) = git_dir {
+        git.current_dir(git_dir);
+    }
+    git.args(["rev-parse", rev]);
+    let output = git.output().map_err(|err| format!("{err:?}"))?;
+
+    match output.status.code() {
+        Some(0) => Ok(true),
+        Some(128) => Ok(false),
+        None => {
+            return Err(format!(
+                "git didn't exit properly: {}",
+                String::from_utf8(output.stderr).map_err(|err| format!("{err:?}"))?
+            ));
+        }
+        Some(code) => {
+            return Err(format!(
+                "git command exited with status code: {code}: {}",
+                String::from_utf8(output.stderr).map_err(|err| format!("{err:?}"))?
+            ));
+        }
+    }
+}
+
+/// Returns the master branch from which we can take diffs to see changes.
+/// This will usually be rust-lang/rust master, but sometimes this might not exist.
+/// This could be because the user is updating their forked master branch using the GitHub UI
+/// and therefore doesn't need an upstream master branch checked out.
+/// We will then fall back to origin/master in the hope that at least this exists.
+pub fn updated_master_branch(git_dir: Option<&Path>) -> Result<String, String> {
+    let upstream_remote = get_rust_lang_rust_remote(git_dir)?;
+    let upstream_master = format!("{upstream_remote}/master");
+    if rev_exists(&upstream_master, git_dir)? {
+        return Ok(upstream_master);
+    }
+
+    // We could implement smarter logic here in the future.
+    Ok("origin/master".into())
+}
diff --git a/src/tools/build_helper/src/lib.rs b/src/tools/build_helper/src/lib.rs
new file mode 100644
index 00000000000..d3d2323db85
--- /dev/null
+++ b/src/tools/build_helper/src/lib.rs
@@ -0,0 +1,2 @@
+pub mod ci;
+pub mod git;
diff --git a/src/tools/bump-stage0/src/main.rs b/src/tools/bump-stage0/src/main.rs
index aa346daf7e5..530a80b1ed3 100644
--- a/src/tools/bump-stage0/src/main.rs
+++ b/src/tools/bump-stage0/src/main.rs
@@ -1,4 +1,4 @@
-use anyhow::Error;
+use anyhow::{Context, Error};
 use curl::easy::Easy;
 use indexmap::IndexMap;
 use std::collections::HashMap;
@@ -13,12 +13,13 @@ struct Tool {
     comments: Vec<String>,
 
     channel: Channel,
+    date: Option<String>,
     version: [u16; 3],
     checksums: IndexMap<String, String>,
 }
 
 impl Tool {
-    fn new() -> Result<Self, Error> {
+    fn new(date: Option<String>) -> Result<Self, Error> {
         let channel = match std::fs::read_to_string("src/ci/channel")?.trim() {
             "stable" => Channel::Stable,
             "beta" => Channel::Beta,
@@ -40,6 +41,7 @@ impl Tool {
         Ok(Self {
             channel,
             version,
+            date,
             config: existing.config,
             comments: existing.comments,
             checksums: IndexMap::new(),
@@ -84,7 +86,7 @@ impl Tool {
             Channel::Nightly => "beta".to_string(),
         };
 
-        let manifest = fetch_manifest(&self.config, &channel)?;
+        let manifest = fetch_manifest(&self.config, &channel, self.date.as_deref())?;
         self.collect_checksums(&manifest, COMPILER_COMPONENTS)?;
         Ok(Stage0Toolchain {
             date: manifest.date,
@@ -110,7 +112,7 @@ impl Tool {
             return Ok(None);
         }
 
-        let manifest = fetch_manifest(&self.config, "nightly")?;
+        let manifest = fetch_manifest(&self.config, "nightly", self.date.as_deref())?;
         self.collect_checksums(&manifest, RUSTFMT_COMPONENTS)?;
         Ok(Some(Stage0Toolchain { date: manifest.date, version: "nightly".into() }))
     }
@@ -141,16 +143,19 @@ impl Tool {
 }
 
 fn main() -> Result<(), Error> {
-    let tool = Tool::new()?;
+    let tool = Tool::new(std::env::args().nth(1))?;
     tool.update_json()?;
     Ok(())
 }
 
-fn fetch_manifest(config: &Config, channel: &str) -> Result<Manifest, Error> {
-    Ok(toml::from_slice(&http_get(&format!(
-        "{}/dist/channel-rust-{}.toml",
-        config.dist_server, channel
-    ))?)?)
+fn fetch_manifest(config: &Config, channel: &str, date: Option<&str>) -> Result<Manifest, Error> {
+    let url = if let Some(date) = date {
+        format!("{}/dist/{}/channel-rust-{}.toml", config.dist_server, date, channel)
+    } else {
+        format!("{}/dist/channel-rust-{}.toml", config.dist_server, channel)
+    };
+
+    Ok(toml::from_slice(&http_get(&url)?)?)
 }
 
 fn http_get(url: &str) -> Result<Vec<u8>, Error> {
@@ -164,7 +169,7 @@ fn http_get(url: &str) -> Result<Vec<u8>, Error> {
             data.extend_from_slice(new_data);
             Ok(new_data.len())
         })?;
-        transfer.perform()?;
+        transfer.perform().context(format!("failed to fetch {url}"))?;
     }
     Ok(data)
 }
diff --git a/src/tools/cargo b/src/tools/cargo
-Subproject 2381cbdb4e9b07090f552d34a44a529b6e620e4
+Subproject 8c460b2237a6359a7e3335890db8da049bdd62f
diff --git a/src/tools/clippy/clippy_lints/src/casts/cast_slice_different_sizes.rs b/src/tools/clippy/clippy_lints/src/casts/cast_slice_different_sizes.rs
index c8e54d7b8e0..27cc5a1c3f0 100644
--- a/src/tools/clippy/clippy_lints/src/casts/cast_slice_different_sizes.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/cast_slice_different_sizes.rs
@@ -68,7 +68,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>, msrv: &Msrv
 fn is_child_of_cast(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
     let map = cx.tcx.hir();
     if_chain! {
-        if let Some(parent_id) = map.find_parent_node(expr.hir_id);
+        if let Some(parent_id) = map.opt_parent_id(expr.hir_id);
         if let Some(parent) = map.find(parent_id);
         then {
             let expr = match parent {
diff --git a/src/tools/clippy/clippy_lints/src/escape.rs b/src/tools/clippy/clippy_lints/src/escape.rs
index 1d09adec12f..dfb43893326 100644
--- a/src/tools/clippy/clippy_lints/src/escape.rs
+++ b/src/tools/clippy/clippy_lints/src/escape.rs
@@ -131,7 +131,7 @@ fn is_argument(map: rustc_middle::hir::map::Map<'_>, id: HirId) -> bool {
         _ => return false,
     }
 
-    matches!(map.find(map.get_parent_node(id)), Some(Node::Param(_)))
+    matches!(map.find_parent(id), Some(Node::Param(_)))
 }
 
 impl<'a, 'tcx> Delegate<'tcx> for EscapeDelegate<'a, 'tcx> {
@@ -156,8 +156,8 @@ impl<'a, 'tcx> Delegate<'tcx> for EscapeDelegate<'a, 'tcx> {
             let map = &self.cx.tcx.hir();
             if is_argument(*map, cmt.hir_id) {
                 // Skip closure arguments
-                let parent_id = map.get_parent_node(cmt.hir_id);
-                if let Some(Node::Expr(..)) = map.find(map.get_parent_node(parent_id)) {
+                let parent_id = map.parent_id(cmt.hir_id);
+                if let Some(Node::Expr(..)) = map.find_parent(parent_id) {
                     return;
                 }
 
diff --git a/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs b/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs
index cf35b1f175c..bdeddf44df7 100644
--- a/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs
+++ b/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs
@@ -251,7 +251,7 @@ impl<'a, 'tcx> Visitor<'tcx> for SliceIndexLintingVisitor<'a, 'tcx> {
                 let map = cx.tcx.hir();
 
                 // Checking for slice indexing
-                let parent_id = map.get_parent_node(expr.hir_id);
+                let parent_id = map.parent_id(expr.hir_id);
                 if let Some(hir::Node::Expr(parent_expr)) = map.find(parent_id);
                 if let hir::ExprKind::Index(_, index_expr) = parent_expr.kind;
                 if let Some((Constant::Int(index_value), _)) = constant(cx, cx.typeck_results(), index_expr);
@@ -259,7 +259,7 @@ impl<'a, 'tcx> Visitor<'tcx> for SliceIndexLintingVisitor<'a, 'tcx> {
                 if index_value < max_suggested_slice;
 
                 // Make sure that this slice index is read only
-                let maybe_addrof_id = map.get_parent_node(parent_id);
+                let maybe_addrof_id = map.parent_id(parent_id);
                 if let Some(hir::Node::Expr(maybe_addrof_expr)) = map.find(maybe_addrof_id);
                 if let hir::ExprKind::AddrOf(_kind, hir::Mutability::Not, _inner_expr) = maybe_addrof_expr.kind;
                 then {
diff --git a/src/tools/clippy/clippy_lints/src/loops/same_item_push.rs b/src/tools/clippy/clippy_lints/src/loops/same_item_push.rs
index 07edee46fa6..540656a2cd9 100644
--- a/src/tools/clippy/clippy_lints/src/loops/same_item_push.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/same_item_push.rs
@@ -63,7 +63,7 @@ pub(super) fn check<'tcx>(
                                 if let Node::Pat(pat) = node;
                                 if let PatKind::Binding(bind_ann, ..) = pat.kind;
                                 if !matches!(bind_ann, BindingAnnotation(_, Mutability::Mut));
-                                let parent_node = cx.tcx.hir().get_parent_node(hir_id);
+                                let parent_node = cx.tcx.hir().parent_id(hir_id);
                                 if let Some(Node::Local(parent_let_expr)) = cx.tcx.hir().find(parent_node);
                                 if let Some(init) = parent_let_expr.init;
                                 then {
diff --git a/src/tools/clippy/clippy_lints/src/manual_rem_euclid.rs b/src/tools/clippy/clippy_lints/src/manual_rem_euclid.rs
index 8d447c37150..38f41d077c1 100644
--- a/src/tools/clippy/clippy_lints/src/manual_rem_euclid.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_rem_euclid.rs
@@ -74,7 +74,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualRemEuclid {
             && let Some(hir_id) = path_to_local(expr3)
             && let Some(Node::Pat(_)) = cx.tcx.hir().find(hir_id) {
                 // Apply only to params or locals with annotated types
-                match cx.tcx.hir().find(cx.tcx.hir().get_parent_node(hir_id)) {
+                match cx.tcx.hir().find_parent(hir_id) {
                     Some(Node::Param(..)) => (),
                     Some(Node::Local(local)) => {
                         let Some(ty) = local.ty else { return };
diff --git a/src/tools/clippy/clippy_lints/src/matches/match_single_binding.rs b/src/tools/clippy/clippy_lints/src/matches/match_single_binding.rs
index c94a1f76330..065a5c72621 100644
--- a/src/tools/clippy/clippy_lints/src/matches/match_single_binding.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/match_single_binding.rs
@@ -140,8 +140,8 @@ pub(crate) fn check<'a>(cx: &LateContext<'a>, ex: &Expr<'a>, arms: &[Arm<'_>], e
 fn opt_parent_assign_span<'a>(cx: &LateContext<'a>, ex: &Expr<'a>) -> Option<AssignmentExpr> {
     let map = &cx.tcx.hir();
 
-    if let Some(Node::Expr(parent_arm_expr)) = map.find(map.get_parent_node(ex.hir_id)) {
-        return match map.find(map.get_parent_node(parent_arm_expr.hir_id)) {
+    if let Some(Node::Expr(parent_arm_expr)) = map.find_parent(ex.hir_id) {
+        return match map.find_parent(parent_arm_expr.hir_id) {
             Some(Node::Local(parent_let_expr)) => Some(AssignmentExpr::Local {
                 span: parent_let_expr.span,
                 pat_span: parent_let_expr.pat.span(),
@@ -183,8 +183,7 @@ fn sugg_with_curlies<'a>(
 
     // If the parent is already an arm, and the body is another match statement,
     // we need curly braces around suggestion
-    let parent_node_id = cx.tcx.hir().get_parent_node(match_expr.hir_id);
-    if let Node::Arm(arm) = &cx.tcx.hir().get(parent_node_id) {
+    if let Node::Arm(arm) = &cx.tcx.hir().get_parent(match_expr.hir_id) {
         if let ExprKind::Match(..) = arm.body.kind {
             cbrace_end = format!("\n{indent}}}");
             // Fix body indent due to the match
diff --git a/src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs b/src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs
index 321fa4b7f99..f0be7771bb1 100644
--- a/src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs
+++ b/src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs
@@ -186,7 +186,7 @@ fn check_for_unsequenced_reads(vis: &mut ReadVisitor<'_, '_>) {
     let map = &vis.cx.tcx.hir();
     let mut cur_id = vis.write_expr.hir_id;
     loop {
-        let parent_id = map.get_parent_node(cur_id);
+        let parent_id = map.parent_id(cur_id);
         if parent_id == cur_id {
             break;
         }
diff --git a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs
index 2f0b7ce16e5..1249db5dc47 100644
--- a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs
@@ -100,7 +100,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue {
         }
 
         // Exclude non-inherent impls
-        if let Some(Node::Item(item)) = cx.tcx.hir().find(cx.tcx.hir().get_parent_node(hir_id)) {
+        if let Some(Node::Item(item)) = cx.tcx.hir().find_parent(hir_id) {
             if matches!(
                 item.kind,
                 ItemKind::Impl(Impl { of_trait: Some(_), .. }) | ItemKind::Trait(..)
diff --git a/src/tools/clippy/clippy_lints/src/non_copy_const.rs b/src/tools/clippy/clippy_lints/src/non_copy_const.rs
index 2a3bd4ee6ce..07fd321d69f 100644
--- a/src/tools/clippy/clippy_lints/src/non_copy_const.rs
+++ b/src/tools/clippy/clippy_lints/src/non_copy_const.rs
@@ -366,7 +366,7 @@ impl<'tcx> LateLintPass<'tcx> for NonCopyConst {
             let mut dereferenced_expr = expr;
             let mut needs_check_adjustment = true;
             loop {
-                let parent_id = cx.tcx.hir().get_parent_node(cur_expr.hir_id);
+                let parent_id = cx.tcx.hir().parent_id(cur_expr.hir_id);
                 if parent_id == cur_expr.hir_id {
                     break;
                 }
diff --git a/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs b/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs
index 75add4ee4aa..870a1c7d88d 100644
--- a/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs
+++ b/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs
@@ -299,7 +299,7 @@ impl<'tcx> LateLintPass<'tcx> for PassByRefOrValue {
         }
 
         // Exclude non-inherent impls
-        if let Some(Node::Item(item)) = cx.tcx.hir().find(cx.tcx.hir().get_parent_node(hir_id)) {
+        if let Some(Node::Item(item)) = cx.tcx.hir().find_parent(hir_id) {
             if matches!(
                 item.kind,
                 ItemKind::Impl(Impl { of_trait: Some(_), .. }) | ItemKind::Trait(..)
diff --git a/src/tools/clippy/clippy_lints/src/unit_types/unit_arg.rs b/src/tools/clippy/clippy_lints/src/unit_types/unit_arg.rs
index ef9f740f704..dd120599c04 100644
--- a/src/tools/clippy/clippy_lints/src/unit_types/unit_arg.rs
+++ b/src/tools/clippy/clippy_lints/src/unit_types/unit_arg.rs
@@ -21,7 +21,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
         return;
     }
     let map = &cx.tcx.hir();
-    let opt_parent_node = map.find(map.get_parent_node(expr.hir_id));
+    let opt_parent_node = map.find_parent(expr.hir_id);
     if_chain! {
         if let Some(hir::Node::Expr(parent_expr)) = opt_parent_node;
         if is_questionmark_desugar_marked_call(parent_expr);
@@ -192,7 +192,7 @@ fn fmt_stmts_and_call(
 
     let mut stmts_and_call_snippet = stmts_and_call.join(&format!("{}{}", ";\n", " ".repeat(call_expr_indent)));
     // expr is not in a block statement or result expression position, wrap in a block
-    let parent_node = cx.tcx.hir().find(cx.tcx.hir().get_parent_node(call_expr.hir_id));
+    let parent_node = cx.tcx.hir().find_parent(call_expr.hir_id);
     if !matches!(parent_node, Some(Node::Block(_))) && !matches!(parent_node, Some(Node::Stmt(_))) {
         let block_indent = call_expr_indent + 4;
         stmts_and_call_snippet =
diff --git a/src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs b/src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs
index 60b46854b4f..84ec0d0fb1c 100644
--- a/src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs
+++ b/src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs
@@ -91,7 +91,7 @@ impl<'tcx> LateLintPass<'tcx> for UnnecessaryWraps {
         }
 
         // Abort if the method is implementing a trait or of it a trait method.
-        if let Some(Node::Item(item)) = cx.tcx.hir().find(cx.tcx.hir().get_parent_node(hir_id)) {
+        if let Some(Node::Item(item)) = cx.tcx.hir().find_parent(hir_id) {
             if matches!(
                 item.kind,
                 ItemKind::Impl(Impl { of_trait: Some(_), .. }) | ItemKind::Trait(..)
diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs
index 929544cd69d..c86f24cbd37 100644
--- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs
@@ -1058,7 +1058,7 @@ fn get_parent_local<'hir>(cx: &LateContext<'hir>, expr: &'hir hir::Expr<'hir>) -
 fn get_parent_local_hir_id<'hir>(cx: &LateContext<'hir>, hir_id: hir::HirId) -> Option<&'hir hir::Local<'hir>> {
     let map = cx.tcx.hir();
 
-    match map.find(map.get_parent_node(hir_id)) {
+    match map.find_parent((hir_id)) {
         Some(hir::Node::Local(local)) => Some(local),
         Some(hir::Node::Pat(pattern)) => get_parent_local_hir_id(cx, pattern.hir_id),
         _ => None,
diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs
index 393988dbad3..7144363637a 100644
--- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs
@@ -219,7 +219,7 @@ fn path_to_matched_type(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> Option<Ve
     match peel_hir_expr_refs(expr).0.kind {
         ExprKind::Path(ref qpath) => match cx.qpath_res(qpath, expr.hir_id) {
             Res::Local(hir_id) => {
-                let parent_id = cx.tcx.hir().get_parent_node(hir_id);
+                let parent_id = cx.tcx.hir().parent_id(hir_id);
                 if let Some(Node::Local(Local { init: Some(init), .. })) = cx.tcx.hir().find(parent_id) {
                     path_to_matched_type(cx, init)
                 } else {
diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs
index d863609b6a7..8290fe9ecb4 100644
--- a/src/tools/clippy/clippy_utils/src/lib.rs
+++ b/src/tools/clippy/clippy_utils/src/lib.rs
@@ -174,7 +174,7 @@ pub fn find_binding_init<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId) -> Option<
     if_chain! {
         if let Some(Node::Pat(pat)) = hir.find(hir_id);
         if matches!(pat.kind, PatKind::Binding(BindingAnnotation::NONE, ..));
-        let parent = hir.get_parent_node(hir_id);
+        let parent = hir.parent_id(hir_id);
         if let Some(Node::Local(local)) = hir.find(parent);
         then {
             return local.init;
@@ -1287,7 +1287,7 @@ pub fn contains_return(expr: &hir::Expr<'_>) -> bool {
 
 /// Gets the parent node, if any.
 pub fn get_parent_node(tcx: TyCtxt<'_>, id: HirId) -> Option<Node<'_>> {
-    tcx.hir().parent_iter(id).next().map(|(_, node)| node)
+    tcx.hir().find_parent(id)
 }
 
 /// Gets the parent expression, if any –- this is useful to constrain a lint.
@@ -2075,7 +2075,7 @@ pub fn is_no_core_crate(cx: &LateContext<'_>) -> bool {
 /// }
 /// ```
 pub fn is_trait_impl_item(cx: &LateContext<'_>, hir_id: HirId) -> bool {
-    if let Some(Node::Item(item)) = cx.tcx.hir().find(cx.tcx.hir().get_parent_node(hir_id)) {
+    if let Some(Node::Item(item)) = cx.tcx.hir().find_parent(hir_id) {
         matches!(item.kind, ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }))
     } else {
         false
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index 7a3c0d28fc3..7e48dd20660 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -2011,7 +2011,7 @@ impl<'test> TestCx<'test> {
                 rustc.args(&["-Zpolonius"]);
             }
             Some(CompareMode::Chalk) => {
-                rustc.args(&["-Zchalk"]);
+                rustc.args(&["-Ztrait-solver=chalk"]);
             }
             Some(CompareMode::SplitDwarf) if self.config.target.contains("windows") => {
                 rustc.args(&["-Csplit-debuginfo=unpacked", "-Zunstable-options"]);
diff --git a/src/tools/compiletest/src/util.rs b/src/tools/compiletest/src/util.rs
index ccba313ee35..6c63b760ff6 100644
--- a/src/tools/compiletest/src/util.rs
+++ b/src/tools/compiletest/src/util.rs
@@ -11,7 +11,7 @@ mod tests;
 
 pub const ASAN_SUPPORTED_TARGETS: &[&str] = &[
     "aarch64-apple-darwin",
-    "aarch64-fuchsia",
+    "aarch64-unknown-fuchsia",
     "aarch64-linux-android",
     "aarch64-unknown-linux-gnu",
     "arm-linux-androideabi",
@@ -19,7 +19,7 @@ pub const ASAN_SUPPORTED_TARGETS: &[&str] = &[
     "i686-linux-android",
     "i686-unknown-linux-gnu",
     "x86_64-apple-darwin",
-    "x86_64-fuchsia",
+    "x86_64-unknown-fuchsia",
     "x86_64-linux-android",
     "x86_64-unknown-freebsd",
     "x86_64-unknown-linux-gnu",
@@ -28,12 +28,12 @@ pub const ASAN_SUPPORTED_TARGETS: &[&str] = &[
 // FIXME(rcvalle): More targets are likely supported.
 pub const CFI_SUPPORTED_TARGETS: &[&str] = &[
     "aarch64-apple-darwin",
-    "aarch64-fuchsia",
+    "aarch64-unknown-fuchsia",
     "aarch64-linux-android",
     "aarch64-unknown-freebsd",
     "aarch64-unknown-linux-gnu",
     "x86_64-apple-darwin",
-    "x86_64-fuchsia",
+    "x86_64-unknown-fuchsia",
     "x86_64-pc-solaris",
     "x86_64-unknown-freebsd",
     "x86_64-unknown-illumos",
diff --git a/src/tools/error_index_generator/book_config.toml b/src/tools/error_index_generator/book_config.toml
index 885100ae3a4..2701ad917bb 100644
--- a/src/tools/error_index_generator/book_config.toml
+++ b/src/tools/error_index_generator/book_config.toml
@@ -7,6 +7,7 @@ src = ""
 git-repository-url = "https://github.com/rust-lang/rust/"
 additional-css = ["error-index.css"]
 additional-js = ["error-index.js"]
+input-404 = ""
 
 [output.html.search]
 enable = true
diff --git a/src/tools/error_index_generator/main.rs b/src/tools/error_index_generator/main.rs
index 1bde8e00782..98eda97e236 100644
--- a/src/tools/error_index_generator/main.rs
+++ b/src/tools/error_index_generator/main.rs
@@ -98,8 +98,7 @@ fn add_rust_attribute_on_codeblock(explanation: &str) -> String {
 
 fn render_html(output_path: &Path) -> Result<(), Box<dyn Error>> {
     let mut introduction = format!(
-        "<script src='redirect.js'></script>
-# Rust error codes index
+        "# Rust error codes index
 
 This page lists all the error codes emitted by the Rust compiler.
 
@@ -149,7 +148,12 @@ This page lists all the error codes emitted by the Rust compiler.
     book.book.sections.push(BookItem::Chapter(chapter));
     book.build()?;
 
-    // We can't put this content into another file, otherwise `mbdbook` will also put it into the
+    // The error-index used to be generated manually (without mdbook), and the
+    // index was located at the top level. Now that it is generated with
+    // mdbook, error-index.html has moved to error_codes/error-index.html.
+    // This adds a redirect so that old links go to the new location.
+    //
+    // We can't put this content into another file, otherwise `mdbook` will also put it into the
     // output directory, making a duplicate.
     fs::write(
         output_path.join("error-index.html"),
@@ -163,14 +167,10 @@ This page lists all the error codes emitted by the Rust compiler.
     </head>
     <body>
         <div>If you are not automatically redirected to the error code index, please <a id="index-link" href="./error_codes/error-index.html">here</a>.
-        <script>document.getElementById("index-link").click()</script>
     </body>
 </html>"#,
     )?;
 
-    // No need for a 404 file, it's already handled by the server.
-    fs::remove_file(output_path.join("error_codes/404.html"))?;
-
     Ok(())
 }
 
diff --git a/src/tools/error_index_generator/redirect.js b/src/tools/error_index_generator/redirect.js
index 8c907f5795d..c80cbf297af 100644
--- a/src/tools/error_index_generator/redirect.js
+++ b/src/tools/error_index_generator/redirect.js
@@ -3,14 +3,10 @@
         let code = window.location.hash.replace(/^#/, '');
         // We have to make sure this pattern matches to avoid inadvertently creating an
         // open redirect.
-        if (!/^E[0-9]+$/.test(code)) {
+        if (/^E[0-9]+$/.test(code)) {
+            window.location.replace('./error_codes/' + code + '.html');
             return;
         }
-        if (window.location.pathname.indexOf("/error_codes/") !== -1) {
-            // We're not at the top level, so we don't prepend with "./error_codes/".
-            window.location = './' + code + '.html';
-        } else {
-            window.location = './error_codes/' + code + '.html';
-        }
     }
+    window.location.replace('./error_codes/error-index.html');
 })()
diff --git a/src/tools/jsondoclint/Cargo.toml b/src/tools/jsondoclint/Cargo.toml
index 84a6c7f96c4..8990310a4f4 100644
--- a/src/tools/jsondoclint/Cargo.toml
+++ b/src/tools/jsondoclint/Cargo.toml
@@ -7,6 +7,8 @@ edition = "2021"
 
 [dependencies]
 anyhow = "1.0.62"
+clap = { version = "4.0.15", features = ["derive"] }
 fs-err = "2.8.1"
 rustdoc-json-types = { version = "0.1.0", path = "../../rustdoc-json-types" }
+serde = { version = "1.0", features = ["derive"] }
 serde_json = "1.0.85"
diff --git a/src/tools/jsondoclint/src/json_find.rs b/src/tools/jsondoclint/src/json_find.rs
index 70e7440f730..a183c4068ce 100644
--- a/src/tools/jsondoclint/src/json_find.rs
+++ b/src/tools/jsondoclint/src/json_find.rs
@@ -1,8 +1,9 @@
 use std::fmt::Write;
 
+use serde::Serialize;
 use serde_json::Value;
 
-#[derive(Debug, Clone, PartialEq, Eq)]
+#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
 pub enum SelectorPart {
     Field(String),
     Index(usize),
diff --git a/src/tools/jsondoclint/src/main.rs b/src/tools/jsondoclint/src/main.rs
index fc54c421b4b..05e938f4f7d 100644
--- a/src/tools/jsondoclint/src/main.rs
+++ b/src/tools/jsondoclint/src/main.rs
@@ -1,59 +1,103 @@
-use std::env;
+use std::io::{BufWriter, Write};
 
-use anyhow::{anyhow, bail, Result};
+use anyhow::{bail, Result};
+use clap::Parser;
 use fs_err as fs;
 use rustdoc_json_types::{Crate, Id, FORMAT_VERSION};
+use serde::Serialize;
 use serde_json::Value;
 
 pub(crate) mod item_kind;
 mod json_find;
 mod validator;
 
-#[derive(Debug, PartialEq, Eq)]
+#[derive(Debug, PartialEq, Eq, Serialize, Clone)]
 struct Error {
     kind: ErrorKind,
     id: Id,
 }
 
-#[derive(Debug, PartialEq, Eq)]
+#[derive(Debug, PartialEq, Eq, Serialize, Clone)]
 enum ErrorKind {
-    NotFound,
+    NotFound(Vec<json_find::Selector>),
     Custom(String),
 }
 
+#[derive(Debug, Serialize)]
+struct JsonOutput {
+    path: String,
+    errors: Vec<Error>,
+}
+
+#[derive(Parser)]
+struct Cli {
+    /// The path to the json file to be linted
+    path: String,
+
+    /// Show verbose output
+    #[arg(long)]
+    verbose: bool,
+
+    #[arg(long)]
+    json_output: Option<String>,
+}
+
 fn main() -> Result<()> {
-    let path = env::args().nth(1).ok_or_else(|| anyhow!("no path given"))?;
+    let Cli { path, verbose, json_output } = Cli::parse();
+
     let contents = fs::read_to_string(&path)?;
     let krate: Crate = serde_json::from_str(&contents)?;
     assert_eq!(krate.format_version, FORMAT_VERSION);
 
-    let mut validator = validator::Validator::new(&krate);
+    let krate_json: Value = serde_json::from_str(&contents)?;
+
+    let mut validator = validator::Validator::new(&krate, krate_json);
     validator.check_crate();
 
+    if let Some(json_output) = json_output {
+        let output = JsonOutput { path: path.clone(), errors: validator.errs.clone() };
+        let mut f = BufWriter::new(fs::File::create(json_output)?);
+        serde_json::to_writer(&mut f, &output)?;
+        f.flush()?;
+    }
+
     if !validator.errs.is_empty() {
         for err in validator.errs {
             match err.kind {
-                ErrorKind::NotFound => {
-                    let krate_json: Value = serde_json::from_str(&contents)?;
-
-                    let sels =
-                        json_find::find_selector(&krate_json, &Value::String(err.id.0.clone()));
-                    match &sels[..] {
-                        [] => unreachable!(
-                            "id must be in crate, or it wouldn't be reported as not found"
-                        ),
-                        [sel] => eprintln!(
-                            "{} not in index or paths, but refered to at '{}'",
-                            err.id.0,
-                            json_find::to_jsonpath(&sel)
-                        ),
-                        [sel, ..] => eprintln!(
-                            "{} not in index or paths, but refered to at '{}' and more",
-                            err.id.0,
-                            json_find::to_jsonpath(&sel)
-                        ),
+                ErrorKind::NotFound(sels) => match &sels[..] {
+                    [] => {
+                        unreachable!(
+                            "id {:?} must be in crate, or it wouldn't be reported as not found",
+                            err.id
+                        )
+                    }
+                    [sel] => eprintln!(
+                        "{} not in index or paths, but refered to at '{}'",
+                        err.id.0,
+                        json_find::to_jsonpath(&sel)
+                    ),
+                    [sel, ..] => {
+                        if verbose {
+                            let sels = sels
+                                .iter()
+                                .map(json_find::to_jsonpath)
+                                .map(|i| format!("'{i}'"))
+                                .collect::<Vec<_>>()
+                                .join(", ");
+                            eprintln!(
+                                "{} not in index or paths, but refered to at {sels}",
+                                err.id.0
+                            );
+                        } else {
+                            eprintln!(
+                                "{} not in index or paths, but refered to at '{}' and {} more",
+                                err.id.0,
+                                json_find::to_jsonpath(&sel),
+                                sels.len() - 1,
+                            )
+                        }
                     }
-                }
+                },
                 ErrorKind::Custom(msg) => eprintln!("{}: {}", err.id.0, msg),
             }
         }
diff --git a/src/tools/jsondoclint/src/validator.rs b/src/tools/jsondoclint/src/validator.rs
index 291d02d67bd..c6f55410e44 100644
--- a/src/tools/jsondoclint/src/validator.rs
+++ b/src/tools/jsondoclint/src/validator.rs
@@ -3,12 +3,16 @@ use std::hash::Hash;
 
 use rustdoc_json_types::{
     Constant, Crate, DynTrait, Enum, FnDecl, Function, FunctionPointer, GenericArg, GenericArgs,
-    GenericBound, GenericParamDef, Generics, Id, Impl, Import, ItemEnum, Module, OpaqueTy, Path,
-    Primitive, ProcMacro, Static, Struct, StructKind, Term, Trait, TraitAlias, Type, TypeBinding,
-    TypeBindingKind, Typedef, Union, Variant, VariantKind, WherePredicate,
+    GenericBound, GenericParamDef, Generics, Id, Impl, Import, ItemEnum, ItemSummary, Module,
+    OpaqueTy, Path, Primitive, ProcMacro, Static, Struct, StructKind, Term, Trait, TraitAlias,
+    Type, TypeBinding, TypeBindingKind, Typedef, Union, Variant, VariantKind, WherePredicate,
 };
+use serde_json::Value;
 
-use crate::{item_kind::Kind, Error, ErrorKind};
+use crate::{item_kind::Kind, json_find, Error, ErrorKind};
+
+// This is a rustc implementation detail that we rely on here
+const LOCAL_CRATE_ID: u32 = 0;
 
 /// The Validator walks over the JSON tree, and ensures it is well formed.
 /// It is made of several parts.
@@ -22,6 +26,7 @@ use crate::{item_kind::Kind, Error, ErrorKind};
 pub struct Validator<'a> {
     pub(crate) errs: Vec<Error>,
     krate: &'a Crate,
+    krate_json: Value,
     /// Worklist of Ids to check.
     todo: HashSet<&'a Id>,
     /// Ids that have already been visited, so don't need to be checked again.
@@ -39,9 +44,10 @@ enum PathKind {
 }
 
 impl<'a> Validator<'a> {
-    pub fn new(krate: &'a Crate) -> Self {
+    pub fn new(krate: &'a Crate, krate_json: Value) -> Self {
         Self {
             krate,
+            krate_json,
             errs: Vec::new(),
             seen_ids: HashSet::new(),
             todo: HashSet::new(),
@@ -50,12 +56,19 @@ impl<'a> Validator<'a> {
     }
 
     pub fn check_crate(&mut self) {
+        // Graph traverse the index
         let root = &self.krate.root;
         self.add_mod_id(root);
         while let Some(id) = set_remove(&mut self.todo) {
             self.seen_ids.insert(id);
             self.check_item(id);
         }
+
+        let root_crate_id = self.krate.index[root].crate_id;
+        assert_eq!(root_crate_id, LOCAL_CRATE_ID, "LOCAL_CRATE_ID is wrong");
+        for (id, item_info) in &self.krate.paths {
+            self.check_item_info(id, item_info);
+        }
     }
 
     fn check_item(&mut self, id: &'a Id) {
@@ -361,6 +374,19 @@ impl<'a> Validator<'a> {
         fp.generic_params.iter().for_each(|gpd| self.check_generic_param_def(gpd));
     }
 
+    fn check_item_info(&mut self, id: &Id, item_info: &ItemSummary) {
+        // FIXME: Their should be a better way to determine if an item is local, rather than relying on `LOCAL_CRATE_ID`,
+        // which encodes rustc implementation details.
+        if item_info.crate_id == LOCAL_CRATE_ID && !self.krate.index.contains_key(id) {
+            self.errs.push(Error {
+                id: id.clone(),
+                kind: ErrorKind::Custom(
+                    "Id for local item in `paths` but not in `index`".to_owned(),
+                ),
+            })
+        }
+    }
+
     fn add_id_checked(&mut self, id: &'a Id, valid: fn(Kind) -> bool, expected: &str) {
         if let Some(kind) = self.kind_of(id) {
             if valid(kind) {
@@ -373,7 +399,11 @@ impl<'a> Validator<'a> {
         } else {
             if !self.missing_ids.contains(id) {
                 self.missing_ids.insert(id);
-                self.fail(id, ErrorKind::NotFound)
+
+                let sels = json_find::find_selector(&self.krate_json, &Value::String(id.0.clone()));
+                assert_ne!(sels.len(), 0);
+
+                self.fail(id, ErrorKind::NotFound(sels))
             }
         }
     }
diff --git a/src/tools/jsondoclint/src/validator/tests.rs b/src/tools/jsondoclint/src/validator/tests.rs
index c4aeee9c53b..1ef41ff123a 100644
--- a/src/tools/jsondoclint/src/validator/tests.rs
+++ b/src/tools/jsondoclint/src/validator/tests.rs
@@ -1,12 +1,17 @@
 use std::collections::HashMap;
 
-use rustdoc_json_types::{Crate, Item, Visibility};
+use rustdoc_json_types::{Crate, Item, ItemKind, ItemSummary, Visibility, FORMAT_VERSION};
+
+use crate::json_find::SelectorPart;
 
 use super::*;
 
 #[track_caller]
 fn check(krate: &Crate, errs: &[Error]) {
-    let mut validator = Validator::new(krate);
+    let krate_string = serde_json::to_string(krate).unwrap();
+    let krate_json = serde_json::from_str(&krate_string).unwrap();
+
+    let mut validator = Validator::new(krate, krate_json);
     validator.check_crate();
 
     assert_eq!(errs, &validator.errs[..]);
@@ -46,5 +51,114 @@ fn errors_on_missing_links() {
         format_version: rustdoc_json_types::FORMAT_VERSION,
     };
 
-    check(&k, &[Error { kind: ErrorKind::NotFound, id: id("1") }]);
+    check(
+        &k,
+        &[Error {
+            kind: ErrorKind::NotFound(vec![vec![
+                SelectorPart::Field("index".to_owned()),
+                SelectorPart::Field("0".to_owned()),
+                SelectorPart::Field("links".to_owned()),
+                SelectorPart::Field("Not Found".to_owned()),
+            ]]),
+            id: id("1"),
+        }],
+    );
+}
+
+// Test we would catch
+// https://github.com/rust-lang/rust/issues/104064#issuecomment-1368589718
+#[test]
+fn errors_on_local_in_paths_and_not_index() {
+    let krate = Crate {
+        root: id("0:0:1572"),
+        crate_version: None,
+        includes_private: false,
+        index: HashMap::from_iter([
+            (
+                id("0:0:1572"),
+                Item {
+                    id: id("0:0:1572"),
+                    crate_id: 0,
+                    name: Some("microcore".to_owned()),
+                    span: None,
+                    visibility: Visibility::Public,
+                    docs: None,
+                    links: HashMap::from_iter([(("prim@i32".to_owned(), id("0:1:1571")))]),
+                    attrs: Vec::new(),
+                    deprecation: None,
+                    inner: ItemEnum::Module(Module {
+                        is_crate: true,
+                        items: vec![id("0:1:717")],
+                        is_stripped: false,
+                    }),
+                },
+            ),
+            (
+                id("0:1:717"),
+                Item {
+                    id: id("0:1:717"),
+                    crate_id: 0,
+                    name: Some("i32".to_owned()),
+                    span: None,
+                    visibility: Visibility::Public,
+                    docs: None,
+                    links: HashMap::default(),
+                    attrs: Vec::new(),
+                    deprecation: None,
+                    inner: ItemEnum::Primitive(Primitive { name: "i32".to_owned(), impls: vec![] }),
+                },
+            ),
+        ]),
+        paths: HashMap::from_iter([(
+            id("0:1:1571"),
+            ItemSummary {
+                crate_id: 0,
+                path: vec!["microcore".to_owned(), "i32".to_owned()],
+                kind: ItemKind::Primitive,
+            },
+        )]),
+        external_crates: HashMap::default(),
+        format_version: rustdoc_json_types::FORMAT_VERSION,
+    };
+
+    check(
+        &krate,
+        &[Error {
+            id: id("0:1:1571"),
+            kind: ErrorKind::Custom("Id for local item in `paths` but not in `index`".to_owned()),
+        }],
+    );
+}
+
+#[test]
+#[should_panic = "LOCAL_CRATE_ID is wrong"]
+fn checks_local_crate_id_is_correct() {
+    let krate = Crate {
+        root: id("root"),
+        crate_version: None,
+        includes_private: false,
+        index: HashMap::from_iter([(
+            id("root"),
+            Item {
+                id: id("root"),
+                crate_id: LOCAL_CRATE_ID.wrapping_add(1),
+                name: Some("irrelavent".to_owned()),
+                span: None,
+                visibility: Visibility::Public,
+                docs: None,
+                links: HashMap::default(),
+                attrs: Vec::new(),
+                deprecation: None,
+                inner: ItemEnum::Module(Module {
+                    is_crate: true,
+                    items: vec![],
+                    is_stripped: false,
+                }),
+            },
+        )]),
+        paths: HashMap::default(),
+        external_crates: HashMap::default(),
+        format_version: FORMAT_VERSION,
+    };
+    check(&krate, &[]);
 }
diff --git a/src/tools/rustc-workspace-hack/Cargo.toml b/src/tools/rustc-workspace-hack/Cargo.toml
index a5f0c0f320a..84b16a37a33 100644
--- a/src/tools/rustc-workspace-hack/Cargo.toml
+++ b/src/tools/rustc-workspace-hack/Cargo.toml
@@ -77,6 +77,8 @@ clap = { version = "3.1.1", features = ["derive", "clap_derive"]}
 curl-sys = { version = "0.4.13", features = ["http2", "libnghttp2-sys"], optional = true }
 # Ensure `extra_traits` of libc, which is used transitively by Cargo.
 libc = { version = "0.2", features = ["extra_traits"] }
+# Ensure `js` of getrandom, which is (unfortunately) used transitively by Cargo.
+getrandom = { version = "0.2", features = ["js"] }
 # Ensure default features of libz-sys, which are disabled in some scenarios.
 libz-sys = { version = "1.1.2" }
 # Ensure default features of regex, which are disabled in some scenarios.
diff --git a/src/tools/rustdoc-gui/tester.js b/src/tools/rustdoc-gui/tester.js
index d40d9a3cb54..900ca389436 100644
--- a/src/tools/rustdoc-gui/tester.js
+++ b/src/tools/rustdoc-gui/tester.js
@@ -9,6 +9,9 @@ const path = require("path");
 const os = require('os');
 const {Options, runTest} = require('browser-ui-test');
 
+// If a test fails or errors, we will retry it two more times in case it was a flaky failure.
+const NB_RETRY = 3;
+
 function showHelp() {
     console.log("rustdoc-js options:");
     console.log("  --doc-folder [PATH]        : location of the generated doc folder");
@@ -129,11 +132,59 @@ function char_printer(n_tests) {
     };
 }
 
-/// Sort array by .file_name property
+// Sort array by .file_name property
 function by_filename(a, b) {
     return a.file_name - b.file_name;
 }
 
+async function runTests(opts, framework_options, files, results, status_bar, showTestFailures) {
+    const tests_queue = [];
+
+    for (const testPath of files) {
+        const callback = runTest(testPath, framework_options)
+            .then(out => {
+                const [output, nb_failures] = out;
+                results[nb_failures === 0 ? "successful" : "failed"].push({
+                    file_name: testPath,
+                    output: output,
+                });
+                if (nb_failures === 0) {
+                    status_bar.successful();
+                } else if (showTestFailures) {
+                    status_bar.erroneous();
+                }
+            })
+            .catch(err => {
+                results.errored.push({
+                    file_name: testPath,
+                    output: err,
+                });
+                if (showTestFailures) {
+                    status_bar.erroneous();
+                }
+            })
+            .finally(() => {
+                // We now remove the promise from the tests_queue.
+                tests_queue.splice(tests_queue.indexOf(callback), 1);
+            });
+        tests_queue.push(callback);
+        if (opts["jobs"] > 0 && tests_queue.length >= opts["jobs"]) {
+            await Promise.race(tests_queue);
+        }
+    }
+    if (tests_queue.length > 0) {
+        await Promise.all(tests_queue);
+    }
+}
+
+function createEmptyResults() {
+    return {
+        successful: [],
+        failed: [],
+        errored: [],
+    };
+}
+
 async function main(argv) {
     let opts = parseOptions(argv.slice(2));
     if (opts === null) {
@@ -144,7 +195,7 @@ async function main(argv) {
     let debug = false;
     // Run tests in sequentially
     let headless = true;
-    const options = new Options();
+    const framework_options = new Options();
     try {
         // This is more convenient that setting fields one by one.
         let args = [
@@ -169,13 +220,12 @@ async function main(argv) {
             args.push("--executable-path");
             args.push(opts["executable_path"]);
         }
-        options.parseArguments(args);
+        framework_options.parseArguments(args);
     } catch (error) {
         console.error(`invalid argument: ${error}`);
         process.exit(1);
     }
 
-    let failed = false;
     let files;
     if (opts["files"].length === 0) {
         files = fs.readdirSync(opts["tests_folder"]);
@@ -187,6 +237,9 @@ async function main(argv) {
         console.error("rustdoc-gui: No test selected");
         process.exit(2);
     }
+    files.forEach((file_name, index) => {
+        files[index] = path.join(opts["tests_folder"], file_name);
+    });
     files.sort();
 
     if (!headless) {
@@ -215,52 +268,29 @@ async function main(argv) {
     };
     process.on('exit', exitHandling);
 
-    const tests_queue = [];
-    let results = {
-        successful: [],
-        failed: [],
-        errored: [],
-    };
+    const originalFilesLen = files.length;
+    let results = createEmptyResults();
     const status_bar = char_printer(files.length);
-    for (let i = 0; i < files.length; ++i) {
-        const file_name = files[i];
-        const testPath = path.join(opts["tests_folder"], file_name);
-        const callback = runTest(testPath, options)
-            .then(out => {
-                const [output, nb_failures] = out;
-                results[nb_failures === 0 ? "successful" : "failed"].push({
-                    file_name: testPath,
-                    output: output,
-                });
-                if (nb_failures > 0) {
-                    status_bar.erroneous();
-                    failed = true;
-                } else {
-                    status_bar.successful();
-                }
-            })
-            .catch(err => {
-                results.errored.push({
-                    file_name: testPath + file_name,
-                    output: err,
-                });
-                status_bar.erroneous();
-                failed = true;
-            })
-            .finally(() => {
-                // We now remove the promise from the tests_queue.
-                tests_queue.splice(tests_queue.indexOf(callback), 1);
-            });
-        tests_queue.push(callback);
-        if (opts["jobs"] > 0 && tests_queue.length >= opts["jobs"]) {
-            await Promise.race(tests_queue);
+
+    let new_results;
+    for (let it = 0; it < NB_RETRY && files.length > 0; ++it) {
+        new_results = createEmptyResults();
+        await runTests(opts, framework_options, files, new_results, status_bar, it + 1 >= NB_RETRY);
+        Array.prototype.push.apply(results.successful, new_results.successful);
+        // We generate the new list of files with the previously failing tests.
+        files = Array.prototype.concat(new_results.failed, new_results.errored);
+        if (files.length > originalFilesLen / 2) {
+            // If we have too many failing tests, it's very likely not flaky failures anymore so
+            // no need to retry.
+            break;
         }
     }
-    if (tests_queue.length > 0) {
-        await Promise.all(tests_queue);
-    }
+
     status_bar.finish();
 
+    Array.prototype.push.apply(results.failed, new_results.failed);
+    Array.prototype.push.apply(results.errored, new_results.errored);
+
     // We don't need this listener anymore.
     process.removeListener("exit", exitHandling);
 
@@ -287,7 +317,7 @@ async function main(argv) {
         });
     }
 
-    if (failed) {
+    if (results.failed.length > 0 || results.errored.length > 0) {
         process.exit(1);
     }
 }
diff --git a/src/tools/rustfmt/tests/target/issue_4110.rs b/src/tools/rustfmt/tests/target/issue_4110.rs
index 4a58c3946e1..d3734e90b7f 100644
--- a/src/tools/rustfmt/tests/target/issue_4110.rs
+++ b/src/tools/rustfmt/tests/target/issue_4110.rs
@@ -20,6 +20,7 @@ fn bindings() {
                 category,
                 span,
                 &format!("`{}`", name),
+                "function",
             ),
         (
             ref name,
diff --git a/src/tools/tidy/Cargo.toml b/src/tools/tidy/Cargo.toml
index fff83a1d097..5f5ae3a65ef 100644
--- a/src/tools/tidy/Cargo.toml
+++ b/src/tools/tidy/Cargo.toml
@@ -11,6 +11,7 @@ miropt-test-tools = { path = "../miropt-test-tools" }
 lazy_static = "1"
 walkdir = "2"
 ignore = "0.4.18"
+semver = "1.0.14"
 termcolor = "1.1.3"
 
 [[bin]]
diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs
index 75454cbdc5f..29501d2d3b6 100644
--- a/src/tools/tidy/src/deps.rs
+++ b/src/tools/tidy/src/deps.rs
@@ -40,6 +40,8 @@ const EXCEPTIONS: &[(&str, &str)] = &[
     ("im-rc", "MPL-2.0+"),                                   // cargo
     ("sized-chunks", "MPL-2.0+"),                            // cargo via im-rc
     ("bitmaps", "MPL-2.0+"),                                 // cargo via im-rc
+    ("fiat-crypto", "MIT OR Apache-2.0 OR BSD-1-Clause"),    // cargo via pasetors
+    ("subtle", "BSD-3-Clause"),                              // cargo via pasetors
     ("instant", "BSD-3-Clause"), // rustc_driver/tracing-subscriber/parking_lot
     ("snap", "BSD-3-Clause"),    // rustc
     ("fluent-langneg", "Apache-2.0"), // rustc (fluent translations)
@@ -96,6 +98,7 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
     "autocfg",
     "bitflags",
     "block-buffer",
+    "bumpalo", // Included in Cargo's dep graph but only activated on wasm32-*-unknown.
     "cc",
     "cfg-if",
     "chalk-derive",
@@ -153,6 +156,7 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
     "itertools",
     "itoa",
     "jobserver",
+    "js-sys", // Included in Cargo's dep graph but only activated on wasm32-*-unknown.
     "lazy_static",
     "libc",
     "libloading",
@@ -191,7 +195,6 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
     "rand",
     "rand_chacha",
     "rand_core",
-    "rand_hc",
     "rand_xorshift",
     "rand_xoshiro",
     "redox_syscall",
@@ -222,6 +225,7 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
     "stable_deref_trait",
     "stacker",
     "static_assertions",
+    "subtle", // dependency of cargo (via pasetors)
     "syn",
     "synstructure",
     "tempfile",
@@ -264,6 +268,13 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
     "valuable",
     "version_check",
     "wasi",
+    // vvv Included in Cargo's dep graph but only activated on wasm32-*-unknown.
+    "wasm-bindgen",
+    "wasm-bindgen-backend",
+    "wasm-bindgen-macro",
+    "wasm-bindgen-macro-support",
+    "wasm-bindgen-shared",
+    // ^^^ Included in Cargo's dep graph but only activated on wasm32-*-unknown.
     "winapi",
     "winapi-i686-pc-windows-gnu",
     "winapi-util",
diff --git a/src/tools/tidy/src/error_codes.rs b/src/tools/tidy/src/error_codes.rs
new file mode 100644
index 00000000000..8d70335a9e7
--- /dev/null
+++ b/src/tools/tidy/src/error_codes.rs
@@ -0,0 +1,384 @@
+//! Tidy check to ensure error codes are properly documented and tested.
+//!
+//! Overview of check:
+//!
+//! 1. We create a list of error codes used by the compiler. Error codes are extracted from `compiler/rustc_error_codes/src/error_codes.rs`.
+//!
+//! 2. We check that the error code has a long-form explanation in `compiler/rustc_error_codes/src/error_codes/`.
+//!   - The explanation is expected to contain a `doctest` that fails with the correct error code. (`EXEMPT_FROM_DOCTEST` *currently* bypasses this check)
+//!   - Note that other stylistic conventions for markdown files are checked in the `style.rs` tidy check.
+//!
+//! 3. We check that the error code has a UI test in `src/test/ui/error-codes/`.
+//!   - We ensure that there is both a `Exxxx.rs` file and a corresponding `Exxxx.stderr` file.
+//!   - We also ensure that the error code is used in the tests.
+//!   - *Currently*, it is possible to opt-out of this check with the `EXEMPTED_FROM_TEST` constant.
+//!
+//! 4. We check that the error code is actually emitted by the compiler.
+//!   - This is done by searching `compiler/` with a regex.
+
+use std::{ffi::OsStr, fs, path::Path};
+
+use regex::Regex;
+
+use crate::walk::{filter_dirs, walk, walk_many};
+
+const ERROR_CODES_PATH: &str = "compiler/rustc_error_codes/src/error_codes.rs";
+const ERROR_DOCS_PATH: &str = "compiler/rustc_error_codes/src/error_codes/";
+const ERROR_TESTS_PATH: &str = "src/test/ui/error-codes/";
+
+// Error codes that (for some reason) can't have a doctest in their explanation. Error codes are still expected to provide a code example, even if untested.
+const IGNORE_DOCTEST_CHECK: &[&str] = &["E0464", "E0570", "E0601", "E0602"];
+
+// Error codes that don't yet have a UI test. This list will eventually be removed.
+const IGNORE_UI_TEST_CHECK: &[&str] = &[
+    "E0461", "E0465", "E0476", "E0490", "E0514", "E0523", "E0554", "E0640", "E0717", "E0729",
+    "E0789",
+];
+
+macro_rules! verbose_print {
+    ($verbose:expr, $($fmt:tt)*) => {
+        if $verbose {
+            println!("{}", format_args!($($fmt)*));
+        }
+    };
+}
+
+pub fn check(root_path: &Path, search_paths: &[&Path], verbose: bool, bad: &mut bool) {
+    let mut errors = Vec::new();
+
+    // Stage 1: create list
+    let error_codes = extract_error_codes(root_path, &mut errors, verbose);
+    println!("Found {} error codes", error_codes.len());
+    println!("Highest error code: `{}`", error_codes.iter().max().unwrap());
+
+    // Stage 2: check list has docs
+    let no_longer_emitted = check_error_codes_docs(root_path, &error_codes, &mut errors, verbose);
+
+    // Stage 3: check list has UI tests
+    check_error_codes_tests(root_path, &error_codes, &mut errors, verbose, &no_longer_emitted);
+
+    // Stage 4: check list is emitted by compiler
+    check_error_codes_used(search_paths, &error_codes, &mut errors, &no_longer_emitted, verbose);
+
+    // Print any errors.
+    for error in errors {
+        tidy_error!(bad, "{}", error);
+    }
+}
+
+/// Stage 1: Parses a list of error codes from `error_codes.rs`.
+fn extract_error_codes(root_path: &Path, errors: &mut Vec<String>, verbose: bool) -> Vec<String> {
+    let path = root_path.join(Path::new(ERROR_CODES_PATH));
+    let file =
+        fs::read_to_string(&path).unwrap_or_else(|e| panic!("failed to read `{path:?}`: {e}"));
+
+    let mut error_codes = Vec::new();
+    let mut reached_undocumented_codes = false;
+
+    for line in file.lines() {
+        let line = line.trim();
+
+        if !reached_undocumented_codes && line.starts_with('E') {
+            let split_line = line.split_once(':');
+
+            // Extract the error code from the line, emitting a fatal error if it is not in a correct format.
+            let err_code = if let Some(err_code) = split_line {
+                err_code.0.to_owned()
+            } else {
+                errors.push(format!(
+                    "Expected a line with the format `Exxxx: include_str!(\"..\")`, but got \"{}\" \
+                    without a `:` delimiter",
+                    line,
+                ));
+                continue;
+            };
+
+            // If this is a duplicate of another error code, emit a fatal error.
+            if error_codes.contains(&err_code) {
+                errors.push(format!("Found duplicate error code: `{}`", err_code));
+                continue;
+            }
+
+            // Ensure that the line references the correct markdown file.
+            let expected_filename = format!(" include_str!(\"./error_codes/{}.md\"),", err_code);
+            if expected_filename != split_line.unwrap().1 {
+                errors.push(format!(
+                    "Error code `{}` expected to reference docs with `{}` but instead found `{}` in \
+                    `compiler/rustc_error_codes/src/error_codes.rs`",
+                    err_code,
+                    expected_filename,
+                    split_line.unwrap().1,
+                ));
+                continue;
+            }
+
+            error_codes.push(err_code);
+        } else if reached_undocumented_codes && line.starts_with('E') {
+            let err_code = match line.split_once(',') {
+                None => line,
+                Some((err_code, _)) => err_code,
+            }
+            .to_string();
+
+            verbose_print!(verbose, "warning: Error code `{}` is undocumented.", err_code);
+
+            if error_codes.contains(&err_code) {
+                errors.push(format!("Found duplicate error code: `{}`", err_code));
+            }
+
+            error_codes.push(err_code);
+        } else if line == ";" {
+            // Once we reach the undocumented error codes, adapt to different syntax.
+            reached_undocumented_codes = true;
+        }
+    }
+
+    error_codes
+}
+
+/// Stage 2: Checks that long-form error code explanations exist and have doctests.
+fn check_error_codes_docs(
+    root_path: &Path,
+    error_codes: &[String],
+    errors: &mut Vec<String>,
+    verbose: bool,
+) -> Vec<String> {
+    let docs_path = root_path.join(Path::new(ERROR_DOCS_PATH));
+
+    let mut no_longer_emitted_codes = Vec::new();
+
+    walk(&docs_path, &mut |_| false, &mut |entry, contents| {
+        let path = entry.path();
+
+        // Error if the file isn't markdown.
+        if path.extension() != Some(OsStr::new("md")) {
+            errors.push(format!(
+                "Found unexpected non-markdown file in error code docs directory: {}",
+                path.display()
+            ));
+            return;
+        }
+
+        // Make sure that the file is referenced in `error_codes.rs`
+        let filename = path.file_name().unwrap().to_str().unwrap().split_once('.');
+        let err_code = filename.unwrap().0; // `unwrap` is ok because we know the filename is in the correct format.
+
+        if error_codes.iter().all(|e| e != err_code) {
+            errors.push(format!(
+                "Found valid file `{}` in error code docs directory without corresponding \
+                entry in `error_code.rs`",
+                path.display()
+            ));
+            return;
+        }
+
+        let (found_code_example, found_proper_doctest, emit_ignore_warning, no_longer_emitted) =
+            check_explanation_has_doctest(&contents, &err_code);
+
+        if emit_ignore_warning {
+            verbose_print!(
+                verbose,
+                "warning: Error code `{err_code}` uses the ignore header. This should not be used, add the error code to the \
+                `IGNORE_DOCTEST_CHECK` constant instead."
+            );
+        }
+
+        if no_longer_emitted {
+            no_longer_emitted_codes.push(err_code.to_owned());
+        }
+
+        if !found_code_example {
+            verbose_print!(
+                verbose,
+                "warning: Error code `{err_code}` doesn't have a code example, all error codes are expected to have one \
+                (even if untested)."
+            );
+        }
+
+        let test_ignored = IGNORE_DOCTEST_CHECK.contains(&&err_code);
+
+        // Check that the explanation has a doctest, and if it shouldn't, that it doesn't
+        if !found_proper_doctest && !test_ignored {
+            errors.push(format!(
+                "`{}` doesn't use its own error code in compile_fail example",
+                path.display(),
+            ));
+        } else if found_proper_doctest && test_ignored {
+            errors.push(format!(
+                "`{}` has a compile_fail doctest with its own error code, it shouldn't \
+                be listed in `IGNORE_DOCTEST_CHECK`",
+                path.display(),
+            ));
+        }
+    });
+
+    no_longer_emitted_codes
+}
+
+/// This function returns a tuple indicating whether the provided explanation:
+/// a) has a code example, tested or not.
+/// b) has a valid doctest
+fn check_explanation_has_doctest(explanation: &str, err_code: &str) -> (bool, bool, bool, bool) {
+    let mut found_code_example = false;
+    let mut found_proper_doctest = false;
+
+    let mut emit_ignore_warning = false;
+    let mut no_longer_emitted = false;
+
+    for line in explanation.lines() {
+        let line = line.trim();
+
+        if line.starts_with("```") {
+            found_code_example = true;
+
+            // Check for the `rustdoc` doctest headers.
+            if line.contains("compile_fail") && line.contains(err_code) {
+                found_proper_doctest = true;
+            }
+
+            if line.contains("ignore") {
+                emit_ignore_warning = true;
+                found_proper_doctest = true;
+            }
+        } else if line
+            .starts_with("#### Note: this error code is no longer emitted by the compiler")
+        {
+            no_longer_emitted = true;
+            found_code_example = true;
+            found_proper_doctest = true;
+        }
+    }
+
+    (found_code_example, found_proper_doctest, emit_ignore_warning, no_longer_emitted)
+}
+
+// Stage 3: Checks that each error code has a UI test in the correct directory
+fn check_error_codes_tests(
+    root_path: &Path,
+    error_codes: &[String],
+    errors: &mut Vec<String>,
+    verbose: bool,
+    no_longer_emitted: &[String],
+) {
+    let tests_path = root_path.join(Path::new(ERROR_TESTS_PATH));
+
+    for code in error_codes {
+        let test_path = tests_path.join(format!("{}.stderr", code));
+
+        if !test_path.exists() && !IGNORE_UI_TEST_CHECK.contains(&code.as_str()) {
+            verbose_print!(
+                verbose,
+                "warning: Error code `{code}` needs to have at least one UI test in the `src/test/ui/error-codes/` directory`!"
+            );
+            continue;
+        }
+        if IGNORE_UI_TEST_CHECK.contains(&code.as_str()) {
+            if test_path.exists() {
+                errors.push(format!(
+                    "Error code `{code}` has a UI test in `src/test/ui/error-codes/{code}.rs`, it shouldn't be listed in `EXEMPTED_FROM_TEST`!"
+                ));
+            }
+            continue;
+        }
+
+        let file = match fs::read_to_string(&test_path) {
+            Ok(file) => file,
+            Err(err) => {
+                verbose_print!(
+                    verbose,
+                    "warning: Failed to read UI test file (`{}`) for `{code}` but the file exists. The test is assumed to work:\n{err}",
+                    test_path.display()
+                );
+                continue;
+            }
+        };
+
+        if no_longer_emitted.contains(code) {
+            // UI tests *can't* contain error codes that are no longer emitted.
+            continue;
+        }
+
+        let mut found_code = false;
+
+        for line in file.lines() {
+            let s = line.trim();
+            // Assuming the line starts with `error[E`, we can substring the error code out.
+            if s.starts_with("error[E") {
+                if &s[6..11] == code {
+                    found_code = true;
+                    break;
+                }
+            };
+        }
+
+        if !found_code {
+            verbose_print!(
+                verbose,
+                "warning: Error code {code}`` has a UI test file, but doesn't contain its own error code!"
+            );
+        }
+    }
+}
+
+/// Stage 4: Search `compiler/` and ensure that every error code is actually used by the compiler and that no undocumented error codes exist.
+fn check_error_codes_used(
+    search_paths: &[&Path],
+    error_codes: &[String],
+    errors: &mut Vec<String>,
+    no_longer_emitted: &[String],
+    verbose: bool,
+) {
+    // We want error codes which match the following cases:
+    //
+    // * foo(a, E0111, a)
+    // * foo(a, E0111)
+    // * foo(E0111, a)
+    // * #[error = "E0111"]
+    let regex = Regex::new(r#"[(,"\s](E\d{4})[,)"]"#).unwrap();
+
+    let mut found_codes = Vec::new();
+
+    walk_many(search_paths, &mut filter_dirs, &mut |entry, contents| {
+        let path = entry.path();
+
+        // Return early if we aren't looking at a source file.
+        if path.extension() != Some(OsStr::new("rs")) {
+            return;
+        }
+
+        for line in contents.lines() {
+            // We want to avoid parsing error codes in comments.
+            if line.trim_start().starts_with("//") {
+                continue;
+            }
+
+            for cap in regex.captures_iter(line) {
+                if let Some(error_code) = cap.get(1) {
+                    let error_code = error_code.as_str().to_owned();
+
+                    if !error_codes.contains(&error_code) {
+                        // This error code isn't properly defined, we must error.
+                        errors.push(format!("Error code `{}` is used in the compiler but not defined and documented in `compiler/rustc_error_codes/src/error_codes.rs`.", error_code));
+                        continue;
+                    }
+
+                    // This error code can now be marked as used.
+                    found_codes.push(error_code);
+                }
+            }
+        }
+    });
+
+    for code in error_codes {
+        if !found_codes.contains(code) && !no_longer_emitted.contains(code) {
+            errors.push(format!("Error code `{code}` exists, but is not emitted by the compiler!"))
+        }
+
+        if found_codes.contains(code) && no_longer_emitted.contains(code) {
+            verbose_print!(
+                verbose,
+                "warning: Error code `{code}` is used when it's marked as \"no longer emitted\""
+            );
+        }
+    }
+}
diff --git a/src/tools/tidy/src/error_codes_check.rs b/src/tools/tidy/src/error_codes_check.rs
deleted file mode 100644
index 3f060e437ac..00000000000
--- a/src/tools/tidy/src/error_codes_check.rs
+++ /dev/null
@@ -1,305 +0,0 @@
-//! Checks that all error codes have at least one test to prevent having error
-//! codes that are silently not thrown by the compiler anymore.
-
-use crate::walk::{filter_dirs, walk};
-use std::collections::{HashMap, HashSet};
-use std::ffi::OsStr;
-use std::fs::read_to_string;
-use std::path::Path;
-
-use regex::Regex;
-
-// A few of those error codes can't be tested but all the others can and *should* be tested!
-const EXEMPTED_FROM_TEST: &[&str] = &[
-    "E0313", "E0461", "E0476", "E0490", "E0514", "E0523", "E0554", "E0640", "E0717", "E0729",
-    "E0789",
-];
-
-// Some error codes don't have any tests apparently...
-const IGNORE_EXPLANATION_CHECK: &[&str] = &["E0464", "E0570", "E0601", "E0602", "E0729"];
-
-// If the file path contains any of these, we don't want to try to extract error codes from it.
-//
-// We need to declare each path in the windows version (with backslash).
-const PATHS_TO_IGNORE_FOR_EXTRACTION: &[&str] =
-    &["src/test/", "src\\test\\", "src/doc/", "src\\doc\\", "src/tools/", "src\\tools\\"];
-
-#[derive(Default, Debug)]
-struct ErrorCodeStatus {
-    has_test: bool,
-    has_explanation: bool,
-    is_used: bool,
-}
-
-fn check_error_code_explanation(
-    f: &str,
-    error_codes: &mut HashMap<String, ErrorCodeStatus>,
-    err_code: String,
-) -> bool {
-    let mut invalid_compile_fail_format = false;
-    let mut found_error_code = false;
-
-    for line in f.lines() {
-        let s = line.trim();
-        if s.starts_with("```") {
-            if s.contains("compile_fail") && s.contains('E') {
-                if !found_error_code {
-                    error_codes.get_mut(&err_code).map(|x| x.has_test = true);
-                    found_error_code = true;
-                }
-            } else if s.contains("compile-fail") {
-                invalid_compile_fail_format = true;
-            }
-        } else if s.starts_with("#### Note: this error code is no longer emitted by the compiler") {
-            if !found_error_code {
-                error_codes.get_mut(&err_code).map(|x| x.has_test = true);
-                found_error_code = true;
-            }
-        }
-    }
-    invalid_compile_fail_format
-}
-
-fn check_if_error_code_is_test_in_explanation(f: &str, err_code: &str) -> bool {
-    let mut ignore_found = false;
-
-    for line in f.lines() {
-        let s = line.trim();
-        if s.starts_with("#### Note: this error code is no longer emitted by the compiler") {
-            return true;
-        }
-        if s.starts_with("```") {
-            if s.contains("compile_fail") && s.contains(err_code) {
-                return true;
-            } else if s.contains("ignore") {
-                // It's very likely that we can't actually make it fail compilation...
-                ignore_found = true;
-            }
-        }
-    }
-    ignore_found
-}
-
-fn extract_error_codes(
-    f: &str,
-    error_codes: &mut HashMap<String, ErrorCodeStatus>,
-    path: &Path,
-    errors: &mut Vec<String>,
-) {
-    let mut reached_no_explanation = false;
-
-    for line in f.lines() {
-        let s = line.trim();
-        if !reached_no_explanation && s.starts_with('E') && s.contains("include_str!(\"") {
-            let err_code = s
-                .split_once(':')
-                .expect(
-                    format!(
-                        "Expected a line with the format `E0xxx: include_str!(\"..\")`, but got {} \
-                         without a `:` delimiter",
-                        s,
-                    )
-                    .as_str(),
-                )
-                .0
-                .to_owned();
-            error_codes.entry(err_code.clone()).or_default().has_explanation = true;
-
-            // Now we extract the tests from the markdown file!
-            let md_file_name = match s.split_once("include_str!(\"") {
-                None => continue,
-                Some((_, md)) => match md.split_once("\")") {
-                    None => continue,
-                    Some((file_name, _)) => file_name,
-                },
-            };
-
-            let Some(parent) = path.parent() else {
-                continue;
-            };
-
-            let path = parent
-                .join(md_file_name)
-                .canonicalize()
-                .expect("failed to canonicalize error explanation file path");
-
-            match read_to_string(&path) {
-                Ok(content) => {
-                    let has_test = check_if_error_code_is_test_in_explanation(&content, &err_code);
-                    if !has_test && !IGNORE_EXPLANATION_CHECK.contains(&err_code.as_str()) {
-                        errors.push(format!(
-                            "`{}` doesn't use its own error code in compile_fail example",
-                            path.display(),
-                        ));
-                    } else if has_test && IGNORE_EXPLANATION_CHECK.contains(&err_code.as_str()) {
-                        errors.push(format!(
-                            "`{}` has a compile_fail example with its own error code, it shouldn't \
-                             be listed in IGNORE_EXPLANATION_CHECK!",
-                            path.display(),
-                        ));
-                    }
-                    if check_error_code_explanation(&content, error_codes, err_code) {
-                        errors.push(format!(
-                            "`{}` uses invalid tag `compile-fail` instead of `compile_fail`",
-                            path.display(),
-                        ));
-                    }
-                }
-                Err(e) => {
-                    eprintln!("Couldn't read `{}`: {}", path.display(), e);
-                }
-            }
-        } else if reached_no_explanation && s.starts_with('E') {
-            let err_code = match s.split_once(',') {
-                None => s,
-                Some((err_code, _)) => err_code,
-            }
-            .to_string();
-            if !error_codes.contains_key(&err_code) {
-                // this check should *never* fail!
-                error_codes.insert(err_code, ErrorCodeStatus::default());
-            }
-        } else if s == ";" {
-            reached_no_explanation = true;
-        }
-    }
-}
-
-fn extract_error_codes_from_tests(f: &str, error_codes: &mut HashMap<String, ErrorCodeStatus>) {
-    for line in f.lines() {
-        let s = line.trim();
-        if s.starts_with("error[E") || s.starts_with("warning[E") {
-            let err_code = match s.split_once(']') {
-                None => continue,
-                Some((err_code, _)) => match err_code.split_once('[') {
-                    None => continue,
-                    Some((_, err_code)) => err_code,
-                },
-            };
-            error_codes.entry(err_code.to_owned()).or_default().has_test = true;
-        }
-    }
-}
-
-fn extract_error_codes_from_source(
-    f: &str,
-    error_codes: &mut HashMap<String, ErrorCodeStatus>,
-    regex: &Regex,
-) {
-    for line in f.lines() {
-        if line.trim_start().starts_with("//") {
-            continue;
-        }
-        for cap in regex.captures_iter(line) {
-            if let Some(error_code) = cap.get(1) {
-                error_codes.entry(error_code.as_str().to_owned()).or_default().is_used = true;
-            }
-        }
-    }
-}
-
-pub fn check(paths: &[&Path], bad: &mut bool) {
-    let mut errors = Vec::new();
-    let mut found_explanations = 0;
-    let mut found_tests = 0;
-    let mut error_codes: HashMap<String, ErrorCodeStatus> = HashMap::new();
-    let mut explanations: HashSet<String> = HashSet::new();
-    // We want error codes which match the following cases:
-    //
-    // * foo(a, E0111, a)
-    // * foo(a, E0111)
-    // * foo(E0111, a)
-    // * #[error = "E0111"]
-    let regex = Regex::new(r#"[(,"\s](E\d{4})[,)"]"#).unwrap();
-
-    for path in paths {
-        walk(path, &mut filter_dirs, &mut |entry, contents| {
-            let file_name = entry.file_name();
-            let entry_path = entry.path();
-
-            if file_name == "error_codes.rs" {
-                extract_error_codes(contents, &mut error_codes, entry.path(), &mut errors);
-                found_explanations += 1;
-            } else if entry_path.extension() == Some(OsStr::new("stderr")) {
-                extract_error_codes_from_tests(contents, &mut error_codes);
-                found_tests += 1;
-            } else if entry_path.extension() == Some(OsStr::new("rs")) {
-                let path = entry.path().to_string_lossy();
-                if PATHS_TO_IGNORE_FOR_EXTRACTION.iter().all(|c| !path.contains(c)) {
-                    extract_error_codes_from_source(contents, &mut error_codes, &regex);
-                }
-            } else if entry_path
-                .parent()
-                .and_then(|p| p.file_name())
-                .map(|p| p == "error_codes")
-                .unwrap_or(false)
-                && entry_path.extension() == Some(OsStr::new("md"))
-            {
-                explanations.insert(file_name.to_str().unwrap().replace(".md", ""));
-            }
-        });
-    }
-    if found_explanations == 0 {
-        tidy_error!(bad, "No error code explanation was tested!");
-    }
-    if found_tests == 0 {
-        tidy_error!(bad, "No error code was found in compilation errors!");
-    }
-    if explanations.is_empty() {
-        tidy_error!(bad, "No error code explanation was found!");
-    }
-    if errors.is_empty() {
-        for (err_code, error_status) in &error_codes {
-            if !error_status.has_test && !EXEMPTED_FROM_TEST.contains(&err_code.as_str()) {
-                errors.push(format!("Error code {err_code} needs to have at least one UI test!"));
-            } else if error_status.has_test && EXEMPTED_FROM_TEST.contains(&err_code.as_str()) {
-                errors.push(format!(
-                    "Error code {} has a UI test, it shouldn't be listed into EXEMPTED_FROM_TEST!",
-                    err_code
-                ));
-            }
-            if !error_status.is_used && !error_status.has_explanation {
-                errors.push(format!(
-                    "Error code {} isn't used and doesn't have an error explanation, it should be \
-                     commented in error_codes.rs file",
-                    err_code
-                ));
-            }
-        }
-    }
-    if errors.is_empty() {
-        // Checking if local constants need to be cleaned.
-        for err_code in EXEMPTED_FROM_TEST {
-            match error_codes.get(err_code.to_owned()) {
-                Some(status) => {
-                    if status.has_test {
-                        errors.push(format!(
-                            "{} error code has a test and therefore should be \
-                            removed from the `EXEMPTED_FROM_TEST` constant",
-                            err_code
-                        ));
-                    }
-                }
-                None => errors.push(format!(
-                    "{} error code isn't used anymore and therefore should be removed \
-                        from `EXEMPTED_FROM_TEST` constant",
-                    err_code
-                )),
-            }
-        }
-    }
-    if errors.is_empty() {
-        for explanation in explanations {
-            if !error_codes.contains_key(&explanation) {
-                errors.push(format!(
-                    "{} error code explanation should be listed in `error_codes.rs`",
-                    explanation
-                ));
-            }
-        }
-    }
-    errors.sort();
-    for err in &errors {
-        tidy_error!(bad, "{err}");
-    }
-}
diff --git a/src/tools/tidy/src/errors.rs b/src/tools/tidy/src/errors.rs
deleted file mode 100644
index fe5fd72b91a..00000000000
--- a/src/tools/tidy/src/errors.rs
+++ /dev/null
@@ -1,77 +0,0 @@
-//! Tidy check to verify the validity of long error diagnostic codes.
-//!
-//! This ensures that error codes are used at most once and also prints out some
-//! statistics about the error codes.
-
-use crate::walk::{filter_dirs, walk};
-use std::collections::HashMap;
-use std::path::Path;
-
-pub fn check(path: &Path, bad: &mut bool) {
-    let mut map: HashMap<_, Vec<_>> = HashMap::new();
-    walk(
-        path,
-        &mut |path| filter_dirs(path) || path.ends_with("src/test"),
-        &mut |entry, contents| {
-            let file = entry.path();
-            let filename = file.file_name().unwrap().to_string_lossy();
-            if filename != "error_codes.rs" {
-                return;
-            }
-
-            // In the `register_long_diagnostics!` macro, entries look like this:
-            //
-            // ```
-            // EXXXX: r##"
-            // <Long diagnostic message>
-            // "##,
-            // ```
-            //
-            // and these long messages often have error codes themselves inside
-            // them, but we don't want to report duplicates in these cases. This
-            // variable keeps track of whether we're currently inside one of these
-            // long diagnostic messages.
-            let mut inside_long_diag = false;
-            for (num, line) in contents.lines().enumerate() {
-                if inside_long_diag {
-                    inside_long_diag = !line.contains("\"##");
-                    continue;
-                }
-
-                let mut search = line;
-                while let Some(i) = search.find('E') {
-                    search = &search[i + 1..];
-                    let code = if search.len() > 4 { search[..4].parse::<u32>() } else { continue };
-                    let code = match code {
-                        Ok(n) => n,
-                        Err(..) => continue,
-                    };
-                    map.entry(code).or_default().push((file.to_owned(), num + 1, line.to_owned()));
-                    break;
-                }
-
-                inside_long_diag = line.contains("r##\"");
-            }
-        },
-    );
-
-    let mut max = 0;
-    for (&code, entries) in map.iter() {
-        if code > max {
-            max = code;
-        }
-        if entries.len() == 1 {
-            continue;
-        }
-
-        tidy_error!(bad, "duplicate error code: {}", code);
-        for &(ref file, line_num, ref line) in entries.iter() {
-            tidy_error!(bad, "{}:{}: {}", file.display(), line_num, line);
-        }
-    }
-
-    if !*bad {
-        println!("* {} error codes", map.len());
-        println!("* highest error code: E{:04}", max);
-    }
-}
diff --git a/src/tools/tidy/src/lib.rs b/src/tools/tidy/src/lib.rs
index ce7e7ac5cd4..15c641d748c 100644
--- a/src/tools/tidy/src/lib.rs
+++ b/src/tools/tidy/src/lib.rs
@@ -56,8 +56,7 @@ pub mod bins;
 pub mod debug_artifacts;
 pub mod deps;
 pub mod edition;
-pub mod error_codes_check;
-pub mod errors;
+pub mod error_codes;
 pub mod extdeps;
 pub mod features;
 pub mod mir_opt_tests;
@@ -69,3 +68,4 @@ pub mod ui_tests;
 pub mod unit_tests;
 pub mod unstable_book;
 pub mod walk;
+pub mod x_version;
diff --git a/src/tools/tidy/src/main.rs b/src/tools/tidy/src/main.rs
index 6714c63ee62..a5685ba7c94 100644
--- a/src/tools/tidy/src/main.rs
+++ b/src/tools/tidy/src/main.rs
@@ -27,6 +27,7 @@ fn main() {
     let src_path = root_path.join("src");
     let library_path = root_path.join("library");
     let compiler_path = root_path.join("compiler");
+    let librustdoc_path = src_path.join("librustdoc");
 
     let args: Vec<String> = env::args().skip(1).collect();
 
@@ -58,7 +59,7 @@ fn main() {
 
                 let handle = s.spawn(|| {
                     let mut flag = false;
-                    $p::check($($args),* , &mut flag);
+                    $p::check($($args, )* &mut flag);
                     if (flag) {
                         bad.store(true, Ordering::Relaxed);
                     }
@@ -79,8 +80,7 @@ fn main() {
         check!(mir_opt_tests, &src_path, bless);
 
         // Checks that only make sense for the compiler.
-        check!(errors, &compiler_path);
-        check!(error_codes_check, &[&src_path, &compiler_path]);
+        check!(error_codes, &root_path, &[&compiler_path, &librustdoc_path], verbose);
 
         // Checks that only make sense for the std libs.
         check!(pal, &library_path);
@@ -107,6 +107,8 @@ fn main() {
         check!(alphabetical, &compiler_path);
         check!(alphabetical, &library_path);
 
+        check!(x_version, &root_path, &cargo);
+
         let collected = {
             drain_handles(&mut handles);
 
diff --git a/src/tools/tidy/src/style.rs b/src/tools/tidy/src/style.rs
index f91e38262f6..723a52c4c68 100644
--- a/src/tools/tidy/src/style.rs
+++ b/src/tools/tidy/src/style.rs
@@ -15,6 +15,7 @@
 //!
 //! A number of these checks can be opted-out of with various directives of the form:
 //! `// ignore-tidy-CHECK-NAME`.
+// ignore-tidy-dbg
 
 use crate::walk::{filter_dirs, walk};
 use regex::{Regex, RegexSet};
@@ -24,6 +25,7 @@ use std::path::Path;
 /// displayed on the console with --example.
 const ERROR_CODE_COLS: usize = 80;
 const COLS: usize = 100;
+const GOML_COLS: usize = 120;
 
 const LINES: usize = 3000;
 
@@ -229,7 +231,8 @@ pub fn check(path: &Path, bad: &mut bool) {
     walk(path, &mut skip, &mut |entry, contents| {
         let file = entry.path();
         let filename = file.file_name().unwrap().to_string_lossy();
-        let extensions = [".rs", ".py", ".js", ".sh", ".c", ".cpp", ".h", ".md", ".css", ".ftl"];
+        let extensions =
+            [".rs", ".py", ".js", ".sh", ".c", ".cpp", ".h", ".md", ".css", ".ftl", ".goml"];
         if extensions.iter().all(|e| !filename.ends_with(e)) || filename.starts_with(".#") {
             return;
         }
@@ -254,8 +257,15 @@ pub fn check(path: &Path, bad: &mut bool) {
 
         let extension = file.extension().unwrap().to_string_lossy();
         let is_error_code = extension == "md" && is_in(file, "src", "error_codes");
+        let is_goml_code = extension == "goml";
 
-        let max_columns = if is_error_code { ERROR_CODE_COLS } else { COLS };
+        let max_columns = if is_error_code {
+            ERROR_CODE_COLS
+        } else if is_goml_code {
+            GOML_COLS
+        } else {
+            COLS
+        };
 
         let can_contain = contents.contains("// ignore-tidy-")
             || contents.contains("# ignore-tidy-")
@@ -278,6 +288,7 @@ pub fn check(path: &Path, bad: &mut bool) {
         let mut skip_leading_newlines =
             contains_ignore_directive(can_contain, &contents, "leading-newlines");
         let mut skip_copyright = contains_ignore_directive(can_contain, &contents, "copyright");
+        let mut skip_dbg = contains_ignore_directive(can_contain, &contents, "dbg");
         let mut leading_new_lines = false;
         let mut trailing_new_lines = 0;
         let mut lines = 0;
@@ -306,6 +317,21 @@ pub fn check(path: &Path, bad: &mut bool) {
             let mut err = |msg: &str| {
                 tidy_error!(bad, "{}:{}: {}", file.display(), i + 1, msg);
             };
+
+            if trimmed.contains("dbg!")
+                && !trimmed.starts_with("//")
+                && !file
+                    .ancestors()
+                    .any(|a| a.ends_with("src/test") || a.ends_with("library/alloc/tests"))
+                && filename != "tests.rs"
+            {
+                suppressible_tidy_err!(
+                    err,
+                    skip_dbg,
+                    "`dbg!` macro is intended as a debugging tool. It should not be in version control."
+                )
+            }
+
             if !under_rustfmt
                 && line.chars().count() > max_columns
                 && !long_line_is_ok(&extension, is_error_code, max_columns, line)
diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs
index 070e72437be..166d09fa8b0 100644
--- a/src/tools/tidy/src/ui_tests.rs
+++ b/src/tools/tidy/src/ui_tests.rs
@@ -10,7 +10,7 @@ use std::path::Path;
 const ENTRY_LIMIT: usize = 1000;
 // FIXME: The following limits should be reduced eventually.
 const ROOT_ENTRY_LIMIT: usize = 939;
-const ISSUES_ENTRY_LIMIT: usize = 2050;
+const ISSUES_ENTRY_LIMIT: usize = 1998;
 
 fn check_entries(path: &Path, bad: &mut bool) {
     for dir in Walk::new(&path.join("test/ui")) {
diff --git a/src/tools/tidy/src/x_version.rs b/src/tools/tidy/src/x_version.rs
new file mode 100644
index 00000000000..5dc6a0588c3
--- /dev/null
+++ b/src/tools/tidy/src/x_version.rs
@@ -0,0 +1,65 @@
+use semver::Version;
+use std::io::ErrorKind;
+use std::path::Path;
+use std::process::{Command, Stdio};
+
+pub fn check(root: &Path, cargo: &Path, bad: &mut bool) {
+    let result = Command::new("x").arg("--wrapper-version").stdout(Stdio::piped()).spawn();
+    // This runs the command inside a temporary directory.
+    // This allows us to compare output of result to see if `--wrapper-version` is not a recognized argument to x.
+    let temp_result = Command::new("x")
+        .arg("--wrapper-version")
+        .current_dir(std::env::temp_dir())
+        .stdout(Stdio::piped())
+        .spawn();
+
+    let (child, temp_child) = match (result, temp_result) {
+        (Ok(child), Ok(temp_child)) => (child, temp_child),
+        (Err(e), _) | (_, Err(e)) => match e.kind() {
+            ErrorKind::NotFound => return,
+            _ => return tidy_error!(bad, "failed to run `x`: {}", e),
+        },
+    };
+
+    let output = child.wait_with_output().unwrap();
+    let temp_output = temp_child.wait_with_output().unwrap();
+
+    if output != temp_output {
+        return tidy_error!(
+            bad,
+            "Current version of x does not support the `--wrapper-version` argument\nConsider updating to the newer version of x by running `cargo install --path src/tools/x`"
+        );
+    }
+
+    if output.status.success() {
+        let version = String::from_utf8_lossy(&output.stdout);
+        let version = Version::parse(version.trim_end()).unwrap();
+
+        if let Some(expected) = get_x_wrapper_version(root, cargo) {
+            if version < expected {
+                return tidy_error!(
+                    bad,
+                    "Current version of x is {version}, but the latest version is {expected}\nConsider updating to the newer version of x by running `cargo install --path src/tools/x`"
+                );
+            }
+        } else {
+            return tidy_error!(
+                bad,
+                "Unable to parse the latest version of `x` at `src/tools/x/Cargo.toml`"
+            );
+        }
+    } else {
+        return tidy_error!(bad, "failed to check version of `x`: {}", output.status);
+    }
+}
+
+// Parse latest version out of `x` Cargo.toml
+fn get_x_wrapper_version(root: &Path, cargo: &Path) -> Option<Version> {
+    let mut cmd = cargo_metadata::MetadataCommand::new();
+    cmd.cargo_path(cargo)
+        .manifest_path(root.join("src/tools/x/Cargo.toml"))
+        .no_deps()
+        .features(cargo_metadata::CargoOpt::AllFeatures);
+    let mut metadata = t!(cmd.exec());
+    metadata.packages.pop().map(|x| x.version)
+}
diff --git a/src/tools/x/src/main.rs b/src/tools/x/src/main.rs
index f07ff43efe9..01f7187851e 100644
--- a/src/tools/x/src/main.rs
+++ b/src/tools/x/src/main.rs
@@ -52,6 +52,14 @@ fn exec_or_status(command: &mut Command) -> io::Result<ExitStatus> {
 }
 
 fn main() {
+    match env::args().skip(1).next().as_deref() {
+        Some("--wrapper-version") => {
+            let version = env!("CARGO_PKG_VERSION");
+            println!("{}", version);
+            return;
+        }
+        _ => {}
+    }
     let current = match env::current_dir() {
         Ok(dir) => dir,
         Err(err) => {
diff --git a/triagebot.toml b/triagebot.toml
index 0da9fcddad8..58108dac496 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -479,6 +479,7 @@ compiler = [
     "compiler-team-contributors",
 ]
 libs = [
+    "@cuviper",
     "@joshtriplett",
     "@Mark-Simulacrum",
     "@m-ou-se",